1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qtgradientdialog.h"
5#include "ui_qtgradientdialog.h"
6#include <QtWidgets/QPushButton>
7
8QT_BEGIN_NAMESPACE
9
10class QtGradientDialogPrivate : public QObject
11{
12 Q_OBJECT
13 QtGradientDialog *q_ptr;
14 Q_DECLARE_PUBLIC(QtGradientDialog)
15public:
16 void slotAboutToShowDetails(bool details, int extensionWidthHint);
17
18 Ui::QtGradientDialog m_ui;
19};
20
21void QtGradientDialogPrivate::slotAboutToShowDetails(bool details, int extensionWidthHint)
22{
23 if (details) {
24 q_ptr->resize(q_ptr->size() + QSize(extensionWidthHint, 0));
25 } else {
26 q_ptr->setMinimumSize(minw: 1, minh: 1);
27 q_ptr->resize(q_ptr->size() - QSize(extensionWidthHint, 0));
28 q_ptr->setMinimumSize(minw: 0, minh: 0);
29 }
30}
31
32/*!
33 \class QtGradientDialog
34
35 \brief The QtGradientDialog class provides a dialog for specifying gradients.
36
37 The gradient dialog's function is to allow users to edit gradients.
38 For example, you might use this in a drawing program to allow the user to set the brush gradient.
39
40 \table
41 \row
42 \li \inlineimage qtgradientdialog.png
43 \li \inlineimage qtgradientdialogextension.png
44 \header
45 \li Details extension hidden
46 \li Details extension visible
47 \endtable
48
49 Starting from the top of the dialog there are several buttons:
50
51 \image qtgradientdialogtopbuttons.png
52
53 The first three buttons allow for changing a type of the gradient (QGradient::Type), while the second three allow for
54 changing spread of the gradient (QGradient::Spread). The last button shows or hides the details extension of the dialog.
55 Conceptually the default view with hidden details provides the full functional control over gradient editing.
56 The additional extension with details allows to set gradient's parameters more precisely. The visibility
57 of extension can be controlled by detailsVisible property. Moreover, if you don't want the user to
58 switch on or off the visibility of extension you can set the detailsButtonVisible property to false.
59
60 Below top buttons there is an area where edited gradient is interactively previewed.
61 In addition the user can edit gradient type's specific parameters directly in this area by dragging
62 appropriate handles.
63
64 \table
65 \row
66 \li \inlineimage qtgradientdialoglineareditor.png
67 \li \inlineimage qtgradientdialogradialeditor.png
68 \li \inlineimage qtgradientdialogconicaleditor.png
69 \header
70 \li Editing linear type
71 \li Editing radial type
72 \li Editing conical type
73 \row
74 \li The user can change the start and final point positions by dragging the circular handles.
75 \li The user can change the center and focal point positions by dragging the circular handles
76 and can change the gradient's radius by dragging horizontal or vertical line.
77 \li The user can change the center point by dragging the circular handle
78 and can change the gradient's angle by dragging the big wheel.
79 \endtable
80
81 In the middle of the dialog there is an area where the user can edit gradient stops.
82
83 \table
84 \row
85 \li \inlineimage qtgradientdialogstops.png
86 \li \inlineimage qtgradientdialogstopszoomed.png
87 \endtable
88
89 The top part of this area contains stop handles, and bottom part shows the preview of gradient stops path.
90 In order to create a new gradient stop double click inside the view over the desired position.
91 If you double click on existing stop handle in the top part of the view, clicked handle will be duplicated
92 (duplicate will contain the same color).
93 The stop can be activated by clicking on its handle. You can activate previous or next stop by pressing
94 left or right key respectively. To jump to the first or last stop press home or end key respectively.
95 The gradient stops editor supports multiselection.
96 Clicking a handle holding the shift modifier key down will select a range of stops between
97 the active stop and clicked one. Clicking a handle holding control modifier key down will remove from or
98 add to selection the clicked stop depending if it was or wasn't already selected respectively.
99 Multiselection can also be created using rubberband (by pressing the left mouse button outside
100 of any handle and dragging).
101 Sometimes it's hard to select a stop because its handle can be partially covered by other handle.
102 In that case the user can zoom in the view by spinning mouse wheel.
103 The selected stop handles can be moved by drag & drop. In order to remove selected stops press delete key.
104 For convenience context menu is provided with the following actions:
105
106 \list
107 \li New Stop - creates a new gradient stop
108 \li Delete - removes the active and all selected stops
109 \li Flip All - mirrors all stops
110 \li Select All - selects all stops
111 \li Zoom In - zooms in
112 \li Zoom Out - zooms out
113 \li Zoom All - goes back to original 100% zoom
114 \endlist
115
116 The bottom part of the QtGradientDialog contains a set of widgets allowing to control the color of
117 the active and selected stops.
118
119 \table
120 \row
121 \li \inlineimage qtgradientdialogcolorhsv.png
122 \li \inlineimage qtgradientdialogcolorrgb.png
123 \endtable
124
125
126 The color button shows the color of the active gradient stop. It also allows for choosing
127 a color from standard color dialog and applying it to the
128 active stop and all selected stops. It's also possible to drag a color directly from the color button
129 and to drop it in gradient stops editor at desired position (it will create new stop with dragged color)
130 or at desired stop handle (it will change the color of that handle).
131
132 To the right of color button there is a set of 2 radio buttons which allows to switch between
133 HVS and RGB color spec.
134
135 Finally there are 4 color sliders working either in HSVA (hue saturation value alpha) or
136 RGBA (red green blue alpha) mode, depending on which radio button is chosen. The radio buttons
137 can be controlled programatically by spec() and setSpec() methods. The sliders show the
138 color of the active stop. By double clicking inside color slider you can set directly the desired color.
139 Changes of slider's are applied to stop selection in the way that the color
140 component being changed is applied to stops in selection only, while other components
141 remain unchanged in selected stops (e.g. when the user is changing the saturation,
142 new saturation is applied to selected stops preventing original hue, value and alpha in multiselection).
143
144 The convenient static functions getGradient() provide modal gradient dialogs, e.g.:
145
146 \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 0
147
148 In order to have more control over the properties of QtGradientDialog use
149 standard QDialog::exec() method:
150
151 \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 1
152
153 \sa {Gradient View Example}
154*/
155
156/*!
157 Constructs a gradient dialog with \a parent as parent widget.
158*/
159
160QtGradientDialog::QtGradientDialog(QWidget *parent)
161 : QDialog(parent), d_ptr(new QtGradientDialogPrivate())
162{
163// setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
164 d_ptr->q_ptr = this;
165 d_ptr->m_ui.setupUi(this);
166 QPushButton *button = d_ptr->m_ui.buttonBox->button(QDialogButtonBox::Ok);
167 if (button)
168 button->setAutoDefault(false);
169 button = d_ptr->m_ui.buttonBox->button(QDialogButtonBox::Cancel);
170 if (button)
171 button->setAutoDefault(false);
172 connect(d_ptr->m_ui.gradientEditor, &QtGradientEditor::aboutToShowDetails,
173 d_ptr.data(), &QtGradientDialogPrivate::slotAboutToShowDetails);
174}
175
176/*!
177 Destroys the gradient dialog
178*/
179
180QtGradientDialog::~QtGradientDialog()
181{
182}
183
184/*!
185 \property QtGradientDialog::gradient
186 \brief the gradient of the dialog
187*/
188void QtGradientDialog::setGradient(const QGradient &gradient)
189{
190 d_ptr->m_ui.gradientEditor->setGradient(gradient);
191}
192
193QGradient QtGradientDialog::gradient() const
194{
195 return d_ptr->m_ui.gradientEditor->gradient();
196}
197
198/*!
199 \property QtGradientDialog::backgroundCheckered
200 \brief whether the background of widgets able to show the colors with alpha channel is checkered.
201
202 \table
203 \row
204 \li \inlineimage qtgradientdialogbackgroundcheckered.png
205 \li \inlineimage qtgradientdialogbackgroundtransparent.png
206 \row
207 \li \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 2
208 \li \snippet doc/src/snippets/code/tools_shared_qtgradienteditor_qtgradientdialog.cpp 3
209 \endtable
210
211 When this property is set to true (the default) widgets inside gradient dialog like color button,
212 color sliders, gradient stops editor and gradient editor will show checkered background
213 in case of transparent colors. Otherwise the background of these widgets is transparent.
214*/
215
216bool QtGradientDialog::isBackgroundCheckered() const
217{
218 return d_ptr->m_ui.gradientEditor->isBackgroundCheckered();
219}
220
221void QtGradientDialog::setBackgroundCheckered(bool checkered)
222{
223 d_ptr->m_ui.gradientEditor->setBackgroundCheckered(checkered);
224}
225
226/*!
227 \property QtGradientDialog::detailsVisible
228 \brief whether details extension is visible.
229
230 When this property is set to true the details extension is visible. By default
231 this property is set to false and the details extension is hidden.
232
233 \sa detailsButtonVisible
234*/
235bool QtGradientDialog::detailsVisible() const
236{
237 return d_ptr->m_ui.gradientEditor->detailsVisible();
238}
239
240void QtGradientDialog::setDetailsVisible(bool visible)
241{
242 d_ptr->m_ui.gradientEditor->setDetailsVisible(visible);
243}
244
245/*!
246 \property QtGradientDialog::detailsButtonVisible
247 \brief whether the details button allowing for showing and hiding details extension is visible.
248
249 When this property is set to true (the default) the details button is visible and the user
250 can show and hide details extension interactively. Otherwise the button is hidden and the details
251 extension is always visible or hidded depending on the value of detailsVisible property.
252
253 \sa detailsVisible
254*/
255bool QtGradientDialog::isDetailsButtonVisible() const
256{
257 return d_ptr->m_ui.gradientEditor->isDetailsButtonVisible();
258}
259
260void QtGradientDialog::setDetailsButtonVisible(bool visible)
261{
262 d_ptr->m_ui.gradientEditor->setDetailsButtonVisible(visible);
263}
264
265/*!
266 Returns the current QColor::Spec used for the color sliders in the dialog.
267*/
268QColor::Spec QtGradientDialog::spec() const
269{
270 return d_ptr->m_ui.gradientEditor->spec();
271}
272
273/*!
274 Sets the current QColor::Spec to \a spec used for the color sliders in the dialog.
275*/
276void QtGradientDialog::setSpec(QColor::Spec spec)
277{
278 d_ptr->m_ui.gradientEditor->setSpec(spec);
279}
280
281/*!
282 Executes a modal gradient dialog, lets the user to specify a gradient, and returns that gradient.
283
284 If the user clicks \gui OK, the gradient specified by the user is returned. If the user clicks \gui Cancel, the \a initial gradient is returned.
285
286 The dialog is constructed with the given \a parent. \a caption is shown as the window title of the dialog and
287 \a initial is the initial gradient shown in the dialog. If the \a ok parameter is not-null,
288 the value it refers to is set to true if the user clicks \gui OK, and set to false if the user clicks \gui Cancel.
289*/
290QGradient QtGradientDialog::getGradient(bool *ok, const QGradient &initial, QWidget *parent, const QString &caption)
291{
292 QtGradientDialog dlg(parent);
293 if (!caption.isEmpty())
294 dlg.setWindowTitle(caption);
295 dlg.setGradient(initial);
296 const int res = dlg.exec();
297 if (ok) {
298 *ok = (res == QDialog::Accepted) ? true : false;
299 }
300 if (res == QDialog::Accepted)
301 return dlg.gradient();
302 return initial;
303}
304
305/*!
306 This method calls getGradient(ok, QLinearGradient(), parent, caption).
307*/
308QGradient QtGradientDialog::getGradient(bool *ok, QWidget *parent, const QString &caption)
309{
310 return getGradient(ok, initial: QLinearGradient(), parent, caption);
311}
312
313QT_END_NAMESPACE
314
315#include "qtgradientdialog.moc"
316

source code of qttools/src/shared/qtgradienteditor/qtgradientdialog.cpp