Logo Search packages:      
Sourcecode: kdegraphics-kde4 version File versions  Download package

generator.cpp

/***************************************************************************
 *   Copyright (C) 2005   by Piotr Szymanski <niedakh@gmail.com>           *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/

#include "generator.h"
#include "generator_p.h"

#include <qeventloop.h>
#include <QtGui/QPrinter>

#include <kdebug.h>
#include <kicon.h>
#include <klocale.h>

#include "document.h"
#include "document_p.h"
#include "page.h"
#include "textpage.h"

using namespace Okular;

GeneratorPrivate::GeneratorPrivate()
    : m_document( 0 ),
      mPixmapGenerationThread( 0 ), mTextPageGenerationThread( 0 ),
      m_mutex( 0 ), m_threadsMutex( 0 ), mPixmapReady( true ), mTextPageReady( true ),
      m_closing( false ), m_closingLoop( 0 )
{
}

GeneratorPrivate::~GeneratorPrivate()
{
    if ( mPixmapGenerationThread )
        mPixmapGenerationThread->wait();

    delete mPixmapGenerationThread;

    if ( mTextPageGenerationThread )
        mTextPageGenerationThread->wait();

    delete mTextPageGenerationThread;

    delete m_mutex;
    delete m_threadsMutex;
}

PixmapGenerationThread* GeneratorPrivate::pixmapGenerationThread()
{
    if ( mPixmapGenerationThread )
        return mPixmapGenerationThread;

    Q_Q( Generator );
    mPixmapGenerationThread = new PixmapGenerationThread( q );
    QObject::connect( mPixmapGenerationThread, SIGNAL( finished() ),
                      q, SLOT( pixmapGenerationFinished() ),
                      Qt::QueuedConnection );

    return mPixmapGenerationThread;
}

TextPageGenerationThread* GeneratorPrivate::textPageGenerationThread()
{
    if ( mTextPageGenerationThread )
        return mTextPageGenerationThread;

    Q_Q( Generator );
    mTextPageGenerationThread = new TextPageGenerationThread( q );
    QObject::connect( mTextPageGenerationThread, SIGNAL( finished() ),
                      q, SLOT( textpageGenerationFinished() ),
                      Qt::QueuedConnection );

    return mTextPageGenerationThread;
}

void GeneratorPrivate::pixmapGenerationFinished()
{
    Q_Q( Generator );
    PixmapRequest *request = mPixmapGenerationThread->request();
    mPixmapGenerationThread->endGeneration();

    QMutexLocker locker( threadsLock() );
    mPixmapReady = true;

    if ( m_closing )
    {
        delete request;
        if ( mTextPageReady )
        {
            locker.unlock();
            m_closingLoop->quit();
        }
        return;
    }

    request->page()->setPixmap( request->id(), new QPixmap( QPixmap::fromImage( mPixmapGenerationThread->image() ) ) );

    q->signalPixmapRequestDone( request );
}

void GeneratorPrivate::textpageGenerationFinished()
{
    Page *page = mTextPageGenerationThread->page();
    mTextPageGenerationThread->endGeneration();

    QMutexLocker locker( threadsLock() );
    mTextPageReady = true;

    if ( m_closing )
    {
        delete mTextPageGenerationThread->textPage();
        if ( mPixmapReady )
        {
            locker.unlock();
            m_closingLoop->quit();
        }
        return;
    }

    if ( mTextPageGenerationThread->textPage() )
        page->setTextPage( mTextPageGenerationThread->textPage() );
}

QMutex* GeneratorPrivate::threadsLock()
{
    if ( !m_threadsMutex )
        m_threadsMutex = new QMutex();
    return m_threadsMutex;
}


00135 Generator::Generator( QObject *parent, const QVariantList &args )
    : QObject( parent ), d_ptr( new GeneratorPrivate() )
{
    d_ptr->q_ptr = this;
    Q_UNUSED( args )
}

Generator::Generator( GeneratorPrivate &dd, QObject *parent, const QVariantList &args )
    : QObject( parent ), d_ptr( &dd )
{
    d_ptr->q_ptr = this;
    Q_UNUSED( args )
}

00149 Generator::~Generator()
{
    delete d_ptr;
}

00154 bool Generator::loadDocumentFromData( const QByteArray &, QVector< Page * > & )
{
    return false;
}

00159 bool Generator::closeDocument()
{
    Q_D( Generator );

    d->m_closing = true;

    d->threadsLock()->lock();
    if ( !( d->mPixmapReady && d->mTextPageReady ) )
    {
        QEventLoop loop;
        d->m_closingLoop = &loop;

        d->threadsLock()->unlock();

        loop.exec();

        d->m_closingLoop = 0;
    }
    else
    {
        d->threadsLock()->unlock();
    }

    bool ret = doCloseDocument();

    d->m_closing = false;

    return ret;
}

00189 bool Generator::canGeneratePixmap() const
{
    Q_D( const Generator );
    return d->mPixmapReady;
}

00195 void Generator::generatePixmap( PixmapRequest *request )
{
    Q_D( Generator );
    d->mPixmapReady = false;

    if ( hasFeature( Threaded ) )
    {
        d->pixmapGenerationThread()->startGeneration( request );

        /**
         * We create the text page for every page that is visible to the
         * user, so he can use the text extraction tools without a delay.
         */
        if ( hasFeature( TextExtraction ) && !request->page()->hasTextPage() && canGenerateTextPage() ) {
            d->mTextPageReady = false;
            d->textPageGenerationThread()->startGeneration( request->page() );
        }

        return;
    }

    request->page()->setPixmap( request->id(), new QPixmap( QPixmap::fromImage( image( request ) ) ) );

    d->mPixmapReady = true;

    signalPixmapRequestDone( request );
}

