diff options
Diffstat (limited to 'tdehtml/tdemultipart')
-rw-r--r-- | tdehtml/tdemultipart/CMakeLists.txt | 48 | ||||
-rw-r--r-- | tdehtml/tdemultipart/Makefile.am | 17 | ||||
-rw-r--r-- | tdehtml/tdemultipart/README | 16 | ||||
-rw-r--r-- | tdehtml/tdemultipart/tdemultipart.cpp | 613 | ||||
-rw-r--r-- | tdehtml/tdemultipart/tdemultipart.desktop | 73 | ||||
-rw-r--r-- | tdehtml/tdemultipart/tdemultipart.h | 118 |
6 files changed, 885 insertions, 0 deletions
diff --git a/tdehtml/tdemultipart/CMakeLists.txt b/tdehtml/tdemultipart/CMakeLists.txt new file mode 100644 index 000000000..f0d03953e --- /dev/null +++ b/tdehtml/tdemultipart/CMakeLists.txt @@ -0,0 +1,48 @@ +################################################# +# +# (C) 2010 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${TQT_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_BINARY_DIR} + ${CMAKE_BINARY_DIR}/tdecore + ${CMAKE_SOURCE_DIR} + ${CMAKE_SOURCE_DIR}/tdehtml + ${CMAKE_SOURCE_DIR}/tdecore + ${CMAKE_SOURCE_DIR}/tdeui + ${CMAKE_SOURCE_DIR}/kio + ${CMAKE_SOURCE_DIR}/kio/kio + ${CMAKE_SOURCE_DIR}/tdeutils +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### other data ################################ + +install( FILES tdemultipart.desktop DESTINATION ${SERVICES_INSTALL_DIR} ) + + +##### libtdemultipart ############################# + +set( target libtdemultipart ) + +set( ${target}_SRCS + tdemultipart.cpp +) + +tde_add_kpart( ${target} AUTOMOC + SOURCES ${${target}_SRCS} + LINK httpfilter-static tdeparts-shared + DESTINATION ${PLUGIN_INSTALL_DIR} +) diff --git a/tdehtml/tdemultipart/Makefile.am b/tdehtml/tdemultipart/Makefile.am new file mode 100644 index 000000000..f02b5931e --- /dev/null +++ b/tdehtml/tdemultipart/Makefile.am @@ -0,0 +1,17 @@ +INCLUDES = -I$(top_srcdir)/tdehtml -I$(top_srcdir)/kio/httpfilter -I$(top_srcdir)/tdeutils $(all_includes) + +# These are not really libraries, but modules dynamically opened. +# So they should be installed in kde_module_dir, which is usually $kde_prefix/lib/trinity +kde_module_LTLIBRARIES = libtdemultipart.la + +libtdemultipart_la_SOURCES = tdemultipart.cpp +libtdemultipart_la_LIBADD = $(LIB_KPARTS) $(top_builddir)/kio/httpfilter/libhttpfilter.la $(LIB_QT) $(LIB_TDECORE) $(LIB_TDEUI) $(LIB_KFILE) $(LIBZ) +libtdemultipart_la_DEPENDENCIES = $(LIB_KPARTS) +libtdemultipart_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) + +# Automatically generate moc files +METASOURCES = AUTO + +# Install the .desktop file into the kde_services directory +kde_services_DATA = tdemultipart.desktop + diff --git a/tdehtml/tdemultipart/README b/tdehtml/tdemultipart/README new file mode 100644 index 000000000..c8a342d68 --- /dev/null +++ b/tdehtml/tdemultipart/README @@ -0,0 +1,16 @@ +KMultiPart implements "server push" for KHTML/Konqueror: +it handles the multipart/mixed and multipart/x-mixed-replace +mimetype, embedding the appropriate component (part). + +Documentation at http://www.netscape.com/assist/net_sites/pushpull.html + +Typical real-world uses: webchats, webcams... + +Testcases: + http://stein.cshl.org/WWW/software/CGI/examples/ + +TODO: +* Use the new streaming API of KParts to pipe data into the part, +the current code does that for KHTML only. +* Change KHTML so that it embeds KMultiPart for images which send multipart/x-mixed-replace +data. diff --git a/tdehtml/tdemultipart/tdemultipart.cpp b/tdehtml/tdemultipart/tdemultipart.cpp new file mode 100644 index 000000000..d5195186d --- /dev/null +++ b/tdehtml/tdemultipart/tdemultipart.cpp @@ -0,0 +1,613 @@ +/* This file is part of the KDE project + Copyright (C) 2002 David Faure <david@mandrakesoft.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "tdemultipart.h" + +#include <tqvbox.h> +#include <kinstance.h> +#include <kmimetype.h> +#include <klocale.h> +#include <kio/job.h> +#include <tqfile.h> +#include <ktempfile.h> +#include <kmessagebox.h> +#include <tdeparts/componentfactory.h> +#include <tdeparts/genericfactory.h> +#include <tdehtml_part.h> +#include <unistd.h> +#include <kxmlguifactory.h> +#include <tqtimer.h> + +typedef KParts::GenericFactory<KMultiPart> KMultiPartFactory; // factory for the part +K_EXPORT_COMPONENT_FACTORY( libtdemultipart /*library name*/, KMultiPartFactory ) + +//#define DEBUG_PARSING + +class KLineParser +{ +public: + KLineParser() { + m_lineComplete = false; + } + void addChar( char c, bool storeNewline ) { + if ( !storeNewline && c == '\r' ) + return; + Q_ASSERT( !m_lineComplete ); + if ( storeNewline || c != '\n' ) { + int sz = m_currentLine.size(); + m_currentLine.resize( sz+1, TQGArray::SpeedOptim ); + m_currentLine[sz] = c; + } + if ( c == '\n' ) + m_lineComplete = true; + } + bool isLineComplete() const { + return m_lineComplete; + } + TQByteArray currentLine() const { + return m_currentLine; + } + void clearLine() { + Q_ASSERT( m_lineComplete ); + reset(); + } + void reset() { + m_currentLine.resize( 0, TQGArray::SpeedOptim ); + m_lineComplete = false; + } +private: + TQByteArray m_currentLine; + bool m_lineComplete; // true when ending with '\n' +}; + +/* testcase: + Content-type: multipart/mixed;boundary=ThisRandomString + +--ThisRandomString +Content-type: text/plain + +Data for the first object. + +--ThisRandomString +Content-type: text/plain + +Data for the second and last object. + +--ThisRandomString-- +*/ + + +KMultiPart::KMultiPart( TQWidget *parentWidget, const char *widgetName, + TQObject *parent, const char *name, const TQStringList& ) + : KParts::ReadOnlyPart( parent, name ) +{ + m_filter = 0L; + + setInstance( KMultiPartFactory::instance() ); + + TQVBox *box = new TQVBox( parentWidget, widgetName ); + setWidget( box ); + + m_extension = new KParts::BrowserExtension( this ); + + // We probably need to use m_extension to get the urlArgs in openURL... + + m_part = 0L; + m_isHTMLPart = false; + m_job = 0L; + m_lineParser = new KLineParser; + m_tempFile = 0L; + + m_timer = new TQTimer( this ); + connect( m_timer, TQT_SIGNAL( timeout() ), this, TQT_SLOT( slotProgressInfo() ) ); +} + +KMultiPart::~KMultiPart() +{ + // important: delete the nested part before the part or qobject destructor runs. + // we now delete the nested part which deletes the part's widget which makes + // _OUR_ m_widget 0 which in turn avoids our part destructor to delete the + // widget ;-) + // ### additional note: it _can_ be that the part has been deleted before: + // when we're in a html frameset and the view dies first, then it will also + // kill the htmlpart + if ( m_part ) + delete static_cast<KParts::ReadOnlyPart *>( m_part ); + delete m_job; + delete m_lineParser; + if ( m_tempFile ) { + m_tempFile->setAutoDelete( true ); + delete m_tempFile; + } + delete m_filter; + m_filter = 0L; +} + + +void KMultiPart::startHeader() +{ + m_bParsingHeader = true; // we expect a header to come first + m_bGotAnyHeader = false; + m_gzip = false; + // just to be sure for now + delete m_filter; + m_filter = 0L; +} + + +bool KMultiPart::openURL( const KURL &url ) +{ + m_url = url; + m_lineParser->reset(); + startHeader(); + + KParts::URLArgs args = m_extension->urlArgs(); + //m_mimeType = args.serviceType; + + // Hmm, args.reload is set to true when reloading, but this doesn't seem to be enough... + // I get "HOLD: Reusing held slave for <url>", and the old data + + m_job = TDEIO::get( url, args.reload, false ); + + emit started( 0 /*m_job*/ ); // don't pass the job, it would interfer with our own infoMessage + + connect( m_job, TQT_SIGNAL( result( TDEIO::Job * ) ), + this, TQT_SLOT( slotJobFinished( TDEIO::Job * ) ) ); + connect( m_job, TQT_SIGNAL( data( TDEIO::Job *, const TQByteArray & ) ), + this, TQT_SLOT( slotData( TDEIO::Job *, const TQByteArray & ) ) ); + + m_numberOfFrames = 0; + m_numberOfFramesSkipped = 0; + m_totalNumberOfFrames = 0; + m_qtime.start(); + m_timer->start( 1000 ); //1s + + return true; +} + +// Yes, libtdenetwork's has such a parser already (MultiPart), +// but it works on the complete string, expecting the whole data to be available.... +// The version here is asynchronous. +void KMultiPart::slotData( TDEIO::Job *job, const TQByteArray &data ) +{ + if (m_boundary.isNull()) + { + TQString tmp = job->queryMetaData("media-boundary"); + kdDebug() << "Got Boundary from kio-http '" << tmp << "'" << endl; + if ( !tmp.isEmpty() ) { + if (tmp.startsWith("--")) + m_boundary = tmp.latin1(); + else + m_boundary = TQCString("--")+tmp.latin1(); + m_boundaryLength = m_boundary.length(); + } + } + // Append to m_currentLine until eol + for ( uint i = 0; i < data.size() ; ++i ) + { + // Store char. Skip if '\n' and currently parsing a header. + m_lineParser->addChar( data[i], !m_bParsingHeader ); + if ( m_lineParser->isLineComplete() ) + { + TQByteArray lineData = m_lineParser->currentLine(); +#ifdef DEBUG_PARSING + kdDebug() << "lineData.size()=" << lineData.size() << endl; +#endif + TQCString line( lineData.data(), lineData.size()+1 ); // deep copy + // 0-terminate the data, but only for the line-based tests below + // We want to keep the raw data in case it ends up in sendData() + int sz = line.size(); + if ( sz > 0 ) + line[sz-1] = '\0'; +#ifdef DEBUG_PARSING + kdDebug() << "[" << m_bParsingHeader << "] line='" << line << "'" << endl; +#endif + if ( m_bParsingHeader ) + { + if ( !line.isEmpty() ) + m_bGotAnyHeader = true; + if ( m_boundary.isNull() ) + { + if ( !line.isEmpty() ) { +#ifdef DEBUG_PARSING + kdDebug() << "Boundary is " << line << endl; +#endif + m_boundary = line; + m_boundaryLength = m_boundary.length(); + } + } + else if ( !tqstrnicmp( line.data(), "Content-Encoding:", 17 ) ) + { + TQString encoding = TQString::fromLatin1(line.data()+17).stripWhiteSpace().lower(); + if (encoding == "gzip" || encoding == "x-gzip") { + m_gzip = true; + } else { + kdDebug() << "FIXME: unhandled encoding type in KMultiPart: " << encoding << endl; + } + } + // parse Content-Type + else if ( !tqstrnicmp( line.data(), "Content-Type:", 13 ) ) + { + Q_ASSERT( m_nextMimeType.isNull() ); + m_nextMimeType = TQString::fromLatin1( line.data() + 14 ).stripWhiteSpace(); + int semicolon = m_nextMimeType.find( ';' ); + if ( semicolon != -1 ) + m_nextMimeType = m_nextMimeType.left( semicolon ); + kdDebug() << "m_nextMimeType=" << m_nextMimeType << endl; + } + // Empty line, end of headers (if we had any header line before) + else if ( line.isEmpty() && m_bGotAnyHeader ) + { + m_bParsingHeader = false; +#ifdef DEBUG_PARSING + kdDebug() << "end of headers" << endl; +#endif + startOfData(); + } + // First header (when we know it from kio_http) + else if ( line == m_boundary ) + ; // nothing to do + else if ( !line.isEmpty() ) // this happens with e.g. Set-Cookie: + kdDebug() << "Ignoring header " << line << endl; + } else { + if ( !tqstrncmp( line, m_boundary, m_boundaryLength ) ) + { +#ifdef DEBUG_PARSING + kdDebug() << "boundary found!" << endl; + kdDebug() << "after it is " << line.data() + m_boundaryLength << endl; +#endif + // Was it the very last boundary ? + if ( !tqstrncmp( line.data() + m_boundaryLength, "--", 2 ) ) + { +#ifdef DEBUG_PARSING + kdDebug() << "Completed!" << endl; +#endif + endOfData(); + emit completed(); + } else + { + char nextChar = *(line.data() + m_boundaryLength); +#ifdef DEBUG_PARSING + kdDebug() << "KMultiPart::slotData nextChar='" << nextChar << "'" << endl; +#endif + if ( nextChar == '\n' || nextChar == '\r' ) { + endOfData(); + startHeader(); + } + else { + // otherwise, false hit, it has trailing stuff + sendData( lineData ); + } + } + } else { + // send to part + sendData( lineData ); + } + } + m_lineParser->clearLine(); + } + } +} + +void KMultiPart::setPart( const TQString& mimeType ) +{ + KXMLGUIFactory *guiFactory = factory(); + if ( guiFactory ) // seems to be 0 when restoring from SM + guiFactory->removeClient( this ); + kdDebug() << "KMultiPart::setPart " << mimeType << endl; + delete m_part; + // Try to find an appropriate viewer component + m_part = KParts::ComponentFactory::createPartInstanceFromQuery<KParts::ReadOnlyPart> + ( m_mimeType, TQString::null, widget(), 0L, this, 0L ); + if ( !m_part ) { + // TODO launch external app + KMessageBox::error( widget(), i18n("No handler found for %1!").arg(m_mimeType) ); + return; + } + // By making the part a child XMLGUIClient of ours, we get its GUI merged in. + insertChildClient( m_part ); + m_part->widget()->show(); + + connect( m_part, TQT_SIGNAL( completed() ), + this, TQT_SLOT( slotPartCompleted() ) ); + + m_isHTMLPart = ( mimeType == "text/html" ); + KParts::BrowserExtension* childExtension = KParts::BrowserExtension::childObject( m_part ); + + if ( childExtension ) + { + + // Forward signals from the part's browser extension + // this is very related (but not exactly like) KHTMLPart::processObjectRequest + + connect( childExtension, TQT_SIGNAL( openURLNotify() ), + m_extension, TQT_SIGNAL( openURLNotify() ) ); + + connect( childExtension, TQT_SIGNAL( openURLRequestDelayed( const KURL &, const KParts::URLArgs & ) ), + m_extension, TQT_SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ) ); + + connect( childExtension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ), + m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) ); + connect( childExtension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs &, const KParts::WindowArgs &, KParts::ReadOnlyPart *& ) ), + m_extension, TQT_SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & , const KParts::WindowArgs &, KParts::ReadOnlyPart *&) ) ); + + // Keep in sync with tdehtml_part.cpp + connect( childExtension, TQT_SIGNAL( popupMenu( const TQPoint &, const KFileItemList & ) ), + m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KFileItemList & ) ) ); + connect( childExtension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList & ) ), + m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList & ) ) ); + connect( childExtension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ), + m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KFileItemList &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags ) ) ); + connect( childExtension, TQT_SIGNAL( popupMenu( const TQPoint &, const KURL &, const TQString &, mode_t ) ), + m_extension, TQT_SIGNAL( popupMenu( const TQPoint &, const KURL &, const TQString &, mode_t ) ) ); + connect( childExtension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const TQString &, mode_t ) ), + m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const TQString &, mode_t ) ) ); + connect( childExtension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ), + m_extension, TQT_SIGNAL( popupMenu( KXMLGUIClient *, const TQPoint &, const KURL &, const KParts::URLArgs &, KParts::BrowserExtension::PopupFlags, mode_t ) ) ); + + + if ( m_isHTMLPart ) + connect( childExtension, TQT_SIGNAL( infoMessage( const TQString & ) ), + m_extension, TQT_SIGNAL( infoMessage( const TQString & ) ) ); + // For non-HTML we prefer to show our infoMessage ourselves. + + childExtension->setBrowserInterface( m_extension->browserInterface() ); + + connect( childExtension, TQT_SIGNAL( enableAction( const char *, bool ) ), + m_extension, TQT_SIGNAL( enableAction( const char *, bool ) ) ); + connect( childExtension, TQT_SIGNAL( setLocationBarURL( const TQString& ) ), + m_extension, TQT_SIGNAL( setLocationBarURL( const TQString& ) ) ); + connect( childExtension, TQT_SIGNAL( setIconURL( const KURL& ) ), + m_extension, TQT_SIGNAL( setIconURL( const KURL& ) ) ); + connect( childExtension, TQT_SIGNAL( loadingProgress( int ) ), + m_extension, TQT_SIGNAL( loadingProgress( int ) ) ); + if ( m_isHTMLPart ) // for non-HTML we have our own + connect( childExtension, TQT_SIGNAL( speedProgress( int ) ), + m_extension, TQT_SIGNAL( speedProgress( int ) ) ); + connect( childExtension, TQT_SIGNAL( selectionInfo( const KFileItemList& ) ), + m_extension, TQT_SIGNAL( selectionInfo( const KFileItemList& ) ) ); + connect( childExtension, TQT_SIGNAL( selectionInfo( const TQString& ) ), + m_extension, TQT_SIGNAL( selectionInfo( const TQString& ) ) ); + connect( childExtension, TQT_SIGNAL( selectionInfo( const KURL::List& ) ), + m_extension, TQT_SIGNAL( selectionInfo( const KURL::List& ) ) ); + connect( childExtension, TQT_SIGNAL( mouseOverInfo( const KFileItem* ) ), + m_extension, TQT_SIGNAL( mouseOverInfo( const KFileItem* ) ) ); + connect( childExtension, TQT_SIGNAL( moveTopLevelWidget( int, int ) ), + m_extension, TQT_SIGNAL( moveTopLevelWidget( int, int ) ) ); + connect( childExtension, TQT_SIGNAL( resizeTopLevelWidget( int, int ) ), + m_extension, TQT_SIGNAL( resizeTopLevelWidget( int, int ) ) ); + } + + m_partIsLoading = false; + // Load the part's plugins too. + // ###### This is a hack. The bug is that KHTMLPart doesn't load its plugins + // if className != "Browser/View". + loadPlugins( this, m_part, m_part->instance() ); + // Get the part's GUI to appear + if ( guiFactory ) + guiFactory->addClient( this ); +} + +void KMultiPart::startOfData() +{ + kdDebug() << "KMultiPart::startOfData" << endl; + Q_ASSERT( !m_nextMimeType.isNull() ); + if( m_nextMimeType.isNull() ) + return; + + if ( m_gzip ) + { + m_filter = new HTTPFilterGZip; + connect( m_filter, TQT_SIGNAL( output( const TQByteArray& ) ), this, TQT_SLOT( reallySendData( const TQByteArray& ) ) ); + } + + if ( m_mimeType != m_nextMimeType ) + { + // Need to switch parts (or create the initial one) + m_mimeType = m_nextMimeType; + setPart( m_mimeType ); + } + Q_ASSERT( m_part ); + // Pass URLArgs (e.g. reload) + KParts::BrowserExtension* childExtension = KParts::BrowserExtension::childObject( m_part ); + if ( childExtension ) + childExtension->setURLArgs( m_extension->urlArgs() ); + + m_nextMimeType = TQString::null; + if ( m_tempFile ) { + m_tempFile->setAutoDelete( true ); + delete m_tempFile; + m_tempFile = 0; + } + if ( m_isHTMLPart ) + { + KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) ); + htmlPart->begin( url() ); + } + else + { + // ###### TODO use a TQByteArray and a data: URL instead + m_tempFile = new KTempFile; + } +} + +void KMultiPart::sendData( const TQByteArray& line ) +{ + if ( m_filter ) + { + m_filter->slotInput( line ); + } + else + { + reallySendData( line ); + } +} + +void KMultiPart::reallySendData( const TQByteArray& line ) +{ + if ( m_isHTMLPart ) + { + KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) ); + htmlPart->write( line.data(), line.size() ); + } + else if ( m_tempFile ) + { + m_tempFile->file()->writeBlock( line.data(), line.size() ); + } +} + +void KMultiPart::endOfData() +{ + Q_ASSERT( m_part ); + if ( m_isHTMLPart ) + { + KHTMLPart* htmlPart = static_cast<KHTMLPart *>( static_cast<KParts::ReadOnlyPart *>( m_part ) ); + htmlPart->end(); + } else if ( m_tempFile ) + { + m_tempFile->close(); + if ( m_partIsLoading ) + { + // The part is still loading the last data! Let it proceed then + // Otherwise we'd keep cancelling it, and nothing would ever show up... + kdDebug() << "KMultiPart::endOfData part isn't ready, skipping frame" << endl; + ++m_numberOfFramesSkipped; + m_tempFile->setAutoDelete( true ); + } + else + { + kdDebug() << "KMultiPart::endOfData opening " << m_tempFile->name() << endl; + KURL url; + url.setPath( m_tempFile->name() ); + m_partIsLoading = true; + (void) m_part->openURL( url ); + } + delete m_tempFile; + m_tempFile = 0L; + } +} + +void KMultiPart::slotPartCompleted() +{ + if ( !m_isHTMLPart ) + { + Q_ASSERT( m_part ); + // Delete temp file used by the part + Q_ASSERT( m_part->url().isLocalFile() ); + kdDebug() << "slotPartCompleted deleting " << m_part->url().path() << endl; + (void) unlink( TQFile::encodeName( m_part->url().path() ) ); + m_partIsLoading = false; + ++m_numberOfFrames; + // Do not emit completed from here. + } +} + +bool KMultiPart::closeURL() +{ + m_timer->stop(); + if ( m_part ) + return m_part->closeURL(); + return true; +} + +void KMultiPart::guiActivateEvent( KParts::GUIActivateEvent * ) +{ + // Not public! + //if ( m_part ) + // m_part->guiActivateEvent( e ); +} + +void KMultiPart::slotJobFinished( TDEIO::Job *job ) +{ + if ( job->error() ) + { + // TODO use tdehtml's error:// scheme + job->showErrorDialog(); + emit canceled( job->errorString() ); + } + else + { + /*if ( m_tdehtml->view()->contentsY() == 0 ) + { + KParts::URLArgs args = m_ext->urlArgs(); + m_tdehtml->view()->setContentsPos( args.xOffset, args.yOffset ); + }*/ + + emit completed(); + + //TQTimer::singleShot( 0, this, TQT_SLOT( updateWindowCaption() ) ); + } + m_job = 0L; +} + +void KMultiPart::slotProgressInfo() +{ + int time = m_qtime.elapsed(); + if ( !time ) return; + if ( m_totalNumberOfFrames == m_numberOfFrames + m_numberOfFramesSkipped ) + return; // No change, don't overwrite statusbar messages if any + //kdDebug() << m_numberOfFrames << " in " << time << " milliseconds" << endl; + TQString str( "%1 frames per second, %2 frames skipped per second" ); + str = str.arg( 1000.0 * (double)m_numberOfFrames / (double)time ); + str = str.arg( 1000.0 * (double)m_numberOfFramesSkipped / (double)time ); + m_totalNumberOfFrames = m_numberOfFrames + m_numberOfFramesSkipped; + //kdDebug() << str << endl; + emit m_extension->infoMessage( str ); +} + +TDEAboutData* KMultiPart::createAboutData() +{ + TDEAboutData* aboutData = new TDEAboutData( "tdemultipart", I18N_NOOP("KMultiPart"), + "0.1", + I18N_NOOP( "Embeddable component for multipart/mixed" ), + TDEAboutData::License_GPL, + "(c) 2001, David Faure <david@mandrakesoft.com>"); + return aboutData; +} + +#if 0 +KMultiPartBrowserExtension::KMultiPartBrowserExtension( KMultiPart *parent, const char *name ) + : KParts::BrowserExtension( parent, name ) +{ + m_imgPart = parent; +} + +int KMultiPartBrowserExtension::xOffset() +{ + return m_imgPart->doc()->view()->contentsX(); +} + +int KMultiPartBrowserExtension::yOffset() +{ + return m_imgPart->doc()->view()->contentsY(); +} + +void KMultiPartBrowserExtension::print() +{ + static_cast<KHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->print(); +} + +void KMultiPartBrowserExtension::reparseConfiguration() +{ + static_cast<KHTMLPartBrowserExtension *>( m_imgPart->doc()->browserExtension() )->reparseConfiguration(); + m_imgPart->doc()->setAutoloadImages( true ); +} +#endif + +#include "tdemultipart.moc" diff --git a/tdehtml/tdemultipart/tdemultipart.desktop b/tdehtml/tdemultipart/tdemultipart.desktop new file mode 100644 index 000000000..d5808d928 --- /dev/null +++ b/tdehtml/tdemultipart/tdemultipart.desktop @@ -0,0 +1,73 @@ +[Desktop Entry] +Type=Service +MimeType=multipart/mixed;multipart/x-mixed-replace +Name=Embeddable Component for multipart/mixed +Name[af]=Inlegbare Komponent vir multideel/gemeng +Name[be]=Унутраны кампанент для multipart/mixed +Name[bg]=Вграден компонент за преглед на съобщения multipart/mixed +Name[bn]=multipart/mixed-এর জন্য অভ্যন্তরীণ উপাদান +Name[bs]=Ugradiva komponenta za multipart/mixed +Name[ca]=Component encastable per a multipart/mescla +Name[cs]=Pohltitelné komponenty pro 'multipart/mixed' +Name[csb]=Składowi kòmpònent dlô multipart/mixed +Name[da]=Indlejrbar komponent for multipart/mixed +Name[de]=Einbettungsfähige Komponente für MIME-Typ multipart/mixed +Name[el]=Στοιχείο που μπορεί να ενσωματωθεί για multipart/mixed +Name[eo]=Enplantebla komponanto por plurparto/mikso +Name[es]=Componente empotrado para multiparte/mezcla +Name[et]=Multipart/mixed põimitav komponent +Name[eu]=Kapsulatutako zati-anitzen/nahastuen osagaia +Name[fa]=مؤلفۀ نهفته برای چند بخش/مخلوط +Name[fi]=Upotettava komponentti multipart/mixed-hallintaan +Name[fr]=Composant intégrable pour le type multipart / mixed +Name[fy]=Yn te sluten komponint foar mulipart/mixed +Name[ga]=Comhpháirt Inleabaithe le haghaidh multipart/mixed +Name[gl]=Compoñente incrustábel para multpart/mixed +Name[he]=רכיב בר־הטבעה עבור מרובה חלקים\מעורב +Name[hi]=मल्टीपार्ट/मिक्स्ड के लिए अंतर्निहित करने योग्य घटक +Name[hr]=Ugradiva komponenta za multipart/mixed +Name[hu]=Beágyazható komponens a multipart/mixed adattípushoz +Name[id]=Komponen Tersisipkan untuk multipart/mixed +Name[is]=Ívefjanleg eining fyrir MIME multipart/mixed +Name[it]=Componente integrabile per multipart/mixed +Name[ja]=マルチパート/混合 の埋め込み可能なコンポーネント +Name[ka]=ჩადგმადი კომპონენტი მრავალნაწილიანი/შერეულისთვის +Name[kk]=multipart/mixed тіркеме үшін ендірілетін компоненті +Name[km]=សមាសភាគដែលអាចបង្កប់ សម្រាប់ផ្នែកជាច្រើន/លាយ +Name[lb]=Abettbar Komponent fir de MIME-Genre multipart/mixed +Name[lt]=Įdedamas komponentas multipart/mixed tipui +Name[lv]=Iegulstama komponente priekš multipart/mixed +Name[mk]=Вгнездлива компонента за multipart/mixed +Name[ms]=Komponen boleh serta untuk pelbagai bahagian/bercampur +Name[nb]=Innebyggbar komponent for multipart/mixed +Name[nds]=Inbettbor Komponent för multipart/mixed +Name[ne]=बहुभाग/मिश्रणका लागि सम्मिलित गर्न सकिने अवयव +Name[nl]=Inbedbaar component voor multipart/mixed +Name[nn]=Inkluderbar komponent for multipart/mixed +Name[pa]=ਬਹੁਭਾਗੀ/ਰਲਵੇਂ ਲਈ ਸ਼ਾਮਿਲ ਭਾਗ +Name[pl]=Moduł składowy dla multipart/mixed +Name[pt]=Componente Embebido para multipart/mixed +Name[pt_BR]=Componente embutido para multipart/mixed +Name[ro]=Componentă înglobată pentru tip MIME multipart/mixed +Name[ru]=Встраиваемый компонент для вложений +Name[rw]=Inyangingo ishyirwamo y'ibicebyinshi/ibivanzwe +Name[se]=Vuojuhanláhkái oassi multipart/mixed:a várás +Name[sk]=Vložiteľný komponent pre multipart/mixed +Name[sl]=Vgradljiva komponenta za multipart/mixed +Name[sr]=Уградива компонента за „multipart/mixed“ +Name[sr@Latn]=Ugradiva komponenta za „multipart/mixed“ +Name[sv]=Inbyggbar komponent för multipart/mixed +Name[ta]=பலப்பகுதி/கலக்கப்பட்ட பகுதிக்குரிய உட்பொதிந்த பகுதி +Name[te]=మల్టిపార్ట్/మిక్స్డ్ కొరకు పొదిగిన అంశం +Name[tg]=Компоненти дарунсохт барои қисматҳои зиёд/омезишшуда +Name[th]=ส่วนประกอบที่ฝังตัวได้สำหรับมัลติพาร์ต/ผสม +Name[tr]=Çok parçalı/karışık için Gömülebilir Bileşen +Name[uk]=Вбудовна компонента для повідомлень multipart/mixed +Name[uz]=Multipart/mixed uchun ichiga oʻrnatib boʻladigan komponent +Name[uz@cyrillic]=Multipart/mixed учун ичига ўрнатиб бўладиган компонент +Name[vi]=Thành phần có khả năng nhúng cho dạng thức thư đa phần/đã trộn (multipart/mixed). +Name[zh_CN]=可嵌入的 multipart/mixed 组件 +Name[zh_HK]=multipart/mixed 的可嵌入元件 +Name[zh_TW]=multipart/mixed 的可嵌入元件 +ServiceTypes=KParts/ReadOnlyPart +X-TDE-Library=libtdemultipart diff --git a/tdehtml/tdemultipart/tdemultipart.h b/tdehtml/tdemultipart/tdemultipart.h new file mode 100644 index 000000000..e4add0816 --- /dev/null +++ b/tdehtml/tdemultipart/tdemultipart.h @@ -0,0 +1,118 @@ +/* This file is part of the KDE project + Copyright (C) 2002 David Faure <david@mandrakesoft.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __tdemultipart_h__ +#define __tdemultipart_h__ + +#include <httpfilter/httpfilter.h> + +#include <tdeparts/part.h> +#include <tdeparts/factory.h> +#include <tdeparts/browserextension.h> +#include <kaboutdata.h> +#include <tqdatetime.h> + +class KHTMLPart; +class TDEInstance; +class KTempFile; +class KLineParser; + +/** + * http://www.netscape.com/assist/net_sites/pushpull.html + */ +class KMultiPart : public KParts::ReadOnlyPart +{ + Q_OBJECT +public: + KMultiPart( TQWidget *parentWidget, const char *widgetName, + TQObject *parent, const char *name, const TQStringList& ); + virtual ~KMultiPart(); + + virtual bool openFile() { return false; } + virtual bool openURL( const KURL &url ); + + virtual bool closeURL(); + + static TDEAboutData* createAboutData(); + +protected: + virtual void guiActivateEvent( KParts::GUIActivateEvent *e ); + void setPart( const TQString& mimeType ); + + void startOfData(); + void sendData( const TQByteArray& line ); + void endOfData(); + +private slots: + void reallySendData( const TQByteArray& line ); + //void slotPopupMenu( KXMLGUIClient *cl, const TQPoint &pos, const KURL &u, const TQString &mime, mode_t mode ); + void slotJobFinished( TDEIO::Job *job ); + void slotData( TDEIO::Job *, const TQByteArray & ); + //void updateWindowCaption(); + + void slotPartCompleted(); + + void startHeader(); + + void slotProgressInfo(); + +private: + KParts::BrowserExtension* m_extension; + TQGuardedPtr<KParts::ReadOnlyPart> m_part; + bool m_isHTMLPart; + bool m_partIsLoading; + TDEIO::Job* m_job; + TQCString m_boundary; + int m_boundaryLength; + TQString m_mimeType; // the one handled by m_part - store the kservice instead? + TQString m_nextMimeType; // while parsing headers + KTempFile* m_tempFile; + KLineParser* m_lineParser; + bool m_bParsingHeader; + bool m_bGotAnyHeader; + bool m_gzip; + HTTPFilterBase *m_filter; + // Speed measurements + long m_totalNumberOfFrames; + long m_numberOfFrames; + long m_numberOfFramesSkipped; + TQTime m_qtime; + TQTimer* m_timer; +}; + +#if 0 +class KMultiPartBrowserExtension : public KParts::BrowserExtension +{ + //Q_OBJECT +public: + KMultiPartBrowserExtension( KMultiPart *parent, const char *name = 0 ); + + virtual int xOffset(); + virtual int yOffset(); + +//protected slots: + void print(); + void reparseConfiguration(); + +private: + KMultiPart *m_imgPart; +}; +#endif + +#endif |