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