diff --git a/lib/documentview/abstractimageview.cpp b/lib/documentview/abstractimageview.cpp index 773fcba4..91738a06 100644 --- a/lib/documentview/abstractimageview.cpp +++ b/lib/documentview/abstractimageview.cpp @@ -1,355 +1,370 @@ // vim: set tabstop=4 shiftwidth=4 noexpandtab: /* Gwenview: an image viewer Copyright 2011 Aurélien Gâteau 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA. */ // Self #include "abstractimageview.moc" // Local // KDE #include #include // Qt #include #include namespace Gwenview { static const int UNIT_STEP = 16; struct AbstractImageViewPrivate { enum Verbosity { Silent, Notify }; AbstractImageView* q; Document::Ptr mDocument; + + bool mEnlargeSmallerImages; + qreal mZoom; bool mZoomToFit; QPointF mImageOffset; QPointF mScrollPos; QPointF mLastDragPos; void adjustImageOffset(Verbosity verbosity = Notify) { QSizeF zoomedDocSize = q->documentSize() * mZoom; QSizeF viewSize = q->boundingRect().size(); QPointF offset( qMax((viewSize.width() - zoomedDocSize.width()) / 2, 0.), qMax((viewSize.height() - zoomedDocSize.height()) / 2, 0.) ); if (offset != mImageOffset) { mImageOffset = offset; if (verbosity == Notify) { q->onImageOffsetChanged(); } } } void adjustScrollPos(Verbosity verbosity = Notify) { setScrollPos(mScrollPos, verbosity); } void setScrollPos(const QPointF& _newPos, Verbosity verbosity = Notify) { QSizeF zoomedDocSize = q->documentSize() * mZoom; QSizeF viewSize = q->boundingRect().size(); QPointF newPos( qBound(0., _newPos.x(), zoomedDocSize.width() - viewSize.width()), qBound(0., _newPos.y(), zoomedDocSize.height() - viewSize.height()) ); if (newPos != mScrollPos) { QPointF oldPos = mScrollPos; mScrollPos = newPos; if (verbosity == Notify) { q->onScrollPosChanged(oldPos); } } } }; AbstractImageView::AbstractImageView(QGraphicsItem* parent) : QGraphicsWidget(parent) , d(new AbstractImageViewPrivate) { d->q = this; + d->mEnlargeSmallerImages = false; d->mZoom = 1; d->mZoomToFit = true; d->mImageOffset = QPointF(0, 0); d->mScrollPos = QPointF(0, 0); setCursor(Qt::OpenHandCursor); setFocusPolicy(Qt::WheelFocus); setFlag(ItemIsSelectable); } AbstractImageView::~AbstractImageView() { delete d; } Document::Ptr AbstractImageView::document() const { return d->mDocument; } void AbstractImageView::setDocument(Document::Ptr doc) { d->mDocument = doc; loadFromDocument(); if (d->mZoomToFit) { setZoom(computeZoomToFit()); } } QSizeF AbstractImageView::documentSize() const { return d->mDocument ? d->mDocument->size() : QSizeF(); } qreal AbstractImageView::zoom() const { return d->mZoom; } -void AbstractImageView::setZoom(qreal zoom, const QPointF& _center) { - qreal oldZoom = d->mZoom; - if (qFuzzyCompare(zoom, oldZoom)) { +void AbstractImageView::setZoom(qreal zoom, const QPointF& _center, AbstractImageView::UpdateType updateType) { + if (updateType == UpdateIfNecessary && qFuzzyCompare(zoom, d->mZoom)) { return; } + qreal oldZoom = d->mZoom; d->mZoom = zoom; QPointF center; if (_center == QPointF(-1, -1)) { center = boundingRect().center(); } else { center = _center; } /* We want to keep the point at viewport coordinates "center" at the same position after zooming. The coordinates of this point in image coordinates can be expressed like this: oldScroll + center imagePointAtOldZoom = ------------------ oldZoom scroll + center imagePointAtZoom = --------------- zoom So we want: imagePointAtOldZoom = imagePointAtZoom oldScroll + center scroll + center <=> ------------------ = --------------- oldZoom zoom zoom <=> scroll = ------- (oldScroll + center) - center oldZoom */ /* Compute oldScroll It's useless to take the new offset in consideration because if a direction of the new offset is not 0, we won't be able to center on a specific point in that direction. */ QPointF oldScroll = scrollPos() - imageOffset(); QPointF scroll = (zoom / oldZoom) * (oldScroll + center) - center; d->adjustImageOffset(AbstractImageViewPrivate::Silent); d->setScrollPos(scroll, AbstractImageViewPrivate::Silent); onZoomChanged(); zoomChanged(d->mZoom); } bool AbstractImageView::zoomToFit() const { return d->mZoomToFit; } void AbstractImageView::setZoomToFit(bool on) { d->mZoomToFit = on; if (on) { setZoom(computeZoomToFit()); } // We do not set zoom to 1 if zoomToFit is off, this is up to the code // calling us. It may went to zoom to some other level and/or to zoom on // a particular position zoomToFitChanged(d->mZoomToFit); } void AbstractImageView::resizeEvent(QGraphicsSceneResizeEvent* event) { QGraphicsWidget::resizeEvent(event); if (d->mZoomToFit) { setZoom(computeZoomToFit()); } else { d->adjustImageOffset(); d->adjustScrollPos(); } } qreal AbstractImageView::computeZoomToFit() const { QSizeF docSize = documentSize(); if (docSize.isEmpty()) { return 1; } QSizeF viewSize = boundingRect().size(); qreal fitWidth = viewSize.width() / docSize.width(); qreal fitHeight = viewSize.height() / docSize.height(); - return qMin(fitWidth, fitHeight); + qreal fit = qMin(fitWidth, fitHeight); + if (!d->mEnlargeSmallerImages) { + fit = qMin(fit, 1.); + } + return fit; } void AbstractImageView::mousePressEvent(QGraphicsSceneMouseEvent* event) { QGraphicsItem::mousePressEvent(event); setCursor(Qt::ClosedHandCursor); d->mLastDragPos = event->pos(); } void AbstractImageView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { QGraphicsItem::mouseMoveEvent(event); QPointF mousePos = event->pos(); QPointF newScrollPos = d->mScrollPos + d->mLastDragPos - mousePos; // Wrap mouse pos qreal maxWidth = boundingRect().width(); qreal maxHeight = boundingRect().height(); // We need a margin because if the window is maximized, the mouse may not // be able to go past the bounding rect. // The mouse get placed 1 pixel before/after the margin to avoid getting // considered as needing to wrap the other way in next mouseMoveEvent // (because we don't check the move vector) const int margin = 5; if (mousePos.x() <= margin) { mousePos.setX(maxWidth - margin - 1); } else if (mousePos.x() >= maxWidth - margin) { mousePos.setX(margin + 1); } if (mousePos.y() <= margin) { mousePos.setY(maxHeight - margin - 1); } else if (mousePos.y() >= maxHeight - margin) { mousePos.setY(margin + 1); } // Set mouse pos (Hackish translation to screen coords!) QPointF screenDelta = event->screenPos() - event->pos(); QCursor::setPos((mousePos + screenDelta).toPoint()); d->mLastDragPos = mousePos; d->setScrollPos(newScrollPos); } void AbstractImageView::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { QGraphicsItem::mouseReleaseEvent(event); setCursor(Qt::OpenHandCursor); } void AbstractImageView::keyPressEvent(QKeyEvent* event) { QPointF delta(0, 0); qreal pageStep = boundingRect().height(); qreal unitStep; if (event->modifiers() & Qt::ShiftModifier) { unitStep = pageStep / 2; } else { unitStep = UNIT_STEP; } switch (event->key()) { case Qt::Key_Left: delta.setX(-unitStep); break; case Qt::Key_Right: delta.setX(unitStep); break; case Qt::Key_Up: delta.setY(-unitStep); break; case Qt::Key_Down: delta.setY(unitStep); break; case Qt::Key_PageUp: delta.setY(-pageStep); break; case Qt::Key_PageDown: delta.setY(pageStep); break; case Qt::Key_Home: d->setScrollPos(QPointF(d->mScrollPos.x(), 0)); return; case Qt::Key_End: d->setScrollPos(QPointF(d->mScrollPos.x(), documentSize().height() * zoom())); return; default: return; } d->setScrollPos(d->mScrollPos + delta); } QPointF AbstractImageView::imageOffset() const { return d->mImageOffset; } QPointF AbstractImageView::scrollPos() const { return d->mScrollPos; } QPointF AbstractImageView::mapToView(const QPointF& imagePos) const { return imagePos * d->mZoom + d->mImageOffset - d->mScrollPos; } QPoint AbstractImageView::mapToView(const QPoint& imagePos) const { return mapToView(QPointF(imagePos)).toPoint(); } QRectF AbstractImageView::mapToView(const QRectF& imageRect) const { return QRectF( mapToView(imageRect.topLeft()), imageRect.size() * zoom() ); } QRect AbstractImageView::mapToView(const QRect& imageRect) const { return QRect( mapToView(imageRect.topLeft()), imageRect.size() * zoom() ); } QPointF AbstractImageView::mapToImage(const QPointF& viewPos) const { return (viewPos - d->mImageOffset + d->mScrollPos) / d->mZoom; } QPoint AbstractImageView::mapToImage(const QPoint& viewPos) const { return mapToImage(QPointF(viewPos)).toPoint(); } QRectF AbstractImageView::mapToImage(const QRectF& viewRect) const { return QRectF( mapToImage(viewRect.topLeft()), viewRect.size() / zoom() ); } QRect AbstractImageView::mapToImage(const QRect& viewRect) const { return QRect( mapToImage(viewRect.topLeft()), viewRect.size() / zoom() ); } +void AbstractImageView::setEnlargeSmallerImages(bool value) { + d->mEnlargeSmallerImages = value; + if (zoomToFit()) { + setZoom(computeZoomToFit()); + } +} + } // namespace diff --git a/lib/documentview/abstractimageview.h b/lib/documentview/abstractimageview.h index 790f9ab6..c6c37512 100644 --- a/lib/documentview/abstractimageview.h +++ b/lib/documentview/abstractimageview.h @@ -1,121 +1,127 @@ // vim: set tabstop=4 shiftwidth=4 noexpandtab: /* Gwenview: an image viewer Copyright 2011 Aurélien Gâteau 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA. */ #ifndef ABSTRACTIMAGEVIEW_H #define ABSTRACTIMAGEVIEW_H // Local #include // KDE // Qt #include namespace Gwenview { class AbstractImageViewPrivate; /** * */ class AbstractImageView : public QGraphicsWidget { Q_OBJECT public: + enum UpdateType { + UpdateIfNecessary, + ForceUpdate + }; AbstractImageView(QGraphicsItem* parent); ~AbstractImageView(); qreal zoom() const; - virtual void setZoom(qreal zoom, const QPointF& center = QPointF(-1, -1)); + virtual void setZoom(qreal zoom, const QPointF& center = QPointF(-1, -1), UpdateType updateType = UpdateIfNecessary); bool zoomToFit() const; virtual void setZoomToFit(bool value); virtual void setDocument(Document::Ptr doc); Document::Ptr document() const; qreal computeZoomToFit() const; virtual QSizeF documentSize() const; QSizeF visibleImageSize() const; /** * If the image is smaller than the view, imageOffset is the distance from * the topleft corner of the view to the topleft corner of the image. * Neither x nor y can be negative. */ QPointF imageOffset() const; /** * The scroll position, in zoomed image coordinates. * x and y are always between 0 and (docsize * zoom - viewsize) */ QPointF scrollPos() const; QPointF mapToView(const QPointF& imagePos) const; QPoint mapToView(const QPoint& imagePos) const; QRectF mapToView(const QRectF& imageRect) const; QRect mapToView(const QRect& imageRect) const; QPointF mapToImage(const QPointF& viewPos) const; QPoint mapToImage(const QPoint& viewPos) const; QRectF mapToImage(const QRectF& viewRect) const; QRect mapToImage(const QRect& viewRect) const; + void setEnlargeSmallerImages(bool value); + Q_SIGNALS: void zoomToFitChanged(bool); void zoomChanged(qreal); protected: void setChildItem(QGraphicsItem*); virtual void loadFromDocument() = 0; virtual void onZoomChanged() = 0; /** * Called when the offset changes. * Note: to avoid multiple adjustments, this is not called if zoom changes! */ virtual void onImageOffsetChanged() = 0; /** * Called when the scrollPos changes. * Note: to avoid multiple adjustments, this is not called if zoom changes! */ virtual void onScrollPosChanged(const QPointF& oldPos) = 0; void resizeEvent(QGraphicsSceneResizeEvent* event); void keyPressEvent(QKeyEvent* event); void mousePressEvent(QGraphicsSceneMouseEvent* event); void mouseMoveEvent(QGraphicsSceneMouseEvent* event); void mouseReleaseEvent(QGraphicsSceneMouseEvent* event); private: friend class AbstractImageViewPrivate; AbstractImageViewPrivate* const d; }; } // namespace #endif /* ABSTRACTIMAGEVIEW_H */ diff --git a/lib/documentview/rasterimageview.cpp b/lib/documentview/rasterimageview.cpp index 1c19d712..c3b998c2 100644 --- a/lib/documentview/rasterimageview.cpp +++ b/lib/documentview/rasterimageview.cpp @@ -1,468 +1,462 @@ // vim: set tabstop=4 shiftwidth=4 noexpandtab: /* Gwenview: an image viewer Copyright 2011 Aurélien Gâteau 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA. */ // Self #include "rasterimageview.moc" // Local #include #include // KDE #include // Qt #include #include #include #include namespace Gwenview { struct RasterImageViewPrivate { RasterImageView* q; ImageScaler* mScaler; QPixmap mBackgroundTexture; // Config RasterImageView::AlphaBackgroundMode mAlphaBackgroundMode; QColor mAlphaBackgroundColor; bool mEnlargeSmallerImages; // /Config bool mBufferIsEmpty; QPixmap mCurrentBuffer; // The alternate buffer is useful when scrolling: existing content is copied // to mAlternateBuffer and buffers are swapped. This avoids allocating a new // QPixmap everytime the image is scrolled. QPixmap mAlternateBuffer; QTimer* mUpdateTimer; QWeakPointer mTool; void createBackgroundTexture() { mBackgroundTexture = QPixmap(32, 32); QPainter painter(&mBackgroundTexture); painter.fillRect(mBackgroundTexture.rect(), QColor(128, 128, 128)); QColor light = QColor(192, 192, 192); painter.fillRect(0, 0, 16, 16, light); painter.fillRect(16, 16, 16, 16, light); } void setupUpdateTimer() { mUpdateTimer = new QTimer(q); mUpdateTimer->setInterval(500); mUpdateTimer->setSingleShot(true); QObject::connect(mUpdateTimer, SIGNAL(timeout()), q, SLOT(updateBuffer())); } void startAnimationIfNecessary() { if (q->document() && q->isVisible()) { q->document()->startAnimation(); } } QSizeF visibleImageSize() const { if (!q->document()) { return QSizeF(); } qreal zoom; if (q->zoomToFit()) { zoom = q->computeZoomToFit(); } else { zoom = q->zoom(); } QSizeF size = q->documentSize() * zoom; return size.boundedTo(q->boundingRect().size()); } QRectF mapViewportToZoomedImage(const QRectF& viewportRect) const { return QRectF( viewportRect.topLeft() - q->imageOffset() + q->scrollPos(), viewportRect.size() ); } void setScalerRegionToVisibleRect() { QRectF rect = mapViewportToZoomedImage(q->boundingRect()); mScaler->setDestinationRegion(QRegion(rect.toRect())); } void createBuffer() { QSize size = visibleImageSize().toSize(); if (size == mCurrentBuffer.size()) { return; } if (!size.isValid()) { mAlternateBuffer = QPixmap(); mCurrentBuffer = QPixmap(); return; } mAlternateBuffer = QPixmap(size); mAlternateBuffer.fill(Qt::transparent); { QPainter painter(&mAlternateBuffer); painter.drawPixmap(0, 0, mCurrentBuffer); } qSwap(mAlternateBuffer, mCurrentBuffer); mAlternateBuffer = QPixmap(); } void drawAlphaBackground(QPainter* painter, const QRect& viewportRect, const QPoint& zoomedImageTopLeft) { if (mAlphaBackgroundMode == RasterImageView::AlphaBackgroundCheckBoard) { QPoint textureOffset( zoomedImageTopLeft.x() % mBackgroundTexture.width(), zoomedImageTopLeft.y() % mBackgroundTexture.height() ); painter->drawTiledPixmap( viewportRect, mBackgroundTexture, textureOffset); } else { painter->fillRect(viewportRect, mAlphaBackgroundColor); } } }; RasterImageView::RasterImageView(QGraphicsItem* parent) : AbstractImageView(parent) , d(new RasterImageViewPrivate) { d->q = this; d->mAlphaBackgroundMode = AlphaBackgroundCheckBoard; d->mAlphaBackgroundColor = Qt::black; d->mEnlargeSmallerImages = false; d->mBufferIsEmpty = true; d->mScaler = new ImageScaler(this); connect(d->mScaler, SIGNAL(scaledRect(int,int,QImage)), SLOT(updateFromScaler(int,int,QImage)) ); setAcceptHoverEvents(true); d->createBackgroundTexture(); d->setupUpdateTimer(); } RasterImageView::~RasterImageView() { delete d; } void RasterImageView::setAlphaBackgroundMode(AlphaBackgroundMode mode) { d->mAlphaBackgroundMode = mode; if (document() && document()->hasAlphaChannel()) { d->mCurrentBuffer = QPixmap(); updateBuffer(); } } void RasterImageView::setAlphaBackgroundColor(const QColor& color) { d->mAlphaBackgroundColor = color; if (document() && document()->hasAlphaChannel()) { d->mCurrentBuffer = QPixmap(); updateBuffer(); } } - -void RasterImageView::setEnlargeSmallerImages(bool value) { - d->mEnlargeSmallerImages = value; - if (zoomToFit()) { - setZoom(computeZoomToFit()); - } -} - void RasterImageView::loadFromDocument() { Document::Ptr doc = document(); connect(doc.data(), SIGNAL(metaInfoLoaded(KUrl)), SLOT(slotDocumentMetaInfoLoaded()) ); connect(doc.data(), SIGNAL(isAnimatedUpdated()), SLOT(slotDocumentIsAnimatedUpdated()) ); const Document::LoadingState state = doc->loadingState(); if (state == Document::MetaInfoLoaded || state == Document::Loaded) { slotDocumentMetaInfoLoaded(); } } void RasterImageView::slotDocumentMetaInfoLoaded() { if (document()->size().isValid()) { finishSetDocument(); } else { // Could not retrieve image size from meta info, we need to load the // full image now. connect(document().data(), SIGNAL(loaded(KUrl)), SLOT(finishSetDocument()) ); document()->startLoadingFullImage(); } } void RasterImageView::finishSetDocument() { if (!document()->size().isValid()) { kError() << "No valid image size available, this should not happen!"; return; } d->createBuffer(); d->mScaler->setDocument(document()); connect(document().data(), SIGNAL(imageRectUpdated(QRect)), SLOT(updateImageRect(QRect)) ); if (zoomToFit()) { - setZoom(computeZoomToFit()); + // Force the update otherwise if computeZoomToFit() returns 1, setZoom() + // will think zoom has not changed and won't update the image + setZoom(computeZoomToFit(), QPointF(-1, -1), ForceUpdate); } else { QRect rect(QPoint(0, 0), document()->size()); updateImageRect(rect); } d->startAnimationIfNecessary(); update(); } void RasterImageView::updateImageRect(const QRect& imageRect) { QRectF viewRect = mapToView(imageRect); if (!viewRect.intersects(boundingRect())) { return; } if (zoomToFit()) { setZoom(computeZoomToFit()); } d->setScalerRegionToVisibleRect(); update(); } void RasterImageView::slotDocumentIsAnimatedUpdated() { d->startAnimationIfNecessary(); } void RasterImageView::updateFromScaler(int zoomedImageLeft, int zoomedImageTop, const QImage& image) { int viewportLeft = zoomedImageLeft - scrollPos().x(); int viewportTop = zoomedImageTop - scrollPos().y(); d->mBufferIsEmpty = false; { QPainter painter(&d->mCurrentBuffer); if (document()->hasAlphaChannel()) { d->drawAlphaBackground( &painter, QRect(viewportLeft, viewportTop, image.width(), image.height()), QPoint(zoomedImageLeft, zoomedImageTop) ); } else { painter.setCompositionMode(QPainter::CompositionMode_Source); } painter.drawImage(viewportLeft, viewportTop, image); } update(); } void RasterImageView::onZoomChanged() { // If we zoom more than twice, then assume the user wants to see the real // pixels, for example to fine tune a crop operation if (zoom() < 2.) { d->mScaler->setTransformationMode(Qt::SmoothTransformation); } else { d->mScaler->setTransformationMode(Qt::FastTransformation); } if (!d->mUpdateTimer->isActive()) { updateBuffer(); } } void RasterImageView::onImageOffsetChanged() { update(); } void RasterImageView::onScrollPosChanged(const QPointF& oldPos) { QPointF delta = scrollPos() - oldPos; // Scroll existing { if (d->mAlternateBuffer.size() != d->mCurrentBuffer.size()) { d->mAlternateBuffer = QPixmap(d->mCurrentBuffer.size()); } QPainter painter(&d->mAlternateBuffer); painter.drawPixmap(-delta, d->mCurrentBuffer); } qSwap(d->mCurrentBuffer, d->mAlternateBuffer); // Scale missing parts QRegion bufferRegion = QRegion(d->mCurrentBuffer.rect().translated(scrollPos().toPoint())); QRegion updateRegion = bufferRegion - bufferRegion.translated(-delta.toPoint()); updateBuffer(updateRegion); update(); } void RasterImageView::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/) { QSize bufferSize = d->mCurrentBuffer.size(); QSizeF paintSize; if (zoomToFit()) { paintSize = documentSize() * computeZoomToFit(); } else { paintSize = bufferSize; } painter->drawPixmap( (boundingRect().width() - paintSize.width()) / 2, (boundingRect().height() - paintSize.height()) / 2, paintSize.width(), paintSize.height(), d->mCurrentBuffer); if (d->mTool) { d->mTool.data()->paint(painter); } // Debug #if 0 QPointF topLeft = imageOffset(); QSizeF visibleSize = documentSize() * zoom(); painter->setPen(Qt::red); painter->drawRect(topLeft.x(), topLeft.y(), visibleSize.width() - 1, visibleSize.height() - 1); painter->setPen(Qt::blue); painter->drawRect(topLeft.x(), topLeft.y(), d->mCurrentBuffer.width() - 1, d->mCurrentBuffer.height() - 1); #endif } void RasterImageView::resizeEvent(QGraphicsSceneResizeEvent* event) { // If we are in zoomToFit mode and have something in our buffer, delay the // update: paint() will paint a scaled version of the buffer until resizing // is done. This is much faster than rescaling the whole image for each // resize event we receive. // mUpdateTimer must be start before calling AbstractImageView::resizeEvent() // because AbstractImageView::resizeEvent() will call onZoomChanged(), which // will trigger an immediate update unless the mUpdateTimer is active. if (zoomToFit() && !d->mBufferIsEmpty) { d->mUpdateTimer->start(); } AbstractImageView::resizeEvent(event); if (!zoomToFit()) { // Only update buffer if we are not in zoomToFit mode: if we are // onZoomChanged() will have already updated the buffer. updateBuffer(); } } void RasterImageView::updateBuffer(const QRegion& region) { d->mUpdateTimer->stop(); d->createBuffer(); d->mScaler->setZoom(zoom()); if (region.isEmpty()) { d->setScalerRegionToVisibleRect(); } else { d->mScaler->setDestinationRegion(region); } } void RasterImageView::setCurrentTool(AbstractRasterImageViewTool* tool) { if (d->mTool) { d->mTool.data()->toolDeactivated(); } d->mTool = tool; if (d->mTool) { d->mTool.data()->toolActivated(); } currentToolChanged(tool); update(); } AbstractRasterImageViewTool* RasterImageView::currentTool() const { return d->mTool.data(); } void RasterImageView::mousePressEvent(QGraphicsSceneMouseEvent* event) { if (d->mTool) { d->mTool.data()->mousePressEvent(event); if (event->isAccepted()) { return; } } AbstractImageView::mousePressEvent(event); } void RasterImageView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { if (d->mTool) { d->mTool.data()->mouseMoveEvent(event); if (event->isAccepted()) { return; } } AbstractImageView::mouseMoveEvent(event); } void RasterImageView::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { if (d->mTool) { d->mTool.data()->mouseReleaseEvent(event); if (event->isAccepted()) { return; } } AbstractImageView::mouseReleaseEvent(event); } void RasterImageView::wheelEvent(QGraphicsSceneWheelEvent* event) { if (d->mTool) { d->mTool.data()->wheelEvent(event); if (event->isAccepted()) { return; } } AbstractImageView::wheelEvent(event); } void RasterImageView::keyPressEvent(QKeyEvent* event) { if (d->mTool) { d->mTool.data()->keyPressEvent(event); if (event->isAccepted()) { return; } } AbstractImageView::keyPressEvent(event); } void RasterImageView::keyReleaseEvent(QKeyEvent* event) { if (d->mTool) { d->mTool.data()->keyReleaseEvent(event); if (event->isAccepted()) { return; } } AbstractImageView::keyReleaseEvent(event); } void RasterImageView::hoverMoveEvent(QGraphicsSceneHoverEvent* event) { if (d->mTool) { d->mTool.data()->hoverMoveEvent(event); if (event->isAccepted()) { return; } } AbstractImageView::hoverMoveEvent(event); } } // namespace diff --git a/lib/documentview/rasterimageview.h b/lib/documentview/rasterimageview.h index b3acd7ab..474b006c 100644 --- a/lib/documentview/rasterimageview.h +++ b/lib/documentview/rasterimageview.h @@ -1,89 +1,88 @@ // vim: set tabstop=4 shiftwidth=4 noexpandtab: /* Gwenview: an image viewer Copyright 2011 Aurélien Gâteau 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. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA. */ #ifndef RASTERIMAGEVIEW_H #define RASTERIMAGEVIEW_H #include // Local #include // KDE class QGraphicsSceneHoverEvent; namespace Gwenview { class AbstractRasterImageViewTool; class RasterImageViewPrivate; class GWENVIEWLIB_EXPORT RasterImageView : public AbstractImageView { Q_OBJECT public: enum AlphaBackgroundMode { AlphaBackgroundCheckBoard, AlphaBackgroundSolid }; RasterImageView(QGraphicsItem* parent = 0); ~RasterImageView(); void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget); void setCurrentTool(AbstractRasterImageViewTool* tool); AbstractRasterImageViewTool* currentTool() const; void setAlphaBackgroundMode(AlphaBackgroundMode mode); void setAlphaBackgroundColor(const QColor& color); - void setEnlargeSmallerImages(bool value); Q_SIGNALS: void currentToolChanged(AbstractRasterImageViewTool*); protected: void loadFromDocument(); void onZoomChanged(); void onImageOffsetChanged(); void onScrollPosChanged(const QPointF& oldPos); void resizeEvent(QGraphicsSceneResizeEvent* event); void mousePressEvent(QGraphicsSceneMouseEvent* event); void mouseMoveEvent(QGraphicsSceneMouseEvent* event); void mouseReleaseEvent(QGraphicsSceneMouseEvent* event); void wheelEvent(QGraphicsSceneWheelEvent* event); void keyPressEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event); void hoverMoveEvent(QGraphicsSceneHoverEvent*); private Q_SLOTS: void slotDocumentMetaInfoLoaded(); void slotDocumentIsAnimatedUpdated(); void finishSetDocument(); void updateFromScaler(int, int, const QImage&); void updateImageRect(const QRect& imageRect); void updateBuffer(const QRegion& region = QRegion()); private: RasterImageViewPrivate* const d; }; } // namespace #endif /* RASTERIMAGEVIEW_H */