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