1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the demonstration applications of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:BSD$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** BSD License Usage |
18 | ** Alternatively, you may use this file under the terms of the BSD license |
19 | ** as follows: |
20 | ** |
21 | ** "Redistribution and use in source and binary forms, with or without |
22 | ** modification, are permitted provided that the following conditions are |
23 | ** met: |
24 | ** * Redistributions of source code must retain the above copyright |
25 | ** notice, this list of conditions and the following disclaimer. |
26 | ** * Redistributions in binary form must reproduce the above copyright |
27 | ** notice, this list of conditions and the following disclaimer in |
28 | ** the documentation and/or other materials provided with the |
29 | ** distribution. |
30 | ** * Neither the name of The Qt Company Ltd nor the names of its |
31 | ** contributors may be used to endorse or promote products derived |
32 | ** from this software without specific prior written permission. |
33 | ** |
34 | ** |
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." |
46 | ** |
47 | ** $QT_END_LICENSE$ |
48 | ** |
49 | ****************************************************************************/ |
50 | |
51 | #include "view.h" |
52 | |
53 | #if defined(QT_PRINTSUPPORT_LIB) |
54 | #include <QtPrintSupport/qtprintsupportglobal.h> |
55 | #if QT_CONFIG(printdialog) |
56 | #include <QPrinter> |
57 | #include <QPrintDialog> |
58 | #endif |
59 | #endif |
60 | #ifndef QT_NO_OPENGL |
61 | #include <QtOpenGL> |
62 | #else |
63 | #include <QtWidgets> |
64 | #endif |
65 | #include <QtMath> |
66 | |
67 | #if QT_CONFIG(wheelevent) |
68 | void GraphicsView::wheelEvent(QWheelEvent *e) |
69 | { |
70 | if (e->modifiers() & Qt::ControlModifier) { |
71 | if (e->angleDelta().y() > 0) |
72 | view->zoomIn(level: 6); |
73 | else |
74 | view->zoomOut(level: 6); |
75 | e->accept(); |
76 | } else { |
77 | QGraphicsView::wheelEvent(event: e); |
78 | } |
79 | } |
80 | #endif |
81 | |
82 | View::View(const QString &name, QWidget *parent) |
83 | : QFrame(parent) |
84 | { |
85 | setFrameStyle(Sunken | StyledPanel); |
86 | graphicsView = new GraphicsView(this); |
87 | graphicsView->setRenderHint(hint: QPainter::Antialiasing, enabled: false); |
88 | graphicsView->setDragMode(QGraphicsView::RubberBandDrag); |
89 | graphicsView->setOptimizationFlags(QGraphicsView::DontSavePainterState); |
90 | graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate); |
91 | graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse); |
92 | |
93 | int size = style()->pixelMetric(metric: QStyle::PM_ToolBarIconSize); |
94 | QSize iconSize(size, size); |
95 | |
96 | QToolButton *zoomInIcon = new QToolButton; |
97 | zoomInIcon->setAutoRepeat(true); |
98 | zoomInIcon->setAutoRepeatInterval(33); |
99 | zoomInIcon->setAutoRepeatDelay(0); |
100 | zoomInIcon->setIcon(QPixmap(":/zoomin.png" )); |
101 | zoomInIcon->setIconSize(iconSize); |
102 | QToolButton *zoomOutIcon = new QToolButton; |
103 | zoomOutIcon->setAutoRepeat(true); |
104 | zoomOutIcon->setAutoRepeatInterval(33); |
105 | zoomOutIcon->setAutoRepeatDelay(0); |
106 | zoomOutIcon->setIcon(QPixmap(":/zoomout.png" )); |
107 | zoomOutIcon->setIconSize(iconSize); |
108 | zoomSlider = new QSlider; |
109 | zoomSlider->setMinimum(0); |
110 | zoomSlider->setMaximum(500); |
111 | zoomSlider->setValue(250); |
112 | zoomSlider->setTickPosition(QSlider::TicksRight); |
113 | |
114 | // Zoom slider layout |
115 | QVBoxLayout *zoomSliderLayout = new QVBoxLayout; |
116 | zoomSliderLayout->addWidget(zoomInIcon); |
117 | zoomSliderLayout->addWidget(zoomSlider); |
118 | zoomSliderLayout->addWidget(zoomOutIcon); |
119 | |
120 | QToolButton *rotateLeftIcon = new QToolButton; |
121 | rotateLeftIcon->setIcon(QPixmap(":/rotateleft.png" )); |
122 | rotateLeftIcon->setIconSize(iconSize); |
123 | QToolButton *rotateRightIcon = new QToolButton; |
124 | rotateRightIcon->setIcon(QPixmap(":/rotateright.png" )); |
125 | rotateRightIcon->setIconSize(iconSize); |
126 | rotateSlider = new QSlider; |
127 | rotateSlider->setOrientation(Qt::Horizontal); |
128 | rotateSlider->setMinimum(-360); |
129 | rotateSlider->setMaximum(360); |
130 | rotateSlider->setValue(0); |
131 | rotateSlider->setTickPosition(QSlider::TicksBelow); |
132 | |
133 | // Rotate slider layout |
134 | QHBoxLayout *rotateSliderLayout = new QHBoxLayout; |
135 | rotateSliderLayout->addWidget(rotateLeftIcon); |
136 | rotateSliderLayout->addWidget(rotateSlider); |
137 | rotateSliderLayout->addWidget(rotateRightIcon); |
138 | |
139 | resetButton = new QToolButton; |
140 | resetButton->setText(tr(s: "0" )); |
141 | resetButton->setEnabled(false); |
142 | |
143 | // Label layout |
144 | QHBoxLayout *labelLayout = new QHBoxLayout; |
145 | label = new QLabel(name); |
146 | label2 = new QLabel(tr(s: "Pointer Mode" )); |
147 | selectModeButton = new QToolButton; |
148 | selectModeButton->setText(tr(s: "Select" )); |
149 | selectModeButton->setCheckable(true); |
150 | selectModeButton->setChecked(true); |
151 | dragModeButton = new QToolButton; |
152 | dragModeButton->setText(tr(s: "Drag" )); |
153 | dragModeButton->setCheckable(true); |
154 | dragModeButton->setChecked(false); |
155 | antialiasButton = new QToolButton; |
156 | antialiasButton->setText(tr(s: "Antialiasing" )); |
157 | antialiasButton->setCheckable(true); |
158 | antialiasButton->setChecked(false); |
159 | openGlButton = new QToolButton; |
160 | openGlButton->setText(tr(s: "OpenGL" )); |
161 | openGlButton->setCheckable(true); |
162 | #ifndef QT_NO_OPENGL |
163 | openGlButton->setEnabled(QGLFormat::hasOpenGL()); |
164 | #else |
165 | openGlButton->setEnabled(false); |
166 | #endif |
167 | printButton = new QToolButton; |
168 | printButton->setIcon(QIcon(QPixmap(":/fileprint.png" ))); |
169 | |
170 | QButtonGroup *pointerModeGroup = new QButtonGroup(this); |
171 | pointerModeGroup->setExclusive(true); |
172 | pointerModeGroup->addButton(selectModeButton); |
173 | pointerModeGroup->addButton(dragModeButton); |
174 | |
175 | labelLayout->addWidget(label); |
176 | labelLayout->addStretch(); |
177 | labelLayout->addWidget(label2); |
178 | labelLayout->addWidget(selectModeButton); |
179 | labelLayout->addWidget(dragModeButton); |
180 | labelLayout->addStretch(); |
181 | labelLayout->addWidget(antialiasButton); |
182 | labelLayout->addWidget(openGlButton); |
183 | labelLayout->addWidget(printButton); |
184 | |
185 | QGridLayout *topLayout = new QGridLayout; |
186 | topLayout->addLayout(labelLayout, row: 0, column: 0); |
187 | topLayout->addWidget(graphicsView, row: 1, column: 0); |
188 | topLayout->addLayout(zoomSliderLayout, row: 1, column: 1); |
189 | topLayout->addLayout(rotateSliderLayout, row: 2, column: 0); |
190 | topLayout->addWidget(resetButton, row: 2, column: 1); |
191 | setLayout(topLayout); |
192 | |
193 | connect(sender: resetButton, signal: &QAbstractButton::clicked, receiver: this, slot: &View::resetView); |
194 | connect(sender: zoomSlider, signal: &QAbstractSlider::valueChanged, receiver: this, slot: &View::setupMatrix); |
195 | connect(sender: rotateSlider, signal: &QAbstractSlider::valueChanged, receiver: this, slot: &View::setupMatrix); |
196 | connect(sender: graphicsView->verticalScrollBar(), signal: &QAbstractSlider::valueChanged, |
197 | receiver: this, slot: &View::setResetButtonEnabled); |
198 | connect(sender: graphicsView->horizontalScrollBar(), signal: &QAbstractSlider::valueChanged, |
199 | receiver: this, slot: &View::setResetButtonEnabled); |
200 | connect(sender: selectModeButton, signal: &QAbstractButton::toggled, receiver: this, slot: &View::togglePointerMode); |
201 | connect(sender: dragModeButton, signal: &QAbstractButton::toggled, receiver: this, slot: &View::togglePointerMode); |
202 | connect(sender: antialiasButton, signal: &QAbstractButton::toggled, receiver: this, slot: &View::toggleAntialiasing); |
203 | connect(sender: openGlButton, signal: &QAbstractButton::toggled, receiver: this, slot: &View::toggleOpenGL); |
204 | connect(sender: rotateLeftIcon, signal: &QAbstractButton::clicked, receiver: this, slot: &View::rotateLeft); |
205 | connect(sender: rotateRightIcon, signal: &QAbstractButton::clicked, receiver: this, slot: &View::rotateRight); |
206 | connect(sender: zoomInIcon, signal: &QAbstractButton::clicked, receiver: this, slot: &View::zoomIn); |
207 | connect(sender: zoomOutIcon, signal: &QAbstractButton::clicked, receiver: this, slot: &View::zoomOut); |
208 | connect(sender: printButton, signal: &QAbstractButton::clicked, receiver: this, slot: &View::print); |
209 | |
210 | setupMatrix(); |
211 | } |
212 | |
213 | QGraphicsView *View::view() const |
214 | { |
215 | return static_cast<QGraphicsView *>(graphicsView); |
216 | } |
217 | |
218 | void View::resetView() |
219 | { |
220 | zoomSlider->setValue(250); |
221 | rotateSlider->setValue(0); |
222 | setupMatrix(); |
223 | graphicsView->ensureVisible(rect: QRectF(0, 0, 0, 0)); |
224 | |
225 | resetButton->setEnabled(false); |
226 | } |
227 | |
228 | void View::setResetButtonEnabled() |
229 | { |
230 | resetButton->setEnabled(true); |
231 | } |
232 | |
233 | void View::setupMatrix() |
234 | { |
235 | qreal scale = qPow(x: qreal(2), y: (zoomSlider->value() - 250) / qreal(50)); |
236 | |
237 | QTransform matrix; |
238 | matrix.scale(sx: scale, sy: scale); |
239 | matrix.rotate(a: rotateSlider->value()); |
240 | |
241 | graphicsView->setTransform(matrix); |
242 | setResetButtonEnabled(); |
243 | } |
244 | |
245 | void View::togglePointerMode() |
246 | { |
247 | graphicsView->setDragMode(selectModeButton->isChecked() |
248 | ? QGraphicsView::RubberBandDrag |
249 | : QGraphicsView::ScrollHandDrag); |
250 | graphicsView->setInteractive(selectModeButton->isChecked()); |
251 | } |
252 | |
253 | void View::toggleOpenGL() |
254 | { |
255 | #ifndef QT_NO_OPENGL |
256 | graphicsView->setViewport(openGlButton->isChecked() ? new QGLWidget(QGLFormat(QGL::SampleBuffers)) : new QWidget); |
257 | #endif |
258 | } |
259 | |
260 | void View::toggleAntialiasing() |
261 | { |
262 | graphicsView->setRenderHint(hint: QPainter::Antialiasing, enabled: antialiasButton->isChecked()); |
263 | } |
264 | |
265 | void View::print() |
266 | { |
267 | #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printdialog) |
268 | QPrinter printer; |
269 | QPrintDialog dialog(&printer, this); |
270 | if (dialog.exec() == QDialog::Accepted) { |
271 | QPainter painter(&printer); |
272 | graphicsView->render(painter: &painter); |
273 | } |
274 | #endif |
275 | } |
276 | |
277 | void View::zoomIn(int level) |
278 | { |
279 | zoomSlider->setValue(zoomSlider->value() + level); |
280 | } |
281 | |
282 | void View::zoomOut(int level) |
283 | { |
284 | zoomSlider->setValue(zoomSlider->value() - level); |
285 | } |
286 | |
287 | void View::rotateLeft() |
288 | { |
289 | rotateSlider->setValue(rotateSlider->value() - 10); |
290 | } |
291 | |
292 | void View::rotateRight() |
293 | { |
294 | rotateSlider->setValue(rotateSlider->value() + 10); |
295 | } |
296 | |