document.cpp 20.4 KB
Newer Older
1
2
/***************************************************************************
 *   Copyright (C) 2004 by Enrico Ros <eros.kde@email.it>                  *
Albert Astals Cid's avatar
Albert Astals Cid committed
3
 *   Copyright (C) 2004 by Albert Astals Cid <tsdgeos@terra.es>            *
4
5
6
7
8
9
10
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/

11
12
// qt/kde/system includes
#include <qdir.h>
13
#include <qfile.h>
14
#include <qfileinfo.h>
15
16
#include <qmutex.h>
#include <qvaluevector.h>
17
#include <qmap.h>
Enrico Ros's avatar
Enrico Ros committed
18
#include <kdebug.h>
19
20
21
#include <klocale.h>
#include <kfinddialog.h>
#include <kmessagebox.h>
22
#include <kmimetype.h>
23
#include <kpassdlg.h>
24
#include <kstandarddirs.h>
25
26
27
28
29
#include <kapplication.h>
#include <krun.h>
#include <kurl.h>
#include <kuserprofile.h>
#include <string.h>
30
31

// local includes
32
#include "ErrorCodes.h"
33
#include "PDFDoc.h"
34
#include "QOutputDev.h"
35
36
37
38
39

#include "kpdf_error.h"
#include "document.h"
#include "page.h"

40
/* Notes:
41
- FIXME event queuing to avoid flow loops (!!??) maybe avoided by the
42
43
44
  warning to not call something 'active' inside an observer method.
*/

45
// structure used internally by KPDFDocument for local variables storage
46
class KPDFDocumentPrivate
47
{
48
public:
49
50
51
    // document related
    QMutex docLock;
    PDFDoc * pdfdoc;
52
    KPDFOutputDev * kpdfOutputDev;
53
    int currentPage;
Enrico Ros's avatar
Enrico Ros committed
54
    QRect currentViewport;
55
    QValueVector< KPDFPage* > pages;
Enrico Ros's avatar
Enrico Ros committed
56

57
    // find related
58
59
60
    QString searchText;
    bool searchCase;
    int searchPage;
61
    // filtering related
62
63
    QString filterText;
    bool filterCase;
64

65
    // observers related (note: won't delete oservers)
66
    QMap< int, KPDFDocumentObserver* > observers;
67
68
69
};

#define foreachObserver( cmd ) {\
70
71
    QMap<int,KPDFDocumentObserver*>::iterator it = d->observers.begin();\
    QMap<int,KPDFDocumentObserver*>::iterator end = d->observers.end();\
72
73
74
75
76
77
78
79
80
    for ( ; it != end ; ++ it ) { (*it)-> cmd ; } }

/*
 * KPDFDocument class
 */
KPDFDocument::KPDFDocument()
{
    d = new KPDFDocumentPrivate;
    d->pdfdoc = 0;
81
    d->currentPage = -1;
82
    d->searchPage = -1;
83
84
    SplashColor paperColor;
    paperColor.rgb8 = splashMakeRGB8( 0xff, 0xff, 0xff );
85
    d->kpdfOutputDev = new KPDFOutputDev( paperColor );
86
}
Enrico Ros's avatar
Enrico Ros committed
87

88
89
KPDFDocument::~KPDFDocument()
{
90
    closeDocument();
91
    delete d->kpdfOutputDev;
92
93
94
    delete d;
}

