khtml Library API Documentation

kmultipart.cpp

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., 59 Temple Place - Suite 330, 00017 Boston, MA 02111-1307, 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 m_boundary = QCString("--")+tmp.latin1(); 00195 m_boundaryLength = m_boundary.length(); 00196 } 00197 } 00198 // Append to m_currentLine until eol 00199 for ( uint i = 0; i < data.size() ; ++i ) 00200 { 00201 // Store char. Skip if '\n' and currently parsing a header. 00202 m_lineParser->addChar( data[i], !m_bParsingHeader ); 00203 if ( m_lineParser->isLineComplete() ) 00204 { 00205 QByteArray lineData = m_lineParser->currentLine(); 00206 #ifdef DEBUG_PARSING 00207 kdDebug() << "lineData.size()=" << lineData.size() << endl; 00208 #endif 00209 QCString line( lineData.data(), lineData.size()+1 ); // deep copy 00210 // 0-terminate the data, but only for the line-based tests below 00211 // We want to keep the raw data in case it ends up in sendData() 00212 int sz = line.size(); 00213 if ( sz > 0 ) 00214 line[sz-1] = '\0'; 00215 #ifdef DEBUG_PARSING 00216 kdDebug() << "[" << m_bParsingHeader << "] line='" << line << "'" << endl; 00217 #endif 00218 if ( m_bParsingHeader ) 00219 { 00220 if ( !line.isEmpty() ) 00221 m_bGotAnyHeader = true; 00222 if ( m_boundary.isNull() ) 00223 { 00224 if ( !line.isEmpty() ) { 00225 #ifdef DEBUG_PARSING 00226 kdDebug() << "Boundary is " << line << endl; 00227 #endif 00228 m_boundary = line; 00229 m_boundaryLength = m_boundary.length(); 00230 } 00231 } 00232 else if ( !qstrnicmp( line.data(), "Content-Encoding:", 17 ) ) 00233 { 00234 QString encoding = QString::fromLatin1(line.data()+17).stripWhiteSpace().lower(); 00235 if (encoding == "gzip" || encoding == "x-gzip") { 00236 m_gzip = true; 00237 } else { 00238 kdDebug() << "FIXME: unhandled encoding type in KMultiPart: " << encoding << endl; 00239 } 00240 } 00241 // parse Content-Type 00242 else if ( !qstrnicmp( line.data(), "Content-Type:", 13 ) ) 00243 { 00244 Q_ASSERT( m_nextMimeType.isNull() ); 00245 m_nextMimeType = QString::fromLatin1( line.data() + 14 ).stripWhiteSpace(); 00246 int semicolon = m_nextMimeType.find( ';' ); 00247 if ( semicolon != -1 ) 00248 m_nextMimeType = m_nextMimeType.left( semicolon ); 00249 kdDebug() << "m_nextMimeType=" << m_nextMimeType << endl; 00250 } 00251 // Empty line, end of headers (if we had any header line before) 00252 else if ( line.isEmpty() && m_bGotAnyHeader ) 00253 { 00254 m_bParsingHeader = false; 00255 #ifdef DEBUG_PARSING 00256 kdDebug() << "end of headers" << endl; 00257 #endif 00258 startOfData(); 00259 } 00260 // First header (when we know it from kio_http) 00261 else if ( line == m_boundary ) 00262 ; // nothing to do 00263 else if ( !line.isEmpty() ) // this happens with e.g. Set-Cookie: 00264 kdDebug() << "Ignoring header " << line << endl; 00265 } else { 00266 if ( !qstrncmp( line, m_boundary, m_boundaryLength ) ) 00267 { 00268 #ifdef DEBUG_PARSING 00269 kdDebug() << "boundary found!" << endl; 00270 kdDebug() << "after it is " << line.data() + m_boundaryLength << endl; 00271 #endif 00272 // Was it the very last boundary ? 00273 if ( !qstrncmp( line.data() + m_boundaryLength, "--", 2 ) ) 00274 { 00275 #ifdef DEBUG_PARSING 00276 kdDebug() << "Completed!" << endl; 00277 #endif 00278 endOfData(); 00279 emit completed(); 00280 } else 00281 { 00282 char nextChar = *(line.data() + m_boundaryLength); 00283 #ifdef DEBUG_PARSING 00284 kdDebug() << "KMultiPart::slotData nextChar='" << nextChar << "'" << endl; 00285 #endif 00286 if ( nextChar == '\n' || nextChar == '\r' ) { 00287 endOfData(); 00288 startHeader(); 00289 } 00290 else { 00291 // otherwise, false hit, it has trailing stuff 00292 sendData( lineData ); 00293 } 00294 } 00295 } else { 00296 // send to part 00297 sendData( lineData ); 00298 } 00299 } 00300 m_lineParser->clearLine(); 00301 } 00302 } 00303 } 00304 00305 void KMultiPart::setPart( const QString& mimeType ) 00306 { 00307 KXMLGUIFactory *guiFactory = factory(); 00308 if ( guiFactory ) // seems to be 0 when restoring from SM 00309 guiFactory->removeClient( this ); 00310 kdDebug() << "KMultiPart::setPart " << mimeType << endl; 00311 delete m_part; 00312 // Try to find an appropriate viewer component 00313 m_part = KParts::ComponentFactory::createPartInstanceFromQuery<KParts::ReadOnlyPart> 00314 ( m_mimeType, QString::null, widget(), 0L, this, 0L ); 00315 if ( !m_part ) { 00316 // TODO launch external app 00317 KMessageBox::error( widget(), i18n("No handler found for %1!").arg(m_mimeType) ); 00318 return; 00319 } 00320 // By making the part a child XMLGUIClient of ours, we get its GUI merged in. 00321 insertChildClient( m_part ); 00322 m_part->widget()->show(); 00323 00324 connect( m_part, SIGNAL( completed() ), 00325 this, SLOT( slotPartCompleted() ) ); 00326 00327 m_isHTMLPart = ( mimeType == "text/html" ); 00328 KParts::BrowserExtension* childExtension = KParts::BrowserExtension::childObject( m_part ); 00329 00330 if ( childExtension ) 00331 { 00332 00333 // Forward signals from the part's browser extension 00334 // this is very related (but not exactly like) KHTMLPart::processObjectRequest 00335 00336 connect( childExtension, SIGNAL( openURLNotify() ), 00337 m_extension, SIGNAL( openURLNotify() ) ); 00338 00339 connect( childExtension, SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ), 00340 m_extension, SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ) ); 00341 00342 connect( childExtension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ), 00343 m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) ); 00344 connect( childExtension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ), 00345 m_extension, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) ); 00346 00347 // Keep in sync with khtml_part.cpp 00348 connect( childExtension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ), 00349 m_extension, SIGNAL( popupMenu( const QPoint &, const KFileItemList & ) ) ); 00350 connect( childExtension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ), 00351 m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList & ) ) ); 00352 connect( childExtension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ), 00353 m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) ); 00354 connect( childExtension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ), 00355 m_extension, SIGNAL( popupMenu( const QPoint &, const KURL &, const QString &, mode_t ) ) ); 00356 connect( childExtension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ), 00357 m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const QString &, mode_t ) ) ); 00358 connect( childExtension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ), 00359 m_extension, SIGNAL( popupMenu( KXMLGUIClient *, const QPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) ); 00360 00361 00362 if ( m_isHTMLPart ) 00363 connect( childExtension, SIGNAL( infoMessage( const QString & ) ), 00364 m_extension, SIGNAL( infoMessage( const QString & ) ) ); 00365 // For non-HTML we prefer to show our infoMessage ourselves. 00366 00367 childExtension->setBrowserInterface( m_extension->browserInterface() ); 00368 00369 connect( childExtension, SIGNAL( enableAction( const char *, bool ) ), 00370 m_extension, SIGNAL( enableAction( const char *, bool ) ) ); 00371 connect( childExtension, SIGNAL( setLocationBarURL( const QString& ) ), 00372 m_extension, SIGNAL( setLocationBarURL( const QString& ) ) ); 00373 connect( childExtension, SIGNAL( setIconURL( const KURL& ) ), 00374 m_extension, SIGNAL( setIconURL( const KURL& ) ) ); 00375 connect( childExtension, SIGNAL( loadingProgress( int ) ), 00376 m_extension, SIGNAL( loadingProgress( int ) ) ); 00377 if ( m_isHTMLPart ) // for non-HTML we have our own 00378 connect( childExtension, SIGNAL( speedProgress( int ) ), 00379 m_extension, SIGNAL( speedProgress( int ) ) ); 00380 connect( childExtension, SIGNAL( selectionInfo( const KFileItemList& ) ), 00381 m_extension, SIGNAL( selectionInfo( const KFileItemList& ) ) ); 00382 connect( childExtension, SIGNAL( selectionInfo( const QString& ) ), 00383 m_extension, SIGNAL( selectionInfo( const QString& ) ) ); 00384 connect( childExtension, SIGNAL( selectionInfo( const KURL::List& ) ), 00385 m_extension, SIGNAL( selectionInfo( const KURL::List& ) ) ); 00386 connect( childExtension, SIGNAL( mouseOverInfo( const KFileItem* ) ), 00387 m_extension, SIGNAL( mouseOverInfo( const KFileItem* ) ) ); 00388 connect( childExtension, SIGNAL( moveTopLevelWidget( int, int ) ), 00389 m_extension, SIGNAL( moveTopLevelWidget( int, int ) ) ); 00390 connect( childExtension, SIGNAL( resizeTopLevelWidget( int, int ) ), 00391 m_extension, SIGNAL( resizeTopLevelWidget( int, int ) ) ); 00392 } 00393 00394 m_partIsLoading = false; 00395 // Load the part's plugins too. 00396 // ###### This is a hack. The bug is that KHTMLPart doesn't load its plugins 00397 // if className != "Browser/View". 00398 loadPlugins( this, m_part, m_part->instance() ); 00399 // Get the part's GUI to appear 00400 if ( guiFactory ) 00401 guiFactory->addClient( this ); 00402 } 00403 00404 void KMultiPart::startOfData() 00405 { 00406 kdDebug() << "KMultiPart::startOfData" << endl; 00407 Q_ASSERT( !m_nextMimeType.isNull() ); 00408 if( m_nextMimeType.isNull() ) 00409 return; 00410 00411 if ( m_gzip ) 00412 { 00413 m_filter = new HTTPFilterGZip; 00414 connect( m_filter, SIGNAL( output( const QByteArray& ) ), this, SLOT( reallySendData( const QByteArray& ) ) ); 00415 } 00416 00417 if ( m_mimeType != m_nextMimeType ) 00418 { 00419 // Need to switch parts (or create the initial one) 00420 m_mimeType = m_nextMimeType; 00421 setPart( m_mimeType ); 00422 } 00423 Q_ASSERT( m_part ); 00424 // Pass URLArgs (e.g. reload) 00425 KParts::BrowserExtension* childExtension = KParts::BrowserExtension::childObject( m_part ); 00426 if ( childExtension ) 00427 childExtension->setURLArgs( m_extension->urlArgs() ); 00428 00429 m_nextMimeType = QString::null; 00430 if ( m_tempFile ) { 00431 m_tempFile->setAutoDelete( true ); 00432 delete m_tempFile; 00433 m_tempFile = 0; 00434 } 00435 if ( m_isHTMLPart ) 00436 { 00437 KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) ); 00438 htmlPart->begin( url() ); 00439 } 00440 else 00441 { 00442 // ###### TODO use a QByteArray and a data: URL instead 00443 m_tempFile = new KTempFile; 00444 } 00445 } 00446 00447 void KMultiPart::sendData( const QByteArray& line ) 00448 { 00449 if ( m_filter ) 00450 { 00451 m_filter->slotInput( line ); 00452 } 00453 else 00454 { 00455 reallySendData( line ); 00456 } 00457 } 00458 00459 void KMultiPart::reallySendData( const QByteArray& line ) 00460 { 00461 if ( m_isHTMLPart ) 00462 { 00463 KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) ); 00464 htmlPart->write( line.data(), line.size() ); 00465 } 00466 else if ( m_tempFile ) 00467 { 00468 m_tempFile->file()->writeBlock( line.data(), line.size() ); 00469 } 00470 } 00471 00472 void KMultiPart::endOfData() 00473 { 00474 Q_ASSERT( m_part ); 00475 if ( m_isHTMLPart ) 00476 { 00477 KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) ); 00478 htmlPart->end(); 00479 } else if ( m_tempFile ) 00480 { 00481 m_tempFile->close(); 00482 if ( m_partIsLoading ) 00483 { 00484 // The part is still loading the last data! Let it proceed then 00485 // Otherwise we'd keep cancelling it, and nothing would ever show up... 00486 kdDebug() << "KMultiPart::endOfData part isn't ready, skipping frame" << endl; 00487 ++m_numberOfFramesSkipped; 00488 m_tempFile->setAutoDelete( true ); 00489 } 00490 else 00491 { 00492 kdDebug() << "KMultiPart::endOfData opening " << m_tempFile->name() << endl; 00493 KURL url; 00494 url.setPath( m_tempFile->name() ); 00495 m_partIsLoading = true; 00496 (void) m_part->openURL( url ); 00497 } 00498 delete m_tempFile; 00499 m_tempFile = 0L; 00500 } 00501 } 00502 00503 void KMultiPart::slotPartCompleted() 00504 { 00505 if ( !m_isHTMLPart ) 00506 { 00507 Q_ASSERT( m_part ); 00508 // Delete temp file used by the part 00509 Q_ASSERT( m_part->url().isLocalFile() ); 00510 kdDebug() << "slotPartCompleted deleting " << m_part->url().path() << endl; 00511 (void) unlink( QFile::encodeName( m_part->url().path() ) ); 00512 m_partIsLoading = false; 00513 ++m_numberOfFrames; 00514 // Do not emit completed from here. 00515 } 00516 } 00517 00518 bool KMultiPart::closeURL() 00519 { 00520 m_timer->stop(); 00521 if ( m_part ) 00522 return m_part->closeURL(); 00523 return true; 00524 } 00525 00526 void KMultiPart::guiActivateEvent( KParts::GUIActivateEvent * ) 00527 { 00528 // Not public! 00529 //if ( m_part ) 00530 // m_part->guiActivateEvent( e ); 00531 } 00532 00533 void KMultiPart::slotJobFinished( KIO::Job *job ) 00534 { 00535 if ( job->error() ) 00536 { 00537 // TODO use khtml's error:// scheme 00538 job->showErrorDialog(); 00539 emit canceled( job->errorString() ); 00540 } 00541 else 00542 { 00543 /*if ( m_khtml->view()->contentsY() == 0 ) 00544 { 00545 KParts::URLArgs args = m_ext->urlArgs(); 00546 m_khtml->view()->setContentsPos( args.xOffset, args.yOffset ); 00547 }*/ 00548 00549 emit completed(); 00550 00551 //QTimer::singleShot( 0, this, SLOT( updateWindowCaption() ) ); 00552 } 00553 m_job = 0L; 00554 } 00555 00556 void KMultiPart::slotProgressInfo() 00557 { 00558 int time = m_qtime.elapsed(); 00559 if ( !time ) return; 00560 if ( m_totalNumberOfFrames == m_numberOfFrames + m_numberOfFramesSkipped ) 00561 return; // No change, don't overwrite statusbar messages if any 00562 //kdDebug() << m_numberOfFrames << " in " << time << " milliseconds" << endl; 00563 QString str( "%1 frames per second, %2 frames skipped per second" ); 00564 str = str.arg( 1000.0 * (double)m_numberOfFrames / (double)time ); 00565 str = str.arg( 1000.0 * (double)m_numberOfFramesSkipped / (double)time ); 00566 m_totalNumberOfFrames = m_numberOfFrames + m_numberOfFramesSkipped; 00567 //kdDebug() << str << endl; 00568 emit m_extension->infoMessage( str ); 00569 } 00570 00571 KAboutData* KMultiPart::createAboutData() 00572 { 00573 KAboutData* aboutData = new KAboutData( "kmultipart", I18N_NOOP("KMultiPart"), 00574 "0.1", 00575 I18N_NOOP( "Embeddable component for multipart/mixed" ), 00576 KAboutData::License_GPL, 00577 "(c) 2001, David Faure <david@mandrakesoft.com>"); 00578 return aboutData; 00579 } 00580 00581 #if 0 00582 KMultiPartBrowserExtension::KMultiPartBrowserExtension( KMultiPart *parent, const char *name ) 00583 : KParts::BrowserExtension( parent, name ) 00584 { 00585 m_imgPart = parent; 00586 } 00587 00588 int KMultiPartBrowserExtension::xOffset() 00589 { 00590 return m_imgPart->doc()->view()->contentsX(); 00591 } 00592 00593 int KMultiPartBrowserExtension::yOffset() 00594 { 00595 return m_imgPart->doc()->view()->contentsY(); 00596 } 00597 00598 void KMultiPartBrowserExtension::print() 00599 { 00600 static_cast<KHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->print(); 00601 } 00602 00603 void KMultiPartBrowserExtension::reparseConfiguration() 00604 { 00605 static_cast<KHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->reparseConfiguration(); 00606 m_imgPart->doc()->setAutoloadImages( true ); 00607 } 00608 #endif 00609 00610 #include "kmultipart.moc"
KDE Logo
This file is part of the documentation for khtml Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 23:31:35 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003