lib

KoFilterManager.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998, 1999 Torben Weis <weis@kde.org>
00003                  2000, 2001 Werner Trobin <trobin@kde.org>
00004    Copyright (C) 2004 Nicolas Goutte <goutte@kde.org>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020 */
00021 
00022 
00023 #include <KoFilterManager.h>
00024 #include <KoFilterManager_p.h>
00025 
00026 #include <qfile.h>
00027 #include <qlabel.h>
00028 #include <qlayout.h>
00029 #include <qptrlist.h>
00030 #include <qapplication.h>
00031 
00032 #include <klocale.h>
00033 #include <kmessagebox.h>
00034 #include <KoDocument.h>
00035 #include <klibloader.h>
00036 #include <klistbox.h>
00037 #include <kmimetype.h>
00038 #include <kdebug.h>
00039 
00040 #include <queue>
00041 
00042 #include <unistd.h>
00043 
00044 class KoFilterManager::Private
00045 {
00046 public:
00047     bool m_batch;
00048 };
00049 
00050 
00051 KoFilterChooser::KoFilterChooser (QWidget *parent, const QStringList &mimeTypes, const QString &nativeFormat)
00052     : KDialogBase (parent, "kofilterchooser", true, i18n ("Choose Filter"),
00053                    KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, true),
00054     m_mimeTypes (mimeTypes)
00055 {
00056     setInitialSize (QSize (300, 350));
00057 
00058     QWidget *page = new QWidget (this);
00059     setMainWidget (page);
00060 
00061     // looks too squashed together without * 2
00062     QVBoxLayout *layout = new QVBoxLayout (page, marginHint (), spacingHint () * 2);
00063 
00064     QLabel *filterLabel = new QLabel (i18n ("Select a filter:"), page, "filterlabel");
00065     layout->addWidget (filterLabel);
00066 
00067     m_filterList = new KListBox (page, "filterlist");
00068     layout->addWidget (m_filterList);
00069 
00070     Q_ASSERT (!m_mimeTypes.isEmpty ());
00071     for (QStringList::ConstIterator it = m_mimeTypes.begin ();
00072             it != m_mimeTypes.end ();
00073             it++)
00074     {
00075         KMimeType::Ptr mime = KMimeType::mimeType (*it);
00076         m_filterList->insertItem (mime->comment ());
00077     }
00078 
00079     if (nativeFormat == "application/x-kword")
00080     {
00081         const int index = m_mimeTypes.findIndex ("text/plain");
00082         if (index > -1)
00083             m_filterList->setCurrentItem (index);
00084     }
00085 
00086     if (m_filterList->currentItem () == -1)
00087         m_filterList->setCurrentItem (0);
00088 
00089     m_filterList->centerCurrentItem ();
00090     m_filterList->setFocus ();
00091 
00092     connect (m_filterList, SIGNAL (selected (int)), this, SLOT (slotOk ()));
00093 }
00094 
00095 KoFilterChooser::~KoFilterChooser ()
00096 {
00097 }
00098 
00099 QString KoFilterChooser::filterSelected ()
00100 {
00101     const int item = m_filterList->currentItem ();
00102 
00103     if (item > -1)
00104         return m_mimeTypes [item];
00105     else
00106         return QString::null;
00107 }
00108 
00109 
00110 // static cache for filter availability
00111 QMap<QString, bool> KoFilterManager::m_filterAvailable;
00112 
00113 const int KoFilterManager::s_area = 30500;
00114 
00115 
00116 KoFilterManager::KoFilterManager( KoDocument* document ) :
00117     m_document( document ), m_parentChain( 0 ), m_graph( "" ), d( 0 )
00118 {
00119     d = new KoFilterManager::Private;
00120     d -> m_batch = false;
00121     if ( document )
00122         QObject::connect( this, SIGNAL( sigProgress( int ) ),
00123                           document, SIGNAL( sigProgress( int ) ) );
00124 }
00125 
00126 
00127 KoFilterManager::KoFilterManager( const QString& url, const QCString& mimetypeHint,
00128                                   KoFilterChain* const parentChain ) :
00129     m_document( 0 ), m_parentChain( parentChain ), m_importUrl( url ), m_importUrlMimetypeHint( mimetypeHint ),
00130     m_graph( "" ), d( 0 )
00131 {
00132     d = new KoFilterManager::Private;
00133     d -> m_batch = false;
00134 }
00135 
00136 KoFilterManager::~KoFilterManager()
00137 {
00138     delete d;
00139 }
00140 
00141 QString KoFilterManager::import( const QString& url, KoFilter::ConversionStatus& status )
00142 {
00143     // Find the mime type for the file to be imported.
00144     KURL u;
00145     u.setPath( url );
00146     KMimeType::Ptr t = KMimeType::findByURL( u, 0, true );
00147 
00148     m_graph.setSourceMimeType( t->name().latin1() );  // .latin1() is okay here (Werner)
00149     if ( !m_graph.isValid() ) {
00150         bool userCancelled = false;
00151 
00152         kdWarning(s_area) << "Can't open " << t->name () << ", trying filter chooser" << endl;
00153         if ( m_document )
00154         {
00155         if ( !m_document->isAutoErrorHandlingEnabled() )
00156         {
00157         status = KoFilter::BadConversionGraph;
00158         return QString::null;
00159         }
00160             QCString nativeFormat = m_document->nativeFormatMimeType ();
00161 
00162             QApplication::setOverrideCursor( arrowCursor );
00163             KoFilterChooser chooser(0,
00164                                     KoFilterManager::mimeFilter (nativeFormat, KoFilterManager::Import, m_document->extraNativeMimeTypes()),
00165                                     nativeFormat);
00166             if (chooser.exec ())
00167             {
00168                 QCString f = chooser.filterSelected ().latin1();
00169 
00170                 if (f == nativeFormat)
00171                 {
00172                     status = KoFilter::OK;
00173                     QApplication::restoreOverrideCursor();
00174                     return url;
00175                 }
00176 
00177                 m_graph.setSourceMimeType (f);
00178             }
00179             else
00180                 userCancelled = true;
00181             QApplication::restoreOverrideCursor();
00182         }
00183 
00184         if (!m_graph.isValid())
00185         {
00186             kdError(s_area) << "Couldn't create a valid graph for this source mimetype: "
00187                             << t->name() << endl;
00188             importErrorHelper( t->name(), userCancelled );
00189             status = KoFilter::BadConversionGraph;
00190             return QString::null;
00191         }
00192     }
00193 
00194     KoFilterChain::Ptr chain( 0 );
00195     // Are we owned by a KoDocument?
00196     if ( m_document ) {
00197         QCString mimeType = m_document->nativeFormatMimeType();
00198         QStringList extraMimes = m_document->extraNativeMimeTypes();
00199         int i=0, n = extraMimes.count();
00200         chain = m_graph.chain( this, mimeType );
00201         while( !chain && i<n) {
00202             mimeType = extraMimes[i].utf8();
00203             chain = m_graph.chain( this, mimeType );
00204             ++i;
00205         }
00206     }
00207     else {
00208         kdError(s_area) << "You aren't supposed to use import() from a filter!" << endl;
00209         status = KoFilter::UsageError;
00210         return QString::null;
00211     }
00212 
00213     if ( !chain ) {
00214         kdError(s_area) << "Couldn't create a valid filter chain!" << endl;
00215         importErrorHelper( t->name() );
00216         status = KoFilter::BadConversionGraph;
00217         return QString::null;
00218     }
00219 
00220     // Okay, let's invoke the filters one after the other
00221     m_direction = Import; // vital information!
00222     m_importUrl = url;  // We want to load that file
00223     m_exportUrl = QString::null;  // This is null for sure, as embedded stuff isn't
00224                                   // allowed to use that method
00225     status = chain->invokeChain();
00226 
00227     m_importUrl = QString::null;  // Reset the import URL
00228 
00229     if ( status == KoFilter::OK )
00230         return chain->chainOutput();
00231     return QString::null;
00232 }
00233 
00234 KoFilter::ConversionStatus KoFilterManager::exp0rt( const QString& url, QCString& mimeType )
00235 {
00236     bool userCancelled = false;
00237 
00238     // The import url should already be set correctly (null if we have a KoDocument
00239     // file manager and to the correct URL if we have an embedded manager)
00240     m_direction = Export; // vital information!
00241     m_exportUrl = url;
00242 
00243     KoFilterChain::Ptr chain = 0;
00244     if ( m_document ) {
00245         // We have to pick the right native mimetype as source.
00246         QStringList nativeMimeTypes;
00247         nativeMimeTypes.append( m_document->nativeFormatMimeType() );
00248         nativeMimeTypes += m_document->extraNativeMimeTypes();
00249         QStringList::ConstIterator it = nativeMimeTypes.begin();
00250         const QStringList::ConstIterator end = nativeMimeTypes.end();
00251         for ( ; !chain && it != end; ++it )
00252         {
00253             m_graph.setSourceMimeType( (*it).latin1() );
00254             if ( m_graph.isValid() )
00255                 chain = m_graph.chain( this, mimeType );
00256         }
00257     }
00258     else if ( !m_importUrlMimetypeHint.isEmpty() ) {
00259         kdDebug(s_area) << "Using the mimetype hint: '" << m_importUrlMimetypeHint << "'" << endl;
00260         m_graph.setSourceMimeType( m_importUrlMimetypeHint );
00261     }
00262     else {
00263         KURL u;
00264         u.setPath( m_importUrl );
00265         KMimeType::Ptr t = KMimeType::findByURL( u, 0, true );
00266         if ( t->name() == KMimeType::defaultMimeType() ) {
00267             kdError(s_area) << "No mimetype found for " << m_importUrl << endl;
00268             return KoFilter::BadMimeType;
00269         }
00270         m_graph.setSourceMimeType( t->name().latin1() );
00271 
00272         if ( !m_graph.isValid() ) {
00273             kdWarning(s_area) << "Can't open " << t->name () << ", trying filter chooser" << endl;
00274 
00275             QApplication::setOverrideCursor( arrowCursor );
00276             KoFilterChooser chooser(0, KoFilterManager::mimeFilter ());
00277             if (chooser.exec ())
00278                 m_graph.setSourceMimeType (chooser.filterSelected ().latin1 ());
00279             else
00280                 userCancelled = true;
00281 
00282             QApplication::restoreOverrideCursor();
00283         }
00284     }
00285 
00286     if (!m_graph.isValid ())
00287     {
00288         kdError(s_area) << "Couldn't create a valid graph for this source mimetype." << endl;
00289         if (!userCancelled) KMessageBox::error( 0L, i18n("Could not export file."), i18n("Missing Export Filter") );
00290         return KoFilter::BadConversionGraph;
00291     }
00292 
00293     if ( !chain ) // already set when coming from the m_document case
00294         chain = m_graph.chain( this, mimeType );
00295 
00296     if ( !chain ) {
00297         kdError(s_area) << "Couldn't create a valid filter chain to " << mimeType << " !" << endl;
00298         KMessageBox::error( 0L, i18n("Could not export file."), i18n("Missing Export Filter") );
00299         return KoFilter::BadConversionGraph;
00300     }
00301 
00302     return chain->invokeChain();
00303 }
00304 
00305 namespace  // in order not to mess with the global namespace ;)
00306 {
00307     // This class is needed only for the static mimeFilter method
00308     class Vertex
00309     {
00310     public:
00311         Vertex( const QCString& mimeType ) : m_color( White ), m_mimeType( mimeType ) {}
00312 
00313         enum Color { White, Gray, Black };
00314         Color color() const { return m_color; }
00315         void setColor( Color color ) { m_color = color; }
00316 
00317         QCString mimeType() const { return m_mimeType; }
00318 
00319         void addEdge( Vertex* vertex ) { if ( vertex ) m_edges.append( vertex ); }
00320         QPtrList<Vertex> edges() const { return m_edges; }
00321 
00322     private:
00323         Color m_color;
00324         QCString m_mimeType;
00325         QPtrList<Vertex> m_edges;
00326     };
00327 
00328     // Some helper methods for the static stuff
00329     // This method builds up the graph in the passed ascii dict
00330     void buildGraph( QAsciiDict<Vertex>& vertices, KoFilterManager::Direction direction )
00331     {
00332         QStringList stopList; // Lists of mimetypes that are considered end of chains
00333         stopList << "text/plain";
00334         stopList << "text/csv";
00335         stopList << "text/x-tex";
00336         stopList << "text/html";
00337 
00338         vertices.setAutoDelete( true );
00339 
00340         // partly copied from build graph, but I don't see any other
00341         // way without crude hacks, as we have to obey the direction here
00342         QValueList<KoDocumentEntry> parts( KoDocumentEntry::query(false, QString::null) );
00343         QValueList<KoDocumentEntry>::ConstIterator partIt( parts.begin() );
00344         QValueList<KoDocumentEntry>::ConstIterator partEnd( parts.end() );
00345 
00346         while ( partIt != partEnd ) {
00347             QStringList nativeMimeTypes = ( *partIt ).service()->property( "X-KDE-ExtraNativeMimeTypes" ).toStringList();
00348             nativeMimeTypes += ( *partIt ).service()->property( "X-KDE-NativeMimeType" ).toString();
00349             QStringList::ConstIterator it = nativeMimeTypes.begin();
00350             const QStringList::ConstIterator end = nativeMimeTypes.end();
00351             for ( ; it != end; ++it )
00352                 if ( !(*it).isEmpty() )
00353                     vertices.insert( (*it).latin1(), new Vertex( (*it).latin1() ) );
00354             ++partIt;
00355         }
00356 
00357         QValueList<KoFilterEntry::Ptr> filters = KoFilterEntry::query(); // no constraint here - we want *all* :)
00358         QValueList<KoFilterEntry::Ptr>::ConstIterator it = filters.begin();
00359         const QValueList<KoFilterEntry::Ptr>::ConstIterator end = filters.end();
00360 
00361         for ( ; it != end; ++it ) {
00362 
00363             QStringList impList; // Import list
00364             QStringList expList; // Export list
00365 
00366             const QStringList::Iterator stopEnd = stopList.end();
00367             // Now we have to exclude the "stop" mimetypes (in the right direction!)
00368             if ( direction == KoFilterManager::Import ) {
00369                 // Import: "stop" mime type should not appear in export
00370                 QStringList::ConstIterator testIt = ( *it )->export_.begin();
00371                 QStringList::ConstIterator testEnd = ( *it )->export_.end();
00372                 for ( ; testIt != testEnd ; ++testIt ) {
00373                     if ( stopList.find( *testIt ) == stopEnd ) {
00374                         expList.append( *testIt );
00375                     }
00376                 }
00377                 impList = ( *it )->import;
00378             }
00379             else {
00380                 // Export: "stop" mime type should not appear in import
00381                 QStringList::ConstIterator testIt = ( *it )->import.begin();
00382                 const QStringList::ConstIterator testEnd = ( *it )->import.end();
00383                 for ( ; testIt != testEnd ; ++testIt ) {
00384                     if ( stopList.find( *testIt ) == stopEnd ) {
00385                         impList.append( *testIt );
00386                     }
00387                 }
00388                 expList = ( *it )->export_;
00389             }
00390 
00391             if ( impList.empty() || expList.empty() )
00392             {
00393                 // This filter cannot be used under these conditions
00394                 kdDebug( 30500 ) << "Filter: " << ( *it )->service()->name() << " ruled out" << endl;
00395                 continue;
00396             }
00397 
00398             // First add the "starting points" to the dict
00399             QStringList::ConstIterator importIt = impList.begin();
00400             const QStringList::ConstIterator importEnd = impList.end();
00401             for ( ; importIt != importEnd; ++importIt ) {
00402                 const QCString key = ( *importIt ).latin1();  // latin1 is okay here (werner)
00403                 // already there?
00404                 if ( !vertices[ key ] )
00405                     vertices.insert( key, new Vertex( key ) );
00406             }
00407 
00408             // Are we allowed to use this filter at all?
00409             if ( KoFilterManager::filterAvailable( *it ) ) {
00410                 QStringList::ConstIterator exportIt = expList.begin();
00411                 const QStringList::ConstIterator exportEnd = expList.end();
00412 
00413                 for ( ; exportIt != exportEnd; ++exportIt ) {
00414                     // First make sure the export vertex is in place
00415                     const QCString key = ( *exportIt ).latin1();  // latin1 is okay here
00416                     Vertex* exp = vertices[ key ];
00417                     if ( !exp ) {
00418                         exp = new Vertex( key );
00419                         vertices.insert( key, exp );
00420                     }
00421                     // Then create the appropriate edges depending on the
00422                     // direction (import/export)
00423                     // This is the chunk of code which actually differs from the
00424                     // graph stuff (apart from the different vertex class)
00425                     importIt = impList.begin(); // ### TODO: why only the first one?
00426                     if ( direction == KoFilterManager::Import ) {
00427                         for ( ; importIt != importEnd; ++importIt )
00428                             exp->addEdge( vertices[ ( *importIt ).latin1() ] );
00429                     } else {
00430                         for ( ; importIt != importEnd; ++importIt )
00431                             vertices[ ( *importIt ).latin1() ]->addEdge( exp );
00432                     }
00433                 }
00434             }
00435             else
00436                 kdDebug( 30500 ) << "Filter: " << ( *it )->service()->name() << " does not apply." << endl;
00437         }
00438     }
00439 
00440     // This method runs a BFS on the graph to determine the connected
00441     // nodes. Make sure that the graph is "cleared" (the colors of the
00442     // nodes are all white)
00443     QStringList connected( const QAsciiDict<Vertex>& vertices, const QCString& mimetype )
00444     {
00445         if ( mimetype.isEmpty() )
00446             return QStringList();
00447         Vertex *v = vertices[ mimetype ];
00448         if ( !v )
00449             return QStringList();
00450 
00451         v->setColor( Vertex::Gray );
00452         std::queue<Vertex*> queue;
00453         queue.push( v );
00454         QStringList connected;
00455 
00456         while ( !queue.empty() ) {
00457             v = queue.front();
00458             queue.pop();
00459             QPtrList<Vertex> edges = v->edges();
00460             QPtrListIterator<Vertex> it( edges );
00461             for ( ; it.current(); ++it ) {
00462                 if ( it.current()->color() == Vertex::White ) {
00463                     it.current()->setColor( Vertex::Gray );
00464                     queue.push( it.current() );
00465                 }
00466             }
00467             v->setColor( Vertex::Black );
00468             connected.append( v->mimeType() );
00469         }
00470         return connected;
00471     }
00472 }
00473 
00474 // The static method to figure out to which parts of the
00475 // graph this mimetype has a connection to.
00476 QStringList KoFilterManager::mimeFilter( const QCString& mimetype, Direction direction, const QStringList& extraNativeMimeTypes )
00477 {
00478     //kdDebug(s_area) << "mimetype=" << mimetype << " extraNativeMimeTypes=" << extraNativeMimeTypes << endl;
00479     QAsciiDict<Vertex> vertices;
00480     buildGraph( vertices, direction );
00481 
00482     // TODO maybe use the fake vertex trick from the method below, to make the search faster?
00483 
00484     QStringList nativeMimeTypes;
00485     nativeMimeTypes.append( QString::fromLatin1( mimetype ) );
00486     nativeMimeTypes += extraNativeMimeTypes;
00487 
00488     // Add the native mimetypes first so that they are on top.
00489     QStringList lst = nativeMimeTypes;
00490 
00491     // Now look for filters which output each of those natives mimetypes
00492     for( QStringList::ConstIterator natit = nativeMimeTypes.begin(); natit != nativeMimeTypes.end(); ++natit ) {
00493         const QStringList outMimes = connected( vertices, (*natit).latin1() );
00494         //kdDebug(s_area) << k_funcinfo << "output formats connected to mime " << *natit << " : " << outMimes << endl;
00495         for ( QStringList::ConstIterator mit = outMimes.begin(); mit != outMimes.end(); ++mit )
00496             if ( lst.find( *mit ) == lst.end() ) // append only if not there already. Qt4: QSet<QString>?
00497                 lst.append( *mit );
00498     }
00499     return lst;
00500 }
00501 
00502 QStringList KoFilterManager::mimeFilter()
00503 {
00504     QAsciiDict<Vertex> vertices;
00505     buildGraph( vertices, KoFilterManager::Import );
00506 
00507     QValueList<KoDocumentEntry> parts( KoDocumentEntry::query(false, QString::null) );
00508     QValueList<KoDocumentEntry>::ConstIterator partIt( parts.begin() );
00509     QValueList<KoDocumentEntry>::ConstIterator partEnd( parts.end() );
00510 
00511     if ( partIt == partEnd )
00512         return QStringList();
00513 
00514     // To find *all* reachable mimetypes, we have to resort to
00515     // a small hat trick, in order to avoid multiple searches:
00516     // We introduce a fake vertex, which is connected to every
00517     // single KOffice mimetype. Due to that one BFS is enough :)
00518     // Now we just need an... ehrm.. unique name for our fake mimetype
00519     Vertex *v = new Vertex( "supercalifragilistic/x-pialadocious" );
00520     vertices.insert( "supercalifragilistic/x-pialadocious", v );
00521     while ( partIt != partEnd ) {
00522         QStringList nativeMimeTypes = ( *partIt ).service()->property( "X-KDE-ExtraNativeMimeTypes" ).toStringList();
00523         nativeMimeTypes += ( *partIt ).service()->property( "X-KDE-NativeMimeType" ).toString();
00524         QStringList::ConstIterator it = nativeMimeTypes.begin();
00525         const QStringList::ConstIterator end = nativeMimeTypes.end();
00526         for ( ; it != end; ++it )
00527             if ( !(*it).isEmpty() )
00528                 v->addEdge( vertices[ (*it).latin1() ] );
00529         ++partIt;
00530     }
00531     QStringList result = connected( vertices, "supercalifragilistic/x-pialadocious" );
00532 
00533     // Finally we have to get rid of our fake mimetype again
00534     result.remove( "supercalifragilistic/x-pialadocious" );
00535     return result;
00536 }
00537 
00538 // Here we check whether the filter is available. This stuff is quite slow,
00539 // but I don't see any other convenient (for the user) way out :}
00540 bool KoFilterManager::filterAvailable( KoFilterEntry::Ptr entry )
00541 {
00542     if ( !entry )
00543         return false;
00544     if ( entry->available != "check" )
00545         return true;
00546 
00547     //kdDebug( 30500 ) << "Checking whether " << entry->service()->name() << " applies." << endl;
00548     // generate some "unique" key
00549     QString key( entry->service()->name() );
00550     key += " - ";
00551     key += entry->service()->library();
00552 
00553     if ( !m_filterAvailable.contains( key ) ) {
00554         //kdDebug( 30500 ) << "Not cached, checking..." << endl;
00555 
00556         KLibrary* library = KLibLoader::self()->library( QFile::encodeName( entry->service()->library() ) );
00557         if ( !library ) {
00558             kdWarning( 30500 ) << "Huh?? Couldn't load the lib: "
00559                                << KLibLoader::self()->lastErrorMessage() << endl;
00560             m_filterAvailable[ key ] = false;
00561             return false;
00562         }
00563 
00564         // This code is "borrowed" from klibloader ;)
00565         QCString symname;
00566         symname.sprintf("check_%s", library->name().latin1() );
00567         void* sym = library->symbol( symname );
00568         if ( !sym )
00569         {
00570             kdWarning( 30500 ) << "The library " << library->name()
00571                                << " does not offer a check_" << library->name()
00572                                << " function." << endl;
00573             m_filterAvailable[ key ] = false;
00574         }
00575         else {
00576             typedef int (*t_func)();
00577             t_func check = (t_func)sym;
00578             m_filterAvailable[ key ] = check() == 1;
00579         }
00580     }
00581     return m_filterAvailable[ key ];
00582 }
00583 
00584 void KoFilterManager::importErrorHelper( const QString& mimeType, const bool suppressDialog )
00585 {
00586     QString tmp = i18n("Could not import file of type\n%1").arg( mimeType );
00587     // ###### FIXME: use KLibLoader::lastErrorMessage() here
00588     if (!suppressDialog) KMessageBox::error( 0L, tmp, i18n("Missing Import Filter") );
00589 }
00590 
00591 void KoFilterManager::setBatchMode( const bool batch )
00592 {
00593     d->m_batch = batch;
00594 }
00595 
00596 bool KoFilterManager::getBatchMode( void ) const
00597 {
00598     return d->m_batch;
00599 }
00600 
00601 #include <KoFilterManager.moc>
00602 #include <KoFilterManager_p.moc>
KDE Home | KDE Accessibility Home | Description of Access Keys