95
bool KPDFDocument::openDocument( const QString & docFile )
96
97
98
99
100
{
    // docFile is always local so we can use QFile on it
    QFile fileReadTest( docFile );
    if ( !fileReadTest.open( IO_ReadOnly ) )
        return false;
101
    long fileSize = fileReadTest.size();
102
103
    fileReadTest.close();

104
105
106
    // free internal data
    closeDocument();

107
108
    GString *filename = new GString( QFile::encodeName( docFile ) );
    delete d->pdfdoc;
109
    d->pdfdoc = new PDFDoc( filename, 0, 0 );
110
111

    if ( !d->pdfdoc->isOk() )
112
    {
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
        if (d->pdfdoc->getErrorCode() == errEncrypted)
        {
            bool first, correct;
            QString prompt;
            QCString pwd;

            first = true;
            correct = false;
            while(!correct)
            {
                if (first)
                {
                    prompt = i18n("Please insert the password to read the document:");
                    first = false;
                }
                else prompt = i18n("Incorrect password. Try again:");
                if (KPasswordDialog::getPassword(pwd, prompt) == KPasswordDialog::Accepted)
                {
                    GString *pwd2;
                    pwd2 = new GString(pwd.data());
                    d->pdfdoc = new PDFDoc(filename, pwd2, pwd2);
                    delete pwd2;
                    correct = d->pdfdoc->isOk();
                    if (!correct && d->pdfdoc->getErrorCode() != errEncrypted)
                    {
                        delete d->pdfdoc;
                        d->pdfdoc = 0;
                        return false;
                    }
                }
                else
                {
                    delete d->pdfdoc;
                    d->pdfdoc = 0;
                    return false;
                }
            }
        }
        else
        {
            delete d->pdfdoc;
            d->pdfdoc = 0;
            return false;
        }
157
158
159
160
161
    }

    // clear xpdf errors
    errors::clear();

162
    // initialize output device for rendering current pdf
163
    d->kpdfOutputDev->startDoc( d->pdfdoc->getXRef() );
164
165

    // build Pages (currentPage was set -1 by deletePages)
166
167
    uint pageCount = d->pdfdoc->getNumPages();
    d->pages.resize( pageCount );
168
169
170
171
172
    if ( pageCount > 0 )
    {
        for ( uint i = 0; i < pageCount ; i++ )
            d->pages[i] = new KPDFPage( i, d->pdfdoc->getPageWidth(i+1), d->pdfdoc->getPageHeight(i+1), d->pdfdoc->getPageRotate(i+1) );
        // filter pages, setup observers and set the first page as current
173
        processPageList( true );
174
175
        slotSetCurrentPage( 0 );
    }
Enrico Ros's avatar
Enrico Ros committed
176

177
178
179
180
181
182
    // check local directory for an overlay xml
    QString fileName = docFile.contains('/') ? docFile.section('/', -1, -1) : docFile;
    fileName = "kpdf/" + QString::number(fileSize) + "." + fileName + ".xml";
    QString localFN = locateLocal( "data", fileName );
    kdWarning() << localFN << endl;

183
184
185
    return true;
}

186
void KPDFDocument::closeDocument()
187
{
188
189
190
191
192
193
194
195
196
197
198
199
200
    // delete pages and clear container
    for ( uint i = 0; i < d->pages.count() ; i++ )
        delete d->pages[i];
    d->pages.clear();

    // broadcast zero pages
    processPageList( true );

    // reset internal variables
    d->currentPage = -1;
    d->searchPage = -1;

    // delete xpds's PDFDoc contents generator
201
202
203
204
    delete d->pdfdoc;
    d->pdfdoc = 0;
}

205
206

uint KPDFDocument::currentPage() const
207
{
208
    return d->currentPage;
209
210
211
212
213
214
215
}

uint KPDFDocument::pages() const
{
    return d->pdfdoc ? d->pdfdoc->getNumPages() : 0;
}

216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
bool KPDFDocument::atBegin() const
{
    return d->currentPage < 1;
}

bool KPDFDocument::atEnd() const
{
    return d->currentPage >= ((int)d->pages.count() - 1);
}

const KPDFPage * KPDFDocument::page( uint n ) const
{
    return ( n < d->pages.count() ) ? d->pages[n] : 0;
}

Albert Astals Cid's avatar
Albert Astals Cid committed
231
232
233
234
235
Outline * KPDFDocument::outline() const
{
    return d->pdfdoc ? d->pdfdoc->getOutline() : 0;
}

236

237
238
void KPDFDocument::addObserver( KPDFDocumentObserver * pObserver )
{
239
    d->observers[ pObserver->observerId() ] = pObserver;
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
}

