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

KHTML

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

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.5
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