~ubuntu-branches/ubuntu/vivid/qpdfview/vivid

« back to all changes in this revision

Viewing changes to sources/presentationview.cpp

  • Committer: Package Import Robot
  • Author(s): Benjamin Eltzner
  • Date: 2013-04-04 14:51:58 UTC
  • mfrom: (1.2.6)
  • Revision ID: package-import@ubuntu.com-20130404145158-cis99qi9kcaiwvet
Tags: 0.4.1-1
* New upstream release.
* Source package now builds three binary packages.
* Included SyncTeX copyright and license into debian/copyright.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 
3
 
Copyright 2012 Adam Reichold
 
3
Copyright 2012-2013 Adam Reichold
4
4
 
5
5
This file is part of qpdfview.
6
6
 
21
21
 
22
22
#include "presentationview.h"
23
23
 
 
24
#include <QKeyEvent>
 
25
#include <QShortcut>
 
26
#include <QTimer>
 
27
 
 
28
#include "model.h"
24
29
#include "pageitem.h"
 
30
#include "documentview.h"
25
31
 
26
 
PresentationView::PresentationView(QMutex* mutex, Poppler::Document* document, QWidget* parent) : QWidget(parent),
27
 
    m_mutex(0),
 
32
PresentationView::PresentationView(Model::Document* document, QWidget* parent) : QGraphicsView(parent),
 
33
    m_prefetchTimer(0),
28
34
    m_document(0),
29
35
    m_numberOfPages(-1),
30
 
    m_currentPage(1),
 
36
    m_currentPage(-1),
 
37
    m_rotation(RotateBy0),
 
38
    m_invertColors(false),
31
39
    m_returnToPage(),
32
 
    m_links(),
33
 
    m_scaleFactor(1.0),
34
 
    m_normalizedTransform(),
35
 
    m_boundingRect(),
36
 
    m_image(),
37
 
    m_render(0)
 
40
    m_pagesScene(0),
 
41
    m_pages()
38
42
{
39
43
    setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
40
44
    setWindowState(windowState() | Qt::WindowFullScreen);
41
 
    setMouseTracking(true);
42
 
 
43
 
    m_render = new QFutureWatcher< void >(this);
44
 
    connect(m_render, SIGNAL(finished()), SLOT(on_render_finished()));
45
 
 
46
 
    connect(this, SIGNAL(imageReady(int,qreal,QImage)), SLOT(on_imageReady(int,qreal,QImage)));
47
 
 
48
 
    m_mutex = mutex;
 
45
 
 
46
    setFrameShape(QFrame::NoFrame);
 
47
 
 
48
    setAcceptDrops(false);
 
49
 
 
50
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
 
51
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
 
52
 
 
53
    new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Space), this, SLOT(previousPage()));
 
54
    new QShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Backspace), this, SLOT(nextPage()));
 
55
 
 
56
    new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Left), this, SLOT(rotateLeft()));
 
57
    new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Right), this, SLOT(rotateRight()));
 
58
 
49
59
    m_document = document;
50
60
 
51
 
    m_numberOfPages = m_document->numPages();
52
 
 
 
61
    m_numberOfPages = m_document->numberOfPages();
 
62
    m_currentPage = 1;
 
63
 
 
64
    // pages
 
65
 
 
66
    m_pagesScene = new QGraphicsScene(this);
 
67
    setScene(m_pagesScene);
 
68
 
 
69
    m_pages.reserve(m_numberOfPages);
 
70
 
 
71
    for(int index = 0; index < m_numberOfPages; ++index)
 
72
    {
 
73
        PageItem* page = new PageItem(m_document->page(index), index, true);
 
74
 
 
75
        page->setPhysicalDpi(physicalDpiX(), physicalDpiY());
 
76
 
 
77
        m_pagesScene->addItem(page);
 
78
        m_pages.append(page);
 
79
 
 
80
        connect(page, SIGNAL(linkClicked(int,qreal,qreal)), SLOT(on_pages_linkClicked(int,qreal,qreal)));
 
81
    }
 