00223 bool Generator::canGenerateTextPage() const
{
    Q_D( const Generator );
    return d->mTextPageReady;
}

00229 void Generator::generateTextPage( Page *page )
{
    Q_D( Generator );
    page->setTextPage( textPage( page ) );
    d->mTextPageReady = true;
}

00236 QImage Generator::image( PixmapRequest * )
{
    return QImage();
}

00241 TextPage* Generator::textPage( Page* )
{
    return 0;
}

00246 const DocumentInfo * Generator::generateDocumentInfo()
{
    return 0;
}

00251 const DocumentSynopsis * Generator::generateDocumentSynopsis()
{
    return 0;
}

FontInfo::List Generator::fontsForPage( int )
{
    return FontInfo::List();
}

00261 const QList<EmbeddedFile*> * Generator::embeddedFiles() const
{
    return 0;
}

00266 Generator::PageSizeMetric Generator::pagesSizeMetric() const
{
    return None;
}

00271 bool Generator::isAllowed( Permission ) const
{
    return true;
}

00276 void Generator::rotationChanged( Rotation, Rotation )
{
}

00280 PageSize::List Generator::pageSizes() const
{
    return PageSize::List();
}

00285 void Generator::pageSizeChanged( const PageSize &, const PageSize & )
{
}

00289 bool Generator::print( QPrinter& )
{
    return false;
}

00294 QVariant Generator::metaData( const QString&, const QVariant& ) const
{
    return QVariant();
}

00299 ExportFormat::List Generator::exportFormats() const
{
    return ExportFormat::List();
}

00304 bool Generator::exportTo( const QString&, const ExportFormat& )
{
    return false;
}

00309 bool Generator::hasFeature( GeneratorFeature feature ) const
{
    Q_D( const Generator );
    return d->m_features.contains( feature );
}

00315 void Generator::signalPixmapRequestDone( PixmapRequest * request )
{
    Q_D( Generator );
    if ( d->m_document )
        d->m_document->requestDone( request );
    else
    {
        delete request;
    }
}

00326 const Document * Generator::document() const
{
    Q_D( const Generator );
    if ( d->m_document )
    {
        return d->m_document->m_parent;
    }
    return 0;
}

00336 void Generator::setFeature( GeneratorFeature feature, bool on )
{
    Q_D( Generator );
    if ( on )
        d->m_features.insert( feature );
    else
        d->m_features.remove( feature );
}

00345 QVariant Generator::documentMetaData( const QString &key, const QVariant &option ) const
{
    Q_D( const Generator );
    if ( !d->m_document )
        return QVariant();

    return d->m_document->documentMetaData( key, option );
}

