Commit d6e70109 authored by Pino Toscano's avatar Pino Toscano

Refactor a bit the way we load the generator libraries: hide the hash with the...

Refactor a bit the way we load the generator libraries: hide the hash with the Generator completely into the Document, so the Document have the complete control over them.
Add fillConfigDialog() and supportedMimeTypes() to the Document, so the Part can get all the info it needs with no need to own the generator structure.
This also loads all the generators when asking for their config widget, but that can be improved easily now; furthermore, all the generators used to load documents are kept.

svn path=/trunk/playground/graphics/okular/; revision=627909
parent 1b172366
......@@ -12,6 +12,7 @@
#include <QtCore/QtAlgorithms>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QHash>
#include <QtCore/QMap>
#include <QtCore/QProcess>
#include <QtCore/QTextStream>
......@@ -27,6 +28,7 @@
#include <kmimetype.h>
#include <kmimetypetrader.h>
#include <krun.h>
#include <kservicetypetrader.h>
#include <kstandarddirs.h>
#include <ktemporaryfile.h>
#include <ktoolinvocation.h>
......@@ -73,6 +75,15 @@ struct RunningSearch
QColor cachedColor;
};
struct GeneratorInfo
{
GeneratorInfo()
: generator( 0 )
{}
Generator * generator;
};
#define foreachObserver( cmd ) {\
QMap< int, DocumentObserver * >::const_iterator it=d->m_observers.begin(), end=d->m_observers.end();\
for ( ; it != end ; ++ it ) { (*it)-> cmd ; } }
......@@ -82,7 +93,7 @@ struct RunningSearch
class Document::Private
{
public:
Private( Document *parent, QHash<QString, Generator*> * generators )
Private( Document *parent )
: m_parent( parent ),
m_lastSearchID( -1 ),
m_tempFile( 0 ),
......@@ -92,9 +103,8 @@ class Document::Private
m_bookmarkManager( 0 ),
m_memCheckTimer( 0 ),
m_saveBookmarksTimer( 0 ),
m_loadedGenerators ( generators ),
m_generator( 0 ),
m_usingCachedGenerator( false )
m_generatorsLoaded( false )
{
}
......@@ -107,6 +117,8 @@ class Document::Private
void loadDocumentInfo();
QString giveAbsolutePath( const QString & fileName );
bool openRelativeFile( const QString & fileName );
Generator * loadGeneratorLibrary( const QString& name, const QString& libname );
void loadAllGeneratorLibraries();
// private slots
void saveDocumentInfo() const;
......@@ -157,11 +169,14 @@ class Document::Private
QTimer *m_memCheckTimer;
QTimer *m_saveBookmarksTimer;
QHash<QString, Generator*>* m_loadedGenerators ;
QHash<QString, GeneratorInfo> m_loadedGenerators;
Generator * m_generator;
bool m_usingCachedGenerator;
bool m_generatorsLoaded;
QVector< Page * > m_pagesVector;
QVector< VisiblePageRect * > m_pageRects;
// cache of the mimetype we support
QStringList m_supportedMimeTypes;
};
QString Document::Private::pagesSizeString() const
......@@ -439,6 +454,54 @@ bool Document::Private::openRelativeFile( const QString & fileName )
return true;
}
Generator * Document::Private::loadGeneratorLibrary( const QString& name, const QString& libname )
{
KLibrary *lib = KLibLoader::self()->globalLibrary( QFile::encodeName( libname ) );
if ( !lib )
{
kWarning() << "Could not load '" << libname << "' library." << endl;
return 0;
}
Generator* (*create_plugin)() = ( Generator* (*)() ) lib->symbol( "create_plugin" );
Generator * generator = create_plugin();
if ( !generator )
{
kWarning() << "Broken generator " << libname << "!" << endl;
return 0;
}
GeneratorInfo info;
info.generator = generator;
m_loadedGenerators[ name ] = info;
return generator;
}
void Document::Private::loadAllGeneratorLibraries()
{
if ( m_generatorsLoaded )
return;
m_generatorsLoaded = true;
QString constraint("([X-KDE-Priority] > 0) and (exist Library)") ;
KService::List offers = KServiceTypeTrader::self()->query( "okular/Generator", constraint );
int count = offers.count();
if ( count <= 0 )
return;
for ( int i = 0; i < count; ++i )
{
QString propName = offers.at(i)->name();
// don't load already loaded generators
QHash< QString, GeneratorInfo >::iterator genIt = m_loadedGenerators.find( propName );
if ( genIt != m_loadedGenerators.end() )
continue;
Generator * g = loadGeneratorLibrary( propName, offers.at(i)->library() );
(void)g;
}
}
void Document::Private::saveDocumentInfo() const
{
if ( m_docFileName.isEmpty() )
......@@ -571,8 +634,8 @@ void Document::Private::rotationFinished( int page )
}
Document::Document( QHash<QString, Generator*> * generators )
: d( new Private( this, generators ) )
Document::Document()
: d( new Private( this ) )
{
d->m_bookmarkManager = new BookmarkManager( this );
}
......@@ -582,6 +645,12 @@ Document::~Document()
// delete generator, pages, and related stuff
closeDocument();
// delete the loaded generators
QHash< QString, GeneratorInfo >::iterator it = d->m_loadedGenerators.begin(), itEnd = d->m_loadedGenerators.end();
for ( ; it != itEnd; ++it )
delete it.value().generator;
d->m_loadedGenerators.clear();
// delete the private structure
delete d;
}
......@@ -637,70 +706,44 @@ bool Document::openDocument( const QString & docFile, const KUrl& url, const KMi
return false;
}
int hRank=0;
// order the offers: the offers with an higher priority come before
qStableSort( offers.begin(), offers.end(), kserviceMoreThan );
// best ranked offer search
if (offers.count() > 1 && Settings::chooseGenerators() )
int offercount = offers.count();
if ( offercount > 1 )
{
QStringList list;
int count=offers.count();
for (int i=0;i<count;++i)
{
list << offers.at(i)->name();
}
ChooseEngineDialog choose( list, mime, 0 );
// sort the offers: the offers with an higher priority come before
qStableSort( offers.begin(), offers.end(), kserviceMoreThan );
int retval = choose.exec();
int index = choose.selectedGenerator();
switch( retval )
if ( Settings::chooseGenerators() )
{
case QDialog::Accepted:
hRank=index;
break;
case QDialog::Rejected:
QStringList list;
for ( int i = 0; i < offercount; ++i )
{
list << offers.at(i)->name();
}
ChooseEngineDialog choose( list, mime, 0 );
if ( choose.exec() == QDialog::Rejected )
return false;
break;
hRank = choose.selectedGenerator();
}
}
QString propName = offers.at(hRank)->name();
d->m_usingCachedGenerator=false;
d->m_generator = d->m_loadedGenerators->take(propName);
if (!d->m_generator)
QHash< QString, GeneratorInfo >::iterator genIt = d->m_loadedGenerators.find( propName );
if ( genIt != d->m_loadedGenerators.end() )
{
KLibLoader *loader = KLibLoader::self();
if (!loader)
{
kWarning() << "Could not start library loader: '" << loader->lastErrorMessage() << "'." << endl;
return false;
}
KLibrary *lib = loader->globalLibrary( QFile::encodeName( offers.at(hRank)->library() ) );
if (!lib)
{
kWarning() << "Could not load '" << offers.at(hRank)->library() << "' library." << endl;
return false;
}
Generator* (*create_plugin)() = ( Generator* (*)() ) lib->symbol( "create_plugin" );
d->m_generator = create_plugin();
if ( !d->m_generator )
{
kWarning() << "Sth broke." << endl;
return false;
}
if ( offers.at(hRank)->property( "X-KDE-okularHasInternalSettings" ).toBool() )
{
d->m_loadedGenerators->insert(propName, d->m_generator);
d->m_usingCachedGenerator=true;
}
// end
d->m_generator = genIt.value().generator;
}
else
{
d->m_usingCachedGenerator=true;
d->m_generator = d->loadGeneratorLibrary( propName, offers.at(hRank)->library() );
if ( !d->m_generator )
return false;
}
Q_ASSERT_X( d->m_generator, "Document::load()", "null generator?!" );
d->m_generator->setDocument( this );
// connect error reporting signals
......@@ -746,10 +789,6 @@ bool Document::openDocument( const QString & docFile, const KUrl& url, const KMi
QApplication::restoreOverrideCursor();
if ( !openOk || d->m_pagesVector.size() <= 0 )
{
if (!d->m_usingCachedGenerator)
{
delete d->m_generator;
}
d->m_generator = 0;
return openOk;
}
......@@ -840,11 +879,10 @@ void Document::closeDocument()
Okular::GuiInterface * iface = qobject_cast< Okular::GuiInterface * >( d->m_generator );
if ( iface )
iface->freeGui();
}
if (!d->m_usingCachedGenerator)
{
// delete contents generator
delete d->m_generator;
// disconnect the generator from this document ...
d->m_generator->setDocument( 0 );
// .. and this document from the generator signals
disconnect( d->m_generator, 0, this, 0 );
}
d->m_generator = 0;
d->m_url = KUrl();
......@@ -2045,6 +2083,44 @@ KPrintDialogPage* Document::printConfigurationWidget() const
return 0;
}
void Document::fillConfigDialog( KConfigDialog * dialog )
{
if ( !dialog )
return;
// ensure that we have all the generators loaded
d->loadAllGeneratorLibraries();
QHash< QString, GeneratorInfo >::iterator it = d->m_loadedGenerators.begin();
QHash< QString, GeneratorInfo >::iterator itEnd = d->m_loadedGenerators.end();
for ( ; it != itEnd; ++it )
{
Okular::ConfigInterface * iface = qobject_cast< Okular::ConfigInterface * >( it.value().generator );
if ( iface )
iface->addPages( dialog );
}
}
QStringList Document::supportedMimeTypes() const
{
if ( !d->m_supportedMimeTypes.isEmpty() )
return d->m_supportedMimeTypes;
QString constraint( "([X-KDE-Priority] > 0) and (exist Library)" );
KService::List offers = KServiceTypeTrader::self()->query( "okular/Generator", constraint );
KService::List::ConstIterator it = offers.begin(), itEnd = offers.end();
for ( ; it != itEnd; ++it )
{
KService::Ptr service = *it;
QStringList mimeTypes = service->serviceTypes();
foreach ( const QString& mimeType, mimeTypes )
if ( !mimeType.contains( "okular" ) )
d->m_supportedMimeTypes.append( mimeType );
}
return d->m_supportedMimeTypes;
}
void Document::requestDone( PixmapRequest * req )
{
#ifndef NDEBUG
......
......@@ -16,7 +16,6 @@
#include <okular/core/global.h>
#include <okular/core/pagesize.h>
#include <QtCore/QHash>
#include <QtCore/QObject>
#include <QtCore/QStringList>
#include <QtCore/QVector>
......@@ -26,6 +25,7 @@
#include <kmimetype.h>
class KBookmark;
class KConfigDialog;
class KPrinter;
class KPrintDialogPage;
class KUrl;
......@@ -81,7 +81,7 @@ class OKULAR_EXPORT Document : public QObject
/**
* Creates a new document with the given list of @p generators.
*/
Document( QHash<QString, Generator*> *generators );
Document();
/**
* Destroys the document.
......@@ -439,6 +439,17 @@ class OKULAR_EXPORT Document : public QObject
*/
KPrintDialogPage* printConfigurationWidget() const;
/**
* Fill the KConfigDialog @p dialog with the setting pages of the
* generators.
*/
void fillConfigDialog( KConfigDialog * dialog );
/**
* Returns the list wih the supported MIME types.
*/
QStringList supportedMimeTypes() const;
/**
* This method is used by the generators to signal the finish of
* the pixmap generation @p request.
......
......@@ -38,7 +38,6 @@
#include <kfiledialog.h>
#include <kfind.h>
#include <kmessagebox.h>
#include <kmimetypetrader.h>
#include <kfinddialog.h>
#include <knuminput.h>
#include <kio/netaccess.h>
......@@ -103,7 +102,7 @@ m_searchStarted(false), m_cliPresentation(false)
setInstance(okularPartFactory::instance());
// build the document
m_document = new Okular::Document(&m_loadedGenerators);
m_document = new Okular::Document();
connect( m_document, SIGNAL( linkFind() ), this, SLOT( slotFind() ) );
connect( m_document, SIGNAL( linkGoToPage() ), this, SLOT( slotGoToPage() ) );
connect( m_document, SIGNAL( linkPresentation() ), this, SLOT( slotShowPresentation() ) );
......@@ -424,10 +423,6 @@ Part::~Part()
delete m_pageSizeLabel;
delete m_document;
QHash<QString, Okular::Generator*>::iterator it = m_loadedGenerators.begin(), itEnd = m_loadedGenerators.end();
for ( ; it != itEnd; ++it )
delete *it;
delete m_tempfile;
......@@ -473,34 +468,12 @@ void Part::openUrlFromBookmarks(const KUrl &_url)
openUrl( url );
}
void Part::supportedMimetypes()
{
m_supportedMimeTypes.clear();
QString constraint("([X-KDE-Priority] > 0) and (exist Library) ") ;
KService::List offers = KServiceTypeTrader::self()->query("okular/Generator",constraint);
KService::List::ConstIterator iterator = offers.begin();
KService::List::ConstIterator end = offers.end();
QStringList::ConstIterator mimeType;
for (; iterator != end; ++iterator)
{
KService::Ptr service = *iterator;
QStringList mimeTypes = service->serviceTypes();
for (mimeType=mimeTypes.begin();mimeType!=mimeTypes.end();++mimeType)
if (! (*mimeType).contains("okular"))
m_supportedMimeTypes << *mimeType;
}
}
void Part::setMimeTypes(KIO::Job *job)
{
if (job)
{
if (m_supportedMimeTypes.count() <= 0)
supportedMimetypes();
job->addMetaData("accept", m_supportedMimeTypes.join(", ") + ", */*;q=0.5");
QStringList supportedMimeTypes = m_document->supportedMimeTypes();
job->addMetaData("accept", supportedMimeTypes.join(", ") + ", */*;q=0.5");
connect(job, SIGNAL(mimetype(KIO::Job*,const QString&)), this, SLOT(readMimeType(KIO::Job*,const QString&)));
}
}
......@@ -510,54 +483,8 @@ void Part::readMimeType(KIO::Job *, const QString &mime)
m_jobMime = mime;
}
void Part::fillGenerators()
{
QString constraint("([X-KDE-Priority] > 0) and (exist Library) and ([X-KDE-okularHasInternalSettings])") ;
KService::List offers = KServiceTypeTrader::self()->query("okular/Generator", constraint);
QString propName;
int count=offers.count();
if (count > 0)
{
KLibLoader *loader = KLibLoader::self();
if (!loader)
{
kWarning() << "Could not start library loader: '" << loader->lastErrorMessage() << "'." << endl;
return;
}
for (int i=0;i<count;i++)
{
propName=offers[i]->property("Name").toString();
// don't load already loaded generators
if (! m_loadedGenerators.take( propName ) )
{
KLibrary *lib = loader->globalLibrary( QFile::encodeName( offers[i]->library() ) );
if (!lib)
{
kWarning() << "Could not load '" << offers[i]->library() << "' library." << endl;
continue;
}
Okular::Generator* (*create_plugin)() = ( Okular::Generator* (*)() ) lib->symbol( "create_plugin" );
if ( !create_plugin )
{
kWarning() << "Library '" << offers.at(i)->library() << "' has no symbol 'create_plugin'." << endl;
continue;
}
// the generator should do anything with the document if we are only configuring
m_loadedGenerators.insert(propName,create_plugin());
m_generatorsWithSettings << propName;
}
}
}
}
void Part::slotGeneratorPreferences( )
{
fillGenerators();
//Generator* gen= m_loadedGenerators[m_generatorsWithSettings[number]];
// an instance the dialog could be already created and could be cached,
// in which case you want to display the cached dialog
if ( KConfigDialog::showDialog( "generator_prefs" ) )
......@@ -567,14 +494,7 @@ void Part::slotGeneratorPreferences( )
KConfigDialog * dialog = new KConfigDialog( m_pageView, "generator_prefs", Okular::Settings::self() );
dialog->setCaption( i18n( "Configure Backends" ) );
QHashIterator<QString, Okular::Generator*> it(m_loadedGenerators);
while(it.hasNext())
{
it.next();
Okular::ConfigInterface * iface = qobject_cast< Okular::ConfigInterface * >( it.value() );
if ( iface )
iface->addPages( dialog );
}
m_document->fillConfigDialog( dialog );
// (for now don't FIXME) keep us informed when the user changes settings
// connect( dialog, SIGNAL( settingsChanged() ), this, SLOT( slotNewConfig() ) );
......
......@@ -113,7 +113,6 @@ class Part : public KParts::ReadOnlyPart, public Okular::DocumentObserver, publi
bool openFile();
bool openUrl(const KUrl &url);
bool closeUrl();
void supportedMimetypes();
protected slots:
// connected to actions
......@@ -157,7 +156,6 @@ class Part : public KParts::ReadOnlyPart, public Okular::DocumentObserver, publi
private:
void doPrint( KPrinter& printer );
void fillGenerators();
bool handleCompressed(KUrl & url, const QString &path, const KMimeType::Ptr mimetype);
void rebuildBookmarkMenu( bool unplugActions = true );
KTemporaryFile *m_tempfile;
......@@ -220,11 +218,6 @@ class Part : public KParts::ReadOnlyPart, public Okular::DocumentObserver, publi
bool m_searchStarted;
BrowserExtension *m_bExtension;
// QHash: key is the name of the generator
QHash<QString, Okular::Generator*> m_loadedGenerators;
// list of names of the generators that have settings
QStringList m_generatorsWithSettings;
QStringList m_supportedMimeTypes;
KSelectAction * m_confGens;
QList<Okular::ExportFormat> m_exportFormats;
QList<QAction*> m_bookmarkActions;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment