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 <QClipboard>
41 #include <QFileInfo>
42 #include <QFileDialog>
43 #include <QMenu>
44 #include <QUrl>
45 #include <QMetaEnum>
46 #include <QMimeData>
47 #include <qstandardpaths.h>
48 #include <qinputdialog.h>
49 #include <assert.h>
50
51 #include <kconfiggroup.h>
52 #include <ksharedconfig.h>
53 #include "khtml_debug.h"
54 #include <klocalizedstring.h>
55 #include <kjobuidelegate.h>
56 #include <kio/job.h>
57 #include <kshell.h>
58 #include <qsavefile.h>
59 #include <kstringhandler.h>
60 #include <ktoolinvocation.h>
61 #include <kmessagebox.h>
62 #include <krun.h>
63 #include <kurifilter.h>
64 #include <kdesktopfile.h>
65 #include <qtemporaryfile.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
KHTMLPartBrowserExtension(KHTMLPart * parent)73 KHTMLPartBrowserExtension::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
xOffset()86 int KHTMLPartBrowserExtension::xOffset()
87 {
88 return m_part->view()->contentsX();
89 }
90
yOffset()91 int KHTMLPartBrowserExtension::yOffset()
92 {
93 return m_part->view()->contentsY();
94 }
95
saveState(QDataStream & stream)96 void KHTMLPartBrowserExtension::saveState(QDataStream &stream)
97 {
98 //qCDebug(KHTML_LOG) << "saveState!";
99 m_part->saveState(stream);
100 }
101
restoreState(QDataStream & stream)102 void KHTMLPartBrowserExtension::restoreState(QDataStream &stream)
103 {
104 //qCDebug(KHTML_LOG) << "restoreState!";
105 m_part->restoreState(stream);
106 }
107
editableWidgetFocused(QWidget * widget)108 void KHTMLPartBrowserExtension::editableWidgetFocused(QWidget *widget)
109 {
110 m_editableFormWidget = widget;
111 updateEditActions();
112
113 if (!m_connectedToClipboard && m_editableFormWidget) {
114 connect(QApplication::clipboard(), SIGNAL(dataChanged()),
115 this, SLOT(updateEditActions()));
116
117 if (m_editableFormWidget->inherits("QLineEdit") || m_editableFormWidget->inherits("QTextEdit"))
118 connect(m_editableFormWidget, SIGNAL(selectionChanged()),
119 this, SLOT(updateEditActions()));
120
121 m_connectedToClipboard = true;
122 }
123 editableWidgetFocused();
124 }
125
editableWidgetBlurred(QWidget *)126 void KHTMLPartBrowserExtension::editableWidgetBlurred(QWidget * /*widget*/)
127 {
128 QWidget *oldWidget = m_editableFormWidget;
129
130 m_editableFormWidget = nullptr;
131 enableAction("cut", false);
132 enableAction("paste", false);
133 m_part->emitSelectionChanged();
134
135 if (m_connectedToClipboard) {
136 disconnect(QApplication::clipboard(), SIGNAL(dataChanged()),
137 this, SLOT(updateEditActions()));
138
139 if (oldWidget) {
140 if (oldWidget->inherits("QLineEdit") || oldWidget->inherits("QTextEdit"))
141 disconnect(oldWidget, SIGNAL(selectionChanged()),
142 this, SLOT(updateEditActions()));
143 }
144
145 m_connectedToClipboard = false;
146 }
147 editableWidgetBlurred();
148 }
149
setExtensionProxy(KParts::BrowserExtension * proxy)150 void KHTMLPartBrowserExtension::setExtensionProxy(KParts::BrowserExtension *proxy)
151 {
152 if (m_extensionProxy) {
153 disconnect(m_extensionProxy, SIGNAL(enableAction(const char*,bool)),
154 this, SLOT(extensionProxyActionEnabled(const char*,bool)));
155 if (m_extensionProxy->inherits("KHTMLPartBrowserExtension")) {
156 disconnect(m_extensionProxy, SIGNAL(editableWidgetFocused()),
157 this, SLOT(extensionProxyEditableWidgetFocused()));
158 disconnect(m_extensionProxy, SIGNAL(editableWidgetBlurred()),
159 this, SLOT(extensionProxyEditableWidgetBlurred()));
160 }
161 }
162
163 m_extensionProxy = proxy;
164
165 if (m_extensionProxy) {
166 connect(m_extensionProxy, SIGNAL(enableAction(const char*,bool)),
167 this, SLOT(extensionProxyActionEnabled(const char*,bool)));
168 if (m_extensionProxy->inherits("KHTMLPartBrowserExtension")) {
169 connect(m_extensionProxy, SIGNAL(editableWidgetFocused()),
170 this, SLOT(extensionProxyEditableWidgetFocused()));
171 connect(m_extensionProxy, SIGNAL(editableWidgetBlurred()),
172 this, SLOT(extensionProxyEditableWidgetBlurred()));
173 }
174
175 enableAction("cut", m_extensionProxy->isActionEnabled("cut"));
176 enableAction("copy", m_extensionProxy->isActionEnabled("copy"));
177 enableAction("paste", m_extensionProxy->isActionEnabled("paste"));
178 } else {
179 updateEditActions();
180 enableAction("copy", false); // ### re-check this
181 }
182 }
183
cut()184 void KHTMLPartBrowserExtension::cut()
185 {
186 if (m_extensionProxy) {
187 callExtensionProxyMethod("cut");
188 return;
189 }
190
191 if (!m_editableFormWidget) {
192 return;
193 }
194
195 QLineEdit *lineEdit = qobject_cast<QLineEdit *>(m_editableFormWidget);
196 if (lineEdit && !lineEdit->isReadOnly()) {
197 lineEdit->cut();
198 }
199 QTextEdit *textEdit = qobject_cast<QTextEdit *>(m_editableFormWidget);
200 if (textEdit && !textEdit->isReadOnly()) {
201 textEdit->cut();
202 }
203 }
204
copy()205 void KHTMLPartBrowserExtension::copy()
206 {
207 if (m_extensionProxy) {
208 callExtensionProxyMethod("copy");
209 return;
210 }
211
212 if (!m_editableFormWidget) {
213 // get selected text and paste to the clipboard
214 QString text = m_part->selectedText();
215 text.replace(QChar(0xa0), ' ');
216 //qCDebug(KHTML_LOG) << text;
217
218 QClipboard *cb = QApplication::clipboard();
219 disconnect(cb, SIGNAL(selectionChanged()), m_part, SLOT(slotClearSelection()));
220 #ifndef QT_NO_MIMECLIPBOARD
221 QString htmltext;
222 /*
223 * When selectionModeEnabled, that means the user has just selected
224 * the text, not ctrl+c to copy it. The selection clipboard
225 * doesn't seem to support mime type, so to save time, don't calculate
226 * the selected text as html.
227 * optomisation disabled for now until everything else works.
228 */
229 //if(!cb->selectionModeEnabled())
230 htmltext = m_part->selectedTextAsHTML();
231 QMimeData *mimeData = new QMimeData;
232 mimeData->setText(text);
233 if (!htmltext.isEmpty()) {
234 htmltext.replace(QChar(0xa0), ' ');
235 mimeData->setHtml(htmltext);
236 }
237 cb->setMimeData(mimeData);
238 #else
239 cb->setText(text);
240 #endif
241
242 connect(cb, SIGNAL(selectionChanged()), m_part, SLOT(slotClearSelection()));
243 } else {
244 QLineEdit *lineEdit = qobject_cast<QLineEdit *>(m_editableFormWidget);
245 if (lineEdit) {
246 lineEdit->copy();
247 }
248 QTextEdit *textEdit = qobject_cast<QTextEdit *>(m_editableFormWidget);
249 if (textEdit) {
250 textEdit->copy();
251 }
252 }
253 }
254
searchProvider()255 void KHTMLPartBrowserExtension::searchProvider()
256 {
257 QAction *action = qobject_cast<QAction *>(sender());
258 if (action) {
259 QUrl url = action->data().toUrl();
260 if (url.host().isEmpty()) {
261 KUriFilterData data(action->data().toString());
262 if (KUriFilter::self()->filterSearchUri(data, KUriFilter::WebShortcutFilter)) {
263 url = data.uri();
264 }
265 }
266
267 KParts::BrowserArguments browserArgs;
268 browserArgs.frameName = "_blank";
269 emit m_part->browserExtension()->openUrlRequest(url, KParts::OpenUrlArguments(), browserArgs);
270 }
271 }
272
paste()273 void KHTMLPartBrowserExtension::paste()
274 {
275 if (m_extensionProxy) {
276 callExtensionProxyMethod("paste");
277 return;
278 }
279
280 if (!m_editableFormWidget) {
281 return;
282 }
283
284 QLineEdit *lineEdit = qobject_cast<QLineEdit *>(m_editableFormWidget);
285 if (lineEdit && !lineEdit->isReadOnly()) {
286 lineEdit->paste();
287 }
288 QTextEdit *textEdit = qobject_cast<QTextEdit *>(m_editableFormWidget);
289 if (textEdit && !textEdit->isReadOnly()) {
290 textEdit->paste();
291 }
292 }
293
callExtensionProxyMethod(const char * method)294 void KHTMLPartBrowserExtension::callExtensionProxyMethod(const char *method)
295 {
296 if (!m_extensionProxy) {
297 return;
298 }
299
300 QMetaObject::invokeMethod(m_extensionProxy, method, Qt::DirectConnection);
301 }
302
updateEditActions()303 void KHTMLPartBrowserExtension::updateEditActions()
304 {
305 if (!m_editableFormWidget) {
306 enableAction("cut", false);
307 enableAction("copy", false);
308 enableAction("paste", false);
309 return;
310 }
311
312 // ### duplicated from KonqMainWindow::slotClipboardDataChanged
313 #ifndef QT_NO_MIMECLIPBOARD // Handle minimalized versions of Qt Embedded
314 const QMimeData *data = QApplication::clipboard()->mimeData();
315 enableAction("paste", data->hasText());
316 #else
317 QString data = QApplication::clipboard()->text();
318 enableAction("paste", data.contains("://"));
319 #endif
320 bool hasSelection = false;
321
322 if (m_editableFormWidget) {
323 if (qobject_cast<QLineEdit *>(m_editableFormWidget)) {
324 hasSelection = static_cast<QLineEdit *>(&(*m_editableFormWidget))->hasSelectedText();
325 } else if (qobject_cast<QTextEdit *>(m_editableFormWidget)) {
326 hasSelection = static_cast<QTextEdit *>(&(*m_editableFormWidget))->textCursor().hasSelection();
327 }
328 }
329
330 enableAction("copy", hasSelection);
331 enableAction("cut", hasSelection);
332 }
333
extensionProxyEditableWidgetFocused()334 void KHTMLPartBrowserExtension::extensionProxyEditableWidgetFocused()
335 {
336 editableWidgetFocused();
337 }
338
extensionProxyEditableWidgetBlurred()339 void KHTMLPartBrowserExtension::extensionProxyEditableWidgetBlurred()
340 {
341 editableWidgetBlurred();
342 }
343
extensionProxyActionEnabled(const char * action,bool enable)344 void KHTMLPartBrowserExtension::extensionProxyActionEnabled(const char *action, bool enable)
345 {
346 // only forward enableAction calls for actions we actually do forward
347 if (strcmp(action, "cut") == 0 ||
348 strcmp(action, "copy") == 0 ||
349 strcmp(action, "paste") == 0) {
350 enableAction(action, enable);
351 }
352 }
353
reparseConfiguration()354 void KHTMLPartBrowserExtension::reparseConfiguration()
355 {
356 m_part->reparseConfiguration();
357 }
358
print()359 void KHTMLPartBrowserExtension::print()
360 {
361 m_part->view()->print();
362 }
363
disableScrolling()364 void KHTMLPartBrowserExtension::disableScrolling()
365 {
366 QScrollArea *scrollArea = m_part->view();
367 if (scrollArea) {
368 scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
369 scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
370 }
371 }
372
373 class KHTMLPopupGUIClient::KHTMLPopupGUIClientPrivate
374 {
375 public:
376 KHTMLPart *m_khtml;
377 QUrl m_url;
378 QUrl m_imageURL;
379 QPixmap m_pixmap;
380 QString m_suggestedFilename;
381 KActionCollection *m_actionCollection;
382 KParts::BrowserExtension::ActionGroupMap actionGroups;
383 };
384
KHTMLPopupGUIClient(KHTMLPart * khtml,const QUrl & url)385 KHTMLPopupGUIClient::KHTMLPopupGUIClient(KHTMLPart *khtml, const QUrl &url)
386 : QObject(khtml), d(new KHTMLPopupGUIClientPrivate)
387 {
388 d->m_khtml = khtml;
389 d->m_url = url;
390 d->m_actionCollection = new KActionCollection(this);
391 bool isImage = false;
392 bool hasSelection = khtml->hasSelection();
393
394 DOM::Element e = khtml->nodeUnderMouse();
395
396 if (!e.isNull() && (e.elementId() == ID_IMG ||
397 (e.elementId() == ID_INPUT && !static_cast<DOM::HTMLInputElement>(e).src().isEmpty()))) {
398 if (e.elementId() == ID_IMG) {
399 DOM::HTMLImageElementImpl *ie = static_cast<DOM::HTMLImageElementImpl *>(e.handle());
400 khtml::RenderImage *ri = dynamic_cast<khtml::RenderImage *>(ie->renderer());
401 if (ri && ri->contentObject()) {
402 d->m_suggestedFilename = static_cast<khtml::CachedImage *>(ri->contentObject())->suggestedFilename();
403 }
404 }
405 isImage = true;
406 }
407
408 if (hasSelection) {
409 QList<QAction *> editActions;
410 QAction *copyAction = d->m_actionCollection->addAction(KStandardAction::Copy, "copy",
411 d->m_khtml->browserExtension(), SLOT(copy()));
412
413 copyAction->setText(i18n("&Copy Text"));
414 copyAction->setEnabled(d->m_khtml->browserExtension()->isActionEnabled("copy"));
415 editActions.append(copyAction);
416
417 editActions.append(khtml->actionCollection()->action("selectAll"));
418
419 addSearchActions(editActions);
420
421 QString selectedTextURL = selectedTextAsOneLine(d->m_khtml);
422 if (selectedTextURL.contains("://") && QUrl(selectedTextURL).isValid()) {
423 if (selectedTextURL.length() > 18) {
424 selectedTextURL.truncate(15);
425 selectedTextURL += "...";
426 }
427 QAction *action = new QAction(i18n("Open '%1'", selectedTextURL), this);
428 d->m_actionCollection->addAction("openSelection", action);
429 action->setIcon(QIcon::fromTheme("window-new"));
430 connect(action, SIGNAL(triggered(bool)), this, SLOT(openSelection()));
431 editActions.append(action);
432 }
433
434 QAction *separator = new QAction(d->m_actionCollection);
435 separator->setSeparator(true);
436 editActions.append(separator);
437
438 d->actionGroups.insert("editactions", editActions);
439 }
440
441 if (!url.isEmpty()) {
442 QList<QAction *> linkActions;
443 if (url.scheme() == "mailto") {
444 QAction *action = new QAction(i18n("&Copy Email Address"), this);
445 d->m_actionCollection->addAction("copylinklocation", action);
446 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotCopyLinkLocation()));
447 linkActions.append(action);
448 } else {
449 QAction *action = new QAction(i18n("&Save Link As..."), this);
450 d->m_actionCollection->addAction("savelinkas", action);
451 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotSaveLinkAs()));
452 linkActions.append(action);
453
454 action = new QAction(i18n("&Copy Link Address"), this);
455 d->m_actionCollection->addAction("copylinklocation", action);
456 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotCopyLinkLocation()));
457 linkActions.append(action);
458 }
459 d->actionGroups.insert("linkactions", linkActions);
460 }
461
462 QList<QAction *> partActions;
463 // frameset? -> add "Reload Frame" etc.
464 if (!hasSelection) {
465 if (khtml->parentPart()) {
466 KActionMenu *menu = new KActionMenu(i18nc("@title:menu HTML frame/iframe", "Frame"), this);
467 QAction *action = new QAction(i18n("Open in New &Window"), this);
468 d->m_actionCollection->addAction("frameinwindow", action);
469 action->setIcon(QIcon::fromTheme("window-new"));
470 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotFrameInWindow()));
471 menu->addAction(action);
472
473 action = new QAction(i18n("Open in &This Window"), this);
474 d->m_actionCollection->addAction("frameintop", action);
475 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotFrameInTop()));
476 menu->addAction(action);
477
478 action = new QAction(i18n("Open in &New Tab"), this);
479 d->m_actionCollection->addAction("frameintab", action);
480 action->setIcon(QIcon::fromTheme("tab-new"));
481 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotFrameInTab()));
482 menu->addAction(action);
483
484 action = new QAction(d->m_actionCollection);
485 action->setSeparator(true);
486 menu->addAction(action);
487
488 action = new QAction(i18n("Reload Frame"), this);
489 d->m_actionCollection->addAction("reloadframe", action);
490 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotReloadFrame()));
491 menu->addAction(action);
492
493 action = new QAction(i18n("Print Frame..."), this);
494 d->m_actionCollection->addAction("printFrame", action);
495 action->setIcon(QIcon::fromTheme("document-print-frame"));
496 connect(action, SIGNAL(triggered(bool)), d->m_khtml->browserExtension(), SLOT(print()));
497 menu->addAction(action);
498
499 action = new QAction(i18n("Save &Frame As..."), this);
500 d->m_actionCollection->addAction("saveFrame", action);
501 connect(action, SIGNAL(triggered(bool)), d->m_khtml, SLOT(slotSaveFrame()));
502 menu->addAction(action);
503
504 action = new QAction(i18n("View Frame Source"), this);
505 d->m_actionCollection->addAction("viewFrameSource", action);
506 connect(action, SIGNAL(triggered(bool)), d->m_khtml, SLOT(slotViewDocumentSource()));
507 menu->addAction(action);
508
509 action = new QAction(i18n("View Frame Information"), this);
510 d->m_actionCollection->addAction("viewFrameInfo", action);
511 connect(action, SIGNAL(triggered(bool)), d->m_khtml, SLOT(slotViewPageInfo()));
512
513 action = new QAction(d->m_actionCollection);
514 action->setSeparator(true);
515 menu->addAction(action);
516
517 if (KHTMLGlobal::defaultHTMLSettings()->isAdFilterEnabled()) {
518 if (khtml->d->m_frame->m_type == khtml::ChildFrame::IFrame) {
519 action = new QAction(i18n("Block IFrame..."), this);
520 d->m_actionCollection->addAction("blockiframe", action);
521 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotBlockIFrame()));
522 menu->addAction(action);
523 }
524 }
525
526 partActions.append(menu);
527 }
528 }
529
530 if (isImage) {
531 if (e.elementId() == ID_IMG) {
532 d->m_imageURL = QUrl(static_cast<DOM::HTMLImageElement>(e).src().string());
533 DOM::HTMLImageElementImpl *imageimpl = static_cast<DOM::HTMLImageElementImpl *>(e.handle());
534 Q_ASSERT(imageimpl);
535 if (imageimpl) { // should be true always. right?
536 if (imageimpl->complete()) {
537 d->m_pixmap = imageimpl->currentPixmap();
538 }
539 }
540 } else {
541 d->m_imageURL = QUrl(static_cast<DOM::HTMLInputElement>(e).src().string());
542 }
543 QAction *action = new QAction(i18n("Save Image As..."), this);
544 d->m_actionCollection->addAction("saveimageas", action);
545 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotSaveImageAs()));
546 partActions.append(action);
547
548 action = new QAction(i18n("Send Image..."), this);
549 d->m_actionCollection->addAction("sendimage", action);
550 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotSendImage()));
551 partActions.append(action);
552
553 #ifndef QT_NO_MIMECLIPBOARD
554 action = new QAction(i18n("Copy Image"), this);
555 d->m_actionCollection->addAction("copyimage", action);
556 action->setEnabled(!d->m_pixmap.isNull());
557 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotCopyImage()));
558 partActions.append(action);
559 #endif
560
561 if (d->m_pixmap.isNull()) { //fallback to image location if still loading the image. this will always be true if ifdef QT_NO_MIMECLIPBOARD
562 action = new QAction(i18n("Copy Image Location"), this);
563 d->m_actionCollection->addAction("copyimagelocation", action);
564 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotCopyImageLocation()));
565 partActions.append(action);
566 }
567
568 QString actionText = d->m_suggestedFilename.isEmpty() ?
569 KStringHandler::csqueeze(d->m_imageURL.fileName() + d->m_imageURL.query(), 25)
570 : d->m_suggestedFilename;
571 action = new QAction(i18n("View Image (%1)", actionText.replace("&", "&&")), this);
572 d->m_actionCollection->addAction("viewimage", action);
573 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotViewImage()));
574 partActions.append(action);
575
576 if (KHTMLGlobal::defaultHTMLSettings()->isAdFilterEnabled()) {
577 action = new QAction(i18n("Block Image..."), this);
578 d->m_actionCollection->addAction("blockimage", action);
579 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotBlockImage()));
580 partActions.append(action);
581
582 if (!d->m_imageURL.host().isEmpty() &&
583 !d->m_imageURL.scheme().isEmpty()) {
584 action = new QAction(i18n("Block Images From %1", d->m_imageURL.host()), this);
585 d->m_actionCollection->addAction("blockhost", action);
586 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotBlockHost()));
587 partActions.append(action);
588 }
589 }
590 QAction *separator = new QAction(d->m_actionCollection);
591 separator->setSeparator(true);
592 partActions.append(separator);
593 }
594
595 if (isImage || url.isEmpty()) {
596 QAction *action = new QAction(i18n("Stop Animations"), this);
597 d->m_actionCollection->addAction("stopanimations", action);
598 connect(action, SIGNAL(triggered(bool)), this, SLOT(slotStopAnimations()));
599 partActions.append(action);
600 QAction *separator = new QAction(d->m_actionCollection);
601 separator->setSeparator(true);
602 partActions.append(separator);
603 }
604 if (!hasSelection && url.isEmpty()) { // only when right-clicking on the page itself
605 partActions.append(khtml->actionCollection()->action("viewDocumentSource"));
606 }
607 if (!hasSelection && url.isEmpty() && !isImage) {
608 partActions.append(khtml->actionCollection()->action("setEncoding"));
609 }
610 d->actionGroups.insert("partactions", partActions);
611 }
612
~KHTMLPopupGUIClient()613 KHTMLPopupGUIClient::~KHTMLPopupGUIClient()
614 {
615 delete d->m_actionCollection;
616 delete d;
617 }
618
addSearchActions(QList<QAction * > & editActions)619 void KHTMLPopupGUIClient::addSearchActions(QList<QAction *> &editActions)
620 {
621 QString selectedText = d->m_khtml->simplifiedSelectedText();
622 // replace linefeeds with spaces
623 selectedText = selectedText.replace(QChar(10), QChar(32)).trimmed();
624
625 if (selectedText.isEmpty()) {
626 return;
627 }
628
629 KUriFilterData data(selectedText);
630 QStringList alternateProviders;
631 alternateProviders << "google" << "google_groups" << "google_news" << "webster" << "dmoz" << "wikipedia";
632 data.setAlternateSearchProviders(alternateProviders);
633 data.setAlternateDefaultSearchProvider("google");
634
635 if (KUriFilter::self()->filterSearchUri(data, KUriFilter::NormalTextFilter)) {
636 const QString squeezedText = KStringHandler::rsqueeze(selectedText, 21);
637 QAction *action = new QAction(i18n("Search for '%1' with %2",
638 squeezedText, data.searchProvider()), this);
639 action->setData(QUrl(data.uri()));
640 action->setIcon(QIcon::fromTheme(data.iconName()));
641 connect(action, SIGNAL(triggered(bool)), d->m_khtml->browserExtension(), SLOT(searchProvider()));
642 d->m_actionCollection->addAction("defaultSearchProvider", action);
643 editActions.append(action);
644
645 const QStringList preferredSearchProviders = data.preferredSearchProviders();
646 if (!preferredSearchProviders.isEmpty()) {
647 KActionMenu *providerList = new KActionMenu(i18n("Search for '%1' with", squeezedText), this);
648 Q_FOREACH (const QString &searchProvider, preferredSearchProviders) {
649 if (searchProvider == data.searchProvider()) {
650 continue;
651 }
652 QAction *action = new QAction(searchProvider, this);
653 action->setData(data.queryForPreferredSearchProvider(searchProvider));
654 d->m_actionCollection->addAction(searchProvider, action);
655 action->setIcon(QIcon::fromTheme(data.iconNameForPreferredSearchProvider(searchProvider)));
656 connect(action, SIGNAL(triggered(bool)), d->m_khtml->browserExtension(), SLOT(searchProvider()));
657 providerList->addAction(action);
658 }
659 d->m_actionCollection->addAction("searchProviderList", providerList);
660 editActions.append(providerList);
661 }
662 }
663 }
664
selectedTextAsOneLine(KHTMLPart * part)665 QString KHTMLPopupGUIClient::selectedTextAsOneLine(KHTMLPart *part)
666 {
667 QString text = part->simplifiedSelectedText();
668 // in addition to what simplifiedSelectedText does,
669 // remove linefeeds and any whitespace surrounding it (#113177),
670 // to get it all in a single line.
671 text.remove(QRegExp("[\\s]*\\n+[\\s]*"));
672 return text;
673 }
674
openSelection()675 void KHTMLPopupGUIClient::openSelection()
676 {
677 KParts::BrowserArguments browserArgs;
678 browserArgs.frameName = "_blank";
679
680 QUrl url(selectedTextAsOneLine(d->m_khtml));
681 emit d->m_khtml->browserExtension()->openUrlRequest(url, KParts::OpenUrlArguments(), browserArgs);
682 }
683
actionGroups() const684 KParts::BrowserExtension::ActionGroupMap KHTMLPopupGUIClient::actionGroups() const
685 {
686 return d->actionGroups;
687 }
688
slotSaveLinkAs()689 void KHTMLPopupGUIClient::slotSaveLinkAs()
690 {
691 KIO::MetaData metaData;
692 metaData["referrer"] = d->m_khtml->referrer();
693 saveURL(d->m_khtml->widget(), i18n("Save Link As"), d->m_url, metaData);
694 }
695
slotSendImage()696 void KHTMLPopupGUIClient::slotSendImage()
697 {
698 QStringList urls;
699 urls.append(d->m_imageURL.url());
700 QString subject = d->m_imageURL.url();
701 KToolInvocation::invokeMailer(QString(), QString(), QString(), subject,
702 QString(), //body
703 QString(),
704 urls); // attachments
705
706 }
707
slotSaveImageAs()708 void KHTMLPopupGUIClient::slotSaveImageAs()
709 {
710 KIO::MetaData metaData;
711 metaData["referrer"] = d->m_khtml->referrer();
712 saveURL(d->m_khtml->widget(), i18n("Save Image As"), d->m_imageURL, metaData, QString(), 0, d->m_suggestedFilename);
713 }
714
slotBlockHost()715 void KHTMLPopupGUIClient::slotBlockHost()
716 {
717 QString name = d->m_imageURL.scheme() + "://" + d->m_imageURL.host() + "/*";
718 KHTMLGlobal::defaultHTMLSettings()->addAdFilter(name);
719 d->m_khtml->reparseConfiguration();
720 }
721
slotBlockImage()722 void KHTMLPopupGUIClient::slotBlockImage()
723 {
724 bool ok = false;
725
726 QString url = QInputDialog::getText(d->m_khtml->widget(), i18n("Add URL to Filter"),
727 i18n("Enter the URL:"), QLineEdit::Normal,
728 d->m_imageURL.url(), &ok);
729 if (ok) {
730 KHTMLGlobal::defaultHTMLSettings()->addAdFilter(url);
731 d->m_khtml->reparseConfiguration();
732 }
733 }
734
slotBlockIFrame()735 void KHTMLPopupGUIClient::slotBlockIFrame()
736 {
737 bool ok = false;
738 QString url = QInputDialog::getText(d->m_khtml->widget(), i18n("Add URL to Filter"),
739 i18n("Enter the URL:"), QLineEdit::Normal,
740 d->m_khtml->url().toString(), &ok);
741 if (ok) {
742 KHTMLGlobal::defaultHTMLSettings()->addAdFilter(url);
743 d->m_khtml->reparseConfiguration();
744 }
745 }
746
slotCopyLinkLocation()747 void KHTMLPopupGUIClient::slotCopyLinkLocation()
748 {
749 QUrl safeURL(d->m_url);
750 safeURL.setPassword(QString());
751 #ifndef QT_NO_MIMECLIPBOARD
752 // Set it in both the mouse selection and in the clipboard
753 QMimeData *mimeData = new QMimeData;
754 mimeData->setUrls(QList<QUrl>() << safeURL);
755 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
756
757 mimeData = new QMimeData;
758 mimeData->setUrls(QList<QUrl>() << safeURL);
759 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection);
760
761 #else
762 QApplication::clipboard()->setText(safeURL.url()); //FIXME(E): Handle multiple entries
763 #endif
764 }
765
slotStopAnimations()766 void KHTMLPopupGUIClient::slotStopAnimations()
767 {
768 d->m_khtml->stopAnimations();
769 }
770
slotCopyImage()771 void KHTMLPopupGUIClient::slotCopyImage()
772 {
773 #ifndef QT_NO_MIMECLIPBOARD
774 QUrl safeURL(d->m_imageURL);
775 safeURL.setPassword(QString());
776
777 // Set it in both the mouse selection and in the clipboard
778 QMimeData *mimeData = new QMimeData;
779 mimeData->setImageData(d->m_pixmap);
780 mimeData->setUrls(QList<QUrl>() << safeURL);
781 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
782
783 mimeData = new QMimeData;
784 mimeData->setImageData(d->m_pixmap);
785 mimeData->setUrls(QList<QUrl>() << safeURL);
786 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection);
787 #else
788 // qCDebug(KHTML_LOG) << "slotCopyImage called when the clipboard does not support this. This should not be possible.";
789 #endif
790 }
791
slotCopyImageLocation()792 void KHTMLPopupGUIClient::slotCopyImageLocation()
793 {
794 QUrl safeURL(d->m_imageURL);
795 safeURL.setPassword(QString());
796 #ifndef QT_NO_MIMECLIPBOARD
797 // Set it in both the mouse selection and in the clipboard
798 QMimeData *mimeData = new QMimeData;
799 mimeData->setUrls(QList<QUrl>() << safeURL);
800 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Clipboard);
801 mimeData = new QMimeData;
802 mimeData->setUrls(QList<QUrl>() << safeURL);
803 QApplication::clipboard()->setMimeData(mimeData, QClipboard::Selection);
804 #else
805 QApplication::clipboard()->setText(safeURL.url()); //FIXME(E): Handle multiple entries
806 #endif
807 }
808
slotViewImage()809 void KHTMLPopupGUIClient::slotViewImage()
810 {
811 d->m_khtml->browserExtension()->createNewWindow(d->m_imageURL);
812 }
813
slotReloadFrame()814 void KHTMLPopupGUIClient::slotReloadFrame()
815 {
816 KParts::OpenUrlArguments args = d->m_khtml->arguments();
817 args.setReload(true);
818 args.metaData()["referrer"] = d->m_khtml->pageReferrer();
819 // reload document
820 d->m_khtml->closeUrl();
821 d->m_khtml->setArguments(args);
822 d->m_khtml->openUrl(d->m_khtml->url());
823 }
824
slotFrameInWindow()825 void KHTMLPopupGUIClient::slotFrameInWindow()
826 {
827 KParts::OpenUrlArguments args = d->m_khtml->arguments();
828 args.metaData()["referrer"] = d->m_khtml->pageReferrer();
829 KParts::BrowserArguments browserArgs(d->m_khtml->browserExtension()->browserArguments());
830 browserArgs.setForcesNewWindow(true);
831 emit d->m_khtml->browserExtension()->createNewWindow(d->m_khtml->url(), args, browserArgs);
832 }
833
slotFrameInTop()834 void KHTMLPopupGUIClient::slotFrameInTop()
835 {
836 KParts::OpenUrlArguments args = d->m_khtml->arguments();
837 args.metaData()["referrer"] = d->m_khtml->pageReferrer();
838 KParts::BrowserArguments browserArgs(d->m_khtml->browserExtension()->browserArguments());
839 browserArgs.frameName = "_top";
840 emit d->m_khtml->browserExtension()->openUrlRequest(d->m_khtml->url(), args, browserArgs);
841 }
842
slotFrameInTab()843 void KHTMLPopupGUIClient::slotFrameInTab()
844 {
845 KParts::OpenUrlArguments args = d->m_khtml->arguments();
846 args.metaData()["referrer"] = d->m_khtml->pageReferrer();
847 KParts::BrowserArguments browserArgs(d->m_khtml->browserExtension()->browserArguments());
848 browserArgs.setNewTab(true);
849 emit d->m_khtml->browserExtension()->createNewWindow(d->m_khtml->url(), args, browserArgs);
850 }
851
saveURL(QWidget * parent,const QString & caption,const QUrl & url,const QMap<QString,QString> & metadata,const QString & filter,long cacheId,const QString & suggestedFilename)852 void KHTMLPopupGUIClient::saveURL(QWidget *parent, const QString &caption,
853 const QUrl &url,
854 const QMap<QString, QString> &metadata,
855 const QString &filter, long cacheId,
856 const QString &suggestedFilename)
857 {
858 QString name = QLatin1String("index.html");
859 if (!suggestedFilename.isEmpty()) {
860 name = suggestedFilename;
861 } else if (!url.fileName().isEmpty()) {
862 name = url.fileName();
863 }
864
865 QUrl destURL;
866 int query;
867 do {
868 query = KMessageBox::Yes;
869 // convert filename to URL using fromLocalFile to avoid trouble with ':' in filenames (#184202)
870 destURL = QFileDialog::getSaveFileUrl(parent, caption, QUrl::fromLocalFile(name), filter);
871 if (destURL.isLocalFile()) {
872 QFileInfo info(destURL.toLocalFile());
873 if (info.exists()) {
874 // TODO: use KIO::RenameDlg (shows more information)
875 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());
876 }
877 }
878 } while (query == KMessageBox::Cancel);
879
880 if (destURL.isValid()) {
881 saveURL(parent, url, destURL, metadata, cacheId);
882 }
883 }
884
saveURL(QWidget * parent,const QUrl & url,const QUrl & destURL,const QMap<QString,QString> & metadata,long cacheId)885 void KHTMLPopupGUIClient::saveURL(QWidget *parent, const QUrl &url, const QUrl &destURL,
886 const QMap<QString, QString> &metadata,
887 long cacheId)
888 {
889 if (destURL.isValid()) {
890 bool saved = false;
891 if (KHTMLPageCache::self()->isComplete(cacheId)) {
892 if (destURL.isLocalFile()) {
893 QSaveFile destFile(destURL.toLocalFile());
894 if (destFile.open(QIODevice::WriteOnly)) {
895 QDataStream stream(&destFile);
896 KHTMLPageCache::self()->saveData(cacheId, &stream);
897 destFile.commit();
898 saved = true;
899 }
900 } else {
901 // save to temp file, then move to final destination.
902 QTemporaryFile destFile;
903 if (destFile.open()) {
904 QDataStream stream(&destFile);
905 KHTMLPageCache::self()->saveData(cacheId, &stream);
906 QUrl url2 = QUrl();
907 url2.setPath(destFile.fileName());
908 KIO::file_move(url2, destURL, -1, KIO::Overwrite);
909 saved = true;
910 }
911 }
912 }
913 if (!saved) {
914 // DownloadManager <-> konqueror integration
915 // find if the integration is enabled
916 // the empty key means no integration
917 // only use download manager for non-local urls!
918 bool downloadViaKIO = true;
919 if (!url.isLocalFile()) {
920 KConfigGroup cfg = KSharedConfig::openConfig("konquerorrc", KConfig::NoGlobals)->group("HTML Settings");
921 QString downloadManger = cfg.readPathEntry("DownloadManager", QString());
922 if (!downloadManger.isEmpty()) {
923 // then find the download manager location
924 // qCDebug(KHTML_LOG) << "Using: "<<downloadManger <<" as Download Manager";
925 QString cmd = QStandardPaths::findExecutable(downloadManger);
926 if (cmd.isEmpty()) {
927 QString errMsg = i18n("The Download Manager (%1) could not be found in your $PATH ", downloadManger);
928 QString errMsgEx = i18n("Try to reinstall it \n\nThe integration with Konqueror will be disabled.");
929 KMessageBox::detailedSorry(nullptr, errMsg, errMsgEx);
930 cfg.writePathEntry("DownloadManager", QString());
931 cfg.sync();
932 } else {
933 downloadViaKIO = false;
934 QUrl cleanDest = destURL;
935 cleanDest.setPassword(QString()); // don't put password into commandline
936 cmd += ' ' + KShell::quoteArg(url.url()) + ' ' +
937 KShell::quoteArg(cleanDest.url());
938 // qCDebug(KHTML_LOG) << "Calling command "<<cmd;
939 KRun::runCommand(cmd, parent->topLevelWidget());
940 }
941 }
942 }
943
944 if (downloadViaKIO) {
945 KParts::BrowserRun::saveUrlUsingKIO(url, destURL, parent, metadata);
946 }
947 } //end if(!saved)
948 }
949 }
950
KHTMLPartBrowserHostExtension(KHTMLPart * part)951 KHTMLPartBrowserHostExtension::KHTMLPartBrowserHostExtension(KHTMLPart *part)
952 : KParts::BrowserHostExtension(part)
953 {
954 m_part = part;
955 }
956
~KHTMLPartBrowserHostExtension()957 KHTMLPartBrowserHostExtension::~KHTMLPartBrowserHostExtension()
958 {
959 }
960
frameNames() const961 QStringList KHTMLPartBrowserHostExtension::frameNames() const
962 {
963 return m_part->frameNames();
964 }
965
frames() const966 const QList<KParts::ReadOnlyPart *> KHTMLPartBrowserHostExtension::frames() const
967 {
968 return m_part->frames();
969 }
970
openUrlInFrame(const QUrl & url,const KParts::OpenUrlArguments & arguments,const KParts::BrowserArguments & browserArguments)971 bool KHTMLPartBrowserHostExtension::openUrlInFrame(const QUrl &url, const KParts::OpenUrlArguments &arguments, const KParts::BrowserArguments &browserArguments)
972 {
973 return m_part->openUrlInFrame(url, arguments, browserArguments);
974 }
975
findFrameParent(KParts::ReadOnlyPart * callingPart,const QString & frame)976 KParts::BrowserHostExtension *KHTMLPartBrowserHostExtension::findFrameParent(KParts::ReadOnlyPart
977 *callingPart, const QString &frame)
978 {
979 KHTMLPart *parentPart = m_part->d->findFrameParent(callingPart, frame, nullptr, true /* navigation*/);
980 if (parentPart) {
981 return parentPart->browserHostExtension();
982 }
983 return nullptr;
984 }
985
986 // defined in khtml_part.cpp
987 extern const int KHTML_NO_EXPORT fastZoomSizes[];
988 extern const int KHTML_NO_EXPORT fastZoomSizeCount;
989
KHTMLZoomFactorAction(KHTMLPart * part,bool direction,const QString & icon,const QString & text,QObject * parent)990 KHTMLZoomFactorAction::KHTMLZoomFactorAction(KHTMLPart *part, bool direction, const QString &icon, const QString &text, QObject *parent)
991 : KSelectAction(text, parent)
992 {
993 setIcon(QIcon::fromTheme(icon));
994
995 setToolBarMode(MenuMode);
996 setToolButtonPopupMode(QToolButton::DelayedPopup);
997
998 init(part, direction);
999 }
1000
init(KHTMLPart * part,bool direction)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
~KHTMLZoomFactorAction()1027 KHTMLZoomFactorAction::~KHTMLZoomFactorAction()
1028 {
1029 }
1030
slotTriggered(QAction * action)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
KHTMLTextExtension(KHTMLPart * part)1043 KHTMLTextExtension::KHTMLTextExtension(KHTMLPart *part)
1044 : KParts::TextExtension(part)
1045 {
1046 connect(part, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));
1047 }
1048
part() const1049 KHTMLPart *KHTMLTextExtension::part() const
1050 {
1051 return static_cast<KHTMLPart *>(parent());
1052 }
1053
hasSelection() const1054 bool KHTMLTextExtension::hasSelection() const
1055 {
1056 return part()->hasSelection();
1057 }
1058
selectedText(Format format) const1059 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
completeText(Format format) const1070 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
KHTMLHtmlExtension(KHTMLPart * part)1083 KHTMLHtmlExtension::KHTMLHtmlExtension(KHTMLPart *part)
1084 : KParts::HtmlExtension(part)
1085 {
1086 }
1087
baseUrl() const1088 QUrl KHTMLHtmlExtension::baseUrl() const
1089 {
1090 return part()->baseURL();
1091 }
1092
hasSelection() const1093 bool KHTMLHtmlExtension::hasSelection() const
1094 {
1095 return part()->hasSelection();
1096 }
1097
supportedQueryMethods() const1098 KParts::SelectorInterface::QueryMethods KHTMLHtmlExtension::supportedQueryMethods() const
1099 {
1100 return (KParts::SelectorInterface::SelectedContent | KParts::SelectorInterface::EntireContent);
1101 }
1102
convertDomElement(const DOM::ElementImpl * domElem)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
querySelector(const QString & query,KParts::SelectorInterface::QueryMethod method) const1118 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
querySelectorAll(const QString & query,KParts::SelectorInterface::QueryMethod method) const1152 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
htmlSettingsProperty(HtmlSettingsInterface::HtmlSettingsType type) const1200 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
setHtmlSettingsProperty(HtmlSettingsInterface::HtmlSettingsType type,const QVariant & value)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
part() const1269 KHTMLPart *KHTMLHtmlExtension::part() const
1270 {
1271 return static_cast<KHTMLPart *>(parent());
1272 }
1273
1274