1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 /***************************************************************************
8 gradienteditor - description
9 -------------------
10 begin : Mit Mai 26 2004
11 copyright : (C) 2004 by Franz Schmid
12 email : Franz.Schmid@altmuehlnet.de
13 ***************************************************************************/
14
15 /***************************************************************************
16 * *
17 * This program is free software; you can redistribute it and/or modify *
18 * it under the terms of the GNU General Public License as published by *
19 * the Free Software Foundation; either version 2 of the License, or *
20 * (at your option) any later version. *
21 * *
22 ***************************************************************************/
23
24 #include "dasheditor.h"
25
26 #include <algorithm>
27
28 #include <QApplication>
29 #include <QCursor>
30 #include <QDoubleSpinBox>
31 #include <QEvent>
32 #include <QLabel>
33 #include <QMouseEvent>
34 #include <QPaintEvent>
35 #include <QPainter>
36 #include <QPixmap>
37 #include <QPolygon>
38 #include <QSignalBlocker>
39 #include <QToolTip>
40
41 #include "scpainter.h"
42 #include "fpoint.h"
43 #include "iconmanager.h"
44
DashPreview(QWidget * pa)45 DashPreview::DashPreview(QWidget *pa) : QFrame(pa)
46 {
47 setFrameShape( QFrame::Panel );
48 setFrameShadow( QFrame::Sunken );
49 setLineWidth( 2 );
50 setMinimumSize(QSize(200, 35));
51 setMaximumSize(QSize(3000, 35));
52 setMouseTracking(true);
53
54 m_dashValues.clear();
55 m_dashValues.append(4.0);
56 m_dashValues.append(2.0);
57 }
58
paintEvent(QPaintEvent * e)59 void DashPreview::paintEvent(QPaintEvent *e)
60 {
61 if (m_onlySelect)
62 m_stops.clear();
63
64 int pWidth = width() - 20;
65 QImage pixm(pWidth, 10, QImage::Format_ARGB32_Premultiplied);
66
67 ScPainter *p = new ScPainter(&pixm, pWidth, 10);
68 p->clear(QColor(128, 128, 128));
69 double startX = 0.0;
70 p->setLineWidth(0);
71 p->setFillMode(ScPainter::Solid);
72 p->setBrush(Qt::black);
73 for (int i = 0; i < m_dashValues.count(); i++)
74 {
75 if (i % 2 == 0)
76 p->setBrush(Qt::black);
77 else
78 p->setBrush(Qt::white);
79 double w = m_dashValues[i] * 10;
80 p->drawRect(startX, 0, w, 10);
81 startX += w;
82 if (m_onlySelect)
83 m_stops.append(startX);
84 }
85 p->setPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin);
86 p->setFillMode(ScPainter::None);
87 p->drawRect(0, 0, pWidth, 10);
88 p->end();
89 delete p;
90
91 QPainter pw;
92 pw.begin(this);
93 pw.drawImage(10, 5, pixm);
94 for (int i = 0; i < m_stops.count(); ++i)
95 {
96 double center = m_stops[i] + 10;
97 pw.setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
98 if (m_currentStop == i)
99 {
100 emit currStep(m_dashValues[m_currentStop]);
101 pw.setBrush(Qt::red);
102 }
103 else
104 pw.setBrush(Qt::blue);
105 QPolygon cr;
106 cr.setPoints(3, qRound(center), 16, qRound(center-4), 29, qRound(center+4), 29);
107 pw.drawPolygon(cr);
108 }
109 pw.end();
110
111 QFrame::paintEvent(e);
112 m_onlySelect = true;
113 }
114
mousePressEvent(QMouseEvent * m)115 void DashPreview::mousePressEvent(QMouseEvent *m)
116 {
117 QRect fpo;
118 m_moveTimer.start();
119 m_mousePressed = true;
120 m_currentStop = -1;
121
122 m->accept();
123 qApp->setOverrideCursor(QCursor(Qt::ArrowCursor));
124
125 for (int i = 0; i < m_stops.count(); ++i)
126 {
127 fpo = QRect(static_cast<int>(m_stops[i]) + 6, 16, 8, 13);
128 if (fpo.contains(m->pos()))
129 {
130 m_currentStop = i;
131 emit currStep(m_dashValues[m_currentStop]);
132 repaint();
133 return;
134 }
135 }
136 }
137
mouseReleaseEvent(QMouseEvent * m)138 void DashPreview::mouseReleaseEvent(QMouseEvent *m)
139 {
140 m->accept();
141 qApp->restoreOverrideCursor();
142 if ((m_mousePressed) && (m_stops.count() > 2) && (m_outside || m->y() > 30))
143 {
144 m_stops.removeAt(m_currentStop);
145 m_dashValues.clear();
146 double startX = 0.0;
147 for (int i = 0; i < m_stops.count(); ++i)
148 {
149 double w = m_stops[i] / 10.0 - startX;
150 m_dashValues.append(w);
151 startX += w;
152 }
153 m_currentStop = 0;
154 m_onlySelect = true;
155 m_mousePressed = false;
156 repaint();
157 emit currStep(m_dashValues[m_currentStop]);
158 emit dashChanged();
159 return;
160 }
161 if ((m->y() < height()) && (m->y() > 16) && (m->x() > 9) && (m->x() < width() - 9))
162 {
163 if (m_currentStop != -1)
164 {
165 if (m_moveTimer.elapsed() < 250)
166 {
167 m_mousePressed = false;
168 return;
169 }
170 m_stops[m_currentStop] = m->x() - 10;
171 }
172 else
173 {
174 if (m_dashValues.count() < 10)
175 m_stops.append(m->x() - 10);
176 std::sort(m_stops.begin(), m_stops.end());
177 m_currentStop = 0;
178 for (int i = 0; i < m_stops.count(); ++i)
179 {
180 QRect fpo = QRect(static_cast<int>(m_stops[i]) + 6, 16, 8, 13);
181 if (fpo.contains(m->pos()))
182 {
183 m_currentStop = i;
184 break;
185 }
186 }
187 }
188 m_dashValues.clear();
189 double startX = 0.0;
190 for (int i = 0; i < m_stops.count(); ++i)
191 {
192 double w = m_stops[i] / 10.0 - startX;
193 m_dashValues.append(w);
194 startX += w;
195 }
196 m_onlySelect = true;
197 repaint();
198 emit currStep(m_dashValues[m_currentStop]);
199 emit dashChanged();
200 }
201 m_mousePressed = false;
202 }
203
mouseMoveEvent(QMouseEvent * m)204 void DashPreview::mouseMoveEvent(QMouseEvent *m)
205 {
206 m->accept();
207
208 QRect fpo;
209 if ((!m_mousePressed) && (m->y() < height()) && (m->y() > 16) && (m->x() > 9) && (m->x() < width() - 9) && (m_dashValues.count() < 10))
210 {
211 setCursor(IconManager::instance().loadCursor("AddPoint.png", 1, 1));
212 for (int i = 0; i < m_stops.count(); ++i)
213 {
214 fpo = QRect(static_cast<int>(m_stops[i]) + 6, 16, 8, 13);
215 if (fpo.contains(m->pos()))
216 {
217 setCursor(QCursor(Qt::SizeHorCursor));
218 return;
219 }
220 }
221 }
222 if ((m_mousePressed) && (m->y() < height()) && (m->y() > 16) && (m->x() > 9) && (m->x() < width() - 9) && (m_currentStop != -1))
223 {
224 qApp->changeOverrideCursor(QCursor(Qt::SizeHorCursor));
225 if (m_currentStop > 1)
226 {
227 if (static_cast<int>(m_stops[m_currentStop - 1] + 10) + 2 >= m->x())
228 return;
229 }
230 if (m_currentStop < static_cast<int>(m_stops.count() - 2))
231 {
232 if (static_cast<int>(m_stops[m_currentStop + 1] + 10) - 2 < m->x())
233 return;
234 }
235 m_stops[m_currentStop] = m->x() - 10;
236 m_dashValues.clear();
237 double startX = 0.0;
238 for (int i = 0; i < m_stops.count(); ++i)
239 {
240 double w = m_stops[i] / 10.0 - startX;
241 m_dashValues.append(w);
242 startX += w;
243 }
244 m_onlySelect = true;
245 repaint();
246 startX = 0.0;
247 for (int i = 0; i < m_currentStop; ++i)
248 {
249 startX += m_stops[i] / 10.0 - startX;
250 }
251 emit currStep(m_stops[m_currentStop] / 10.0 - startX);
252 }
253 if ((m_mousePressed) && (m_outside || m->y() > 30) && (m_currentStop >= 0) && (m_stops.count() > 2))
254 qApp->changeOverrideCursor(IconManager::instance().loadCursor("DelPoint.png", 1, 1));
255 }
256
leaveEvent(QEvent *)257 void DashPreview::leaveEvent(QEvent*)
258 {
259 if (m_mousePressed)
260 {
261 if ((m_currentStop >= 0) && (m_stops.count() > 2))
262 qApp->changeOverrideCursor(IconManager::instance().loadCursor("DelPoint.png", 1, 1));
263 else
264 qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
265 }
266 m_outside = true;
267 }
268
enterEvent(QEvent *)269 void DashPreview::enterEvent(QEvent*)
270 {
271 m_outside = false;
272 }
273
setActStep(double t)274 void DashPreview::setActStep(double t)
275 {
276 if (m_currentStop == -1)
277 return;
278 m_dashValues[m_currentStop] = t;
279 m_onlySelect = true;
280 repaint();
281 emit dashChanged();
282 }
283
setDashValues(const QVector<double> & vals)284 void DashPreview::setDashValues(const QVector<double>& vals)
285 {
286 m_dashValues = vals;
287 if ((m_currentStop >= vals.count()) || (m_currentStop == -1))
288 m_currentStop = 0;
289 m_onlySelect = true;
290 if (m_dashValues.count() != 0)
291 {
292 if ((m_currentStop >= vals.count()) || (m_currentStop == -1))
293 emit currStep(m_dashValues[0]);
294 else
295 emit currStep(m_dashValues[m_currentStop]);
296 }
297 update();
298 }
299
DashEditor(QWidget * pa)300 DashEditor::DashEditor(QWidget *pa) : QFrame(pa)
301 {
302 setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum));
303 setFrameShape( QFrame::Panel );
304 setLineWidth( 1 );
305 QGridLayout *gridLayout = new QGridLayout(this);
306 gridLayout->setSpacing(3);
307 gridLayout->setContentsMargins(6, 6, 6, 6);
308
309 Preview = new DashPreview(this);
310 gridLayout->addWidget(Preview, 0, 0, 1, 2);
311
312 Position = new QDoubleSpinBox( this );
313 Position->setDecimals(1);
314 Position->setMinimum(0);
315 Position->setMaximum(100);
316 Position->setSingleStep(0.1);
317 Position->setValue(0);
318 Desc = new QLabel( this );
319
320 Offset = new QDoubleSpinBox( this );
321 Offset->setDecimals(1);
322 Offset->setMinimum(0);
323 Offset->setMaximum(100);
324 Offset->setSingleStep(0.1);
325 Offset->setValue(0);
326 Desc2 = new QLabel( this );
327 languageChange();
328
329 gridLayout->addWidget(Desc, 1, 0, 1, 1);
330 gridLayout->addWidget(Position, 1, 1, 1, 1);
331 gridLayout->addWidget(Desc2, 2, 0, 1, 1);
332 gridLayout->addWidget(Offset, 2, 1, 1, 1);
333
334 connect(Position, SIGNAL(valueChanged(double)), Preview, SLOT(setActStep(double)));
335 connect(Offset, SIGNAL(valueChanged(double)), this, SIGNAL(dashChanged()));
336 connect(Preview, SIGNAL(currStep(double)), this, SLOT(setPos(double)));
337 connect(Preview, SIGNAL(dashChanged()), this, SIGNAL(dashChanged()));
338 }
339
setPos(double p)340 void DashEditor::setPos(double p)
341 {
342 QSignalBlocker blocker(Position);
343 Position->setValue(p);
344 }
345
setDashValues(QVector<double> vals,double linewidth,double offset)346 void DashEditor::setDashValues(QVector<double> vals, double linewidth, double offset)
347 {
348 QVector<double> tmp;
349 for (int i = 0; i < vals.count(); i++)
350 tmp.append(vals[i] / linewidth);
351 Preview->setDashValues(tmp);
352
353 disconnect(Offset, SIGNAL(valueChanged(double)), this, SIGNAL(dashChanged()));
354 Offset->setValue(offset / linewidth);
355 connect(Offset, SIGNAL(valueChanged(double)), this, SIGNAL(dashChanged()));
356 }
357
getDashValues(double linewidth)358 QVector<double> DashEditor::getDashValues(double linewidth)
359 {
360 auto dashValues = Preview->dashValues();
361 for (int i = 0; i < dashValues.count(); i++)
362 dashValues[i] *= linewidth;
363 return dashValues;
364 }
365
changeEvent(QEvent * e)366 void DashEditor::changeEvent(QEvent *e)
367 {
368 if (e->type() == QEvent::LanguageChange)
369 languageChange();
370 else
371 QWidget::changeEvent(e);
372 }
373
languageChange()374 void DashEditor::languageChange()
375 {
376 Desc->setText( tr( "Value:" ) );
377 Desc2->setText( tr( "Offset:" ) );
378 }
379