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 examples 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
52#include "paintarea.h"
53#include "interfaces.h"
54
55#include <QMouseEvent>
56#include <QPainter>
57
58PaintArea::PaintArea(QWidget *parent) : QWidget(parent)
59{
60 setAttribute(Qt::WA_StaticContents);
61 setAttribute(Qt::WA_OpaquePaintEvent);
62
63 theImage.fill(qRgb(255, 255, 255));
64}
65
66bool PaintArea::openImage(const QString &fileName)
67{
68 QImage image;
69 if (!image.load(fileName))
70 return false;
71
72 setImage(image);
73 return true;
74}
75
76bool PaintArea::saveImage(const QString &fileName, const char *fileFormat)
77{
78 return theImage.save(fileName, fileFormat);
79}
80
81void PaintArea::setImage(const QImage &image)
82{
83 theImage = image.convertToFormat(QImage::Format_RGB32);
84 update();
85 updateGeometry();
86}
87
88void PaintArea::insertShape(const QPainterPath &path)
89{
90 pendingPath = path;
91#ifndef QT_NO_CURSOR
92 setCursor(Qt::CrossCursor);
93#endif
94}
95
96void PaintArea::setBrushColor(const QColor &color)
97{
98 this->color = color;
99}
100
101void PaintArea::setBrushWidth(int width)
102{
103 thickness = width;
104}
105
106//! [0]
107void PaintArea::setBrush(BrushInterface *brushInterface, const QString &brush)
108{
109 this->brushInterface = brushInterface;
110 this->brush = brush;
111}
112//! [0]
113
114QSize PaintArea::sizeHint() const
115{
116 return theImage.size();
117}
118
119void PaintArea::paintEvent(QPaintEvent * /* event */)
120{
121 QPainter painter(this);
122 painter.drawImage(QPoint(0, 0), theImage);
123}
124
125void PaintArea::mousePressEvent(QMouseEvent *event)
126{
127 if (event->button() == Qt::LeftButton) {
128 if (!pendingPath.isEmpty()) {
129 QPainter painter(&theImage);
130 setupPainter(painter);
131
132 const QRectF boundingRect = pendingPath.boundingRect();
133 QLinearGradient gradient(boundingRect.topRight(),
134 boundingRect.bottomLeft());
135 gradient.setColorAt(0.0, QColor(color.red(), color.green(),
136 color.blue(), 63));
137 gradient.setColorAt(1.0, QColor(color.red(), color.green(),
138 color.blue(), 191));
139 painter.setBrush(gradient);
140 painter.translate(event->position().toPoint() - boundingRect.center());
141 painter.drawPath(pendingPath);
142
143 pendingPath = QPainterPath();
144#ifndef QT_NO_CURSOR
145 unsetCursor();
146#endif
147 update();
148 } else {
149 if (brushInterface) {
150 QPainter painter(&theImage);
151 setupPainter(painter);
152 const QRect rect = brushInterface->mousePress(brush, painter,
153 event->position().toPoint());
154 update(rect);
155 }
156
157 lastPos = event->position().toPoint();
158 }
159 }
160}
161
162//! [1]
163void PaintArea::mouseMoveEvent(QMouseEvent *event)
164{
165 if ((event->buttons() & Qt::LeftButton) && lastPos != QPoint(-1, -1)) {
166 if (brushInterface) {
167 QPainter painter(&theImage);
168 setupPainter(painter);
169 const QRect rect = brushInterface->mouseMove(brush, painter, lastPos,
170 event->position().toPoint());
171 update(rect);
172 }
173
174 lastPos = event->position().toPoint();
175 }
176}
177//! [1]
178
179void PaintArea::mouseReleaseEvent(QMouseEvent *event)
180{
181 if (event->button() == Qt::LeftButton && lastPos != QPoint(-1, -1)) {
182 if (brushInterface) {
183 QPainter painter(&theImage);
184 setupPainter(painter);
185 QRect rect = brushInterface->mouseRelease(brush, painter,
186 event->position().toPoint());
187 update(rect);
188 }
189
190 lastPos = QPoint(-1, -1);
191 }
192}
193
194void PaintArea::setupPainter(QPainter &painter)
195{
196 painter.setRenderHint(QPainter::Antialiasing, true);
197 painter.setPen(QPen(color, thickness, Qt::SolidLine, Qt::RoundCap,
198 Qt::RoundJoin));
199}
200