1/* This file is part of the KDE project
2 *
3 * Copyright (C) 2000-2003 Simon Hausmann <hausmann@kde.org>
4 * 2001-2003 George Staikos <staikos@kde.org>
5 * 2001-2003 Laurent Montel <montel@kde.org>
6 * 2001-2003 Dirk Mueller <mueller@kde.org>
7 * 2001-2003 Waldo Bastian <bastian@kde.org>
8 * 2001-2003 David Faure <faure@kde.org>
9 * 2001-2003 Daniel Naber <dnaber@kde.org>
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details.
20 *
21 * You should have received a copy of the GNU Library General Public License
22 * along with this library; see the file COPYING.LIB. If not, write to
23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 * Boston, MA 02110-1301, USA.
25 */
26
27#include "khtml_ext.h"
28#include "khtmlview.h"
29#include "khtml_pagecache.h"
30#include "rendering/render_form.h"
31#include "rendering/render_image.h"
32#include "html/html_imageimpl.h"
33#include "misc/loader.h"
34#include "dom/html_form.h"
35#include "dom/html_image.h"
36#include "dom/dom_string.h"
37#include "dom/html_document.h"
38#include "dom/dom_element.h"
39#include "xml/dom_elementimpl.h"
40#include <QtGui/QClipboard>
41#include <QtCore/QFileInfo>
42#include <QtGui/QMenu>
43#include <QtCore/QUrl>
44#include <QtCore/QMetaEnum>
45#include <assert.h>
46
47#include <kdebug.h>
48#include <klocale.h>
49#include <kfiledialog.h>
50#include <kjobuidelegate.h>
51#include <kio/job.h>
52#include <kshell.h>
53#include <ktoolbar.h>
54#include <ksavefile.h>
55#include <kstringhandler.h>
56#include <ktoolinvocation.h>
57#include <kmessagebox.h>
58#include <kstandarddirs.h>
59#include <krun.h>
60#include <kurifilter.h>
61#include <kicon.h>
62#include <kiconloader.h>
63#include <kdesktopfile.h>
64#include <kinputdialog.h>
65#include <ktemporaryfile.h>
66#include "khtml_global.h"
67#include <kstandardaction.h>
68#include <kactioncollection.h>
69#include <kactionmenu.h>
70
71#include "khtmlpart_p.h"
72
73KHTMLPartBrowserExtension::KHTMLPartBrowserExtension( KHTMLPart *parent )
74: KParts::BrowserExtension( parent )
75{
76 m_part = parent;
77 setURLDropHandlingEnabled( true );
78
79 enableAction( "cut", false );
80 enableAction( "copy", false );
81 enableAction( "paste", false );
82
83 m_connectedToClipboard = false;
84}
85
86int KHTMLPartBrowserExtension::xOffset()
87{
88 return m_part->view()->contentsX();
89}
90
91int KHTMLPartBrowserExtension::yOffset()
92{
93 return m_part->view()->contentsY();
94}
95
96void KHTMLPartBrowserExtension::saveState( QDataStream &stream )
97{
98 //kDebug( 6050 ) << "saveState!";
99 m_part->saveState( stream );
100}
101
102void KHTMLPartBrowserExtension::restoreState( QDataStream &stream )
103{
104 //kDebug( 6050 ) << "restoreState!";
105 m_part->restoreState( stream );
106}
107
108void KHTMLPartBrowserExtension::editableWidgetFocused( QWidget *widget )
109{
110 m_editableFormWidget = widget;
111 updateEditActions();
112
113 if ( !m_connectedToClipboard && m_editableFormWidget )
114 {
115 connect( QApplication::clipboard(), SIGNAL(dataChanged()),
116 this, SLOT(updateEditActions()) );
117
118 if ( m_editableFormWidget->inherits( "QLineEdit" ) || m_editableFormWidget->inherits( "QTextEdit" ) )
119 connect( m_editableFormWidget, SIGNAL(selectionChanged()),
120 this, SLOT(updateEditActions()) );
121
122 m_connectedToClipboard = true;
123 }
124 editableWidgetFocused();
125}
126
127void KHTMLPartBrowserExtension::editableWidgetBlurred( QWidget * /*widget*/ )
128{
129 QWidget *oldWidget = m_editableFormWidget;
130
131 m_editableFormWidget = 0;
132 enableAction( "cut", false );
133 enableAction( "paste", false );
134 m_part->emitSelectionChanged();
135
136 if ( m_connectedToClipboard )
137 {
138 disconnect( QApplication::clipboard(), SIGNAL(dataChanged()),
139 this, SLOT(updateEditActions()) );
140
141 if ( oldWidget )
142 {
143 if ( oldWidget->inherits( "QLineEdit" ) || oldWidget->inherits( "QTextEdit" ) )
144 disconnect( oldWidget, SIGNAL(selectionChanged()),
145 this, SLOT(updateEditActions()) );
146 }
147
148 m_connectedToClipboard = false;
149 }
150 editableWidgetBlurred();
151}
152
153void KHTMLPartBrowserExtension::setExtensionProxy( KParts::BrowserExtension *proxy )
154{
155 if ( m_extensionProxy )
156 {
157 disconnect( m_extensionProxy, SIGNAL(enableAction(const char*,bool)),
158 this, SLOT(extensionProxyActionEnabled(const char*,bool)) );
159 if ( m_extensionProxy->inherits( "KHTMLPartBrowserExtension" ) )
160 {
161 disconnect( m_extensionProxy, SIGNAL(editableWidgetFocused()),
162 this, SLOT(extensionProxyEditableWidgetFocused()) );
163 disconnect( m_extensionProxy, SIGNAL(editableWidgetBlurred()),
164 this, SLOT(extensionProxyEditableWidgetBlurred()) );
165 }
166 }
167
168 m_extensionProxy = proxy;
169
170 if ( m_extensionProxy )
171 {
172 connect( m_extensionProxy, SIGNAL(enableAction(const char*,bool)),
173 this, SLOT(extensionProxyActionEnabled(const char*,bool)) );
174 if ( m_extensionProxy->inherits( "KHTMLPartBrowserExtension" ) )
175 {
176 connect( m_extensionProxy, SIGNAL(editableWidgetFocused()),
177 this, SLOT(extensionProxyEditableWidgetFocused()) );
178 connect( m_extensionProxy, SIGNAL(editableWidgetBlurred()),
179 this, SLOT(extensionProxyEditableWidgetBlurred()) );
180 }
181
182 enableAction( "cut", m_extensionProxy->isActionEnabled( "cut" ) );
183 enableAction( "copy", m_extensionProxy->isActionEnabled( "copy" ) );
184 enableAction( "paste", m_extensionProxy->isActionEnabled( "paste" ) );
185 }
186 else
187 {
188 updateEditActions();
189 enableAction( "copy", false ); // ### re-check this
190 }
191}
192
193void KHTMLPartBrowserExtension::cut()
194{
195 if ( m_extensionProxy )
196 {
197 callExtensionProxyMethod( "cut" );
198 return;
199 }
200
201 if ( !m_editableFormWidget )
202 return;
203
204 QLineEdit* lineEdit = qobject_cast<QLineEdit *>( m_editableFormWidget );
205 if ( lineEdit && !lineEdit->isReadOnly() )
206 lineEdit->cut();
207 QTextEdit* textEdit = qobject_cast<QTextEdit *>( m_editableFormWidget );
208 if ( textEdit && !textEdit->isReadOnly() )
209 textEdit->cut();
210}
211
212void KHTMLPartBrowserExtension::copy()
213{
214 if ( m_extensionProxy )
215 {
216 callExtensionProxyMethod( "copy" );
217 return;
218 }
219
220 if ( !m_editableFormWidget )
221 {
222 // get selected text and paste to the clipboard
223 QString text = m_part->selectedText();
224 text.replace( QChar( 0xa0 ), ' ' );
225 //kDebug(6050) << text;
226
227 QClipboard *cb = QApplication::clipboard();
228 disconnect( cb, SIGNAL(selectionChanged()), m_part, SLOT(slotClearSelection()) );
229#ifndef QT_NO_MIMECLIPBOARD
230 QString htmltext;
231 /*
232 * When selectionModeEnabled, that means the user has just selected
233 * the text, not ctrl+c to copy it. The selection clipboard
234 * doesn't seem to support mime type, so to save time, don't calculate
235 * the selected text as html.
236 * optomisation disabled for now until everything else works.
237 */
238 //if(!cb->selectionModeEnabled())
239 htmltext = m_part->selectedTextAsHTML();
240 QMimeData *mimeData = new QMimeData;
241 mimeData->setText(text);
242 if(!htmltext.isEmpty()) {
243 htmltext.replace( QChar( 0xa0 ), ' ' );
244 mimeData->setHtml(htmltext);
245 }
246 cb->setMimeData(mimeData);
247#else
248 cb->setText(text);
249#endif
250
251 connect( cb, SIGNAL(selectionChanged()), m_part, SLOT(slotClearSelection()) );
252 }
253 else
254 {
255 QLineEdit* lineEdit = qobject_cast<QLineEdit *>( m_editableFormWidget );
256 if ( lineEdit )
257 lineEdit->copy();
258 QTextEdit* textEdit = qobject_cast<QTextEdit *>( m_editableFormWidget );
259 if ( textEdit )
260 textEdit->copy();
261 }
262}
263
264void KHTMLPartBrowserExtension::searchProvider()
265{
266 KAction *action = qobject_cast<KAction*>(sender());
267 if (action) {
268 KUrl url = action->data().toUrl();
269 if (url.host().isEmpty()) {
270 KUriFilterData data(action->data().toString());
271 if (KUriFilter::self()->filterSearchUri(data, KUriFilter::WebShortcutFilter))
272 url = data.uri();
273 }
274
275 KParts::BrowserArguments browserArgs;
276 browserArgs.frameName = "_blank";
277 emit m_part->browserExtension()->openUrlRequest( url, KParts::OpenUrlArguments(), browserArgs );
278 }
279}
280
281void KHTMLPartBrowserExtension::paste()
282{
283 if ( m_extensionProxy )
284 {
285 callExtensionProxyMethod( "paste" );
286 return;
287 }
288
289 if ( !m_editableFormWidget )
290 return;
291
292 QLineEdit* lineEdit = qobject_cast<QLineEdit *>( m_editableFormWidget );
293 if ( lineEdit && !lineEdit->isReadOnly() )
294 lineEdit->paste();
295 QTextEdit* textEdit = qobject_cast<QTextEdit *>( m_editableFormWidget );
296 if ( textEdit && !textEdit->isReadOnly() )
297 textEdit->paste();
298}
299
300void KHTMLPartBrowserExtension::callExtensionProxyMethod( const char *method )
301{
302 if ( !m_extensionProxy )
303 return;
304
305 QMetaObject::invokeMethod(m_extensionProxy, method, Qt::DirectConnection);
306}
307
308void KHTMLPartBrowserExtension::updateEditActions()
309{
310 if ( !m_editableFormWidget )
311 {
312 enableAction( "cut", false );
313 enableAction( "copy", false );
314 enableAction( "paste", false );
315 return;
316 }
317
318 // ### duplicated from KonqMainWindow::slotClipboardDataChanged
319#ifndef QT_NO_MIMECLIPBOARD // Handle minimalized versions of Qt Embedded
320 const QMimeData *data = QApplication::clipboard()->mimeData();
321 enableAction( "paste", data->hasFormat( "text/plain" ) );
322#else
323 QString data=QApplication::clipboard()->text();
324 enableAction( "paste", data.contains("://"));
325#endif
326 bool hasSelection = false;
327
328 if( m_editableFormWidget) {
329 if ( qobject_cast<QLineEdit*>(m_editableFormWidget))
330 hasSelection = static_cast<QLineEdit *>( &(*m_editableFormWidget) )->hasSelectedText();
331 else if(qobject_cast<QTextEdit*>(m_editableFormWidget))
332 hasSelection = static_cast<QTextEdit *>( &(*m_editableFormWidget) )->textCursor().hasSelection();
333 }
334
335 enableAction( "copy", hasSelection );
336 enableAction( "cut", hasSelection );
337}
338
339void KHTMLPartBrowserExtension::extensionProxyEditableWidgetFocused() {
340 editableWidgetFocused();
341}
342
343void KHTMLPartBrowserExtension::extensionProxyEditableWidgetBlurred() {
344 editableWidgetBlurred();
345}
346
347void KHTMLPartBrowserExtension::extensionProxyActionEnabled( const char *action, bool enable )
348{
349 // only forward enableAction calls for actions we actually do forward
350 if ( strcmp( action, "cut" ) == 0 ||
351 strcmp( action, "copy" ) == 0 ||
352 strcmp( action, "paste" ) == 0 ) {
353 enableAction( action, enable );
354 }
355}
356
357void KHTMLPartBrowserExtension::reparseConfiguration()
358{
359 m_part->reparseConfiguration();
360}
361
362void KHTMLPartBrowserExtension::print()
363{
364 m_part->view()->print();
365}
366
367void KHTMLPartBrowserExtension::disableScrolling()
368{
369 QScrollArea *scrollArea = m_part->view();
370 if (scrollArea) {
371 scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
372 scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
373 }
374}
375
376class KHTMLPopupGUIClient::KHTMLPopupGUIClientPrivate
377{
378public:
379 KHTMLPart *m_khtml;
380 KUrl m_url;
381 KUrl m_imageURL;
382 QPixmap m_pixmap;
383 QString m_suggestedFilename;
384 KActionCollection* m_actionCollection;
385 KParts::BrowserExtension::ActionGroupMap actionGroups;
386};
387
388
389KHTMLPopupGUIClient::KHTMLPopupGUIClient( KHTMLPart *khtml, const KUrl &url )
390 : QObject( khtml ), d(new KHTMLPopupGUIClientPrivate)
391{
392 d->m_khtml = khtml;
393 d->m_url = url;
394 d->m_actionCollection = new KActionCollection(this);
395 bool isImage = false;
396 bool hasSelection = khtml->hasSelection();
397
398 DOM::Element e = khtml->nodeUnderMouse();
399
400 if ( !e.isNull() && (e.elementId() == ID_IMG ||
401 (e.elementId() == ID_INPUT && !static_cast<DOM::HTMLInputElement>(e).src().isEmpty())))
402 {
403 if (e.elementId() == ID_IMG) {
404 DOM::HTMLImageElementImpl *ie = static_cast<DOM::HTMLImageElementImpl*>(e.handle());
405 khtml::RenderImage *ri = dynamic_cast<khtml::RenderImage*>(ie->renderer());
406 if (ri && ri->contentObject()) {
407 d->m_suggestedFilename = static_cast<khtml::CachedImage*>(ri->contentObject())->suggestedFilename();
408 }
409 }
410 isImage=true;
411 }
412
413 if (hasSelection) {
414 QList<QAction *> editActions;
415 QAction* copyAction = d->m_actionCollection->addAction( KStandardAction::Copy, "copy",
416 d->m_khtml->browserExtension(), SLOT(copy()) );
417
418 copyAction->setText(i18n("&Copy Text"));
419 copyAction->setEnabled(d->m_khtml->browserExtension()->isActionEnabled( "copy" ));
420 editActions.append(copyAction);
421
422 editActions.append(khtml->actionCollection()->action("selectAll"));
423
424 addSearchActions(editActions);
425
426 QString selectedTextURL = selectedTextAsOneLine(d->m_khtml);
427 if ( selectedTextURL.contains("://") && KUrl(selectedTextURL).isValid() ) {
428 if (selectedTextURL.length() > 18) {
429 selectedTextURL.truncate(15);
430 selectedTextURL += "...";
431 }
432 KAction *action = new KAction(i18n("Open '%1'", selectedTextURL), this);
433 d->m_actionCollection->addAction( "openSelection", action );
434 action->setIcon( KIcon( "window-new" ) );
435 connect( action, SIGNAL(triggered(bool)), this, SLOT(openSelection()) );
436 editActions.append(action);
437 }
438
439 KAction* separator = new KAction(d->m_actionCollection);
440 separator->setSeparator(true);
441 editActions.append(separator);
442
443 d->actionGroups.insert("editactions", editActions);
444 }
445
446 if (!url.isEmpty()) {
447 QList<QAction *> linkActions;
448 if (url.protocol() == "mailto") {
449 KAction *action = new KAction( i18n( "&Copy Email Address" ), this );
450 d->m_actionCollection->addAction( "copylinklocation", action );
451 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotCopyLinkLocation()) );
452 linkActions.append(action);
453 } else {
454 KAction *action = new KAction( i18n( "&Save Link As..." ), this );
455 d->m_actionCollection->addAction( "savelinkas", action );
456 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotSaveLinkAs()) );
457 linkActions.append(action);
458
459 action = new KAction( i18n( "&Copy Link Address" ), this );
460 d->m_actionCollection->addAction( "copylinklocation", action );
461 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotCopyLinkLocation()) );
462 linkActions.append(action);
463 }
464 d->actionGroups.insert("linkactions", linkActions);
465 }
466
467 QList<QAction *> partActions;
468 // frameset? -> add "Reload Frame" etc.
469 if (!hasSelection) {
470 if ( khtml->parentPart() ) {
471 KActionMenu* menu = new KActionMenu( i18nc("@title:menu HTML frame/iframe", "Frame"), this);
472 KAction *action = new KAction( i18n( "Open in New &Window" ), this );
473 d->m_actionCollection->addAction( "frameinwindow", action );
474 action->setIcon( KIcon( "window-new" ) );
475 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotFrameInWindow()) );
476 menu->addAction(action);
477
478 action = new KAction( i18n( "Open in &This Window" ), this );
479 d->m_actionCollection->addAction( "frameintop", action );
480 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotFrameInTop()) );
481 menu->addAction(action);
482
483 action = new KAction( i18n( "Open in &New Tab" ), this );
484 d->m_actionCollection->addAction( "frameintab", action );
485 action->setIcon( KIcon( "tab-new" ) );
486 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotFrameInTab()) );
487 menu->addAction(action);
488
489 action = new KAction(d->m_actionCollection);
490 action->setSeparator(true);
491 menu->addAction(action);
492
493 action = new KAction( i18n( "Reload Frame" ), this );
494 d->m_actionCollection->addAction( "reloadframe", action );
495 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotReloadFrame()) );
496 menu->addAction(action);
497
498 action = new KAction( i18n( "Print Frame..." ), this );
499 d->m_actionCollection->addAction( "printFrame", action );
500 action->setIcon( KIcon( "document-print-frame" ) );
501 connect( action, SIGNAL(triggered(bool)), d->m_khtml->browserExtension(), SLOT(print()) );
502 menu->addAction(action);
503
504 action = new KAction( i18n( "Save &Frame As..." ), this );
505 d->m_actionCollection->addAction( "saveFrame", action );
506 connect( action, SIGNAL(triggered(bool)), d->m_khtml, SLOT(slotSaveFrame()) );
507 menu->addAction(action);
508
509 action = new KAction( i18n( "View Frame Source" ), this );
510 d->m_actionCollection->addAction( "viewFrameSource", action );
511 connect( action, SIGNAL(triggered(bool)), d->m_khtml, SLOT(slotViewDocumentSource()) );
512 menu->addAction(action);
513
514 action = new KAction( i18n( "View Frame Information" ), this );
515 d->m_actionCollection->addAction( "viewFrameInfo", action );
516 connect( action, SIGNAL(triggered(bool)), d->m_khtml, SLOT(slotViewPageInfo()) );
517
518 action = new KAction(d->m_actionCollection);
519 action->setSeparator(true);
520 menu->addAction(action);
521
522 if ( KHTMLGlobal::defaultHTMLSettings()->isAdFilterEnabled() ) {
523 if ( khtml->d->m_frame->m_type == khtml::ChildFrame::IFrame ) {
524 action = new KAction( i18n( "Block IFrame..." ), this );
525 d->m_actionCollection->addAction( "blockiframe", action );
526 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotBlockIFrame()) );
527 menu->addAction(action);
528 }
529 }
530
531 partActions.append(menu);
532 }
533 }
534
535 if (isImage) {
536 if ( e.elementId() == ID_IMG ) {
537 d->m_imageURL = KUrl( static_cast<DOM::HTMLImageElement>( e ).src().string() );
538 DOM::HTMLImageElementImpl *imageimpl = static_cast<DOM::HTMLImageElementImpl *>( e.handle() );
539 Q_ASSERT(imageimpl);
540 if(imageimpl) // should be true always. right?
541 {
542 if(imageimpl->complete()) {
543 d->m_pixmap = imageimpl->currentPixmap();
544 }
545 }
546 }
547 else
548 d->m_imageURL = KUrl( static_cast<DOM::HTMLInputElement>( e ).src().string() );
549 KAction *action = new KAction( i18n( "Save Image As..." ), this );
550 d->m_actionCollection->addAction( "saveimageas", action );
551 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotSaveImageAs()) );
552 partActions.append(action);
553
554 action = new KAction( i18n( "Send Image..." ), this );
555 d->m_actionCollection->addAction( "sendimage", action );
556 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotSendImage()) );
557 partActions.append(action);
558
559#ifndef QT_NO_MIMECLIPBOARD
560 action = new KAction( i18n( "Copy Image" ), this );
561 d->m_actionCollection->addAction( "copyimage", action );
562 action->setEnabled(!d->m_pixmap.isNull());
563 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotCopyImage()) );
564 partActions.append(action);
565#endif
566
567 if(d->m_pixmap.isNull()) { //fallback to image location if still loading the image. this will always be true if ifdef QT_NO_MIMECLIPBOARD
568 action = new KAction( i18n( "Copy Image Location" ), this );
569 d->m_actionCollection->addAction( "copyimagelocation", action );
570 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotCopyImageLocation()) );
571 partActions.append(action);
572 }
573
574 QString actionText = d->m_suggestedFilename.isEmpty() ?
575 KStringHandler::csqueeze(d->m_imageURL.fileName()+d->m_imageURL.query(), 25)
576 : d->m_suggestedFilename;
577 action = new KAction( i18n("View Image (%1)", actionText.replace("&", "&&")), this );
578 d->m_actionCollection->addAction( "viewimage", action );
579 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotViewImage()) );
580 partActions.append(action);
581
582 if (KHTMLGlobal::defaultHTMLSettings()->isAdFilterEnabled()) {
583 action = new KAction( i18n( "Block Image..." ), this );
584 d->m_actionCollection->addAction( "blockimage", action );
585 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotBlockImage()) );
586 partActions.append(action);
587
588 if (!d->m_imageURL.host().isEmpty() &&
589 !d->m_imageURL.protocol().isEmpty())
590 {
591 action = new KAction( i18n( "Block Images From %1" , d->m_imageURL.host()), this );
592 d->m_actionCollection->addAction( "blockhost", action );
593 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotBlockHost()) );
594 partActions.append(action);
595 }
596 }
597 KAction* separator = new KAction(d->m_actionCollection);
598 separator->setSeparator(true);
599 partActions.append(separator);
600 }
601
602 if ( isImage || url.isEmpty() ) {
603 KAction *action = new KAction( i18n( "Stop Animations" ), this );
604 d->m_actionCollection->addAction( "stopanimations", action );
605 connect( action, SIGNAL(triggered(bool)), this, SLOT(slotStopAnimations()) );
606 partActions.append(action);
607 KAction* separator = new KAction(d->m_actionCollection);
608 separator->setSeparator(true);
609 partActions.append(separator);
610 }
611 if (!hasSelection && url.isEmpty()) { // only when right-clicking on the page itself
612 partActions.append(khtml->actionCollection()->action("viewDocumentSource"));
613 }
614 if (!hasSelection && url.isEmpty() && !isImage) {
615 partActions.append(khtml->actionCollection()->action("setEncoding"));
616 }
617 d->actionGroups.insert("partactions", partActions);
618}
619
620KHTMLPopupGUIClient::~KHTMLPopupGUIClient()
621{
622 delete d->m_actionCollection;
623 delete d;
624}
625
626void KHTMLPopupGUIClient::addSearchActions(QList<QAction *>& editActions)
627{
628 QString selectedText = d->m_khtml->simplifiedSelectedText();
629 // replace linefeeds with spaces
630 selectedText.replace(QChar(10), QChar(32)).trimmed();
631
632 if (selectedText.isEmpty())
633 return;
634
635 KUriFilterData data(selectedText);
636 QStringList alternateProviders;
637 alternateProviders << "google" << "google_groups" << "google_news" << "webster" << "dmoz" << "wikipedia";
638 data.setAlternateSearchProviders(alternateProviders);
639 data.setAlternateDefaultSearchProvider("google");
640
641 if (KUriFilter::self()->filterSearchUri(data, KUriFilter::NormalTextFilter)) {
642 const QString squeezedText = KStringHandler::rsqueeze(selectedText, 21);
643 KAction *action = new KAction(i18n("Search for '%1' with %2",
644 squeezedText, data.searchProvider()), this);
645 action->setData(QUrl(data.uri()));
646 action->setIcon(KIcon(data.iconName()));
647 connect(action, SIGNAL(triggered(bool)), d->m_khtml->browserExtension(), SLOT(searchProvider()));
648 d->m_actionCollection->addAction("defaultSearchProvider", action);
649 editActions.append(action);
650
651 const QStringList preferredSearchProviders = data.preferredSearchProviders();
652 if (!preferredSearchProviders.isEmpty()) {
653 KActionMenu* providerList = new KActionMenu(i18n("Search for '%1' with", squeezedText), this);
654 Q_FOREACH(const QString &searchProvider, preferredSearchProviders) {
655 if (searchProvider == data.searchProvider())
656 continue;
657 KAction *action = new KAction(searchProvider, this);
658 action->setData(data.queryForPreferredSearchProvider(searchProvider));
659 d->m_actionCollection->addAction(searchProvider, action);
660 action->setIcon(KIcon(data.iconNameForPreferredSearchProvider(searchProvider)));
661 connect(action, SIGNAL(triggered(bool)), d->m_khtml->browserExtension(), SLOT(searchProvider()));
662 providerList->addAction(action);
663 }
664 d->m_actionCollection->addAction("searchProviderList", providerList);
665 editActions.append(providerList);
666 }
667 }
668}
669
670QString KHTMLPopupGUIClient::selectedTextAsOneLine(KHTMLPart* part)
671{
672 QString text = part->simplifiedSelectedText();
673 // in addition to what simplifiedSelectedText does,
674 // remove linefeeds and any whitespace surrounding it (#113177),
675 // to get it all in a single line.
676 text.remove(QRegExp("[\\s]*\\n+[\\s]*"));
677 return text;
678}
679
680void KHTMLPopupGUIClient::openSelection()
681{
682 KParts::BrowserArguments browserArgs;
683 browserArgs.frameName = "_blank";
684
685 emit d->m_khtml->browserExtension()->openUrlRequest(selectedTextAsOneLine(d->m_khtml), KParts::OpenUrlArguments(), browserArgs);
686}
687
688KParts::BrowserExtension::ActionGroupMap KHTMLPopupGUIClient::actionGroups() const
689{
690 return d->actionGroups;
691}
692
693void KHTMLPopupGUIClient::slotSaveLinkAs()
694{
695 KIO::MetaData metaData;
696 metaData["referrer"] = d->m_khtml->referrer();
697 saveURL( d->m_khtml->widget(), i18n( "Save Link As" ), d->m_url, metaData );
698}
699
700void KHTMLPopupGUIClient::slotSendImage()
701{
702 QStringList urls;
703 urls.append( d->m_imageURL.url());
704 QString subject = d->m_imageURL.url();
705 KToolInvocation::invokeMailer(QString(), QString(), QString(), subject,
706 QString(), //body
707 QString(),
708 urls); // attachments
709
710
711}
712
713void KHTMLPopupGUIClient::slotSaveImageAs()
714{
715 KIO::MetaData metaData;
716 metaData["referrer"] = d->m_khtml->referrer();
717 saveURL( d->m_khtml->widget(), i18n( "Save Image As" ), d->m_imageURL, metaData, QString(), 0, d->m_suggestedFilename );
718}
719
720void KHTMLPopupGUIClient::slotBlockHost()
721{
722 QString name=d->m_imageURL.protocol()+"://"+d->m_imageURL.host()+"/*";
723 KHTMLGlobal::defaultHTMLSettings()->addAdFilter( name );
724 d->m_khtml->reparseConfiguration();
725}
726
727void KHTMLPopupGUIClient::slotBlockImage()
728{
729 bool ok = false;
730
731 QString url = KInputDialog::getText( i18n("Add URL to Filter"),
732 i18n("Enter the URL:"),
733 d->m_imageURL.url(),
734 &ok);
735 if ( ok ) {
736 KHTMLGlobal::defaultHTMLSettings()->addAdFilter( url );
737 d->m_khtml->reparseConfiguration();
738 }
739}
740
741void KHTMLPopupGUIClient::slotBlockIFrame()
742{
743 bool ok = false;
744 QString url = KInputDialog::getText( i18n( "Add URL to Filter"),
745 i18n("Enter the URL:"),
746 d->m_khtml->url().url(),
747 &ok );
748 if ( ok ) {
749 KHTMLGlobal::defaultHTMLSettings()->addAdFilter( url );
750 d->m_khtml->reparseConfiguration();
751 }
752}
753
754void KHTMLPopupGUIClient::slotCopyLinkLocation()
755{
756 KUrl safeURL(d->m_url);
757 safeURL.setPass(QString());
758#ifndef QT_NO_MIMECLIPBOARD
759 // Set it in both the mouse selection and in the clipboard
760 QMimeData* mimeData = new QMimeData;
761 safeURL.populateMimeData( mimeData );
762 QApplication::clipboard()->setMimeData( mimeData, QClipboard::Clipboard );
763
764 mimeData = new QMimeData;
765 safeURL.populateMimeData( mimeData );
766 QApplication::clipboard()->setMimeData( mimeData, QClipboard::Selection );
767
768#else
769 QApplication::clipboard()->setText( safeURL.url() ); //FIXME(E): Handle multiple entries
770#endif
771}
772
773void KHTMLPopupGUIClient::slotStopAnimations()
774{
775 d->m_khtml->stopAnimations();
776}
777
778void KHTMLPopupGUIClient::slotCopyImage()
779{
780#ifndef QT_NO_MIMECLIPBOARD
781 KUrl safeURL(d->m_imageURL);
782 safeURL.setPass(QString());
783
784 // Set it in both the mouse selection and in the clipboard
785 QMimeData* mimeData = new QMimeData;
786 mimeData->setImageData( d->m_pixmap );
787 safeURL.populateMimeData( mimeData );
788 QApplication::clipboard()->setMimeData( mimeData, QClipboard::Clipboard );
789
790 mimeData = new QMimeData;
791 mimeData->setImageData( d->m_pixmap );
792 safeURL.populateMimeData( mimeData );
793 QApplication::clipboard()->setMimeData( mimeData, QClipboard::Selection );
794#else
795 kDebug() << "slotCopyImage called when the clipboard does not support this. This should not be possible.";
796#endif
797}
798
799void KHTMLPopupGUIClient::slotCopyImageLocation()
800{
801 KUrl safeURL(d->m_imageURL);
802 safeURL.setPass(QString());
803#ifndef QT_NO_MIMECLIPBOARD
804 // Set it in both the mouse selection and in the clipboard
805 QMimeData* mimeData = new QMimeData;
806 safeURL.populateMimeData( mimeData );
807 QApplication::clipboard()->setMimeData( mimeData, QClipboard::Clipboard );
808 mimeData = new QMimeData;
809 safeURL.populateMimeData( mimeData );
810 QApplication::clipboard()->setMimeData( mimeData, QClipboard::Selection );
811#else
812 QApplication::clipboard()->setText( safeURL.url() ); //FIXME(E): Handle multiple entries
813#endif
814}
815
816void KHTMLPopupGUIClient::slotViewImage()
817{
818 d->m_khtml->browserExtension()->createNewWindow(d->m_imageURL);
819}
820
821void KHTMLPopupGUIClient::slotReloadFrame()
822{
823 KParts::OpenUrlArguments args = d->m_khtml->arguments();
824 args.setReload( true );
825 args.metaData()["referrer"] = d->m_khtml->pageReferrer();
826 // reload document
827 d->m_khtml->closeUrl();
828 d->m_khtml->setArguments( args );
829 d->m_khtml->openUrl( d->m_khtml->url() );
830}
831
832void KHTMLPopupGUIClient::slotFrameInWindow()
833{
834 KParts::OpenUrlArguments args = d->m_khtml->arguments();
835 args.metaData()["referrer"] = d->m_khtml->pageReferrer();
836 KParts::BrowserArguments browserArgs( d->m_khtml->browserExtension()->browserArguments() );
837 browserArgs.setForcesNewWindow(true);
838 emit d->m_khtml->browserExtension()->createNewWindow( d->m_khtml->url(), args, browserArgs );
839}
840
841void KHTMLPopupGUIClient::slotFrameInTop()
842{
843 KParts::OpenUrlArguments args = d->m_khtml->arguments();
844 args.metaData()["referrer"] = d->m_khtml->pageReferrer();
845 KParts::BrowserArguments browserArgs( d->m_khtml->browserExtension()->browserArguments() );
846 browserArgs.frameName = "_top";
847 emit d->m_khtml->browserExtension()->openUrlRequest( d->m_khtml->url(), args, browserArgs );
848}
849
850void KHTMLPopupGUIClient::slotFrameInTab()
851{
852 KParts::OpenUrlArguments args = d->m_khtml->arguments();
853 args.metaData()["referrer"] = d->m_khtml->pageReferrer();
854 KParts::BrowserArguments browserArgs( d->m_khtml->browserExtension()->browserArguments() );
855 browserArgs.setNewTab(true);
856 emit d->m_khtml->browserExtension()->createNewWindow( d->m_khtml->url(), args, browserArgs );
857}
858
859void KHTMLPopupGUIClient::saveURL( QWidget *parent, const QString &caption,
860 const KUrl &url,
861 const QMap<QString, QString> &metadata,
862 const QString &filter, long cacheId,
863 const QString & suggestedFilename )
864{
865 QString name = QLatin1String( "index.html" );
866 if ( !suggestedFilename.isEmpty() )
867 name = suggestedFilename;
868 else if ( !url.fileName(KUrl::ObeyTrailingSlash).isEmpty() )
869 name = url.fileName(KUrl::ObeyTrailingSlash);
870
871 KUrl destURL;
872 int query;
873 do {
874 query = KMessageBox::Yes;
875 // convert filename to URL using fromPath to avoid trouble with ':' in filenames (#184202)
876 destURL = KFileDialog::getSaveUrl( KUrl::fromPath(name), filter, parent, caption );
877 if( destURL.isLocalFile() )
878 {
879 QFileInfo info( destURL.toLocalFile() );
880 if( info.exists() ) {
881 // TODO: use KIO::RenameDlg (shows more information)
882 query = KMessageBox::warningContinueCancel( parent, i18n( "A file named \"%1\" already exists. " "Are you sure you want to overwrite it?" , info.fileName() ), i18n( "Overwrite File?" ), KGuiItem(i18n( "Overwrite" )) );
883 }
884 }
885 } while ( query == KMessageBox::Cancel );
886
887 if ( destURL.isValid() )
888 saveURL(parent, url, destURL, metadata, cacheId);
889}
890
891void KHTMLPopupGUIClient::saveURL( QWidget* parent, const KUrl &url, const KUrl &destURL,
892 const QMap<QString, QString> &metadata,
893 long cacheId )
894{
895 if ( destURL.isValid() )
896 {
897 bool saved = false;
898 if (KHTMLPageCache::self()->isComplete(cacheId))
899 {
900 if (destURL.isLocalFile())
901 {
902 KSaveFile destFile(destURL.toLocalFile());
903 if (destFile.open())
904 {
905 QDataStream stream ( &destFile );
906 KHTMLPageCache::self()->saveData(cacheId, &stream);
907 saved = true;
908 }
909 }
910 else
911 {
912 // save to temp file, then move to final destination.
913 KTemporaryFile destFile;
914 if (destFile.open())
915 {
916 QDataStream stream ( &destFile );
917 KHTMLPageCache::self()->saveData(cacheId, &stream);
918 KUrl url2 = KUrl();
919 url2.setPath(destFile.fileName());
920 KIO::file_move(url2, destURL, -1, KIO::Overwrite);
921 saved = true;
922 }
923 }
924 }
925 if(!saved)
926 {
927 // DownloadManager <-> konqueror integration
928 // find if the integration is enabled
929 // the empty key means no integration
930 // only use download manager for non-local urls!
931 bool downloadViaKIO = true;
932 if ( !url.isLocalFile() )
933 {
934 KConfigGroup cfg = KSharedConfig::openConfig("konquerorrc", KConfig::NoGlobals)->group("HTML Settings");
935 QString downloadManger = cfg.readPathEntry("DownloadManager", QString());
936 if (!downloadManger.isEmpty())
937 {
938 // then find the download manager location
939 kDebug(1000) << "Using: "<<downloadManger <<" as Download Manager";
940 QString cmd = KStandardDirs::findExe(downloadManger);
941 if (cmd.isEmpty())
942 {
943 QString errMsg=i18n("The Download Manager (%1) could not be found in your $PATH ", downloadManger);
944 QString errMsgEx= i18n("Try to reinstall it \n\nThe integration with Konqueror will be disabled.");
945 KMessageBox::detailedSorry(0,errMsg,errMsgEx);
946 cfg.writePathEntry("DownloadManager",QString());
947 cfg.sync ();
948 }
949 else
950 {
951 downloadViaKIO = false;
952 KUrl cleanDest = destURL;
953 cleanDest.setPass( QString() ); // don't put password into commandline
954 cmd += ' ' + KShell::quoteArg(url.url()) + ' ' +
955 KShell::quoteArg(cleanDest.url());
956 kDebug(1000) << "Calling command "<<cmd;
957 KRun::runCommand(cmd, parent->topLevelWidget());
958 }
959 }
960 }
961
962 if ( downloadViaKIO )
963 {
964 KParts::BrowserRun::saveUrlUsingKIO(url, destURL, parent, metadata);
965 }
966 } //end if(!saved)
967 }
968}
969
970KHTMLPartBrowserHostExtension::KHTMLPartBrowserHostExtension( KHTMLPart *part )
971: KParts::BrowserHostExtension( part )
972{
973 m_part = part;
974}
975
976KHTMLPartBrowserHostExtension::~KHTMLPartBrowserHostExtension()
977{
978}
979
980QStringList KHTMLPartBrowserHostExtension::frameNames() const
981{
982 return m_part->frameNames();
983}
984
985const QList<KParts::ReadOnlyPart*> KHTMLPartBrowserHostExtension::frames() const
986{
987 return m_part->frames();
988}
989
990bool KHTMLPartBrowserHostExtension::openUrlInFrame(const KUrl &url, const KParts::OpenUrlArguments& arguments, const KParts::BrowserArguments &browserArguments)
991{
992 return m_part->openUrlInFrame( url, arguments, browserArguments );
993}
994
995KParts::BrowserHostExtension* KHTMLPartBrowserHostExtension::findFrameParent( KParts::ReadOnlyPart
996 *callingPart, const QString &frame )
997{
998 KHTMLPart *parentPart = m_part->d->findFrameParent(callingPart, frame, 0, true /* navigation*/);
999 if (parentPart)
1000 return parentPart->browserHostExtension();
1001 return 0;
1002}
1003
1004
1005// defined in khtml_part.cpp
1006extern const int KDE_NO_EXPORT fastZoomSizes[];
1007extern const int KDE_NO_EXPORT fastZoomSizeCount;
1008
1009KHTMLZoomFactorAction::KHTMLZoomFactorAction( KHTMLPart *part, bool direction, const QString &icon, const QString &text, QObject *parent )
1010 : KSelectAction( text, parent )
1011{
1012 setIcon( KIcon( icon ) );
1013
1014 setToolBarMode(MenuMode);
1015 setToolButtonPopupMode(QToolButton::DelayedPopup);
1016
1017 init(part, direction);
1018}
1019
1020void KHTMLZoomFactorAction::init(KHTMLPart *part, bool direction)
1021{
1022 m_direction = direction;
1023 m_part = part;
1024
1025 // xgettext: no-c-format
1026 addAction( i18n( "Default Font Size (100%)" ) );
1027
1028 int m = m_direction ? 1 : -1;
1029 int ofs = fastZoomSizeCount / 2; // take index of 100%
1030
1031 // this only works if there is an odd number of elements in fastZoomSizes[]
1032 for ( int i = m; i != m*(ofs+1); i += m )
1033 {
1034 int num = i * m;
1035 QString numStr = QString::number( num );
1036 if ( num > 0 ) numStr.prepend( QLatin1Char('+') );
1037
1038 // xgettext: no-c-format
1039 addAction( i18n( "%1%" , fastZoomSizes[ofs + i] ) );
1040 }
1041
1042 connect( selectableActionGroup(), SIGNAL(triggered(QAction*)), this, SLOT(slotTriggered(QAction*)) );
1043}
1044
1045KHTMLZoomFactorAction::~KHTMLZoomFactorAction()
1046{
1047}
1048
1049void KHTMLZoomFactorAction::slotTriggered(QAction* action)
1050{
1051 int idx = selectableActionGroup()->actions().indexOf(action);
1052
1053 if (idx == 0)
1054 m_part->setFontScaleFactor(100);
1055 else
1056 m_part->setFontScaleFactor(fastZoomSizes[fastZoomSizeCount/2 + (m_direction ? 1 : -1)*idx]);
1057 setCurrentAction( 0L );
1058}
1059
1060KHTMLTextExtension::KHTMLTextExtension(KHTMLPart* part)
1061 : KParts::TextExtension(part)
1062{
1063 connect(part, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));
1064}
1065
1066KHTMLPart* KHTMLTextExtension::part() const
1067{
1068 return static_cast<KHTMLPart*>(parent());
1069}
1070
1071bool KHTMLTextExtension::hasSelection() const
1072{
1073 return part()->hasSelection();
1074}
1075
1076QString KHTMLTextExtension::selectedText(Format format) const
1077{
1078 switch(format) {
1079 case PlainText:
1080 return part()->selectedText();
1081 case HTML:
1082 return part()->selectedTextAsHTML();
1083 }
1084 return QString();
1085}
1086
1087QString KHTMLTextExtension::completeText(Format format) const
1088{
1089 switch(format) {
1090 case PlainText:
1091 return part()->htmlDocument().body().innerText().string();
1092 case HTML:
1093 return part()->htmlDocument().body().innerHTML().string();
1094 }
1095 return QString();
1096}
1097
1098////
1099
1100KHTMLHtmlExtension::KHTMLHtmlExtension(KHTMLPart* part)
1101 : KParts::HtmlExtension(part)
1102{
1103}
1104
1105KUrl KHTMLHtmlExtension::baseUrl() const
1106{
1107 return part()->baseURL();
1108}
1109
1110bool KHTMLHtmlExtension::hasSelection() const
1111{
1112 return part()->hasSelection();
1113}
1114
1115KParts::SelectorInterface::QueryMethods KHTMLHtmlExtension::supportedQueryMethods() const
1116{
1117 return (KParts::SelectorInterface::SelectedContent | KParts::SelectorInterface::EntireContent);
1118}
1119
1120static KParts::SelectorInterface::Element convertDomElement(const DOM::ElementImpl* domElem)
1121{
1122 KParts::SelectorInterface::Element elem;
1123 elem.setTagName(domElem->tagName().string());
1124 const DOM::NamedAttrMapImpl* attrMap = domElem->attributes(true /*readonly*/);
1125 if (attrMap) {
1126 for (unsigned i = 0; i < attrMap->length(); ++i) {
1127 const DOM::AttributeImpl& attr = attrMap->attributeAt(i);
1128 elem.setAttribute(attr.localName().string(), attr.value().string());
1129 // we could have a setAttributeNS too.
1130 }
1131 }
1132 return elem;
1133}
1134
1135KParts::SelectorInterface::Element KHTMLHtmlExtension::querySelector(const QString& query, KParts::SelectorInterface::QueryMethod method) const
1136{
1137 KParts::SelectorInterface::Element element;
1138
1139 // If the specified method is None, return an empty list; similarly
1140 // if the document is null, which may be possible in case of an error
1141 if (method == KParts::SelectorInterface::None || part()->document().isNull())
1142 return element;
1143
1144 if (!(supportedQueryMethods() & method))
1145 return element;
1146
1147 switch (method) {
1148 case KParts::SelectorInterface::EntireContent: {
1149 int ec = 0; // exceptions are ignored
1150 WTF::RefPtr<DOM::ElementImpl> domElem = part()->document().handle()->querySelector(query, ec);
1151 element = convertDomElement(domElem.get());
1152 break;
1153 }
1154 case KParts::SelectorInterface::SelectedContent:
1155 if (part()->hasSelection()) {
1156 DOM::Element domElem = part()->selection().cloneContents().querySelector(query);
1157 element = convertDomElement(static_cast<DOM::ElementImpl*>(domElem.handle()));
1158 }
1159 break;
1160 default:
1161 break;
1162 }
1163
1164 return element;
1165}
1166
1167QList<KParts::SelectorInterface::Element> KHTMLHtmlExtension::querySelectorAll(const QString& query, KParts::SelectorInterface::QueryMethod method) const
1168{
1169 QList<KParts::SelectorInterface::Element> elements;
1170
1171 // If the specified method is None, return an empty list; similarly
1172 // if the document is null, which may be possible in case of an error
1173 if (method == KParts::SelectorInterface::None || part()->document().isNull())
1174 return elements;
1175
1176 // If the specified method is not supported, return an empty list...
1177 if (!(supportedQueryMethods() & method))
1178 return elements;
1179
1180 switch (method) {
1181 case KParts::SelectorInterface::EntireContent: {
1182 int ec = 0; // exceptions are ignored
1183 WTF::RefPtr<DOM::NodeListImpl> nodes = part()->document().handle()->querySelectorAll(query, ec);
1184 const unsigned long len = nodes->length();
1185 elements.reserve(len);
1186 for (unsigned long i = 0; i < len; ++i) {
1187 DOM::NodeImpl* node = nodes->item(i);
1188 if (node->isElementNode()) { // should be always true
1189 elements.append(convertDomElement(static_cast<DOM::ElementImpl*>(node)));
1190 }
1191 }
1192 break;
1193 }
1194 case KParts::SelectorInterface::SelectedContent:
1195 if (part()->hasSelection()) {
1196 DOM::NodeList nodes = part()->selection().cloneContents().querySelectorAll(query);
1197 const unsigned long len = nodes.length();
1198 for (unsigned long i = 0; i < len; ++i) {
1199 DOM::NodeImpl* node = nodes.item(i).handle();
1200 if (node->isElementNode())
1201 elements.append(convertDomElement(static_cast<DOM::ElementImpl*>(node)));
1202 }
1203 }
1204 break;
1205 default:
1206 break;
1207 }
1208
1209 return elements;
1210}
1211
1212QVariant KHTMLHtmlExtension::htmlSettingsProperty(HtmlSettingsInterface::HtmlSettingsType type) const
1213{
1214 if (part()) {
1215 switch (type) {
1216 case KParts::HtmlSettingsInterface::AutoLoadImages:
1217 return part()->autoloadImages();
1218 case KParts::HtmlSettingsInterface::DnsPrefetchEnabled:
1219 return (part()->dnsPrefetch() == KHTMLPart::DNSPrefetchEnabled);
1220 case KParts::HtmlSettingsInterface::JavaEnabled:
1221 return part()->javaEnabled();
1222 case KParts::HtmlSettingsInterface::JavascriptEnabled:
1223 return part()->jScriptEnabled();
1224 case KParts::HtmlSettingsInterface::MetaRefreshEnabled:
1225 return part()->metaRefreshEnabled();
1226 case KParts::HtmlSettingsInterface::PluginsEnabled:
1227 return part()->pluginsEnabled();
1228 default:
1229 break;
1230 }
1231 }
1232 return QVariant();
1233}
1234
1235bool KHTMLHtmlExtension::setHtmlSettingsProperty(HtmlSettingsInterface::HtmlSettingsType type, const QVariant& value)
1236{
1237 KHTMLPart* p = part();
1238
1239 if (p) {
1240 switch (type) {
1241 case KParts::HtmlSettingsInterface::AutoLoadImages:
1242 p->setAutoloadImages(value.toBool());
1243 return true;
1244 case KParts::HtmlSettingsInterface::DnsPrefetchEnabled:
1245 p->setDNSPrefetch((value.toBool() ? KHTMLPart::DNSPrefetchEnabled : KHTMLPart::DNSPrefetchDisabled));
1246 return true;
1247 case KParts::HtmlSettingsInterface::JavaEnabled:
1248 p->setJavaEnabled(value.toBool());
1249 return true;
1250 case KParts::HtmlSettingsInterface::JavascriptEnabled:
1251 p->setJScriptEnabled(value.toBool());
1252 return true;
1253 case KParts::HtmlSettingsInterface::MetaRefreshEnabled:
1254 p->setMetaRefreshEnabled(value.toBool());
1255 return true;
1256 case KParts::HtmlSettingsInterface::PluginsEnabled:
1257 p->setPluginsEnabled(value.toBool());
1258 return true;
1259 case KParts::HtmlSettingsInterface::UserDefinedStyleSheetURL: {
1260 const KUrl url (value.toUrl());
1261 if (url.protocol() == QLatin1String("data")) {
1262 const QByteArray data (url.encodedPath());
1263 if (!data.isEmpty()) {
1264 const int index = data.indexOf(',');
1265 const QByteArray decodedData ((index > -1 ? QByteArray::fromBase64(data.mid(index)) : QByteArray()));
1266 p->setUserStyleSheet(QString::fromUtf8(decodedData.constData(), decodedData.size()));
1267 }
1268 } else {
1269 p->setUserStyleSheet(url);
1270 }
1271 return true;
1272 }
1273 default:
1274 break; // Unsupported property...
1275 }
1276 }
1277
1278 return false;
1279}
1280
1281
1282KHTMLPart* KHTMLHtmlExtension::part() const
1283{
1284 return static_cast<KHTMLPart*>(parent());
1285}
1286
1287#include "khtml_ext.moc"
1288