File indexing completed on 2024-05-12 04:19:40

0001 // vim: set tabstop=4 shiftwidth=4 expandtab:
0002 /*
0003 Gwenview: an image viewer
0004 Copyright 2008 Aurélien Gâteau <agateau@kde.org>
0005 
0006 This program is free software; you can redistribute it and/or
0007 modify it under the terms of the GNU General Public License
0008 as published by the Free Software Foundation; either version 2
0009 of the License, or (at your option) any later version.
0010 
0011 This program is distributed in the hope that it will be useful,
0012 but WITHOUT ANY WARRANTY; without even the implied warranty of
0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0014 GNU General Public License for more details.
0015 
0016 You should have received a copy of the GNU General Public License
0017 along with this program; if not, write to the Free Software
0018 Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA.
0019 
0020 */
0021 // Self
0022 #include "svgviewadapter.h"
0023 
0024 // Qt
0025 #include <QCursor>
0026 #include <QGraphicsSceneEvent>
0027 #include <QGraphicsSvgItem>
0028 #include <QGraphicsTextItem>
0029 #include <QSvgRenderer>
0030 
0031 // KF
0032 
0033 // Local
0034 #include "alphabackgrounditem.h"
0035 #include "gwenview_lib_debug.h"
0036 #include <lib/gvdebug.h>
0037 #include <lib/gwenviewconfig.h>
0038 
0039 namespace Gwenview
0040 {
0041 /// SvgImageView ////
0042 SvgImageView::SvgImageView(QGraphicsItem *parent)
0043     : AbstractImageView(parent)
0044     , mSvgItem(new QGraphicsSvgItem(this))
0045 {
0046     // At certain scales, the SVG can render outside its own bounds up to 1 pixel
0047     // This clips it so it isn't drawn outside the background or over the selection rect
0048     mSvgItem->setFlag(ItemClipsToShape);
0049 
0050     // So we aren't unnecessarily drawing the background for every paint()
0051     setCacheMode(QGraphicsItem::DeviceCoordinateCache);
0052 }
0053 
0054 void SvgImageView::loadFromDocument()
0055 {
0056     Document::Ptr doc = document();
0057     GV_RETURN_IF_FAIL(doc);
0058 
0059     if (doc->loadingState() == Document::Loaded) {
0060         QMetaObject::invokeMethod(this, &SvgImageView::finishLoadFromDocument, Qt::QueuedConnection);
0061     }
0062 
0063     // Ensure finishLoadFromDocument is also called when
0064     // - loadFromDocument was called before the document was fully loaded
0065     // - reloading is triggered (e.g. via F5)
0066     connect(doc.data(), &Document::loaded, this, &SvgImageView::finishLoadFromDocument);
0067 }
0068 
0069 void SvgImageView::finishLoadFromDocument()
0070 {
0071     QSvgRenderer *renderer = document()->svgRenderer();
0072     GV_RETURN_IF_FAIL(renderer);
0073     mSvgItem->setSharedRenderer(renderer);
0074     if (zoomToFit()) {
0075         setZoom(computeZoomToFit(), QPointF(-1, -1), ForceUpdate);
0076     } else if (zoomToFill()) {
0077         setZoom(computeZoomToFill(), QPointF(-1, -1), ForceUpdate);
0078     } else {
0079         mSvgItem->setScale(zoom());
0080     }
0081     applyPendingScrollPos();
0082     Q_EMIT completed();
0083     backgroundItem()->setVisible(true);
0084 }
0085 
0086 void SvgImageView::onZoomChanged()
0087 {
0088     mSvgItem->setScale(zoom());
0089     adjustItemPos();
0090 }
0091 
0092 void SvgImageView::onImageOffsetChanged()
0093 {
0094     adjustItemPos();
0095 }
0096 
0097 void SvgImageView::onScrollPosChanged(const QPointF & /* oldPos */)
0098 {
0099     adjustItemPos();
0100 }
0101 
0102 void SvgImageView::adjustItemPos()
0103 {
0104     mSvgItem->setPos((imageOffset() - scrollPos()).toPoint());
0105     update();
0106 }
0107 
0108 //// SvgViewAdapter ////
0109 struct SvgViewAdapterPrivate {
0110     SvgImageView *mView;
0111 };
0112 
0113 SvgViewAdapter::SvgViewAdapter()
0114     : d(new SvgViewAdapterPrivate)
0115 {
0116     d->mView = new SvgImageView;
0117     setWidget(d->mView);
0118     connect(d->mView, &SvgImageView::zoomChanged, this, &SvgViewAdapter::zoomChanged);
0119     connect(d->mView, &SvgImageView::zoomToFitChanged, this, &SvgViewAdapter::zoomToFitChanged);
0120     connect(d->mView, &SvgImageView::zoomToFillChanged, this, &SvgViewAdapter::zoomToFillChanged);
0121     connect(d->mView, &SvgImageView::zoomInRequested, this, &SvgViewAdapter::zoomInRequested);
0122     connect(d->mView, &SvgImageView::zoomOutRequested, this, &SvgViewAdapter::zoomOutRequested);
0123     connect(d->mView, &SvgImageView::scrollPosChanged, this, &SvgViewAdapter::scrollPosChanged);
0124     connect(d->mView, &SvgImageView::completed, this, &SvgViewAdapter::completed);
0125     connect(d->mView, &SvgImageView::previousImageRequested, this, &SvgViewAdapter::previousImageRequested);
0126     connect(d->mView, &SvgImageView::nextImageRequested, this, &SvgViewAdapter::nextImageRequested);
0127     connect(d->mView, &SvgImageView::toggleFullScreenRequested, this, &SvgViewAdapter::toggleFullScreenRequested);
0128 }
0129 
0130 SvgViewAdapter::~SvgViewAdapter()
0131 {
0132     delete d;
0133 }
0134 
0135 QCursor SvgViewAdapter::cursor() const
0136 {
0137     return widget()->cursor();
0138 }
0139 
0140 void SvgViewAdapter::setCursor(const QCursor &cursor)
0141 {
0142     widget()->setCursor(cursor);
0143 }
0144 
0145 void SvgViewAdapter::setDocument(const Document::Ptr &doc)
0146 {
0147     d->mView->setDocument(doc);
0148 }
0149 
0150 Document::Ptr SvgViewAdapter::document() const
0151 {
0152     return d->mView->document();
0153 }
0154 
0155 void SvgViewAdapter::loadConfig()
0156 {
0157     d->mView->backgroundItem()->setMode(GwenviewConfig::alphaBackgroundMode());
0158     d->mView->backgroundItem()->setColor(GwenviewConfig::alphaBackgroundColor());
0159     d->mView->setEnlargeSmallerImages(GwenviewConfig::enlargeSmallerImages());
0160 }
0161 
0162 void SvgViewAdapter::setZoomToFit(bool on)
0163 {
0164     d->mView->setZoomToFit(on);
0165 }
0166 
0167 void SvgViewAdapter::setZoomToFill(bool on, const QPointF &center)
0168 {
0169     d->mView->setZoomToFill(on, center);
0170 }
0171 
0172 bool SvgViewAdapter::zoomToFit() const
0173 {
0174     return d->mView->zoomToFit();
0175 }
0176 
0177 bool SvgViewAdapter::zoomToFill() const
0178 {
0179     return d->mView->zoomToFill();
0180 }
0181 
0182 qreal SvgViewAdapter::zoom() const
0183 {
0184     return d->mView->zoom();
0185 }
0186 
0187 void SvgViewAdapter::setZoom(qreal zoom, const QPointF &center)
0188 {
0189     d->mView->setZoom(zoom, center);
0190 }
0191 
0192 qreal SvgViewAdapter::computeZoomToFit() const
0193 {
0194     return d->mView->computeZoomToFit();
0195 }
0196 
0197 qreal SvgViewAdapter::computeZoomToFill() const
0198 {
0199     return d->mView->computeZoomToFill();
0200 }
0201 
0202 QPointF SvgViewAdapter::scrollPos() const
0203 {
0204     return d->mView->scrollPos();
0205 }
0206 
0207 void SvgViewAdapter::setScrollPos(const QPointF &pos)
0208 {
0209     d->mView->setScrollPos(pos);
0210 }
0211 
0212 QRectF SvgViewAdapter::visibleDocumentRect() const
0213 {
0214     return QRectF(d->mView->imageOffset(), d->mView->visibleImageSize());
0215 }
0216 
0217 AbstractImageView *SvgViewAdapter::imageView() const
0218 {
0219     return d->mView;
0220 }
0221 
0222 } // namespace
0223 
0224 #include "moc_svgviewadapter.cpp"