/* This file is part of the KDE project * * Copyright (C) 2000-2003 Simon Hausmann * 2001-2003 George Staikos * 2001-2003 Laurent Montel * 2001-2003 Dirk Mueller * 2001-2003 Waldo Bastian * 2001-2003 David Faure * 2001-2003 Daniel Naber * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "khtml_ext.h" #include "khtmlview.h" #include "rendering/render_form.h" #include "rendering/render_image.h" #include "html/html_imageimpl.h" #include "misc/loader.h" #include "dom/html_form.h" #include "dom/html_image.h" #include "dom/dom_string.h" #include "dom/html_document.h" #include "dom/dom_element.h" #include "xml/dom_elementimpl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "khtml_global.h" #include #include #include #include "khtmlpart_p.h" KHTMLPartBrowserExtension::KHTMLPartBrowserExtension( KHTMLPart *parent ) : KParts::BrowserExtension( parent ) { m_part = parent; setURLDropHandlingEnabled( true ); enableAction( "cut", false ); enableAction( "copy", false ); enableAction( "paste", false ); m_connectedToClipboard = false; } int KHTMLPartBrowserExtension::xOffset() { return m_part->view()->contentsX(); } int KHTMLPartBrowserExtension::yOffset() { return m_part->view()->contentsY(); } void KHTMLPartBrowserExtension::saveState( QDataStream &stream ) { //kDebug( 6050 ) << "saveState!"; m_part->saveState( stream ); } void KHTMLPartBrowserExtension::restoreState( QDataStream &stream ) { //kDebug( 6050 ) << "restoreState!"; m_part->restoreState( stream ); } void KHTMLPartBrowserExtension::editableWidgetFocused( QWidget *widget ) { m_editableFormWidget = widget; updateEditActions(); if ( !m_connectedToClipboard && m_editableFormWidget ) { connect( QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(updateEditActions()) ); if ( m_editableFormWidget->inherits( "QLineEdit" ) || m_editableFormWidget->inherits( "QTextEdit" ) ) connect( m_editableFormWidget, SIGNAL(selectionChanged()), this, SLOT(updateEditActions()) ); m_connectedToClipboard = true; } editableWidgetFocused(); } void KHTMLPartBrowserExtension::editableWidgetBlurred( QWidget * /*widget*/ ) { QWidget *oldWidget = m_editableFormWidget; m_editableFormWidget = 0; enableAction( "cut", false ); enableAction( "paste", false ); m_part->emitSelectionChanged(); if ( m_connectedToClipboard ) { disconnect( QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(updateEditActions()) ); if ( oldWidget ) { if ( oldWidget->inherits( "QLineEdit" ) || oldWidget->inherits( "QTextEdit" ) ) disconnect( oldWidget, SIGNAL(selectionChanged()), this, SLOT(updateEditActions()) ); } m_connectedToClipboard = false; } editableWidgetBlurred(); } void KHTMLPartBrowserExtension::setExtensionProxy( KParts::BrowserExtension *proxy ) { if ( m_extensionProxy ) { disconnect( m_extensionProxy, SIGNAL(enableAction(const char*,bool)), this, SLOT(extensionProxyActionEnabled(const char*,bool)) ); if ( m_extensionProxy->inherits( "KHTMLPartBrowserExtension" ) ) { disconnect( m_extensionProxy, SIGNAL(editableWidgetFocused()), this, SLOT(extensionProxyEditableWidgetFocused()) ); disconnect( m_extensionProxy, SIGNAL(editableWidgetBlurred()), this, SLOT(extensionProxyEditableWidgetBlurred()) ); } } m_extensionProxy = proxy; if ( m_extensionProxy ) { connect( m_extensionProxy, SIGNAL(enableAction(const char*,bool)), this, SLOT(extensionProxyActionEnabled(const char*,bool)) ); if ( m_extensionProxy->inherits( "KHTMLPartBrowserExtension" ) ) { connect( m_extensionProxy, SIGNAL(editableWidgetFocused()), this, SLOT(extensionProxyEditableWidgetFocused()) ); connect( m_extensionProxy, SIGNAL(editableWidgetBlurred()), this, SLOT(extensionProxyEditableWidgetBlurred()) ); } enableAction( "cut", m_extensionProxy->isActionEnabled( "cut" ) ); enableAction( "copy", m_extensionProxy->isActionEnabled( "copy" ) ); enableAction( "paste", m_extensionProxy->isActionEnabled( "paste" ) ); } else { updateEditActions(); enableAction( "copy", false ); // ### re-check this } } void KHTMLPartBrowserExtension::cut() { if ( m_extensionProxy ) { callExtensionProxyMethod( "cut" ); return; } if ( !m_editableFormWidget ) return; QLineEdit* lineEdit = qobject_cast( m_editableFormWidget ); if ( lineEdit && !lineEdit->isReadOnly() ) lineEdit->cut(); QTextEdit* textEdit = qobject_cast( m_editableFormWidget ); if ( textEdit && !textEdit->isReadOnly() ) textEdit->cut(); } void KHTMLPartBrowserExtension::copy() { if ( m_extensionProxy ) { callExtensionProxyMethod( "copy" ); return; } if ( !m_editableFormWidget ) { // get selected text and paste to the clipboard QString text = m_part->selectedText(); text.replace( QChar( 0xa0 ), ' ' ); //kDebug(6050) << text; QClipboard *cb = QApplication::clipboard(); disconnect( cb, SIGNAL(selectionChanged()), m_part, SLOT(slotClearSelection()) ); QString htmltext; /* * When selectionModeEnabled, that means the user has just selected * the text, not ctrl+c to copy it. The selection clipboard * doesn't seem to support mime type, so to save time, don't calculate * the selected text as html. * optomisation disabled for now until everything else works. */ //if(!cb->selectionModeEnabled()) htmltext = m_part->selectedTextAsHTML(); QMimeData *mimeData = new QMimeData; mimeData->setText(text); if(!htmltext.isEmpty()) { htmltext.replace( QChar( 0xa0 ), ' ' ); mimeData->setHtml(htmltext); } cb->setMimeData(mimeData); connect( cb, SIGNAL(selectionChanged()), m_part, SLOT(slotClearSelection()) ); } else { QLineEdit* lineEdit = qobject_cast( m_editableFormWidget ); if ( lineEdit ) lineEdit->copy(); QTextEdit* textEdit = qobject_cast( m_editableFormWidget ); if ( textEdit ) textEdit->copy(); } } void KHTMLPartBrowserExtension::searchProvider() { KAction *action = qobject_cast(sender()); if (action) { KUrl url = action->data().toUrl(); if (url.host().isEmpty()) { KUriFilterData data(action->data().toString()); if (KUriFilter::self()->filterSearchUri(data, KUriFilter::WebShortcutFilter)) url = data.uri(); } KParts::BrowserArguments browserArgs; browserArgs.frameName = "_blank"; emit m_part->browserExtension()->openUrlRequest( url, KParts::OpenUrlArguments(), browserArgs ); } } void KHTMLPartBrowserExtension::paste() { if ( m_extensionProxy ) { callExtensionProxyMethod( "paste" ); return; } if ( !m_editableFormWidget ) return; QLineEdit* lineEdit = qobject_cast( m_editableFormWidget ); if ( lineEdit && !lineEdit->isReadOnly() ) lineEdit->paste(); QTextEdit* textEdit = qobject_cast( m_editableFormWidget ); if ( textEdit && !textEdit->isReadOnly() ) textEdit->paste(); } void KHTMLPartBrowserExtension::callExtensionProxyMethod( const char *method ) { if ( !m_extensionProxy ) return; QMetaObject::invokeMethod(m_extensionProxy, method, Qt::DirectConnection); } void KHTMLPartBrowserExtension::updateEditActions() { if ( !m_editableFormWidget ) { enableAction( "cut", false ); enableAction( "copy", false ); enableAction( "paste", false ); return; } // ### duplicated from KonqMainWindow::slotClipboardDataChanged const QMimeData *data = QApplication::clipboard()->mimeData(); enableAction( "paste", data->hasFormat( "text/plain" ) ); bool hasSelection = false; if( m_editableFormWidget) { if ( qobject_cast(m_editableFormWidget)) hasSelection = static_cast( &(*m_editableFormWidget) )->hasSelectedText(); else if(qobject_cast(m_editableFormWidget)) hasSelection = static_cast( &(*m_editableFormWidget) )->textCursor().hasSelection(); } enableAction( "copy", hasSelection ); enableAction( "cut", hasSelection ); } void KHTMLPartBrowserExtension::extensionProxyEditableWidgetFocused() { editableWidgetFocused(); } void KHTMLPartBrowserExtension::extensionProxyEditableWidgetBlurred() { editableWidgetBlurred(); } void KHTMLPartBrowserExtension::extensionProxyActionEnabled( const char *action, bool enable ) { // only forward enableAction calls for actions we actually do forward if ( strcmp( action, "cut" ) == 0 || strcmp( action, "copy" ) == 0 || strcmp( action, "paste" ) == 0 ) { enableAction( action, enable ); } } void KHTMLPartBrowserExtension::reparseConfiguration() { m_part->reparseConfiguration(); } void KHTMLPartBrowserExtension::print() { m_part->view()->print(); } void KHTMLPartBrowserExtension::disableScrolling() { QScrollArea *scrollArea = m_part->view(); if (scrollArea) { scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } } class KHTMLPopupGUIClient::KHTMLPopupGUIClientPrivate { public: KHTMLPart *m_khtml; KUrl m_url; KUrl m_imageURL; QPixmap m_pixmap; QString m_suggestedFilename; KActionCollection* m_actionCollection; KParts::BrowserExtension::ActionGroupMap actionGroups; }; KHTMLPopupGUIClient::KHTMLPopupGUIClient( KHTMLPart *khtml, const KUrl &url ) : QObject( khtml ), d(new KHTMLPopupGUIClientPrivate) { d->m_khtml = khtml; d->m_url = url; d->m_actionCollection = new KActionCollection(this); bool isImage = false; bool hasSelection = khtml->hasSelection(); DOM::Element e = khtml->nodeUnderMouse(); if ( !e.isNull() && (e.elementId() == ID_IMG || (e.elementId() == ID_INPUT && !static_cast(e).src().isEmpty()))) { if (e.elementId() == ID_IMG) { DOM::HTMLImageElementImpl *ie = static_cast(e.handle()); khtml::RenderImage *ri = dynamic_cast(ie->renderer()); if (ri && ri->contentObject()) { d->m_suggestedFilename = static_cast(ri->contentObject())->suggestedFilename(); } } isImage=true; } if (hasSelection) { QList editActions; QAction* copyAction = d->m_actionCollection->addAction( KStandardAction::Copy, "copy", d->m_khtml->browserExtension(), SLOT(copy()) ); copyAction->setText(i18n("&Copy Text")); copyAction->setEnabled(d->m_khtml->browserExtension()->isActionEnabled( "copy" )); editActions.append(copyAction); editActions.append(khtml->actionCollection()->action("selectAll")); addSearchActions(editActions); QString selectedTextURL = selectedTextAsOneLine(d->m_khtml); if ( selectedTextURL.contains("://") && KUrl(selectedTextURL).isValid() ) { if (selectedTextURL.length() > 18) { selectedTextURL.truncate(15); selectedTextURL += "..."; } KAction *action = new KAction(i18n("Open '%1'", selectedTextURL), this); d->m_actionCollection->addAction( "openSelection", action ); action->setIcon( KIcon( "window-new" ) ); connect( action, SIGNAL(triggered(bool)), this, SLOT(openSelection()) ); editActions.append(action); } KAction* separator = new KAction(d->m_actionCollection); separator->setSeparator(true); editActions.append(separator); d->actionGroups.insert("editactions", editActions); } if (!url.isEmpty()) { QList linkActions; if (url.protocol() == "mailto") { KAction *action = new KAction( i18n( "&Copy Email Address" ), this ); d->m_actionCollection->addAction( "copylinklocation", action ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotCopyLinkLocation()) ); linkActions.append(action); } else { KAction *action = new KAction( i18n( "&Save Link As..." ), this ); d->m_actionCollection->addAction( "savelinkas", action ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotSaveLinkAs()) ); linkActions.append(action); action = new KAction( i18n( "&Copy Link Address" ), this ); d->m_actionCollection->addAction( "copylinklocation", action ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotCopyLinkLocation()) ); linkActions.append(action); } d->actionGroups.insert("linkactions", linkActions); } QList partActions; // frameset? -> add "Reload Frame" etc. if (!hasSelection) { if ( khtml->parentPart() ) { KActionMenu* menu = new KActionMenu( i18nc("@title:menu HTML frame/iframe", "Frame"), this); KAction *action = new KAction( i18n( "Open in New &Window" ), this ); d->m_actionCollection->addAction( "frameinwindow", action ); action->setIcon( KIcon( "window-new" ) ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotFrameInWindow()) ); menu->addAction(action); action = new KAction( i18n( "Open in &This Window" ), this ); d->m_actionCollection->addAction( "frameintop", action ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotFrameInTop()) ); menu->addAction(action); action = new KAction( i18n( "Open in &New Tab" ), this ); d->m_actionCollection->addAction( "frameintab", action ); action->setIcon( KIcon( "tab-new" ) ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotFrameInTab()) ); menu->addAction(action); action = new KAction(d->m_actionCollection); action->setSeparator(true); menu->addAction(action); action = new KAction( i18n( "Reload Frame" ), this ); d->m_actionCollection->addAction( "reloadframe", action ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotReloadFrame()) ); menu->addAction(action); action = new KAction( i18n( "Print Frame..." ), this ); d->m_actionCollection->addAction( "printFrame", action ); action->setIcon( KIcon( "document-print-frame" ) ); connect( action, SIGNAL(triggered(bool)), d->m_khtml->browserExtension(), SLOT(print()) ); menu->addAction(action); action = new KAction( i18n( "Save &Frame As..." ), this ); d->m_actionCollection->addAction( "saveFrame", action ); connect( action, SIGNAL(triggered(bool)), d->m_khtml, SLOT(slotSaveFrame()) ); menu->addAction(action); action = new KAction( i18n( "View Frame Source" ), this ); d->m_actionCollection->addAction( "viewFrameSource", action ); connect( action, SIGNAL(triggered(bool)), d->m_khtml, SLOT(slotViewDocumentSource()) ); menu->addAction(action); action = new KAction( i18n( "View Frame Information" ), this ); d->m_actionCollection->addAction( "viewFrameInfo", action ); connect( action, SIGNAL(triggered(bool)), d->m_khtml, SLOT(slotViewPageInfo()) ); action = new KAction(d->m_actionCollection); action->setSeparator(true); menu->addAction(action); if ( KHTMLGlobal::defaultHTMLSettings()->isAdFilterEnabled() ) { if ( khtml->d->m_frame->m_type == khtml::ChildFrame::IFrame ) { action = new KAction( i18n( "Block IFrame..." ), this ); d->m_actionCollection->addAction( "blockiframe", action ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotBlockIFrame()) ); menu->addAction(action); } } partActions.append(menu); } } if (isImage) { if ( e.elementId() == ID_IMG ) { d->m_imageURL = KUrl( static_cast( e ).src().string() ); DOM::HTMLImageElementImpl *imageimpl = static_cast( e.handle() ); Q_ASSERT(imageimpl); if(imageimpl) // should be true always. right? { if(imageimpl->complete()) { d->m_pixmap = imageimpl->currentPixmap(); } } } else d->m_imageURL = KUrl( static_cast( e ).src().string() ); KAction *action = new KAction( i18n( "Save Image As..." ), this ); d->m_actionCollection->addAction( "saveimageas", action ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotSaveImageAs()) ); partActions.append(action); action = new KAction( i18n( "Send Image..." ), this ); d->m_actionCollection->addAction( "sendimage", action ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotSendImage()) ); partActions.append(action); action = new KAction( i18n( "Copy Image" ), this ); d->m_actionCollection->addAction( "copyimage", action ); action->setEnabled(!d->m_pixmap.isNull()); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotCopyImage()) ); partActions.append(action); if(d->m_pixmap.isNull()) { //fallback to image location if still loading the image. this will always be true if ifdef QT_NO_MIMECLIPBOARD action = new KAction( i18n( "Copy Image Location" ), this ); d->m_actionCollection->addAction( "copyimagelocation", action ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotCopyImageLocation()) ); partActions.append(action); } QString actionText = d->m_suggestedFilename.isEmpty() ? KStringHandler::csqueeze(d->m_imageURL.fileName()+d->m_imageURL.query(), 25) : d->m_suggestedFilename; action = new KAction( i18n("View Image (%1)", actionText.replace("&", "&&")), this ); d->m_actionCollection->addAction( "viewimage", action ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotViewImage()) ); partActions.append(action); if (KHTMLGlobal::defaultHTMLSettings()->isAdFilterEnabled()) { action = new KAction( i18n( "Block Image..." ), this ); d->m_actionCollection->addAction( "blockimage", action ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotBlockImage()) ); partActions.append(action); if (!d->m_imageURL.host().isEmpty() && !d->m_imageURL.protocol().isEmpty()) { action = new KAction( i18n( "Block Images From %1" , d->m_imageURL.host()), this ); d->m_actionCollection->addAction( "blockhost", action ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotBlockHost()) ); partActions.append(action); } } KAction* separator = new KAction(d->m_actionCollection); separator->setSeparator(true); partActions.append(separator); } if ( isImage || url.isEmpty() ) { KAction *action = new KAction( i18n( "Stop Animations" ), this ); d->m_actionCollection->addAction( "stopanimations", action ); connect( action, SIGNAL(triggered(bool)), this, SLOT(slotStopAnimations()) ); partActions.append(action); KAction* separator = new KAction(d->m_actionCollection); separator->setSeparator(true); partActions.append(separator); } if (!hasSelection && url.isEmpty()) { // only when right-clicking on the page itself partActions.append(khtml->actionCollection()->action("viewDocumentSource")); } if (!hasSelection && url.isEmpty() && !isImage) { partActions.append(khtml->actionCollection()->action("setEncoding")); } d->actionGroups.insert("partactions", partActions); } KHTMLPopupGUIClient::~KHTMLPopupGUIClient() { delete d->m_actionCollection; delete d; } void KHTMLPopupGUIClient::addSearchActions(QList& editActions) { QString selectedText = d->m_khtml->simplifiedSelectedText(); // replace linefeeds with spaces selectedText = selectedText.replace(QChar(10), QChar(32)).trimmed(); if (selectedText.isEmpty()) return; KUriFilterData data(selectedText); QStringList alternateProviders; alternateProviders << "google" << "google_groups" << "google_news" << "webster" << "dmoz" << "wikipedia"; data.setAlternateSearchProviders(alternateProviders); data.setAlternateDefaultSearchProvider("google"); if (KUriFilter::self()->filterSearchUri(data, KUriFilter::NormalTextFilter)) { const QString squeezedText = KStringHandler::rsqueeze(selectedText, 21); KAction *action = new KAction(i18n("Search for '%1' with %2", squeezedText, data.searchProvider()), this); action->setData(QUrl(data.uri())); action->setIcon(KIcon(data.iconName())); connect(action, SIGNAL(triggered(bool)), d->m_khtml->browserExtension(), SLOT(searchProvider())); d->m_actionCollection->addAction("defaultSearchProvider", action); editActions.append(action); const QStringList preferredSearchProviders = data.preferredSearchProviders(); if (!preferredSearchProviders.isEmpty()) { KActionMenu* providerList = new KActionMenu(i18n("Search for '%1' with", squeezedText), this); Q_FOREACH(const QString &searchProvider, preferredSearchProviders) { if (searchProvider == data.searchProvider()) continue; KAction *action = new KAction(searchProvider, this); action->setData(data.queryForPreferredSearchProvider(searchProvider)); d->m_actionCollection->addAction(searchProvider, action); action->setIcon(KIcon(data.iconNameForPreferredSearchProvider(searchProvider))); connect(action, SIGNAL(triggered(bool)), d->m_khtml->browserExtension(), SLOT(searchProvider())); providerList->addAction(action); } d->m_actionCollection->addAction("searchProviderList", providerList); editActions.append(providerList); } } } QString KHTMLPopupGUIClient::selectedTextAsOneLine(KHTMLPart* part) { QString text = part->simplifiedSelectedText(); // in addition to what simplifiedSelectedText does, // remove linefeeds and any whitespace surrounding it (#113177), // to get it all in a single line. text.remove(QRegExp("[\\s]*\\n+[\\s]*")); return text; } void KHTMLPopupGUIClient::openSelection() { KParts::BrowserArguments browserArgs; browserArgs.frameName = "_blank"; emit d->m_khtml->browserExtension()->openUrlRequest(selectedTextAsOneLine(d->m_khtml), KParts::OpenUrlArguments(), browserArgs); } KParts::BrowserExtension::ActionGroupMap KHTMLPopupGUIClient::actionGroups() const { return d->actionGroups; } void KHTMLPopupGUIClient::slotSaveLinkAs() { KIO::MetaData metaData; metaData["referrer"] = d->m_khtml->referrer(); saveURL( d->m_khtml->widget(), i18n( "Save Link As" ), d->m_url, metaData ); } void KHTMLPopupGUIClient::slotSendImage() { QStringList urls; urls.append( d->m_imageURL.url()); QString subject = d->m_imageURL.url(); KToolInvocation::invokeMailer(QString(), QString(), QString(), subject, QString(), //body QString(), urls); // attachments } void KHTMLPopupGUIClient::slotSaveImageAs() { KIO::MetaData metaData; metaData["referrer"] = d->m_khtml->referrer(); saveURL( d->m_khtml->widget(), i18n( "Save Image As" ), d->m_imageURL, metaData, QString(), d->m_suggestedFilename ); } void KHTMLPopupGUIClient::slotBlockHost() { QString name=d->m_imageURL.protocol()+"://"+d->m_imageURL.host()+"/*"; KHTMLGlobal::defaultHTMLSettings()->addAdFilter( name ); d->m_khtml->reparseConfiguration(); } void KHTMLPopupGUIClient::slotBlockImage() { bool ok = false; QString url = KInputDialog::getText( i18n("Add URL to Filter"), i18n("Enter the URL:"), d->m_imageURL.url(), &ok); if ( ok ) { KHTMLGlobal::defaultHTMLSettings()->addAdFilter( url ); d->m_khtml->reparseConfiguration(); } } void KHTMLPopupGUIClient::slotBlockIFrame() { bool ok = false; QString url = KInputDialog::getText( i18n( "Add URL to Filter"), i18n("Enter the URL:"), d->m_khtml->url().url(), &ok ); if ( ok ) { KHTMLGlobal::defaultHTMLSettings()->addAdFilter( url ); d->m_khtml->reparseConfiguration(); } } void KHTMLPopupGUIClient::slotCopyLinkLocation() { KUrl safeURL(d->m_url); safeURL.setPass(QString()); // Set it in both the mouse selection and in the clipboard QMimeData* mimeData = new QMimeData; safeURL.populateMimeData( mimeData ); QApplication::clipboard()->setMimeData( mimeData, QClipboard::Clipboard ); mimeData = new QMimeData; safeURL.populateMimeData( mimeData ); QApplication::clipboard()->setMimeData( mimeData, QClipboard::Selection ); } void KHTMLPopupGUIClient::slotStopAnimations() { d->m_khtml->stopAnimations(); } void KHTMLPopupGUIClient::slotCopyImage() { KUrl safeURL(d->m_imageURL); safeURL.setPass(QString()); // Set it in both the mouse selection and in the clipboard QMimeData* mimeData = new QMimeData; mimeData->setImageData( d->m_pixmap ); safeURL.populateMimeData( mimeData ); QApplication::clipboard()->setMimeData( mimeData, QClipboard::Clipboard ); mimeData = new QMimeData; mimeData->setImageData( d->m_pixmap ); safeURL.populateMimeData( mimeData ); QApplication::clipboard()->setMimeData( mimeData, QClipboard::Selection ); } void KHTMLPopupGUIClient::slotCopyImageLocation() { KUrl safeURL(d->m_imageURL); safeURL.setPass(QString()); // Set it in both the mouse selection and in the clipboard QMimeData* mimeData = new QMimeData; safeURL.populateMimeData( mimeData ); QApplication::clipboard()->setMimeData( mimeData, QClipboard::Clipboard ); mimeData = new QMimeData; safeURL.populateMimeData( mimeData ); QApplication::clipboard()->setMimeData( mimeData, QClipboard::Selection ); } void KHTMLPopupGUIClient::slotViewImage() { d->m_khtml->browserExtension()->createNewWindow(d->m_imageURL); } void KHTMLPopupGUIClient::slotReloadFrame() { KParts::OpenUrlArguments args = d->m_khtml->arguments(); args.setReload( true ); args.metaData()["referrer"] = d->m_khtml->pageReferrer(); // reload document d->m_khtml->closeUrl(); d->m_khtml->setArguments( args ); d->m_khtml->openUrl( d->m_khtml->url() ); } void KHTMLPopupGUIClient::slotFrameInWindow() { KParts::OpenUrlArguments args = d->m_khtml->arguments(); args.metaData()["referrer"] = d->m_khtml->pageReferrer(); KParts::BrowserArguments browserArgs( d->m_khtml->browserExtension()->browserArguments() ); browserArgs.setForcesNewWindow(true); emit d->m_khtml->browserExtension()->createNewWindow( d->m_khtml->url(), args, browserArgs ); } void KHTMLPopupGUIClient::slotFrameInTop() { KParts::OpenUrlArguments args = d->m_khtml->arguments(); args.metaData()["referrer"] = d->m_khtml->pageReferrer(); KParts::BrowserArguments browserArgs( d->m_khtml->browserExtension()->browserArguments() ); browserArgs.frameName = "_top"; emit d->m_khtml->browserExtension()->openUrlRequest( d->m_khtml->url(), args, browserArgs ); } void KHTMLPopupGUIClient::slotFrameInTab() { KParts::OpenUrlArguments args = d->m_khtml->arguments(); args.metaData()["referrer"] = d->m_khtml->pageReferrer(); KParts::BrowserArguments browserArgs( d->m_khtml->browserExtension()->browserArguments() ); browserArgs.setNewTab(true); emit d->m_khtml->browserExtension()->createNewWindow( d->m_khtml->url(), args, browserArgs ); } void KHTMLPopupGUIClient::saveURL( QWidget *parent, const QString &caption, const KUrl &url, const QMap &metadata, const QString &filter, const QString & suggestedFilename ) { QString name = QLatin1String( "index.html" ); if ( !suggestedFilename.isEmpty() ) name = suggestedFilename; else if ( !url.fileName(KUrl::ObeyTrailingSlash).isEmpty() ) name = url.fileName(KUrl::ObeyTrailingSlash); KUrl destURL; int query; do { query = KMessageBox::Yes; // convert filename to URL using fromPath to avoid trouble with ':' in filenames (#184202) destURL = KFileDialog::getSaveUrl( KUrl::fromPath(name), filter, parent, caption ); if( destURL.isLocalFile() ) { QFileInfo info( destURL.toLocalFile() ); if( info.exists() ) { // TODO: use KIO::RenameDlg (shows more information) 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" )) ); } } } while ( query == KMessageBox::Cancel ); if ( destURL.isValid() ) saveURL(parent, url, destURL, metadata); } void KHTMLPopupGUIClient::saveURL( QWidget* parent, const KUrl &url, const KUrl &destURL, const QMap &metadata ) { if ( destURL.isValid() ) { // DownloadManager <-> konqueror integration // find if the integration is enabled // the empty key means no integration // only use download manager for non-local urls! KConfigGroup cfg = KSharedConfig::openConfig("konquerorrc", KConfig::NoGlobals)->group("HTML Settings"); QString downloadManger = cfg.readPathEntry("DownloadManager", QString()); if (!url.isLocalFile() && !downloadManger.isEmpty()) { // then find the download manager location QString cmd = KStandardDirs::findExe(downloadManger); kDebug(1000) << "Using: " << cmd << " as Download Manager"; if (cmd.isEmpty()) { QString errMsg=i18n("The Download Manager (%1) could not be found in your $PATH ", downloadManger); QString errMsgEx= i18n("Try to reinstall it \n\nThe integration with Konqueror will be disabled."); KMessageBox::detailedSorry(0,errMsg,errMsgEx); cfg.writePathEntry("DownloadManager",QString()); cfg.sync (); } else { KUrl cleanDest = destURL; cleanDest.setPass( QString() ); // don't put password into commandline cmd += ' ' + KShell::quoteArg(url.url()) + ' ' + KShell::quoteArg(cleanDest.url()); kDebug(1000) << "Calling command "<topLevelWidget()); } } else { KParts::BrowserRun::saveUrlUsingKIO(url, destURL, parent, metadata); } } } KHTMLPartBrowserHostExtension::KHTMLPartBrowserHostExtension( KHTMLPart *part ) : KParts::BrowserHostExtension( part ) { m_part = part; } KHTMLPartBrowserHostExtension::~KHTMLPartBrowserHostExtension() { } QStringList KHTMLPartBrowserHostExtension::frameNames() const { return m_part->frameNames(); } const QList KHTMLPartBrowserHostExtension::frames() const { return m_part->frames(); } bool KHTMLPartBrowserHostExtension::openUrlInFrame(const KUrl &url, const KParts::OpenUrlArguments& arguments, const KParts::BrowserArguments &browserArguments) { return m_part->openUrlInFrame( url, arguments, browserArguments ); } KParts::BrowserHostExtension* KHTMLPartBrowserHostExtension::findFrameParent( KParts::ReadOnlyPart *callingPart, const QString &frame ) { KHTMLPart *parentPart = m_part->d->findFrameParent(callingPart, frame, 0, true /* navigation*/); if (parentPart) return parentPart->browserHostExtension(); return 0; } // defined in khtml_part.cpp extern const int KDE_NO_EXPORT fastZoomSizes[]; extern const int KDE_NO_EXPORT fastZoomSizeCount; KHTMLZoomFactorAction::KHTMLZoomFactorAction( KHTMLPart *part, bool direction, const QString &icon, const QString &text, QObject *parent ) : KSelectAction( text, parent ) { setIcon( KIcon( icon ) ); setToolBarMode(MenuMode); setToolButtonPopupMode(QToolButton::DelayedPopup); init(part, direction); } void KHTMLZoomFactorAction::init(KHTMLPart *part, bool direction) { m_direction = direction; m_part = part; // xgettext: no-c-format addAction( i18n( "Default Font Size (100%)" ) ); int m = m_direction ? 1 : -1; int ofs = fastZoomSizeCount / 2; // take index of 100% // this only works if there is an odd number of elements in fastZoomSizes[] for ( int i = m; i != m*(ofs+1); i += m ) { int num = i * m; QString numStr = QString::number( num ); if ( num > 0 ) numStr.prepend( QLatin1Char('+') ); // xgettext: no-c-format addAction( i18n( "%1%" , fastZoomSizes[ofs + i] ) ); } connect( selectableActionGroup(), SIGNAL(triggered(QAction*)), this, SLOT(slotTriggered(QAction*)) ); } KHTMLZoomFactorAction::~KHTMLZoomFactorAction() { } void KHTMLZoomFactorAction::slotTriggered(QAction* action) { int idx = selectableActionGroup()->actions().indexOf(action); if (idx == 0) m_part->setFontScaleFactor(100); else m_part->setFontScaleFactor(fastZoomSizes[fastZoomSizeCount/2 + (m_direction ? 1 : -1)*idx]); setCurrentAction( 0L ); } KHTMLTextExtension::KHTMLTextExtension(KHTMLPart* part) : KParts::TextExtension(part) { connect(part, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged())); } KHTMLPart* KHTMLTextExtension::part() const { return static_cast(parent()); } bool KHTMLTextExtension::hasSelection() const { return part()->hasSelection(); } QString KHTMLTextExtension::selectedText(Format format) const { switch(format) { case PlainText: return part()->selectedText(); case HTML: return part()->selectedTextAsHTML(); } return QString(); } QString KHTMLTextExtension::completeText(Format format) const { switch(format) { case PlainText: return part()->htmlDocument().body().innerText().string(); case HTML: return part()->htmlDocument().body().innerHTML().string(); } return QString(); } //// KHTMLHtmlExtension::KHTMLHtmlExtension(KHTMLPart* part) : KParts::HtmlExtension(part) { } KUrl KHTMLHtmlExtension::baseUrl() const { return part()->baseURL(); } bool KHTMLHtmlExtension::hasSelection() const { return part()->hasSelection(); } KParts::SelectorInterface::QueryMethods KHTMLHtmlExtension::supportedQueryMethods() const { return (KParts::SelectorInterface::SelectedContent | KParts::SelectorInterface::EntireContent); } static KParts::SelectorInterface::Element convertDomElement(const DOM::ElementImpl* domElem) { KParts::SelectorInterface::Element elem; elem.setTagName(domElem->tagName().string()); const DOM::NamedAttrMapImpl* attrMap = domElem->attributes(true /*readonly*/); if (attrMap) { for (unsigned i = 0; i < attrMap->length(); ++i) { const DOM::AttributeImpl& attr = attrMap->attributeAt(i); elem.setAttribute(attr.localName().string(), attr.value().string()); // we could have a setAttributeNS too. } } return elem; } KParts::SelectorInterface::Element KHTMLHtmlExtension::querySelector(const QString& query, KParts::SelectorInterface::QueryMethod method) const { KParts::SelectorInterface::Element element; // If the specified method is None, return an empty list; similarly // if the document is null, which may be possible in case of an error if (method == KParts::SelectorInterface::None || part()->document().isNull()) return element; if (!(supportedQueryMethods() & method)) return element; switch (method) { case KParts::SelectorInterface::EntireContent: { int ec = 0; // exceptions are ignored WTF::RefPtr domElem = part()->document().handle()->querySelector(query, ec); element = convertDomElement(domElem.get()); break; } case KParts::SelectorInterface::SelectedContent: if (part()->hasSelection()) { DOM::Element domElem = part()->selection().cloneContents().querySelector(query); element = convertDomElement(static_cast(domElem.handle())); } break; default: break; } return element; } QList KHTMLHtmlExtension::querySelectorAll(const QString& query, KParts::SelectorInterface::QueryMethod method) const { QList elements; // If the specified method is None, return an empty list; similarly // if the document is null, which may be possible in case of an error if (method == KParts::SelectorInterface::None || part()->document().isNull()) return elements; // If the specified method is not supported, return an empty list... if (!(supportedQueryMethods() & method)) return elements; switch (method) { case KParts::SelectorInterface::EntireContent: { int ec = 0; // exceptions are ignored WTF::RefPtr nodes = part()->document().handle()->querySelectorAll(query, ec); const unsigned long len = nodes->length(); elements.reserve(len); for (unsigned long i = 0; i < len; ++i) { DOM::NodeImpl* node = nodes->item(i); if (node->isElementNode()) { // should be always true elements.append(convertDomElement(static_cast(node))); } } break; } case KParts::SelectorInterface::SelectedContent: if (part()->hasSelection()) { DOM::NodeList nodes = part()->selection().cloneContents().querySelectorAll(query); const unsigned long len = nodes.length(); for (unsigned long i = 0; i < len; ++i) { DOM::NodeImpl* node = nodes.item(i).handle(); if (node->isElementNode()) elements.append(convertDomElement(static_cast(node))); } } break; default: break; } return elements; } QVariant KHTMLHtmlExtension::htmlSettingsProperty(HtmlSettingsInterface::HtmlSettingsType type) const { if (part()) { switch (type) { case KParts::HtmlSettingsInterface::AutoLoadImages: return part()->autoloadImages(); case KParts::HtmlSettingsInterface::DnsPrefetchEnabled: return (part()->dnsPrefetch() == KHTMLPart::DNSPrefetchEnabled); case KParts::HtmlSettingsInterface::JavaEnabled: return part()->javaEnabled(); case KParts::HtmlSettingsInterface::JavascriptEnabled: return part()->jScriptEnabled(); case KParts::HtmlSettingsInterface::MetaRefreshEnabled: return part()->metaRefreshEnabled(); case KParts::HtmlSettingsInterface::PluginsEnabled: return part()->pluginsEnabled(); default: break; } } return QVariant(); } bool KHTMLHtmlExtension::setHtmlSettingsProperty(HtmlSettingsInterface::HtmlSettingsType type, const QVariant& value) { KHTMLPart* p = part(); if (p) { switch (type) { case KParts::HtmlSettingsInterface::AutoLoadImages: p->setAutoloadImages(value.toBool()); return true; case KParts::HtmlSettingsInterface::DnsPrefetchEnabled: p->setDNSPrefetch((value.toBool() ? KHTMLPart::DNSPrefetchEnabled : KHTMLPart::DNSPrefetchDisabled)); return true; case KParts::HtmlSettingsInterface::JavaEnabled: p->setJavaEnabled(value.toBool()); return true; case KParts::HtmlSettingsInterface::JavascriptEnabled: p->setJScriptEnabled(value.toBool()); return true; case KParts::HtmlSettingsInterface::MetaRefreshEnabled: p->setMetaRefreshEnabled(value.toBool()); return true; case KParts::HtmlSettingsInterface::PluginsEnabled: p->setPluginsEnabled(value.toBool()); return true; case KParts::HtmlSettingsInterface::UserDefinedStyleSheetURL: { const KUrl url (value.toUrl()); if (url.protocol() == QLatin1String("data")) { const QByteArray data (url.encodedPath()); if (!data.isEmpty()) { const int index = data.indexOf(','); const QByteArray decodedData ((index > -1 ? QByteArray::fromBase64(data.mid(index)) : QByteArray())); p->setUserStyleSheet(QString::fromUtf8(decodedData.constData(), decodedData.size())); } } else { p->setUserStyleSheet(url); } return true; } default: break; // Unsupported property... } } return false; } KHTMLPart* KHTMLHtmlExtension::part() const { return static_cast(parent()); } #include "moc_khtml_ext.cpp"