82
 
 
83
    m_pagesScene->setBackgroundBrush(QBrush(PageItem::paperColor()));
 
84
 
 
85
    // prefetch
 
86
 
 
87
    m_prefetchTimer = new QTimer(this);
 
88
    m_prefetchTimer->setInterval(250);
 
89
    m_prefetchTimer->setSingleShot(true);
 
90
 
 
91
    connect(this, SIGNAL(currentPageChanged(int)), m_prefetchTimer, SLOT(start()));
 
92
    connect(this, SIGNAL(rotationChanged(Rotation)), m_prefetchTimer, SLOT(start()));
 
93
 
 
94
    connect(m_prefetchTimer, SIGNAL(timeout()), SLOT(on_prefetch_timeout()));
 
95
 
 
96
    if(DocumentView::prefetch())
 
97
    {
 
98
        m_prefetchTimer->blockSignals(false);
 
99
        m_prefetchTimer->start();
 
100
    }
 
101
    else
 
102
    {
 
103
        m_prefetchTimer->blockSignals(true);
 
104
        m_prefetchTimer->stop();
 
105
    }
 
106
 
 
107
    prepareScene();
53
108
    prepareView();
54
109
}
55
110
 
56
111
PresentationView::~PresentationView()
57
112
{
58
 
    m_render->cancel();
59
 
    m_render->waitForFinished();
60
 
 
61
 
    qDeleteAll(m_links);
 
113
    qDeleteAll(m_pages);
62
114
}
63
115
 
64
116
int PresentationView::numberOfPages() const
71
123
    return m_currentPage;
72
124
}
73
125
 
 
126
Rotation PresentationView::rotation() const
 
127
{
 
128
    return m_rotation;
 
129
}
 
130
 
 
131
void PresentationView::setRotation(Rotation rotation)
 
132
{
 
133
    if(m_rotation != rotation)
 
134
    {
 
135
        m_rotation = rotation;
 
136
 
 
137
        prepareScene();
 
138
        prepareView();
 
139
 
 
140
        emit rotationChanged(m_rotation);
 
141
    }
 
142
}
 
143
 
 
144
bool PresentationView::invertColors() const
 
145
{
 
146
    return m_invertColors;
 
147
}
 
148
 
 
149
void PresentationView::setInvertColors(bool invertColors)
 
150
{
 
151
    if(m_invertColors != invertColors)
 
152
    {
 
153
        m_invertColors = invertColors;
 
154
 
 
155
        foreach(PageItem* page, m_pages)
 
156
        {
 
157
            page->setInvertColors(m_invertColors);
 
158
        }
 
159
 
 
160
        QColor backgroundColor = PageItem::paperColor();
 
161
 
 
162
        if(m_invertColors)
 
163
        {
 
164
            backgroundColor.setRgb(~backgroundColor.rgb());
 
165
        }
 
166
 
 
167
        m_pagesScene->setBackgroundBrush(QBrush(backgroundColor));
 
168
 
 
169
        emit invertColorsChanged(m_invertColors);
 
170
    }
 
171
}
 
172
 
74
173
void PresentationView::show()
75
174
{
76
175
    QWidget::show();
115
214
    }
116
215
}
117
216
 
118
 
void PresentationView::startRender()
119
 
{
120
 
    if(!m_render->isRunning())
121
 
    {
122
 
        m_render->setFuture(QtConcurrent::run(this, &PresentationView::render, m_currentPage - 1, m_scaleFactor));
123
 
    }
124
 
}
125
 
 
126
 
void PresentationView::cancelRender()
127
 
{
128
 
    m_render->cancel();
129
 
 
130
 
    m_image = QImage();
131
 
}
132
 
 
133
 
void PresentationView::on_render_finished()
134
 
{
135
 
    update();
136
 
}
137
 
 
138
 
void PresentationView::on_imageReady(int index, qreal scaleFactor, QImage image)
139
 
