~ubuntu-branches/ubuntu/precise/gwenview/precise-proposed

« back to all changes in this revision

Viewing changes to lib/imageview.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2011-12-15 14:17:54 UTC
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: package-import@ubuntu.com-20111215141754-z043hyx69dulbggf
Tags: upstream-4.7.90
ImportĀ upstreamĀ versionĀ 4.7.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
Gwenview: an image viewer
3
 
Copyright 2007 AurĆ©lien GĆ¢teau <agateau@kde.org>
4
 
 
5
 
This program is free software; you can redistribute it and/or
6
 
modify it under the terms of the GNU General Public License
7
 
as published by the Free Software Foundation; either version 2
8
 
of the License, or (at your option) any later version.
9
 
 
10
 
This program is distributed in the hope that it will be useful,
11
 
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
GNU General Public License for more details.
14
 
 
15
 
You should have received a copy of the GNU General Public License
16
 
along with this program; if not, write to the Free Software
17
 
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18
 
 
19
 
*/
20
 
#include "imageview.moc"
21
 
 
22
 
// Qt
23
 
#include <QApplication>
24
 
#include <QPainter>
25
 
#include <QPaintEvent>
26
 
#include <QPointer>
27
 
#include <QScrollBar>
28
 
 
29
 
// KDE
30
 
#include <kdebug.h>
31
 
 
32
 
// Local
33
 
#include "abstractimageviewtool.h"
34
 
#include "imagescaler.h"
35
 
 
36
 
 
37
 
namespace Gwenview {
38
 
 
39
 
#undef ENABLE_LOG
40
 
#undef LOG
41
 
//#define ENABLE_LOG
42
 
#ifdef ENABLE_LOG
43
 
#define LOG(x) kDebug() << x
44
 
#else
45
 
#define LOG(x) ;
46
 
#endif
47
 
 
48
 
struct ImageViewPrivate {
49
 
        ImageView* mView;
50
 
        QPixmap mBackgroundTexture;
51
 
        QWidget* mViewport;
52
 
        ImageView::AlphaBackgroundMode mAlphaBackgroundMode;
53
 
        QColor mAlphaBackgroundColor;
54
 
        bool mEnlargeSmallerImages;
55
 
        Document::Ptr mDocument;
56
 
        qreal mZoom;
57
 
        bool mZoomToFit;
58
 
        QPixmap mCurrentBuffer;
59
 
        QPixmap mAlternateBuffer;
60
 
        ImageScaler* mScaler;
61
 
        QPointer<AbstractImageViewTool> mTool;
62
 
        QPointer<AbstractImageViewTool> mDefaultTool;
63
 
        bool mInsideSetZoom;
64
 
 
65
 
 
66
 
        void createBackgroundTexture() {
67
 
                mBackgroundTexture = QPixmap(32, 32);
68
 
                QPainter painter(&mBackgroundTexture);
69
 
                painter.fillRect(mBackgroundTexture.rect(), QColor(128, 128, 128));
70
 
                QColor light = QColor(192, 192, 192);
71
 
                painter.fillRect(0, 0, 16, 16, light);
72
 
                painter.fillRect(16, 16, 16, 16, light);
73
 
        }
74
 
 
75
 
 
76
 
        QSize visibleImageSize() const {
77
 
                if (!mDocument) {
78
 
                        return QSize();
79
 
                }
80
 
                QSize size;
81
 
                qreal zoom;
82
 
                if (mZoomToFit) {
83
 
                        zoom = mView->computeZoomToFit();
84
 
                } else {
85
 
                        zoom = mZoom;
86
 
                }
87
 
 
88
 
                size = mDocument->size() * zoom;
89
 
                size = size.boundedTo(mViewport->size());
90
 
 
91
 
                return size;
92
 
        }
93
 
 
94
 
 
95
 
