khtml_ext.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /* This file is part of the KDE project
00003  *
00004  * Copyright (C) 2000-2003 Simon Hausmann <hausmann@kde.org>
00005  *               2001-2003 George Staikos <staikos@kde.org>
00006  *               2001-2003 Laurent Montel <montel@kde.org>
00007  *               2001-2003 Dirk Mueller <mueller@kde.org>
00008  *               2001-2003 Waldo Bastian <bastian@kde.org>
00009  *               2001-2003 David Faure <faure@kde.org>
00010  *               2001-2003 Daniel Naber <dnaber@kde.org>
00011  *
00012  * This library is free software; you can redistribute it and/or
00013  * modify it under the terms of the GNU Library General Public
00014  * License as published by the Free Software Foundation; either
00015  * version 2 of the License, or (at your option) any later version.
00016  *
00017  * This library is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020  * Library General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU Library General Public License
00023  * along with this library; see the file COPYING.LIB.  If not, write to
00024  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00025  * Boston, MA 02110-1301, USA.
00026  */
00027 
00028 #include <assert.h>
00029 #include "khtml_ext.h"
00030 #include "khtmlview.h"
00031 #include "khtml_pagecache.h"
00032 #include "rendering/render_form.h"
00033 #include "rendering/render_image.h"
00034 #include "html/html_imageimpl.h"
00035 #include "misc/loader.h"
00036 #include "dom/html_form.h"
00037 #include "dom/html_image.h"
00038 #include <qclipboard.h>
00039 #include <qfileinfo.h>
00040 #include <qpopupmenu.h>
00041 #include <qmetaobject.h>
00042 #include <private/qucomextra_p.h>
00043 #include <qdragobject.h>
00044 
00045 #include <kdebug.h>
00046 #include <klocale.h>
00047 #include <kfiledialog.h>
00048 #include <kio/job.h>
00049 #include <kprocess.h>
00050 #include <ktoolbarbutton.h>
00051 #include <ktoolbar.h>
00052 #include <ksavefile.h>
00053 #include <kurldrag.h>
00054 #include <kstringhandler.h>
00055 #include <kapplication.h>
00056 #include <kmessagebox.h>
00057 #include <kstandarddirs.h>
00058 #include <krun.h>
00059 #include <kurifilter.h>
00060 #include <kiconloader.h>
00061 #include <kdesktopfile.h>
00062 #include <kmultipledrag.h>
00063 #include <kinputdialog.h>
00064 
00065 #include "khtml_factory.h"
00066 
00067 #include "dom/dom_element.h"
00068 #include "misc/htmltags.h"
00069 
00070 #include "khtmlpart_p.h"
00071 
00072 KHTMLPartBrowserExtension::KHTMLPartBrowserExtension( KHTMLPart *parent, const char *name )
00073 : KParts::BrowserExtension( parent, name )
00074 {
00075     m_part = parent;
00076     setURLDropHandlingEnabled( true );
00077 
00078     enableAction( "cut", false );
00079     enableAction( "copy", false );
00080     enableAction( "paste", false );
00081 
00082     m_connectedToClipboard = false;
00083 }
00084 
00085 int KHTMLPartBrowserExtension::xOffset()
00086 {
00087     return m_part->view()->contentsX();
00088 }
00089 
00090 int KHTMLPartBrowserExtension::yOffset()
00091 {
00092   return m_part->view()->contentsY();
00093 }
00094 
00095 void KHTMLPartBrowserExtension::saveState( QDataStream &stream )
00096 {
00097   //kdDebug( 6050 ) << "saveState!" << endl;
00098   m_part->saveState( stream );
00099 }
00100 
00101 void KHTMLPartBrowserExtension::restoreState( QDataStream &stream )
00102 {
00103   //kdDebug( 6050 ) << "restoreState!" << endl;
00104   m_part->restoreState( stream );
00105 }
00106 
00107 void KHTMLPartBrowserExtension::editableWidgetFocused( QWidget *widget )
00108 {
00109     m_editableFormWidget = widget;
00110     updateEditActions();
00111 
00112     if ( !m_connectedToClipboard && m_editableFormWidget )
00113     {
00114         connect( QApplication::clipboard(), SIGNAL( dataChanged() ),
00115                  this, SLOT( updateEditActions() ) );
00116 
00117         if ( m_editableFormWidget->inherits( "QLineEdit" ) || m_editableFormWidget->inherits( "QTextEdit" ) )
00118             connect( m_editableFormWidget, SIGNAL( selectionChanged() ),
00119                      this, SLOT( updateEditActions() ) );
00120 
00121         m_connectedToClipboard = true;
00122     }
00123     editableWidgetFocused();
00124 }
00125 
00126 void KHTMLPartBrowserExtension::editableWidgetBlurred( QWidget * /*widget*/ )
00127 {
00128     QWidget *oldWidget = m_editableFormWidget;
00129 
00130     m_editableFormWidget = 0;
00131     enableAction( "cut", false );
00132     enableAction( "paste", false );
00133     m_part->emitSelectionChanged();
00134 
00135     if ( m_connectedToClipboard )
00136     {
00137         disconnect( QApplication::clipboard(), SIGNAL( dataChanged() ),
00138                     this, SLOT( updateEditActions() ) );
00139 
00140         if ( oldWidget )
00141         {
00142             if ( oldWidget->inherits( "QLineEdit" ) || oldWidget->inherits( "QTextEdit" ) )
00143                 disconnect( oldWidget, SIGNAL( selectionChanged() ),
00144                             this, SLOT( updateEditActions() ) );
00145         }
00146 
00147         m_connectedToClipboard = false;
00148     }
00149     editableWidgetBlurred();
00150 }
00151 
00152 void KHTMLPartBrowserExtension::setExtensionProxy( KParts::BrowserExtension *proxy )
00153 {
00154     if ( m_extensionProxy )
00155     {
00156         disconnect( m_extensionProxy, SIGNAL( enableAction( const char *, bool ) ),
00157                     this, SLOT( extensionProxyActionEnabled( const char *, bool ) ) );
00158         if ( m_extensionProxy->inherits( "KHTMLPartBrowserExtension" ) )
00159         {
00160             disconnect( m_extensionProxy, SIGNAL( editableWidgetFocused() ),
00161                         this, SLOT( extensionProxyEditableWidgetFocused() ) );
00162             disconnect( m_extensionProxy, SIGNAL( editableWidgetBlurred() ),
00163                         this, SLOT( extensionProxyEditableWidgetBlurred() ) );
00164         }
00165     }
00166 
00167     m_extensionProxy = proxy;
00168 
00169     if ( m_extensionProxy )
00170     {
00171         connect( m_extensionProxy, SIGNAL( enableAction( const char *, bool ) ),
00172                  this, SLOT( extensionProxyActionEnabled( const char *, bool ) ) );
00173         if ( m_extensionProxy->inherits( "KHTMLPartBrowserExtension" ) )
00174         {
00175             connect( m_extensionProxy, SIGNAL( editableWidgetFocused() ),
00176                      this, SLOT( extensionProxyEditableWidgetFocused() ) );
00177             connect( m_extensionProxy, SIGNAL( editableWidgetBlurred() ),
00178                      this, SLOT( extensionProxyEditableWidgetBlurred() ) );
00179         }
00180 
00181         enableAction( "cut", m_extensionProxy->isActionEnabled( "cut" ) );
00182         enableAction( "copy", m_extensionProxy->isActionEnabled( "copy" ) );
00183         enableAction( "paste", m_extensionProxy->isActionEnabled( "paste" ) );
00184     }
00185     else
00186     {
00187         updateEditActions();
00188         enableAction( "copy", false ); // ### re-check this
00189     }
00190 }
00191 
00192 void KHTMLPartBrowserExtension::cut()
00193 {
00194     if ( m_extensionProxy )
00195     {
00196         callExtensionProxyMethod( "cut()" );
00197         return;
00198     }
00199 
00200     if ( !m_editableFormWidget )
00201         return;
00202 
00203     if ( m_editableFormWidget->inherits( "QLineEdit" ) )
00204         static_cast<QLineEdit *>( &(*m_editableFormWidget) )->cut();
00205     else if ( m_editableFormWidget->inherits( "QTextEdit" ) )
00206         static_cast<QTextEdit *>( &(*m_editableFormWidget) )->cut();
00207 }
00208 
00209 void KHTMLPartBrowserExtension::copy()
00210 {
00211     if ( m_extensionProxy )
00212     {
00213         callExtensionProxyMethod( "copy()" );
00214         return;
00215     }
00216 
00217     kdDebug( 6050 ) << "************! KHTMLPartBrowserExtension::copy()" << endl;
00218     if ( !m_editableFormWidget )
00219     {
00220         // get selected text and paste to the clipboard
00221         QString text= m_part->selectedText();
00222     text.replace( QChar( 0xa0 ), ' ' );
00223 
00224 
00225         QClipboard *cb = QApplication::clipboard();
00226         disconnect( cb, SIGNAL( selectionChanged() ), m_part, SLOT( slotClearSelection() ) );
00227 #ifndef QT_NO_MIMECLIPBOARD
00228     QString htmltext;
00229     /*
00230      * When selectionModeEnabled, that means the user has just selected
00231      * the text, not ctrl+c to copy it.  The selection clipboard
00232      * doesn't seem to support mime type, so to save time, don't calculate
00233      * the selected text as html.
00234      * optomisation disabled for now until everything else works.
00235     */
00236     //if(!cb->selectionModeEnabled())
00237         htmltext = m_part->selectedTextAsHTML();
00238     QTextDrag *textdrag = new QTextDrag(text, 0L);
00239     KMultipleDrag *drag = new KMultipleDrag( m_editableFormWidget );
00240     drag->addDragObject( textdrag );
00241     if(!htmltext.isEmpty()) {
00242         htmltext.replace( QChar( 0xa0 ), ' ' );
00243         QTextDrag *htmltextdrag = new QTextDrag(htmltext, 0L);
00244         htmltextdrag->setSubtype("html");
00245         drag->addDragObject( htmltextdrag );
00246     }
00247         cb->setData(drag);
00248 #else
00249     cb->setText(text);
00250 #endif
00251 
00252         connect( cb, SIGNAL( selectionChanged() ), m_part, SLOT( slotClearSelection() ) );
00253     }
00254     else
00255     {
00256         if ( m_editableFormWidget->inherits( "QLineEdit" ) )
00257             static_cast<QLineEdit *>( &(*m_editableFormWidget) )->copy();
00258         else if ( m_editableFormWidget->inherits( "QTextEdit" ) )
00259             static_cast<QTextEdit *>( &(*m_editableFormWidget) )->copy();
00260     }
00261 }
00262 
00263 void KHTMLPartBrowserExtension::searchProvider()
00264 {
00265     // action name is of form "previewProvider[<searchproviderprefix>:]"
00266     const QString searchProviderPrefix = QString( sender()->name() ).mid( 14 );
00267 
00268     KURIFilterData data;
00269     QStringList list;
00270     data.setData( searchProviderPrefix + m_part->selectedText() );
00271     list << "kurisearchfilter" << "kuriikwsfilter";
00272 
00273     if( !KURIFilter::self()->filterURI(data, list) )
00274     {
00275         KDesktopFile file("searchproviders/google.desktop", true, "services");
00276         data.setData(file.readEntry("Query").replace("\\{@}", m_part->selectedText()));
00277     }
00278 
00279     KParts::URLArgs args;
00280     args.frameName = "_blank";
00281 
00282     emit m_part->browserExtension()->openURLRequest( data.uri(), args );
00283 }
00284 
00285 void KHTMLPartBrowserExtension::openSelection()
00286 {
00287     KParts::URLArgs args;
00288     args.frameName = "_blank";
00289 
00290     emit m_part->browserExtension()->openURLRequest( m_part->selectedText(), args );
00291 }
00292 
00293 void KHTMLPartBrowserExtension::paste()
00294 {
00295     if ( m_extensionProxy )
00296     {
00297         callExtensionProxyMethod( "paste()" );
00298         return;
00299     }
00300 
00301     if ( !m_editableFormWidget )
00302         return;
00303 
00304     if ( m_editableFormWidget->inherits( "QLineEdit" ) )
00305         static_cast<QLineEdit *>( &(*m_editableFormWidget) )->paste();
00306     else if ( m_editableFormWidget->inherits( "QTextEdit" ) )
00307         static_cast<QTextEdit *>( &(*m_editableFormWidget) )->paste();
00308 }
00309 
00310 void KHTMLPartBrowserExtension::callExtensionProxyMethod( const char *method )
00311 {
00312     if ( !m_extensionProxy )
00313         return;
00314 
00315     int slot = m_extensionProxy->metaObject()->findSlot( method );
00316     if ( slot == -1 )
00317         return;
00318 
00319     QUObject o[ 1 ];
00320     m_extensionProxy->qt_invoke( slot, o );
00321 }
00322 
00323 void KHTMLPartBrowserExtension::updateEditActions()
00324 {
00325     if ( !m_editableFormWidget )
00326     {
00327         enableAction( "cut", false );
00328         enableAction( "copy", false );
00329         enableAction( "paste", false );
00330         return;
00331     }
00332 
00333     // ### duplicated from KonqMainWindow::slotClipboardDataChanged
00334 #ifndef QT_NO_MIMECLIPBOARD // Handle minimalized versions of Qt Embedded
00335     QMimeSource *data = QApplication::clipboard()->data();
00336     enableAction( "paste", data->provides( "text/plain" ) );
00337 #else
00338     QString data=QApplication::clipboard()->text();
00339     enableAction( "paste", data.contains("://"));
00340 #endif
00341     bool hasSelection = false;
00342 
00343     if( m_editableFormWidget) {
00344         if ( ::qt_cast<QLineEdit*>(m_editableFormWidget))
00345             hasSelection = static_cast<QLineEdit *>( &(*m_editableFormWidget) )->hasSelectedText();
00346         else if(::qt_cast<QTextEdit*>(m_editableFormWidget))
00347             hasSelection = static_cast<QTextEdit *>( &(*m_editableFormWidget) )->hasSelectedText();
00348     }
00349 
00350     enableAction( "copy", hasSelection );
00351     enableAction( "cut", hasSelection );
00352 }
00353 
00354 void KHTMLPartBrowserExtension::extensionProxyEditableWidgetFocused() {
00355     editableWidgetFocused();
00356 }
00357 
00358 void KHTMLPartBrowserExtension::extensionProxyEditableWidgetBlurred() {
00359     editableWidgetBlurred();
00360 }
00361 
00362 void KHTMLPartBrowserExtension::extensionProxyActionEnabled( const char *action, bool enable )
00363 {
00364     // only forward enableAction calls for actions we actually do forward
00365     if ( strcmp( action, "cut" ) == 0 ||
00366          strcmp( action, "copy" ) == 0 ||
00367          strcmp( action, "paste" ) == 0 ) {
00368         enableAction( action, enable );
00369     }
00370 }
00371 
00372 void KHTMLPartBrowserExtension::reparseConfiguration()
00373 {
00374   m_part->reparseConfiguration();
00375 }
00376 
00377 void KHTMLPartBrowserExtension::print()
00378 {
00379   m_part->view()->print();
00380 }
00381 
00382 void KHTMLPartBrowserExtension::disableScrolling()
00383 {
00384   QScrollView *scrollView = m_part->view();
00385   if (scrollView) {
00386     scrollView->setVScrollBarMode(QScrollView::AlwaysOff);
00387     scrollView->setHScrollBarMode(QScrollView::AlwaysOff);
00388   }
00389 }
00390 
00391 class KHTMLPopupGUIClient::KHTMLPopupGUIClientPrivate
00392 {
00393 public:
00394   KHTMLPart *m_khtml;
00395   KURL m_url;
00396   KURL m_imageURL;
00397   QPixmap m_pixmap;
00398   QString m_suggestedFilename;
00399 };
00400 
00401 
00402 KHTMLPopupGUIClient::KHTMLPopupGUIClient( KHTMLPart *khtml, const QString &doc, const KURL &url )
00403   : QObject( khtml )
00404 {
00405   d = new KHTMLPopupGUIClientPrivate;
00406   d->m_khtml = khtml;
00407   d->m_url = url;
00408   bool isImage = false;
00409   bool hasSelection = khtml->hasSelection();
00410   setInstance( khtml->instance() );
00411 
00412   DOM::Element e;
00413   e = khtml->nodeUnderMouse();
00414 
00415   if ( !e.isNull() && (e.elementId() == ID_IMG ||
00416                        (e.elementId() == ID_INPUT && !static_cast<DOM::HTMLInputElement>(e).src().isEmpty())))
00417   {
00418     if (e.elementId() == ID_IMG) {
00419       DOM::HTMLImageElementImpl *ie = static_cast<DOM::HTMLImageElementImpl*>(e.handle());
00420       khtml::RenderImage *ri = dynamic_cast<khtml::RenderImage*>(ie->renderer());
00421       if (ri && ri->contentObject()) {
00422         d->m_suggestedFilename = static_cast<khtml::CachedImage*>(ri->contentObject())->suggestedFilename();
00423       }
00424     }
00425     isImage=true;
00426   }
00427 
00428   if (hasSelection)
00429   {
00430       KAction* copyAction = KStdAction::copy( d->m_khtml->browserExtension(), SLOT( copy() ), actionCollection(), "copy" );
00431       copyAction->setText(i18n("&Copy Text"));
00432       copyAction->setEnabled(d->m_khtml->browserExtension()->isActionEnabled( "copy" ));
00433       actionCollection()->insert( khtml->actionCollection()->action( "selectAll" ) );
00434 
00435 
00436       // Fill search provider entries
00437       KConfig config("kuriikwsfilterrc");
00438       config.setGroup("General");
00439       const QString defaultEngine = config.readEntry("DefaultSearchEngine", "google");
00440       const char keywordDelimiter = config.readNumEntry("KeywordDelimiter", ':');
00441 
00442       // search text
00443       QString selectedText = khtml->selectedText();
00444       if ( selectedText.length()>18 ) {
00445         selectedText.truncate(15);
00446         selectedText+="...";
00447       }
00448 
00449       // default search provider
00450       KService::Ptr service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(defaultEngine));
00451 
00452       // search provider icon
00453       QPixmap icon;
00454       KURIFilterData data;
00455       QStringList list;
00456       data.setData( QString("some keyword") );
00457       list << "kurisearchfilter" << "kuriikwsfilter";
00458 
00459       QString name;
00460       if ( KURIFilter::self()->filterURI(data, list) )
00461       {
00462         QString iconPath = locate("cache", KMimeType::favIconForURL(data.uri()) + ".png");
00463         if ( iconPath.isEmpty() )
00464           icon = SmallIcon("find");
00465         else
00466           icon = QPixmap( iconPath );
00467         name = service->name();
00468       }
00469       else
00470       {
00471         icon = SmallIcon("google");
00472         name = "Google";
00473       }
00474 
00475       new KAction( i18n( "Search '%1' at %2" ).arg( selectedText ).arg( name ), icon, 0, d->m_khtml->browserExtension(),
00476                      SLOT( searchProvider() ), actionCollection(), "searchProvider" );
00477 
00478       // favorite search providers
00479       QStringList favoriteEngines;
00480       favoriteEngines << "google" << "google_groups" << "google_news" << "webster" << "dmoz" << "wikipedia";
00481       favoriteEngines = config.readListEntry("FavoriteSearchEngines", favoriteEngines);
00482 
00483       if ( !favoriteEngines.isEmpty()) {
00484         KActionMenu* providerList = new KActionMenu( i18n( "Search '%1' At" ).arg( selectedText ), actionCollection(), "searchProviderList" );
00485 
00486         QStringList::ConstIterator it = favoriteEngines.begin();
00487         for ( ; it != favoriteEngines.end(); ++it ) {
00488           if (*it==defaultEngine)
00489             continue;
00490           service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(*it));
00491           if (!service)
00492             continue;
00493           const QString searchProviderPrefix = *(service->property("Keys").toStringList().begin()) + keywordDelimiter;
00494           data.setData( searchProviderPrefix + "some keyword" );
00495 
00496           if ( KURIFilter::self()->filterURI(data, list) )
00497           {
00498             QString iconPath = locate("cache", KMimeType::favIconForURL(data.uri()) + ".png");
00499             if ( iconPath.isEmpty() )
00500               icon = SmallIcon("find");
00501             else
00502               icon = QPixmap( iconPath );
00503             name = service->name();
00504 
00505             providerList->insert( new KAction( name, icon, 0, d->m_khtml->browserExtension(),
00506               SLOT( searchProvider() ), actionCollection(), QString( "searchProvider" + searchProviderPrefix ).latin1() ) );
00507           }
00508         }
00509       }
00510 
00511 
00512       if ( selectedText.contains("://") && KURL(selectedText).isValid() )
00513          new KAction( i18n( "Open '%1'" ).arg( selectedText ), "window_new", 0,
00514          d->m_khtml->browserExtension(), SLOT( openSelection() ), actionCollection(), "openSelection" );
00515   }
00516   else if ( url.isEmpty() && !isImage )
00517   {
00518       actionCollection()->insert( khtml->actionCollection()->action( "security" ) );
00519       actionCollection()->insert( khtml->actionCollection()->action( "setEncoding" ) );
00520       new KAction( i18n( "Stop Animations" ), 0, this, SLOT( slotStopAnimations() ),
00521                    actionCollection(), "stopanimations" );
00522   }
00523 
00524   if ( !url.isEmpty() )
00525   {
00526     if (url.protocol() == "mailto")
00527     {
00528       new KAction( i18n( "Copy Email Address" ), 0, this, SLOT( slotCopyLinkLocation() ),
00529                  actionCollection(), "copylinklocation" );
00530     }
00531     else
00532     {
00533       new KAction( i18n( "&Save Link As..." ), 0, this, SLOT( slotSaveLinkAs() ),
00534                  actionCollection(), "savelinkas" );
00535       new KAction( i18n( "Copy &Link Address" ), 0, this, SLOT( slotCopyLinkLocation() ),
00536                  actionCollection(), "copylinklocation" );
00537     }
00538   }
00539 
00540   // frameset? -> add "Reload Frame" etc.
00541   if (!hasSelection)
00542   {
00543     if ( khtml->parentPart() )
00544     {
00545       new KAction( i18n( "Open in New &Window" ), "window_new", 0, this, SLOT( slotFrameInWindow() ),
00546                                           actionCollection(), "frameinwindow" );
00547       new KAction( i18n( "Open in &This Window" ), 0, this, SLOT( slotFrameInTop() ),
00548                                           actionCollection(), "frameintop" );
00549       new KAction( i18n( "Open in &New Tab" ), "tab_new", 0, this, SLOT( slotFrameInTab() ),
00550                                        actionCollection(), "frameintab" );
00551       new KAction( i18n( "Reload Frame" ), 0, this, SLOT( slotReloadFrame() ),
00552                                         actionCollection(), "reloadframe" );
00553 
00554       if ( KHTMLFactory::defaultHTMLSettings()->isAdFilterEnabled() ) {
00555           if ( khtml->d->m_frame->m_type == khtml::ChildFrame::IFrame )
00556               new KAction( i18n( "Block IFrame..." ), 0, this, SLOT( slotBlockIFrame() ), actionCollection(), "blockiframe" );
00557       }
00558 
00559       new KAction( i18n( "View Frame Source" ), 0, d->m_khtml, SLOT( slotViewDocumentSource() ),
00560                                           actionCollection(), "viewFrameSource" );
00561       new KAction( i18n( "View Frame Information" ), 0, d->m_khtml, SLOT( slotViewPageInfo() ), actionCollection(), "viewFrameInfo" );
00562       // This one isn't in khtml_popupmenu.rc anymore, because Print isn't either,
00563       // and because print frame is already in the toolbar and the menu.
00564       // But leave this here, so that it's easy to read it.
00565       new KAction( i18n( "Print Frame..." ), "frameprint", 0, d->m_khtml->browserExtension(), SLOT( print() ), actionCollection(), "printFrame" );
00566       new KAction( i18n( "Save &Frame As..." ), 0, d->m_khtml, SLOT( slotSaveFrame() ), actionCollection(), "saveFrame" );
00567 
00568       actionCollection()->insert( khtml->parentPart()->actionCollection()->action( "viewDocumentSource" ) );
00569       actionCollection()->insert( khtml->parentPart()->actionCollection()->action( "viewPageInfo" ) );
00570     } else {
00571       actionCollection()->insert( khtml->actionCollection()->action( "viewDocumentSource" ) );
00572       actionCollection()->insert( khtml->actionCollection()->action( "viewPageInfo" ) );
00573     }
00574   } else if (isImage || !url.isEmpty()) {
00575     actionCollection()->insert( khtml->actionCollection()->action( "viewDocumentSource" ) );
00576     actionCollection()->insert( khtml->actionCollection()->action( "viewPageInfo" ) );
00577     new KAction( i18n( "Stop Animations" ), 0, this, SLOT( slotStopAnimations() ),
00578                  actionCollection(), "stopanimations" );
00579   }
00580 
00581   if (isImage)
00582   {
00583     if ( e.elementId() == ID_IMG ) {
00584       d->m_imageURL = KURL( static_cast<DOM::HTMLImageElement>( e ).src().string() );
00585       DOM::HTMLImageElementImpl *imageimpl = static_cast<DOM::HTMLImageElementImpl *>( e.handle() );
00586       Q_ASSERT(imageimpl);
00587       if(imageimpl) // should be true always.  right?
00588       {
00589         if(imageimpl->complete()) {
00590       d->m_pixmap = imageimpl->currentPixmap();
00591     }
00592       }
00593     }
00594     else
00595       d->m_imageURL = KURL( static_cast<DOM::HTMLInputElement>( e ).src().string() );
00596     new KAction( i18n( "Save Image As..." ), 0, this, SLOT( slotSaveImageAs() ),
00597                  actionCollection(), "saveimageas" );
00598     new KAction( i18n( "Send Image..." ), 0, this, SLOT( slotSendImage() ),
00599                  actionCollection(), "sendimage" );
00600 
00601 
00602 #ifndef QT_NO_MIMECLIPBOARD
00603     (new KAction( i18n( "Copy Image" ), 0, this, SLOT( slotCopyImage() ),
00604                  actionCollection(), "copyimage" ))->setEnabled(!d->m_pixmap.isNull());
00605 #endif
00606 
00607     if(d->m_pixmap.isNull()) {    //fallback to image location if still loading the image.  this will always be true if ifdef QT_NO_MIMECLIPBOARD
00608       new KAction( i18n( "Copy Image Location" ), 0, this, SLOT( slotCopyImageLocation() ),
00609                    actionCollection(), "copyimagelocation" );
00610     }
00611 
00612     QString name = KStringHandler::csqueeze(d->m_imageURL.fileName()+d->m_imageURL.query(), 25);
00613     new KAction( i18n( "View Image (%1)" ).arg(d->m_suggestedFilename.isEmpty() ? name.replace("&", "&&") : d->m_suggestedFilename.replace("&", "&&")), 0, this, SLOT( slotViewImage() ),
00614                  actionCollection(), "viewimage" );
00615 
00616     if (KHTMLFactory::defaultHTMLSettings()->isAdFilterEnabled())
00617     {
00618       new KAction( i18n( "Block Image..." ), 0, this, SLOT( slotBlockImage() ),
00619                    actionCollection(), "blockimage" );
00620 
00621       if (!d->m_imageURL.host().isEmpty() &&
00622           !d->m_imageURL.protocol().isEmpty())
00623       {
00624         new KAction( i18n( "Block Images From %1" ).arg(d->m_imageURL.host()), 0, this, SLOT( slotBlockHost() ),
00625                      actionCollection(), "blockhost" );
00626       }
00627     }
00628   }
00629 
00630   setXML( doc );
00631   setDOMDocument( QDomDocument(), true ); // ### HACK
00632 
00633   QDomElement menu = domDocument().documentElement().namedItem( "Menu" ).toElement();
00634 
00635   if ( actionCollection()->count() > 0 )
00636     menu.insertBefore( domDocument().createElement( "separator" ), menu.firstChild() );
00637 }
00638 
00639 KHTMLPopupGUIClient::~KHTMLPopupGUIClient()
00640 {
00641   delete d;
00642 }
00643 
00644 void KHTMLPopupGUIClient::slotSaveLinkAs()
00645 {
00646   KIO::MetaData metaData;
00647   metaData["referrer"] = d->m_khtml->referrer();
00648   saveURL( d->m_khtml->widget(), i18n( "Save Link As" ), d->m_url, metaData );
00649 }
00650 
00651 void KHTMLPopupGUIClient::slotSendImage()
00652 {
00653     QStringList urls;
00654     urls.append( d->m_imageURL.url());
00655     QString subject = d->m_imageURL.url();
00656     kapp->invokeMailer(QString::null, QString::null, QString::null, subject,
00657                        QString::null, //body
00658                        QString::null,
00659                        urls); // attachments
00660 
00661 
00662 }
00663 
00664 void KHTMLPopupGUIClient::slotSaveImageAs()
00665 {
00666   KIO::MetaData metaData;
00667   metaData["referrer"] = d->m_khtml->referrer();
00668   saveURL( d->m_khtml->widget(), i18n( "Save Image As" ), d->m_imageURL, metaData, QString::null, 0, d->m_suggestedFilename );
00669 }
00670 
00671 void KHTMLPopupGUIClient::slotBlockHost()
00672 {
00673     QString name=d->m_imageURL.protocol()+"://"+d->m_imageURL.host()+"/*";
00674     KHTMLFactory::defaultHTMLSettings()->addAdFilter( name );
00675     d->m_khtml->reparseConfiguration();
00676 }
00677 
00678 void KHTMLPopupGUIClient::slotBlockImage()
00679 {
00680     bool ok = false;
00681 
00682     QString url = KInputDialog::getText( i18n("Add URL to Filter"),
00683                                          "Enter the URL:",
00684                                          d->m_imageURL.url(),
00685                                          &ok);
00686     if ( ok ) {
00687         KHTMLFactory::defaultHTMLSettings()->addAdFilter( url );
00688         d->m_khtml->reparseConfiguration();
00689     }
00690 }
00691 
00692 void KHTMLPopupGUIClient::slotBlockIFrame()
00693 {
00694     bool ok = false;
00695     QString url = KInputDialog::getText( i18n( "Add URL to Filter"),
00696                                                "Enter the URL:",
00697                                                d->m_khtml->url().url(),
00698                                                &ok );
00699     if ( ok ) {
00700         KHTMLFactory::defaultHTMLSettings()->addAdFilter( url );
00701         d->m_khtml->reparseConfiguration();
00702     }
00703 }
00704 
00705 void KHTMLPopupGUIClient::slotCopyLinkLocation()
00706 {
00707   KURL safeURL(d->m_url);
00708   safeURL.setPass(QString::null);
00709 #ifndef QT_NO_MIMECLIPBOARD
00710   // Set it in both the mouse selection and in the clipboard
00711   KURL::List lst;
00712   lst.append( safeURL );
00713   QApplication::clipboard()->setData( new KURLDrag( lst ), QClipboard::Clipboard );
00714   QApplication::clipboard()->setData( new KURLDrag( lst ), QClipboard::Selection );
00715 #else
00716   QApplication::clipboard()->setText( safeURL.url() ); //FIXME(E): Handle multiple entries
00717 #endif
00718 }
00719 
00720 void KHTMLPopupGUIClient::slotStopAnimations()
00721 {
00722   d->m_khtml->stopAnimations();
00723 }
00724 
00725 void KHTMLPopupGUIClient::slotCopyImage()
00726 {
00727 #ifndef QT_NO_MIMECLIPBOARD
00728   KURL safeURL(d->m_imageURL);
00729   safeURL.setPass(QString::null);
00730 
00731   KURL::List lst;
00732   lst.append( safeURL );
00733   KMultipleDrag *drag = new KMultipleDrag(d->m_khtml->view(), "Image");
00734 
00735   drag->addDragObject( new QImageDrag(d->m_pixmap.convertToImage()) );
00736   drag->addDragObject( new KURLDrag(lst, d->m_khtml->view(), "Image URL") );
00737 
00738   // Set it in both the mouse selection and in the clipboard
00739   QApplication::clipboard()->setData( drag, QClipboard::Clipboard );
00740   QApplication::clipboard()->setData( new KURLDrag(lst), QClipboard::Selection );
00741 #else
00742   kdDebug() << "slotCopyImage called when the clipboard does not support this.  This should not be possible." << endl;
00743 #endif
00744 }
00745 
00746 void KHTMLPopupGUIClient::slotCopyImageLocation()
00747 {
00748   KURL safeURL(d->m_imageURL);
00749   safeURL.setPass(QString::null);
00750 #ifndef QT_NO_MIMECLIPBOARD
00751   // Set it in both the mouse selection and in the clipboard
00752   KURL::List lst;
00753   lst.append( safeURL );
00754   QApplication::clipboard()->setData( new KURLDrag( lst ), QClipboard::Clipboard );
00755   QApplication::clipboard()->setData( new KURLDrag( lst ), QClipboard::Selection );
00756 #else
00757   QApplication::clipboard()->setText( safeURL.url() ); //FIXME(E): Handle multiple entries
00758 #endif
00759 }
00760 
00761 void KHTMLPopupGUIClient::slotViewImage()
00762 {
00763   d->m_khtml->browserExtension()->createNewWindow(d->m_imageURL);
00764 }
00765 
00766 void KHTMLPopupGUIClient::slotReloadFrame()
00767 {
00768   KParts::URLArgs args( d->m_khtml->browserExtension()->urlArgs() );
00769   args.reload = true;
00770   args.metaData()["referrer"] = d->m_khtml->pageReferrer();
00771   // reload document
00772   d->m_khtml->closeURL();
00773   d->m_khtml->browserExtension()->setURLArgs( args );
00774   d->m_khtml->openURL( d->m_khtml->url() );
00775 }
00776 
00777 void KHTMLPopupGUIClient::slotFrameInWindow()
00778 {
00779   KParts::URLArgs args( d->m_khtml->browserExtension()->urlArgs() );
00780   args.metaData()["referrer"] = d->m_khtml->pageReferrer();
00781   args.metaData()["forcenewwindow"] = "true";
00782   emit d->m_khtml->browserExtension()->createNewWindow( d->m_khtml->url(), args );
00783 }
00784 
00785 void KHTMLPopupGUIClient::slotFrameInTop()
00786 {
00787   KParts::URLArgs args( d->m_khtml->browserExtension()->urlArgs() );
00788   args.metaData()["referrer"] = d->m_khtml->pageReferrer();
00789   args.frameName = "_top";
00790   emit d->m_khtml->browserExtension()->openURLRequest( d->m_khtml->url(), args );
00791 }
00792 
00793 void KHTMLPopupGUIClient::slotFrameInTab()
00794 {
00795   KParts::URLArgs args( d->m_khtml->browserExtension()->urlArgs() );
00796   args.metaData()["referrer"] = d->m_khtml->pageReferrer();
00797   args.setNewTab(true);
00798   emit d->m_khtml->browserExtension()->createNewWindow( d->m_khtml->url(), args );
00799 }
00800 
00801 void KHTMLPopupGUIClient::saveURL( QWidget *parent, const QString &caption,
00802                                    const KURL &url,
00803                                    const QMap<QString, QString> &metadata,
00804                                    const QString &filter, long cacheId,
00805                                    const QString & suggestedFilename )
00806 {
00807   QString name = QString::fromLatin1( "index.html" );
00808   if ( !suggestedFilename.isEmpty() )
00809     name = suggestedFilename;
00810   else if ( !url.fileName().isEmpty() )
00811     name = url.fileName();
00812 
00813   KURL destURL;
00814   int query;
00815   do {
00816     query = KMessageBox::Yes;
00817     destURL = KFileDialog::getSaveURL( name, filter, parent, caption );
00818       if( destURL.isLocalFile() )
00819       {
00820         QFileInfo info( destURL.path() );
00821         if( info.exists() ) {
00822           // TODO: use KIO::RenameDlg (shows more information)
00823           query = KMessageBox::warningContinueCancel( parent, i18n( "A file named \"%1\" already exists. " "Are you sure you want to overwrite it?" ).arg( info.fileName() ), i18n( "Overwrite File?" ), i18n( "Overwrite" ) );
00824         }
00825        }
00826    } while ( query == KMessageBox::Cancel );
00827 
00828   if ( destURL.isValid() )
00829     saveURL(url, destURL, metadata, cacheId);
00830 }
00831 
00832 void KHTMLPopupGUIClient::saveURL( const KURL &url, const KURL &destURL,
00833                                    const QMap<QString, QString> &metadata,
00834                                    long cacheId )
00835 {
00836     if ( destURL.isValid() )
00837     {
00838         bool saved = false;
00839         if (KHTMLPageCache::self()->isComplete(cacheId))
00840         {
00841             if (destURL.isLocalFile())
00842             {
00843                 KSaveFile destFile(destURL.path());
00844                 if (destFile.status() == 0)
00845                 {
00846                     KHTMLPageCache::self()->saveData(cacheId, destFile.dataStream());
00847                     saved = true;
00848                 }
00849             }
00850             else
00851             {
00852                 // save to temp file, then move to final destination.
00853                 KTempFile destFile;
00854                 if (destFile.status() == 0)
00855                 {
00856                     KHTMLPageCache::self()->saveData(cacheId, destFile.dataStream());
00857                     destFile.close();
00858                     KURL url2 = KURL();
00859                     url2.setPath(destFile.name());
00860                     KIO::file_move(url2, destURL, -1, true /*overwrite*/);
00861                     saved = true;
00862                 }
00863             }
00864         }
00865         if(!saved)
00866         {
00867           // DownloadManager <-> konqueror integration
00868           // find if the integration is enabled
00869           // the empty key  means no integration
00870           // only use download manager for non-local urls!
00871           bool downloadViaKIO = true;
00872           if ( !url.isLocalFile() )
00873           {
00874             KConfig cfg("konquerorrc", false, false);
00875             cfg.setGroup("HTML Settings");
00876             QString downloadManger = cfg.readPathEntry("DownloadManager");
00877             if (!downloadManger.isEmpty())
00878             {
00879                 // then find the download manager location
00880                 kdDebug(1000) << "Using: "<<downloadManger <<" as Download Manager" <<endl;
00881                 QString cmd = KStandardDirs::findExe(downloadManger);
00882                 if (cmd.isEmpty())
00883                 {
00884                     QString errMsg=i18n("The Download Manager (%1) could not be found in your $PATH ").arg(downloadManger);
00885                     QString errMsgEx= i18n("Try to reinstall it  \n\nThe integration with Konqueror will be disabled!");
00886                     KMessageBox::detailedSorry(0,errMsg,errMsgEx);
00887                     cfg.writePathEntry("DownloadManager",QString::null);
00888                     cfg.sync ();
00889                 }
00890                 else
00891                 {
00892                     downloadViaKIO = false;
00893                     KURL cleanDest = destURL;
00894                     cleanDest.setPass( QString::null ); // don't put password into commandline
00895                     cmd += " " + KProcess::quote(url.url()) + " " +
00896                            KProcess::quote(cleanDest.url());
00897                     kdDebug(1000) << "Calling command  "<<cmd<<endl;
00898                     KRun::runCommand(cmd);
00899                 }
00900             }
00901           }
00902 
00903           if ( downloadViaKIO )
00904           {
00905               KIO::Job *job = KIO::file_copy( url, destURL, -1, true /*overwrite*/ );
00906               job->setMetaData(metadata);
00907               job->addMetaData("MaxCacheSize", "0"); // Don't store in http cache.
00908               job->addMetaData("cache", "cache"); // Use entry from cache if available.
00909               job->setAutoErrorHandlingEnabled( true );
00910           }
00911         } //end if(!saved)
00912     }
00913 }
00914 
00915 KHTMLPartBrowserHostExtension::KHTMLPartBrowserHostExtension( KHTMLPart *part )
00916 : KParts::BrowserHostExtension( part )
00917 {
00918   m_part = part;
00919 }
00920 
00921 KHTMLPartBrowserHostExtension::~KHTMLPartBrowserHostExtension()
00922 {
00923 }
00924 
00925 QStringList KHTMLPartBrowserHostExtension::frameNames() const
00926 {
00927   return m_part->frameNames();
00928 }
00929 
00930 const QPtrList<KParts::ReadOnlyPart> KHTMLPartBrowserHostExtension::frames() const
00931 {
00932   return m_part->frames();
00933 }
00934 
00935 bool KHTMLPartBrowserHostExtension::openURLInFrame( const KURL &url, const KParts::URLArgs &urlArgs )
00936 {
00937   return m_part->openURLInFrame( url, urlArgs );
00938 }
00939 
00940 void KHTMLPartBrowserHostExtension::virtual_hook( int id, void *data )
00941 {
00942   if (id == VIRTUAL_FIND_FRAME_PARENT)
00943   {
00944     FindFrameParentParams *param = static_cast<FindFrameParentParams*>(data);
00945     KHTMLPart *parentPart = m_part->findFrameParent(param->callingPart, param->frame);
00946     if (parentPart)
00947        param->parent = parentPart->browserHostExtension();
00948     return;
00949   }
00950   BrowserHostExtension::virtual_hook( id, data );
00951 }
00952 
00953 
00954 // defined in khtml_part.cpp
00955 extern const int KDE_NO_EXPORT fastZoomSizes[];
00956 extern const int KDE_NO_EXPORT fastZoomSizeCount;
00957 
00958 // BCI: remove in KDE 4
00959 KHTMLZoomFactorAction::KHTMLZoomFactorAction( KHTMLPart *part, bool direction, const QString &text, const QString &icon, const QObject *receiver, const char *slot, QObject *parent, const char *name )
00960     : KAction( text, icon, 0, receiver, slot, parent, name )
00961 {
00962     init(part, direction);
00963 }
00964 
00965 KHTMLZoomFactorAction::KHTMLZoomFactorAction( KHTMLPart *part, bool direction, const QString &text, const QString &icon, const KShortcut &cut, const QObject *receiver, const char *slot, QObject *parent, const char *name )
00966     : KAction( text, icon, cut, receiver, slot, parent, name )
00967 {
00968     init(part, direction);
00969 }
00970 
00971 void KHTMLZoomFactorAction::init(KHTMLPart *part, bool direction)
00972 {
00973     m_direction = direction;
00974     m_part = part;
00975 
00976     m_popup = new QPopupMenu;
00977     // xgettext: no-c-format
00978     m_popup->insertItem( i18n( "Default Font Size (100%)" ) );
00979 
00980     int m = m_direction ? 1 : -1;
00981     int ofs = fastZoomSizeCount / 2;       // take index of 100%
00982 
00983     // this only works if there is an odd number of elements in fastZoomSizes[]
00984     for ( int i = m; i != m*(ofs+1); i += m )
00985     {
00986         int num = i * m;
00987         QString numStr = QString::number( num );
00988         if ( num > 0 ) numStr.prepend( '+' );
00989 
00990         // xgettext: no-c-format
00991         m_popup->insertItem( i18n( "%1%" ).arg( fastZoomSizes[ofs + i] ) );
00992     }
00993 
00994     connect( m_popup, SIGNAL( activated( int ) ), this, SLOT( slotActivated( int ) ) );
00995 }
00996 
00997 KHTMLZoomFactorAction::~KHTMLZoomFactorAction()
00998 {
00999     delete m_popup;
01000 }
01001 
01002 int KHTMLZoomFactorAction::plug( QWidget *w, int index )
01003 {
01004     int containerId = KAction::plug( w, index );
01005     if ( containerId == -1 || !w->inherits( "KToolBar" ) )
01006         return containerId;
01007 
01008     KToolBarButton *button = static_cast<KToolBar *>( w )->getButton( itemId( containerId ) );
01009     if ( !button )
01010         return containerId;
01011 
01012     button->setDelayedPopup( m_popup );
01013     return containerId;
01014 }
01015 
01016 void KHTMLZoomFactorAction::slotActivated( int id )
01017 {
01018     int idx = m_popup->indexOf( id );
01019 
01020     if (idx == 0)
01021         m_part->setZoomFactor(100);
01022     else
01023         m_part->setZoomFactor(fastZoomSizes[fastZoomSizeCount/2 + (m_direction ? 1 : -1)*idx]);
01024 }
01025 
01026 #include "khtml_ext.moc"
01027 
KDE Home | KDE Accessibility Home | Description of Access Keys