1 /*
2 SPDX-FileCopyrightText: 2008-2019 Graeme Gott <graeme@gottcode.org>
3
4 SPDX-License-Identifier: GPL-3.0-or-later
5 */
6
7 #include "overview.h"
8
9 #include "zoom_slider.h"
10
11 #include <QGraphicsPixmapItem>
12 #include <QGraphicsScene>
13 #include <QIcon>
14 #include <QSettings>
15 #include <QWheelEvent>
16
17 #include <algorithm>
18 #include <cmath>
19
20 //-----------------------------------------------------------------------------
21
Overview(QWidget * parent)22 Overview::Overview(QWidget* parent)
23 : QGraphicsView(parent)
24 , m_min_scale_level(0)
25 , m_scale_level(0)
26 {
27 setWindowTitle(tr("Overview"));
28 setWindowFlags(Qt::Tool);
29
30 setBackgroundBrush(Qt::darkGray);
31 setBackgroundRole(QPalette::Window);
32 setRenderHint(QPainter::SmoothPixmapTransform, true);
33 setDragMode(ScrollHandDrag);
34 setFrameStyle(NoFrame);
35
36 // Create scene
37 QGraphicsScene* scene = new QGraphicsScene(this);
38 setScene(scene);
39 m_pixmap = new QGraphicsPixmapItem;
40 m_pixmap->setTransformationMode(Qt::SmoothTransformation);
41 scene->addItem(m_pixmap);
42 reset();
43
44 // Restore geometry
45 QSettings settings;
46 if (settings.contains("Overview/Geometry")) {
47 restoreGeometry(settings.value("Overview/Geometry").toByteArray());
48 setMinimumSize(size());
49 } else {
50 resize(400, 400);
51 setMinimumSize(size());
52 }
53 m_default = settings.value("Overview/Default", true).toBool();
54 }
55
56 //-----------------------------------------------------------------------------
57
load(const QImage & image,qreal pixelratio)58 void Overview::load(const QImage& image, qreal pixelratio)
59 {
60 // Find minimum scale
61 m_min_scale_level = 9;
62 int side_max = std::max(image.width(), image.height()) * 0.9;
63 int side = 400;
64 if (side_max > side) {
65 for (int i = 9; i >= 0; --i) {
66 int side_test = std::floor(400.0 / ZoomSlider::scaleFactor(i));
67 if (side_test > side_max) {
68 break;
69 }
70 m_min_scale_level = i;
71 side = side_test;
72 }
73 } else {
74 side = side_max;
75 }
76 QPixmap pixmap = QPixmap::fromImage(image.scaled(side * pixelratio, side * pixelratio, Qt::KeepAspectRatio, Qt::SmoothTransformation), Qt::AutoColor | Qt::AvoidDither);
77 pixmap.setDevicePixelRatio(pixelratio);
78 zoom(m_min_scale_level);
79
80 // Resize window
81 bool default_size = m_default;
82 QSize size = transform().mapRect(QRect(QPoint(0,0), pixmap.size() / pixelratio)).size();
83 setMinimumSize(size);
84 if (default_size) {
85 resize(minimumSize());
86 }
87
88 // Show overview
89 setPixmap(pixmap);
90 }
91
92 //-----------------------------------------------------------------------------
93
reset()94 void Overview::reset()
95 {
96 // Prevent zooming
97 m_min_scale_level = 9;
98 zoom(m_min_scale_level);
99
100 // Show loading icon
101 setPixmap(QIcon::fromTheme("image-loading", QIcon(":/tango/image-loading.png")).pixmap(128,128));
102 }
103
104 //-----------------------------------------------------------------------------
105
moveEvent(QMoveEvent * event)106 void Overview::moveEvent(QMoveEvent* event)
107 {
108 QSettings().setValue("Overview/Geometry", saveGeometry());
109 QGraphicsView::moveEvent(event);
110 }
111
112 //-----------------------------------------------------------------------------
113
hideEvent(QHideEvent * event)114 void Overview::hideEvent(QHideEvent* event)
115 {
116 emit toggled(false);
117 QGraphicsView::hideEvent(event);
118 }
119
120 //-----------------------------------------------------------------------------
121
resizeEvent(QResizeEvent * event)122 void Overview::resizeEvent(QResizeEvent* event)
123 {
124 m_default = (size() == minimumSize());
125 QSettings settings;
126 settings.setValue("Overview/Default", m_default);
127 settings.setValue("Overview/Geometry", saveGeometry());
128 QGraphicsView::resizeEvent(event);
129 }
130
131 //-----------------------------------------------------------------------------
132
showEvent(QShowEvent * event)133 void Overview::showEvent(QShowEvent* event)
134 {
135 emit toggled(true);
136 QGraphicsView::showEvent(event);
137 }
138
139 //-----------------------------------------------------------------------------
140
wheelEvent(QWheelEvent * event)141 void Overview::wheelEvent(QWheelEvent* event)
142 {
143 if (event->angleDelta().y() > 0) {
144 zoomIn();
145 } else {
146 zoomOut();
147 }
148 event->accept();
149 }
150
151 //-----------------------------------------------------------------------------
152
setPixmap(const QPixmap & pixmap)153 void Overview::setPixmap(const QPixmap& pixmap)
154 {
155 m_pixmap->setPixmap(pixmap);
156 scene()->setSceneRect(m_pixmap->boundingRect());
157 centerOn(m_pixmap);
158 }
159
160 //-----------------------------------------------------------------------------
161
zoomIn()162 void Overview::zoomIn()
163 {
164 zoom(m_scale_level + 1);
165 }
166
167 //-----------------------------------------------------------------------------
168
zoomOut()169 void Overview::zoomOut()
170 {
171 zoom(m_scale_level - 1);
172 }
173
174 //-----------------------------------------------------------------------------
175
zoom(int level)176 void Overview::zoom(int level)
177 {
178 m_scale_level = qBound(m_min_scale_level, level, 9);
179 float s = ZoomSlider::scaleFactor(m_scale_level);
180 resetTransform();
181 scale(s, s);
182
183 Qt::ScrollBarPolicy policy = (m_scale_level > m_min_scale_level) ? Qt::ScrollBarAsNeeded : Qt::ScrollBarAlwaysOff;
184 setHorizontalScrollBarPolicy(policy);
185 setVerticalScrollBarPolicy(policy);
186 }
187
188 //-----------------------------------------------------------------------------
189