{
140
 
    if(m_currentPage - 1 != index || !qFuzzyCompare(m_scaleFactor, scaleFactor))
141
 
    {
142
 
        return;
143
 
    }
144
 
 
145
 
    if(PageItem::invertColors())
146
 
    {
147
 
        image.invertPixels();
148
 
    }
149
 
 
150
 
    if(!m_render->isCanceled())
151
 
    {
152
 
        m_image = image;
153
 
    }
154
 
}
155
 
 
156
 
void PresentationView::resizeEvent(QResizeEvent*)
157
 
{
 
217
void PresentationView::returnToPage()
 
218
{
 
219
    if(!m_returnToPage.isEmpty())
 
220
    {
 
221
        jumpToPage(m_returnToPage.pop(), false);
 
222
    }
 
223
}
 
224
 
 
225
void PresentationView::rotateLeft()
 
226
{
 
227
    switch(m_rotation)
 
228
    {
 
229
    default:
 
230
    case RotateBy0:
 
231
        setRotation(RotateBy270);
 
232
        break;
 
233
    case RotateBy90:
 
234
        setRotation(RotateBy0);
 
235
        break;
 
236
    case RotateBy180:
 
237
        setRotation(RotateBy90);
 
238
        break;
 
239
    case RotateBy270:
 
240
        setRotation(RotateBy180);
 
241
        break;
 
242
    }
 
243
}
 
244
 
 
245
void PresentationView::rotateRight()
 
246
{
 
247
    switch(m_rotation)
 
248
    {
 
249
    default:
 
250
    case RotateBy0:
 
251
        setRotation(RotateBy90);
 
252
        break;
 
253
    case RotateBy90:
 
254
        setRotation(RotateBy180);
 
255
        break;
 
256
    case RotateBy180:
 
257
        setRotation(RotateBy270);
 
258
        break;
 
259
    case RotateBy270:
 
260
        setRotation(RotateBy0);
 
261
        break;
 
262
    }
 
263
}
 
264
 
 
265
void PresentationView::on_prefetch_timeout()
 
266
{
 
267
    int fromPage = m_currentPage, toPage = m_currentPage;
 
268
 
 
269
    fromPage -= DocumentView::prefetchDistance() / 2;
 
270
    toPage += DocumentView::prefetchDistance();
 
271
 
 
272
    fromPage = fromPage >= 1 ? fromPage : 1;
 
273
    toPage = toPage <= m_numberOfPages ? toPage : m_numberOfPages;
 
274
 
 
275
    for(int index = fromPage - 1; index <= toPage - 1; ++index)
 
276
    {
 
277
        m_pages.at(index)->startRender(true);
 
278
    }
 
279
}
 
280
 
 
281
void PresentationView::on_pages_linkClicked(int page, qreal left, qreal top)
 
282
{
 
283
    Q_UNUSED(left);
 
284
    Q_UNUSED(top);
 
285
 
 
286
    page = page >= 1 ? page : 1;
 
287
    page = page <= m_numberOfPages ? page : m_numberOfPages;
 
288
 
 
289
    jumpToPage(page, true);
 
290
}
 
291
 
 
292
void PresentationView::resizeEvent(QResizeEvent* event)
 
293
{
 
294
    QGraphicsView::resizeEvent(event);
 
295
 
 
296
    prepareScene();
158
297
    prepareView();
159
298
}
160
299
 
161
 
void PresentationView::paintEvent(QPaintEvent*)
162
 
{
163
 
    QPainter painter(this);
164
 
 
165
 
    QColor backgroundColor = PageItem::paperColor();
166
 
 
167
 
    if(PageItem::invertColors())
168
 
    {
169
 
        backgroundColor.setRgb(~backgroundColor.rgb());
170
 
    }
171
 
 
172
 
    painter.fillRect(rect(), QBrush(backgroundColor));
173
 
 
174
 
    if(!m_image.isNull())
175
 
    {
176
 
        painter.drawImage(m_boundingRect.topLeft(), m_image);
177
 
    }
178
 
    else
179
 
    {
180
 
        startRender();
181
 
    }
182
 
}
183
 
 
184
300
void PresentationView::keyPressEvent(QKeyEvent* event)
185
301
{
186
302
    switch(event->key())
212
328
        event->accept();
213
329
        return;
214
330
    case Qt::Key_Return:
215
 
    case Qt::Key_Enter:
216
 
        if(!m_returnToPage.isEmpty())
217
 
        {
218
 
            jumpToPage(m_returnToPage.pop(), false);
219
 
        }
 
331
        returnToPage();
220
332
 
221
333
        event->accept();
222
334
        return;
228
340
        return;
229
341
    }
230
342
 
 
343
    if(event->modifiers() == Qt::ControlModifier && event->key() == Qt::Key_I)
 
344
    {
 
345
        setInvertColors(!invertColors());
 
346
 
 
347
        event->accept();
 
348
        return;
 
349
    }
 
350
 
231
351
    QWidget::keyPressEvent(event);
232
352
}
233
353
 
