File indexing completed on 2024-05-12 04:06:25

0001 /*
0002     SPDX-FileCopyrightText: 2010 Johannes Loehnert <loehnert.kde@gmx.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "puzzlepreview.h"
0008 
0009 #include "../file-io/puzzlestructs.h"
0010 #include "settings.h"
0011 
0012 #include <cmath>
0013 #include <QMouseEvent>
0014 #include <QPainter>
0015 #include <KLocalizedString>
0016 
0017 Palapeli::PuzzlePreview::PuzzlePreview(QWidget* parent)
0018 {
0019     m_settingsSaveTimer = new QTimer(this);
0020     connect(m_settingsSaveTimer, &QTimer::timeout, this, &PuzzlePreview::writeConfigIfGeometryChanged);
0021     m_geometryChanged = false;
0022 
0023     m_hoverZoom = 1.0;
0024     m_isZoomed = false;
0025     m_mousePos = QPoint();
0026 
0027     setScene(new QGraphicsScene(this));
0028     setParent(parent);
0029     setWindowTitle(i18nc("@title:window", "Preview of completed puzzle"));
0030     setWindowFlags(Qt::Tool | Qt::WindowTitleHint);
0031     setAttribute (Qt::WA_NoMousePropagation); // Accept all mouse events.
0032     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
0033     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
0034     setRenderHint(QPainter::SmoothPixmapTransform);
0035     scene()->addText(i18nc("text in preview window",
0036         "Image is not available."));    // Seen if image-data not found.
0037     setSceneRect(scene()->itemsBoundingRect());
0038 
0039     // read size and position settings
0040     QRect geometry = Settings::puzzlePreviewGeometry();
0041     resize(geometry.size());
0042 
0043     // default (-1/-1) toprect: don't change position
0044     if (geometry.left() >= 0 && geometry.top() >= 0)
0045         move(geometry.topLeft());
0046 
0047     m_settingsSaveTimer->start(500);
0048     hide();
0049     updateViewport();
0050 }
0051 
0052 void Palapeli::PuzzlePreview::setImage(const QImage &image)
0053 {
0054     scene()->clear();
0055     scene()->addPixmap(QPixmap::fromImage(image));
0056     setSceneRect(image.rect());
0057     updateViewport();
0058 }
0059 
0060 void Palapeli::PuzzlePreview::loadImageFrom(const Palapeli::PuzzleMetadata& md)
0061 {
0062     // Metadata is assumed to have been loaded by the caller.
0063     setImage(md.image);
0064     setWindowTitle(i18nc("@title:window", "%1 - Preview", md.name));
0065     // Set hover-zoom so that 3x3 pieces would be visible on a square grid.
0066     m_hoverZoom = sqrt(md.pieceCount)/3.0;
0067     if (m_hoverZoom < 1)
0068         m_hoverZoom = 1;
0069 }
0070 
0071 void Palapeli::PuzzlePreview::toggleVisible()
0072 {
0073     setVisible(!isVisible());
0074     Settings::setPuzzlePreviewVisible(isVisible());
0075     Settings::self()->save();
0076 }
0077 
0078 void Palapeli::PuzzlePreview::mouseMoveEvent(QMouseEvent* event)
0079 {
0080     m_mousePos = event->pos();
0081     updateViewport();
0082     QGraphicsView::mouseMoveEvent(event);
0083 }
0084 
0085 void Palapeli::PuzzlePreview::enterEvent(QEnterEvent* event)
0086 {
0087     setMouseTracking(true);
0088     m_isZoomed = true;
0089     m_mousePos = QPoint();
0090     // wait with update for first mouseMoveEvent
0091     QGraphicsView::enterEvent(event);
0092 }
0093 
0094 void Palapeli::PuzzlePreview::leaveEvent(QEvent* event)
0095 {
0096     setMouseTracking(false);
0097     m_isZoomed = false;
0098     updateViewport();
0099     QGraphicsView::leaveEvent(event);
0100 }
0101 
0102 void Palapeli::PuzzlePreview::resizeEvent(QResizeEvent* event)
0103 {
0104     updateViewport();
0105     m_geometryChanged = true;
0106     QGraphicsView::resizeEvent(event);
0107 }
0108 
0109 void Palapeli::PuzzlePreview::moveEvent(QMoveEvent* event)
0110 {
0111     m_geometryChanged = true;
0112     QGraphicsView::moveEvent(event);
0113 }
0114 
0115 void Palapeli::PuzzlePreview::closeEvent(QCloseEvent* event)
0116 {
0117     // Triggered by the preview window's Close button.
0118     event->accept();
0119     Q_EMIT closing();
0120 }
0121 
0122 void Palapeli::PuzzlePreview::writeConfigIfGeometryChanged()
0123 {
0124     if (!m_geometryChanged) return;
0125 
0126     // move() includes window frame, resize() doesn't :-/
0127     Settings::setPuzzlePreviewGeometry(QRect(frameGeometry().topLeft(), size()));
0128     Settings::self()->save();
0129     m_geometryChanged = false;
0130 }
0131 
0132 void Palapeli::PuzzlePreview::updateViewport()
0133 {
0134     qreal zoom;
0135     // calculate zoom for fit-in-window
0136     zoom = width() / sceneRect().width();
0137     if (zoom > height() / sceneRect().height())
0138         zoom = height() / sceneRect().height();
0139 
0140     if (m_isZoomed)
0141         zoom *= m_hoverZoom;
0142 
0143     // do not enlarge
0144     if (zoom>1)
0145         zoom = 1;
0146 
0147     resetTransform();
0148     scale(zoom, zoom);
0149 
0150     if (m_isZoomed)
0151     {
0152         // focus moves with cursor position
0153         QPointF pos = m_mousePos;
0154         pos.rx() *= sceneRect().width() / width();
0155         pos.ry() *= sceneRect().height() / height();
0156         centerOn(pos);
0157     }
0158 }
0159 
0160 #include "moc_puzzlepreview.cpp"