• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • 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 #include <qvbox.h>
00023 #include <kinstance.h>
00024 #include <kmimetype.h>
00025 #include <klocale.h>
00026 #include <kio/job.h>
00027 #include <qfile.h>
00028 #include <ktempfile.h>
00029 #include <kmessagebox.h>
00030 #include <kparts/componentfactory.h>
00031 #include <kparts/genericfactory.h>
00032 #include <khtml_part.h>
00033 #include <unistd.h>
00034 #include <kxmlguifactory.h>
00035 #include <qtimer.h>
00036 
00037 typedef KParts::GenericFactory<KMultiPart> KMultiPartFactory; // factory for the part
00038 K_EXPORT_COMPONENT_FACTORY( libkmultipart /*library name*/, KMultiPartFactory )
00039 
00040 //#define DEBUG_PARSING
00041 
00042 class KLineParser
00043 {
00044 public:
00045     KLineParser() {
00046         m_lineComplete = false;
00047     }
00048     void addChar( char c, bool storeNewline ) {
00049         if ( !storeNewline && c == '\r' )
00050             return;
00051         Q_ASSERT( !m_lineComplete );
00052         if ( storeNewline || c != '\n' ) {
00053             int sz = m_currentLine.size();
00054             m_currentLine.resize( sz+1, QGArray::SpeedOptim );
00055             m_currentLine[sz] = c;
00056         }
00057         if ( c == '\n' )
00058             m_lineComplete = true;
00059     }
00060     bool isLineComplete() const {
00061         return m_lineComplete;
00062     }
00063     QByteArray currentLine() const {
00064         return m_currentLine;
00065     }
00066     void clearLine() {
00067         Q_ASSERT( m_lineComplete );
00068         reset();
00069     }
00070     void reset() {
00071         m_currentLine.resize( 0, QGArray::SpeedOptim );
00072         m_lineComplete = false;
00073     }
00074 private:
00075     QByteArray m_currentLine;
00076     bool m_lineComplete; // true when ending with '\n'
00077 };
00078 
00079 /* testcase:
00080    Content-type: multipart/mixed;boundary=ThisRandomString
00081 
00082 --ThisRandomString
00083 Content-type: text/plain
00084 
00085 Data for the first object.
00086 
00087 --ThisRandomString
00088 Content-type: text/plain
00089 
00090 Data for the second and last object.
00091 
00092 --ThisRandomString--
00093 */
00094 
00095 
00096 KMultiPart::KMultiPart( QWidget *parentWidget, const char *widgetName,
00097                         QObject *parent, const char *name, const QStringList& )
00098     : KParts::ReadOnlyPart( parent, name )
00099 {
00100     m_filter = 0L;
00101 
00102     setInstance( KMultiPartFactory::instance() );
00103 
00104     QVBox *box = new QVBox( parentWidget, widgetName );
00105     setWidget( box );
00106 
00107     m_extension = new KParts::BrowserExtension( this );
00108 
00109     // We probably need to use m_extension to get the urlArgs in openURL...
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->setAutoDelete( 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     m_url = url;
00157     m_lineParser->reset();
00158     startHeader();
00159 
00160     KParts::URLArgs args = m_extension->urlArgs();
00161     //m_mimeType = args.serviceType;
00162 
00163     // Hmm, args.reload is set to true when reloading, but this doesn't seem to be enough...
00164     // I get "HOLD: Reusing held slave for <url>", and the old data
00165 
00166     m_job = KIO::get( url, args.reload, false );
00167 
00168     emit started( 0 /*m_job*/ ); // don't pass the job, it would interfer with our own infoMessage
00169 
00170     connect( m_job, SIGNAL( result( KIO::Job * ) ),
00171              this, SLOT( slotJobFinished( KIO::Job * ) ) );
00172     connect( m_job, SIGNAL( data( KIO::Job *, const QByteArray & ) ),
00173              this, SLOT( slotData( KIO::Job *, const QByteArray & ) ) );
00174 
00175     m_numberOfFrames = 0;
00176     m_numberOfFramesSkipped = 0;
00177     m_totalNumberOfFrames = 0;
00178     m_qtime.start();
00179     m_timer->start( 1000 ); //1s
00180 
00181     return true;
00182 }
00183 
00184 // Yes, libkdenetwork's has such a parser already (MultiPart),
00185 // but it works on the complete string, expecting the whole data to be available....
00186 // The version here is asynchronous.
00187 void KMultiPart::slotData( KIO::Job *job, const QByteArray &data )
00188 {
00189     if (m_boundary.isNull())
00190     {
00191        QString tmp = job->queryMetaData("media-boundary");
00192        kdDebug() << "Got Boundary from kio-http '" << tmp << "'" << endl;
00193        if ( !tmp.isEmpty() ) {
00194            if (tmp.startsWith("--"))
00195                m_boundary = tmp.latin1();
00196            else
00197                m_boundary = QCString("--")+tmp.latin1();
00198            m_boundaryLength = m_boundary.length();
00199        }
00200     }
00201     // Append to m_currentLine until eol
00202     for ( uint i = 0; i < data.size() ; ++i )
00203     {
00204         // Store char. Skip if '\n' and currently parsing a header.
00205         m_lineParser->addChar( data[i], !m_bParsingHeader );
00206         if ( m_lineParser->isLineComplete() )
00207         {
00208             QByteArray lineData = m_lineParser->currentLine();
00209 #ifdef DEBUG_PARSING
00210             kdDebug() << "lineData.size()=" << lineData.size() << endl;
00211 #endif
00212             QCString line( lineData.data(), lineData.size()+1 ); // deep copy
00213             // 0-terminate the data, but only for the line-based tests below
00214             // We want to keep the raw data in case it ends up in sendData()
00215             int sz = line.size();
00216             if ( sz > 0 )
00217                 line[sz-1] = '\0';
00218 #ifdef DEBUG_PARSING
00219             kdDebug() << "[" << m_bParsingHeader << "] line='" << line << "'" << endl;
00220 #endif
00221             if ( m_bParsingHeader )
00222             {
00223                 if ( !line.isEmpty() )
00224                     m_bGotAnyHeader = true;
00225                 if ( m_boundary.isNull() )
00226                 {
00227                     if ( !line.isEmpty() ) {
00228 #ifdef DEBUG_PARSING
00229                         kdDebug() << "Boundary is " << line << endl;
00230 #endif
00231                         m_boundary = line;
00232                         m_boundaryLength = m_boundary.length();
00233                     }
00234                 }
00235                 else if ( !qstrnicmp( line.data(), "Content-Encoding:", 17 ) )
00236                 {
00237                     QString encoding = QString::fromLatin1(line.data()+17).stripWhiteSpace().lower();
00238                     if (encoding == "gzip" || encoding == "x-gzip") {
00239                         m_gzip = true;
00240                     } else {
00241                         kdDebug() << "FIXME: unhandled encoding type in KMultiPart: " << encoding << endl;
00242                     }
00243                 }
00244                 // parse Content-Type
00245                 else if ( !qstrnicmp( line.data(), "Content-Type:", 13 ) )
00246                 {
00247                     Q_ASSERT( m_nextMimeType.isNull() );
00248                     m_nextMimeType = QString::fromLatin1( line.data() + 14 ).stripWhiteSpace();
00249                     int semicolon = m_nextMimeType.find( ';' );
00250                     if ( semicolon != -1 )
00251                         m_nextMimeType = m_nextMimeType.left( semicolon );
00252                     kdDebug() << "m_nextMimeType=" << m_nextMimeType << endl;
00253                 }
00254                 // Empty line, end of headers (if we had any header line before)
00255                 else if ( line.isEmpty() && m_bGotAnyHeader )
00256                 {
00257                     m_bParsingHeader = false;
00258 #ifdef DEBUG_PARSING
00259                     kdDebug() << "end of headers" << endl;
00260 #endif
00261                     startOfData();
00262                 }
00263                 // First header (when we know it from kio_http)
00264                 else if ( line == m_boundary )
00265                     ; // nothing to do
00266                 else if ( !line.isEmpty() ) // this happens with e.g. Set-Cookie:
00267                     kdDebug() << "Ignoring header " << line << endl;
00268             } else {
00269                 if ( !qstrncmp( line, m_boundary, m_boundaryLength ) )
00270                 {
00271 #ifdef DEBUG_PARSING
00272                     kdDebug() << "boundary found!" << endl;
00273                     kdDebug() << "after it is " << line.data() + m_boundaryLength << endl;
00274 #endif
00275                     // Was it the very last boundary ?
00276                     if ( !qstrncmp( line.data() + m_boundaryLength, "--", 2 ) )
00277                     {
00278 #ifdef DEBUG_PARSING
00279                         kdDebug() << "Completed!" << endl;
00280 #endif
00281                         endOfData();
00282                         emit completed();
00283                     } else
00284                     {
00285                         char nextChar = *(line.data() + m_boundaryLength);
00286 #ifdef DEBUG_PARSING
00287                         kdDebug() << "KMultiPart::slotData nextChar='" << nextChar << "'" << endl;
00288 #endif
00289                         if ( nextChar == '\n' || nextChar == '\r' ) {
00290                             endOfData();
00291                             startHeader();
00292                         }
00293                         else {
00294                             // otherwise, false hit, it has trailing stuff
00295                             sendData( lineData );
00296                         }
00297                     }
00298                 } else {
00299                     // send to part
00300                     sendData( lineData );
00301                 }
00302             }
00303             m_lineParser->clearLine();
00304         }
00305     }
00306 }
00307 
00308 void KMultiPart::setPart( const QString& mimeType )
00309 {
00310     KXMLGUIFactory *guiFactory = factory();
00311     if ( guiFactory ) // seems to be 0 when restoring from SM
00312         guiFactory->removeClient( this );
00313     kdDebug() << "KMultiPart::setPart " << mimeType << endl;
00314     delete m_part;
00315     // Try to find an appropriate viewer component
00316     m_part = KParts::ComponentFactory::createPartInstanceFromQuery<KParts::ReadOnlyPart>
00317              ( m_mimeType, QString::null, widget(), 0L, this, 0L );
00318     if ( !m_part ) {
00319         // TODO launch external app
00320         KMessageBox::error( widget(), i18n("No handler found for %1!").arg(m_mimeType) );
00321         return;
00322     }
00323     // By making the part a child XMLGUIClient of ours, we get its GUI merged in.
00324     insertChildClient( m_part );
00325     m_part->widget()->show();
00326 
00327     connect( m_part, SIGNAL( completed() ),
00328              this, SLOT( slotPartCompleted() ) );
00329 
00330     m_isHTMLPart = ( mimeType == "text/html" );
00331     KParts::BrowserExtension* childExtension = KParts::BrowserExtension::childObject( m_part );
00332 
00333     if ( childExtension )
00334     {
00335 
00336         // Forward signals from the part's browser extension
00337         // this is very related (but not exactly like) KHTMLPart::processObjectRequest
00338 
00339         connect( childExtension, SIGNAL( openURLNotify() ),
00340                  m_extension, SIGNAL( openURLNotify() ) );
00341 
00342         connect( childExtension, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
00343                  m_extension, SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ) );
00344 
00345         connect( childExtension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
00346                  m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
00347         connect( childExtension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
00348                  m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
00349 
00350         // Keep in sync with khtml_part.cpp
00351         connect( childExtension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ),
00352                  m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ) );
00353         connect( childExtension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ),
00354                  m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ) );
00355         connect( childExtension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ),
00356                  m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) );
00357         connect( childExtension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ),
00358                  m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ) );
00359         connect( childExtension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ),
00360                  m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ) );
00361         connect( childExtension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ),
00362                  m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) );
00363 
00364 
00365         if ( m_isHTMLPart )
00366             connect( childExtension, SIGNAL( infoMessage( const QString & ) ),
00367                      m_extension, SIGNAL( infoMessage( const QString & ) ) );
00368         // For non-HTML we prefer to show our infoMessage ourselves.
00369 
00370         childExtension->setBrowserInterface( m_extension->browserInterface() );
00371 
00372         connect( childExtension, SIGNAL( enableAction( const char *, bool ) ),
00373                  m_extension, SIGNAL( enableAction( const char *, bool ) ) );
00374         connect( childExtension, SIGNAL( setLocationBarURL( const QString& ) ),
00375                  m_extension, SIGNAL( setLocationBarURL( const QString& ) ) );
00376         connect( childExtension, SIGNAL( setIconURL( const KURL& ) ),
00377                  m_extension, SIGNAL( setIconURL( const KURL& ) ) );
00378         connect( childExtension, SIGNAL( loadingProgress( int ) ),
00379                  m_extension, SIGNAL( loadingProgress( int ) ) );
00380         if ( m_isHTMLPart ) // for non-HTML we have our own
00381             connect( childExtension, SIGNAL( speedProgress( int ) ),
00382                      m_extension, SIGNAL( speedProgress( int ) ) );
00383         connect( childExtension, SIGNAL( selectionInfo( const KFileItemList& ) ),
00384                  m_extension, SIGNAL( selectionInfo( const KFileItemList& ) ) );
00385         connect( childExtension, SIGNAL( selectionInfo( const QString& ) ),
00386                  m_extension, SIGNAL( selectionInfo( const QString& ) ) );
00387         connect( childExtension, SIGNAL( selectionInfo( const KURL::List& ) ),
00388                  m_extension, SIGNAL( selectionInfo( const KURL::List& ) ) );
00389         connect( childExtension, SIGNAL( mouseOverInfo( const KFileItem* ) ),
00390                  m_extension, SIGNAL( mouseOverInfo( const KFileItem* ) ) );
00391         connect( childExtension, SIGNAL( moveTopLevelWidget( int, int ) ),
00392                  m_extension, SIGNAL( moveTopLevelWidget( int, int ) ) );
00393         connect( childExtension, SIGNAL( resizeTopLevelWidget( int, int ) ),
00394                  m_extension, SIGNAL( resizeTopLevelWidget( int, int ) ) );
00395     }
00396 
00397     m_partIsLoading = false;
00398     // Load the part's plugins too.
00399     // ###### This is a hack. The bug is that KHTMLPart doesn't load its plugins
00400     // if className != "Browser/View".
00401     loadPlugins( this, m_part, m_part->instance() );
00402     // Get the part's GUI to appear
00403     if ( guiFactory )
00404         guiFactory->addClient( this );
00405 }
00406 
00407 void KMultiPart::startOfData()
00408 {
00409     kdDebug() << "KMultiPart::startOfData" << endl;
00410     Q_ASSERT( !m_nextMimeType.isNull() );
00411     if( m_nextMimeType.isNull() )
00412         return;
00413 
00414     if ( m_gzip )
00415     {
00416         m_filter = new HTTPFilterGZip;
00417         connect( m_filter, SIGNAL( output( const QByteArray& ) ), this, SLOT( reallySendData( const QByteArray& ) ) );
00418     }
00419 
00420     if ( m_mimeType != m_nextMimeType )
00421     {
00422         // Need to switch parts (or create the initial one)
00423         m_mimeType = m_nextMimeType;
00424         setPart( m_mimeType );
00425     }
00426     Q_ASSERT( m_part );
00427     // Pass URLArgs (e.g. reload)
00428     KParts::BrowserExtension* childExtension = KParts::BrowserExtension::childObject( m_part );
00429     if ( childExtension )
00430         childExtension->setURLArgs( m_extension->urlArgs() );
00431 
00432     m_nextMimeType = QString::null;
00433     if ( m_tempFile ) {
00434         m_tempFile->setAutoDelete( true );
00435         delete m_tempFile;
00436         m_tempFile = 0;
00437     }
00438     if ( m_isHTMLPart )
00439     {
00440         KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) );
00441         htmlPart->begin( url() );
00442     }
00443     else
00444     {
00445         // ###### TODO use a QByteArray and a data: URL instead
00446         m_tempFile = new KTempFile;
00447     }
00448 }
00449 
00450 void KMultiPart::sendData( const QByteArray& line )
00451 {
00452     if ( m_filter )
00453     {
00454         m_filter->slotInput( line );
00455     }
00456     else
00457     {
00458         reallySendData( line );
00459     }
00460 }
00461 
00462 void KMultiPart::reallySendData( const QByteArray& line )
00463 {
00464     if ( m_isHTMLPart )
00465     {
00466         KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) );
00467         htmlPart->write( line.data(), line.size() );
00468     }
00469     else if ( m_tempFile )
00470     {
00471         m_tempFile->file()->writeBlock( line.data(), line.size() );
00472     }
00473 }
00474 
00475 void KMultiPart::endOfData()
00476 {
00477     Q_ASSERT( m_part );
00478     if ( m_isHTMLPart )
00479     {
00480         KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) );
00481         htmlPart->end();
00482     } else if ( m_tempFile )
00483     {
00484         m_tempFile->close();
00485         if ( m_partIsLoading )
00486         {
00487             // The part is still loading the last data! Let it proceed then
00488             // Otherwise we'd keep cancelling it, and nothing would ever show up...
00489             kdDebug() << "KMultiPart::endOfData part isn't ready, skipping frame" << endl;
00490             ++m_numberOfFramesSkipped;
00491             m_tempFile->setAutoDelete( true );
00492         }
00493         else
00494         {
00495             kdDebug() << "KMultiPart::endOfData opening " << m_tempFile->name() << endl;
00496             KURL url;
00497             url.setPath( m_tempFile->name() );
00498             m_partIsLoading = true;
00499             (void) m_part->openURL( url );
00500         }
00501         delete m_tempFile;
00502         m_tempFile = 0L;
00503     }
00504 }
00505 
00506 void KMultiPart::slotPartCompleted()
00507 {
00508     if ( !m_isHTMLPart )
00509     {
00510         Q_ASSERT( m_part );
00511         // Delete temp file used by the part
00512         Q_ASSERT( m_part->url().isLocalFile() );
00513     kdDebug() << "slotPartCompleted deleting " << m_part->url().path() << endl;
00514         (void) unlink( QFile::encodeName( m_part->url().path() ) );
00515         m_partIsLoading = false;
00516         ++m_numberOfFrames;
00517         // Do not emit completed from here.
00518     }
00519 }
00520 
00521 bool KMultiPart::closeURL()
00522 {
00523     m_timer->stop();
00524     if ( m_part )
00525         return m_part->closeURL();
00526     return true;
00527 }
00528 
00529 void KMultiPart::guiActivateEvent( KParts::GUIActivateEvent * )
00530 {
00531     // Not public!
00532     //if ( m_part )
00533     //    m_part->guiActivateEvent( e );
00534 }
00535 
00536 void KMultiPart::slotJobFinished( KIO::Job *job )
00537 {
00538     if ( job->error() )
00539     {
00540         // TODO use khtml's error:// scheme
00541         job->showErrorDialog();
00542         emit canceled( job->errorString() );
00543     }
00544     else
00545     {
00546         /*if ( m_khtml->view()->contentsY() == 0 )
00547         {
00548             KParts::URLArgs args = m_ext->urlArgs();
00549             m_khtml->view()->setContentsPos( args.xOffset, args.yOffset );
00550         }*/
00551 
00552         emit completed();
00553 
00554         //QTimer::singleShot( 0, this, SLOT( updateWindowCaption() ) );
00555     }
00556     m_job = 0L;
00557 }
00558 
00559 void KMultiPart::slotProgressInfo()
00560 {
00561     int time = m_qtime.elapsed();
00562     if ( !time ) return;
00563     if ( m_totalNumberOfFrames == m_numberOfFrames + m_numberOfFramesSkipped )
00564         return; // No change, don't overwrite statusbar messages if any
00565     //kdDebug() << m_numberOfFrames << " in " << time << " milliseconds" << endl;
00566     QString str( "%1 frames per second, %2 frames skipped per second" );
00567     str = str.arg( 1000.0 * (double)m_numberOfFrames / (double)time );
00568     str = str.arg( 1000.0 * (double)m_numberOfFramesSkipped / (double)time );
00569     m_totalNumberOfFrames = m_numberOfFrames + m_numberOfFramesSkipped;
00570     //kdDebug() << str << endl;
00571     emit m_extension->infoMessage( str );
00572 }
00573 
00574 KAboutData* KMultiPart::createAboutData()
00575 {
00576     KAboutData* aboutData = new KAboutData( "kmultipart", I18N_NOOP("KMultiPart"),
00577                                              "0.1",
00578                                             I18N_NOOP( "Embeddable component for multipart/mixed" ),
00579                                              KAboutData::License_GPL,
00580                                              "(c) 2001, David Faure <david@mandrakesoft.com>");
00581     return aboutData;
00582 }
00583 
00584 #if 0
00585 KMultiPartBrowserExtension::KMultiPartBrowserExtension( KMultiPart *parent, const char *name )
00586     : KParts::BrowserExtension( parent, name )
00587 {
00588     m_imgPart = parent;
00589 }
00590 
00591 int KMultiPartBrowserExtension::xOffset()
00592 {
00593     return m_imgPart->doc()->view()->contentsX();
00594 }
00595 
00596 int KMultiPartBrowserExtension::yOffset()
00597 {
00598     return m_imgPart->doc()->view()->contentsY();
00599 }
00600 
00601 void KMultiPartBrowserExtension::print()
00602 {
00603     static_cast<KHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->print();
00604 }
00605 
00606 void KMultiPartBrowserExtension::reparseConfiguration()
00607 {
00608     static_cast<KHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->reparseConfiguration();
00609     m_imgPart->doc()->setAutoloadImages( true );
00610 }
00611 #endif
00612 
00613 #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

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
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