void KPDFDocument::requestPixmap( int id, uint page, int width, int height, bool syn )
{
    KPDFPage * kp = d->pages[page];
    if ( !d->pdfdoc || !kp || kp->width() < 1 || kp->height() < 1 )
        return;

    if ( syn )
    {
        // in-place Pixmap generation for syncronous requests
        if ( !kp->hasPixmap( id, width, height ) )
        {
            // compute dpi used to get an image with desired width and height
            double fakeDpiX = width * 72.0 / kp->width(),
                   fakeDpiY = height * 72.0 / kp->height();
256
257
258
259

            // setup kpdf output device: text page is generated only if we are at 72dpi.
            // since we can pre-generate the TextPage at the right res.. why not?
            bool genTextPage = !kp->hasSearchPage() && (width == kp->width()) && (height == kp->height());
260
261
262
            // generate links if rendering pages on pageview
            bool genLinks = id == PAGEVIEW_ID;
            d->kpdfOutputDev->setParams( width, height, genTextPage, genLinks );
263

264
            d->docLock.lock();
265
            d->pdfdoc->displayPage( d->kpdfOutputDev, page + 1, fakeDpiX, fakeDpiY, 0, true, genLinks );
266
267
268
            d->docLock.unlock();

            kp->setPixmap( id, d->kpdfOutputDev->takePixmap() );
269
270
            if ( genTextPage )
                kp->setSearchPage( d->kpdfOutputDev->takeTextPage() );
271
272
            if ( genLinks )
                kp->setLinks( d->kpdfOutputDev->takeLinks() );
273
            kp->setActiveRects( d->kpdfOutputDev->takeActiveRects() );
274
275
276
277
278
279
280
281
282
283

            d->observers[id]->notifyPixmapChanged( page );
        }
    }
    else
    {
        //TODO asyncronous events queuing
    }
}

284
285
286
287
288
289
290
291
292
293
294
295
void KPDFDocument::requestTextPage( uint n )
{
    KPDFPage * page = d->pages[ n ];
    // build a TextPage using the lightweight KPDFTextDev generator..
    KPDFTextDev td;
    d->docLock.lock();
    d->pdfdoc->displayPage( &td, page->number()+1, 72, 72, 0, true, false );
    d->docLock.unlock();
    // ..and attach it to the page
    page->setSearchPage( td.takeTextPage() );
}

Albert Astals Cid's avatar
Albert Astals Cid committed
296
// BEGIN slots
297
298
void KPDFDocument::slotSetCurrentPage( int page )
{
Enrico Ros's avatar
Enrico Ros committed
299
    slotSetCurrentPageViewport( page, QRect() );
300
301
}

Enrico Ros's avatar
Enrico Ros committed
302
void KPDFDocument::slotSetCurrentPageViewport( int page, const QRect & viewport )
303
{
Enrico Ros's avatar
Enrico Ros committed
304
    if ( page < 0 )
305
        page = 0;
Enrico Ros's avatar
Enrico Ros committed
306
307
308
    else if ( page > (int)d->pages.count() )
        page = d->pages.count() - 1;
    if ( page == d->currentPage && viewport == d->currentViewport )
309
310
        return;
    d->currentPage = page;
Enrico Ros's avatar
Enrico Ros committed
311
312
    d->currentViewport = viewport;
    foreachObserver( pageSetCurrent( page, viewport ) );
313
314
315
    pageChanged();
}

316
void KPDFDocument::slotSetFilter( const QString & pattern, bool keepCase )
317
{
318
319
320
    d->filterText = pattern;
    d->filterCase = keepCase;
    processPageList( false );
321
}
322

323
void KPDFDocument::slotBookmarkPage( int n, bool on )
324
{
325
326
    KPDFPage * page = ( n < (int)d->pages.count() ) ? d->pages[ n ] : 0;
    if ( page )
327
    {
328
329
        page->bookmark( on );
        foreachObserver( notifyPixmapChanged( n ) );
330
331
332
    }
}

