File indexing completed on 2024-04-28 11:39:46

0001 /* This file is part of the KDE project
0002  *
0003  * Copyright (C) 2000-2003 Simon Hausmann <hausmann@kde.org>
0004  *               2001-2003 George Staikos <staikos@kde.org>
0005  *               2001-2003 Laurent Montel <montel@kde.org>
0006  *               2001-2003 Dirk Mueller <mueller@kde.org>
0007  *               2001-2003 Waldo Bastian <bastian@kde.org>
0008  *               2001-2003 David Faure <faure@kde.org>
0009  *               2001-2003 Daniel Naber <dnaber@kde.org>
0010  *
0011  * This library is free software; you can redistribute it and/or
0012  * modify it under the terms of the GNU Library General Public
0013  * License as published by the Free Software Foundation; either
0014  * version 2 of the License, or (at your option) any later version.
0015  *
0016  * This library is distributed in the hope that it will be useful,
0017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0019  * Library General Public License for more details.
0020  *
0021  * You should have received a copy of the GNU Library General Public License
0022  * along with this library; see the file COPYING.LIB.  If not, write to
0023  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0024  * Boston, MA 02110-1301, USA.
0025  */
0026 
0027 #include "khtml_ext.h"
0028 #include "khtmlview.h"
0029 #include "khtml_pagecache.h"
0030 #include "rendering/render_form.h"
0031 #include "rendering/render_image.h"
0032 #include "html/html_imageimpl.h"
0033 #include "misc/loader.h"
0034 #include "dom/html_form.h"
0035 #include "dom/html_image.h"
0036 #include "dom/dom_string.h"
0037 #include "dom/html_document.h"
0038 #include "dom/dom_element.h"
0039 #include "xml/dom_elementimpl.h"
0040 #include <QClipboard>
0041 #include <QFileInfo>
0042 #include <QFileDialog>
0043 #include <QMenu>
0044 #include <QUrl>
0045 #include <QMetaEnum>
0046 #include <QMimeData>
0047 #include <qstandardpaths.h>
0048 #include <qinputdialog.h>
0049 #include <assert.h>
0050 
0051 #include <kconfiggroup.h>
0052 #include <ksharedconfig.h>
0053 #include "khtml_debug.h"
0054 #include <klocalizedstring.h>
0055 #include <kjobuidelegate.h>
0056 #include <kio/job.h>
0057 #include <kshell.h>
0058 #include <qsavefile.h>
0059 #include <kstringhandler.h>
0060 #include <ktoolinvocation.h>
0061 #include <kmessagebox.h>
0062 #include <krun.h>
0063 #include <kurifilter.h>
0064 #include <kdesktopfile.h>
0065 #include <qtemporaryfile.h>
0066 #include "khtml_global.h"
0067 #include <kstandardaction.h>
0068 #include <kactioncollection.h>
0069 #include <kactionmenu.h>
0070 
0071 #include "khtmlpart_p.h"
0072 
0073 KHTMLPartBrowserExtension::KHTMLPartBrowserExtension(KHTMLPart *parent)
0074     : KParts::BrowserExtension(parent)
0075 {
0076     m_part = parent;
0077     setURLDropHandlingEnabled(true);
0078 
0079     enableAction("cut", false);
0080     enableAction("copy", false);
0081     enableAction("paste", false);
0082 
0083     m_connectedToClipboard = false;
0084 }
0085 
0086 int KHTMLPartBrowserExtension::xOffset()
0087 {
0088     return m_part->view()->contentsX();
0089 }
0090 
0091 int KHTMLPartBrowserExtension::yOffset()
0092 {
0093     return m_part->view()->contentsY();
0094 }
0095 
0096 void KHTMLPartBrowserExtension::saveState(QDataStream &stream)
0097 {
0098     //qCDebug(KHTML_LOG) << "saveState!";
0099     m_part->saveState(stream);
0100 }
0101 
0102 void KHTMLPartBrowserExtension::restoreState(QDataStream &stream)
0103 {
0104     //qCDebug(KHTML_LOG) << "restoreState!";
0105     m_part->restoreState(stream);
0106 }
0107 
0108 void KHTMLPartBrowserExtension::editableWidgetFocused(QWidget *widget)
0109 {
0110     m_editableFormWidget = widget;
0111     updateEditActions();
0112 
0113     if (!m_connectedToClipboard && m_editableFormWidget) {
0114         connect(QApplication::clipboard(), SIGNAL(dataChanged()),
0115                 this, SLOT(updateEditActions()));
0116 
0117         if (m_editableFormWidget->inherits("QLineEdit") || m_editableFormWidget->inherits("QTextEdit"))
0118             connect(m_editableFormWidget, SIGNAL(selectionChanged()),
0119                     this, SLOT(updateEditActions()));
0120 
0121         m_connectedToClipboard = true;
0122     }
0123     editableWidgetFocused();
0124 }
0125 
0126 void KHTMLPartBrowserExtension::editableWidgetBlurred(QWidget * /*widget*/)
0127 {
0128     QWidget *oldWidget = m_editableFormWidget;
0129 
0130     m_editableFormWidget = nullptr;
0131     enableAction("cut", false);
0132     enableAction("paste", false);
0133     m_part->emitSelectionChanged();
0134 
0135     if (m_connectedToClipboard) {
0136         disconnect(QApplication::clipboard(), SIGNAL(dataChanged()),
0137                    this, SLOT(updateEditActions()));
0138 
0139         if (oldWidget) {
0140             if (oldWidget->inherits("QLineEdit") || oldWidget->inherits("QTextEdit"))
0141                 disconnect(oldWidget, SIGNAL(selectionChanged()),
0142                            this, SLOT(updateEditActions()));
0143         }
0144 
0145         m_connectedToClipboard = false;
0146     }
0147     editableWidgetBlurred();
0148 }
0149 
0150 void KHTMLPartBrowserExtension::setExtensionProxy(KParts::BrowserExtension *proxy)
0151 {
0152     if (m_extensionProxy) {
0153         disconnect(m_extensionProxy, SIGNAL(enableAction(const char*,bool)),
0154                    this, SLOT(extensionProxyActionEnabled(const char*,bool)));
0155         if (m_extensionProxy->inherits("KHTMLPartBrowserExtension")) {
0156             disconnect(m_extensionProxy, SIGNAL(editableWidgetFocused()),
0157                        this, SLOT(extensionProxyEditableWidgetFocused()));
0158             disconnect(m_extensionProxy, SIGNAL(editableWidgetBlurred()),
0159                        this, SLOT(extensionProxyEditableWidgetBlurred()));
0160         }
0161     }
0162 
0163     m_extensionProxy = proxy;
0164 
0165     if (m_extensionProxy) {
0166         connect(m_extensionProxy, SIGNAL(enableAction(const char*,bool)),
0167                 this, SLOT(extensionProxyActionEnabled(const char*,bool)));
0168         if (m_extensionProxy->inherits("KHTMLPartBrowserExtension")) {
0169             connect(m_extensionProxy, SIGNAL(editableWidgetFocused()),
0170                     this, SLOT(extensionProxyEditableWidgetFocused()));
0171             connect(m_extensionProxy, SIGNAL(editableWidgetBlurred()),
0172                     this, SLOT(extensionProxyEditableWidgetBlurred()));
0173         }
0174 
0175         enableAction("cut", m_extensionProxy->isActionEnabled("cut"));
0176         enableAction("copy", m_extensionProxy->isActionEnabled("copy"));
0177         enableAction("paste", m_extensionProxy->isActionEnabled("paste"));
0178     } else {
0179         updateEditActions();
0180         enableAction("copy", false);   // ### re-check this
0181     }
0182 }
0183 
0184 void KHTMLPartBrowserExtension::cut()
0185 {
0186     if (m_extensionProxy) {
0187         callExtensionProxyMethod("cut");
0188         return;
0189     }
0190 
0191     if (!m_editableFormWidget) {
0192         return;
0193     }
0194 
0195     QLineEdit *lineEdit = qobject_cast<QLineEdit *>(m_editableFormWidget);
0196     if (lineEdit && !lineEdit->isReadOnly()) {
0197         lineEdit->cut();
0198     }
0199     QTextEdit *textEdit = qobject_cast<QTextEdit *>(m_editableFormWidget);
0200     if (textEdit && !textEdit->isReadOnly()) {
0201         textEdit->cut();
0202     }
0203 }
0204 
0205 void KHTMLPartBrowserExtension::copy()
0206 {
0207     if (m_extensionProxy) {
0208         callExtensionProxyMethod("copy");
0209         return;
0210     }
0211 
0212     if (!m_editableFormWidget) {
0213         // get selected text and paste to the clipboard
0214         QString text = m_part->selectedText();
0215         text.replace(QChar(0xa0), ' ');
0216         //qCDebug(KHTML_LOG) << text;
0217 
0218         QClipboard *cb = QApplication::clipboard();
0219         disconnect(cb, SIGNAL(selectionChanged()), m_part, SLOT(slotClearSelection()));
0220 #ifndef QT_NO_MIMECLIPBOARD
0221         QString htmltext;
0222         /*
0223          * When selectionModeEnabled, that means the user has just selected
0224          * the text, not ctrl+c to copy it.  The selection clipboard
0225          * doesn't seem to support mime type, so to save time, don't calculate
0226          * the selected text as html.
0227          * optomisation disabled for now until everything else works.
0228         */
0229         //if(!cb->selectionModeEnabled())
0230         htmltext = m_part->selectedTextAsHTML();
0231         QMimeData *mimeData = new QMimeData;
0232         mimeData->setText(text);
0233         if (!htmltext.isEmpty()) {
0234             htmltext.replace(QChar(0xa0), ' ');
0235             mimeData->setHtml(htmltext);
0236         }
0237         cb->setMimeData(mimeData);
0238 #else
0239         cb->setText(text);
0240 #endif
0241 
0242         connect(cb, SIGNAL(selectionChanged()), m_part, SLOT(slotClearSelection()));
0243     } else {
0244         QLineEdit *lineEdit = qobject_cast<QLineEdit *>(m_editableFormWidget);
0245         if (lineEdit) {
0246             lineEdit->copy();
0247         }
0248         QTextEdit *textEdit = qobject_cast<QTextEdit *>(m_editableFormWidget);
0249         if (textEdit) {
0250             textEdit->copy();
0251         }
0252     }
0253 }
0254 
0255 void KHTMLPartBrowserExtension::searchProvider()
0256 {
0257     QAction *action = qobject_cast<QAction *>(sender());
0258     if (action) {
0259         QUrl url = action->data().toUrl();
0260         if (url.host().isEmpty()) {
0261             KUriFilterData data(action->data().toString());
0262             if (KUriFilter::self()->filterSearchUri(data, KUriFilter::WebShortcutFilter)) {
0263                 url = data.uri();
0264             }
0265         }
0266 
0267         KParts::BrowserArguments browserArgs;
0268         browserArgs.frameName = "_blank";
0269         emit m_part->browserExtension()->openUrlRequest(url, KParts::OpenUrlArguments(), browserArgs);
0270     }
0271 }
0272 
0273 void KHTMLPartBrowserExtension::paste()
0274 {
0275     if (m_extensionProxy) {
0276         callExtensionProxyMethod("paste");
0277         return;
0278     }
0279 
0280     if (!m_editableFormWidget) {
0281         return;
0282     }
0283 
0284     QLineEdit *lineEdit = qobject_cast<QLineEdit *>(m_editableFormWidget);
0285     if (lineEdit && !lineEdit->isReadOnly()) {
0286         lineEdit->paste();
0287     }
0288     QTextEdit *textEdit = qobject_cast<QTextEdit *>(m_editableFormWidget);
0289     if (textEdit && !textEdit->isReadOnly()) {
0290         textEdit->paste();
0291     }
0292 }
0293 
0294 void KHTMLPartBrowserExtension::callExtensionProxyMethod(const char *method)
0295 {
0296     if (!m_extensionProxy) {
0297         return;
0298     }
0299 
0300     QMetaObject::invokeMethod(m_extensionProxy, method, Qt::DirectConnection);
0301 }
0302 
0303 void KHTMLPartBrowserExtension::updateEditActions()
0304 {
0305     if (!m_editableFormWidget) {
0306         enableAction("cut", false);
0307         enableAction("copy", false);
0308         enableAction("paste", false);
0309         return;
0310     }
0311 
0312     // ### duplicated from KonqMainWindow::slotClipboardDataChanged
0313 #ifndef QT_NO_MIMECLIPBOARD // Handle minimalized versions of Qt Embedded
0314     const QMimeData *data = QApplication::clipboard()->mimeData();
0315     enableAction("paste", data->hasText());
0316 #else
0317     QString data = QApplication::clipboard()->text();
0318     enableAction("paste", data.contains("://"));
0319 #endif
0320     bool hasSelection = false;
0321 
0322     if (m_editableFormWidget) {
0323         if (qobject_cast<QLineEdit *>(m_editableFormWidget)) {
0324             hasSelection = static_cast<QLineEdit *>(&(*m_editableFormWidget))->hasSelectedText();
0325         } else if (qobject_cast<QTextEdit *>(m_editableFormWidget)) {
0326             hasSelection = static_cast<QTextEdit *>(&(*m_editableFormWidget))->textCursor().hasSelection();
0327         }
0328     }
0329 
0330     enableAction("copy", hasSelection);
0331     enableAction("cut", hasSelection);
0332 }
0333 
0334 void KHTMLPartBrowserExtension::extensionProxyEditableWidgetFocused()
0335 {
0336     editableWidgetFocused();
0337 }
0338 
0339 void KHTMLPartBrowserExtension::extensionProxyEditableWidgetBlurred()
0340 {
0341     editableWidgetBlurred();
0342 }
0343 
0344 void KHTMLPartBrowserExtension::extensionProxyActionEnabled(const char *action, bool enable)
0345 {
0346     // only forward enableAction calls for actions we actually do forward
0347     if (strcmp(action, "cut") == 0 ||
0348             strcmp(action, "copy") == 0 ||
0349             strcmp(action, "paste") == 0) {
0350         enableAction(action, enable);
0351     }
0352 }
0353 
0354 void KHTMLPartBrowserExtension::reparseConfiguration()
0355 {
0356     m_part->reparseConfiguration();
0357 }
0358 
0359 void KHTMLPartBrowserExtension::print()
0360 {
0361     m_part->view()->print();
0362 }
0363 
0364 void KHTMLPartBrowserExtension::disableScrolling()
0365 {
0366     QScrollArea *scrollArea = m_part->view();
0367     if (scrollArea) {
0368         scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
0369         scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
0370     }
0371 }
0372 
0373 class KHTMLPopupGUIClient::KHTMLPopupGUIClientPrivate
0374 {
0375 public:
0376     KHTMLPart *m_khtml;
0377     QUrl m_url;
0378     QUrl m_imageURL;
0379     QPixmap m_pixmap;
0380     QString m_suggestedFilename;
0381     KActionCollection *m_actionCollection;
0382     KParts::BrowserExtension::ActionGroupMap actionGroups;
0383 };
0384 
0385 KHTMLPopupGUIClient::KHTMLPopupGUIClient(KHTMLPart *khtml, const QUrl &url)
0386     : QObject(khtml), d(new KHTMLPopupGUIClientPrivate)
0387 {
0388     d->m_khtml = khtml;
0389     d->m_url = url;
0390     d->m_actionCollection = new KActionCollection(this);
0391     bool isImage = false;
0392     bool hasSelection = khtml->hasSelection();
0393 
0394     DOM::Element e = khtml->nodeUnderMouse();
0395 
0396     if (!e.isNull() && (e.elementId() == ID_IMG ||
0397                         (e.elementId() == ID_INPUT && !static_cast<DOM::HTMLInputElement>(e).src().isEmpty()))) {
0398         if (e.elementId() == ID_IMG) {
0399             DOM::HTMLImageElementImpl *ie = static_cast<DOM::HTMLImageElementImpl *>(e.handle());
0400             khtml::RenderImage *ri = dynamic_cast<khtml::RenderImage *>(ie->renderer());
0401             if (ri && ri->contentObject()) {
0402                 d->m_suggestedFilename = static_cast<khtml::CachedImage *>(ri->contentObject())->suggestedFilename();
0403             }
0404         }
0405         isImage = true;
0406     }
0407 
0408     if (hasSelection) {
0409         QList<QAction *> editActions;
0410         QAction *copyAction = d->m_actionCollection->addAction(KStandardAction::Copy, "copy",
0411                               d->m_khtml->browserExtension(), SLOT(copy()));
0412 
0413         copyAction->setText(i18n("&Copy Text"));
0414         copyAction->setEnabled(d->m_khtml->browserExtension()->isActionEnabled("copy"));
0415         editActions.append(copyAction);
0416 
0417         editActions.append(khtml->actionCollection()->action("selectAll"));
0418 
0419         addSearchActions(editActions);
0420 
0421         QString selectedTextURL = selectedTextAsOneLine(d->m_khtml);
0422         if (selectedTextURL.contains("://") && QUrl(selectedTextURL).isValid()) {
0423             if (selectedTextURL.length() > 18) {
0424                 selectedTextURL.truncate(15);
0425                 selectedTextURL += "...";
0426             }
0427             QAction *action = new QAction(i18n("Open '%1'", selectedTextURL), this);
0428             d->m_actionCollection->addAction("openSelection", action);
0429             action->setIcon(QIcon::fromTheme("window-new"));
0430             connect(action, SIGNAL(triggered(bool)), this, SLOT(openSelection()));
0431             editActions.append(action);
0432         }
0433 
0434         QAction *separator = new QAction(d->m_actionCollection);
0435         separator->setSeparator(true);
0436         editActions.append(separator);
0437 
0438         d->actionGroups.insert("editactions", editActions);
0439     }
0440 
0441     if (!url.isEmpty()) {
0442         QList<QAction *> linkActions;
0443         if (url.scheme() == "mailto") {
0444             QAction *action = new QAction(i18n("&Copy Email Address"), this);
0445             d->m_actionCollection->addAction("copylinklocation", action);
0446             connect(action, SIGNAL(triggered(bool)), this, SLOT(slotCopyLinkLocation()));
0447             linkActions.append(action);
0448         } else {
0449             QAction *action = new QAction(i18n("&Save Link As..."), this);
0450             d->m_actionCollection->addAction("savelinkas", action);
0451             connect(action, SIGNAL(triggered(bool)), this, SLOT(slotSaveLinkAs()));
0452             linkActions.append(action);
0453 
0454             action = new QAction(i18n("&Copy Link Address"), this);
0455             d->m_actionCollection->addAction("copylinklocation", action);
0456             connect(action, SIGNAL(triggered(bool)), this, SLOT(slotCopyLinkLocation()));
0457             linkActions.append(action);
0458         }
0459         d->actionGroups.insert("linkactions", linkActions);
0460     }
0461 
0462     QList<QAction *> partActions;
0463     // frameset? -> add "Reload Frame" etc.
0464     if (!hasSelection) {
0465         if (khtml->parentPart()) {
0466             KActionMenu *menu = new KActionMenu(i18nc("@title:menu HTML frame/iframe", "Frame"), this);
0467             QAction *action = new QAction(i18n("Open in New &Window"), this);
0468             d->m_actionCollection->addAction("frameinwindow", action);
0469             action->setIcon(QIcon::fromTheme("window-new"));
0470             connect(action, SIGNAL(triggered(bool)), this, SLOT(slotFrameInWindow()));
0471             menu->addAction(action);
0472 
0473             action = new QAction(i18n("Open in &This Window"), this);
0474             d->m_actionCollection->addAction("frameintop", action);
0475             connect(action, SIGNAL(triggered(bool)), this, SLOT(slotFrameInTop()));
0476             menu->addAction(action);
0477 
0478             action = new QAction(i18n("Open in &New Tab"), this);
0479             d->m_actionCollection->addAction("frameintab", action);
0480             action->setIcon(QIcon::fromTheme("tab-new"));
0481             connect(action, SIGNAL(triggered(bool)), this, SLOT(slotFrameInTab()));
0482             menu->addAction(action);
0483 
0484             action = new QAction(d->m_actionCollection);
0485             action->setSeparator(true);
0486             menu->addAction(action);
0487 
0488             action = new QAction(i18n("Reload Frame"), this);
0489             d->m_actionCollection->addAction("reloadframe", action);
0490             connect(action, SIGNAL(triggered(bool)), this, SLOT(slotReloadFrame()));
0491             menu->addAction(action);
0492 
0493             action = new QAction(i18n("Print Frame..."), this);
0494             d->m_actionCollection->addAction("printFrame", action);
0495             action->setIcon(QIcon::fromTheme("document-print-frame"));
0496             connect(action, SIGNAL(triggered(bool)), d->m_khtml->browserExtension(), SLOT(print()));
0497             menu->addAction(action);
0498 
0499             action = new QAction(i18n("Save &Frame As..."), this);
0500             d->m_actionCollection->addAction("saveFrame", action);
0501             connect(action, SIGNAL(triggered(bool)), d->m_khtml, SLOT(slotSaveFrame()));
0502             menu->addAction(action);
0503 
0504             action = new QAction(i18n("View Frame Source"), this);
0505             d->m_actionCollection->addAction("viewFrameSource", action);
0506             connect(action, SIGNAL(triggered(bool)), d->m_khtml, SLOT(slotViewDocumentSource()));
0507             menu->addAction(action);
0508 
0509             action = new QAction(i18n("View Frame Information"), this);
0510             d->m_actionCollection->addAction("viewFrameInfo", action);
0511             connect(action, SIGNAL(triggered(bool)), d->m_khtml, SLOT(slotViewPageInfo()));
0512 
0513             action = new QAction(d->m_actionCollection);
0514             action->setSeparator(true);
0515             menu->addAction(action);
0516 
0517             if (KHTMLGlobal::defaultHTMLSettings()->isAdFilterEnabled()) {
0518                 if (khtml->d->m_frame->m_type == khtml::ChildFrame::IFrame) {
0519                     action = new QAction(i18n("Block IFrame..."), this);
0520                     d->m_actionCollection->addAction("blockiframe", action);
0521                     connect(action, SIGNAL(triggered(bool)), this, SLOT(slotBlockIFrame()));
0522                     menu->addAction(action);
0523                 }
0524             }
0525 
0526             partActions.append(menu);
0527         }
0528     }
0529 
0530     if (isImage) {
0531         if (e.elementId() == ID_IMG) {
0532             d->m_imageURL = QUrl(static_cast<DOM::HTMLImageElement>(e).src().string());
0533             DOM::HTMLImageElementImpl *imageimpl = static_cast<DOM::HTMLImageElementImpl *>(e.handle());
0534             Q_ASSERT(imageimpl);
0535             if (imageimpl) { // should be true always.  right?
0536                 if (imageimpl->complete()) {
0537                     d->m_pixmap = imageimpl->currentPixmap();
0538                 }
0539             }
0540         } else {
0541             d->m_imageURL = QUrl(static_cast<DOM::HTMLInputElement>(e).src().string());
0542         }
0543         QAction *action = new QAction(i18n("Save Image As..."), this);
0544         d->m_actionCollection->addAction("saveimageas", action);
0545         connect(action, SIGNAL(triggered(bool)), this, SLOT(slotSaveImageAs()));
0546         partActions.append(action);
0547 
0548         action = new QAction(i18n("Send Image..."), this);
0549         d->m_actionCollection->addAction("sendimage", action);
0550         connect(action, SIGNAL(triggered(bool)), this, SLOT(slotSendImage()));
0551         partActions.append(action);
0552 
0553 #ifndef QT_NO_MIMECLIPBOARD
0554         action = new QAction(i18n("Copy Image"), this);
0555         d->m_actionCollection->addAction("copyimage", action);
0556         action->setEnabled(!d->m_pixmap.isNull());
0557         connect(action, SIGNAL(triggered(bool)), this, SLOT(slotCopyImage()));
0558         partActions.append(action);
0559 #endif
0560 
0561         if (d->m_pixmap.isNull()) {   //fallback to image location if still loading the image.  this will always be true if ifdef QT_NO_MIMECLIPBOARD
0562             action = new QAction(i18n("Copy Image Location"), this);
0563             d->m_actionCollection->addAction("copyimagelocation", action);
0564             connect(action, SIGNAL(triggered(bool)), this, SLOT(slotCopyImageLocation()));
0565             partActions.append(action);
0566         }
0567 
0568         QString actionText = d->m_suggestedFilename.isEmpty() ?
0569                              KStringHandler::csqueeze(d->m_imageURL.fileName() + d->m_imageURL.query(), 25)
0570                              : d->m_suggestedFilename;
0571         action = new QAction(i18n("View Image (%1)", actionText.replace("&", "&&")), this);
0572         d->m_actionCollection->addAction("viewimage", action);
0573         connect(action, SIGNAL(triggered(bool)), this, SLOT(slotViewImage()));
0574         partActions.append(action);
0575 
0576         if (KHTMLGlobal::defaultHTMLSettings()->isAdFilterEnabled()) {
0577             action = new QAction(i18n("Block Image..."), this);
0578             d->m_actionCollection->addAction("blockimage", action);
0579             connect(action, SIGNAL(triggered(bool)), this, SLOT(slotBlockImage()));
0580             partActions.append(action);
0581 
0582             if (!d->m_imageURL.host().isEmpty() &&
0583                     !d->m_imageURL.scheme().isEmpty()) {
0584                 action = new QAction(i18n("Block Images From %1", d->m_imageURL.host()), this);
0585                 d->m_actionCollection->addAction("blockhost", action);
0586                 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotBlockHost()));
0587                 partActions.append(action);
0588             }
0589         }
0590         QAction *separator = new QAction(d->m_actionCollection);
0591         separator->setSeparator(true);
0592         partActions.append(separator);
0593     }
0594 
0595     if (isImage || url.isEmpty()) {
0596         QAction *action = new QAction(i18n("Stop Animations"), this);
0597         d->m_actionCollection->addAction("stopanimations", action);
0598         connect(action, SIGNAL(triggered(bool)), this, SLOT(slotStopAnimations()));
0599         partActions.append(action);
0600         QAction *separator = new QAction(d->m_actionCollection);
0601         separator->setSeparator(true);
0602         partActions.append(separator);
0603     }
0604     if (!hasSelection && url.isEmpty()) { // only when right-clicking on the page itself
0605         partActions.append(khtml->actionCollection()->action("viewDocumentSource"));
0606     }
0607     if (!hasSelection && url.isEmpty() && !isImage) {
0608         partActions.append(khtml->actionCollection()->action("setEncoding"));
0609     }
0610     d->actionGroups.insert("partactions", partActions);
0611 }
0612 
0613 KHTMLPopupGUIClient::~KHTMLPopupGUIClient()
0614 {
0615     delete d->m_actionCollection;
0616     delete d;
0617 }
0618 
0619 void KHTMLPopupGUIClient::addSearchActions(QList<QAction *> &editActions)
0620 {
0621     QString selectedText = d->m_khtml->simplifiedSelectedText();
0622     // replace linefeeds with spaces
0623     selectedText = selectedText.replace(QChar(10), QChar(32)).trimmed();
0624 
0625     if (selectedText.isEmpty()) {
0626         return;
0627     }
0628 
0629     KUriFilterData data(selectedText);
0630     QStringList alternateProviders;
0631     alternateProviders << "google" << "google_groups" << "google_news" << "webster" << "dmoz" << "wikipedia";
0632     data.setAlternateSearchProviders(alternateProviders);
0633     data.setAlternateDefaultSearchProvider("google");
0634 
0635     if (KUriFilter::self()->filterSearchUri(data, KUriFilter::NormalTextFilter)) {
0636         const QString squeezedText = KStringHandler::rsqueeze(selectedText, 21);
0637         QAction *action = new QAction(i18n("Search for '%1' with %2",
0638                                            squeezedText, data.searchProvider()), this);
0639         action->setData(QUrl(data.uri()));
0640         action->setIcon(QIcon::fromTheme(data.iconName()));
0641         connect(action, SIGNAL(triggered(bool)), d->m_khtml->browserExtension(), SLOT(searchProvider()));
0642         d->m_actionCollection->addAction("defaultSearchProvider", action);
0643         editActions.append(action);
0644 
0645         const QStringList preferredSearchProviders = data.preferredSearchProviders();
0646         if (!preferredSearchProviders.isEmpty()) {
0647             KActionMenu *providerList = new KActionMenu(i18n("Search for '%1' with", squeezedText), this);
0648             Q_FOREACH (const QString &searchProvider, preferredSearchProviders) {
0649                 if (searchProvider == data.searchProvider()) {
0650                     continue;
0651                 }
0652                 QAction *action = new QAction(searchProvider, this);
0653                 action->setData(data.queryForPreferredSearchProvider(searchProvider));
0654                 d->m_actionCollection->addAction(searchProvider, action);
0655                 action->setIcon(QIcon::fromTheme(data.iconNameForPreferredSearchProvider(searchProvider)));
0656                 connect(action, SIGNAL(triggered(bool)), d->m_khtml->browserExtension(), SLOT(searchProvider()));
0657                 providerList->addAction(action);
0658             }
0659             d->m_actionCollection->addAction("searchProviderList", providerList);
0660             editActions.append(providerList);
0661         }
0662     }
0663 }
0664 
0665 QString KHTMLPopupGUIClient::selectedTextAsOneLine(KHTMLPart *part)
0666 {
0667     QString text = part->simplifiedSelectedText();
0668     // in addition to what simplifiedSelectedText does,
0669     // remove linefeeds and any whitespace surrounding it (#113177),
0670     // to get it all in a single line.
0671     text.remove(QRegExp("[\\s]*\\n+[\\s]*"));
0672     return text;
0673 }
0674 
0675 void KHTMLPopupGUIClient::openSelection()
0676 {
0677     KParts::BrowserArguments browserArgs;
0678     browserArgs.frameName = "_blank";
0679 
0680     QUrl url(selectedTextAsOneLine(d->m_khtml));
0681     emit d->m_khtml->browserExtension()->openUrlRequest(url, KParts::OpenUrlArguments(), browserArgs);
0682 }
0683 
0684 KParts::BrowserExtension::ActionGroupMap KHTMLPopupGUIClient::actionGroups() const
0685 {
0686     return d->actionGroups;
0687 }
0688 
0689 void KHTMLPopupGUIClient::slotSaveLinkAs()
0690 {
0691     KIO::MetaData metaData;
0692     metaData["referrer"] = d->m_khtml->referrer();
0693     saveURL(d->m_khtml->widget(), i18n("Save Link As"), d->m_url, metaData);
0694 }
0695 
0696 void KHTMLPopupGUIClient::slotSendImage()
0697 {
0698     QStringList urls;
0699     urls.append(d->m_imageURL.url());
0700     QString subject = d->m_imageURL.url();
0701     KToolInvocation::invokeMailer(QString(), QString(), QString(), subject,
0702                                   QString(), //body
0703                                   QString(),
0704                                   urls); // attachments
0705 
0706 }
0707 
0708 void KHTMLPopupGUIClient::slotSaveImageAs()
0709 {
0710     KIO::MetaData metaData;
0711     metaData["referrer"] = d->m_khtml->referrer();
0712     saveURL(d->m_khtml->widget(), i18n("Save Image As"), d->m_imageURL, metaData, QString(), 0, d->m_suggestedFilename);
0713 }
0714 
0715 void KHTMLPopupGUIClient::slotBlockHost()
0716 {
0717     QString name = d->m_imageURL.scheme() + "://" + d->m_imageURL.host() + "/*";
0718     KHTMLGlobal::defaultHTMLSettings()->addAdFilter(name);
0719     d->m_khtml->reparseConfiguration();
0720 }
0721 
0722 void KHTMLPopupGUIClient::slotBlockImage()
0723 {
0724     bool ok = false;
0725 
0726     QString url = QInputDialog::getText(d->m_khtml->widget(), i18n("Add URL to Filter"),
0727                                         i18n("Enter the URL:"), QLineEdit::Normal,
0728                                         d->m_imageURL.url(), &ok);
0729     if (ok) {
0730         KHTMLGlobal::defaultHTMLSettings()->addAdFilter(url);
0731         d->m_khtml->reparseConfiguration();
0732     }
0733 }
0734 
0735 void KHTMLPopupGUIClient::slotBlockIFrame()
0736 {
0737     bool ok = false;
0738     QString url = QInputDialog::getText(d->m_khtml->widget(), i18n("Add URL to Filter"),
0739                                         i18n("Enter the URL:"), QLineEdit::Normal,
0740                                         d->m_khtml->url().toString(), &ok);
0741     if (ok) {
0742         KHTMLGlobal::defaultHTMLSettings()->addAdFilter(url);
0743         d->m_khtml->reparseConfiguration();
0744     }
0745 }
0746 
0747 void KHTMLPopupGUIClient::slotCopyLinkLocation()
0748 {
0749     QUrl safeURL(d->m_url);
0750     safeURL.setPassword(QString());
0751 #ifndef QT_NO_MIMECLIPBOARD
0752     // Set it in both the mouse selection and in the clipboard
0753     QMimeData *mimeData = new QMimeData;
0754     mimeData->setUrls(QList<QUrl>() << safeURL);
0755     QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
0756 
0757     mimeData = new QMimeData;
0758     mimeData->setUrls(QList<QUrl>() << safeURL);
0759     QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection);
0760 
0761 #else
0762     QApplication::clipboard()->setText(safeURL.url());   //FIXME(E): Handle multiple entries
0763 #endif
0764 }
0765 
0766 void KHTMLPopupGUIClient::slotStopAnimations()
0767 {
0768     d->m_khtml->stopAnimations();
0769 }
0770 
0771 void KHTMLPopupGUIClient::slotCopyImage()
0772 {
0773 #ifndef QT_NO_MIMECLIPBOARD
0774     QUrl safeURL(d->m_imageURL);
0775     safeURL.setPassword(QString());
0776 
0777     // Set it in both the mouse selection and in the clipboard
0778     QMimeData *mimeData = new QMimeData;
0779     mimeData->setImageData(d->m_pixmap);
0780     mimeData->setUrls(QList<QUrl>() << safeURL);
0781     QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
0782 
0783     mimeData = new QMimeData;
0784     mimeData->setImageData(d->m_pixmap);
0785     mimeData->setUrls(QList<QUrl>() << safeURL);
0786     QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection);
0787 #else
0788     // qCDebug(KHTML_LOG) << "slotCopyImage called when the clipboard does not support this.  This should not be possible.";
0789 #endif
0790 }
0791 
0792 void KHTMLPopupGUIClient::slotCopyImageLocation()
0793 {
0794     QUrl safeURL(d->m_imageURL);
0795     safeURL.setPassword(QString());
0796 #ifndef QT_NO_MIMECLIPBOARD
0797     // Set it in both the mouse selection and in the clipboard
0798     QMimeData *mimeData = new QMimeData;
0799     mimeData->setUrls(QList<QUrl>() << safeURL);
0800     QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
0801     mimeData = new QMimeData;
0802     mimeData->setUrls(QList<QUrl>() << safeURL);
0803     QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection);
0804 #else
0805     QApplication::clipboard()->setText(safeURL.url());   //FIXME(E): Handle multiple entries
0806 #endif
0807 }
0808 
0809 void KHTMLPopupGUIClient::slotViewImage()
0810 {
0811     d->m_khtml->browserExtension()->createNewWindow(d->m_imageURL);
0812 }
0813 
0814 void KHTMLPopupGUIClient::slotReloadFrame()
0815 {
0816     KParts::OpenUrlArguments args = d->m_khtml->arguments();
0817     args.setReload(true);
0818     args.metaData()["referrer"] = d->m_khtml->pageReferrer();
0819     // reload document
0820     d->m_khtml->closeUrl();
0821     d->m_khtml->setArguments(args);
0822     d->m_khtml->openUrl(d->m_khtml->url());
0823 }
0824 
0825 void KHTMLPopupGUIClient::slotFrameInWindow()
0826 {
0827     KParts::OpenUrlArguments args = d->m_khtml->arguments();
0828     args.metaData()["referrer"] = d->m_khtml->pageReferrer();
0829     KParts::BrowserArguments browserArgs(d->m_khtml->browserExtension()->browserArguments());
0830     browserArgs.setForcesNewWindow(true);
0831     emit d->m_khtml->browserExtension()->createNewWindow(d->m_khtml->url(), args, browserArgs);
0832 }
0833 
0834 void KHTMLPopupGUIClient::slotFrameInTop()
0835 {
0836     KParts::OpenUrlArguments args = d->m_khtml->arguments();
0837     args.metaData()["referrer"] = d->m_khtml->pageReferrer();
0838     KParts::BrowserArguments browserArgs(d->m_khtml->browserExtension()->browserArguments());
0839     browserArgs.frameName = "_top";
0840     emit d->m_khtml->browserExtension()->openUrlRequest(d->m_khtml->url(), args, browserArgs);
0841 }
0842 
0843 void KHTMLPopupGUIClient::slotFrameInTab()
0844 {
0845     KParts::OpenUrlArguments args = d->m_khtml->arguments();
0846     args.metaData()["referrer"] = d->m_khtml->pageReferrer();
0847     KParts::BrowserArguments browserArgs(d->m_khtml->browserExtension()->browserArguments());
0848     browserArgs.setNewTab(true);
0849     emit d->m_khtml->browserExtension()->createNewWindow(d->m_khtml->url(), args, browserArgs);
0850 }
0851 
0852 void KHTMLPopupGUIClient::saveURL(QWidget *parent, const QString &caption,
0853                                   const QUrl &url,
0854                                   const QMap<QString, QString> &metadata,
0855                                   const QString &filter, long cacheId,
0856                                   const QString &suggestedFilename)
0857 {
0858     QString name = QLatin1String("index.html");
0859     if (!suggestedFilename.isEmpty()) {
0860         name = suggestedFilename;
0861     } else if (!url.fileName().isEmpty()) {
0862         name = url.fileName();
0863     }
0864 
0865     QUrl destURL;
0866     int query;
0867     do {
0868         query = KMessageBox::PrimaryAction;
0869         // convert filename to URL using fromLocalFile to avoid trouble with ':' in filenames (#184202)
0870         destURL = QFileDialog::getSaveFileUrl(parent, caption, QUrl::fromLocalFile(name), filter);
0871         if (destURL.isLocalFile()) {
0872             QFileInfo info(destURL.toLocalFile());
0873             if (info.exists()) {
0874                 // TODO: use KIO::RenameDlg (shows more information)
0875                 query = KMessageBox::warningContinueCancel(parent, i18n("A file named \"%1\" already exists. " "Are you sure you want to overwrite it?",  info.fileName()), i18n("Overwrite File?"), KStandardGuiItem::overwrite());
0876             }
0877         }
0878     } while (query == KMessageBox::Cancel);
0879 
0880     if (destURL.isValid()) {
0881         saveURL(parent, url, destURL, metadata, cacheId);
0882     }
0883 }
0884 
0885 void KHTMLPopupGUIClient::saveURL(QWidget *parent, const QUrl &url, const QUrl &destURL,
0886                                   const QMap<QString, QString> &metadata,
0887                                   long cacheId)
0888 {
0889     if (destURL.isValid()) {
0890         bool saved = false;
0891         if (KHTMLPageCache::self()->isComplete(cacheId)) {
0892             if (destURL.isLocalFile()) {
0893                 QSaveFile destFile(destURL.toLocalFile());
0894                 if (destFile.open(QIODevice::WriteOnly)) {
0895                     QDataStream stream(&destFile);
0896                     KHTMLPageCache::self()->saveData(cacheId, &stream);
0897                     destFile.commit();
0898                     saved = true;
0899                 }
0900             } else {
0901                 // save to temp file, then move to final destination.
0902                 QTemporaryFile destFile;
0903                 if (destFile.open()) {
0904                     QDataStream stream(&destFile);
0905                     KHTMLPageCache::self()->saveData(cacheId, &stream);
0906                     QUrl url2 = QUrl();
0907                     url2.setPath(destFile.fileName());
0908                     KIO::file_move(url2, destURL, -1, KIO::Overwrite);
0909                     saved = true;
0910                 }
0911             }
0912         }
0913         if (!saved) {
0914             // DownloadManager <-> konqueror integration
0915             // find if the integration is enabled
0916             // the empty key  means no integration
0917             // only use download manager for non-local urls!
0918             bool downloadViaKIO = true;
0919             if (!url.isLocalFile()) {
0920                 KConfigGroup cfg = KSharedConfig::openConfig("konquerorrc", KConfig::NoGlobals)->group("HTML Settings");
0921                 QString downloadManger = cfg.readPathEntry("DownloadManager", QString());
0922                 if (!downloadManger.isEmpty()) {
0923                     // then find the download manager location
0924                     // qCDebug(KHTML_LOG) << "Using: "<<downloadManger <<" as Download Manager";
0925                     QString cmd = QStandardPaths::findExecutable(downloadManger);
0926                     if (cmd.isEmpty()) {
0927                         QString errMsg = i18n("The Download Manager (%1) could not be found in your $PATH ", downloadManger);
0928                         QString errMsgEx = i18n("Try to reinstall it  \n\nThe integration with Konqueror will be disabled.");
0929                         KMessageBox::detailedError(nullptr, errMsg, errMsgEx);
0930                         cfg.writePathEntry("DownloadManager", QString());
0931                         cfg.sync();
0932                     } else {
0933                         downloadViaKIO = false;
0934                         QUrl cleanDest = destURL;
0935                         cleanDest.setPassword(QString());   // don't put password into commandline
0936                         cmd += ' ' + KShell::quoteArg(url.url()) + ' ' +
0937                                KShell::quoteArg(cleanDest.url());
0938                         // qCDebug(KHTML_LOG) << "Calling command  "<<cmd;
0939                         KRun::runCommand(cmd, parent->topLevelWidget());
0940                     }
0941                 }
0942             }
0943 
0944             if (downloadViaKIO) {
0945                 KParts::BrowserRun::saveUrlUsingKIO(url, destURL, parent, metadata);
0946             }
0947         } //end if(!saved)
0948     }
0949 }
0950 
0951 KHTMLPartBrowserHostExtension::KHTMLPartBrowserHostExtension(KHTMLPart *part)
0952     : KParts::BrowserHostExtension(part)
0953 {
0954     m_part = part;
0955 }
0956 
0957 KHTMLPartBrowserHostExtension::~KHTMLPartBrowserHostExtension()
0958 {
0959 }
0960 
0961 QStringList KHTMLPartBrowserHostExtension::frameNames() const
0962 {
0963     return m_part->frameNames();
0964 }
0965 
0966 const QList<KParts::ReadOnlyPart *> KHTMLPartBrowserHostExtension::frames() const
0967 {
0968     return m_part->frames();
0969 }
0970 
0971 bool KHTMLPartBrowserHostExtension::openUrlInFrame(const QUrl &url, const KParts::OpenUrlArguments &arguments, const KParts::BrowserArguments &browserArguments)
0972 {
0973     return m_part->openUrlInFrame(url, arguments, browserArguments);
0974 }
0975 
0976 KParts::BrowserHostExtension *KHTMLPartBrowserHostExtension::findFrameParent(KParts::ReadOnlyPart
0977         *callingPart, const QString &frame)
0978 {
0979     KHTMLPart *parentPart = m_part->d->findFrameParent(callingPart, frame, nullptr, true /* navigation*/);
0980     if (parentPart) {
0981         return parentPart->browserHostExtension();
0982     }
0983     return nullptr;
0984 }
0985 
0986 // defined in khtml_part.cpp
0987 extern const int KHTML_NO_EXPORT fastZoomSizes[];
0988 extern const int KHTML_NO_EXPORT fastZoomSizeCount;
0989 
0990 KHTMLZoomFactorAction::KHTMLZoomFactorAction(KHTMLPart *part, bool direction, const QString &icon, const QString &text, QObject *parent)
0991     : KSelectAction(text, parent)
0992 {
0993     setIcon(QIcon::fromTheme(icon));
0994 
0995     setToolBarMode(MenuMode);
0996     setToolButtonPopupMode(QToolButton::DelayedPopup);
0997 
0998     init(part, direction);
0999 }
1000 
1001 void KHTMLZoomFactorAction::init(KHTMLPart *part, bool direction)
1002 {
1003     m_direction = direction;
1004     m_part = part;
1005 
1006     // xgettext: no-c-format
1007     addAction(i18n("Default Font Size (100%)"));
1008 
1009     int m = m_direction ? 1 : -1;
1010     int ofs = fastZoomSizeCount / 2;       // take index of 100%
1011 
1012     // this only works if there is an odd number of elements in fastZoomSizes[]
1013     for (int i = m; i != m * (ofs + 1); i += m) {
1014         int num = i * m;
1015         QString numStr = QString::number(num);
1016         if (num > 0) {
1017             numStr.prepend(QLatin1Char('+'));
1018         }
1019 
1020         // xgettext: no-c-format
1021         addAction(i18n("%1%",  fastZoomSizes[ofs + i]));
1022     }
1023 
1024     connect(selectableActionGroup(), SIGNAL(triggered(QAction*)), this, SLOT(slotTriggered(QAction*)));
1025 }
1026 
1027 KHTMLZoomFactorAction::~KHTMLZoomFactorAction()
1028 {
1029 }
1030 
1031 void KHTMLZoomFactorAction::slotTriggered(QAction *action)
1032 {
1033     int idx = selectableActionGroup()->actions().indexOf(action);
1034 
1035     if (idx == 0) {
1036         m_part->setFontScaleFactor(100);
1037     } else {
1038         m_part->setFontScaleFactor(fastZoomSizes[fastZoomSizeCount / 2 + (m_direction ? 1 : -1)*idx]);
1039     }
1040     setCurrentAction(nullptr);
1041 }
1042 
1043 KHTMLTextExtension::KHTMLTextExtension(KHTMLPart *part)
1044     : KParts::TextExtension(part)
1045 {
1046     connect(part, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));
1047 }
1048 
1049 KHTMLPart *KHTMLTextExtension::part() const
1050 {
1051     return static_cast<KHTMLPart *>(parent());
1052 }
1053 
1054 bool KHTMLTextExtension::hasSelection() const
1055 {
1056     return part()->hasSelection();
1057 }
1058 
1059 QString KHTMLTextExtension::selectedText(Format format) const
1060 {
1061     switch (format) {
1062     case PlainText:
1063         return part()->selectedText();
1064     case HTML:
1065         return part()->selectedTextAsHTML();
1066     }
1067     return QString();
1068 }
1069 
1070 QString KHTMLTextExtension::completeText(Format format) const
1071 {
1072     switch (format) {
1073     case PlainText:
1074         return part()->htmlDocument().body().innerText().string();
1075     case HTML:
1076         return part()->htmlDocument().body().innerHTML().string();
1077     }
1078     return QString();
1079 }
1080 
1081 ////
1082 
1083 KHTMLHtmlExtension::KHTMLHtmlExtension(KHTMLPart *part)
1084     : KParts::HtmlExtension(part)
1085 {
1086 }
1087 
1088 QUrl KHTMLHtmlExtension::baseUrl() const
1089 {
1090     return part()->baseURL();
1091 }
1092 
1093 bool KHTMLHtmlExtension::hasSelection() const
1094 {
1095     return part()->hasSelection();
1096 }
1097 
1098 KParts::SelectorInterface::QueryMethods KHTMLHtmlExtension::supportedQueryMethods() const
1099 {
1100     return (KParts::SelectorInterface::SelectedContent | KParts::SelectorInterface::EntireContent);
1101 }
1102 
1103 static KParts::SelectorInterface::Element convertDomElement(const DOM::ElementImpl *domElem)
1104 {
1105     KParts::SelectorInterface::Element elem;
1106     elem.setTagName(domElem->tagName().string());
1107     const DOM::NamedAttrMapImpl *attrMap = domElem->attributes(true /*readonly*/);
1108     if (attrMap) {
1109         for (unsigned i = 0; i < attrMap->length(); ++i) {
1110             const DOM::AttributeImpl &attr = attrMap->attributeAt(i);
1111             elem.setAttribute(attr.localName().string(), attr.value().string());
1112             // we could have a setAttributeNS too.
1113         }
1114     }
1115     return elem;
1116 }
1117 
1118 KParts::SelectorInterface::Element KHTMLHtmlExtension::querySelector(const QString &query, KParts::SelectorInterface::QueryMethod method) const
1119 {
1120     KParts::SelectorInterface::Element element;
1121 
1122     // If the specified method is None, return an empty list; similarly
1123     // if the document is null, which may be possible in case of an error
1124     if (method == KParts::SelectorInterface::None || part()->document().isNull()) {
1125         return element;
1126     }
1127 
1128     if (!(supportedQueryMethods() & method)) {
1129         return element;
1130     }
1131 
1132     switch (method) {
1133     case KParts::SelectorInterface::EntireContent: {
1134         int ec = 0; // exceptions are ignored
1135         WTF::RefPtr<DOM::ElementImpl> domElem = part()->document().handle()->querySelector(query, ec);
1136         element = convertDomElement(domElem.get());
1137         break;
1138     }
1139     case KParts::SelectorInterface::SelectedContent:
1140         if (part()->hasSelection()) {
1141             DOM::Element domElem = part()->selection().cloneContents().querySelector(query);
1142             element = convertDomElement(static_cast<DOM::ElementImpl *>(domElem.handle()));
1143         }
1144         break;
1145     default:
1146         break;
1147     }
1148 
1149     return element;
1150 }
1151 
1152 QList<KParts::SelectorInterface::Element> KHTMLHtmlExtension::querySelectorAll(const QString &query, KParts::SelectorInterface::QueryMethod method) const
1153 {
1154     QList<KParts::SelectorInterface::Element> elements;
1155 
1156     // If the specified method is None, return an empty list; similarly
1157     // if the document is null, which may be possible in case of an error
1158     if (method == KParts::SelectorInterface::None || part()->document().isNull()) {
1159         return elements;
1160     }
1161 
1162     // If the specified method is not supported, return an empty list...
1163     if (!(supportedQueryMethods() & method)) {
1164         return elements;
1165     }
1166 
1167     switch (method) {
1168     case KParts::SelectorInterface::EntireContent: {
1169         int ec = 0; // exceptions are ignored
1170         WTF::RefPtr<DOM::NodeListImpl> nodes = part()->document().handle()->querySelectorAll(query, ec);
1171         const unsigned long len = nodes->length();
1172         elements.reserve(len);
1173         for (unsigned long i = 0; i < len; ++i) {
1174             DOM::NodeImpl *node = nodes->item(i);
1175             if (node->isElementNode()) { // should be always true
1176                 elements.append(convertDomElement(static_cast<DOM::ElementImpl *>(node)));
1177             }
1178         }
1179         break;
1180     }
1181     case KParts::SelectorInterface::SelectedContent:
1182         if (part()->hasSelection()) {
1183             DOM::NodeList nodes = part()->selection().cloneContents().querySelectorAll(query);
1184             const unsigned long len = nodes.length();
1185             for (unsigned long i = 0; i < len; ++i) {
1186                 DOM::NodeImpl *node = nodes.item(i).handle();
1187                 if (node->isElementNode()) {
1188                     elements.append(convertDomElement(static_cast<DOM::ElementImpl *>(node)));
1189                 }
1190             }
1191         }
1192         break;
1193     default:
1194         break;
1195     }
1196 
1197     return elements;
1198 }
1199 
1200 QVariant KHTMLHtmlExtension::htmlSettingsProperty(HtmlSettingsInterface::HtmlSettingsType type) const
1201 {
1202     if (part()) {
1203         switch (type) {
1204         case KParts::HtmlSettingsInterface::AutoLoadImages:
1205             return part()->autoloadImages();
1206         case KParts::HtmlSettingsInterface::DnsPrefetchEnabled:
1207             return (part()->dnsPrefetch() == KHTMLPart::DNSPrefetchEnabled);
1208         case KParts::HtmlSettingsInterface::JavaEnabled:
1209             return part()->javaEnabled();
1210         case KParts::HtmlSettingsInterface::JavascriptEnabled:
1211             return part()->jScriptEnabled();
1212         case KParts::HtmlSettingsInterface::MetaRefreshEnabled:
1213             return part()->metaRefreshEnabled();
1214         case KParts::HtmlSettingsInterface::PluginsEnabled:
1215             return part()->pluginsEnabled();
1216         default:
1217             break;
1218         }
1219     }
1220     return QVariant();
1221 }
1222 
1223 bool KHTMLHtmlExtension::setHtmlSettingsProperty(HtmlSettingsInterface::HtmlSettingsType type, const QVariant &value)
1224 {
1225     KHTMLPart *p = part();
1226 
1227     if (p) {
1228         switch (type) {
1229         case KParts::HtmlSettingsInterface::AutoLoadImages:
1230             p->setAutoloadImages(value.toBool());
1231             return true;
1232         case KParts::HtmlSettingsInterface::DnsPrefetchEnabled:
1233             p->setDNSPrefetch((value.toBool() ? KHTMLPart::DNSPrefetchEnabled : KHTMLPart::DNSPrefetchDisabled));
1234             return true;
1235         case KParts::HtmlSettingsInterface::JavaEnabled:
1236             p->setJavaEnabled(value.toBool());
1237             return true;
1238         case KParts::HtmlSettingsInterface::JavascriptEnabled:
1239             p->setJScriptEnabled(value.toBool());
1240             return true;
1241         case KParts::HtmlSettingsInterface::MetaRefreshEnabled:
1242             p->setMetaRefreshEnabled(value.toBool());
1243             return true;
1244         case KParts::HtmlSettingsInterface::PluginsEnabled:
1245             p->setPluginsEnabled(value.toBool());
1246             return true;
1247         case KParts::HtmlSettingsInterface::UserDefinedStyleSheetURL: {
1248             const QUrl url(value.toUrl());
1249             if (url.scheme() == QLatin1String("data")) {
1250                 const QByteArray data(url.path(QUrl::FullyEncoded).toLatin1());
1251                 if (!data.isEmpty()) {
1252                     const int index = data.indexOf(',');
1253                     const QByteArray decodedData((index > -1 ? QByteArray::fromBase64(data.mid(index)) : QByteArray()));
1254                     p->setUserStyleSheet(QString::fromUtf8(decodedData.constData(), decodedData.size()));
1255                 }
1256             } else {
1257                 p->setUserStyleSheet(url);
1258             }
1259             return true;
1260         }
1261         default:
1262             break; // Unsupported property...
1263         }
1264     }
1265 
1266     return false;
1267 }
1268 
1269 KHTMLPart *KHTMLHtmlExtension::part() const
1270 {
1271     return static_cast<KHTMLPart *>(parent());
1272 }
1273 
1274 #include "moc_khtml_ext.cpp"