diff --git a/lib/documentview/abstractimageview.cpp b/lib/documentview/abstractimageview.cpp index 15e7c1f7..35f47e7f 100644 --- a/lib/documentview/abstractimageview.cpp +++ b/lib/documentview/abstractimageview.cpp @@ -1,234 +1,234 @@ // 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 { struct AbstractImageViewPrivate { AbstractImageView* q; Document::Ptr mDoc; qreal mZoom; bool mZoomToFit; QPixmap mCurrentBuffer; // The alternate buffer is useful when scrolling: existing content is copied // to mAlternateBuffer and buffers are then swapped. This avoids the // allocation of a new QPixmap everytime the view is scrolled. QPixmap mAlternateBuffer; QTimer* mZoomToFitUpdateTimer; void setupZoomToFitUpdateTimer() { mZoomToFitUpdateTimer = new QTimer(q); mZoomToFitUpdateTimer->setInterval(500); mZoomToFitUpdateTimer->setSingleShot(true); QObject::connect(mZoomToFitUpdateTimer, SIGNAL(timeout()), q, SLOT(updateZoomToFit())); } }; AbstractImageView::AbstractImageView(QGraphicsItem* parent) : QGraphicsWidget(parent) , d(new AbstractImageViewPrivate) { d->q = this; d->mZoom = 1; d->mZoomToFit = true; setFlag(ItemIsFocusable); setFlag(ItemIsSelectable); d->setupZoomToFitUpdateTimer(); } AbstractImageView::~AbstractImageView() { delete d; } void AbstractImageView::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/) { QSize bufferSize = d->mCurrentBuffer.size(); QSizeF paintSize; if (d->mZoomToFit) { paintSize = documentSize() * computeZoomToFit(); } else { paintSize = bufferSize; } painter->drawPixmap( (boundingRect().width() - paintSize.width()) / 2, (boundingRect().height() - paintSize.height()) / 2, paintSize.width(), paintSize.height(), d->mCurrentBuffer); } qreal AbstractImageView::zoom() const { return d->mZoom; } void AbstractImageView::setZoom(qreal zoom, const QPointF& /*center*/) { d->mZoom = zoom; createBuffer(); updateBuffer(); } bool AbstractImageView::zoomToFit() const { return d->mZoomToFit; } void AbstractImageView::setZoomToFit(bool value) { if (d->mZoomToFit == value) { return; } d->mZoomToFit = value; if (d->mZoomToFit) { setZoom(computeZoomToFit()); } zoomToFitChanged(value); } Document::Ptr AbstractImageView::document() const { return d->mDoc; } void AbstractImageView::setDocument(Document::Ptr doc) { d->mDoc = doc; } QSizeF AbstractImageView::documentSize() const { return d->mDoc ? d->mDoc->size() : QSizeF(); } 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); } void AbstractImageView::resizeEvent(QGraphicsSceneResizeEvent* event) { QGraphicsWidget::resizeEvent(event); if (d->mZoomToFit) { d->mZoomToFitUpdateTimer->start(); } } void AbstractImageView::updateZoomToFit() { if (!d->mZoomToFit) { return; } setZoom(computeZoomToFit()); } QSizeF AbstractImageView::visibleImageSize() const { if (!d->mDoc) { return QSizeF(); } qreal zoom; if (d->mZoomToFit) { zoom = computeZoomToFit(); } else { zoom = d->mZoom; } QSizeF size = documentSize() * zoom; size = size.boundedTo(boundingRect().size()); return size; } QRectF AbstractImageView::mapViewportToZoomedImage(const QRectF& viewportRect) const { // FIXME: QGV - QPointF offset = QPointF(0, 0); //mView->imageOffset(); + //QPointF offset = QPointF(0, 0); //mView->imageOffset(); QRectF rect = QRectF( viewportRect.x(), //+ hScroll() - offset.x(), viewportRect.y(), //+ vScroll() - offset.y(), viewportRect.width(), viewportRect.height() ); return rect; } void AbstractImageView::createBuffer() { QSize size = visibleImageSize().toSize(); if (size == d->mCurrentBuffer.size()) { return; } if (!size.isValid()) { d->mAlternateBuffer = QPixmap(); d->mCurrentBuffer = QPixmap(); return; } d->mAlternateBuffer = QPixmap(size); d->mAlternateBuffer.fill(Qt::transparent); { QPainter painter(&d->mAlternateBuffer); painter.drawPixmap(0, 0, d->mCurrentBuffer); } qSwap(d->mAlternateBuffer, d->mCurrentBuffer); d->mAlternateBuffer = QPixmap(); } QPixmap& AbstractImageView::buffer() { return d->mCurrentBuffer; } -void AbstractImageView::keyPressEvent(QKeyEvent* event) { +void AbstractImageView::keyPressEvent(QKeyEvent* /*event*/) { kDebug() << d->mDoc->url(); } -void AbstractImageView::keyReleaseEvent(QKeyEvent* event) { +void AbstractImageView::keyReleaseEvent(QKeyEvent* /*event*/) { kDebug() << d->mDoc->url(); } -void AbstractImageView::mousePressEvent(QGraphicsSceneMouseEvent* event) { +void AbstractImageView::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/) { kDebug(); // Necessary to get focus when clicking on a single image setFocus(); } -void AbstractImageView::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { +void AbstractImageView::mouseMoveEvent(QGraphicsSceneMouseEvent* /*event*/) { kDebug(); } -void AbstractImageView::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { +void AbstractImageView::mouseReleaseEvent(QGraphicsSceneMouseEvent* /*event*/) { kDebug(); } } // namespace diff --git a/lib/documentview/documentview.cpp b/lib/documentview/documentview.cpp index fe2d4301..d040356e 100644 --- a/lib/documentview/documentview.cpp +++ b/lib/documentview/documentview.cpp @@ -1,737 +1,737 @@ // vim: set tabstop=4 shiftwidth=4 noexpandtab: /* Gwenview: an image viewer Copyright 2008 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 "documentview.moc" // Qt #include #include #include #include #include #include #include #include #include #include #include // KDE #include #include #include #include #include #include #include // Local #include #include #include #include #include #include #include #include #include #include #include #include namespace Gwenview { #undef ENABLE_LOG #undef LOG //#define ENABLE_LOG #ifdef ENABLE_LOG #define LOG(x) kDebug() << x #else #define LOG(x) ; #endif static const qreal REAL_DELTA = 0.001; static const qreal MAXIMUM_ZOOM_VALUE = qreal(DocumentView::MaximumZoom); static const int COMPARE_MARGIN = 4; struct DocumentViewPrivate { DocumentView* that; QGraphicsProxyWidget* mHud; KModifierKeyInfo* mModifierKeyInfo; QCursor mZoomCursor; QCursor mPreviousCursor; QWeakPointer mMoveAnimation; QGraphicsProxyWidget* mLoadingIndicator; QScopedPointer mAdapter; QList mZoomSnapValues; Document::Ptr mDocument; bool mCurrent; bool mCompareMode; void setCurrentAdapter(AbstractDocumentViewAdapter* adapter) { Q_ASSERT(adapter); mAdapter.reset(adapter); adapter->widget()->setParentItem(that); resizeAdapterWidget(); if (adapter->canZoom()) { QObject::connect(adapter, SIGNAL(zoomChanged(qreal)), that, SLOT(slotZoomChanged(qreal)) ); QObject::connect(adapter, SIGNAL(zoomToFitChanged(bool)), that, SIGNAL(zoomToFitChanged(bool)) ); } // FIXME QGV /* QAbstractScrollArea* area = qobject_cast(adapter->widget()); if (area) { QObject::connect(area->horizontalScrollBar(), SIGNAL(valueChanged(int)), that, SIGNAL(positionChanged())); QObject::connect(area->verticalScrollBar(), SIGNAL(valueChanged(int)), that, SIGNAL(positionChanged())); } */ adapter->widget()->installSceneEventFilter(that); if (mCurrent) { adapter->widget()->setFocus(); } that->adapterChanged(); that->positionChanged(); if (adapter->canZoom()) { that->zoomToFitChanged(adapter->zoomToFit()); } } void setupZoomCursor() { QString path = KStandardDirs::locate("appdata", "cursors/zoom.png"); QPixmap cursorPixmap = QPixmap(path); mZoomCursor = QCursor(cursorPixmap); } void setZoomCursor() { QCursor currentCursor = mAdapter.data()->cursor(); if (currentCursor.pixmap().cacheKey() == mZoomCursor.pixmap().cacheKey()) { return; } mPreviousCursor = currentCursor; mAdapter.data()->setCursor(mZoomCursor); } void restoreCursor() { mAdapter.data()->setCursor(mPreviousCursor); } void setupLoadingIndicator() { KPixmapSequence sequence("process-working", 22); KPixmapSequenceWidget* widget = new KPixmapSequenceWidget; widget->setSequence(sequence); widget->setInterval(100); mLoadingIndicator = new QGraphicsProxyWidget(that); mLoadingIndicator->setWidget(widget); GraphicsWidgetFloater* floater = new GraphicsWidgetFloater(that); floater->setChildWidget(mLoadingIndicator); } QToolButton* createHudButton(const QString& text, const char* iconName, bool showText) { QToolButton* button = new QToolButton; if (showText) { button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); button->setText(text); } else { button->setToolTip(text); } button->setIcon(SmallIcon(iconName)); return button; } void setupHud() { QToolButton* trashButton = createHudButton(i18n("Trash"), "user-trash", false); QToolButton* deselectButton = createHudButton(i18n("Deselect"), "list-remove", true); QWidget* content = new QWidget; QHBoxLayout* layout = new QHBoxLayout(content); layout->setMargin(0); layout->setSpacing(4); layout->addWidget(trashButton); layout->addWidget(deselectButton); HudWidget* hud = new HudWidget; hud->init(content, HudWidget::OptionNone); mHud = new QGraphicsProxyWidget(that); mHud->setWidget(hud); GraphicsWidgetFloater* floater = new GraphicsWidgetFloater(that); floater->setChildWidget(mHud); floater->setAlignment(Qt::AlignBottom | Qt::AlignHCenter); QObject::connect(trashButton, SIGNAL(clicked()), that, SLOT(emitHudTrashClicked())); QObject::connect(deselectButton, SIGNAL(clicked()), that, SLOT(emitHudDeselectClicked())); mHud->hide(); } void updateCaption() { QString caption; Document::Ptr doc = mAdapter->document(); if (!doc) { emit that->captionUpdateRequested(caption); return; } caption = doc->url().fileName(); QSize size = doc->size(); if (size.isValid()) { caption += QString(" - %1x%2") .arg(size.width()) .arg(size.height()); if (mAdapter->canZoom()) { int intZoom = qRound(mAdapter->zoom() * 100); caption += QString(" - %1%") .arg(intZoom); } } emit that->captionUpdateRequested(caption); } void uncheckZoomToFit() { if (mAdapter->zoomToFit()) { mAdapter->setZoomToFit(false); } } void setZoom(qreal zoom, const QPointF& center = QPointF(-1, -1)) { uncheckZoomToFit(); zoom = qBound(that->minimumZoom(), zoom, MAXIMUM_ZOOM_VALUE); mAdapter->setZoom(zoom, center); } void updateZoomSnapValues() { qreal min = that->minimumZoom(); mZoomSnapValues.clear(); if (min < 1.) { mZoomSnapValues << min; for (qreal invZoom = 16.; invZoom > 1.; invZoom /= 2.) { qreal zoom = 1. / invZoom; if (zoom > min) { mZoomSnapValues << zoom; } } } for (qreal zoom = 1; zoom <= MAXIMUM_ZOOM_VALUE ; zoom += 1.) { mZoomSnapValues << zoom; } that->minimumZoomChanged(min); } void showLoadingIndicator() { if (!mLoadingIndicator) { setupLoadingIndicator(); } mLoadingIndicator->show(); mLoadingIndicator->setZValue(1); } void hideLoadingIndicator() { if (!mLoadingIndicator) { return; } mLoadingIndicator->hide(); } void animate(QPropertyAnimation* anim) { QObject::connect(anim, SIGNAL(finished()), that, SLOT(slotAnimationFinished())); anim->setDuration(500); anim->start(QAbstractAnimation::DeleteWhenStopped); } void resizeAdapterWidget() { QRectF rect = QRectF(QPointF(0, 0), that->boundingRect().size()); if (mCompareMode) { rect.adjust(COMPARE_MARGIN, COMPARE_MARGIN, -COMPARE_MARGIN, -COMPARE_MARGIN); } mAdapter->widget()->setGeometry(rect); } void adapterMousePressEvent(QGraphicsSceneMouseEvent* event) { if (mAdapter->canZoom()) { if (event->modifiers() == Qt::ControlModifier) { // Ctrl + Left or right button => zoom in or out if (event->button() == Qt::LeftButton) { that->zoomIn(event->pos()); } else if (event->button() == Qt::RightButton) { that->zoomOut(event->pos()); } } else if (event->button() == Qt::MidButton) { // Middle click => toggle zoom to fit that->setZoomToFit(!mAdapter->zoomToFit()); } } QMetaObject::invokeMethod(that, "emitFocused", Qt::QueuedConnection); } }; DocumentView::DocumentView() : d(new DocumentViewPrivate) { d->that = this; d->mModifierKeyInfo = new KModifierKeyInfo(this); connect(d->mModifierKeyInfo, SIGNAL(keyPressed(Qt::Key,bool)), SLOT(slotKeyPressed(Qt::Key,bool))); d->mLoadingIndicator = 0; setFlag(ItemIsFocusable); setFlag(ItemIsSelectable); d->setupZoomCursor(); d->setupHud(); d->setCurrentAdapter(new MessageViewAdapter); d->mCurrent = false; d->mCompareMode = false; } DocumentView::~DocumentView() { delete d; } void DocumentView::createAdapterForDocument() { const MimeTypeUtils::Kind documentKind = d->mDocument->kind(); if (d->mAdapter && documentKind == d->mAdapter->kind() && documentKind != MimeTypeUtils::KIND_UNKNOWN) { // Do not reuse for KIND_UNKNOWN: we may need to change the message LOG("Reusing current adapter"); return; } AbstractDocumentViewAdapter* adapter = 0; switch (documentKind) { case MimeTypeUtils::KIND_RASTER_IMAGE: adapter = new ImageViewAdapter; break; case MimeTypeUtils::KIND_SVG_IMAGE: adapter = new SvgViewAdapter; break; case MimeTypeUtils::KIND_VIDEO: adapter = new VideoViewAdapter; connect(adapter, SIGNAL(videoFinished()), SIGNAL(videoFinished())); break; case MimeTypeUtils::KIND_UNKNOWN: adapter = new MessageViewAdapter; static_cast(adapter)->setErrorMessage(i18n("Gwenview does not know how to display this kind of document")); break; default: kWarning() << "should not be called for documentKind=" << documentKind; adapter = new MessageViewAdapter; break; } d->setCurrentAdapter(adapter); } void DocumentView::openUrl(const KUrl& url) { if (d->mDocument) { disconnect(d->mDocument.data(), 0, this, 0); } d->mDocument = DocumentFactory::instance()->load(url); connect(d->mDocument.data(), SIGNAL(busyChanged(KUrl,bool)), SLOT(slotBusyChanged(KUrl,bool))); if (d->mDocument->loadingState() < Document::KindDetermined) { MessageViewAdapter* messageViewAdapter = qobject_cast(d->mAdapter.data()); if (messageViewAdapter) { messageViewAdapter->setInfoMessage(QString()); } d->showLoadingIndicator(); connect(d->mDocument.data(), SIGNAL(kindDetermined(KUrl)), SLOT(finishOpenUrl())); } else { finishOpenUrl(); } } void DocumentView::finishOpenUrl() { disconnect(d->mDocument.data(), SIGNAL(kindDetermined(KUrl)), this, SLOT(finishOpenUrl())); if (d->mDocument->loadingState() < Document::KindDetermined) { kWarning() << "d->mDocument->loadingState() < Document::KindDetermined, this should not happen!"; return; } if (d->mDocument->loadingState() == Document::LoadingFailed) { slotLoadingFailed(); return; } createAdapterForDocument(); connect(d->mDocument.data(), SIGNAL(downSampledImageReady()), SLOT(slotLoaded()) ); connect(d->mDocument.data(), SIGNAL(loaded(KUrl)), SLOT(slotLoaded()) ); connect(d->mDocument.data(), SIGNAL(loadingFailed(KUrl)), SLOT(slotLoadingFailed()) ); d->mAdapter->setDocument(d->mDocument); d->updateCaption(); if (d->mDocument->loadingState() == Document::Loaded) { slotLoaded(); } } void DocumentView::reset() { d->hideLoadingIndicator(); if (d->mDocument) { disconnect(d->mDocument.data(), 0, this, 0); d->mDocument = 0; } d->setCurrentAdapter(new EmptyAdapter); } bool DocumentView::isEmpty() const { return qobject_cast(d->mAdapter.data()); } void DocumentView::loadAdapterConfig() { d->mAdapter->loadConfig(); } ImageView* DocumentView::imageView() const { return d->mAdapter->imageView(); } void DocumentView::slotLoaded() { d->hideLoadingIndicator(); d->updateCaption(); d->updateZoomSnapValues(); if (!d->mAdapter->zoomToFit()) { qreal min = minimumZoom(); if (d->mAdapter->zoom() < min) { d->mAdapter->setZoom(min); } } emit completed(); } void DocumentView::slotLoadingFailed() { d->hideLoadingIndicator(); MessageViewAdapter* adapter = new MessageViewAdapter; adapter->setDocument(d->mDocument); QString message = i18n("Loading %1 failed", d->mDocument->url().fileName()); adapter->setErrorMessage(message, d->mDocument->errorString()); d->setCurrentAdapter(adapter); emit completed(); } bool DocumentView::canZoom() const { return d->mAdapter->canZoom(); } void DocumentView::setZoomToFit(bool on) { if (on == d->mAdapter->zoomToFit()) { return; } d->mAdapter->setZoomToFit(on); if (!on) { d->mAdapter->setZoom(1.); } } bool DocumentView::zoomToFit() const { return d->mAdapter->zoomToFit(); } void DocumentView::zoomActualSize() { d->uncheckZoomToFit(); d->mAdapter->setZoom(1.); } void DocumentView::zoomIn(const QPointF& center) { qreal currentZoom = d->mAdapter->zoom(); Q_FOREACH(qreal zoom, d->mZoomSnapValues) { if (zoom > currentZoom + REAL_DELTA) { d->setZoom(zoom, center); return; } } } void DocumentView::zoomOut(const QPointF& center) { qreal currentZoom = d->mAdapter->zoom(); QListIterator it(d->mZoomSnapValues); it.toBack(); while (it.hasPrevious()) { qreal zoom = it.previous(); if (zoom < currentZoom - REAL_DELTA) { d->setZoom(zoom, center); return; } } } void DocumentView::slotZoomChanged(qreal zoom) { d->updateCaption(); zoomChanged(zoom); } void DocumentView::setZoom(qreal zoom) { d->setZoom(zoom); } qreal DocumentView::zoom() const { return d->mAdapter->zoom(); } void DocumentView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) { if (event->modifiers() == Qt::NoModifier) { toggleFullScreenRequested(); } } void DocumentView::wheelEvent(QGraphicsSceneWheelEvent* event) { if (d->mAdapter->canZoom() && event->modifiers() & Qt::ControlModifier) { // Ctrl + wheel => zoom in or out if (event->delta() > 0) { zoomIn(event->pos()); } else { zoomOut(event->pos()); } return; } if (event->modifiers() == Qt::NoModifier && GwenviewConfig::mouseWheelBehavior() == MouseWheelBehavior::Browse ) { // Browse with mouse wheel if (event->delta() > 0) { previousImageRequested(); } else { nextImageRequested(); } } } void DocumentView::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) { // Filter out context menu if Ctrl is down to avoid showing it when // zooming out with Ctrl + Right button if (event->modifiers() != Qt::ControlModifier) { contextMenuRequested(); } } void DocumentView::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/) { if (!d->mCompareMode) { return; } if (d->mCurrent) { painter->save(); painter->setBrush(Qt::NoBrush); painter->setPen(QPen(palette().highlight().color(), 2)); painter->setRenderHint(QPainter::Antialiasing); QRectF selectionRect = boundingRect().adjusted(2, 2, -2, -2); painter->drawRoundedRect(selectionRect, 3, 3); painter->restore(); } } void DocumentView::slotBusyChanged(const KUrl&, bool busy) { if (busy) { d->showLoadingIndicator(); } else { d->hideLoadingIndicator(); } } qreal DocumentView::minimumZoom() const { // There is no point zooming out less than zoomToFit, but make sure it does // not get too small either return qMax(0.001, qMin(double(d->mAdapter->computeZoomToFit()), 1.)); } void DocumentView::setCompareMode(bool compare) { d->mCompareMode = compare; d->resizeAdapterWidget(); if (compare) { d->mHud->show(); d->mHud->setZValue(1); } else { d->mHud->hide(); } } void DocumentView::setCurrent(bool value) { d->mCurrent = value; if (value) { d->mAdapter->widget()->setFocus(); } update(); } bool DocumentView::isCurrent() const { return d->mCurrent; } QPoint DocumentView::position() const { // FIXME: QGV /* QAbstractScrollArea* area = qobject_cast(d->mAdapter->widget()); if (!area) { return QPoint(); } return QPoint( area->horizontalScrollBar()->value(), area->verticalScrollBar()->value() ); */ return QPoint(); } void DocumentView::setPosition(const QPoint& pos) { QAbstractScrollArea* area = qobject_cast(d->mAdapter->widget()); if (!area) { return; } area->horizontalScrollBar()->setValue(pos.x()); area->verticalScrollBar()->setValue(pos.y()); } void DocumentView::slotKeyPressed(Qt::Key key, bool pressed) { if (key == Qt::Key_Control) { if (pressed) { d->setZoomCursor(); } else { d->restoreCursor(); } } } Document::Ptr DocumentView::document() const { return d->mDocument; } KUrl DocumentView::url() const { Document::Ptr doc = d->mDocument; return doc ? doc->url() : KUrl(); } void DocumentView::emitHudDeselectClicked() { hudDeselectClicked(this); } void DocumentView::emitHudTrashClicked() { hudTrashClicked(this); } void DocumentView::emitFocused() { focused(this); } void DocumentView::setGeometry(const QRectF& rect) { QGraphicsWidget::setGeometry(rect); d->resizeAdapterWidget(); } void DocumentView::moveTo(const QRect& rect) { if (d->mMoveAnimation) { d->mMoveAnimation.data()->setEndValue(rect); } else { setGeometry(rect); } } void DocumentView::moveToAnimated(const QRect& rect) { QPropertyAnimation* anim = new QPropertyAnimation(this, "geometry"); anim->setStartValue(geometry()); anim->setEndValue(rect); d->animate(anim); d->mMoveAnimation = anim; } void DocumentView::fadeIn() { setOpacity(0); show(); QPropertyAnimation* anim = new QPropertyAnimation(this, "opacity"); anim->setStartValue(0.); anim->setEndValue(1.); d->animate(anim); } void DocumentView::fadeOut() { QPropertyAnimation* anim = new QPropertyAnimation(this, "opacity"); anim->setStartValue(1.); anim->setEndValue(0.); d->animate(anim); } void DocumentView::slotAnimationFinished() { animationFinished(this); } -bool DocumentView::sceneEventFilter(QGraphicsItem* item, QEvent* event) { +bool DocumentView::sceneEventFilter(QGraphicsItem*, QEvent* event) { if (event->type() == QEvent::GraphicsSceneMousePress) { QGraphicsSceneMouseEvent* mouseEvent = static_cast(event); d->adapterMousePressEvent(mouseEvent); } return false; } } // namespace diff --git a/lib/documentview/imageviewadapter.cpp b/lib/documentview/imageviewadapter.cpp index 42570d65..e2cd5a27 100644 --- a/lib/documentview/imageviewadapter.cpp +++ b/lib/documentview/imageviewadapter.cpp @@ -1,360 +1,360 @@ // vim: set tabstop=4 shiftwidth=4 noexpandtab: /* Gwenview: an image viewer Copyright 2008 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 "imageviewadapter.moc" // Qt #include #include // KDE #include // Local #include #include #include #include #include namespace Gwenview { struct RasterImageViewPrivate { RasterImageView* q; ImageScaler* mScaler; void startAnimationIfNecessary() { } void setScalerRegionToVisibleRect() { QRectF rect = q->mapViewportToZoomedImage(q->boundingRect()); mScaler->setDestinationRegion(QRegion(rect.toRect())); } }; RasterImageView::RasterImageView(QGraphicsItem* parent) : AbstractImageView(parent) , d(new RasterImageViewPrivate) { d->q = this; d->mScaler = new ImageScaler(this); connect(d->mScaler, SIGNAL(scaledRect(int,int,QImage)), SLOT(updateFromScaler(int,int,QImage)) ); } RasterImageView::~RasterImageView() { delete d; } void RasterImageView::setDocument(Document::Ptr doc) { AbstractImageView::setDocument(doc); 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; } createBuffer(); d->mScaler->setDocument(document()); connect(document().data(), SIGNAL(imageRectUpdated(QRect)), SLOT(updateImageRect(QRect)) ); if (zoomToFit()) { // Set the zoom to an invalid value to make sure setZoom() does not // return early because the new zoom is the same as the old zoom. // FIXME: QGV //d->mZoom = -1; setZoom(computeZoomToFit()); } else { QRect rect(QPoint(0, 0), document()->size()); updateImageRect(rect); } d->startAnimationIfNecessary(); update(); } -void RasterImageView::updateImageRect(const QRect& imageRect) { +void RasterImageView::updateImageRect(const QRect& /*imageRect*/) { // FIXME: QGV /* QRect viewportRect = mapToViewport(imageRect); viewportRect = viewportRect.intersected(d->mViewport->rect()); if (viewportRect.isEmpty()) { return; } */ if (zoomToFit()) { setZoom(computeZoomToFit()); } d->setScalerRegionToVisibleRect(); update(); } void RasterImageView::slotDocumentIsAnimatedUpdated() { d->startAnimationIfNecessary(); } void RasterImageView::updateBuffer() { d->mScaler->setZoom(zoom()); d->setScalerRegionToVisibleRect(); } void RasterImageView::updateFromScaler(int zoomedImageLeft, int zoomedImageTop, const QImage& image) { // FIXME: QGV int viewportLeft = zoomedImageLeft; // - d->hScroll(); int viewportTop = zoomedImageTop; // - d->vScroll(); { QPainter painter(&buffer()); /* if (d->mDocument->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); */ painter.setCompositionMode(QPainter::CompositionMode_Source); painter.drawImage(viewportLeft, viewportTop, image); } update(); } void RasterImageView::setZoom(qreal zoom, const QPointF& _center) { // FIXME: QGV #if 0 if (!d->mDocument) { return; } qreal oldZoom = d->mZoom; if (qAbs(zoom - oldZoom) < 0.001) { return; } // Get offset *before* setting mZoom, otherwise we get the new offset QPoint oldOffset = imageOffset(); d->mZoom = zoom; QPoint center; if (_center == QPoint(-1, -1)) { center = QPoint(d->mViewport->width() / 2, d->mViewport->height() / 2); } else { center = _center; } // 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 (d->mZoom < 2.) { d->mScaler->setTransformationMode(Qt::SmoothTransformation); } else { d->mScaler->setTransformationMode(Qt::FastTransformation); } d->createBuffer(); d->mInsideSetZoom = true; /* 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 = QPointF(d->hScroll(), d->vScroll()) - oldOffset; QPointF scroll = (zoom / oldZoom) * (oldScroll + center) - center; updateScrollBars(); horizontalScrollBar()->setValue(int(scroll.x())); verticalScrollBar()->setValue(int(scroll.y())); d->mInsideSetZoom = false; d->mScaler->setZoom(d->mZoom); d->setScalerRegionToVisibleRect(); emit zoomChanged(d->mZoom); #endif AbstractImageView::setZoom(zoom, _center); updateBuffer(); } //// ImageViewAdapter //// struct ImageViewAdapterPrivate { ImageViewAdapter* that; RasterImageView* mView; /* ScrollTool* mScrollTool; void setupScrollTool() { mScrollTool = new ScrollTool(mView); mView->setDefaultTool(mScrollTool); } */ }; ImageViewAdapter::ImageViewAdapter() : d(new ImageViewAdapterPrivate) { d->that = this; /* d->mView = new ImageView; QGraphicsProxyWidget* proxyWidget = new QGraphicsProxyWidget; proxyWidget->setWidget(d->mView); setWidget(proxyWidget); d->setupScrollTool(); connect(d->mView, SIGNAL(zoomChanged(qreal)), SIGNAL(zoomChanged(qreal)) ); */ d->mView = new RasterImageView; setWidget(d->mView); } ImageViewAdapter::~ImageViewAdapter() { delete d; } ImageView* ImageViewAdapter::imageView() const { // FIXME: QGV //return d->mView; return 0; } QCursor ImageViewAdapter::cursor() const { return d->mView->cursor(); } void ImageViewAdapter::setCursor(const QCursor& cursor) { d->mView->setCursor(cursor); } void ImageViewAdapter::setDocument(Document::Ptr doc) { d->mView->setDocument(doc); connect(doc.data(), SIGNAL(loadingFailed(KUrl)), SLOT(slotLoadingFailed()) ); if (doc->loadingState() == Document::LoadingFailed) { slotLoadingFailed(); } } qreal ImageViewAdapter::zoom() const { return d->mView->zoom(); } void ImageViewAdapter::setZoomToFit(bool on) { d->mView->setZoomToFit(on); } bool ImageViewAdapter::zoomToFit() const { return d->mView->zoomToFit(); } void ImageViewAdapter::setZoom(qreal zoom, const QPointF& center) { d->mView->setZoom(zoom, center); } qreal ImageViewAdapter::computeZoomToFit() const { return d->mView->computeZoomToFit(); } Document::Ptr ImageViewAdapter::document() const { return d->mView->document(); } void ImageViewAdapter::slotLoadingFailed() { d->mView->setDocument(Document::Ptr()); } void ImageViewAdapter::loadConfig() { // FIXME: QGV /* d->mView->setAlphaBackgroundMode(GwenviewConfig::alphaBackgroundMode()); d->mView->setAlphaBackgroundColor(GwenviewConfig::alphaBackgroundColor()); d->mView->setEnlargeSmallerImages(GwenviewConfig::enlargeSmallerImages()); */ } } // namespace diff --git a/part/gvpart.cpp b/part/gvpart.cpp index 1e740bb7..44d36a1a 100644 --- a/part/gvpart.cpp +++ b/part/gvpart.cpp @@ -1,199 +1,199 @@ /* Gwenview: an image viewer Copyright 2007-2008 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, Boston, MA 02110-1301, USA. */ #include "gvpart.moc" // Qt // KDE #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Local #include "../lib/document/document.h" #include "../lib/document/documentfactory.h" #include "../lib/documentview/documentview.h" #include "../lib/documentview/documentviewcontroller.h" #include "../lib/imageformats/imageformats.h" #include "../lib/urlutils.h" #include "../lib/version.h" #include "../lib/zoomwidget.h" #include "gvbrowserextension.h" //Factory Code K_PLUGIN_FACTORY(GVPartFactory, registerPlugin();) K_EXPORT_PLUGIN(GVPartFactory ) namespace Gwenview { -GVPart::GVPart(QWidget* parentWidget, QObject* parent, const QVariantList& /*args*/) +GVPart::GVPart(QWidget* /*parentWidget*/, QObject* parent, const QVariantList& /*args*/) : KParts::ReadOnlyPart(parent) { KGlobal::locale()->insertCatalog("gwenview"); // FIXME: QGV //mDocumentView = new DocumentView(parentWidget); //setWidget(mDocumentView); connect(mDocumentView, SIGNAL(captionUpdateRequested(QString)), SIGNAL(setWindowCaption(QString))); connect(mDocumentView, SIGNAL(completed()), SIGNAL(completed())); // FIXME: QGV //mDocumentView->setContextMenuPolicy(Qt::CustomContextMenu); connect(mDocumentView, SIGNAL(customContextMenuRequested(QPoint)), SLOT(showContextMenu()) ); // Necessary to have zoom actions DocumentViewController* documentViewController = new DocumentViewController(actionCollection(), this); documentViewController->setView(mDocumentView); KAction* action = new KAction(actionCollection()); action->setText(i18nc("@action", "Properties")); connect(action, SIGNAL(triggered()), SLOT(showProperties())); actionCollection()->addAction("file_show_properties", action); KStandardAction::saveAs(this, SLOT(saveAs()), actionCollection()); Gwenview::ImageFormats::registerPlugins(); new GVBrowserExtension(this); setXMLFile("gvpart/gvpart.rc"); } void GVPart::showProperties() { // FIXME: QGV //KPropertiesDialog::showDialog(url(), mDocumentView); } bool GVPart::openFile() { return false; } bool GVPart::openUrl(const KUrl& url) { if (!url.isValid()) { return false; } setUrl(url); Document::Ptr doc = DocumentFactory::instance()->load(url); if (arguments().reload()) { doc->reload(); } if (!UrlUtils::urlIsFastLocalFile(url)) { // Keep raw data of remote files to avoid downloading them again in // saveAs() doc->setKeepRawData(true); } mDocumentView->openUrl(url); return true; } KAboutData* GVPart::createAboutData() { KAboutData* aboutData = new KAboutData( "gvpart", /* appname */ "gwenview", /* catalogName */ ki18n("Gwenview KPart"), /* programName */ GWENVIEW_VERSION); /* version */ aboutData->setShortDescription(ki18n("An Image Viewer")); aboutData->setLicense(KAboutData::License_GPL); aboutData->setCopyrightStatement(ki18n("Copyright 2000-2010 Aurélien Gâteau")); aboutData->addAuthor( ki18n("Aurélien Gâteau"), ki18n("Main developer"), "agateau@kde.org"); return aboutData; } inline void addActionToMenu(KMenu* menu, KActionCollection* actionCollection, const char* name) { QAction* action = actionCollection->action(name); if (action) { menu->addAction(action); } } void GVPart::showContextMenu() { // FIXME QGV //KMenu menu(mDocumentView); KMenu menu; addActionToMenu(&menu, actionCollection(), "file_save_as"); menu.addSeparator(); addActionToMenu(&menu, actionCollection(), "view_actual_size"); addActionToMenu(&menu, actionCollection(), "view_zoom_to_fit"); addActionToMenu(&menu, actionCollection(), "view_zoom_in"); addActionToMenu(&menu, actionCollection(), "view_zoom_out"); menu.addSeparator(); addActionToMenu(&menu, actionCollection(), "file_show_properties"); menu.exec(QCursor::pos()); } void GVPart::saveAs() { KUrl srcUrl = url(); KUrl dstUrl = KFileDialog::getSaveUrl(srcUrl.fileName(), QString(), widget()); if (!dstUrl.isValid()) { return; } KIO::Job* job; Document::Ptr doc = DocumentFactory::instance()->load(srcUrl); QByteArray rawData = doc->rawData(); if (rawData.length() > 0) { job = KIO::storedPut(rawData, dstUrl, -1); } else { job = KIO::file_copy(srcUrl, dstUrl); } connect(job, SIGNAL(result(KJob*)), this, SLOT(showJobError(KJob*)) ); } void GVPart::showJobError(KJob* job) { if (job->error() != 0) { KIO::JobUiDelegate* ui = static_cast(job)->ui(); if (!ui) { kError() << "Saving failed. job->ui() is null."; return; } ui->setWindow(widget()); ui->showErrorMessage(); } } } // namespace