333
void KPDFDocument::slotFind( const QString & string, bool keepCase )
334
{
335
336
337
338
339
340
    // turn selection drawing off on filtered pages
    if ( !d->filterText.isEmpty() )
        unHilightPages();

    // save params for the 'find next' case
    if ( !string.isEmpty() )
341
    {
342
343
        d->searchText = string;
        d->searchCase = keepCase;
344
345
    }

346
347
348
    // continue checking last SearchPage first (if it is the current page)
    int currentPage = d->currentPage;
    int pageCount = d->pages.count();
349
350
351
352
353
    KPDFPage * foundPage = 0,
             * lastPage = (d->searchPage > -1) ? d->pages[ d->searchPage ] : 0;
    if ( lastPage && d->searchPage == currentPage )
        if ( lastPage->hasText( d->searchText, d->searchCase, false ) )
            foundPage = lastPage;
354
        else
355
        {
356
            lastPage->hilightLastSearch( false );
357
358
            currentPage++;
            pageCount--;
359
360
        }

361
362
363
    if ( !foundPage )
        // loop through the whole document
        for ( int i = 0; i < pageCount; i++ )
Enrico Ros's avatar
Enrico Ros committed
364
        {
365
366
367
368
369
370
371
372
373
            if ( currentPage >= pageCount )
            {
                if ( KMessageBox::questionYesNo(0, i18n("End of document reached.\nContinue from the beginning?")) == KMessageBox::Yes )
                    currentPage = 0;
                else
                    break;
            }
            KPDFPage * page = d->pages[ currentPage ];
            if ( !page->hasSearchPage() )
374
                requestTextPage( page->number() );
375
            if ( page->hasText( d->searchText, d->searchCase, true ) )
376
377
378
379
380
            {
                foundPage = page;
                break;
            }
            currentPage++;
Enrico Ros's avatar
Enrico Ros committed
381
382
        }

383
    if ( foundPage )
384
    {
385
386
        int pageNumber = foundPage->number();
        d->searchPage = pageNumber;
387
        foundPage->hilightLastSearch( true );
388
389
        slotSetCurrentPage( pageNumber );
        foreachObserver( notifyPixmapChanged( pageNumber ) );
390
    }
391
    else
392
        KMessageBox::information( 0, i18n("No matches found for '%1'.").arg(d->searchText) );
393
394
}

