compile
[kdegraphics.git] / okular / core / generator.cpp
blob302dc233ba31592d6a1afb01bbd8ffdb486d38d1
1 /***************************************************************************
2 * Copyright (C) 2005 by Piotr Szymanski <niedakh@gmail.com> *
3 * Copyright (C) 2008 by Albert Astals Cid <aacid@kde.org> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 ***************************************************************************/
11 #include "generator.h"
12 #include "generator_p.h"
14 #include <qeventloop.h>
15 #include <QtGui/QPrinter>
17 #include <kdebug.h>
18 #include <kicon.h>
19 #include <klocale.h>
21 #include "document.h"
22 #include "document_p.h"
23 #include "page.h"
24 #include "textpage.h"
25 #include "utils.h"
27 using namespace Okular;
29 GeneratorPrivate::GeneratorPrivate()
30 : m_document( 0 ),
31 mPixmapGenerationThread( 0 ), mTextPageGenerationThread( 0 ),
32 m_mutex( 0 ), m_threadsMutex( 0 ), mPixmapReady( true ), mTextPageReady( true ),
33 m_closing( false ), m_closingLoop( 0 )
37 GeneratorPrivate::~GeneratorPrivate()
39 if ( mPixmapGenerationThread )
40 mPixmapGenerationThread->wait();
42 delete mPixmapGenerationThread;
44 if ( mTextPageGenerationThread )
45 mTextPageGenerationThread->wait();
47 delete mTextPageGenerationThread;
49 delete m_mutex;
50 delete m_threadsMutex;
53 PixmapGenerationThread* GeneratorPrivate::pixmapGenerationThread()
55 if ( mPixmapGenerationThread )
56 return mPixmapGenerationThread;
58 Q_Q( Generator );
59 mPixmapGenerationThread = new PixmapGenerationThread( q );
60 QObject::connect( mPixmapGenerationThread, SIGNAL( finished() ),
61 q, SLOT( pixmapGenerationFinished() ),
62 Qt::QueuedConnection );
64 return mPixmapGenerationThread;
67 TextPageGenerationThread* GeneratorPrivate::textPageGenerationThread()
69 if ( mTextPageGenerationThread )
70 return mTextPageGenerationThread;
72 Q_Q( Generator );
73 mTextPageGenerationThread = new TextPageGenerationThread( q );
74 QObject::connect( mTextPageGenerationThread, SIGNAL( finished() ),
75 q, SLOT( textpageGenerationFinished() ),
76 Qt::QueuedConnection );
78 return mTextPageGenerationThread;
81 void GeneratorPrivate::pixmapGenerationFinished()
83 Q_Q( Generator );
84 PixmapRequest *request = mPixmapGenerationThread->request();
85 mPixmapGenerationThread->endGeneration();
87 QMutexLocker locker( threadsLock() );
88 mPixmapReady = true;
90 if ( m_closing )
92 delete request;
93 if ( mTextPageReady )
95 locker.unlock();
96 m_closingLoop->quit();
98 return;
101 const QImage& img = mPixmapGenerationThread->image();
102 request->page()->setPixmap( request->id(), new QPixmap( QPixmap::fromImage( img ) ) );
103 const int pageNumber = request->page()->number();
105 q->signalPixmapRequestDone( request );
106 if ( mPixmapGenerationThread->calcBoundingBox() )
107 q->updatePageBoundingBox( pageNumber, mPixmapGenerationThread->boundingBox() );
110 void GeneratorPrivate::textpageGenerationFinished()
112 Q_Q( Generator );
113 Page *page = mTextPageGenerationThread->page();
114 mTextPageGenerationThread->endGeneration();
116 QMutexLocker locker( threadsLock() );
117 mTextPageReady = true;
119 if ( m_closing )
121 delete mTextPageGenerationThread->textPage();
122 if ( mPixmapReady )
124 locker.unlock();
125 m_closingLoop->quit();
127 return;
130 if ( mTextPageGenerationThread->textPage() )
132 TextPage *tp = mTextPageGenerationThread->textPage();
133 page->setTextPage( tp );
134 q->signalTextGenerationDone( page, tp );
138 QMutex* GeneratorPrivate::threadsLock()
140 if ( !m_threadsMutex )
141 m_threadsMutex = new QMutex();
142 return m_threadsMutex;
145 QVariant GeneratorPrivate::metaData( const QString &, const QVariant & ) const
147 return QVariant();
150 QImage GeneratorPrivate::image( PixmapRequest * )
152 return QImage();
156 Generator::Generator( QObject *parent, const QVariantList &args )
157 : QObject( parent ), d_ptr( new GeneratorPrivate() )
159 d_ptr->q_ptr = this;
160 Q_UNUSED( args )
163 Generator::Generator( GeneratorPrivate &dd, QObject *parent, const QVariantList &args )
164 : QObject( parent ), d_ptr( &dd )
166 d_ptr->q_ptr = this;
167 Q_UNUSED( args )
170 Generator::~Generator()
172 delete d_ptr;
175 bool Generator::loadDocumentFromData( const QByteArray &, QVector< Page * > & )
177 return false;
180 bool Generator::closeDocument()
182 Q_D( Generator );
184 d->m_closing = true;
186 d->threadsLock()->lock();
187 if ( !( d->mPixmapReady && d->mTextPageReady ) )
189 QEventLoop loop;
190 d->m_closingLoop = &loop;
192 d->threadsLock()->unlock();
194 loop.exec();
196 d->m_closingLoop = 0;
198 else
200 d->threadsLock()->unlock();
203 bool ret = doCloseDocument();
205 d->m_closing = false;
207 return ret;
210 bool Generator::canGeneratePixmap() const
212 Q_D( const Generator );
213 return d->mPixmapReady;
216 void Generator::generatePixmap( PixmapRequest *request )
218 Q_D( Generator );
219 d->mPixmapReady = false;
221 if ( hasFeature( Threaded ) )
223 d->pixmapGenerationThread()->startGeneration( request, !request->page()->isBoundingBoxKnown() );
226 * We create the text page for every page that is visible to the
227 * user, so he can use the text extraction tools without a delay.
229 if ( hasFeature( TextExtraction ) && !request->page()->hasTextPage() && canGenerateTextPage() ) {
230 d->mTextPageReady = false;
231 d->textPageGenerationThread()->startGeneration( request->page() );
234 return;
237 const QImage& img = image( request );
238 request->page()->setPixmap( request->id(), new QPixmap( QPixmap::fromImage( img ) ) );
239 const bool bboxKnown = request->page()->isBoundingBoxKnown();
240 const int pageNumber = request->page()->number();
242 d->mPixmapReady = true;
244 signalPixmapRequestDone( request );
245 if ( !bboxKnown )
246 updatePageBoundingBox( pageNumber, Utils::imageBoundingBox( &img ) );
249 bool Generator::canGenerateTextPage() const
251 Q_D( const Generator );
252 return d->mTextPageReady;
255 void Generator::generateTextPage( Page *page )
257 Q_D( Generator );
258 TextPage *tp = textPage( page );
259 page->setTextPage( tp );
260 d->mTextPageReady = true;
261 signalTextGenerationDone( page, tp );
264 QImage Generator::image( PixmapRequest *request )
266 Q_D( Generator );
267 return d->image( request );
270 TextPage* Generator::textPage( Page* )
272 return 0;
275 const DocumentInfo * Generator::generateDocumentInfo()
277 return 0;
280 const DocumentSynopsis * Generator::generateDocumentSynopsis()
282 return 0;
285 FontInfo::List Generator::fontsForPage( int )
287 return FontInfo::List();
290 const QList<EmbeddedFile*> * Generator::embeddedFiles() const
292 return 0;
295 Generator::PageSizeMetric Generator::pagesSizeMetric() const
297 return None;
300 bool Generator::isAllowed( Permission ) const
302 return true;
305 void Generator::rotationChanged( Rotation, Rotation )
309 PageSize::List Generator::pageSizes() const
311 return PageSize::List();
314 void Generator::pageSizeChanged( const PageSize &, const PageSize & )
318 bool Generator::print( QPrinter& )
320 return false;
323 QVariant Generator::metaData( const QString &key, const QVariant &option ) const
325 Q_D( const Generator );
326 return d->metaData( key, option );
329 ExportFormat::List Generator::exportFormats() const
331 return ExportFormat::List();
334 bool Generator::exportTo( const QString&, const ExportFormat& )
336 return false;
339 bool Generator::hasFeature( GeneratorFeature feature ) const
341 Q_D( const Generator );
342 return d->m_features.contains( feature );
345 void Generator::signalPixmapRequestDone( PixmapRequest * request )
347 Q_D( Generator );
348 if ( d->m_document )
349 d->m_document->requestDone( request );
350 else
352 delete request;
356 void Generator::signalTextGenerationDone( Page *page, TextPage *textPage )
358 Q_D( Generator );
359 if ( d->m_document )
360 d->m_document->textGenerationDone( page );
361 else
362 delete textPage;
365 const Document * Generator::document() const
367 Q_D( const Generator );
368 if ( d->m_document )
370 return d->m_document->m_parent;
372 return 0;
375 void Generator::setFeature( GeneratorFeature feature, bool on )
377 Q_D( Generator );
378 if ( on )
379 d->m_features.insert( feature );
380 else
381 d->m_features.remove( feature );
384 QVariant Generator::documentMetaData( const QString &key, const QVariant &option ) const
386 Q_D( const Generator );
387 if ( !d->m_document )
388 return QVariant();
390 return d->m_document->documentMetaData( key, option );
393 QMutex* Generator::userMutex() const
395 Q_D( const Generator );
396 if ( !d->m_mutex )
398 d->m_mutex = new QMutex();
400 return d->m_mutex;
403 void Generator::updatePageBoundingBox( int page, const NormalizedRect & boundingBox )
405 Q_D( Generator );
406 if ( d->m_document ) // still connected to document?
407 d->m_document->setPageBoundingBox( page, boundingBox );
410 void Generator::requestFontData(const Okular::FontInfo & /*font*/, QByteArray * /*data*/)
415 PixmapRequest::PixmapRequest( int id, int pageNumber, int width, int height, int priority, bool asynchronous )
416 : d( new PixmapRequestPrivate )
418 d->mId = id;
419 d->mPageNumber = pageNumber;
420 d->mWidth = width;
421 d->mHeight = height;
422 d->mPriority = priority;
423 d->mAsynchronous = asynchronous;
424 d->mForce = false;
427 PixmapRequest::~PixmapRequest()
429 delete d;
432 int PixmapRequest::id() const
434 return d->mId;
437 int PixmapRequest::pageNumber() const
439 return d->mPageNumber;
442 int PixmapRequest::width() const
444 return d->mWidth;
447 int PixmapRequest::height() const
449 return d->mHeight;
452 int PixmapRequest::priority() const
454 return d->mPriority;
457 bool PixmapRequest::asynchronous() const
459 return d->mAsynchronous;
462 Page* PixmapRequest::page() const
464 return d->mPage;
467 void PixmapRequestPrivate::swap()
469 qSwap( mWidth, mHeight );
472 class Okular::ExportFormatPrivate : public QSharedData
474 public:
475 ExportFormatPrivate( const QString &description, const KMimeType::Ptr &mimeType, const KIcon &icon = KIcon() )
476 : QSharedData(), mDescription( description ), mMimeType( mimeType ), mIcon( icon )
479 ~ExportFormatPrivate()
483 QString mDescription;
484 KMimeType::Ptr mMimeType;
485 KIcon mIcon;
488 ExportFormat::ExportFormat()
489 : d( new ExportFormatPrivate( QString(), KMimeType::Ptr() ) )
493 ExportFormat::ExportFormat( const QString &description, const KMimeType::Ptr &mimeType )
494 : d( new ExportFormatPrivate( description, mimeType ) )
498 ExportFormat::ExportFormat( const KIcon &icon, const QString &description, const KMimeType::Ptr &mimeType )
499 : d( new ExportFormatPrivate( description, mimeType, icon ) )
503 ExportFormat::~ExportFormat()
507 ExportFormat::ExportFormat( const ExportFormat &other )
508 : d( other.d )
512 ExportFormat& ExportFormat::operator=( const ExportFormat &other )
514 if ( this == &other )
515 return *this;
517 d = other.d;
519 return *this;
522 QString ExportFormat::description() const
524 return d->mDescription;
527 KMimeType::Ptr ExportFormat::mimeType() const
529 return d->mMimeType;
532 KIcon ExportFormat::icon() const
534 return d->mIcon;
537 bool ExportFormat::isNull() const
539 return d->mMimeType.isNull() || d->mDescription.isNull();
542 ExportFormat ExportFormat::standardFormat( StandardExportFormat type )
544 switch ( type )
546 case PlainText:
547 return ExportFormat( KIcon( "text-x-generic" ), i18n( "Plain &Text..." ), KMimeType::mimeType( "text/plain" ) );
548 break;
549 case PDF:
550 return ExportFormat( KIcon( "application-pdf" ), i18n( "PDF" ), KMimeType::mimeType( "application/pdf" ) );
551 break;
552 case OpenDocumentText:
553 return ExportFormat(
554 KIcon( "application-vnd.oasis.opendocument.text" ),
555 i18nc( "This is the document format", "OpenDocument Text" ),
556 KMimeType::mimeType( "application/vnd.oasis.opendocument.text" ) );
557 break;
558 case HTML:
559 return ExportFormat( KIcon( "text-html" ), i18nc( "This is the document format", "HTML" ), KMimeType::mimeType( "text/html" ) );
560 break;
562 return ExportFormat();
565 bool ExportFormat::operator==( const ExportFormat &other ) const
567 return d == other.d;
570 bool ExportFormat::operator!=( const ExportFormat &other ) const
572 return d != other.d;
575 QDebug operator<<( QDebug str, const Okular::PixmapRequest &req )
577 QString s = QString( "%1 PixmapRequest (id: %2) (%3x%4), prio %5, pageNo %6" )
578 .arg( QString( req.asynchronous() ? "Async" : "Sync" ) )
579 .arg( req.id() )
580 .arg( req.width() )
581 .arg( req.height() )
582 .arg( req.priority() )
583 .arg( req.pageNumber() );
584 str << qPrintable( s );
585 return str;
588 #include "generator.moc"