234
 
void PresentationView::mousePressEvent(QMouseEvent* event)
 
354
void PresentationView::wheelEvent(QWheelEvent* event)
235
355
{
236
 
    foreach(Poppler::LinkGoto* link, m_links)
237
 
    {
238
 
        if(m_normalizedTransform.mapRect(link->linkArea().normalized()).contains(event->pos()))
239
 
        {
240
 
            int page = link->destination().pageNumber();
241
 
 
242
 
            page = page >= 1 ? page : 1;
243
 
            page = page <= m_numberOfPages ? page : m_numberOfPages;
244
 
 
245
 
            jumpToPage(page);
246
 
 
247
 
            event->accept();
248
 
            return;
249
 
        }
250
 
    }
251
 
 
252
 
    QWidget::mousePressEvent(event);
 
356
    if(event->modifiers() == DocumentView::rotateModifiers())
 
357
    {
 
358
        if(event->delta() > 0)
 
359
        {
 
360
            rotateLeft();
 
361
        }
 
362
        else
 
363
        {
 
364
            rotateRight();
 
365
        }
 
366
 
 
367
        event->accept();
 
368
        return;
 
369
    }
 
370
    else if(event->modifiers() == Qt::NoModifier)
 
371
    {
 
372
        if(event->delta() > 0 && m_currentPage != 1)
 
373
        {
 
374
            previousPage();
 
375
 
 
376
            event->accept();
 
377
            return;
 
378
        }
 
379
        else if(event->delta() < 0 && m_currentPage != m_numberOfPages)
 
380
        {
 
381
            nextPage();
 
382
 
 
383
            event->accept();
 
384
            return;
 
385
        }
 
386
    }
 
387
 
 
388
    QGraphicsView::wheelEvent(event);
253
389
}
254
390
 
255
 
void PresentationView::mouseMoveEvent(QMouseEvent* event)
 
391
void PresentationView::prepareScene()
256
392
{
257
 
    foreach(Poppler::LinkGoto* link, m_links)
 
393
    for(int index = 0; index < m_numberOfPages; ++index)
258
394
    {
259
 
        if(m_normalizedTransform.mapRect(link->linkArea().normalized()).contains(event->pos()))
 
395
        PageItem* page = m_pages.at(index);
 
396
        QSizeF size = page->size();
 
397
 
 
398
        qreal visibleWidth = viewport()->width();
 
399
        qreal visibleHeight = viewport()->height();
 
400
 
 
401
        qreal pageWidth = 0.0;
 
402
        qreal pageHeight = 0.0;
 
403
 
 
404
        switch(m_rotation)
260
405
        {
261
 
            setCursor(Qt::PointingHandCursor);
262
 
            QToolTip::showText(event->globalPos(), tr("Go to page %1.").arg(link->destination().pageNumber()));
263
 
 
264
 
            return;
 
406
        default:
 
407
        case RotateBy0:
 
408
        case RotateBy180:
 
409
            pageWidth = physicalDpiX() / 72.0 * size.width();
 
410
            pageHeight = physicalDpiY() / 72.0 * size.height();
 
411
            break;
 
412
        case RotateBy90:
 
413
        case RotateBy270:
 
414
            pageWidth = physicalDpiX() / 72.0 * size.height();
 
415
            pageHeight = physicalDpiY() / 72.0 * size.width();
 
416
            break;
265
417
        }
 
418
 
 
419
        qreal scaleFactor = qMin(visibleWidth / pageWidth, visibleHeight / pageHeight);
 
420
 
 
421
        page->setScaleFactor(scaleFactor);
 
422
        page->setRotation(m_rotation);
266
423
    }
267
 
 
268
 
    unsetCursor();
269
 
    QToolTip::hideText();
270
424
}
271
425
 