395
void KPDFDocument::slotProcessLink( const KPDFLink * link )
396
{
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
    if ( !link )
        return;

    switch( link->type() )
    {
    case KPDFLink::Goto: {
        // make copies of the 'nameDest' (string) and the 'dest' (class)
        char * namedDest = 0;
        link->copyString( namedDest, link->getNamedDest() );
        LinkDest * dest = link->getDest() ? ((LinkDest*)link->getDest())->copy() : 0;

        // first open filename if link is pointing outside this document
        QString fileName( link->getFileName() );
        if ( !fileName.isNull() )
            if ( !openRelativeFile( fileName ) )
            {
                kdWarning() << "Link: Error opening '" << fileName << "'." << endl;
                delete dest;
                delete namedDest;
                return;
            }

        // now previous KPDFLink and KPDFPage don't exist anymore!
        if ( namedDest && !dest )
        {
            GString temp( namedDest );
423
            d->docLock.lock();
424
425
426
            dest = d->pdfdoc->findDest( &temp  );
            d->docLock.unlock();
        }
427
        if ( dest && dest->isOk() )
428
        {
Enrico Ros's avatar
Enrico Ros committed
429
430
            // get destination page number
            int pageNum = dest->getPageNum() - 1;
431
432
433
434
            if ( dest->isPageRef() )
            {
                Ref ref = dest->getPageRef();
                d->docLock.lock();
Enrico Ros's avatar
Enrico Ros committed
435
                pageNum = d->pdfdoc->findPage( ref.num, ref.gen ) - 1;
436
437
438
                d->docLock.unlock();
            }
            // get destination position
Enrico Ros's avatar
Enrico Ros committed
439
440
441
            QRect r;
            KPDFPage * page = (pageNum >= 0 && pageNum < (int)d->pages.count()) ? d->pages[ pageNum ] : 0;
            //if ( page )
442
443
444
445
            /* TODO
            switch ( dest->getKind() )
            {
            case destXYZ
Enrico Ros's avatar
Enrico Ros committed
446
                OD -> cvtUserToDev( dest->getLeft(), dest->getTop(), &X, &Y );
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
                if ( dest->getChangeLeft() )
                    make hor change
                if ( dest->getChangeTop() )
                    make ver change
                if ( dest->getChangeZoom() )
                    make zoom change
            case destFit
            case destFitB
                fit page
            case destFitH
            case destFitBH
                read top, fit Width
            case destFitV
            case destFitBV
                read left, fit Height
            destFitR
                read and fit left,bottom,right,top
            }*/
Enrico Ros's avatar
Enrico Ros committed
465
            slotSetCurrentPageViewport( pageNum, r );
466
467
468
469
470
471
472
473
474
475
        }
        delete namedDest;
        delete dest;
        } break;

    case KPDFLink::Execute: {
        QString fileName( link->getFileName() );
        if ( fileName.endsWith( ".pdf" ) || fileName.endsWith( ".PDF" ) )
            openRelativeFile( fileName );
        else
476
477
478
        {
			KMimeType::Ptr mime;
			KService::Ptr ptr;
Laurent Montel's avatar
Laurent Montel committed
479

480
481
			// the only pdf i have that has that kind of link don't define an application
			// and use the fileName as the file to open
Laurent Montel's avatar
Laurent Montel committed
482

483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
			fileName = giveAbsolutePath( fileName );
			mime = KMimeType::findByPath( fileName );
			// Check executables
			if ( KRun::isExecutableFile( fileName, mime->name() ) )
			{
				// Don't have any pdf that uses this code path, just a guess on how it should work
				if ( link->getParameters() )
				{
					fileName = giveAbsolutePath( link->getParameters() );
					mime = KMimeType::findByPath( fileName );
					if ( KRun::isExecutableFile( fileName, mime->name() ) )
					{
						// this case is a link pointing to an executable with a parameter
						// that also is an executable, possibly a hand-crafted pdf
						KMessageBox::information( 0, i18n("The pdf file is trying to execute an external application and for your safety kpdf does not allow that.") );
						return;
					}
				}
				else
				{
					// this case is a link pointing to an executable with no parameters
					// core developers find unacceptable executing it even after asking the user
					KMessageBox::information( 0, i18n("The pdf file is trying to execute an external application and for your safety kpdf does not allow that.") );
					return;
				}
			}
Laurent Montel's avatar
Laurent Montel committed
509

510
511
512
513
514
515
516
517
518
			ptr = KServiceTypeProfile::preferredService(mime->name(), "Application");
			if (ptr)
			{
				KURL::List lst;
				lst.append( fileName );
				KRun::run( *ptr, lst );
			}
			else KMessageBox::information( 0, i18n("No application found for opening file of mimetype %1.").arg(mime->name()) );
        }
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
        } break;

    case KPDFLink::Named: {
        const char * name = link->getName();
        if ( !strcmp( name, "NextPage" ) && (d->currentPage < (int)d->pages.count() - 1) )
            slotSetCurrentPage( d->currentPage + 1 );
        else if ( !strcmp( name, "PrevPage" ) && d->currentPage > 0 )
            slotSetCurrentPage( d->currentPage - 1 );
        else if ( !strcmp( name, "FirstPage" ) )
            slotSetCurrentPage( 0 );
        else if ( !strcmp( name, "LastPage" ) )
            slotSetCurrentPage( d->pages.count() - 1 );
        else if ( !strcmp( name, "GoBack" ) )
            {} //TODO
        else if ( !strcmp( name, "GoForward" ) )
            {} //TODO
        else if ( !strcmp( name, "Quit" ) )
            kapp->quit();
        else
            {}//FIXME error(-1, "Unknown named action: '%s'", name);
        } break;

    case KPDFLink::URI: {
        KService::Ptr ptr = KServiceTypeProfile::preferredService("text/html", "Application");
        KURL::List lst;
        lst.append( link->getURI() );
        KRun::run( *ptr, lst );
        } break;

    case KPDFLink::Movie:
    case KPDFLink::Unknown:
        // unimplemented cases
        break;
    }
553
}
Albert Astals Cid's avatar
Albert Astals Cid committed
554
//END slots
555

556
557
558
559
560
561
562
563
564
565
566
QString KPDFDocument::giveAbsolutePath( const QString & fileName )
{
	const char * currentName = d->pdfdoc->getFileName()->getCString();
	if ( !currentName || currentName[0] == 0 )
		return QString::null;

    // convert the pdf fileName to absolute using current pdf path
	QFileInfo currentInfo( currentName );
	return currentInfo.dir().absFilePath( fileName );
}

