1 /* This file is part of the KDE project
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>
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.
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.
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.
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 <QtGui/QClipboard>
37 #include <QtCore/QFileInfo>
38 #include <QtGui/QMenu>
39 #include <QtCore/QUrl>
40 #include <QtCore/QMetaEnum>
45 #include <kfiledialog.h>
46 #include <kjobuidelegate.h>
50 #include <ksavefile.h>
51 #include <kstringhandler.h>
52 #include <ktoolinvocation.h>
53 #include <kmessagebox.h>
54 #include <kstandarddirs.h>
56 #include <kurifilter.h>
58 #include <kiconloader.h>
59 #include <kdesktopfile.h>
60 #include <kinputdialog.h>
61 #include <ktemporaryfile.h>
62 #include "khtml_global.h"
63 #include <kstandardaction.h>
64 #include <kactioncollection.h>
65 #include <kactionmenu.h>
67 #include "dom/dom_element.h"
68 #include "misc/htmltags.h"
70 #include "khtmlpart_p.h"
72 KHTMLPartBrowserExtension::KHTMLPartBrowserExtension( KHTMLPart
*parent
)
73 : KParts::BrowserExtension( parent
)
76 setURLDropHandlingEnabled( true );
78 enableAction( "cut", false );
79 enableAction( "copy", false );
80 enableAction( "paste", false );
82 m_connectedToClipboard
= false;
85 int KHTMLPartBrowserExtension::xOffset()
87 return m_part
->view()->contentsX();
90 int KHTMLPartBrowserExtension::yOffset()
92 return m_part
->view()->contentsY();
95 void KHTMLPartBrowserExtension::saveState( QDataStream
&stream
)
97 //kDebug( 6050 ) << "saveState!";
98 m_part
->saveState( stream
);
101 void KHTMLPartBrowserExtension::restoreState( QDataStream
&stream
)
103 //kDebug( 6050 ) << "restoreState!";
104 m_part
->restoreState( stream
);
107 void KHTMLPartBrowserExtension::editableWidgetFocused( QWidget
*widget
)
109 m_editableFormWidget
= widget
;
112 if ( !m_connectedToClipboard
&& m_editableFormWidget
)
114 connect( QApplication::clipboard(), SIGNAL( dataChanged() ),
115 this, SLOT( updateEditActions() ) );
117 if ( m_editableFormWidget
->inherits( "QLineEdit" ) || m_editableFormWidget
->inherits( "QTextEdit" ) )
118 connect( m_editableFormWidget
, SIGNAL( selectionChanged() ),
119 this, SLOT( updateEditActions() ) );
121 m_connectedToClipboard
= true;
123 editableWidgetFocused();
126 void KHTMLPartBrowserExtension::editableWidgetBlurred( QWidget
* /*widget*/ )
128 QWidget
*oldWidget
= m_editableFormWidget
;
130 m_editableFormWidget
= 0;
131 enableAction( "cut", false );
132 enableAction( "paste", false );
133 m_part
->emitSelectionChanged();
135 if ( m_connectedToClipboard
)
137 disconnect( QApplication::clipboard(), SIGNAL( dataChanged() ),
138 this, SLOT( updateEditActions() ) );
142 if ( oldWidget
->inherits( "QLineEdit" ) || oldWidget
->inherits( "QTextEdit" ) )
143 disconnect( oldWidget
, SIGNAL( selectionChanged() ),
144 this, SLOT( updateEditActions() ) );
147 m_connectedToClipboard
= false;
149 editableWidgetBlurred();
152 void KHTMLPartBrowserExtension::setExtensionProxy( KParts::BrowserExtension
*proxy
)
154 if ( m_extensionProxy
)
156 disconnect( m_extensionProxy
, SIGNAL( enableAction( const char *, bool ) ),
157 this, SLOT( extensionProxyActionEnabled( const char *, bool ) ) );
158 if ( m_extensionProxy
->inherits( "KHTMLPartBrowserExtension" ) )
160 disconnect( m_extensionProxy
, SIGNAL( editableWidgetFocused() ),
161 this, SLOT( extensionProxyEditableWidgetFocused() ) );
162 disconnect( m_extensionProxy
, SIGNAL( editableWidgetBlurred() ),
163 this, SLOT( extensionProxyEditableWidgetBlurred() ) );
167 m_extensionProxy
= proxy
;
169 if ( m_extensionProxy
)
171 connect( m_extensionProxy
, SIGNAL( enableAction( const char *, bool ) ),
172 this, SLOT( extensionProxyActionEnabled( const char *, bool ) ) );
173 if ( m_extensionProxy
->inherits( "KHTMLPartBrowserExtension" ) )
175 connect( m_extensionProxy
, SIGNAL( editableWidgetFocused() ),
176 this, SLOT( extensionProxyEditableWidgetFocused() ) );
177 connect( m_extensionProxy
, SIGNAL( editableWidgetBlurred() ),
178 this, SLOT( extensionProxyEditableWidgetBlurred() ) );
181 enableAction( "cut", m_extensionProxy
->isActionEnabled( "cut" ) );
182 enableAction( "copy", m_extensionProxy
->isActionEnabled( "copy" ) );
183 enableAction( "paste", m_extensionProxy
->isActionEnabled( "paste" ) );
188 enableAction( "copy", false ); // ### re-check this
192 void KHTMLPartBrowserExtension::cut()
194 if ( m_extensionProxy
)
196 callExtensionProxyMethod( "cut()" );
200 if ( !m_editableFormWidget
)
203 if ( m_editableFormWidget
->inherits( "QLineEdit" ) )
204 static_cast<QLineEdit
*>( &(*m_editableFormWidget
) )->cut();
205 else if ( m_editableFormWidget
->inherits( "QTextEdit" ) )
206 static_cast<QTextEdit
*>( &(*m_editableFormWidget
) )->cut();
209 void KHTMLPartBrowserExtension::copy()
211 if ( m_extensionProxy
)
213 callExtensionProxyMethod( "copy()" );
217 kDebug( 6050 ) << "************! KHTMLPartBrowserExtension::copy()";
218 if ( !m_editableFormWidget
)
220 // get selected text and paste to the clipboard
221 QString text
= m_part
->selectedText();
222 text
.replace( QChar( 0xa0 ), ' ' );
224 QClipboard
*cb
= QApplication::clipboard();
225 disconnect( cb
, SIGNAL( selectionChanged() ), m_part
, SLOT( slotClearSelection() ) );
226 #ifndef QT_NO_MIMECLIPBOARD
229 * When selectionModeEnabled, that means the user has just selected
230 * the text, not ctrl+c to copy it. The selection clipboard
231 * doesn't seem to support mime type, so to save time, don't calculate
232 * the selected text as html.
233 * optomisation disabled for now until everything else works.
235 //if(!cb->selectionModeEnabled())
236 htmltext
= m_part
->selectedTextAsHTML();
237 QMimeData
*mimeData
= new QMimeData
;
238 mimeData
->setText(text
);
239 if(!htmltext
.isEmpty()) {
240 htmltext
.replace( QChar( 0xa0 ), ' ' );
241 mimeData
->setHtml(htmltext
);
243 cb
->setMimeData(mimeData
);
248 connect( cb
, SIGNAL( selectionChanged() ), m_part
, SLOT( slotClearSelection() ) );
252 if ( m_editableFormWidget
->inherits( "QLineEdit" ) )
253 static_cast<QLineEdit
*>( &(*m_editableFormWidget
) )->copy();
254 else if ( m_editableFormWidget
->inherits( "QTextEdit" ) )
255 static_cast<QTextEdit
*>( &(*m_editableFormWidget
) )->copy();
259 void KHTMLPartBrowserExtension::searchProvider()
261 // action name is of form "previewProvider[<searchproviderprefix>:]"
262 const QString searchProviderPrefix
= QString( sender()->objectName() ).mid( 14 );
264 const QString text
= m_part
->simplifiedSelectedText();
267 data
.setData( searchProviderPrefix
+ text
);
268 list
<< "kurisearchfilter" << "kuriikwsfilter";
270 if( !KUriFilter::self()->filterUri(data
, list
) )
272 KDesktopFile
file("services", "searchproviders/google.desktop");
273 QString encodedSearchTerm
= QUrl::toPercentEncoding(text
);
274 KConfigGroup
cg(file
.desktopGroup());
275 data
.setData(cg
.readEntry("Query").replace("\\{@}", encodedSearchTerm
));
278 KParts::BrowserArguments browserArgs
;
279 browserArgs
.frameName
= "_blank";
281 emit m_part
->browserExtension()->openUrlRequest( data
.uri(), KParts::OpenUrlArguments(), browserArgs
);
284 void KHTMLPartBrowserExtension::paste()
286 if ( m_extensionProxy
)
288 callExtensionProxyMethod( "paste()" );
292 if ( !m_editableFormWidget
)
295 if ( m_editableFormWidget
->inherits( "QLineEdit" ) )
296 static_cast<QLineEdit
*>( &(*m_editableFormWidget
) )->paste();
297 else if ( m_editableFormWidget
->inherits( "QTextEdit" ) )
298 static_cast<QTextEdit
*>( &(*m_editableFormWidget
) )->paste();
301 void KHTMLPartBrowserExtension::callExtensionProxyMethod( const char *method
)
303 if ( !m_extensionProxy
)
306 int slot
= m_extensionProxy
->metaObject()->indexOfSlot( method
);
310 QMetaObject::invokeMethod(m_extensionProxy
, method
, Qt::DirectConnection
);
313 void KHTMLPartBrowserExtension::updateEditActions()
315 if ( !m_editableFormWidget
)
317 enableAction( "cut", false );
318 enableAction( "copy", false );
319 enableAction( "paste", false );
323 // ### duplicated from KonqMainWindow::slotClipboardDataChanged
324 #ifndef QT_NO_MIMECLIPBOARD // Handle minimalized versions of Qt Embedded
325 const QMimeData
*data
= QApplication::clipboard()->mimeData();
326 enableAction( "paste", data
->hasFormat( "text/plain" ) );
328 QString data
=QApplication::clipboard()->text();
329 enableAction( "paste", data
.contains("://"));
331 bool hasSelection
= false;
333 if( m_editableFormWidget
) {
334 if ( qobject_cast
<QLineEdit
*>(m_editableFormWidget
))
335 hasSelection
= static_cast<QLineEdit
*>( &(*m_editableFormWidget
) )->hasSelectedText();
336 else if(qobject_cast
<QTextEdit
*>(m_editableFormWidget
))
337 hasSelection
= static_cast<QTextEdit
*>( &(*m_editableFormWidget
) )->textCursor().hasSelection();
340 enableAction( "copy", hasSelection
);
341 enableAction( "cut", hasSelection
);
344 void KHTMLPartBrowserExtension::extensionProxyEditableWidgetFocused() {
345 editableWidgetFocused();
348 void KHTMLPartBrowserExtension::extensionProxyEditableWidgetBlurred() {
349 editableWidgetBlurred();
352 void KHTMLPartBrowserExtension::extensionProxyActionEnabled( const char *action
, bool enable
)
354 // only forward enableAction calls for actions we actually do forward
355 if ( strcmp( action
, "cut" ) == 0 ||
356 strcmp( action
, "copy" ) == 0 ||
357 strcmp( action
, "paste" ) == 0 ) {
358 enableAction( action
, enable
);
362 void KHTMLPartBrowserExtension::reparseConfiguration()
364 m_part
->reparseConfiguration();
367 void KHTMLPartBrowserExtension::print()
369 m_part
->view()->print();
372 void KHTMLPartBrowserExtension::disableScrolling()
374 QScrollArea
*scrollArea
= m_part
->view();
376 scrollArea
->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
377 scrollArea
->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
381 class KHTMLPopupGUIClient::KHTMLPopupGUIClientPrivate
388 QString m_suggestedFilename
;
389 KActionCollection
* m_actionCollection
;
390 KParts::BrowserExtension::ActionGroupMap actionGroups
;
394 KHTMLPopupGUIClient::KHTMLPopupGUIClient( KHTMLPart
*khtml
, const KUrl
&url
)
395 : QObject( khtml
), d(new KHTMLPopupGUIClientPrivate
)
399 d
->m_actionCollection
= new KActionCollection(this);
400 bool isImage
= false;
401 bool hasSelection
= khtml
->hasSelection();
403 DOM::Element e
= khtml
->nodeUnderMouse();
405 if ( !e
.isNull() && (e
.elementId() == ID_IMG
||
406 (e
.elementId() == ID_INPUT
&& !static_cast<DOM::HTMLInputElement
>(e
).src().isEmpty())))
408 if (e
.elementId() == ID_IMG
) {
409 DOM::HTMLImageElementImpl
*ie
= static_cast<DOM::HTMLImageElementImpl
*>(e
.handle());
410 khtml::RenderImage
*ri
= dynamic_cast<khtml::RenderImage
*>(ie
->renderer());
411 if (ri
&& ri
->contentObject()) {
412 d
->m_suggestedFilename
= static_cast<khtml::CachedImage
*>(ri
->contentObject())->suggestedFilename();
419 QList
<QAction
*> editActions
;
420 QAction
* copyAction
= d
->m_actionCollection
->addAction( KStandardAction::Copy
, "copy",
421 d
->m_khtml
->browserExtension(), SLOT( copy() ) );
423 copyAction
->setText(i18n("&Copy Text"));
424 copyAction
->setEnabled(d
->m_khtml
->browserExtension()->isActionEnabled( "copy" ));
425 editActions
.append(copyAction
);
427 editActions
.append(khtml
->actionCollection()->action("selectAll"));
429 addSearchActions(editActions
);
431 QString selectedTextURL
= selectedTextAsOneLine();
432 if ( selectedTextURL
.contains("://") && KUrl(selectedTextURL
).isValid() ) {
433 if (selectedTextURL
.length() > 18) {
434 selectedTextURL
.truncate(15);
435 selectedTextURL
+= "...";
437 KAction
*action
= new KAction(i18n("Open '%1'", selectedTextURL
), this);
438 d
->m_actionCollection
->addAction( "openSelection", action
);
439 action
->setIcon( KIcon( "window-new" ) );
440 connect( action
, SIGNAL(triggered(bool)), this, SLOT( openSelection() ) );
441 editActions
.append(action
);
444 KAction
* separator
= new KAction(d
->m_actionCollection
);
445 separator
->setSeparator(true);
446 editActions
.append(separator
);
448 d
->actionGroups
.insert("editactions", editActions
);
451 if (!url
.isEmpty()) {
452 QList
<QAction
*> linkActions
;
453 if (url
.protocol() == "mailto") {
454 KAction
*action
= new KAction( i18n( "&Copy Email Address" ), this );
455 d
->m_actionCollection
->addAction( "copylinklocation", action
);
456 connect( action
, SIGNAL(triggered(bool)), this, SLOT(slotCopyLinkLocation()) );
457 linkActions
.append(action
);
459 KAction
*action
= new KAction( i18n( "&Save Link As..." ), this );
460 d
->m_actionCollection
->addAction( "savelinkas", action
);
461 connect( action
, SIGNAL(triggered(bool)), this, SLOT(slotSaveLinkAs()) );
462 linkActions
.append(action
);
464 action
= new KAction( i18n( "&Copy Link Address" ), this );
465 d
->m_actionCollection
->addAction( "copylinklocation", action
);
466 connect( action
, SIGNAL(triggered(bool)), this, SLOT( slotCopyLinkLocation() ) );
467 linkActions
.append(action
);
469 d
->actionGroups
.insert("linkactions", linkActions
);
472 QList
<QAction
*> partActions
;
473 // frameset? -> add "Reload Frame" etc.
475 if ( khtml
->parentPart() ) {
476 KActionMenu
* menu
= new KActionMenu( i18nc("@title:menu HTML frame/iframe", "Frame"), this);
477 KAction
*action
= new KAction( i18n( "Open in New &Window" ), this );
478 d
->m_actionCollection
->addAction( "frameinwindow", action
);
479 action
->setIcon( KIcon( "window-new" ) );
480 connect( action
, SIGNAL(triggered(bool)), this, SLOT(slotFrameInWindow()) );
481 menu
->addAction(action
);
483 action
= new KAction( i18n( "Open in &This Window" ), this );
484 d
->m_actionCollection
->addAction( "frameintop", action
);
485 connect( action
, SIGNAL(triggered(bool)), this, SLOT( slotFrameInTop() ) );
486 menu
->addAction(action
);
488 action
= new KAction( i18n( "Open in &New Tab" ), this );
489 d
->m_actionCollection
->addAction( "frameintab", action
);
490 action
->setIcon( KIcon( "tab-new" ) );
491 connect( action
, SIGNAL(triggered(bool)), this, SLOT( slotFrameInTab() ) );
492 menu
->addAction(action
);
494 action
= new KAction(d
->m_actionCollection
);
495 action
->setSeparator(true);
496 menu
->addAction(action
);
498 action
= new KAction( i18n( "Reload Frame" ), this );
499 d
->m_actionCollection
->addAction( "reloadframe", action
);
500 connect( action
, SIGNAL(triggered(bool)), this, SLOT( slotReloadFrame() ) );
501 menu
->addAction(action
);
503 action
= new KAction( i18n( "Print Frame..." ), this );
504 d
->m_actionCollection
->addAction( "printFrame", action
);
505 action
->setIcon( KIcon( "document-print-frame" ) );
506 connect( action
, SIGNAL(triggered(bool)), d
->m_khtml
->browserExtension(), SLOT( print() ) );
507 menu
->addAction(action
);
509 action
= new KAction( i18n( "Save &Frame As..." ), this );
510 d
->m_actionCollection
->addAction( "saveFrame", action
);
511 connect( action
, SIGNAL(triggered(bool)), d
->m_khtml
, SLOT( slotSaveFrame() ) );
512 menu
->addAction(action
);
514 action
= new KAction( i18n( "View Frame Source" ), this );
515 d
->m_actionCollection
->addAction( "viewFrameSource", action
);
516 connect( action
, SIGNAL(triggered(bool)), d
->m_khtml
, SLOT( slotViewDocumentSource() ) );
517 menu
->addAction(action
);
519 action
= new KAction( i18n( "View Frame Information" ), this );
520 d
->m_actionCollection
->addAction( "viewFrameInfo", action
);
521 connect( action
, SIGNAL(triggered(bool)), d
->m_khtml
, SLOT( slotViewPageInfo() ) );
523 action
= new KAction(d
->m_actionCollection
);
524 action
->setSeparator(true);
525 menu
->addAction(action
);
527 if ( KHTMLGlobal::defaultHTMLSettings()->isAdFilterEnabled() ) {
528 if ( khtml
->d
->m_frame
->m_type
== khtml::ChildFrame::IFrame
) {
529 action
= new KAction( i18n( "Block IFrame..." ), this );
530 d
->m_actionCollection
->addAction( "blockiframe", action
);
531 connect( action
, SIGNAL(triggered(bool)), this, SLOT( slotBlockIFrame() ) );
532 menu
->addAction(action
);
536 partActions
.append(menu
);
541 if ( e
.elementId() == ID_IMG
) {
542 d
->m_imageURL
= KUrl( static_cast<DOM::HTMLImageElement
>( e
).src().string() );
543 DOM::HTMLImageElementImpl
*imageimpl
= static_cast<DOM::HTMLImageElementImpl
*>( e
.handle() );
545 if(imageimpl
) // should be true always. right?
547 if(imageimpl
->complete()) {
548 d
->m_pixmap
= imageimpl
->currentPixmap();
553 d
->m_imageURL
= KUrl( static_cast<DOM::HTMLInputElement
>( e
).src().string() );
554 KAction
*action
= new KAction( i18n( "Save Image As..." ), this );
555 d
->m_actionCollection
->addAction( "saveimageas", action
);
556 connect( action
, SIGNAL(triggered(bool)), this, SLOT( slotSaveImageAs() ) );
557 partActions
.append(action
);
559 action
= new KAction( i18n( "Send Image..." ), this );
560 d
->m_actionCollection
->addAction( "sendimage", action
);
561 connect( action
, SIGNAL(triggered(bool)), this, SLOT( slotSendImage() ) );
562 partActions
.append(action
);
564 #ifndef QT_NO_MIMECLIPBOARD
565 action
= new KAction( i18n( "Copy Image" ), this );
566 d
->m_actionCollection
->addAction( "copyimage", action
);
567 action
->setEnabled(!d
->m_pixmap
.isNull());
568 connect( action
, SIGNAL(triggered(bool)), this, SLOT( slotCopyImage() ) );
569 partActions
.append(action
);
572 if(d
->m_pixmap
.isNull()) { //fallback to image location if still loading the image. this will always be true if ifdef QT_NO_MIMECLIPBOARD
573 action
= new KAction( i18n( "Copy Image Location" ), this );
574 d
->m_actionCollection
->addAction( "copyimagelocation", action
);
575 connect( action
, SIGNAL(triggered(bool)), this, SLOT( slotCopyImageLocation() ) );
576 partActions
.append(action
);
579 QString actionText
= d
->m_suggestedFilename
.isEmpty() ?
580 KStringHandler::csqueeze(d
->m_imageURL
.fileName()+d
->m_imageURL
.query(), 25)
581 : d
->m_suggestedFilename
;
582 action
= new KAction( i18n("View Image (%1)", actionText
.replace("&", "&&")), this );
583 d
->m_actionCollection
->addAction( "viewimage", action
);
584 connect( action
, SIGNAL(triggered(bool)), this, SLOT( slotViewImage() ) );
585 partActions
.append(action
);
587 if (KHTMLGlobal::defaultHTMLSettings()->isAdFilterEnabled()) {
588 action
= new KAction( i18n( "Block Image..." ), this );
589 d
->m_actionCollection
->addAction( "blockimage", action
);
590 connect( action
, SIGNAL(triggered(bool)), this, SLOT( slotBlockImage() ) );
591 partActions
.append(action
);
593 if (!d
->m_imageURL
.host().isEmpty() &&
594 !d
->m_imageURL
.protocol().isEmpty())
596 action
= new KAction( i18n( "Block Images From %1" , d
->m_imageURL
.host()), this );
597 d
->m_actionCollection
->addAction( "blockhost", action
);
598 connect( action
, SIGNAL(triggered(bool)), this, SLOT( slotBlockHost() ) );
599 partActions
.append(action
);
602 KAction
* separator
= new KAction(d
->m_actionCollection
);
603 separator
->setSeparator(true);
604 partActions
.append(separator
);
607 if ( isImage
|| url
.isEmpty() ) {
608 KAction
*action
= new KAction( i18n( "Stop Animations" ), this );
609 d
->m_actionCollection
->addAction( "stopanimations", action
);
610 connect( action
, SIGNAL(triggered(bool)), this, SLOT(slotStopAnimations()) );
611 partActions
.append(action
);
612 KAction
* separator
= new KAction(d
->m_actionCollection
);
613 separator
->setSeparator(true);
614 partActions
.append(separator
);
616 if (!hasSelection
&& url
.isEmpty()) { // only when right-clicking on the page itself
617 partActions
.append(khtml
->actionCollection()->action("viewDocumentSource"));
619 if (!hasSelection
&& url
.isEmpty() && !isImage
) {
620 partActions
.append(khtml
->actionCollection()->action("setEncoding"));
622 d
->actionGroups
.insert("partactions", partActions
);
625 KHTMLPopupGUIClient::~KHTMLPopupGUIClient()
627 delete d
->m_actionCollection
;
631 void KHTMLPopupGUIClient::addSearchActions(QList
<QAction
*>& editActions
)
633 // Fill search provider entries
634 KConfig
config("kuriikwsfilterrc");
635 KConfigGroup cg
= config
.group("General");
636 const QString defaultEngine
= cg
.readEntry("DefaultSearchEngine", "google");
637 const char keywordDelimiter
= cg
.readEntry("KeywordDelimiter", static_cast<int>(':'));
640 QString selectedText
= d
->m_khtml
->simplifiedSelectedText();
641 if (selectedText
.isEmpty())
644 selectedText
.replace("&", "&&");
645 if (selectedText
.length() > 18) {
646 selectedText
.truncate(15);
647 selectedText
+= "...";
650 // default search provider
651 KService::Ptr service
;
652 if( !defaultEngine
.isEmpty())
653 service
= KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(defaultEngine
));
655 // search provider icon
659 data
.setData(QString("some keyword"));
660 list
<< "kurisearchfilter" << "kuriikwsfilter";
663 if (KUriFilter::self()->filterUri(data
, list
)) {
664 QString iconPath
= KStandardDirs::locate("cache", KMimeType::favIconForUrl(data
.uri()) + ".png");
665 if (iconPath
.isEmpty())
666 icon
= KIcon("edit-find");
668 icon
= KIcon(QPixmap(iconPath
));
669 name
= service
->name();
671 icon
= KIcon("google");
675 KAction
*action
= new KAction(i18n("Search for '%1' with %2", selectedText
, name
), this);
676 d
->m_actionCollection
->addAction("searchProvider", action
);
677 editActions
.append(action
);
678 action
->setIcon(icon
);
679 connect(action
, SIGNAL(triggered(bool)), d
->m_khtml
->browserExtension(), SLOT(searchProvider()));
681 // favorite search providers
682 QStringList favoriteEngines
;
683 favoriteEngines
<< "google" << "google_groups" << "google_news" << "webster" << "dmoz" << "wikipedia";
684 favoriteEngines
= cg
.readEntry("FavoriteSearchEngines", favoriteEngines
);
686 if (!favoriteEngines
.isEmpty()) {
687 KActionMenu
* providerList
= new KActionMenu(i18n("Search for '%1' with", selectedText
), this);
688 d
->m_actionCollection
->addAction("searchProviderList", providerList
);
689 editActions
.append(providerList
);
691 QStringList::ConstIterator it
= favoriteEngines
.constBegin();
692 for (; it
!= favoriteEngines
.constEnd(); ++it
) {
693 if (*it
==defaultEngine
)
695 service
= KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(*it
));
698 const QString searchProviderPrefix
= *(service
->property("Keys").toStringList().begin()) + keywordDelimiter
;
699 data
.setData(searchProviderPrefix
+ "some keyword");
701 if (KUriFilter::self()->filterUri(data
, list
)) {
702 const QString iconPath
= KStandardDirs::locate("cache", KMimeType::favIconForUrl(data
.uri()) + ".png");
703 if (iconPath
.isEmpty())
704 icon
= KIcon("edit-find");
706 icon
= KIcon(iconPath
);
707 name
= service
->name();
709 KAction
*action
= new KAction(name
, this);
710 d
->m_actionCollection
->addAction(QString("searchProvider" + searchProviderPrefix
).toLatin1().constData(), action
);
711 action
->setIcon(icon
);
712 connect(action
, SIGNAL(triggered(bool)), d
->m_khtml
->browserExtension(), SLOT(searchProvider()));
714 providerList
->addAction(action
);
720 QString
KHTMLPopupGUIClient::selectedTextAsOneLine() const
722 QString text
= d
->m_khtml
->simplifiedSelectedText();
723 // in addition to what simplifiedSelectedText does,
724 // remove linefeeds and any whitespace surrounding it (#113177),
725 // to get it all in a single line.
726 text
.remove(QRegExp("[\\s]*\\n+[\\s]*"));
730 void KHTMLPopupGUIClient::openSelection()
732 KParts::BrowserArguments browserArgs
;
733 browserArgs
.frameName
= "_blank";
735 emit d
->m_khtml
->browserExtension()->openUrlRequest(selectedTextAsOneLine(), KParts::OpenUrlArguments(), browserArgs
);
738 KParts::BrowserExtension::ActionGroupMap
KHTMLPopupGUIClient::actionGroups() const
740 return d
->actionGroups
;
743 void KHTMLPopupGUIClient::slotSaveLinkAs()
745 KIO::MetaData metaData
;
746 metaData
["referrer"] = d
->m_khtml
->referrer();
747 saveURL( d
->m_khtml
->widget(), i18n( "Save Link As" ), d
->m_url
, metaData
);
750 void KHTMLPopupGUIClient::slotSendImage()
753 urls
.append( d
->m_imageURL
.url());
754 QString subject
= d
->m_imageURL
.url();
755 KToolInvocation::invokeMailer(QString(), QString(), QString(), subject
,
758 urls
); // attachments
763 void KHTMLPopupGUIClient::slotSaveImageAs()
765 KIO::MetaData metaData
;
766 metaData
["referrer"] = d
->m_khtml
->referrer();
767 saveURL( d
->m_khtml
->widget(), i18n( "Save Image As" ), d
->m_imageURL
, metaData
, QString(), 0, d
->m_suggestedFilename
);
770 void KHTMLPopupGUIClient::slotBlockHost()
772 QString name
=d
->m_imageURL
.protocol()+"://"+d
->m_imageURL
.host()+"/*";
773 KHTMLGlobal::defaultHTMLSettings()->addAdFilter( name
);
774 d
->m_khtml
->reparseConfiguration();
777 void KHTMLPopupGUIClient::slotBlockImage()
781 QString url
= KInputDialog::getText( i18n("Add URL to Filter"),
782 i18n("Enter the URL:"),
786 KHTMLGlobal::defaultHTMLSettings()->addAdFilter( url
);
787 d
->m_khtml
->reparseConfiguration();
791 void KHTMLPopupGUIClient::slotBlockIFrame()
794 QString url
= KInputDialog::getText( i18n( "Add URL to Filter"),
795 i18n("Enter the URL:"),
796 d
->m_khtml
->url().url(),
799 KHTMLGlobal::defaultHTMLSettings()->addAdFilter( url
);
800 d
->m_khtml
->reparseConfiguration();
804 void KHTMLPopupGUIClient::slotCopyLinkLocation()
806 KUrl
safeURL(d
->m_url
);
807 safeURL
.setPass(QString());
808 #ifndef QT_NO_MIMECLIPBOARD
809 // Set it in both the mouse selection and in the clipboard
810 QMimeData
* mimeData
= new QMimeData
;
811 safeURL
.populateMimeData( mimeData
);
812 QApplication::clipboard()->setMimeData( mimeData
, QClipboard::Clipboard
);
814 mimeData
= new QMimeData
;
815 safeURL
.populateMimeData( mimeData
);
816 QApplication::clipboard()->setMimeData( mimeData
, QClipboard::Selection
);
819 QApplication::clipboard()->setText( safeURL
.url() ); //FIXME(E): Handle multiple entries
823 void KHTMLPopupGUIClient::slotStopAnimations()
825 d
->m_khtml
->stopAnimations();
828 void KHTMLPopupGUIClient::slotCopyImage()
830 #ifndef QT_NO_MIMECLIPBOARD
831 KUrl
safeURL(d
->m_imageURL
);
832 safeURL
.setPass(QString());
834 // Set it in both the mouse selection and in the clipboard
835 QMimeData
* mimeData
= new QMimeData
;
836 mimeData
->setImageData( d
->m_pixmap
);
837 safeURL
.populateMimeData( mimeData
);
838 QApplication::clipboard()->setMimeData( mimeData
, QClipboard::Clipboard
);
840 mimeData
= new QMimeData
;
841 mimeData
->setImageData( d
->m_pixmap
);
842 safeURL
.populateMimeData( mimeData
);
843 QApplication::clipboard()->setMimeData( mimeData
, QClipboard::Selection
);
845 kDebug() << "slotCopyImage called when the clipboard does not support this. This should not be possible.";
849 void KHTMLPopupGUIClient::slotCopyImageLocation()
851 KUrl
safeURL(d
->m_imageURL
);
852 safeURL
.setPass(QString());
853 #ifndef QT_NO_MIMECLIPBOARD
854 // Set it in both the mouse selection and in the clipboard
855 QMimeData
* mimeData
= new QMimeData
;
856 safeURL
.populateMimeData( mimeData
);
857 QApplication::clipboard()->setMimeData( mimeData
, QClipboard::Clipboard
);
858 mimeData
= new QMimeData
;
859 safeURL
.populateMimeData( mimeData
);
860 QApplication::clipboard()->setMimeData( mimeData
, QClipboard::Selection
);
862 QApplication::clipboard()->setText( safeURL
.url() ); //FIXME(E): Handle multiple entries
866 void KHTMLPopupGUIClient::slotViewImage()
868 d
->m_khtml
->browserExtension()->createNewWindow(d
->m_imageURL
);
871 void KHTMLPopupGUIClient::slotReloadFrame()
873 KParts::OpenUrlArguments args
= d
->m_khtml
->arguments();
874 args
.setReload( true );
875 args
.metaData()["referrer"] = d
->m_khtml
->pageReferrer();
877 d
->m_khtml
->closeUrl();
878 d
->m_khtml
->setArguments( args
);
879 d
->m_khtml
->openUrl( d
->m_khtml
->url() );
882 void KHTMLPopupGUIClient::slotFrameInWindow()
884 KParts::OpenUrlArguments args
= d
->m_khtml
->arguments();
885 args
.metaData()["referrer"] = d
->m_khtml
->pageReferrer();
886 args
.metaData()["forcenewwindow"] = "true";
887 emit d
->m_khtml
->browserExtension()->createNewWindow( d
->m_khtml
->url(), args
);
890 void KHTMLPopupGUIClient::slotFrameInTop()
892 KParts::OpenUrlArguments args
= d
->m_khtml
->arguments();
893 args
.metaData()["referrer"] = d
->m_khtml
->pageReferrer();
894 KParts::BrowserArguments
browserArgs( d
->m_khtml
->browserExtension()->browserArguments() );
895 browserArgs
.frameName
= "_top";
896 emit d
->m_khtml
->browserExtension()->openUrlRequest( d
->m_khtml
->url(), args
, browserArgs
);
899 void KHTMLPopupGUIClient::slotFrameInTab()
901 KParts::OpenUrlArguments args
= d
->m_khtml
->arguments();
902 args
.metaData()["referrer"] = d
->m_khtml
->pageReferrer();
903 KParts::BrowserArguments
browserArgs( d
->m_khtml
->browserExtension()->browserArguments() );
904 browserArgs
.setNewTab(true);
905 emit d
->m_khtml
->browserExtension()->createNewWindow( d
->m_khtml
->url(), args
, browserArgs
);
908 void KHTMLPopupGUIClient::saveURL( QWidget
*parent
, const QString
&caption
,
910 const QMap
<QString
, QString
> &metadata
,
911 const QString
&filter
, long cacheId
,
912 const QString
& suggestedFilename
)
914 QString name
= QLatin1String( "index.html" );
915 if ( !suggestedFilename
.isEmpty() )
916 name
= suggestedFilename
;
917 else if ( !url
.fileName().isEmpty() )
918 name
= url
.fileName();
923 query
= KMessageBox::Yes
;
924 destURL
= KFileDialog::getSaveUrl( name
, filter
, parent
, caption
);
925 if( destURL
.isLocalFile() )
927 QFileInfo
info( destURL
.toLocalFile() );
928 if( info
.exists() ) {
929 // TODO: use KIO::RenameDlg (shows more information)
930 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" )) );
933 } while ( query
== KMessageBox::Cancel
);
935 if ( destURL
.isValid() )
936 saveURL(parent
, url
, destURL
, metadata
, cacheId
);
939 void KHTMLPopupGUIClient::saveURL( QWidget
* parent
, const KUrl
&url
, const KUrl
&destURL
,
940 const QMap
<QString
, QString
> &metadata
,
943 if ( destURL
.isValid() )
946 if (KHTMLPageCache::self()->isComplete(cacheId
))
948 if (destURL
.isLocalFile())
950 KSaveFile
destFile(destURL
.toLocalFile());
953 QDataStream
stream ( &destFile
);
954 KHTMLPageCache::self()->saveData(cacheId
, &stream
);
960 // save to temp file, then move to final destination.
961 KTemporaryFile destFile
;
964 QDataStream
stream ( &destFile
);
965 KHTMLPageCache::self()->saveData(cacheId
, &stream
);
967 url2
.setPath(destFile
.fileName());
968 KIO::file_move(url2
, destURL
, -1, KIO::Overwrite
);
975 // DownloadManager <-> konqueror integration
976 // find if the integration is enabled
977 // the empty key means no integration
978 // only use download manager for non-local urls!
979 bool downloadViaKIO
= true;
980 if ( !url
.isLocalFile() )
982 KConfigGroup cfg
= KSharedConfig::openConfig("konquerorrc", KConfig::NoGlobals
)->group("HTML Settings");
983 QString downloadManger
= cfg
.readPathEntry("DownloadManager", QString());
984 if (!downloadManger
.isEmpty())
986 // then find the download manager location
987 kDebug(1000) << "Using: "<<downloadManger
<<" as Download Manager";
988 QString cmd
= KStandardDirs::findExe(downloadManger
);
991 QString errMsg
=i18n("The Download Manager (%1) could not be found in your $PATH ", downloadManger
);
992 QString errMsgEx
= i18n("Try to reinstall it \n\nThe integration with Konqueror will be disabled.");
993 KMessageBox::detailedSorry(0,errMsg
,errMsgEx
);
994 cfg
.writePathEntry("DownloadManager",QString());
999 downloadViaKIO
= false;
1000 KUrl cleanDest
= destURL
;
1001 cleanDest
.setPass( QString() ); // don't put password into commandline
1002 cmd
+= ' ' + KShell::quoteArg(url
.url()) + ' ' +
1003 KShell::quoteArg(cleanDest
.url());
1004 kDebug(1000) << "Calling command "<<cmd
;
1005 KRun::runCommand(cmd
, parent
->topLevelWidget());
1010 if ( downloadViaKIO
)
1012 KIO::Job
*job
= KIO::file_copy( url
, destURL
, -1, KIO::Overwrite
);
1013 job
->setMetaData(metadata
);
1014 job
->addMetaData("MaxCacheSize", "0"); // Don't store in http cache.
1015 job
->addMetaData("cache", "cache"); // Use entry from cache if available.
1016 job
->uiDelegate()->setAutoErrorHandlingEnabled( true );
1022 KHTMLPartBrowserHostExtension::KHTMLPartBrowserHostExtension( KHTMLPart
*part
)
1023 : KParts::BrowserHostExtension( part
)
1028 KHTMLPartBrowserHostExtension::~KHTMLPartBrowserHostExtension()
1032 QStringList
KHTMLPartBrowserHostExtension::frameNames() const
1034 return m_part
->frameNames();
1037 const QList
<KParts::ReadOnlyPart
*> KHTMLPartBrowserHostExtension::frames() const
1039 return m_part
->frames();
1042 bool KHTMLPartBrowserHostExtension::openUrlInFrame(const KUrl
&url
, const KParts::OpenUrlArguments
& arguments
, const KParts::BrowserArguments
&browserArguments
)
1044 return m_part
->openUrlInFrame( url
, arguments
, browserArguments
);
1047 KParts::BrowserHostExtension
* KHTMLPartBrowserHostExtension::findFrameParent( KParts::ReadOnlyPart
1048 *callingPart
, const QString
&frame
)
1050 KHTMLPart
*parentPart
= m_part
->findFrameParent(callingPart
, frame
);
1052 return parentPart
->browserHostExtension();
1057 // defined in khtml_part.cpp
1058 extern const int KDE_NO_EXPORT fastZoomSizes
[];
1059 extern const int KDE_NO_EXPORT fastZoomSizeCount
;
1061 KHTMLZoomFactorAction::KHTMLZoomFactorAction( KHTMLPart
*part
, bool direction
, const QString
&icon
, const QString
&text
, QObject
*parent
)
1062 : KSelectAction( text
, parent
)
1064 setIcon( KIcon( icon
) );
1066 setToolBarMode(MenuMode
);
1067 setToolButtonPopupMode(QToolButton::DelayedPopup
);
1069 init(part
, direction
);
1072 void KHTMLZoomFactorAction::init(KHTMLPart
*part
, bool direction
)
1074 m_direction
= direction
;
1077 // xgettext: no-c-format
1078 addAction( i18n( "Default Font Size (100%)" ) );
1080 int m
= m_direction
? 1 : -1;
1081 int ofs
= fastZoomSizeCount
/ 2; // take index of 100%
1083 // this only works if there is an odd number of elements in fastZoomSizes[]
1084 for ( int i
= m
; i
!= m
*(ofs
+1); i
+= m
)
1087 QString numStr
= QString::number( num
);
1088 if ( num
> 0 ) numStr
.prepend( QLatin1Char('+') );
1090 // xgettext: no-c-format
1091 addAction( i18n( "%1%" , fastZoomSizes
[ofs
+ i
] ) );
1094 connect( selectableActionGroup(), SIGNAL( triggered(QAction
*) ), this, SLOT( slotTriggered(QAction
*) ) );
1097 KHTMLZoomFactorAction::~KHTMLZoomFactorAction()
1101 void KHTMLZoomFactorAction::slotTriggered(QAction
* action
)
1103 int idx
= selectableActionGroup()->actions().indexOf(action
);
1106 m_part
->setFontScaleFactor(100);
1108 m_part
->setFontScaleFactor(fastZoomSizes
[fastZoomSizeCount
/2 + (m_direction
? 1 : -1)*idx
]);
1109 setCurrentAction( 0L );
1112 #include "khtml_ext.moc"