        void drawAlphaBackground(QPainter* painter, const QRect& viewportRect, const QPoint& zoomedImageTopLeft) {
96
 
                if (mAlphaBackgroundMode == ImageView::AlphaBackgroundCheckBoard) {
97
 
                        QPoint textureOffset(
98
 
                                zoomedImageTopLeft.x() % mBackgroundTexture.width(),
99
 
                                zoomedImageTopLeft.y() % mBackgroundTexture.height()
100
 
                                );
101
 
                        painter->drawTiledPixmap(
102
 
                                viewportRect,
103
 
                                mBackgroundTexture,
104
 
                                textureOffset);
105
 
                } else {
106
 
                        painter->fillRect(viewportRect, mAlphaBackgroundColor);
107
 
                }
108
 
        }
109
 
 
110
 
        void createBuffer() {
111
 
                QSize size = mView->size();
112
 
                if (size == mCurrentBuffer.size()) {
113
 
                        return;
114
 
                }
115
 
                if (!size.isValid()) {
116
 
                        mAlternateBuffer = QPixmap();
117
 
                        mCurrentBuffer = QPixmap();
118
 
                        return;
119
 
                }
120
 
 
121
 
                mAlternateBuffer = QPixmap(size);
122
 
                QPainter painter(&mAlternateBuffer);
123
 
                QColor bgColor = mViewport->palette().color(mViewport->backgroundRole());
124
 
                painter.fillRect(mAlternateBuffer.rect(), bgColor);
125
 
                painter.drawPixmap(0, 0, mCurrentBuffer);
126
 
                qSwap(mAlternateBuffer, mCurrentBuffer);
127
 
 
128
 
                mAlternateBuffer = QPixmap();
129
 
        }
130
 
 
131
 
 
132
 
        int hScroll() const {
133
 
                if (mZoomToFit) {
134
 
                        return 0;
135
 
                } else {
136
 
                        return mView->horizontalScrollBar()->value();
137
 
                }
138
 
        }
139
 
 
140
 
        int vScroll() const {
141
 
                if (mZoomToFit) {
142
 
                        return 0;
143
 
                } else {
144
 
                        return mView->verticalScrollBar()->value();
145
 
                }
146
 
        }
147
 
 
148
 
        QRect mapViewportToZoomedImage(const QRect& viewportRect) {
149
 
                QPoint offset = mView->imageOffset();
150
 
                QRect rect = QRect(
151
 
                        viewportRect.x() + hScroll() - offset.x(),
152
 
                        viewportRect.y() + vScroll() - offset.y(),
153
 
                        viewportRect.width(),
154
 
                        viewportRect.height()
155
 
                );
156
 
 
157
 
                return rect;
158
 
        }
159
 
 
160
 
 
161
 
        void setScalerRegionToVisibleRect() {
162
 
                QRect rect = mapViewportToZoomedImage(mViewport->rect());
163
 
                mScaler->setDestinationRegion(QRegion(rect));
164
 
        }
165
 
 
166
 
 
167
 
        void forceBufferRecreation() {
168
 
                mCurrentBuffer = QPixmap();
169
 
                createBuffer();
170
 
                setScalerRegionToVisibleRect();
171
 
        }
172
 
 
173
 
 
174
 
        void startAnimationIfNecessary() {
175
 
                if (mDocument && mView->isVisible()) {
176
 
                        mDocument->startAnimation();
177
 
                }
178
 
        }
179
 
 
180
 
 
181
 
        // At least gcc 3.4.6 on FreeBSD requires a default constructor.
182
 