00354 QMutex* Generator::userMutex() const
{
    Q_D( const Generator );
    if ( !d->m_mutex )
    {
        d->m_mutex = new QMutex();
    }
    return d->m_mutex;
}


00365 PixmapRequest::PixmapRequest( int id, int pageNumber, int width, int height, int priority, bool asynchronous )
  : d( new PixmapRequestPrivate )
{
    d->mId = id;
    d->mPageNumber = pageNumber;
    d->mWidth = width;
    d->mHeight = height;
    d->mPriority = priority;
    d->mAsynchronous = asynchronous;
}

00376 PixmapRequest::~PixmapRequest()
{
    delete d;
}

00381 int PixmapRequest::id() const
{
    return d->mId;
}

00386 int PixmapRequest::pageNumber() const
{
    return d->mPageNumber;
}

00391 int PixmapRequest::width() const
{
    return d->mWidth;
}

00396 int PixmapRequest::height() const
{
    return d->mHeight;
}

00401 int PixmapRequest::priority() const
{
    return d->mPriority;
}

00406 bool PixmapRequest::asynchronous() const
{
    return d->mAsynchronous;
}

00411 Page* PixmapRequest::page() const
{
    return d->mPage;
}

void PixmapRequestPrivate::swap()
{
    qSwap( mWidth, mHeight );
}

class Okular::ExportFormatPrivate : public QSharedData
{
    public:
        ExportFormatPrivate( const QString &description, const KMimeType::Ptr &mimeType, const KIcon &icon = KIcon() )
            : QSharedData(), mDescription( description ), mMimeType( mimeType ), mIcon( icon )
        {
        }
        ~ExportFormatPrivate()
        {
        }

        QString mDescription;
        KMimeType::Ptr mMimeType;
        KIcon mIcon;
};

00437 ExportFormat::ExportFormat()
    : d( new ExportFormatPrivate( QString(), KMimeType::Ptr() ) )
{
}

00442 ExportFormat::ExportFormat( const QString &description, const KMimeType::Ptr &mimeType )
    : d( new ExportFormatPrivate( description, mimeType ) )
{
}

00447 ExportFormat::ExportFormat( const KIcon &icon, const QString &description, const KMimeType::Ptr &mimeType )
    : d( new ExportFormatPrivate( description, mimeType, icon ) )
{
}

00452 ExportFormat::~ExportFormat()
{
}

00456 ExportFormat::ExportFormat( const ExportFormat &other )
    : d( other.d )
{
}

00461 ExportFormat& ExportFormat::operator=( const ExportFormat &other )
{
    if ( this == &other )
        return *this;

    d = other.d;

    return *this;
}

00471 QString ExportFormat::description() const
{
    return d->mDescription;
}

00476 KMimeType::Ptr ExportFormat::mimeType() const
{
    return d->mMimeType;
}

00481 KIcon ExportFormat::icon() const
{
    return d->mIcon;
}

00486 bool ExportFormat::isNull() const
{
    return d->mMimeType.isNull() || d->mDescription.isNull();
}

00491 ExportFormat ExportFormat::standardFormat( StandardExportFormat type )
{
    switch ( type )
    {
        case PlainText:
            return ExportFormat( KIcon( "text-x-generic" ), i18n( "Plain &Text..." ), KMimeType::mimeType( "text/plain" ) );
            break;
        case PDF:
            return ExportFormat( KIcon( "application-pdf" ), i18n( "PDF" ), KMimeType::mimeType( "application/pdf" ) );
            break;
    }
    return ExportFormat();
}

bool ExportFormat::operator==( const ExportFormat &other ) const
{
    return d == other.d;
}

bool ExportFormat::operator!=( const ExportFormat &other ) const
{
    return d != other.d;
}

QDebug operator<<( QDebug str, const Okular::PixmapRequest &req )
{
    QString s = QString( "%1 PixmapRequest (id: %2) (%3x%4), prio %5, pageNo %6" )
        .arg( QString( req.asynchronous() ? "Async" : "Sync" ) )
        .arg( req.id() )
        .arg( req.width() )
        .arg( req.height() )
        .arg( req.priority() )
        .arg( req.pageNumber() );
    str << qPrintable( s );
    return str;
}

#include "generator.moc"

Generated by  Doxygen 1.6.0   Back to index