272
426
void PresentationView::prepareView()
273
427
{
274
 
    m_mutex->lock();
275
 
 
276
 
    Poppler::Page* page = m_document->page(m_currentPage - 1);
277
 
 
278
 
    QSizeF size = page->pageSizeF();
279
 
 
280
 
    {
281
 
        // links
282
 
 
283
 
        qDeleteAll(m_links);
284
 
 
285
 
        m_links.clear();
286
 
 
287
 
        foreach(Poppler::Link* link, page->links())
288
 
        {
289
 
            if(link->linkType() == Poppler::Link::Goto)
290
 
            {
291
 
                Poppler::LinkGoto* linkGoto = static_cast< Poppler::LinkGoto* >(link);
292
 
 
293
 
                if(!linkGoto->isExternal())
294
 
                {
295
 
                    m_links.append(linkGoto);
296
 
                    continue;
297
 
                }
298
 
            }
299
 
 
300
 
            delete link;
301
 
        }
302
 
    }
303
 
 
304
 
    delete page;
305
 
 
306
 
    m_mutex->unlock();
307
 
 
308
 
    {
309
 
        m_scaleFactor = qMin(width() / size.width(), height() / size.height());
310
 
 
311
 
        m_boundingRect.setLeft(0.5 * (width() - m_scaleFactor * size.width()));
312
 
        m_boundingRect.setTop(0.5 * (height() - m_scaleFactor * size.height()));
313
 
        m_boundingRect.setWidth(m_scaleFactor * size.width());
314
 
        m_boundingRect.setHeight(m_scaleFactor * size.height());
315
 
 
316
 
        m_normalizedTransform.reset();
317
 
        m_normalizedTransform.translate(m_boundingRect.left(), m_boundingRect.top());
318
 
        m_normalizedTransform.scale(m_boundingRect.width(), m_boundingRect.height());
319
 
    }
320
 
 
321
 
    cancelRender();
322
 
 
323
 
    update();
324
 
}
325
 
 
326
 
void PresentationView::render(int index, qreal scaleFactor)
327
 
{
328
 
    QMutexLocker mutexLocker(m_mutex);
329
 
 
330
 
    if(m_render->isCanceled())
331
 
    {
332
 
        return;
333
 
    }
334
 
 
335
 
    Poppler::Page* page = m_document->page(index);
336
 
 
337
 
    QImage image = page->renderToImage(scaleFactor * 72.0, scaleFactor * 72.0);
338
 
 
339
 
    delete page;
340
 
 
341
 
    if(m_render->isCanceled())
342
 
    {
343
 
        return;
344
 
    }
345
 
 
346
 
    emit imageReady(index, scaleFactor, image);
 
428
    for(int index = 0; index < m_numberOfPages; ++index)
 
429
    {
 
430
        PageItem* page = m_pages.at(index);
 
431
 
 
432
        if(index == m_currentPage - 1)
 
433
        {
 
434
            page->setVisible(true);
 
435
 
 
436
            setSceneRect(page->boundingRect().translated(page->pos()));
 
437
        }
 
438
        else
 
439
        {
 
440
            page->setVisible(false);
 
441
 
 
442
            page->cancelRender();
 
443
        }
 
444
 
 
445
    }
 
446
 
 
447
    viewport()->update();
347
448
}