|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
|
|
|
|
2000, 2001 Werner Trobin <trobin@kde.org>
|
|
|
|
Copyright (C) 2004 Nicolas Goutte <goutte@kde.org>
|
|
|
|
|
|
|
|
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 <KoFilterManager.h>
|
|
|
|
#include <KoFilterManager_p.h>
|
|
|
|
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <tqlabel.h>
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqptrlist.h>
|
|
|
|
#include <tqapplication.h>
|
|
|
|
|
|
|
|
#include <tdelocale.h>
|
|
|
|
#include <tdemessagebox.h>
|
|
|
|
#include <KoDocument.h>
|
|
|
|
#include <klibloader.h>
|
|
|
|
#include <tdelistbox.h>
|
|
|
|
#include <kmimetype.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
#include <queue>
|
|
|
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
class KoFilterManager::Private
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
bool m_batch;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
KoFilterChooser::KoFilterChooser (TQWidget *parent, const TQStringList &mimeTypes, const TQString &nativeFormat)
|
|
|
|
: KDialogBase (parent, "kofilterchooser", true, i18n ("Choose Filter"),
|
|
|
|
KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, true),
|
|
|
|
m_mimeTypes (mimeTypes)
|
|
|
|
{
|
|
|
|
setInitialSize (TQSize (300, 350));
|
|
|
|
|
|
|
|
TQWidget *page = new TQWidget (this);
|
|
|
|
setMainWidget (page);
|
|
|
|
|
|
|
|
// looks too squashed together without * 2
|
|
|
|
TQVBoxLayout *layout = new TQVBoxLayout (page, marginHint (), spacingHint () * 2);
|
|
|
|
|
|
|
|
TQLabel *filterLabel = new TQLabel (i18n ("Select a filter:"), page, "filterlabel");
|
|
|
|
layout->addWidget (filterLabel);
|
|
|
|
|
|
|
|
m_filterList = new TDEListBox (page, "filterlist");
|
|
|
|
layout->addWidget (m_filterList);
|
|
|
|
|
|
|
|
Q_ASSERT (!m_mimeTypes.isEmpty ());
|
|
|
|
for (TQStringList::ConstIterator it = m_mimeTypes.begin ();
|
|
|
|
it != m_mimeTypes.end ();
|
|
|
|
it++)
|
|
|
|
{
|
|
|
|
KMimeType::Ptr mime = KMimeType::mimeType (*it);
|
|
|
|
m_filterList->insertItem (mime->comment ());
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nativeFormat == "application/x-kword")
|
|
|
|
{
|
|
|
|
const int index = m_mimeTypes.findIndex ("text/plain");
|
|
|
|
if (index > -1)
|
|
|
|
m_filterList->setCurrentItem (index);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_filterList->currentItem () == -1)
|
|
|
|
m_filterList->setCurrentItem (0);
|
|
|
|
|
|
|
|
m_filterList->centerCurrentItem ();
|
|
|
|
m_filterList->setFocus ();
|
|
|
|
|
|
|
|
connect (m_filterList, TQT_SIGNAL (selected (int)), this, TQT_SLOT (slotOk ()));
|
|
|
|
}
|
|
|
|
|
|
|
|
KoFilterChooser::~KoFilterChooser ()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KoFilterChooser::filterSelected ()
|
|
|
|
{
|
|
|
|
const int item = m_filterList->currentItem ();
|
|
|
|
|
|
|
|
if (item > -1)
|
|
|
|
return m_mimeTypes [item];
|
|
|
|
else
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// static cache for filter availability
|
|
|
|
TQMap<TQString, bool> KoFilterManager::m_filterAvailable;
|
|
|
|
|
|
|
|
const int KoFilterManager::s_area = 30500;
|
|
|
|
|
|
|
|
|
|
|
|
KoFilterManager::KoFilterManager( KoDocument* document ) :
|
|
|
|
m_document( document ), m_parentChain( 0 ), m_graph( "" ), d( 0 )
|
|
|
|
{
|
|
|
|
d = new KoFilterManager::Private;
|
|
|
|
d -> m_batch = false;
|
|
|
|
if ( document )
|
|
|
|
TQObject::connect( this, TQT_SIGNAL( sigProgress( int ) ),
|
|
|
|
document, TQT_SIGNAL( sigProgress( int ) ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
KoFilterManager::KoFilterManager( const TQString& url, const TQCString& mimetypeHint,
|
|
|
|
KoFilterChain* const parentChain ) :
|
|
|
|
m_document( 0 ), m_parentChain( parentChain ), m_importUrl( url ), m_importUrlMimetypeHint( mimetypeHint ),
|
|
|
|
m_graph( "" ), d( 0 )
|
|
|
|
{
|
|
|
|
d = new KoFilterManager::Private;
|
|
|
|
d -> m_batch = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
KoFilterManager::~KoFilterManager()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString KoFilterManager::import( const TQString& url, KoFilter::ConversionStatus& status )
|
|
|
|
{
|
|
|
|
// Find the mime type for the file to be imported.
|
|
|
|
KURL u;
|
|
|
|
u.setPath( url );
|
|
|
|
KMimeType::Ptr t = KMimeType::findByURL( u, 0, true );
|
|
|
|
|
|
|
|
m_graph.setSourceMimeType( t->name().latin1() ); // .latin1() is okay here (Werner)
|
|
|
|
if ( !m_graph.isValid() ) {
|
|
|
|
bool userCancelled = false;
|
|
|
|
|
|
|
|
kdWarning(s_area) << "Can't open " << t->name () << ", trying filter chooser" << endl;
|
|
|
|
if ( m_document )
|
|
|
|
{
|
|
|
|
if ( !m_document->isAutoErrorHandlingEnabled() )
|
|
|
|
{
|
|
|
|
status = KoFilter::BadConversionGraph;
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
TQCString nativeFormat = m_document->nativeFormatMimeType ();
|
|
|
|
|
|
|
|
TQApplication::setOverrideCursor( arrowCursor );
|
|
|
|
KoFilterChooser chooser(0,
|
|
|
|
KoFilterManager::mimeFilter (nativeFormat, KoFilterManager::Import, m_document->extraNativeMimeTypes()),
|
|
|
|
nativeFormat);
|
|
|
|
if (chooser.exec ())
|
|
|
|
{
|
|
|
|
TQCString f = chooser.filterSelected ().latin1();
|
|
|
|
|
|
|
|
if (f == nativeFormat)
|
|
|
|
{
|
|
|
|
status = KoFilter::OK;
|
|
|
|
TQApplication::restoreOverrideCursor();
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_graph.setSourceMimeType (f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
userCancelled = true;
|
|
|
|
TQApplication::restoreOverrideCursor();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_graph.isValid())
|
|
|
|
{
|
|
|
|
kdError(s_area) << "Couldn't create a valid graph for this source mimetype: "
|
|
|
|
<< t->name() << endl;
|
|
|
|
importErrorHelper( t->name(), userCancelled );
|
|
|
|
status = KoFilter::BadConversionGraph;
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KoFilterChain::Ptr chain( 0 );
|
|
|
|
// Are we owned by a KoDocument?
|
|
|
|
if ( m_document ) {
|
|
|
|
TQCString mimeType = m_document->nativeFormatMimeType();
|
|
|
|
TQStringList extraMimes = m_document->extraNativeMimeTypes();
|
|
|
|
int i=0, n = extraMimes.count();
|
|
|
|
chain = m_graph.chain( this, mimeType );
|
|
|
|
while( !chain && i<n) {
|
|
|
|
mimeType = extraMimes[i].utf8();
|
|
|
|
chain = m_graph.chain( this, mimeType );
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
kdError(s_area) << "You aren't supposed to use import() from a filter!" << endl;
|
|
|
|
status = KoFilter::UsageError;
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !chain ) {
|
|
|
|
kdError(s_area) << "Couldn't create a valid filter chain!" << endl;
|
|
|
|
importErrorHelper( t->name() );
|
|
|
|
status = KoFilter::BadConversionGraph;
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Okay, let's invoke the filters one after the other
|
|
|
|
m_direction = Import; // vital information!
|
|
|
|
m_importUrl = url; // We want to load that file
|
|
|
|
m_exportUrl = TQString(); // This is null for sure, as embedded stuff isn't
|
|
|
|
// allowed to use that method
|
|
|
|
status = chain->invokeChain();
|
|
|
|
|
|
|
|
m_importUrl = TQString(); // Reset the import URL
|
|
|
|
|
|
|
|
if ( status == KoFilter::OK )
|
|
|
|
return chain->chainOutput();
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
|
|
|
|
KoFilter::ConversionStatus KoFilterManager::exp0rt( const TQString& url, TQCString& mimeType )
|
|
|
|
{
|
|
|
|
bool userCancelled = false;
|
|
|
|
|
|
|
|
// The import url should already be set correctly (null if we have a KoDocument
|
|
|
|
// file manager and to the correct URL if we have an embedded manager)
|
|
|
|
m_direction = Export; // vital information!
|
|
|
|
m_exportUrl = url;
|
|
|
|
|
|
|
|
KoFilterChain::Ptr chain = 0;
|
|
|
|
if ( m_document ) {
|
|
|
|
// We have to pick the right native mimetype as source.
|
|
|
|
TQStringList nativeMimeTypes;
|
|
|
|
nativeMimeTypes.append( m_document->nativeFormatMimeType() );
|
|
|
|
nativeMimeTypes += m_document->extraNativeMimeTypes();
|
|
|
|
TQStringList::ConstIterator it = nativeMimeTypes.begin();
|
|
|
|
const TQStringList::ConstIterator end = nativeMimeTypes.end();
|
|
|
|
for ( ; !chain && it != end; ++it )
|
|
|
|
{
|
|
|
|
m_graph.setSourceMimeType( (*it).latin1() );
|
|
|
|
if ( m_graph.isValid() )
|
|
|
|
chain = m_graph.chain( this, mimeType );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if ( !m_importUrlMimetypeHint.isEmpty() ) {
|
|
|
|
kdDebug(s_area) << "Using the mimetype hint: '" << m_importUrlMimetypeHint << "'" << endl;
|
|
|
|
m_graph.setSourceMimeType( m_importUrlMimetypeHint );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
KURL u;
|
|
|
|
u.setPath( m_importUrl );
|
|
|
|
KMimeType::Ptr t = KMimeType::findByURL( u, 0, true );
|
|
|
|
if ( t->name() == KMimeType::defaultMimeType() ) {
|
|
|
|
kdError(s_area) << "No mimetype found for " << m_importUrl << endl;
|
|
|
|
return KoFilter::BadMimeType;
|
|
|
|
}
|
|
|
|
m_graph.setSourceMimeType( t->name().latin1() );
|
|
|
|
|
|
|
|
if ( !m_graph.isValid() ) {
|
|
|
|
kdWarning(s_area) << "Can't open " << t->name () << ", trying filter chooser" << endl;
|
|
|
|
|
|
|
|
TQApplication::setOverrideCursor( arrowCursor );
|
|
|
|
KoFilterChooser chooser(0, KoFilterManager::mimeFilter ());
|
|
|
|
if (chooser.exec ())
|
|
|
|
m_graph.setSourceMimeType (chooser.filterSelected ().latin1 ());
|
|
|
|
else
|
|
|
|
userCancelled = true;
|
|
|
|
|
|
|
|
TQApplication::restoreOverrideCursor();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_graph.isValid ())
|
|
|
|
{
|
|
|
|
kdError(s_area) << "Couldn't create a valid graph for this source mimetype." << endl;
|
|
|
|
if (!userCancelled) KMessageBox::error( 0L, i18n("Could not export file."), i18n("Missing Export Filter") );
|
|
|
|
return KoFilter::BadConversionGraph;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !chain ) // already set when coming from the m_document case
|
|
|
|
chain = m_graph.chain( this, mimeType );
|
|
|
|
|
|
|
|
if ( !chain ) {
|
|
|
|
kdError(s_area) << "Couldn't create a valid filter chain to " << mimeType << " !" << endl;
|
|
|
|
KMessageBox::error( 0L, i18n("Could not export file."), i18n("Missing Export Filter") );
|
|
|
|
return KoFilter::BadConversionGraph;
|
|
|
|
}
|
|
|
|
|
|
|
|
return chain->invokeChain();
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace // in order not to mess with the global namespace ;)
|
|
|
|
{
|
|
|
|
// This class is needed only for the static mimeFilter method
|
|
|
|
class Vertex
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Vertex( const TQCString& mimeType ) : m_color( White ), m_mimeType( mimeType ) {}
|
|
|
|
|
|
|
|
enum Color { White, Gray, Black };
|
|
|
|
Color color() const { return m_color; }
|
|
|
|
void setColor( Color color ) { m_color = color; }
|
|
|
|
|
|
|
|
TQCString mimeType() const { return m_mimeType; }
|
|
|
|
|
|
|
|
void addEdge( Vertex* vertex ) { if ( vertex ) m_edges.append( vertex ); }
|
|
|
|
TQPtrList<Vertex> edges() const { return m_edges; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
Color m_color;
|
|
|
|
TQCString m_mimeType;
|
|
|
|
TQPtrList<Vertex> m_edges;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Some helper methods for the static stuff
|
|
|
|
// This method builds up the graph in the passed ascii dict
|
|
|
|
void buildGraph( TQAsciiDict<Vertex>& vertices, KoFilterManager::Direction direction )
|
|
|
|
{
|
|
|
|
TQStringList stopList; // Lists of mimetypes that are considered end of chains
|
|
|
|
stopList << "text/plain";
|
|
|
|
stopList << "text/csv";
|
|
|
|
stopList << "text/x-tex";
|
|
|
|
stopList << "text/html";
|
|
|
|
|
|
|
|
vertices.setAutoDelete( true );
|
|
|
|
|
|
|
|
// partly copied from build graph, but I don't see any other
|
|
|
|
// way without crude hacks, as we have to obey the direction here
|
|
|
|
TQValueList<KoDocumentEntry> parts( KoDocumentEntry::query(false, TQString()) );
|
|
|
|
TQValueList<KoDocumentEntry>::ConstIterator partIt( parts.begin() );
|
|
|
|
TQValueList<KoDocumentEntry>::ConstIterator partEnd( parts.end() );
|
|
|
|
|
|
|
|
while ( partIt != partEnd ) {
|
|
|
|
TQStringList nativeMimeTypes = ( *partIt ).service()->property( "X-TDE-ExtraNativeMimeTypes" ).toStringList();
|
|
|
|
nativeMimeTypes += ( *partIt ).service()->property( "X-TDE-NativeMimeType" ).toString();
|
|
|
|
TQStringList::ConstIterator it = nativeMimeTypes.begin();
|
|
|
|
const TQStringList::ConstIterator end = nativeMimeTypes.end();
|
|
|
|
for ( ; it != end; ++it )
|
|
|
|
if ( !(*it).isEmpty() )
|
|
|
|
vertices.insert( (*it).latin1(), new Vertex( (*it).latin1() ) );
|
|
|
|
++partIt;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQValueList<KoFilterEntry::Ptr> filters = KoFilterEntry::query(); // no constraint here - we want *all* :)
|
|
|
|
TQValueList<KoFilterEntry::Ptr>::ConstIterator it = filters.begin();
|
|
|
|
const TQValueList<KoFilterEntry::Ptr>::ConstIterator end = filters.end();
|
|
|
|
|
|
|
|
for ( ; it != end; ++it ) {
|
|
|
|
|
|
|
|
TQStringList impList; // Import list
|
|
|
|
TQStringList expList; // Export list
|
|
|
|
|
|
|
|
const TQStringList::Iterator stopEnd = stopList.end();
|
|
|
|
// Now we have to exclude the "stop" mimetypes (in the right direction!)
|
|
|
|
if ( direction == KoFilterManager::Import ) {
|
|
|
|
// Import: "stop" mime type should not appear in export
|
|
|
|
TQStringList::ConstIterator testIt = ( *it )->export_.begin();
|
|
|
|
TQStringList::ConstIterator testEnd = ( *it )->export_.end();
|
|
|
|
for ( ; testIt != testEnd ; ++testIt ) {
|
|
|
|
if ( stopList.find( *testIt ) == stopEnd ) {
|
|
|
|
expList.append( *testIt );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impList = ( *it )->import;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Export: "stop" mime type should not appear in import
|
|
|
|
TQStringList::ConstIterator testIt = ( *it )->import.begin();
|
|
|
|
const TQStringList::ConstIterator testEnd = ( *it )->import.end();
|
|
|
|
for ( ; testIt != testEnd ; ++testIt ) {
|
|
|
|
if ( stopList.find( *testIt ) == stopEnd ) {
|
|
|
|
impList.append( *testIt );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
expList = ( *it )->export_;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( impList.empty() || expList.empty() )
|
|
|
|
{
|
|
|
|
// This filter cannot be used under these conditions
|
|
|
|
kdDebug( 30500 ) << "Filter: " << ( *it )->service()->name() << " ruled out" << endl;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// First add the "starting points" to the dict
|
|
|
|
TQStringList::ConstIterator importIt = impList.begin();
|
|
|
|
const TQStringList::ConstIterator importEnd = impList.end();
|
|
|
|
for ( ; importIt != importEnd; ++importIt ) {
|
|
|
|
const TQCString key = ( *importIt ).latin1(); // latin1 is okay here (werner)
|
|
|
|
// already there?
|
|
|
|
if ( !vertices[ key ] )
|
|
|
|
vertices.insert( key, new Vertex( key ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Are we allowed to use this filter at all?
|
|
|
|
if ( KoFilterManager::filterAvailable( *it ) ) {
|
|
|
|
TQStringList::ConstIterator exportIt = expList.begin();
|
|
|
|
const TQStringList::ConstIterator exportEnd = expList.end();
|
|
|
|
|
|
|
|
for ( ; exportIt != exportEnd; ++exportIt ) {
|
|
|
|
// First make sure the export vertex is in place
|
|
|
|
const TQCString key = ( *exportIt ).latin1(); // latin1 is okay here
|
|
|
|
Vertex* exp = vertices[ key ];
|
|
|
|
if ( !exp ) {
|
|
|
|
exp = new Vertex( key );
|
|
|
|
vertices.insert( key, exp );
|
|
|
|
}
|
|
|
|
// Then create the appropriate edges depending on the
|
|
|
|
// direction (import/export)
|
|
|
|
// This is the chunk of code which actually differs from the
|
|
|
|
// graph stuff (apart from the different vertex class)
|
|
|
|
importIt = impList.begin(); // ### TODO: why only the first one?
|
|
|
|
if ( direction == KoFilterManager::Import ) {
|
|
|
|
for ( ; importIt != importEnd; ++importIt )
|
|
|
|
exp->addEdge( vertices[ ( *importIt ).latin1() ] );
|
|
|
|
} else {
|
|
|
|
for ( ; importIt != importEnd; ++importIt )
|
|
|
|
vertices[ ( *importIt ).latin1() ]->addEdge( exp );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
kdDebug( 30500 ) << "Filter: " << ( *it )->service()->name() << " does not apply." << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This method runs a BFS on the graph to determine the connected
|
|
|
|
// nodes. Make sure that the graph is "cleared" (the colors of the
|
|
|
|
// nodes are all white)
|
|
|
|
TQStringList connected( const TQAsciiDict<Vertex>& vertices, const TQCString& mimetype )
|
|
|
|
{
|
|
|
|
if ( mimetype.isEmpty() )
|
|
|
|
return TQStringList();
|
|
|
|
Vertex *v = vertices[ mimetype ];
|
|
|
|
if ( !v )
|
|
|
|
return TQStringList();
|
|
|
|
|
|
|
|
v->setColor( Vertex::Gray );
|
|
|
|
std::queue<Vertex*> queue;
|
|
|
|
queue.push( v );
|
|
|
|
TQStringList connected;
|
|
|
|
|
|
|
|
while ( !queue.empty() ) {
|
|
|
|
v = queue.front();
|
|
|
|
queue.pop();
|
|
|
|
TQPtrList<Vertex> edges = v->edges();
|
|
|
|
TQPtrListIterator<Vertex> it( edges );
|
|
|
|
for ( ; it.current(); ++it ) {
|
|
|
|
if ( it.current()->color() == Vertex::White ) {
|
|
|
|
it.current()->setColor( Vertex::Gray );
|
|
|
|
queue.push( it.current() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
v->setColor( Vertex::Black );
|
|
|
|
connected.append( v->mimeType() );
|
|
|
|
}
|
|
|
|
return connected;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The static method to figure out to which parts of the
|
|
|
|
// graph this mimetype has a connection to.
|
|
|
|
TQStringList KoFilterManager::mimeFilter( const TQCString& mimetype, Direction direction, const TQStringList& extraNativeMimeTypes )
|
|
|
|
{
|
|
|
|
//kdDebug(s_area) << "mimetype=" << mimetype << " extraNativeMimeTypes=" << extraNativeMimeTypes << endl;
|
|
|
|
TQAsciiDict<Vertex> vertices;
|
|
|
|
buildGraph( vertices, direction );
|
|
|
|
|
|
|
|
// TODO maybe use the fake vertex trick from the method below, to make the search faster?
|
|
|
|
|
|
|
|
TQStringList nativeMimeTypes;
|
|
|
|
nativeMimeTypes.append( TQString::fromLatin1( mimetype ) );
|
|
|
|
nativeMimeTypes += extraNativeMimeTypes;
|
|
|
|
|
|
|
|
// Add the native mimetypes first so that they are on top.
|
|
|
|
TQStringList lst = nativeMimeTypes;
|
|
|
|
|
|
|
|
// Now look for filters which output each of those natives mimetypes
|
|
|
|
for( TQStringList::ConstIterator natit = nativeMimeTypes.begin(); natit != nativeMimeTypes.end(); ++natit ) {
|
|
|
|
const TQStringList outMimes = connected( vertices, (*natit).latin1() );
|
|
|
|
//kdDebug(s_area) << k_funcinfo << "output formats connected to mime " << *natit << " : " << outMimes << endl;
|
|
|
|
for ( TQStringList::ConstIterator mit = outMimes.begin(); mit != outMimes.end(); ++mit )
|
|
|
|
if ( lst.find( *mit ) == lst.end() ) // append only if not there already. TQt4: TQSet<TQString>?
|
|
|
|
lst.append( *mit );
|
|
|
|
}
|
|
|
|
return lst;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList KoFilterManager::mimeFilter()
|
|
|
|
{
|
|
|
|
TQAsciiDict<Vertex> vertices;
|
|
|
|
buildGraph( vertices, KoFilterManager::Import );
|
|
|
|
|
|
|
|
TQValueList<KoDocumentEntry> parts( KoDocumentEntry::query(false, TQString()) );
|
|
|
|
TQValueList<KoDocumentEntry>::ConstIterator partIt( parts.begin() );
|
|
|
|
TQValueList<KoDocumentEntry>::ConstIterator partEnd( parts.end() );
|
|
|
|
|
|
|
|
if ( partIt == partEnd )
|
|
|
|
return TQStringList();
|
|
|
|
|
|
|
|
// To find *all* reachable mimetypes, we have to resort to
|
|
|
|
// a small hat trick, in order to avoid multiple searches:
|
|
|
|
// We introduce a fake vertex, which is connected to every
|
|
|
|
// single KOffice mimetype. Due to that one BFS is enough :)
|
|
|
|
// Now we just need an... ehrm.. unique name for our fake mimetype
|
|
|
|
Vertex *v = new Vertex( "supercalifragilistic/x-pialadocious" );
|
|
|
|
vertices.insert( "supercalifragilistic/x-pialadocious", v );
|
|
|
|
while ( partIt != partEnd ) {
|
|
|
|
TQStringList nativeMimeTypes = ( *partIt ).service()->property( "X-TDE-ExtraNativeMimeTypes" ).toStringList();
|
|
|
|
nativeMimeTypes += ( *partIt ).service()->property( "X-TDE-NativeMimeType" ).toString();
|
|
|
|
TQStringList::ConstIterator it = nativeMimeTypes.begin();
|
|
|
|
const TQStringList::ConstIterator end = nativeMimeTypes.end();
|
|
|
|
for ( ; it != end; ++it )
|
|
|
|
if ( !(*it).isEmpty() )
|
|
|
|
v->addEdge( vertices[ (*it).latin1() ] );
|
|
|
|
++partIt;
|
|
|
|
}
|
|
|
|
TQStringList result = connected( vertices, "supercalifragilistic/x-pialadocious" );
|
|
|
|
|
|
|
|
// Finally we have to get rid of our fake mimetype again
|
|
|
|
result.remove( "supercalifragilistic/x-pialadocious" );
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Here we check whether the filter is available. This stuff is quite slow,
|
|
|
|
// but I don't see any other convenient (for the user) way out :}
|
|
|
|
bool KoFilterManager::filterAvailable( KoFilterEntry::Ptr entry )
|
|
|
|
{
|
|
|
|
if ( !entry )
|
|
|
|
return false;
|
|
|
|
if ( entry->available != "check" )
|
|
|
|
return true;
|
|
|
|
|
|
|
|
//kdDebug( 30500 ) << "Checking whether " << entry->service()->name() << " applies." << endl;
|
|
|
|
// generate some "unique" key
|
|
|
|
TQString key( entry->service()->name() );
|
|
|
|
key += " - ";
|
|
|
|
key += entry->service()->library();
|
|
|
|
|
|
|
|
if ( !m_filterAvailable.contains( key ) ) {
|
|
|
|
//kdDebug( 30500 ) << "Not cached, checking..." << endl;
|
|
|
|
|
|
|
|
KLibrary* library = KLibLoader::self()->library( TQFile::encodeName( entry->service()->library() ) );
|
|
|
|
if ( !library ) {
|
|
|
|
kdWarning( 30500 ) << "Huh?? Couldn't load the lib: "
|
|
|
|
<< KLibLoader::self()->lastErrorMessage() << endl;
|
|
|
|
m_filterAvailable[ key ] = false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This code is "borrowed" from klibloader ;)
|
|
|
|
TQCString symname;
|
|
|
|
symname.sprintf("check_%s", library->name().latin1() );
|
|
|
|
void* sym = library->symbol( symname );
|
|
|
|
if ( !sym )
|
|
|
|
{
|
|
|
|
kdWarning( 30500 ) << "The library " << library->name()
|
|
|
|
<< " does not offer a check_" << library->name()
|
|
|
|
<< " function." << endl;
|
|
|
|
m_filterAvailable[ key ] = false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
typedef int (*t_func)();
|
|
|
|
t_func check = (t_func)sym;
|
|
|
|
m_filterAvailable[ key ] = check() == 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return m_filterAvailable[ key ];
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoFilterManager::importErrorHelper( const TQString& mimeType, const bool suppressDialog )
|
|
|
|
{
|
|
|
|
TQString tmp = i18n("Could not import file of type\n%1").arg( mimeType );
|
|
|
|
// ###### FIXME: use KLibLoader::lastErrorMessage() here
|
|
|
|
if (!suppressDialog) KMessageBox::error( 0L, tmp, i18n("Missing Import Filter") );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KoFilterManager::setBatchMode( const bool batch )
|
|
|
|
{
|
|
|
|
d->m_batch = batch;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KoFilterManager::getBatchMode( void ) const
|
|
|
|
{
|
|
|
|
return d->m_batch;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <KoFilterManager.moc>
|
|
|
|
#include <KoFilterManager_p.moc>
|