• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KHTML

kmultipart.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE project
00002    Copyright (C) 2002 David Faure <david@mandrakesoft.com>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "kmultipart.h"
00021 
00022 
00023 #include <kcomponentdata.h>
00024 #include <kmimetype.h>
00025 #include <klocale.h>
00026 #include <kjobuidelegate.h>
00027 #include <kio/job.h>
00028 #include <QtCore/QFile>
00029 #include <ktemporaryfile.h>
00030 #include <kmessagebox.h>
00031 #include <kparts/componentfactory.h>
00032 #include <kparts/genericfactory.h>
00033 #include <khtml_part.h>
00034 #include <unistd.h>
00035 #include <kxmlguifactory.h>
00036 #include <QtCore/QTimer>
00037 #include <kvbox.h>
00038 
00039 typedef KParts::GenericFactory<KMultiPart> KMultiPartFactory; // factory for the part
00040 K_EXPORT_COMPONENT_FACTORY( libkmultipart /*library name*/, KMultiPartFactory )
00041 
00042 //#define DEBUG_PARSING
00043 
00044 class KLineParser
00045 {
00046 public:
00047     KLineParser() {
00048         m_lineComplete = false;
00049     }
00050     void addChar( char c, bool storeNewline ) {
00051         if ( !storeNewline && c == '\r' )
00052             return;
00053         Q_ASSERT( !m_lineComplete );
00054         if ( storeNewline || c != '\n' ) {
00055             int sz = m_currentLine.size();
00056             m_currentLine.resize( sz+1 );
00057             m_currentLine[sz] = c;
00058         }
00059         if ( c == '\n' )
00060             m_lineComplete = true;
00061     }
00062     bool isLineComplete() const {
00063         return m_lineComplete;
00064     }
00065     QByteArray currentLine() const {
00066         return m_currentLine;
00067     }
00068     void clearLine() {
00069         Q_ASSERT( m_lineComplete );
00070         reset();
00071     }
00072     void reset() {
00073         m_currentLine.resize( 0 );
00074         m_lineComplete = false;
00075     }
00076 private:
00077     QByteArray m_currentLine;
00078     bool m_lineComplete; // true when ending with '\n'
00079 };
00080 
00081 /* testcase:
00082    Content-type: multipart/mixed;boundary=ThisRandomString
00083 
00084 --ThisRandomString
00085 Content-type: text/plain
00086 
00087 Data for the first object.
00088 
00089 --ThisRandomString
00090 Content-type: text/plain
00091 
00092 Data for the second and last object.
00093 
00094 --ThisRandomString--
00095 */
00096 
00097 
00098 KMultiPart::KMultiPart( QWidget *parentWidget,
00099                         QObject *parent, const QStringList& )
00100     : KParts::ReadOnlyPart( parent )
00101 {
00102     m_filter = 0L;
00103 
00104     setComponentData( KMultiPartFactory::componentData() );
00105 
00106     KVBox *box = new KVBox( parentWidget );
00107     setWidget( box );
00108 
00109     m_extension = new KParts::BrowserExtension( this );
00110 
00111     m_part = 0L;
00112     m_isHTMLPart = false;
00113     m_job = 0L;
00114     m_lineParser = new KLineParser;
00115     m_tempFile = 0L;
00116 
00117     m_timer = new QTimer( this );
00118     connect( m_timer, SIGNAL( timeout() ), this, SLOT( slotProgressInfo() ) );
00119 }
00120 
00121 KMultiPart::~KMultiPart()
00122 {
00123     // important: delete the nested part before the part or qobject destructor runs.
00124     // we now delete the nested part which deletes the part's widget which makes
00125     // _OUR_ m_widget 0 which in turn avoids our part destructor to delete the
00126     // widget ;-)
00127     // ### additional note: it _can_ be that the part has been deleted before:
00128     // when we're in a html frameset and the view dies first, then it will also
00129     // kill the htmlpart
00130     if ( m_part )
00131         delete static_cast<KParts::ReadOnlyPart *>( m_part );
00132     delete m_job;
00133     delete m_lineParser;
00134     if ( m_tempFile ) {
00135         m_tempFile->setAutoRemove( true );
00136         delete m_tempFile;
00137     }
00138     delete m_filter;
00139     m_filter = 0L;
00140 }
00141 
00142 
00143 void KMultiPart::startHeader()
00144 {
00145     m_bParsingHeader = true; // we expect a header to come first
00146     m_bGotAnyHeader = false;
00147     m_gzip = false;
00148     // just to be sure for now
00149     delete m_filter;
00150     m_filter = 0L;
00151 }
00152 
00153 
00154 bool KMultiPart::openUrl( const KUrl &url )
00155 {
00156     setUrl(url);
00157     m_lineParser->reset();
00158     startHeader();
00159 
00160     //m_mimeType = arguments().mimeType();
00161 
00162     // Hmm, args.reload is set to true when reloading, but this doesn't seem to be enough...
00163     // I get "HOLD: Reusing held slave for <url>", and the old data
00164 
00165     m_job = KIO::get( url,
00166                       arguments().reload() ? KIO::Reload : KIO::NoReload,
00167                       KIO::HideProgressInfo );
00168 
00169     emit started( 0 /*m_job*/ ); // don't pass the job, it would interfere with our own infoMessage
00170 
00171     connect( m_job, SIGNAL( result( KJob * ) ),
00172              this, SLOT( slotJobFinished( KJob * ) ) );
00173     connect( m_job, SIGNAL( data( KIO::Job *, const QByteArray & ) ),
00174              this, SLOT( slotData( KIO::Job *, const QByteArray & ) ) );
00175 
00176     m_numberOfFrames = 0;
00177     m_numberOfFramesSkipped = 0;
00178     m_totalNumberOfFrames = 0;
00179     m_qtime.start();
00180     m_timer->start( 1000 ); //1s
00181 
00182     return true;
00183 }
00184 
00185 // Yes, libkdenetwork's has such a parser already (MultiPart),
00186 // but it works on the complete string, expecting the whole data to be available....
00187 // The version here is asynchronous.
00188 void KMultiPart::slotData( KIO::Job *job, const QByteArray &data )
00189 {
00190     if (m_boundary.isNull())
00191     {
00192        QString tmp = job->queryMetaData("media-boundary");
00193        kDebug() << "Got Boundary from kio-http '" << tmp << "'";
00194        if ( !tmp.isEmpty() ) {
00195            if (tmp.startsWith(QLatin1String("--")))
00196                m_boundary = tmp.toLatin1();
00197            else
00198                m_boundary = QByteArray("--")+tmp.toLatin1();
00199            m_boundaryLength = m_boundary.length();
00200        }
00201     }
00202     // Append to m_currentLine until eol
00203     for ( int i = 0; i < data.size() ; ++i )
00204     {
00205         // Store char. Skip if '\n' and currently parsing a header.
00206         m_lineParser->addChar( data[i], !m_bParsingHeader );
00207         if ( m_lineParser->isLineComplete() )
00208         {
00209             QByteArray lineData = m_lineParser->currentLine();
00210 #ifdef DEBUG_PARSING
00211             kDebug() << "lineData.size()=" << lineData.size();
00212 #endif
00213             QByteArray line( lineData.data(), lineData.size()+1 ); // deep copy
00214             // 0-terminate the data, but only for the line-based tests below
00215             // We want to keep the raw data in case it ends up in sendData()
00216             int sz = line.size();
00217             if ( sz > 0 )
00218                 line[sz-1] = '\0';
00219 #ifdef DEBUG_PARSING
00220             kDebug() << "[" << m_bParsingHeader << "] line='" << line << "'";
00221 #endif
00222             if ( m_bParsingHeader )
00223             {
00224                 if ( !line.isEmpty() )
00225                     m_bGotAnyHeader = true;
00226                 if ( m_boundary.isNull() )
00227                 {
00228                     if ( !line.isEmpty() ) {
00229 #ifdef DEBUG_PARSING
00230                         kDebug() << "Boundary is " << line;
00231 #endif
00232                         m_boundary = line;
00233                         m_boundaryLength = m_boundary.length();
00234                     }
00235                 }
00236                 else if ( !qstrnicmp( line.data(), "Content-Encoding:", 17 ) )
00237                 {
00238                     QString encoding = QString::fromLatin1(line.data()+17).trimmed().toLower();
00239                     if (encoding == "gzip" || encoding == "x-gzip") {
00240                         m_gzip = true;
00241                     } else {
00242                         kDebug() << "FIXME: unhandled encoding type in KMultiPart: " << encoding;
00243                     }
00244                 }
00245                 // parse Content-Type
00246                 else if ( !qstrnicmp( line.data(), "Content-Type:", 13 ) )
00247                 {
00248                     Q_ASSERT( m_nextMimeType.isNull() );
00249                     m_nextMimeType = QString::fromLatin1( line.data() + 14 ).trimmed();
00250                     int semicolon = m_nextMimeType.indexOf( ';' );
00251                     if ( semicolon != -1 )
00252                         m_nextMimeType = m_nextMimeType.left( semicolon );
00253                     kDebug() << "m_nextMimeType=" << m_nextMimeType;
00254                 }
00255                 // Empty line, end of headers (if we had any header line before)
00256                 else if ( line.isEmpty() && m_bGotAnyHeader )
00257                 {
00258                     m_bParsingHeader = false;
00259 #ifdef DEBUG_PARSING
00260                     kDebug() << "end of headers";
00261 #endif
00262                     startOfData();
00263                 }
00264                 // First header (when we know it from kio_http)
00265                 else if ( line == m_boundary )
00266                     ; // nothing to do
00267                 else if ( !line.isEmpty() ) // this happens with e.g. Set-Cookie:
00268                     kDebug() << "Ignoring header " << line;
00269             } else {
00270                 if ( !qstrncmp( line, m_boundary, m_boundaryLength ) )
00271                 {
00272 #ifdef DEBUG_PARSING
00273                     kDebug() << "boundary found!";
00274                     kDebug() << "after it is " << line.data() + m_boundaryLength;
00275 #endif
00276                     // Was it the very last boundary ?
00277                     if ( !qstrncmp( line.data() + m_boundaryLength, "--", 2 ) )
00278                     {
00279 #ifdef DEBUG_PARSING
00280                         kDebug() << "Completed!";
00281 #endif
00282                         endOfData();
00283                         emit completed();
00284                     } else
00285                     {
00286                         char nextChar = *(line.data() + m_boundaryLength);
00287 #ifdef DEBUG_PARSING
00288                         kDebug() << "KMultiPart::slotData nextChar='" << nextChar << "'";
00289 #endif
00290                         if ( nextChar == '\n' || nextChar == '\r' ) {
00291                             endOfData();
00292                             startHeader();
00293                         }
00294                         else {
00295                             // otherwise, false hit, it has trailing stuff
00296                             sendData( lineData );
00297                         }
00298                     }
00299                 } else {
00300                     // send to part
00301                     sendData( lineData );
00302                 }
00303             }
00304             m_lineParser->clearLine();
00305         }
00306     }
00307 }
00308 
00309 void KMultiPart::setPart( const QString& mimeType )
00310 {
00311     KXMLGUIFactory *guiFactory = factory();
00312     if ( guiFactory ) // seems to be 0 when restoring from SM
00313         guiFactory->removeClient( this );
00314     kDebug() << "KMultiPart::setPart " << mimeType;
00315     delete m_part;
00316     // Try to find an appropriate viewer component
00317     m_part = KParts::ComponentFactory::createPartInstanceFromQuery<KParts::ReadOnlyPart>
00318              ( m_mimeType, QString(), widget(), this );
00319     if ( !m_part ) {
00320         // TODO launch external app
00321         KMessageBox::error( widget(), i18n("No handler found for %1.", m_mimeType) );
00322         return;
00323     }
00324     // By making the part a child XMLGUIClient of ours, we get its GUI merged in.
00325     insertChildClient( m_part );
00326     m_part->widget()->show();
00327 
00328     connect( m_part, SIGNAL( completed() ),
00329              this, SLOT( slotPartCompleted() ) );
00330 
00331     m_isHTMLPart = ( mimeType == "text/html" );
00332     KParts::BrowserExtension* childExtension = KParts::BrowserExtension::childObject( m_part );
00333 
00334     if ( childExtension )
00335     {
00336 
00337         // Forward signals from the part's browser extension
00338         // this is very related (but not exactly like) KHTMLPart::processObjectRequest
00339 
00340         connect( childExtension, SIGNAL( openURLNotify() ),
00341                  m_extension, SIGNAL( openURLNotify() ) );
00342 
00343         connect( childExtension, SIGNAL( openUrlRequestDelayed( const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments& ) ),
00344                  m_extension, SIGNAL( openUrlRequest( const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments & ) ) );
00345 
00346         connect( childExtension, SIGNAL( createNewWindow( const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments&, const KParts::WindowArgs &, KParts::ReadOnlyPart** ) ),
00347                  m_extension, SIGNAL( createNewWindow( const KUrl &, const KParts::OpenUrlArguments&, const KParts::BrowserArguments& , const KParts::WindowArgs &, KParts::ReadOnlyPart**) ) );
00348 
00349         // Keep in sync with khtml_part.cpp
00350         connect( childExtension, SIGNAL(popupMenu(QPoint,KFileItemList,KParts::OpenUrlArguments,KParts::BrowserArguments,KParts::BrowserExtension::PopupFlags,KParts::BrowserExtension::ActionGroupMap)),
00351              m_extension, SIGNAL(popupMenu(QPoint,KFileItemList,KParts::OpenUrlArguments,KParts::BrowserArguments,KParts::BrowserExtension::PopupFlags,KParts::BrowserExtension::ActionGroupMap)) );
00352         connect( childExtension, SIGNAL(popupMenu(QPoint,KUrl,mode_t,KParts::OpenUrlArguments,KParts::BrowserArguments,KParts::BrowserExtension::PopupFlags,KParts::BrowserExtension::ActionGroupMap)),
00353              m_extension, SIGNAL(popupMenu(QPoint,KUrl,mode_t,KParts::OpenUrlArguments,KParts::BrowserArguments,KParts::BrowserExtension::PopupFlags,KParts::BrowserExtension::ActionGroupMap)) );
00354 
00355         if ( m_isHTMLPart )
00356             connect( childExtension, SIGNAL( infoMessage( const QString & ) ),
00357                      m_extension, SIGNAL( infoMessage( const QString & ) ) );
00358         // For non-HTML we prefer to show our infoMessage ourselves.
00359 
00360         childExtension->setBrowserInterface( m_extension->browserInterface() );
00361 
00362         connect( childExtension, SIGNAL( enableAction( const char *, bool ) ),
00363                  m_extension, SIGNAL( enableAction( const char *, bool ) ) );
00364         connect( childExtension, SIGNAL( setLocationBarURL( const QString& ) ),
00365                  m_extension, SIGNAL( setLocationBarURL( const QString& ) ) );
00366         connect( childExtension, SIGNAL( setIconURL( const KUrl& ) ),
00367                  m_extension, SIGNAL( setIconURL( const KUrl& ) ) );
00368         connect( childExtension, SIGNAL( loadingProgress( int ) ),
00369                  m_extension, SIGNAL( loadingProgress( int ) ) );
00370         if ( m_isHTMLPart ) // for non-HTML we have our own
00371             connect( childExtension, SIGNAL( speedProgress( int ) ),
00372                      m_extension, SIGNAL( speedProgress( int ) ) );
00373         connect( childExtension, SIGNAL( selectionInfo( const KFileItemList& ) ),
00374                  m_extension, SIGNAL( selectionInfo( const KFileItemList& ) ) );
00375         connect( childExtension, SIGNAL( selectionInfo( const QString& ) ),
00376                  m_extension, SIGNAL( selectionInfo( const QString& ) ) );
00377         connect( childExtension, SIGNAL( selectionInfo( const KUrl::List& ) ),
00378                  m_extension, SIGNAL( selectionInfo( const KUrl::List& ) ) );
00379         connect( childExtension, SIGNAL( mouseOverInfo( const KFileItem& ) ),
00380                  m_extension, SIGNAL( mouseOverInfo( const KFileItem& ) ) );
00381         connect( childExtension, SIGNAL( moveTopLevelWidget( int, int ) ),
00382                  m_extension, SIGNAL( moveTopLevelWidget( int, int ) ) );
00383         connect( childExtension, SIGNAL( resizeTopLevelWidget( int, int ) ),
00384                  m_extension, SIGNAL( resizeTopLevelWidget( int, int ) ) );
00385     }
00386 
00387     m_partIsLoading = false;
00388     // Load the part's plugins too.
00389     // ###### This is a hack. The bug is that KHTMLPart doesn't load its plugins
00390     // if className != "Browser/View".
00391     loadPlugins( this, m_part, m_part->componentData() );
00392     // Get the part's GUI to appear
00393     if ( guiFactory )
00394         guiFactory->addClient( this );
00395 }
00396 
00397 void KMultiPart::startOfData()
00398 {
00399     kDebug() << "KMultiPart::startOfData";
00400     Q_ASSERT( !m_nextMimeType.isNull() );
00401     if( m_nextMimeType.isNull() )
00402         return;
00403 
00404     if ( m_gzip )
00405     {
00406         m_filter = new HTTPFilterGZip;
00407         connect( m_filter, SIGNAL( output( const QByteArray& ) ), this, SLOT( reallySendData( const QByteArray& ) ) );
00408     }
00409 
00410     if ( m_mimeType != m_nextMimeType )
00411     {
00412         // Need to switch parts (or create the initial one)
00413         m_mimeType = m_nextMimeType;
00414         setPart( m_mimeType );
00415     }
00416     Q_ASSERT( m_part );
00417     // Pass args (e.g. reload)
00418     m_part->setArguments( arguments() );
00419     KParts::BrowserExtension* childExtension = KParts::BrowserExtension::childObject( m_part );
00420     if ( childExtension )
00421         childExtension->setBrowserArguments( m_extension->browserArguments() );
00422 
00423     m_nextMimeType.clear();
00424     if ( m_tempFile ) {
00425         m_tempFile->setAutoRemove( true );
00426         delete m_tempFile;
00427         m_tempFile = 0;
00428     }
00429     if ( m_isHTMLPart )
00430     {
00431         KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) );
00432         htmlPart->begin( url() );
00433     }
00434     else
00435     {
00436         // ###### TODO use a QByteArray and a data: URL instead
00437         m_tempFile = new KTemporaryFile;
00438         m_tempFile->open();
00439     }
00440 }
00441 
00442 void KMultiPart::sendData( const QByteArray& line )
00443 {
00444     if ( m_filter )
00445     {
00446         m_filter->slotInput( line );
00447     }
00448     else
00449     {
00450         reallySendData( line );
00451     }
00452 }
00453 
00454 void KMultiPart::reallySendData( const QByteArray& line )
00455 {
00456     if ( m_isHTMLPart )
00457     {
00458         KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) );
00459         htmlPart->write( line.data(), line.size() );
00460     }
00461     else if ( m_tempFile )
00462     {
00463         m_tempFile->write( line.data(), line.size() );
00464     }
00465 }
00466 
00467 void KMultiPart::endOfData()
00468 {
00469     Q_ASSERT( m_part );
00470     if ( m_isHTMLPart )
00471     {
00472         KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) );
00473         htmlPart->end();
00474     } else if ( m_tempFile )
00475     {
00476         m_tempFile->close();
00477         if ( m_partIsLoading )
00478         {
00479             // The part is still loading the last data! Let it proceed then
00480             // Otherwise we'd keep canceling it, and nothing would ever show up...
00481             kDebug() << "KMultiPart::endOfData part isn't ready, skipping frame";
00482             ++m_numberOfFramesSkipped;
00483             m_tempFile->setAutoRemove( true );
00484         }
00485         else
00486         {
00487             kDebug() << "KMultiPart::endOfData opening " << m_tempFile->fileName();
00488             KUrl url;
00489             url.setPath( m_tempFile->fileName() );
00490             m_partIsLoading = true;
00491             (void) m_part->openUrl( url );
00492         }
00493         delete m_tempFile;
00494         m_tempFile = 0L;
00495     }
00496 }
00497 
00498 void KMultiPart::slotPartCompleted()
00499 {
00500     if ( !m_isHTMLPart )
00501     {
00502         Q_ASSERT( m_part );
00503         // Delete temp file used by the part
00504         Q_ASSERT( m_part->url().isLocalFile() );
00505     kDebug() << "slotPartCompleted deleting " << m_part->url().path();
00506         (void) unlink( QFile::encodeName( m_part->url().path() ) );
00507         m_partIsLoading = false;
00508         ++m_numberOfFrames;
00509         // Do not emit completed from here.
00510     }
00511 }
00512 
00513 bool KMultiPart::closeUrl()
00514 {
00515     m_timer->stop();
00516     if ( m_part )
00517         return m_part->closeUrl();
00518     return true;
00519 }
00520 
00521 void KMultiPart::guiActivateEvent( KParts::GUIActivateEvent * )
00522 {
00523     // Not public!
00524     //if ( m_part )
00525     //    m_part->guiActivateEvent( e );
00526 }
00527 
00528 void KMultiPart::slotJobFinished( KJob *job )
00529 {
00530     if ( job->error() )
00531     {
00532         // TODO use khtml's error:// scheme
00533         job->uiDelegate()->showErrorMessage();
00534         emit canceled( job->errorString() );
00535     }
00536     else
00537     {
00538         /*if ( m_khtml->view()->contentsY() == 0 )
00539         {
00540             const KParts::OpenUrlArguments args = arguments();
00541             m_khtml->view()->setContentsPos( args.xOffset(), args.yOffset() );
00542         }*/
00543 
00544         emit completed();
00545 
00546         //QTimer::singleShot( 0, this, SLOT( updateWindowCaption() ) );
00547     }
00548     m_job = 0L;
00549 }
00550 
00551 void KMultiPart::slotProgressInfo()
00552 {
00553     int time = m_qtime.elapsed();
00554     if ( !time ) return;
00555     if ( m_totalNumberOfFrames == m_numberOfFrames + m_numberOfFramesSkipped )
00556         return; // No change, don't overwrite statusbar messages if any
00557     //kDebug() << m_numberOfFrames << " in " << time << " milliseconds";
00558     QString str( "%1 frames per second, %2 frames skipped per second" );
00559     str = str.arg( 1000.0 * (double)m_numberOfFrames / (double)time );
00560     str = str.arg( 1000.0 * (double)m_numberOfFramesSkipped / (double)time );
00561     m_totalNumberOfFrames = m_numberOfFrames + m_numberOfFramesSkipped;
00562     //kDebug() << str;
00563     emit m_extension->infoMessage( str );
00564 }
00565 
00566 KAboutData* KMultiPart::createAboutData()
00567 {
00568     KAboutData* aboutData = new KAboutData( "kmultipart", 0, ki18n("KMultiPart"),
00569                                             "0.1",
00570                                             ki18n( "Embeddable component for multipart/mixed" ),
00571                                             KAboutData::License_GPL,
00572                                             ki18n("Copyright 2001, David Faure <email>david@mandrakesoft.com</email>"));
00573     return aboutData;
00574 }
00575 
00576 #if 0
00577 KMultiPartBrowserExtension::KMultiPartBrowserExtension( KMultiPart *parent, const char *name )
00578     : KParts::BrowserExtension( parent, name )
00579 {
00580     m_imgPart = parent;
00581 }
00582 
00583 int KMultiPartBrowserExtension::xOffset()
00584 {
00585     return m_imgPart->doc()->view()->contentsX();
00586 }
00587 
00588 int KMultiPartBrowserExtension::yOffset()
00589 {
00590     return m_imgPart->doc()->view()->contentsY();
00591 }
00592 
00593 void KMultiPartBrowserExtension::print()
00594 {
00595     static_cast<KHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->print();
00596 }
00597 
00598 void KMultiPartBrowserExtension::reparseConfiguration()
00599 {
00600     static_cast<KHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->reparseConfiguration();
00601     m_imgPart->doc()->setAutoloadImages( true );
00602 }
00603 #endif
00604 
00605 #include "kmultipart.moc"

KHTML

Skip menu "KHTML"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal