TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tdemultipart.cpp 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613
  1. /* This file is part of the KDE project
  2. Copyright (C) 2002 David Faure <david@mandrakesoft.com>
  3. This library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public
  5. License as published by the Free Software Foundation; either
  6. version 2 of the License, or (at your option) any later version.
  7. This library is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. Library General Public License for more details.
  11. You should have received a copy of the GNU Library General Public License
  12. along with this library; see the file COPYING.LIB. If not, write to
  13. the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  14. Boston, MA 02110-1301, USA.
  15. */
  16. #include "tdemultipart.h"
  17. #include <tqvbox.h>
  18. #include <kinstance.h>
  19. #include <kmimetype.h>
  20. #include <klocale.h>
  21. #include <tdeio/job.h>
  22. #include <tqfile.h>
  23. #include <ktempfile.h>
  24. #include <kmessagebox.h>
  25. #include <tdeparts/componentfactory.h>
  26. #include <tdeparts/genericfactory.h>
  27. #include <tdehtml_part.h>
  28. #include <unistd.h>
  29. #include <kxmlguifactory.h>
  30. #include <tqtimer.h>
  31. typedef KParts::GenericFactory<KMultiPart> KMultiPartFactory; // factory for the part
  32. K_EXPORT_COMPONENT_FACTORY( libtdemultipart /*library name*/, KMultiPartFactory )
  33. //#define DEBUG_PARSING
  34. class KLineParser
  35. {
  36. public:
  37. KLineParser() {
  38. m_lineComplete = false;
  39. }
  40. void addChar( char c, bool storeNewline ) {
  41. if ( !storeNewline && c == '\r' )
  42. return;
  43. Q_ASSERT( !m_lineComplete );
  44. if ( storeNewline || c != '\n' ) {
  45. int sz = m_currentLine.size();
  46. m_currentLine.resize( sz+1, TQGArray::SpeedOptim );
  47. m_currentLine[sz] = c;
  48. }
  49. if ( c == '\n' )
  50. m_lineComplete = true;
  51. }
  52. bool isLineComplete() const {
  53. return m_lineComplete;
  54. }
  55. TQByteArray currentLine() const {
  56. return m_currentLine;
  57. }
  58. void clearLine() {
  59. Q_ASSERT( m_lineComplete );
  60. reset();
  61. }
  62. void reset() {
  63. m_currentLine.resize( 0, TQGArray::SpeedOptim );
  64. m_lineComplete = false;
  65. }
  66. private:
  67. TQByteArray m_currentLine;
  68. bool m_lineComplete; // true when ending with '\n'
  69. };
  70. /* testcase:
  71. Content-type: multipart/mixed;boundary=ThisRandomString
  72. --ThisRandomString
  73. Content-type: text/plain
  74. Data for the first object.
  75. --ThisRandomString
  76. Content-type: text/plain
  77. Data for the second and last object.
  78. --ThisRandomString--
  79. */
  80. KMultiPart::KMultiPart( TQWidget *parentWidget, const char *widgetName,
  81. TQObject *parent, const char *name, const TQStringList& )
  82. : KParts::ReadOnlyPart( parent, name )
  83. {
  84. m_filter = 0L;
  85. setInstance( KMultiPartFactory::instance() );
  86. TQVBox *box = new TQVBox( parentWidget, widgetName );
  87. setWidget( box );
  88. m_extension = new KParts::BrowserExtension( this );
  89. // We probably need to use m_extension to get the urlArgs in openURL...
  90. m_part = 0L;
  91. m_isHTMLPart = false;
  92. m_job = 0L;
  93. m_lineParser = new KLineParser;
  94. m_tempFile = 0L;
  95. m_timer = new TQTimer( this );
  96. connect( m_timer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotProgressInfo() ) );
  97. }
  98. KMultiPart::~KMultiPart()
  99. {
  100. // important: delete the nested part before the part or qobject destructor runs.
  101. // we now delete the nested part which deletes the part's widget which makes
  102. // _OUR_ m_widget 0 which in turn avoids our part destructor to delete the
  103. // widget ;-)
  104. // ### additional note: it _can_ be that the part has been deleted before:
  105. // when we're in a html frameset and the view dies first, then it will also
  106. // kill the htmlpart
  107. if ( m_part )
  108. delete static_cast<KParts::ReadOnlyPart *>( m_part );
  109. delete m_job;
  110. delete m_lineParser;
  111. if ( m_tempFile ) {
  112. m_tempFile->setAutoDelete( true );
  113. delete m_tempFile;
  114. }
  115. delete m_filter;
  116. m_filter = 0L;
  117. }
  118. void KMultiPart::startHeader()
  119. {
  120. m_bParsingHeader = true; // we expect a header to come first
  121. m_bGotAnyHeader = false;
  122. m_gzip = false;
  123. // just to be sure for now
  124. delete m_filter;
  125. m_filter = 0L;
  126. }
  127. bool KMultiPart::openURL( const KURL &url )
  128. {
  129. m_url = url;
  130. m_lineParser->reset();
  131. startHeader();
  132. KParts::URLArgs args = m_extension->urlArgs();
  133. //m_mimeType = args.serviceType;
  134. // Hmm, args.reload is set to true when reloading, but this doesn't seem to be enough...
  135. // I get "HOLD: Reusing held slave for <url>", and the old data
  136. m_job = TDEIO::get( url, args.reload, false );
  137. emit started( 0 /*m_job*/ ); // don't pass the job, it would interfer with our own infoMessage
  138. connect( m_job, TQT_SIGNAL( result( TDEIO::Job * ) ),
  139. this, TQT_SLOT( slotJobFinished( TDEIO::Job * ) ) );
  140. connect( m_job, TQT_SIGNAL( data( TDEIO::Job *, const TQByteArray & ) ),
  141. this, TQT_SLOT( slotData( TDEIO::Job *, const TQByteArray & ) ) );
  142. m_numberOfFrames = 0;
  143. m_numberOfFramesSkipped = 0;
  144. m_totalNumberOfFrames = 0;
  145. m_qtime.start();
  146. m_timer->start( 1000 ); //1s
  147. return true;
  148. }
  149. // Yes, libtdenetwork's has such a parser already (MultiPart),
  150. // but it works on the complete string, expecting the whole data to be available....
  151. // The version here is asynchronous.
  152. void KMultiPart::slotData( TDEIO::Job *job, const TQByteArray &data )
  153. {
  154. if (m_boundary.isNull())
  155. {
  156. TQString tmp = job->queryMetaData("media-boundary");
  157. kdDebug() << "Got Boundary from kio-http '" << tmp << "'" << endl;
  158. if ( !tmp.isEmpty() ) {
  159. if (tmp.startsWith("--"))
  160. m_boundary = tmp.latin1();
  161. else
  162. m_boundary = TQCString("--")+tmp.latin1();
  163. m_boundaryLength = m_boundary.length();
  164. }
  165. }
  166. // Append to m_currentLine until eol
  167. for ( uint i = 0; i < data.size() ; ++i )
  168. {
  169. // Store char. Skip if '\n' and currently parsing a header.
  170. m_lineParser->addChar( data[i], !m_bParsingHeader );
  171. if ( m_lineParser->isLineComplete() )
  172. {
  173. TQByteArray lineData = m_lineParser->currentLine();
  174. #ifdef DEBUG_PARSING
  175. kdDebug() << "lineData.size()=" << lineData.size() << endl;
  176. #endif
  177. TQCString line( lineData.data(), lineData.size()+1 ); // deep copy
  178. // 0-terminate the data, but only for the line-based tests below
  179. // We want to keep the raw data in case it ends up in sendData()
  180. int sz = line.size();
  181. if ( sz > 0 )
  182. line[sz-1] = '\0';
  183. #ifdef DEBUG_PARSING
  184. kdDebug() << "[" << m_bParsingHeader << "] line='" << line << "'" << endl;
  185. #endif
  186. if ( m_bParsingHeader )
  187. {
  188. if ( !line.isEmpty() )
  189. m_bGotAnyHeader = true;
  190. if ( m_boundary.isNull() )
  191. {
  192. if ( !line.isEmpty() ) {
  193. #ifdef DEBUG_PARSING
  194. kdDebug() << "Boundary is " << line << endl;
  195. #endif
  196. m_boundary = line;
  197. m_boundaryLength = m_boundary.length();
  198. }
  199. }
  200. else if ( !tqstrnicmp( line.data(), "Content-Encoding:", 17 ) )
  201. {
  202. TQString encoding = TQString::fromLatin1(line.data()+17).stripWhiteSpace().lower();
  203. if (encoding == "gzip" || encoding == "x-gzip") {
  204. m_gzip = true;
  205. } else {
  206. kdDebug() << "FIXME: unhandled encoding type in KMultiPart: " << encoding << endl;
  207. }
  208. }
  209. // parse Content-Type
  210. else if ( !tqstrnicmp( line.data(), "Content-Type:", 13 ) )
  211. {
  212. Q_ASSERT( m_nextMimeType.isNull() );
  213. m_nextMimeType = TQString::fromLatin1( line.data() + 14 ).stripWhiteSpace();
  214. int semicolon = m_nextMimeType.find( ';' );
  215. if ( semicolon != -1 )
  216. m_nextMimeType = m_nextMimeType.left( semicolon );
  217. kdDebug() << "m_nextMimeType=" << m_nextMimeType << endl;
  218. }
  219. // Empty line, end of headers (if we had any header line before)
  220. else if ( line.isEmpty() && m_bGotAnyHeader )
  221. {
  222. m_bParsingHeader = false;
  223. #ifdef DEBUG_PARSING
  224. kdDebug() << "end of headers" << endl;
  225. #endif
  226. startOfData();
  227. }
  228. // First header (when we know it from tdeio_http)
  229. else if ( line == m_boundary )
  230. ; // nothing to do
  231. else if ( !line.isEmpty() ) // this happens with e.g. Set-Cookie:
  232. kdDebug() << "Ignoring header " << line << endl;
  233. } else {
  234. if ( !tqstrncmp( line, m_boundary, m_boundaryLength ) )
  235. {
  236. #ifdef DEBUG_PARSING
  237. kdDebug() << "boundary found!" << endl;
  238. kdDebug() << "after it is " << line.data() + m_boundaryLength << endl;
  239. #endif
  240. // Was it the very last boundary ?
  241. if ( !tqstrncmp( line.data() + m_boundaryLength, "--", 2 ) )
  242. {
  243. #ifdef DEBUG_PARSING
  244. kdDebug() << "Completed!" << endl;
  245. #endif
  246. endOfData();
  247. emit completed();
  248. } else
  249. {
  250. char nextChar = *(line.data() + m_boundaryLength);
  251. #ifdef DEBUG_PARSING
  252. kdDebug() << "KMultiPart::slotData nextChar='" << nextChar << "'" << endl;
  253. #endif
  254. if ( nextChar == '\n' || nextChar == '\r' ) {
  255. endOfData();
  256. startHeader();
  257. }
  258. else {
  259. // otherwise, false hit, it has trailing stuff
  260. sendData( lineData );
  261. }
  262. }
  263. } else {
  264. // send to part
  265. sendData( lineData );
  266. }
  267. }
  268. m_lineParser->clearLine();
  269. }
  270. }
  271. }
  272. void KMultiPart::setPart( const TQString& mimeType )
  273. {
  274. KXMLGUIFactory *guiFactory = factory();
  275. if ( guiFactory ) // seems to be 0 when restoring from SM
  276. guiFactory->removeClient( this );
  277. kdDebug() << "KMultiPart::setPart " << mimeType << endl;
  278. delete m_part;
  279. // Try to find an appropriate viewer component
  280. m_part = KParts::ComponentFactory::createPartInstanceFromQuery<KParts::ReadOnlyPart>
  281. ( m_mimeType, TQString::null, widget(), 0L, this, 0L );
  282. if ( !m_part ) {
  283. // TODO launch external app
  284. KMessageBox::error( widget(), i18n("No handler found for %1!").arg(m_mimeType) );
  285. return;
  286. }
  287. // By making the part a child XMLGUIClient of ours, we get its GUI merged in.
  288. insertChildClient( m_part );
  289. m_part->widget()->show();
  290. connect( m_part, TQT_SIGNAL( completed() ),
  291. this, TQT_SLOT( slotPartCompleted() ) );
  292. m_isHTMLPart = ( mimeType == "text/html" );
  293. KParts::BrowserExtension* childExtension = KParts::BrowserExtension::childObject( m_part );
  294. if ( childExtension )
  295. {
  296. // Forward signals from the part's browser extension
  297. // this is very related (but not exactly like) TDEHTMLPart::processObjectRequest
  298. connect( childExtension, TQT_SIGNAL( openURLNotify() ),
  299. m_extension, TQT_SIGNAL( openURLNotify() ) );
  300. connect( childExtension, TQT_SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ),
  301. m_extension, TQT_SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ) );
  302. connect( childExtension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ),
  303. m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) );
  304. connect( childExtension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ),
  305. m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) );
  306. // Keep in sync with tdehtml_part.cpp
  307. connect( childExtension, TQT_SIGNAL( popupMenu( const TQPoint &, const KFileItemList & ) ),
  308. m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KFileItemList & ) ) );
  309. connect( childExtension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList & ) ),
  310. m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList & ) ) );
  311. connect( childExtension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ),
  312. m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) );
  313. connect( childExtension, TQT_SIGNAL( popupMenu( const TQPoint &, const KURL &, const TQString &, mode_t ) ),
  314. m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KURL &, const TQString &, mode_t ) ) );
  315. connect( childExtension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const TQString &, mode_t ) ),
  316. m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const TQString &, mode_t ) ) );
  317. connect( childExtension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ),
  318. m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) );
  319. if ( m_isHTMLPart )
  320. connect( childExtension, TQT_SIGNAL( infoMessage( const TQString & ) ),
  321. m_extension, TQT_SIGNAL( infoMessage( const TQString & ) ) );
  322. // For non-HTML we prefer to show our infoMessage ourselves.
  323. childExtension->setBrowserInterface( m_extension->browserInterface() );
  324. connect( childExtension, TQT_SIGNAL( enableAction( const char *, bool ) ),
  325. m_extension, TQT_SIGNAL( enableAction( const char *, bool ) ) );
  326. connect( childExtension, TQT_SIGNAL( setLocationBarURL( const TQString& ) ),
  327. m_extension, TQT_SIGNAL( setLocationBarURL( const TQString& ) ) );
  328. connect( childExtension, TQT_SIGNAL( setIconURL( const KURL& ) ),
  329. m_extension, TQT_SIGNAL( setIconURL( const KURL& ) ) );
  330. connect( childExtension, TQT_SIGNAL( loadingProgress( int ) ),
  331. m_extension, TQT_SIGNAL( loadingProgress( int ) ) );
  332. if ( m_isHTMLPart ) // for non-HTML we have our own
  333. connect( childExtension, TQT_SIGNAL( speedProgress( int ) ),
  334. m_extension, TQT_SIGNAL( speedProgress( int ) ) );
  335. connect( childExtension, TQT_SIGNAL( selectionInfo( const KFileItemList& ) ),
  336. m_extension, TQT_SIGNAL( selectionInfo( const KFileItemList& ) ) );
  337. connect( childExtension, TQT_SIGNAL( selectionInfo( const TQString& ) ),
  338. m_extension, TQT_SIGNAL( selectionInfo( const TQString& ) ) );
  339. connect( childExtension, TQT_SIGNAL( selectionInfo( const KURL::List& ) ),
  340. m_extension, TQT_SIGNAL( selectionInfo( const KURL::List& ) ) );
  341. connect( childExtension, TQT_SIGNAL( mouseOverInfo( const KFileItem* ) ),
  342. m_extension, TQT_SIGNAL( mouseOverInfo( const KFileItem* ) ) );
  343. connect( childExtension, TQT_SIGNAL( moveTopLevelWidget( int, int ) ),
  344. m_extension, TQT_SIGNAL( moveTopLevelWidget( int, int ) ) );
  345. connect( childExtension, TQT_SIGNAL( resizeTopLevelWidget( int, int ) ),
  346. m_extension, TQT_SIGNAL( resizeTopLevelWidget( int, int ) ) );
  347. }
  348. m_partIsLoading = false;
  349. // Load the part's plugins too.
  350. // ###### This is a hack. The bug is that TDEHTMLPart doesn't load its plugins
  351. // if className != "Browser/View".
  352. loadPlugins( this, m_part, m_part->instance() );
  353. // Get the part's GUI to appear
  354. if ( guiFactory )
  355. guiFactory->addClient( this );
  356. }
  357. void KMultiPart::startOfData()
  358. {
  359. kdDebug() << "KMultiPart::startOfData" << endl;
  360. Q_ASSERT( !m_nextMimeType.isNull() );
  361. if( m_nextMimeType.isNull() )
  362. return;
  363. if ( m_gzip )
  364. {
  365. m_filter = new HTTPFilterGZip;
  366. connect( m_filter, TQT_SIGNAL( output( const TQByteArray& ) ), this, TQT_SLOT( reallySendData( const TQByteArray& ) ) );
  367. }
  368. if ( m_mimeType != m_nextMimeType )
  369. {
  370. // Need to switch parts (or create the initial one)
  371. m_mimeType = m_nextMimeType;
  372. setPart( m_mimeType );
  373. }
  374. Q_ASSERT( m_part );
  375. // Pass URLArgs (e.g. reload)
  376. KParts::BrowserExtension* childExtension = KParts::BrowserExtension::childObject( m_part );
  377. if ( childExtension )
  378. childExtension->setURLArgs( m_extension->urlArgs() );
  379. m_nextMimeType = TQString::null;
  380. if ( m_tempFile ) {
  381. m_tempFile->setAutoDelete( true );
  382. delete m_tempFile;
  383. m_tempFile = 0;
  384. }
  385. if ( m_isHTMLPart )
  386. {
  387. TDEHTMLPart* htmlPart = static_cast<TDEHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) );
  388. htmlPart->begin( url() );
  389. }
  390. else
  391. {
  392. // ###### TODO use a TQByteArray and a data: URL instead
  393. m_tempFile = new KTempFile;
  394. }
  395. }
  396. void KMultiPart::sendData( const TQByteArray& line )
  397. {
  398. if ( m_filter )
  399. {
  400. m_filter->slotInput( line );
  401. }
  402. else
  403. {
  404. reallySendData( line );
  405. }
  406. }
  407. void KMultiPart::reallySendData( const TQByteArray& line )
  408. {
  409. if ( m_isHTMLPart )
  410. {
  411. TDEHTMLPart* htmlPart = static_cast<TDEHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) );
  412. htmlPart->write( line.data(), line.size() );
  413. }
  414. else if ( m_tempFile )
  415. {
  416. m_tempFile->file()->writeBlock( line.data(), line.size() );
  417. }
  418. }
  419. void KMultiPart::endOfData()
  420. {
  421. Q_ASSERT( m_part );
  422. if ( m_isHTMLPart )
  423. {
  424. TDEHTMLPart* htmlPart = static_cast<TDEHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) );
  425. htmlPart->end();
  426. } else if ( m_tempFile )
  427. {
  428. m_tempFile->close();
  429. if ( m_partIsLoading )
  430. {
  431. // The part is still loading the last data! Let it proceed then
  432. // Otherwise we'd keep cancelling it, and nothing would ever show up...
  433. kdDebug() << "KMultiPart::endOfData part isn't ready, skipping frame" << endl;
  434. ++m_numberOfFramesSkipped;
  435. m_tempFile->setAutoDelete( true );
  436. }
  437. else
  438. {
  439. kdDebug() << "KMultiPart::endOfData opening " << m_tempFile->name() << endl;
  440. KURL url;
  441. url.setPath( m_tempFile->name() );
  442. m_partIsLoading = true;
  443. (void) m_part->openURL( url );
  444. }
  445. delete m_tempFile;
  446. m_tempFile = 0L;
  447. }
  448. }
  449. void KMultiPart::slotPartCompleted()
  450. {
  451. if ( !m_isHTMLPart )
  452. {
  453. Q_ASSERT( m_part );
  454. // Delete temp file used by the part
  455. Q_ASSERT( m_part->url().isLocalFile() );
  456. kdDebug() << "slotPartCompleted deleting " << m_part->url().path() << endl;
  457. (void) unlink( TQFile::encodeName( m_part->url().path() ) );
  458. m_partIsLoading = false;
  459. ++m_numberOfFrames;
  460. // Do not emit completed from here.
  461. }
  462. }
  463. bool KMultiPart::closeURL()
  464. {
  465. m_timer->stop();
  466. if ( m_part )
  467. return m_part->closeURL();
  468. return true;
  469. }
  470. void KMultiPart::guiActivateEvent( KParts::GUIActivateEvent * )
  471. {
  472. // Not public!
  473. //if ( m_part )
  474. // m_part->guiActivateEvent( e );
  475. }
  476. void KMultiPart::slotJobFinished( TDEIO::Job *job )
  477. {
  478. if ( job->error() )
  479. {
  480. // TODO use tdehtml's error:// scheme
  481. job->showErrorDialog();
  482. emit canceled( job->errorString() );
  483. }
  484. else
  485. {
  486. /*if ( m_tdehtml->view()->contentsY() == 0 )
  487. {
  488. KParts::URLArgs args = m_ext->urlArgs();
  489. m_tdehtml->view()->setContentsPos( args.xOffset, args.yOffset );
  490. }*/
  491. emit completed();
  492. //TQTimer::singleShot( 0, this, TQT_SLOT( updateWindowCaption() ) );
  493. }
  494. m_job = 0L;
  495. }
  496. void KMultiPart::slotProgressInfo()
  497. {
  498. int time = m_qtime.elapsed();
  499. if ( !time ) return;
  500. if ( m_totalNumberOfFrames == m_numberOfFrames + m_numberOfFramesSkipped )
  501. return; // No change, don't overwrite statusbar messages if any
  502. //kdDebug() << m_numberOfFrames << " in " << time << " milliseconds" << endl;
  503. TQString str( "%1 frames per second, %2 frames skipped per second" );
  504. str = str.arg( 1000.0 * (double)m_numberOfFrames / (double)time );
  505. str = str.arg( 1000.0 * (double)m_numberOfFramesSkipped / (double)time );
  506. m_totalNumberOfFrames = m_numberOfFrames + m_numberOfFramesSkipped;
  507. //kdDebug() << str << endl;
  508. emit m_extension->infoMessage( str );
  509. }
  510. TDEAboutData* KMultiPart::createAboutData()
  511. {
  512. TDEAboutData* aboutData = new TDEAboutData( "tdemultipart", I18N_NOOP("KMultiPart"),
  513. "0.1",
  514. I18N_NOOP( "Embeddable component for multipart/mixed" ),
  515. TDEAboutData::License_GPL,
  516. "(c) 2001, David Faure <david@mandrakesoft.com>");
  517. return aboutData;
  518. }
  519. #if 0
  520. KMultiPartBrowserExtension::KMultiPartBrowserExtension( KMultiPart *parent, const char *name )
  521. : KParts::BrowserExtension( parent, name )
  522. {
  523. m_imgPart = parent;
  524. }
  525. int KMultiPartBrowserExtension::xOffset()
  526. {
  527. return m_imgPart->doc()->view()->contentsX();
  528. }
  529. int KMultiPartBrowserExtension::yOffset()
  530. {
  531. return m_imgPart->doc()->view()->contentsY();
  532. }
  533. void KMultiPartBrowserExtension::print()
  534. {
  535. static_cast<TDEHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->print();
  536. }
  537. void KMultiPartBrowserExtension::reparseConfiguration()
  538. {
  539. static_cast<TDEHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->reparseConfiguration();
  540. m_imgPart->doc()->setAutoloadImages( true );
  541. }
  542. #endif
  543. #include "tdemultipart.moc"