        ImageViewPrivate() { }
183
 
};
184
 
 
185
 
 
186
 
ImageView::ImageView(QWidget* parent)
187
 
: QAbstractScrollArea(parent)
188
 
, d(new ImageViewPrivate)
189
 
{
190
 
        d->mAlphaBackgroundMode = AlphaBackgroundCheckBoard;
191
 
        d->mAlphaBackgroundColor = Qt::black;
192
 
 
193
 
        d->mView = this;
194
 
        d->mZoom = 1.;
195
 
        d->mZoomToFit = true;
196
 
        d->createBackgroundTexture();
197
 
        setFrameShape(QFrame::NoFrame);
198
 
        setBackgroundRole(QPalette::Base);
199
 
        d->mViewport = new QWidget();
200
 
        setViewport(d->mViewport);
201
 
        d->mViewport->setMouseTracking(true);
202
 
        horizontalScrollBar()->setSingleStep(16);
203
 
        verticalScrollBar()->setSingleStep(16);
204
 
        d->mScaler = new ImageScaler(this);
205
 
        d->mInsideSetZoom = false;
206
 
 
207
 
        if (QApplication::isRightToLeft()) {
208
 
                // Ensure we don't get weird behavior in RightToleft mode
209
 
                // See bug #210058
210
 
                horizontalScrollBar()->setLayoutDirection(Qt::LeftToRight);
211
 
        }
212
 
        connect(d->mScaler, SIGNAL(scaledRect(int, int, const QImage&)), 
213
 
                SLOT(updateFromScaler(int, int, const QImage&)) );
214
 
}
215
 
 
216
 
ImageView::~ImageView() {
217
 
        delete d;
218
 
}
219
 
 
220
 
 
221
 
void ImageView::setAlphaBackgroundMode(AlphaBackgroundMode mode) {
222
 
        d->mAlphaBackgroundMode = mode;
223
 
        if (d->mDocument && d->mDocument->hasAlphaChannel()) {
224
 
                d->forceBufferRecreation();
225
 
        }
226
 
}
227
 
 
228
 
 
229
 
void ImageView::setAlphaBackgroundColor(const QColor& color) {
230
 
        d->mAlphaBackgroundColor = color;
231
 
        if (d->mDocument && d->mDocument->hasAlphaChannel()) {
232
 
                d->forceBufferRecreation();
233
 
        }
234
 
}
235
 
 
236
 
 
237
 
void ImageView::setEnlargeSmallerImages(bool value) {
238
 
        d->mEnlargeSmallerImages = value;
239
 
        if (d->mZoomToFit) {
240
 
                setZoom(computeZoomToFit());
241
 
        }
242
 
}
243
 
 
244
 
 
245
 
void ImageView::setDocument(Document::Ptr document) {
246
 
        if (d->mDocument) {
247
 
                d->mDocument->stopAnimation();
248
 
                disconnect(d->mDocument.data(), 0, this, 0);
249
 
        }
250
 
        d->mDocument = document;
251
 
        if (!document) {
252
 
                d->mViewport->update();
253
 
                return;
254
 
        }
255
 
 
256
 
        connect(d->mDocument.data(), SIGNAL(metaInfoLoaded(const KUrl&)),
257
 
                SLOT(slotDocumentMetaInfoLoaded()) );
258
 
        connect(d->mDocument.data(), SIGNAL(isAnimatedUpdated()),
259
 
                SLOT(slotDocumentIsAnimatedUpdated()) );
260
 
 
261
 
        const Document::LoadingState state = d->mDocument->loadingState();
262
 
        if (state == Document::MetaInfoLoaded || state == Document::Loaded) {
263
 
                slotDocumentMetaInfoLoaded();
264
 
        }
265
 
}
266
 
 
267
 
 
268
 
void ImageView::slotDocumentMetaInfoLoaded() {
269
 
        if (d->mDocument->size().isValid()) {
270
 
                finishSetDocument();
271
 
        } else {
272
 
                // Could not retrieve image size from meta info, we need to load the
273
 
                // full image now.
274
 
                connect(d->mDocument.data(), SIGNAL(loaded(const KUrl&)),
275
 
                        SLOT(finishSetDocument()) );
276
 
                d->mDocument->startLoadingFullImage();
277
 
        }
278
 
}
279
 
 
280
 
 
281
 
void ImageView::finishSetDocument() {
282
 
        if (!d->mDocument->size().isValid()) {
283
 
                kError() << "No valid image size available, this should not happen!";
284
 
                return;
285
 
        }
286
 
 
287
 
        d->createBuffer();
288
 
        d->mScaler->setDocument(d->mDocument);
289
 
 
290
 
        connect(d->mDocument.data(), SIGNAL(imageRectUpdated(const QRect&)),
291
 
                SLOT(updateImageRect(const QRect&)) );
292
 
 
293
 
        if (d->mZoomToFit) {
294
 
                // Set the zoom to an invalid value to make sure setZoom() does not
295
 
                // return early because the new zoom is the same as the old zoom.
296
 
                d->mZoom = -1;
297
 
                setZoom(computeZoomToFit());
298
 
        } else {
299
 
                QRect rect(QPoint(0, 0), d->mDocument->size());
300
 
                updateImageRect(rect);
301
 
                updateScrollBars();
302
 
        }
303
 
 
304
 
        d->startAnimationIfNecessary();
305
 
        d->mViewport->update();
306
 
}
307
 
 
308
 
 
309
 
Document::Ptr ImageView::document() const {
310
 
        return d->mDocument;
311
 
}
312
 
 
313
 
 
314
 
void ImageView::slotDocumentIsAnimatedUpdated() {
315
 
        d->startAnimationIfNecessary();
316
 
}
317
 
 
318
 
 
319
 
void ImageView::updateImageRect(const QRect& imageRect) {
320
 
        LOG("imageRect" << imageRect);
321
 
        QRect viewportRect = mapToViewport(imageRect);
322
 
        viewportRect = viewportRect.intersected(d->mViewport->rect());
323
 
        if (viewportRect.isEmpty()) {
324
 
                return;
325
 
        }
326
 
 
327
 
        if (d->mZoomToFit) {
328
 
                setZoom(computeZoomToFit());
329
 
        }
330
 
        d->setScalerRegionToVisibleRect();
331
 
        d->mViewport->update();
332
 
}
333
 
 
334
 
 
335
 
void ImageView::paintEvent(QPaintEvent* event) {
336
 
        QPainter painter(d->mViewport);
337
 
        painter.setClipRect(event->rect());
338
 
 
339
 
        painter.setCompositionMode(QPainter::CompositionMode_Source);
340
 
        painter.drawPixmap(0, 0, d->mCurrentBuffer);
341
 
 
342
 
        painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
343
 
        if (d->mTool) {
344
 
                d->mTool->paint(&painter);
345
 
        }
346
 
}
347
 
 
348
 
void ImageView::resizeEvent(QResizeEvent*) {
349
 
        if (d->mZoomToFit) {
350
 
                // Bypass "same zoom" test: even if the zoom is the same we want a new
351
 
                // buffer of the correct size (and if switching from/to fullscreen, using
352
 
                // the correct background) to be created
353
 
                d->mZoom = -1;
354
 
                setZoom(computeZoomToFit());
355
 
                // Make sure one can't use mousewheel in zoom-to-fit mode
356
 
                horizontalScrollBar()->setRange(0, 0);
357
 
                verticalScrollBar()->setRange(0, 0);
358
 
        } else {
359
 
                d->createBuffer();
360
 
                updateScrollBars();
361
 
                d->setScalerRegionToVisibleRect();
362
 
        }
363
 
}
364
 
 
365
 
QPoint ImageView::imageOffset() const {
366
 
        QSize size = d->visibleImageSize();
367
 
        int left = qMax( (d->mViewport->width() - size.width()) / 2, 0);
368
 
        int top = qMax( (d->mViewport->height() - size.height()) / 2, 0);
369
 
 
370
 
        return QPoint(left, top);
371
 
}
372
 
 
373
 
 
374
 
void ImageView::setZoom(qreal zoom, const QPoint& _center) {
375
 
        if (!d->mDocument) {
376
 
                return;
377
 
        }
378
 
 
379
 
        qreal oldZoom = d->mZoom;
380
 
        if (qAbs(zoom - oldZoom) < 0.001) {
381
 
                return;
382
 
        }
383
 
        // Get offset *before* setting mZoom, otherwise we get the new offset
384
 
        QPoint oldOffset = imageOffset();
385
 
        d->mZoom = zoom;
386
 
 
387
 
        QPoint center;
388
 
        if (_center == QPoint(-1, -1)) {
389
 
                center = QPoint(d->mViewport->width() / 2, d->mViewport->height() / 2);
390
 
        } else {
391
 
                center = _center;
392
 
        }
393
 
 
394
 
        // If we zoom more than twice, then assume the user wants to see the real
395
 
        // pixels, for example to fine tune a crop operation
396
 
        if (d->mZoom < 2.) {
397
 
                d->mScaler->setTransformationMode(Qt::SmoothTransformation);
398
 
        } else {
399
 
                d->mScaler->setTransformationMode(Qt::FastTransformation);
400
 
        }
401
 
 
402
 
        d->createBuffer();
403
 
        d->mInsideSetZoom = true;
404
 
 
405
 
        /*
406
 
        We want to keep the point at viewport coordinates "center" at the same
407
 
        position after zooming. The coordinates of this point in image coordinates
408
 
        can be expressed like this:
409
 
 
410
 
                              oldScroll + center
411
 
        imagePointAtOldZoom = ------------------
412
 
                                   oldZoom
413
 
 
414
 
                           scroll + center
415
 
        imagePointAtZoom = ---------------
416
 
                                zoom
417
 
 
418
 
        So we want:
419
 
 
420
 
            imagePointAtOldZoom = imagePointAtZoom
421
 
 
422
 
            oldScroll + center   scroll + center
423
 
        <=> ------------------ = ---------------
424
 
                  oldZoom             zoom
425
 
 
426
 
                      zoom
427
 
        <=> scroll = ------- (oldScroll + center) - center
428
 
                     oldZoom
429
 
        */
430
 
 
431
 
        /*
432
 
        Compute oldScroll
433
 
        It's useless to take the new offset in consideration because if a direction
434
 
        of the new offset is not 0, we won't be able to center on a specific point
435
 
        in that direction.
436
 
        */
437
 
        QPointF oldScroll = QPointF(d->hScroll(), d->vScroll()) - oldOffset;
438
 
 
439
 
        QPointF scroll = (zoom / oldZoom) * (oldScroll + center) - center;
440
 
 
441
 
        updateScrollBars();
442
 
        horizontalScrollBar()->setValue(int(scroll.x()));
443
 
        verticalScrollBar()->setValue(int(scroll.y()));
444
 
        d->mInsideSetZoom = false;
445
 
 
446
 
        d->mScaler->setZoom(d->mZoom);
447
 
        d->setScalerRegionToVisibleRect();
448
 
        emit zoomChanged(d->mZoom);
449
 
}
450
 
 
451
 
qreal ImageView::zoom() const {
452
 
        return d->mZoom;
453
 
}
454
 
 
455
 
bool ImageView::zoomToFit() const {
456
 
        return d->mZoomToFit;
457
 
}
458
 
 
459
 
void ImageView::setZoomToFit(bool on) {
460
 
        d->mZoomToFit = on;
461
 
        if (d->mZoomToFit) {
462
 
                setZoom(computeZoomToFit());
463
 
        }
464
 
}
465
 
 
466
 
void ImageView::updateScrollBars() {
467
 
        if (!d->mDocument || d->mZoomToFit) {
468
 
                setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
469
 
                setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
470
 
                return;
471
 
        }
472
 
        setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
473
 
        setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
474
 
 
475
 
        int max;
476
 
        int width = d->mViewport->width();
477
 
        int height = d->mViewport->height();
478
 
 
479
 
        max = qMax(0, int(d->mDocument->width() * d->mZoom) - width);
480
 
        horizontalScrollBar()->setRange(0, max);
481
 
        horizontalScrollBar()->setPageStep(width);
482
 
 
483
 
        max = qMax(0, int(d->mDocument->height() * d->mZoom) - height);
484
 
        verticalScrollBar()->setRange(0, max);
485
 
        verticalScrollBar()->setPageStep(height);
486
 
}
487
 
 
488
 
 
489
 
void ImageView::scrollContentsBy(int dx, int dy) {
490
 
        if (d->mInsideSetZoom) {
491
 
                // Do not scroll anything: since we are zooming the whole viewport will
492
 
                // eventually be repainted
493
 
                return;
494
 
        }
495
 
        // Scroll existing
496
 
        {
497
 
                if (d->mAlternateBuffer.size() != d->mCurrentBuffer.size()) {
498
 
                        d->mAlternateBuffer = QPixmap(d->mCurrentBuffer.size());
499
 
                }
500
 
                QPainter painter(&d->mAlternateBuffer);
501
 
                painter.drawPixmap(dx, dy, d->mCurrentBuffer);
502
 
        }
503
 
        qSwap(d->mCurrentBuffer, d->mAlternateBuffer);
504
 
 
505
 
        // Scale missing parts
506
 
        QRegion region;
507
 
        int posX = d->hScroll();
508
 
        int posY = d->vScroll();
509
 
        int width = d->mViewport->width();
510
 
        int height = d->mViewport->height();
511
 
 
512
 
        QRect rect;
513
 
        if (dx > 0) {
514
 
                rect = QRect(posX, posY, dx, height);
515
 
        } else {
516
 
                rect = QRect(posX + width + dx, posY, -dx, height);
517
 
        }
518
 
        region |= rect;
519
 
 
520
 
        if (dy > 0) {
521
 
                rect = QRect(posX, posY, width, dy);
522
 
        } else {
523
 
                rect = QRect(posX, posY + height + dy, width, -dy);
524
 
        }
525
 
        region |= rect;
526
 
 
527
 
        d->mScaler->setDestinationRegion(region);
528
 
        d->mViewport->update();
529
 
}
530
 
 
531
 
 
532
 
void ImageView::updateFromScaler(int zoomedImageLeft, int zoomedImageTop, const QImage& image) {
533
 
        LOG("");
534
 
        QPoint offset = imageOffset();
535
 
        int viewportLeft = offset.x() + zoomedImageLeft - d->hScroll();
536
 
        int viewportTop = offset.y() + zoomedImageTop - d->vScroll();
537
 
 
538
 
        {
539
 
                QPainter painter(&d->mCurrentBuffer);
540
 
                if (d->mDocument->hasAlphaChannel()) {
541
 
                        d->drawAlphaBackground(
542
 
                                &painter, QRect(viewportLeft, viewportTop, image.width(), image.height()),
543
 
                                QPoint(zoomedImageLeft, zoomedImageTop)
544
 
                                );
545
 
                } else {
546
 
                        painter.setCompositionMode(QPainter::CompositionMode_Source);
547
 
                }
548
 
                painter.drawImage(viewportLeft, viewportTop, image);
549
 
 
550
 
                // Clear borders. We do it here which is quite late, but this way we ensure
551
 
                // borders are not cleared until the new image is ready. Meanwhile we
552
 
                // continue to show the previous image. If we cleared the borders earlier
553
 
                // we could end up clearing the borders on the previous image, leading to
554
 
                // a temporary cropped result
555
 
                QColor bgColor = d->mViewport->palette().color(d->mViewport->backgroundRole());
556
 
                QRegion region = d->mCurrentBuffer.rect();
557
 
                region -= QRect(imageOffset(), d->mDocument->size() * d->mZoom);
558
 
                Q_FOREACH(const QRect& rect, region.rects()) {
559
 
                        painter.fillRect(rect, bgColor);
560
 
                }
561
 
                /*
562
 
                // Debug rects
563
 
                QPen pen(Qt::red);
564
 
                pen.setStyle(Qt::DotLine);
565
 
                painter.setPen(pen);
566
 
                painter.drawRect(viewportLeft, viewportTop, image.width() - 1, image.height() - 1);
567
 
                */
568
 
        }
569
 
        d->mViewport->update();
570
 
}
571
 
 
572
 
 
573
 
void ImageView::setCurrentTool(AbstractImageViewTool* tool) {
574
 
        if (d->mTool) {
575
 
                d->mTool->toolDeactivated();
576
 
        }
577
 
        d->mTool = tool ? QPointer<AbstractImageViewTool>(tool) : d->mDefaultTool;
578
 
        if (d->mTool) {
579
 
                d->mTool->toolActivated();
580
 
        }
581
 
        d->mViewport->update();
582
 
}
583
 
 
584
 
 
585
 
AbstractImageViewTool* ImageView::currentTool() const {
586
 
        return d->mTool;
587
 
}
588
 
 
589
 
 
590
 
void ImageView::setDefaultTool(AbstractImageViewTool* tool) {
591
 
        d->mDefaultTool = tool;
592
 
        if (!d->mTool && tool) {
593
 
                setCurrentTool(tool);
594
 
        }
595
 
}
596
 
 
597
 
 
598
 
AbstractImageViewTool* ImageView::defaultTool() const {
599
 
        return d->mDefaultTool;
600
 
}
601
 
 
602
 
 
603
 
QPoint ImageView::mapToViewport(const QPoint& src) const {
604
 
        QPoint dst(int(src.x() * d->mZoom), int(src.y() * d->mZoom));
605
 
 
606
 
        dst += imageOffset();
607
 
 
608
 
        dst.rx() -= d->hScroll();
609
 
        dst.ry() -= d->vScroll();
610
 
 
611
 
        return dst;
612
 
}
613
 
 
614
 
 
615
 
QPointF ImageView::mapToViewportF(const QPointF& src) const {
616
 
        QPointF dst(src.x() * d->mZoom, src.y() * d->mZoom);
617
 
 
618
 
        dst += imageOffset();
619
 
 
620
 
        dst.rx() -= d->hScroll();
621
 
        dst.ry() -= d->vScroll();
622
 
 
623
 
        return dst;
624
 
}
625
 
 
626
 
 
627
 
QRect ImageView::mapToViewport(const QRect& src) const {
628
 
        QRect dst(
629
 
                mapToViewport(src.topLeft()),
630
 
                mapToViewport(src.bottomRight())
631
 
        );
632
 
        return dst;
633
 
}
634
 
 
635
 
 
636
 
QRectF ImageView::mapToViewportF(const QRectF& src) const {
637
 
        QRectF dst(
638
 
                mapToViewportF(src.topLeft()),
639
 
                mapToViewportF(src.bottomRight())
640
 
        );
641
 
        return dst;
642
 
}
643
 
 
644
 
 
645
 
QPoint ImageView::mapToImage(const QPoint& src) const {
646
 
        QPoint dst = src;
647
 
        
648
 
        dst.rx() += d->hScroll();
649
 
        dst.ry() += d->vScroll();
650
 
 
651
 
        dst -= imageOffset();
652
 
 
653
 
        return QPoint(int(dst.x() / d->mZoom), int(dst.y() / d->mZoom));
654
 
}
655
 
 
656
 
 
657
 
QPointF ImageView::mapToImageF(const QPointF& src) const {
658
 
        QPointF dst = src;
659
 
 
660
 
        dst.rx() += d->hScroll();
661
 
        dst.ry() += d->vScroll();
662
 
 
663
 
        dst -= imageOffset();
664
 
 
665
 
        return dst / d->mZoom;
666
 
}
667
 
 
668
 
 
669
 
QRect ImageView::mapToImage(const QRect& src) const {
670
 
        QRect dst(
671
 
                mapToImage(src.topLeft()),
672
 
                mapToImage(src.bottomRight())
673
 
        );
674
 
        return dst;
675
 
}
676
 
 
677
 
 
678
 
QRectF ImageView::mapToImageF(const QRectF& src) const {
679
 
        QRectF dst(
680
 
                mapToImageF(src.topLeft()),
681
 
                mapToImageF(src.bottomRight())
682
 
        );
683
 
        return dst;
684
 
}
685
 
 
686
 
 
687
 
qreal ImageView::computeZoomToFit() const {
688
 
        qreal zoom = qMin(computeZoomToFitWidth(), computeZoomToFitHeight());
689
 
 
690
 
        if (!d->mEnlargeSmallerImages) {
691
 
                zoom = qMin(zoom, qreal(1.0));
692
 
        }
693
 
 
694
 
        return zoom;
695
 
}
696
 
 
697
 
 
698
 
qreal ImageView::computeZoomToFitWidth() const {
699
 
        if (!d->mDocument || !d->mDocument->size().isValid()) {
700
 
                return 1.;
701
 
        }
702
 
        return qreal(d->mViewport->width()) / d->mDocument->width();
703
 
}
704
 
 
705
 
 
706
 
qreal ImageView::computeZoomToFitHeight() const {
707
 
        if (!d->mDocument || !d->mDocument->size().isValid()) {
708
 
                return 1.;
709
 
        }
710
 
        return qreal(d->mViewport->height()) / d->mDocument->height();
711
 
}
712
 
 
713
 
 
714
 
void ImageView::showEvent(QShowEvent* event) {
715
 
        QAbstractScrollArea::showEvent(event);
716
 
        d->startAnimationIfNecessary();
717
 
}
718
 
 
719
 
 
720
 
void ImageView::hideEvent(QHideEvent* event) {
721
 
        QAbstractScrollArea::hideEvent(event);
722
 
        if (d->mDocument) {
723
 
                d->mDocument->stopAnimation();
724
 
        }
725
 
}
726
 
 
727
 
 
728
 
void ImageView::mousePressEvent(QMouseEvent* event) {
729
 
        if (d->mTool) {
730
 
                d->mTool->mousePressEvent(event);
731
 
        }
732
 
}
733
 
 
734
 
 
735
 
void ImageView::mouseMoveEvent(QMouseEvent* event) {
736
 
        if (d->mTool) {
737
 
                d->mTool->mouseMoveEvent(event);
738
 
        }
739
 
}
740
 
 
741
 
 
742
 
void ImageView::mouseReleaseEvent(QMouseEvent* event) {
743
 
        if (d->mTool) {
744
 
                d->mTool->mouseReleaseEvent(event);
745
 
        }
746
 
}
747
 
 
748
 
 
749
 
void ImageView::wheelEvent(QWheelEvent* event) {
750
 
        if (d->mTool) {
751
 
                d->mTool->wheelEvent(event);
752
 
        }
753
 
}
754
 
 
755
 
 
756
 
void ImageView::keyPressEvent(QKeyEvent* event) {
757
 
        if (d->mTool) {
758
 
                d->mTool->keyPressEvent(event);
759
 
        }
760
 
        QAbstractScrollArea::keyPressEvent(event);
761
 
}
762
 
 
763
 
 
764
 
void ImageView::keyReleaseEvent(QKeyEvent* event) {
765
 
        if (d->mTool) {
766
 
                d->mTool->keyReleaseEvent(event);
767
 
        }
768
 
        QAbstractScrollArea::keyReleaseEvent(event);
769
 
}
770
 
 
771
 
 
772
 
} // namespace