00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include <koFilterManager.h>
00023
#include <koFilterManager_p.h>
00024
00025
#include <qfile.h>
00026
#include <qlabel.h>
00027
#include <qlayout.h>
00028
#include <qptrlist.h>
00029
#include <qapplication.h>
00030
00031
#include <klocale.h>
00032
#include <kmessagebox.h>
00033
#include <koDocument.h>
00034
#include <klibloader.h>
00035
#include <klistbox.h>
00036
#include <kmimetype.h>
00037
#include <kdebug.h>
00038
00039
#include <queue>
00040
00041
#include <unistd.h>
00042
00043
00044 KoFilterChooser::KoFilterChooser (
QWidget *parent,
const QStringList &mimeTypes,
const QString &nativeFormat)
00045 : KDialogBase (parent, "kofilterchooser", true, i18n ("Choose Filter"),
00046 KDialogBase::Ok | KDialogBase::Cancel, KDialogBase::Ok, true),
00047 m_mimeTypes (mimeTypes)
00048 {
00049 setInitialSize (
QSize (300, 350));
00050
00051
QWidget *page =
new QWidget (
this);
00052 setMainWidget (page);
00053
00054
00055
QVBoxLayout *layout =
new QVBoxLayout (page, marginHint (), spacingHint () * 2);
00056
00057
QLabel *filterLabel =
new QLabel (i18n (
"Select a filter:"), page,
"filterlabel");
00058 layout->addWidget (filterLabel);
00059
00060 m_filterList =
new KListBox (page,
"filterlist");
00061 layout->addWidget (m_filterList);
00062
00063 Q_ASSERT (!m_mimeTypes.isEmpty ());
00064
for (QStringList::ConstIterator it = m_mimeTypes.begin ();
00065 it != m_mimeTypes.end ();
00066 it++)
00067 {
00068 KMimeType::Ptr mime = KMimeType::mimeType (*it);
00069 m_filterList->insertItem (mime->comment ());
00070 }
00071
00072
if (nativeFormat ==
"application/x-kword")
00073 {
00074
const int index = m_mimeTypes.findIndex (
"text/plain");
00075
if (index > -1)
00076 m_filterList->setCurrentItem (index);
00077 }
00078
00079
if (m_filterList->currentItem () == -1)
00080 m_filterList->setCurrentItem (0);
00081
00082 m_filterList->centerCurrentItem ();
00083 m_filterList->setFocus ();
00084
00085 connect (m_filterList, SIGNAL (selected (
int)),
this, SLOT (slotOk ()));
00086 }
00087
00088 KoFilterChooser::~KoFilterChooser ()
00089 {
00090 }
00091
00092
QString KoFilterChooser::filterSelected ()
00093 {
00094
const int item = m_filterList->currentItem ();
00095
00096
if (item > -1)
00097
return m_mimeTypes [item];
00098
else
00099
return QString::null;
00100 }
00101
00102
00103
00104
QMap<QString, bool> KoFilterManager::m_filterAvailable;
00105
00106
const int KoFilterManager::s_area = 30500;
00107
00108
00109 KoFilterManager::KoFilterManager(
KoDocument* document ) :
00110 m_document( document ), m_parentChain( 0 ), m_graph( "" ), d( 0 )
00111 {
00112
if ( document )
00113 QObject::connect(
this, SIGNAL( sigProgress(
int ) ),
00114 document, SIGNAL( sigProgress(
int ) ) );
00115 }
00116
00117
00118 KoFilterManager::KoFilterManager(
const QString& url,
const QCString& mimetypeHint,
00119
KoFilterChain*
const parentChain ) :
00120 m_document( 0 ), m_parentChain( parentChain ), m_importUrl( url ), m_importUrlMimetypeHint( mimetypeHint ),
00121 m_graph( "" ), d( 0 )
00122 {
00123 }
00124
00125 KoFilterManager::~KoFilterManager()
00126 {
00127 }
00128
00129 QString KoFilterManager::import(
const QString& url, KoFilter::ConversionStatus& status )
00130 {
00131
00132 KURL u;
00133 u.setPath( url );
00134 KMimeType::Ptr t = KMimeType::findByURL( u, 0,
true );
00135
if ( t->name() == KMimeType::defaultMimeType() ) {
00136 kdError(s_area) <<
"No mimetype found for " << url << endl;
00137 status = KoFilter::BadMimeType;
00138
return QString::null;
00139 }
00140
00141 m_graph.setSourceMimeType( t->name().latin1() );
00142
if ( !m_graph.isValid() ) {
00143
bool userCancelled =
false;
00144
00145 kdWarning(s_area) <<
"Can't open " << t->name () <<
", trying filter chooser" << endl;
00146
if ( m_document )
00147 {
00148
if ( !m_document->
isAutoErrorHandlingEnabled() )
00149 {
00150 status = KoFilter::BadConversionGraph;
00151
return QString::null;
00152 }
00153
QCString nativeFormat = m_document->
nativeFormatMimeType ();
00154
00155 QApplication::setOverrideCursor( arrowCursor );
00156 KoFilterChooser chooser(0,
00157
KoFilterManager::mimeFilter (nativeFormat, KoFilterManager::Import),
00158 nativeFormat);
00159
if (chooser.exec ())
00160 {
00161
QCString f = chooser.filterSelected ().latin1();
00162
00163
if (f == nativeFormat)
00164 {
00165 status = KoFilter::OK;
00166 QApplication::restoreOverrideCursor();
00167
return url;
00168 }
00169
00170 m_graph.setSourceMimeType (f);
00171 }
00172
else
00173 userCancelled =
true;
00174 QApplication::restoreOverrideCursor();
00175 }
00176
00177
if (!m_graph.isValid())
00178 {
00179 kdError(s_area) <<
"Couldn't create a valid graph for this source mimetype: "
00180 << t->name() << endl;
00181 importErrorHelper( t->name(), userCancelled );
00182 status = KoFilter::BadConversionGraph;
00183
return QString::null;
00184 }
00185 }
00186
00187 KoFilterChain::Ptr chain( 0 );
00188
00189
if ( m_document ) {
00190
QCString mimeType( m_document->
nativeFormatMimeType() );
00191 chain = m_graph.chain(
this, mimeType );
00192 }
00193
else {
00194 kdError(s_area) <<
"You aren't supposed to use import() from a filter!" << endl;
00195 status = KoFilter::UsageError;
00196
return QString::null;
00197 }
00198
00199
if ( !chain ) {
00200 kdError(s_area) <<
"Couldn't create a valid filter chain!" << endl;
00201 importErrorHelper( t->name() );
00202 status = KoFilter::BadConversionGraph;
00203
return QString::null;
00204 }
00205
00206
00207 m_direction = Import;
00208 m_importUrl = url;
00209 m_exportUrl = QString::null;
00210
00211 status = chain->invokeChain();
00212
00213 m_importUrl = QString::null;
00214
00215
if ( status == KoFilter::OK )
00216
return chain->chainOutput();
00217
return QString::null;
00218 }
00219
00220 KoFilter::ConversionStatus
KoFilterManager::exp0rt(
const QString& url,
QCString& mimeType )
00221 {
00222
bool userCancelled =
false;
00223
00224
00225
00226 m_direction = Export;
00227 m_exportUrl = url;
00228
00229
if ( m_document )
00230 m_graph.setSourceMimeType( m_document->
nativeFormatMimeType() );
00231
else if ( !m_importUrlMimetypeHint.isEmpty() ) {
00232 kdDebug(s_area) <<
"Using the mimetype hint: '" << m_importUrlMimetypeHint <<
"'" << endl;
00233 m_graph.setSourceMimeType( m_importUrlMimetypeHint );
00234 }
00235
else {
00236 KURL u;
00237 u.setPath( m_importUrl );
00238 KMimeType::Ptr t = KMimeType::findByURL( u, 0,
true );
00239
if ( t->name() == KMimeType::defaultMimeType() ) {
00240 kdError(s_area) <<
"No mimetype found for " << m_importUrl << endl;
00241
return KoFilter::BadMimeType;
00242 }
00243 m_graph.setSourceMimeType( t->name().latin1() );
00244
00245
if ( !m_graph.isValid() ) {
00246 kdWarning(s_area) <<
"Can't open " << t->name () <<
", trying filter chooser" << endl;
00247
00248 QApplication::setOverrideCursor( arrowCursor );
00249 KoFilterChooser chooser(0,
KoFilterManager::mimeFilter ());
00250
if (chooser.exec ())
00251 m_graph.setSourceMimeType (chooser.filterSelected ().latin1 ());
00252
else
00253 userCancelled =
true;
00254
00255 QApplication::restoreOverrideCursor();
00256 }
00257 }
00258
00259
if (!m_graph.isValid ())
00260 {
00261 kdError(s_area) <<
"Couldn't create a valid graph for this source mimetype." << endl;
00262
if (!userCancelled) KMessageBox::error( 0L, i18n(
"Could not export file."), i18n(
"Missing Export Filter") );
00263
return KoFilter::BadConversionGraph;
00264 }
00265
00266 KoFilterChain::Ptr chain = m_graph.chain(
this, mimeType );
00267
00268
if ( !chain ) {
00269 kdError(s_area) <<
"Couldn't create a valid filter chain!" << endl;
00270 KMessageBox::error( 0L, i18n(
"Could not export file."), i18n(
"Missing Export Filter") );
00271
return KoFilter::BadConversionGraph;
00272 }
00273
00274
return chain->invokeChain();
00275 }
00276
00277
namespace
00278 {
00279
00280
class Vertex
00281 {
00282
public:
00283 Vertex(
const QCString& mimeType ) : m_color( White ), m_mimeType( mimeType ) {}
00284
00285
enum Color { White, Gray, Black };
00286 Color color()
const {
return m_color; }
00287
void setColor( Color color ) { m_color = color; }
00288
00289
QCString mimeType()
const {
return m_mimeType; }
00290
00291
void addEdge( Vertex* vertex ) {
if ( vertex ) m_edges.append( vertex ); }
00292
QPtrList<Vertex> edges()
const {
return m_edges; }
00293
00294
private:
00295 Color m_color;
00296
QCString m_mimeType;
00297
QPtrList<Vertex> m_edges;
00298 };
00299
00300
00301
00302
void buildGraph(
QAsciiDict<Vertex>& vertices, KoFilterManager::Direction direction )
00303 {
00304 vertices.setAutoDelete(
true );
00305
00306
00307
00308
QValueList<KoDocumentEntry> parts( KoDocumentEntry::query(
false, QString::null) );
00309
QValueList<KoDocumentEntry>::ConstIterator partIt( parts.begin() );
00310
QValueList<KoDocumentEntry>::ConstIterator partEnd( parts.end() );
00311
00312
while ( partIt != partEnd ) {
00313
QCString key( ( *partIt ).service()->property(
"X-KDE-NativeMimeType" ).toString().latin1() );
00314
if ( !key.isEmpty() )
00315 vertices.insert( key,
new Vertex( key ) );
00316 ++partIt;
00317 }
00318
00319
QValueList<KoFilterEntry::Ptr> filters =
KoFilterEntry::query();
00320
QValueList<KoFilterEntry::Ptr>::ConstIterator it = filters.begin();
00321
QValueList<KoFilterEntry::Ptr>::ConstIterator end = filters.end();
00322
00323
for ( ; it != end; ++it ) {
00324
00325 QStringList::ConstIterator importIt = ( *it )->import.begin();
00326 QStringList::ConstIterator importEnd = ( *it )->import.end();
00327
for ( ; importIt != importEnd; ++importIt ) {
00328
QCString key = ( *importIt ).latin1();
00329
00330
if ( !vertices[ key ] )
00331 vertices.insert( key,
new Vertex( key ) );
00332 }
00333
00334
00335
if (
KoFilterManager::filterAvailable( *it ) ) {
00336 QStringList::ConstIterator exportIt = ( *it )->export_.begin();
00337 QStringList::ConstIterator exportEnd = ( *it )->export_.end();
00338
00339
for ( ; exportIt != exportEnd; ++exportIt ) {
00340
00341
QCString key = ( *exportIt ).latin1();
00342 Vertex* exp = vertices[ key ];
00343
if ( !exp ) {
00344 exp =
new Vertex( key );
00345 vertices.insert( key, exp );
00346 }
00347
00348
00349
00350
00351 importIt = ( *it )->import.begin();
00352
if ( direction == KoFilterManager::Import ) {
00353
for ( ; importIt != importEnd; ++importIt )
00354 exp->addEdge( vertices[ ( *importIt ).latin1() ] );
00355 }
else {
00356
for ( ; importIt != importEnd; ++importIt )
00357 vertices[ ( *importIt ).latin1() ]->addEdge( exp );
00358 }
00359 }
00360 }
00361
else
00362 kdDebug( 30500 ) <<
"Filter: " << ( *it )->service()->name() <<
" doesn't apply." << endl;
00363 }
00364 }
00365
00366
00367
00368
00369
QStringList connected(
const QAsciiDict<Vertex>& vertices,
const QCString& mimetype )
00370 {
00371
if ( mimetype.isEmpty() )
00372
return QStringList();
00373 Vertex *v = vertices[ mimetype ];
00374
if ( !v )
00375
return QStringList();
00376
00377 v->setColor( Vertex::Gray );
00378 std::queue<Vertex*> queue;
00379 queue.push( v );
00380
QStringList connected;
00381
00382
while ( !queue.empty() ) {
00383 v = queue.front();
00384 queue.pop();
00385
QPtrList<Vertex> edges = v->edges();
00386
QPtrListIterator<Vertex> it( edges );
00387
for ( ; it.current(); ++it ) {
00388
if ( it.current()->color() == Vertex::White ) {
00389 it.current()->setColor( Vertex::Gray );
00390 queue.push( it.current() );
00391 }
00392 }
00393 v->setColor( Vertex::Black );
00394 connected.append( v->mimeType() );
00395 }
00396
return connected;
00397 }
00398 }
00399
00400
00401
00402 QStringList KoFilterManager::mimeFilter(
const QCString& mimetype, Direction direction )
00403 {
00404
QAsciiDict<Vertex> vertices;
00405 buildGraph( vertices, direction );
00406
return connected( vertices, mimetype );
00407 }
00408
00409 QStringList KoFilterManager::mimeFilter()
00410 {
00411
QAsciiDict<Vertex> vertices;
00412 buildGraph( vertices, KoFilterManager::Import );
00413
00414
QValueList<KoDocumentEntry> parts( KoDocumentEntry::query(
false, QString::null) );
00415
QValueList<KoDocumentEntry>::ConstIterator partIt( parts.begin() );
00416
QValueList<KoDocumentEntry>::ConstIterator partEnd( parts.end() );
00417
00418
if ( partIt == partEnd )
00419
return QStringList();
00420
00421
00422
00423
00424
00425
00426 Vertex *v =
new Vertex(
"supercalifragilistic/x-pialadocious" );
00427 vertices.insert(
"supercalifragilistic/x-pialadocious", v );
00428
while ( partIt != partEnd ) {
00429
QCString key( ( *partIt ).service()->property(
"X-KDE-NativeMimeType" ).toString().latin1() );
00430
if ( !key.isEmpty() )
00431 v->addEdge( vertices[ key ] );
00432 ++partIt;
00433 }
00434
QStringList result = connected( vertices,
"supercalifragilistic/x-pialadocious" );
00435
00436
00437 result.remove(
"supercalifragilistic/x-pialadocious" );
00438
return result;
00439 }
00440
00441
00442
00443 bool KoFilterManager::filterAvailable( KoFilterEntry::Ptr entry )
00444 {
00445
if ( !entry )
00446
return false;
00447
if ( entry->available !=
"check" )
00448
return true;
00449
00450
00451
00452
QString key( entry->service()->name() );
00453 key +=
" - ";
00454 key += entry->service()->library();
00455
00456
if ( !m_filterAvailable.contains( key ) ) {
00457
00458
00459 KLibrary* library = KLibLoader::self()->library( QFile::encodeName( entry->service()->library() ) );
00460
if ( !library ) {
00461 kdWarning( 30500 ) <<
"Huh?? Couldn't load the lib: "
00462 << KLibLoader::self()->lastErrorMessage() << endl;
00463 m_filterAvailable[ key ] =
false;
00464
return false;
00465 }
00466
00467
00468
QCString symname;
00469 symname.sprintf(
"check_%s", library->name().latin1() );
00470
void* sym = library->symbol( symname );
00471
if ( !sym )
00472 {
00473 kdWarning( 30500 ) <<
"The library " << library->name()
00474 <<
" does not offer a check_" << library->name()
00475 <<
" function." << endl;
00476 m_filterAvailable[ key ] =
false;
00477 }
00478
else {
00479
typedef int (*t_func)();
00480 t_func check = (t_func)sym;
00481 m_filterAvailable[ key ] = check() == 1;
00482 }
00483 }
00484
return m_filterAvailable[ key ];
00485 }
00486
00487
void KoFilterManager::importErrorHelper(
const QString& mimeType,
const bool suppressDialog )
00488 {
00489
QString tmp = i18n(
"Could not import file of type\n%1").arg( mimeType );
00490
00491
if (!suppressDialog) KMessageBox::error( 0L, tmp, i18n(
"Missing Import Filter") );
00492 }
00493
00494
#include <koFilterManager.moc>
00495
#include <koFilterManager_p.moc>