567
568
bool KPDFDocument::openRelativeFile( const QString & fileName )
{
569
570
    QString absFileName = giveAbsolutePath( fileName );
    if ( absFileName.isNull() )
571
572
573
574
575
576
577
578
        return false;

    kdDebug() << "openDocument: '" << absFileName << "'" << endl;

    // open the absolute filename
    return openDocument( absFileName );
}

579
void KPDFDocument::processPageList( bool documentChanged )
580
{
581
582
583
    if ( d->filterText.length() < 3 )
        unHilightPages();
    else
584
    {
585
        uint pageCount = d->pages.count();
586
        for ( uint i = 0; i < pageCount ; i++ )
587
588
        {
            KPDFPage * page = d->pages[ i ];
589
            if ( d->filterText.length() < 3 )
590
591
592
593
594
595
596
597
598
599
600
601
602
                page->hilightLastSearch( false );
            else
            {
                if ( !page->hasSearchPage() )
                {
                    // build a TextPage using the lightweight KPDFTextDev generator..
                    KPDFTextDev td;
                    d->docLock.lock();
                    d->pdfdoc->displayPage( &td, page->number()+1, 72, 72, 0, true, false );
                    d->docLock.unlock();
                    // ..and attach it to the page
                    page->setSearchPage( td.takeTextPage() );
                }
603
604
                bool found = page->hasText( d->filterText, d->filterCase, true );
                page->hilightLastSearch( found );
605
606
607
            }
        }
    }
608
609

    // send the list to observers
610
    foreachObserver( pageSetup( d->pages, documentChanged ) );
611
612
}

613
void KPDFDocument::unHilightPages()
614
{
Laurent Montel's avatar
Laurent Montel committed
615
    if ( d->filterText.isEmpty() )
616
617
        return;

618
619
620
621
622
623
624
625
626
627
628
    d->filterText = "";
    QValueVector<KPDFPage*>::iterator it = d->pages.begin(), end = d->pages.end();
    for ( ; it != end; ++it )
    {
        KPDFPage * page = *it;
        if ( page->isHilighted() )
        {
            page->hilightLastSearch( false );
            foreachObserver( notifyPixmapChanged( page->number() ) );
        }
    }
629
630
}

631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
/** TO BE IMPORTED:
	void generateThumbnails(PDFDoc *doc);
	void stopThumbnailGeneration();
protected slots:
	void customEvent(QCustomEvent *e);
private slots:
	void changeSelected(int i);
	void emitClicked(int i);
signals:
	void clicked(int);
private:
	void generateNextThumbnail();
	ThumbnailGenerator *m_tg;

	void resizeThumbnails();
	int m_nextThumbnail;
	bool m_ignoreNext;

DELETE:
if (m_tg)
{
	m_tg->wait();
	delete m_tg;
}

void ThumbnailList::generateThumbnails(PDFDoc *doc)
{
	m_nextThumbnail = 1;
	m_doc = doc;
	generateNextThumbnail();
}

void ThumbnailList::generateNextThumbnail()
{
	if (m_tg)
	{
		m_tg->wait();
		delete m_tg;
	}
	m_tg = new ThumbnailGenerator(m_doc, m_docMutex, m_nextThumbnail, QPaintDevice::x11AppDpiX(), this);
	m_tg->start();
}


void ThumbnailList::stopThumbnailGeneration()
{
	if (m_tg)
	{
		m_ignoreNext = true;
		m_tg->wait();
		delete m_tg;
		m_tg = 0;
	}
}


void ThumbnailList::customEvent(QCustomEvent *e)
{
	if (e->type() == 65432 && !m_ignoreNext)
	{
		QImage *i =  (QImage*)(e -> data());
Albert Astals Cid's avatar
Albert Astals Cid committed
692

693
694
695
696
697
698
699
700
701
702
703
704
705
706
		setThumbnail(m_nextThumbnail, i);
		m_nextThumbnail++;
		if (m_nextThumbnail <= m_doc->getNumPages()) generateNextThumbnail();
		else
		{
			m_tg->wait();
			delete m_tg;
			m_tg = 0;
		}
	}
	m_ignoreNext = false;
}
*/

707
#include "document.moc"