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