[2] | 1 | /****************************************************************************
|
---|
| 2 | **
|
---|
[846] | 3 | ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
---|
[561] | 4 | ** All rights reserved.
|
---|
| 5 | ** Contact: Nokia Corporation ([email protected])
|
---|
[2] | 6 | **
|
---|
| 7 | ** This file is part of the tools applications of the Qt Toolkit.
|
---|
| 8 | **
|
---|
| 9 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
| 10 | ** Commercial Usage
|
---|
| 11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
| 12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
| 13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
| 14 | ** a written agreement between you and Nokia.
|
---|
| 15 | **
|
---|
| 16 | ** GNU Lesser General Public License Usage
|
---|
| 17 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
| 18 | ** General Public License version 2.1 as published by the Free Software
|
---|
| 19 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
| 20 | ** packaging of this file. Please review the following information to
|
---|
| 21 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
| 22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
| 23 | **
|
---|
[561] | 24 | ** In addition, as a special exception, Nokia gives you certain additional
|
---|
| 25 | ** rights. These rights are described in the Nokia Qt LGPL Exception
|
---|
| 26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
---|
[2] | 27 | **
|
---|
| 28 | ** GNU General Public License Usage
|
---|
| 29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
| 30 | ** General Public License version 3.0 as published by the Free Software
|
---|
| 31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
| 32 | ** packaging of this file. Please review the following information to
|
---|
| 33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
| 34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
| 35 | **
|
---|
[561] | 36 | ** If you have questions regarding the use of this file, please contact
|
---|
| 37 | ** Nokia at [email protected].
|
---|
[2] | 38 | ** $QT_END_LICENSE$
|
---|
| 39 | **
|
---|
| 40 | ****************************************************************************/
|
---|
| 41 |
|
---|
| 42 | #include "qtgradientstopswidget.h"
|
---|
| 43 | #include "qtgradientstopsmodel.h"
|
---|
| 44 |
|
---|
| 45 | #include <QtCore/QMap>
|
---|
| 46 | #include <QtGui/QImage>
|
---|
| 47 | #include <QtGui/QPainter>
|
---|
| 48 | #include <QtGui/QScrollBar>
|
---|
| 49 | #include <QtGui/QMouseEvent>
|
---|
| 50 | #include <QtGui/QRubberBand>
|
---|
| 51 | #include <QtGui/QMenu>
|
---|
| 52 |
|
---|
| 53 | QT_BEGIN_NAMESPACE
|
---|
| 54 |
|
---|
| 55 | class QtGradientStopsWidgetPrivate
|
---|
| 56 | {
|
---|
| 57 | QtGradientStopsWidget *q_ptr;
|
---|
| 58 | Q_DECLARE_PUBLIC(QtGradientStopsWidget)
|
---|
| 59 | public:
|
---|
| 60 | typedef QMap<qreal, QColor> PositionColorMap;
|
---|
| 61 | typedef QMap<QtGradientStop *, qreal> StopPositionMap;
|
---|
| 62 |
|
---|
| 63 | void slotStopAdded(QtGradientStop *stop);
|
---|
| 64 | void slotStopRemoved(QtGradientStop *stop);
|
---|
| 65 | void slotStopMoved(QtGradientStop *stop, qreal newPos);
|
---|
| 66 | void slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2);
|
---|
| 67 | void slotStopChanged(QtGradientStop *stop, const QColor &newColor);
|
---|
| 68 | void slotStopSelected(QtGradientStop *stop, bool selected);
|
---|
| 69 | void slotCurrentStopChanged(QtGradientStop *stop);
|
---|
| 70 | void slotNewStop();
|
---|
| 71 | void slotDelete();
|
---|
| 72 | void slotFlipAll();
|
---|
| 73 | void slotSelectAll();
|
---|
| 74 | void slotZoomIn();
|
---|
| 75 | void slotZoomOut();
|
---|
| 76 | void slotResetZoom();
|
---|
| 77 |
|
---|
| 78 | double fromViewport(int x) const;
|
---|
| 79 | double toViewport(double x) const;
|
---|
| 80 | QtGradientStop *stopAt(const QPoint &viewportPos) const;
|
---|
| 81 | QList<QtGradientStop *> stopsAt(const QPoint &viewportPos) const;
|
---|
| 82 | void setupMove(QtGradientStop *stop, int x);
|
---|
| 83 | void ensureVisible(double x); // x = stop position
|
---|
| 84 | void ensureVisible(QtGradientStop *stop);
|
---|
| 85 | QtGradientStop *newStop(const QPoint &viewportPos);
|
---|
| 86 |
|
---|
| 87 | bool m_backgroundCheckered;
|
---|
| 88 | QtGradientStopsModel *m_model;
|
---|
| 89 | double m_handleSize;
|
---|
| 90 | int m_scaleFactor;
|
---|
| 91 | double m_zoom;
|
---|
| 92 |
|
---|
| 93 | #ifndef QT_NO_DRAGANDDROP
|
---|
| 94 | QtGradientStop *m_dragStop;
|
---|
| 95 | QtGradientStop *m_changedStop;
|
---|
| 96 | QtGradientStop *m_clonedStop;
|
---|
| 97 | QtGradientStopsModel *m_dragModel;
|
---|
| 98 | QColor m_dragColor;
|
---|
| 99 | void clearDrag();
|
---|
| 100 | void removeClonedStop();
|
---|
| 101 | void restoreChangedStop();
|
---|
| 102 | void changeStop(qreal pos);
|
---|
| 103 | void cloneStop(qreal pos);
|
---|
| 104 | #endif
|
---|
| 105 |
|
---|
| 106 | QRubberBand *m_rubber;
|
---|
| 107 | QPoint m_clickPos;
|
---|
| 108 |
|
---|
| 109 | QList<QtGradientStop *> m_stops;
|
---|
| 110 |
|
---|
| 111 | bool m_moving;
|
---|
| 112 | int m_moveOffset;
|
---|
| 113 | StopPositionMap m_moveStops;
|
---|
| 114 |
|
---|
| 115 | PositionColorMap m_moveOriginal;
|
---|
| 116 | };
|
---|
| 117 |
|
---|
| 118 | double QtGradientStopsWidgetPrivate::fromViewport(int x) const
|
---|
| 119 | {
|
---|
| 120 | QSize size = q_ptr->viewport()->size();
|
---|
| 121 | int w = size.width();
|
---|
| 122 | int max = q_ptr->horizontalScrollBar()->maximum();
|
---|
| 123 | int val = q_ptr->horizontalScrollBar()->value();
|
---|
| 124 | return ((double)x * m_scaleFactor + w * val) / (w * (m_scaleFactor + max));
|
---|
| 125 | }
|
---|
| 126 |
|
---|
| 127 | double QtGradientStopsWidgetPrivate::toViewport(double x) const
|
---|
| 128 | {
|
---|
| 129 | QSize size = q_ptr->viewport()->size();
|
---|
| 130 | int w = size.width();
|
---|
| 131 | int max = q_ptr->horizontalScrollBar()->maximum();
|
---|
| 132 | int val = q_ptr->horizontalScrollBar()->value();
|
---|
| 133 | return w * (x * (m_scaleFactor + max) - val) / m_scaleFactor;
|
---|
| 134 | }
|
---|
| 135 |
|
---|
| 136 | QtGradientStop *QtGradientStopsWidgetPrivate::stopAt(const QPoint &viewportPos) const
|
---|
| 137 | {
|
---|
| 138 | double posY = m_handleSize / 2;
|
---|
| 139 | QListIterator<QtGradientStop *> itStop(m_stops);
|
---|
| 140 | while (itStop.hasNext()) {
|
---|
| 141 | QtGradientStop *stop = itStop.next();
|
---|
| 142 |
|
---|
| 143 | double posX = toViewport(stop->position());
|
---|
| 144 |
|
---|
| 145 | double x = viewportPos.x() - posX;
|
---|
| 146 | double y = viewportPos.y() - posY;
|
---|
| 147 |
|
---|
| 148 | if ((m_handleSize * m_handleSize / 4) > (x * x + y * y))
|
---|
| 149 | return stop;
|
---|
| 150 | }
|
---|
| 151 | return 0;
|
---|
| 152 | }
|
---|
| 153 |
|
---|
| 154 | QList<QtGradientStop *> QtGradientStopsWidgetPrivate::stopsAt(const QPoint &viewportPos) const
|
---|
| 155 | {
|
---|
| 156 | QList<QtGradientStop *> stops;
|
---|
| 157 | double posY = m_handleSize / 2;
|
---|
| 158 | QListIterator<QtGradientStop *> itStop(m_stops);
|
---|
| 159 | while (itStop.hasNext()) {
|
---|
| 160 | QtGradientStop *stop = itStop.next();
|
---|
| 161 |
|
---|
| 162 | double posX = toViewport(stop->position());
|
---|
| 163 |
|
---|
| 164 | double x = viewportPos.x() - posX;
|
---|
| 165 | double y = viewportPos.y() - posY;
|
---|
| 166 |
|
---|
| 167 | if ((m_handleSize * m_handleSize / 4) > (x * x + y * y))
|
---|
| 168 | stops.append(stop);
|
---|
| 169 | }
|
---|
| 170 | return stops;
|
---|
| 171 | }
|
---|
| 172 |
|
---|
| 173 | void QtGradientStopsWidgetPrivate::setupMove(QtGradientStop *stop, int x)
|
---|
| 174 | {
|
---|
| 175 | m_model->setCurrentStop(stop);
|
---|
| 176 |
|
---|
| 177 | int viewportX = qRound(toViewport(stop->position()));
|
---|
| 178 | m_moveOffset = x - viewportX;
|
---|
| 179 |
|
---|
| 180 | QList<QtGradientStop *> stops = m_stops;
|
---|
| 181 | m_stops.clear();
|
---|
| 182 | QListIterator<QtGradientStop *> itStop(stops);
|
---|
| 183 | while (itStop.hasNext()) {
|
---|
| 184 | QtGradientStop *s = itStop.next();
|
---|
| 185 | if (m_model->isSelected(s) || s == stop) {
|
---|
| 186 | m_moveStops[s] = s->position() - stop->position();
|
---|
| 187 | m_stops.append(s);
|
---|
| 188 | } else {
|
---|
| 189 | m_moveOriginal[s->position()] = s->color();
|
---|
| 190 | }
|
---|
| 191 | }
|
---|
| 192 | itStop.toFront();
|
---|
| 193 | while (itStop.hasNext()) {
|
---|
| 194 | QtGradientStop *s = itStop.next();
|
---|
| 195 | if (!m_model->isSelected(s))
|
---|
| 196 | m_stops.append(s);
|
---|
| 197 | }
|
---|
| 198 | m_stops.removeAll(stop);
|
---|
| 199 | m_stops.prepend(stop);
|
---|
| 200 | }
|
---|
| 201 |
|
---|
| 202 | void QtGradientStopsWidgetPrivate::ensureVisible(double x)
|
---|
| 203 | {
|
---|
| 204 | double viewX = toViewport(x);
|
---|
| 205 | if (viewX < 0 || viewX > q_ptr->viewport()->size().width()) {
|
---|
| 206 | int max = q_ptr->horizontalScrollBar()->maximum();
|
---|
| 207 | int newVal = qRound(x * (max + m_scaleFactor) - m_scaleFactor / 2);
|
---|
| 208 | q_ptr->horizontalScrollBar()->setValue(newVal);
|
---|
| 209 | }
|
---|
| 210 | }
|
---|
| 211 |
|
---|
| 212 | void QtGradientStopsWidgetPrivate::ensureVisible(QtGradientStop *stop)
|
---|
| 213 | {
|
---|
| 214 | if (!stop)
|
---|
| 215 | return;
|
---|
| 216 | ensureVisible(stop->position());
|
---|
| 217 | }
|
---|
| 218 |
|
---|
| 219 | QtGradientStop *QtGradientStopsWidgetPrivate::newStop(const QPoint &viewportPos)
|
---|
| 220 | {
|
---|
| 221 | QtGradientStop *copyStop = stopAt(viewportPos);
|
---|
| 222 | double posX = fromViewport(viewportPos.x());
|
---|
| 223 | QtGradientStop *stop = m_model->at(posX);
|
---|
| 224 | if (!stop) {
|
---|
| 225 | QColor newColor;
|
---|
| 226 | if (copyStop)
|
---|
| 227 | newColor = copyStop->color();
|
---|
| 228 | else
|
---|
| 229 | newColor = m_model->color(posX);
|
---|
| 230 | if (!newColor.isValid())
|
---|
| 231 | newColor = Qt::white;
|
---|
| 232 | stop = m_model->addStop(posX, newColor);
|
---|
| 233 | }
|
---|
| 234 | return stop;
|
---|
| 235 | }
|
---|
| 236 |
|
---|
| 237 | void QtGradientStopsWidgetPrivate::slotStopAdded(QtGradientStop *stop)
|
---|
| 238 | {
|
---|
| 239 | m_stops.append(stop);
|
---|
| 240 | q_ptr->viewport()->update();
|
---|
| 241 | }
|
---|
| 242 |
|
---|
| 243 | void QtGradientStopsWidgetPrivate::slotStopRemoved(QtGradientStop *stop)
|
---|
| 244 | {
|
---|
| 245 | m_stops.removeAll(stop);
|
---|
| 246 | q_ptr->viewport()->update();
|
---|
| 247 | }
|
---|
| 248 |
|
---|
| 249 | void QtGradientStopsWidgetPrivate::slotStopMoved(QtGradientStop *stop, qreal newPos)
|
---|
| 250 | {
|
---|
| 251 | Q_UNUSED(stop)
|
---|
| 252 | Q_UNUSED(newPos)
|
---|
| 253 | q_ptr->viewport()->update();
|
---|
| 254 | }
|
---|
| 255 |
|
---|
| 256 | void QtGradientStopsWidgetPrivate::slotStopsSwapped(QtGradientStop *stop1, QtGradientStop *stop2)
|
---|
| 257 | {
|
---|
| 258 | Q_UNUSED(stop1)
|
---|
| 259 | Q_UNUSED(stop2)
|
---|
| 260 | q_ptr->viewport()->update();
|
---|
| 261 | }
|
---|
| 262 |
|
---|
| 263 | void QtGradientStopsWidgetPrivate::slotStopChanged(QtGradientStop *stop, const QColor &newColor)
|
---|
| 264 | {
|
---|
| 265 | Q_UNUSED(stop)
|
---|
| 266 | Q_UNUSED(newColor)
|
---|
| 267 | q_ptr->viewport()->update();
|
---|
| 268 | }
|
---|
| 269 |
|
---|
| 270 | void QtGradientStopsWidgetPrivate::slotStopSelected(QtGradientStop *stop, bool selected)
|
---|
| 271 | {
|
---|
| 272 | Q_UNUSED(stop)
|
---|
| 273 | Q_UNUSED(selected)
|
---|
| 274 | q_ptr->viewport()->update();
|
---|
| 275 | }
|
---|
| 276 |
|
---|
| 277 | void QtGradientStopsWidgetPrivate::slotCurrentStopChanged(QtGradientStop *stop)
|
---|
| 278 | {
|
---|
| 279 | Q_UNUSED(stop)
|
---|
| 280 |
|
---|
| 281 | if (!m_model)
|
---|
| 282 | return;
|
---|
| 283 | q_ptr->viewport()->update();
|
---|
| 284 | if (stop) {
|
---|
| 285 | m_stops.removeAll(stop);
|
---|
| 286 | m_stops.prepend(stop);
|
---|
| 287 | }
|
---|
| 288 | }
|
---|
| 289 |
|
---|
| 290 | void QtGradientStopsWidgetPrivate::slotNewStop()
|
---|
| 291 | {
|
---|
| 292 | if (!m_model)
|
---|
| 293 | return;
|
---|
| 294 |
|
---|
| 295 | QtGradientStop *stop = newStop(m_clickPos);
|
---|
| 296 |
|
---|
| 297 | if (!stop)
|
---|
| 298 | return;
|
---|
| 299 |
|
---|
| 300 | m_model->clearSelection();
|
---|
| 301 | m_model->selectStop(stop, true);
|
---|
| 302 | m_model->setCurrentStop(stop);
|
---|
| 303 | }
|
---|
| 304 |
|
---|
| 305 | void QtGradientStopsWidgetPrivate::slotDelete()
|
---|
| 306 | {
|
---|
| 307 | if (!m_model)
|
---|
| 308 | return;
|
---|
| 309 |
|
---|
| 310 | m_model->deleteStops();
|
---|
| 311 | }
|
---|
| 312 |
|
---|
| 313 | void QtGradientStopsWidgetPrivate::slotFlipAll()
|
---|
| 314 | {
|
---|
| 315 | if (!m_model)
|
---|
| 316 | return;
|
---|
| 317 |
|
---|
| 318 | m_model->flipAll();
|
---|
| 319 | }
|
---|
| 320 |
|
---|
| 321 | void QtGradientStopsWidgetPrivate::slotSelectAll()
|
---|
| 322 | {
|
---|
| 323 | if (!m_model)
|
---|
| 324 | return;
|
---|
| 325 |
|
---|
| 326 | m_model->selectAll();
|
---|
| 327 | }
|
---|
| 328 |
|
---|
| 329 | void QtGradientStopsWidgetPrivate::slotZoomIn()
|
---|
| 330 | {
|
---|
| 331 | double newZoom = q_ptr->zoom() * 2;
|
---|
| 332 | if (newZoom > 100)
|
---|
| 333 | newZoom = 100;
|
---|
| 334 | if (newZoom == q_ptr->zoom())
|
---|
| 335 | return;
|
---|
| 336 |
|
---|
| 337 | q_ptr->setZoom(newZoom);
|
---|
| 338 | emit q_ptr->zoomChanged(q_ptr->zoom());
|
---|
| 339 | }
|
---|
| 340 |
|
---|
| 341 | void QtGradientStopsWidgetPrivate::slotZoomOut()
|
---|
| 342 | {
|
---|
| 343 | double newZoom = q_ptr->zoom() / 2;
|
---|
| 344 | if (newZoom < 1)
|
---|
| 345 | newZoom = 1;
|
---|
| 346 | if (newZoom == q_ptr->zoom())
|
---|
| 347 | return;
|
---|
| 348 |
|
---|
| 349 | q_ptr->setZoom(newZoom);
|
---|
| 350 | emit q_ptr->zoomChanged(q_ptr->zoom());
|
---|
| 351 | }
|
---|
| 352 |
|
---|
| 353 | void QtGradientStopsWidgetPrivate::slotResetZoom()
|
---|
| 354 | {
|
---|
| 355 | if (1 == q_ptr->zoom())
|
---|
| 356 | return;
|
---|
| 357 |
|
---|
| 358 | q_ptr->setZoom(1);
|
---|
| 359 | emit q_ptr->zoomChanged(1);
|
---|
| 360 | }
|
---|
| 361 |
|
---|
| 362 | QtGradientStopsWidget::QtGradientStopsWidget(QWidget *parent)
|
---|
[561] | 363 | : QAbstractScrollArea(parent), d_ptr(new QtGradientStopsWidgetPrivate)
|
---|
[2] | 364 | {
|
---|
| 365 | d_ptr->q_ptr = this;
|
---|
| 366 | d_ptr->m_backgroundCheckered = true;
|
---|
| 367 | d_ptr->m_model = 0;
|
---|
| 368 | d_ptr->m_handleSize = 25.0;
|
---|
| 369 | d_ptr->m_scaleFactor = 1000;
|
---|
| 370 | d_ptr->m_moving = false;
|
---|
| 371 | d_ptr->m_zoom = 1;
|
---|
| 372 | d_ptr->m_rubber = new QRubberBand(QRubberBand::Rectangle, this);
|
---|
| 373 | #ifndef QT_NO_DRAGANDDROP
|
---|
| 374 | d_ptr->m_dragStop = 0;
|
---|
| 375 | d_ptr->m_changedStop = 0;
|
---|
| 376 | d_ptr->m_clonedStop = 0;
|
---|
| 377 | d_ptr->m_dragModel = 0;
|
---|
| 378 | #endif
|
---|
| 379 | setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
---|
| 380 | setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
---|
| 381 | horizontalScrollBar()->setRange(0, (int)(d_ptr->m_scaleFactor * (d_ptr->m_zoom - 1) + 0.5));
|
---|
| 382 | horizontalScrollBar()->setPageStep(d_ptr->m_scaleFactor);
|
---|
| 383 | horizontalScrollBar()->setSingleStep(4);
|
---|
| 384 | viewport()->setAutoFillBackground(false);
|
---|
| 385 |
|
---|
| 386 | setAcceptDrops(true);
|
---|
| 387 |
|
---|
| 388 | setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred));
|
---|
| 389 | }
|
---|
| 390 |
|
---|
| 391 | QtGradientStopsWidget::~QtGradientStopsWidget()
|
---|
| 392 | {
|
---|
| 393 | }
|
---|
| 394 |
|
---|
| 395 | QSize QtGradientStopsWidget::sizeHint() const
|
---|
| 396 | {
|
---|
| 397 | return QSize(qRound(2 * d_ptr->m_handleSize), qRound(3 * d_ptr->m_handleSize) + horizontalScrollBar()->sizeHint().height());
|
---|
| 398 | }
|
---|
| 399 |
|
---|
| 400 | QSize QtGradientStopsWidget::minimumSizeHint() const
|
---|
| 401 | {
|
---|
| 402 | return QSize(qRound(2 * d_ptr->m_handleSize), qRound(3 * d_ptr->m_handleSize) + horizontalScrollBar()->minimumSizeHint().height());
|
---|
| 403 | }
|
---|
| 404 |
|
---|
| 405 | void QtGradientStopsWidget::setBackgroundCheckered(bool checkered)
|
---|
| 406 | {
|
---|
| 407 | if (d_ptr->m_backgroundCheckered == checkered)
|
---|
| 408 | return;
|
---|
| 409 | d_ptr->m_backgroundCheckered = checkered;
|
---|
| 410 | update();
|
---|
| 411 | }
|
---|
| 412 |
|
---|
| 413 | bool QtGradientStopsWidget::isBackgroundCheckered() const
|
---|
| 414 | {
|
---|
| 415 | return d_ptr->m_backgroundCheckered;
|
---|
| 416 | }
|
---|
| 417 |
|
---|
| 418 | void QtGradientStopsWidget::setGradientStopsModel(QtGradientStopsModel *model)
|
---|
| 419 | {
|
---|
| 420 | if (d_ptr->m_model == model)
|
---|
| 421 | return;
|
---|
| 422 |
|
---|
| 423 | if (d_ptr->m_model) {
|
---|
[561] | 424 | disconnect(d_ptr->m_model, SIGNAL(stopAdded(QtGradientStop*)),
|
---|
| 425 | this, SLOT(slotStopAdded(QtGradientStop*)));
|
---|
| 426 | disconnect(d_ptr->m_model, SIGNAL(stopRemoved(QtGradientStop*)),
|
---|
| 427 | this, SLOT(slotStopRemoved(QtGradientStop*)));
|
---|
| 428 | disconnect(d_ptr->m_model, SIGNAL(stopMoved(QtGradientStop*,qreal)),
|
---|
| 429 | this, SLOT(slotStopMoved(QtGradientStop*,qreal)));
|
---|
| 430 | disconnect(d_ptr->m_model, SIGNAL(stopsSwapped(QtGradientStop*,QtGradientStop*)),
|
---|
| 431 | this, SLOT(slotStopsSwapped(QtGradientStop*,QtGradientStop*)));
|
---|
| 432 | disconnect(d_ptr->m_model, SIGNAL(stopChanged(QtGradientStop*,QColor)),
|
---|
| 433 | this, SLOT(slotStopChanged(QtGradientStop*,QColor)));
|
---|
| 434 | disconnect(d_ptr->m_model, SIGNAL(stopSelected(QtGradientStop*,bool)),
|
---|
| 435 | this, SLOT(slotStopSelected(QtGradientStop*,bool)));
|
---|
| 436 | disconnect(d_ptr->m_model, SIGNAL(currentStopChanged(QtGradientStop*)),
|
---|
| 437 | this, SLOT(slotCurrentStopChanged(QtGradientStop*)));
|
---|
[2] | 438 |
|
---|
| 439 | d_ptr->m_stops.clear();
|
---|
| 440 | }
|
---|
| 441 |
|
---|
| 442 | d_ptr->m_model = model;
|
---|
| 443 |
|
---|
| 444 | if (d_ptr->m_model) {
|
---|
[561] | 445 | connect(d_ptr->m_model, SIGNAL(stopAdded(QtGradientStop*)),
|
---|
| 446 | this, SLOT(slotStopAdded(QtGradientStop*)));
|
---|
| 447 | connect(d_ptr->m_model, SIGNAL(stopRemoved(QtGradientStop*)),
|
---|
| 448 | this, SLOT(slotStopRemoved(QtGradientStop*)));
|
---|
| 449 | connect(d_ptr->m_model, SIGNAL(stopMoved(QtGradientStop*,qreal)),
|
---|
| 450 | this, SLOT(slotStopMoved(QtGradientStop*,qreal)));
|
---|
| 451 | connect(d_ptr->m_model, SIGNAL(stopsSwapped(QtGradientStop*,QtGradientStop*)),
|
---|
| 452 | this, SLOT(slotStopsSwapped(QtGradientStop*,QtGradientStop*)));
|
---|
| 453 | connect(d_ptr->m_model, SIGNAL(stopChanged(QtGradientStop*,QColor)),
|
---|
| 454 | this, SLOT(slotStopChanged(QtGradientStop*,QColor)));
|
---|
| 455 | connect(d_ptr->m_model, SIGNAL(stopSelected(QtGradientStop*,bool)),
|
---|
| 456 | this, SLOT(slotStopSelected(QtGradientStop*,bool)));
|
---|
| 457 | connect(d_ptr->m_model, SIGNAL(currentStopChanged(QtGradientStop*)),
|
---|
| 458 | this, SLOT(slotCurrentStopChanged(QtGradientStop*)));
|
---|
[2] | 459 |
|
---|
| 460 | QList<QtGradientStop *> stops = d_ptr->m_model->stops().values();
|
---|
| 461 | QListIterator<QtGradientStop *> itStop(stops);
|
---|
| 462 | while (itStop.hasNext())
|
---|
| 463 | d_ptr->slotStopAdded(itStop.next());
|
---|
| 464 |
|
---|
| 465 | QList<QtGradientStop *> selected = d_ptr->m_model->selectedStops();
|
---|
| 466 | QListIterator<QtGradientStop *> itSelect(selected);
|
---|
| 467 | while (itSelect.hasNext())
|
---|
| 468 | d_ptr->slotStopSelected(itSelect.next(), true);
|
---|
| 469 |
|
---|
| 470 | d_ptr->slotCurrentStopChanged(d_ptr->m_model->currentStop());
|
---|
| 471 | }
|
---|
| 472 | }
|
---|
| 473 |
|
---|
| 474 | void QtGradientStopsWidget::mousePressEvent(QMouseEvent *e)
|
---|
| 475 | {
|
---|
| 476 | typedef QtGradientStopsModel::PositionStopMap PositionStopMap;
|
---|
| 477 | if (!d_ptr->m_model)
|
---|
| 478 | return;
|
---|
| 479 |
|
---|
| 480 | if (e->button() != Qt::LeftButton)
|
---|
| 481 | return;
|
---|
| 482 |
|
---|
| 483 | d_ptr->m_moving = true;
|
---|
| 484 |
|
---|
| 485 | d_ptr->m_moveStops.clear();
|
---|
| 486 | d_ptr->m_moveOriginal.clear();
|
---|
| 487 | d_ptr->m_clickPos = e->pos();
|
---|
| 488 | QtGradientStop *stop = d_ptr->stopAt(e->pos());
|
---|
| 489 | if (stop) {
|
---|
| 490 | if (e->modifiers() & Qt::ControlModifier) {
|
---|
| 491 | d_ptr->m_model->selectStop(stop, !d_ptr->m_model->isSelected(stop));
|
---|
| 492 | } else if (e->modifiers() & Qt::ShiftModifier) {
|
---|
| 493 | QtGradientStop *oldCurrent = d_ptr->m_model->currentStop();
|
---|
| 494 | if (oldCurrent) {
|
---|
| 495 | PositionStopMap stops = d_ptr->m_model->stops();
|
---|
| 496 | PositionStopMap::ConstIterator itSt = stops.constFind(oldCurrent->position());
|
---|
| 497 | if (itSt != stops.constEnd()) {
|
---|
| 498 | while (itSt != stops.constFind(stop->position())) {
|
---|
| 499 | d_ptr->m_model->selectStop(itSt.value(), true);
|
---|
| 500 | if (oldCurrent->position() < stop->position())
|
---|
| 501 | ++itSt;
|
---|
| 502 | else
|
---|
| 503 | --itSt;
|
---|
| 504 | }
|
---|
| 505 | }
|
---|
| 506 | }
|
---|
| 507 | d_ptr->m_model->selectStop(stop, true);
|
---|
| 508 | } else {
|
---|
| 509 | if (!d_ptr->m_model->isSelected(stop)) {
|
---|
| 510 | d_ptr->m_model->clearSelection();
|
---|
| 511 | d_ptr->m_model->selectStop(stop, true);
|
---|
| 512 | }
|
---|
| 513 | }
|
---|
| 514 | d_ptr->setupMove(stop, e->pos().x());
|
---|
| 515 | } else {
|
---|
| 516 | d_ptr->m_model->clearSelection();
|
---|
| 517 | d_ptr->m_rubber->setGeometry(QRect(d_ptr->m_clickPos, QSize()));
|
---|
| 518 | d_ptr->m_rubber->show();
|
---|
| 519 | }
|
---|
| 520 | viewport()->update();
|
---|
| 521 | }
|
---|
| 522 |
|
---|
| 523 | void QtGradientStopsWidget::mouseReleaseEvent(QMouseEvent *e)
|
---|
| 524 | {
|
---|
| 525 | if (!d_ptr->m_model)
|
---|
| 526 | return;
|
---|
| 527 |
|
---|
| 528 | if (e->button() != Qt::LeftButton)
|
---|
| 529 | return;
|
---|
| 530 |
|
---|
| 531 | d_ptr->m_moving = false;
|
---|
| 532 | d_ptr->m_rubber->hide();
|
---|
| 533 | d_ptr->m_moveStops.clear();
|
---|
| 534 | d_ptr->m_moveOriginal.clear();
|
---|
| 535 | }
|
---|
| 536 |
|
---|
| 537 | void QtGradientStopsWidget::mouseMoveEvent(QMouseEvent *e)
|
---|
| 538 | {
|
---|
| 539 | typedef QtGradientStopsWidgetPrivate::PositionColorMap PositionColorMap;
|
---|
| 540 | typedef QtGradientStopsModel::PositionStopMap PositionStopMap;
|
---|
| 541 | typedef QtGradientStopsWidgetPrivate::StopPositionMap StopPositionMap;
|
---|
| 542 | if (!d_ptr->m_model)
|
---|
| 543 | return;
|
---|
| 544 |
|
---|
| 545 | if (!(e->buttons() & Qt::LeftButton))
|
---|
| 546 | return;
|
---|
| 547 |
|
---|
| 548 | if (!d_ptr->m_moving)
|
---|
| 549 | return;
|
---|
| 550 |
|
---|
| 551 | if (!d_ptr->m_moveStops.isEmpty()) {
|
---|
| 552 | double maxOffset = 0.0;
|
---|
| 553 | double minOffset = 0.0;
|
---|
| 554 | bool first = true;
|
---|
| 555 | StopPositionMap::ConstIterator itStop = d_ptr->m_moveStops.constBegin();
|
---|
| 556 | while (itStop != d_ptr->m_moveStops.constEnd()) {
|
---|
| 557 | double offset = itStop.value();
|
---|
| 558 |
|
---|
| 559 | if (first) {
|
---|
| 560 | maxOffset = offset;
|
---|
| 561 | minOffset = offset;
|
---|
| 562 | first = false;
|
---|
| 563 | } else {
|
---|
| 564 | if (maxOffset < offset)
|
---|
| 565 | maxOffset = offset;
|
---|
| 566 | else if (minOffset > offset)
|
---|
| 567 | minOffset = offset;
|
---|
| 568 | }
|
---|
| 569 | ++itStop;
|
---|
| 570 | }
|
---|
| 571 |
|
---|
| 572 | double viewportMin = d_ptr->toViewport(-minOffset);
|
---|
| 573 | double viewportMax = d_ptr->toViewport(1.0 - maxOffset);
|
---|
| 574 |
|
---|
| 575 | PositionStopMap newPositions;
|
---|
| 576 |
|
---|
| 577 | int viewportX = e->pos().x() - d_ptr->m_moveOffset;
|
---|
| 578 |
|
---|
| 579 | if (viewportX > viewport()->size().width())
|
---|
| 580 | viewportX = viewport()->size().width();
|
---|
| 581 | else if (viewportX < 0)
|
---|
| 582 | viewportX = 0;
|
---|
| 583 |
|
---|
| 584 | double posX = d_ptr->fromViewport(viewportX);
|
---|
| 585 |
|
---|
| 586 | if (viewportX > viewportMax)
|
---|
| 587 | posX = 1.0 - maxOffset;
|
---|
| 588 | else if (viewportX < viewportMin)
|
---|
| 589 | posX = -minOffset;
|
---|
| 590 |
|
---|
| 591 | itStop = d_ptr->m_moveStops.constBegin();
|
---|
| 592 | while (itStop != d_ptr->m_moveStops.constEnd()) {
|
---|
| 593 | QtGradientStop *stop = itStop.key();
|
---|
| 594 |
|
---|
| 595 | newPositions[posX + itStop.value()] = stop;
|
---|
| 596 |
|
---|
| 597 | ++itStop;
|
---|
| 598 | }
|
---|
| 599 |
|
---|
| 600 | bool forward = true;
|
---|
| 601 | PositionStopMap::ConstIterator itNewPos = newPositions.constBegin();
|
---|
| 602 | if (itNewPos.value()->position() < itNewPos.key())
|
---|
| 603 | forward = false;
|
---|
| 604 |
|
---|
| 605 | itNewPos = forward ? newPositions.constBegin() : newPositions.constEnd();
|
---|
| 606 | while (itNewPos != (forward ? newPositions.constEnd() : newPositions.constBegin())) {
|
---|
| 607 | if (!forward)
|
---|
| 608 | --itNewPos;
|
---|
| 609 | QtGradientStop *stop = itNewPos.value();
|
---|
| 610 | double newPos = itNewPos.key();
|
---|
| 611 | if (newPos > 1)
|
---|
| 612 | newPos = 1;
|
---|
| 613 | else if (newPos < 0)
|
---|
| 614 | newPos = 0;
|
---|
| 615 |
|
---|
| 616 | QtGradientStop *existingStop = d_ptr->m_model->at(newPos);
|
---|
| 617 | if (existingStop && !d_ptr->m_moveStops.contains(existingStop))
|
---|
| 618 | d_ptr->m_model->removeStop(existingStop);
|
---|
| 619 | d_ptr->m_model->moveStop(stop, newPos);
|
---|
| 620 |
|
---|
| 621 | if (forward)
|
---|
| 622 | ++itNewPos;
|
---|
| 623 | }
|
---|
| 624 |
|
---|
| 625 | PositionColorMap::ConstIterator itOld = d_ptr->m_moveOriginal.constBegin();
|
---|
| 626 | while (itOld != d_ptr->m_moveOriginal.constEnd()) {
|
---|
| 627 | double position = itOld.key();
|
---|
| 628 | if (!d_ptr->m_model->at(position))
|
---|
| 629 | d_ptr->m_model->addStop(position, itOld.value());
|
---|
| 630 |
|
---|
| 631 | ++itOld;
|
---|
| 632 | }
|
---|
| 633 |
|
---|
| 634 | } else {
|
---|
| 635 | QRect r(QRect(d_ptr->m_clickPos, e->pos()).normalized());
|
---|
| 636 | r.translate(1, 0);
|
---|
| 637 | d_ptr->m_rubber->setGeometry(r);
|
---|
| 638 | //d_ptr->m_model->clearSelection();
|
---|
| 639 |
|
---|
| 640 | int xv1 = d_ptr->m_clickPos.x();
|
---|
| 641 | int xv2 = e->pos().x();
|
---|
| 642 | if (xv1 > xv2) {
|
---|
| 643 | int temp = xv1;
|
---|
| 644 | xv1 = xv2;
|
---|
| 645 | xv2 = temp;
|
---|
| 646 | }
|
---|
| 647 | int yv1 = d_ptr->m_clickPos.y();
|
---|
| 648 | int yv2 = e->pos().y();
|
---|
| 649 | if (yv1 > yv2) {
|
---|
| 650 | int temp = yv1;
|
---|
| 651 | yv1 = yv2;
|
---|
| 652 | yv2 = temp;
|
---|
| 653 | }
|
---|
| 654 |
|
---|
| 655 | QPoint p1, p2;
|
---|
| 656 |
|
---|
| 657 | if (yv2 < d_ptr->m_handleSize / 2) {
|
---|
| 658 | p1 = QPoint(xv1, yv2);
|
---|
| 659 | p2 = QPoint(xv2, yv2);
|
---|
| 660 | } else if (yv1 > d_ptr->m_handleSize / 2) {
|
---|
| 661 | p1 = QPoint(xv1, yv1);
|
---|
| 662 | p2 = QPoint(xv2, yv1);
|
---|
| 663 | } else {
|
---|
| 664 | p1 = QPoint(xv1, qRound(d_ptr->m_handleSize / 2));
|
---|
| 665 | p2 = QPoint(xv2, qRound(d_ptr->m_handleSize / 2));
|
---|
| 666 | }
|
---|
| 667 |
|
---|
| 668 | QList<QtGradientStop *> beginList = d_ptr->stopsAt(p1);
|
---|
| 669 | QList<QtGradientStop *> endList = d_ptr->stopsAt(p2);
|
---|
| 670 |
|
---|
| 671 | double x1 = d_ptr->fromViewport(xv1);
|
---|
| 672 | double x2 = d_ptr->fromViewport(xv2);
|
---|
| 673 |
|
---|
| 674 | QListIterator<QtGradientStop *> itStop(d_ptr->m_stops);
|
---|
| 675 | while (itStop.hasNext()) {
|
---|
| 676 | QtGradientStop *stop = itStop.next();
|
---|
| 677 | if ((stop->position() >= x1 && stop->position() <= x2) ||
|
---|
| 678 | beginList.contains(stop) || endList.contains(stop))
|
---|
| 679 | d_ptr->m_model->selectStop(stop, true);
|
---|
| 680 | else
|
---|
| 681 | d_ptr->m_model->selectStop(stop, false);
|
---|
| 682 | }
|
---|
| 683 | }
|
---|
| 684 | }
|
---|
| 685 |
|
---|
| 686 | void QtGradientStopsWidget::mouseDoubleClickEvent(QMouseEvent *e)
|
---|
| 687 | {
|
---|
| 688 | if (!d_ptr->m_model)
|
---|
| 689 | return;
|
---|
| 690 |
|
---|
| 691 | if (e->button() != Qt::LeftButton)
|
---|
| 692 | return;
|
---|
| 693 |
|
---|
| 694 | if (d_ptr->m_clickPos != e->pos()) {
|
---|
| 695 | mousePressEvent(e);
|
---|
| 696 | return;
|
---|
| 697 | }
|
---|
| 698 | d_ptr->m_moving = true;
|
---|
| 699 | d_ptr->m_moveStops.clear();
|
---|
| 700 | d_ptr->m_moveOriginal.clear();
|
---|
| 701 |
|
---|
| 702 | QtGradientStop *stop = d_ptr->newStop(e->pos());
|
---|
| 703 |
|
---|
| 704 | if (!stop)
|
---|
| 705 | return;
|
---|
| 706 |
|
---|
| 707 | d_ptr->m_model->clearSelection();
|
---|
| 708 | d_ptr->m_model->selectStop(stop, true);
|
---|
| 709 |
|
---|
| 710 | d_ptr->setupMove(stop, e->pos().x());
|
---|
| 711 |
|
---|
| 712 | viewport()->update();
|
---|
| 713 | }
|
---|
| 714 |
|
---|
| 715 | void QtGradientStopsWidget::keyPressEvent(QKeyEvent *e)
|
---|
| 716 | {
|
---|
| 717 | typedef QtGradientStopsModel::PositionStopMap PositionStopMap;
|
---|
| 718 | if (!d_ptr->m_model)
|
---|
| 719 | return;
|
---|
| 720 |
|
---|
| 721 | if (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace) {
|
---|
| 722 | d_ptr->m_model->deleteStops();
|
---|
| 723 | } else if (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right ||
|
---|
| 724 | e->key() == Qt::Key_Home || e->key() == Qt::Key_End) {
|
---|
| 725 | PositionStopMap stops = d_ptr->m_model->stops();
|
---|
| 726 | if (stops.isEmpty())
|
---|
| 727 | return;
|
---|
| 728 | QtGradientStop *newCurrent = 0;
|
---|
| 729 | QtGradientStop *current = d_ptr->m_model->currentStop();
|
---|
| 730 | if (!current || e->key() == Qt::Key_Home || e->key() == Qt::Key_End) {
|
---|
| 731 | if (e->key() == Qt::Key_Left || e->key() == Qt::Key_Home)
|
---|
| 732 | newCurrent = stops.constBegin().value();
|
---|
| 733 | else if (e->key() == Qt::Key_Right || e->key() == Qt::Key_End)
|
---|
| 734 | newCurrent = (--stops.constEnd()).value();
|
---|
| 735 | } else {
|
---|
| 736 | PositionStopMap::ConstIterator itStop = stops.constBegin();
|
---|
| 737 | while (itStop.value() != current)
|
---|
| 738 | ++itStop;
|
---|
| 739 | if (e->key() == Qt::Key_Left && itStop != stops.constBegin())
|
---|
| 740 | --itStop;
|
---|
| 741 | else if (e->key() == Qt::Key_Right && itStop != --stops.constEnd())
|
---|
| 742 | ++itStop;
|
---|
| 743 | newCurrent = itStop.value();
|
---|
| 744 | }
|
---|
| 745 | d_ptr->m_model->clearSelection();
|
---|
| 746 | d_ptr->m_model->selectStop(newCurrent, true);
|
---|
| 747 | d_ptr->m_model->setCurrentStop(newCurrent);
|
---|
| 748 | d_ptr->ensureVisible(newCurrent);
|
---|
| 749 | } else if (e->key() == Qt::Key_A) {
|
---|
| 750 | if (e->modifiers() & Qt::ControlModifier)
|
---|
| 751 | d_ptr->m_model->selectAll();
|
---|
| 752 | }
|
---|
| 753 | }
|
---|
| 754 |
|
---|
| 755 | void QtGradientStopsWidget::paintEvent(QPaintEvent *e)
|
---|
| 756 | {
|
---|
| 757 | Q_UNUSED(e)
|
---|
| 758 | if (!d_ptr->m_model)
|
---|
| 759 | return;
|
---|
| 760 |
|
---|
| 761 | QtGradientStopsModel *model = d_ptr->m_model;
|
---|
| 762 | #ifndef QT_NO_DRAGANDDROP
|
---|
| 763 | if (d_ptr->m_dragModel)
|
---|
| 764 | model = d_ptr->m_dragModel;
|
---|
| 765 | #endif
|
---|
| 766 |
|
---|
| 767 | QSize size = viewport()->size();
|
---|
| 768 | int w = size.width();
|
---|
| 769 | double h = size.height() - d_ptr->m_handleSize;
|
---|
| 770 | if (w <= 0)
|
---|
| 771 | return;
|
---|
| 772 |
|
---|
| 773 | QPixmap pix(size);
|
---|
| 774 | QPainter p;
|
---|
| 775 |
|
---|
| 776 | if (d_ptr->m_backgroundCheckered) {
|
---|
| 777 | int pixSize = 20;
|
---|
| 778 | QPixmap pm(2 * pixSize, 2 * pixSize);
|
---|
| 779 | QPainter pmp(&pm);
|
---|
| 780 | pmp.fillRect(0, 0, pixSize, pixSize, Qt::white);
|
---|
| 781 | pmp.fillRect(pixSize, pixSize, pixSize, pixSize, Qt::white);
|
---|
| 782 | pmp.fillRect(0, pixSize, pixSize, pixSize, Qt::black);
|
---|
| 783 | pmp.fillRect(pixSize, 0, pixSize, pixSize, Qt::black);
|
---|
| 784 |
|
---|
| 785 | p.begin(&pix);
|
---|
| 786 | p.setBrushOrigin((size.width() % pixSize + pixSize) / 2, (size.height() % pixSize + pixSize) / 2);
|
---|
| 787 | p.fillRect(viewport()->rect(), pm);
|
---|
| 788 | p.setBrushOrigin(0, 0);
|
---|
| 789 | } else {
|
---|
| 790 | p.begin(viewport());
|
---|
| 791 | }
|
---|
| 792 |
|
---|
| 793 | double viewBegin = (double)w * horizontalScrollBar()->value() / d_ptr->m_scaleFactor;
|
---|
| 794 |
|
---|
| 795 | int val = horizontalScrollBar()->value();
|
---|
| 796 | int max = horizontalScrollBar()->maximum();
|
---|
| 797 |
|
---|
| 798 | double begin = (double)val / (d_ptr->m_scaleFactor + max);
|
---|
| 799 | double end = (double)(val + d_ptr->m_scaleFactor) / (d_ptr->m_scaleFactor + max);
|
---|
| 800 | double width = end - begin;
|
---|
| 801 |
|
---|
| 802 | if (h > 0) {
|
---|
| 803 | QLinearGradient lg(0, 0, w, 0);
|
---|
| 804 | QMap<qreal, QtGradientStop *> stops = model->stops();
|
---|
| 805 | QMapIterator<qreal, QtGradientStop *> itStop(stops);
|
---|
| 806 | while (itStop.hasNext()) {
|
---|
| 807 | QtGradientStop *stop = itStop.next().value();
|
---|
| 808 | double pos = stop->position();
|
---|
| 809 | if (pos >= begin && pos <= end) {
|
---|
| 810 | double gradPos = (pos - begin) / width;
|
---|
| 811 | QColor c = stop->color();
|
---|
| 812 | lg.setColorAt(gradPos, c);
|
---|
| 813 | }
|
---|
| 814 | //lg.setColorAt(stop->position(), stop->color());
|
---|
| 815 | }
|
---|
| 816 | lg.setColorAt(0, model->color(begin));
|
---|
| 817 | lg.setColorAt(1, model->color(end));
|
---|
| 818 | QImage img(w, 1, QImage::Format_ARGB32_Premultiplied);
|
---|
| 819 | QPainter p1(&img);
|
---|
| 820 | p1.setCompositionMode(QPainter::CompositionMode_Source);
|
---|
| 821 |
|
---|
| 822 | /*
|
---|
| 823 | if (viewBegin != 0)
|
---|
| 824 | p1.translate(-viewBegin, 0);
|
---|
| 825 | if (d_ptr->m_zoom != 1)
|
---|
| 826 | p1.scale(d_ptr->m_zoom, 1);
|
---|
| 827 | */
|
---|
| 828 | p1.fillRect(0, 0, w, 1, lg);
|
---|
| 829 |
|
---|
| 830 | p.fillRect(QRectF(0, d_ptr->m_handleSize, w, h), QPixmap::fromImage(img));
|
---|
| 831 | }
|
---|
| 832 |
|
---|
| 833 |
|
---|
| 834 | double handleWidth = d_ptr->m_handleSize * d_ptr->m_scaleFactor / (w * (d_ptr->m_scaleFactor + max));
|
---|
| 835 |
|
---|
| 836 | QColor insideColor = QColor::fromRgb(0x20, 0x20, 0x20, 0xFF);
|
---|
| 837 | QColor borderColor = QColor(Qt::white);
|
---|
| 838 | QColor drawColor;
|
---|
| 839 | QColor back1 = QColor(Qt::lightGray);
|
---|
| 840 | QColor back2 = QColor(Qt::darkGray);
|
---|
| 841 | QColor back = QColor::fromRgb((back1.red() + back2.red()) / 2,
|
---|
| 842 | (back1.green() + back2.green()) / 2,
|
---|
| 843 | (back1.blue() + back2.blue()) / 2);
|
---|
| 844 |
|
---|
| 845 | QPen pen;
|
---|
| 846 | p.setRenderHint(QPainter::Antialiasing);
|
---|
| 847 | QListIterator<QtGradientStop *> itStop(d_ptr->m_stops);
|
---|
| 848 | itStop.toBack();
|
---|
| 849 | while (itStop.hasPrevious()) {
|
---|
| 850 | QtGradientStop *stop = itStop.previous();
|
---|
| 851 | double x = stop->position();
|
---|
| 852 | if (x >= begin - handleWidth / 2 && x <= end + handleWidth / 2) {
|
---|
| 853 | double viewX = x * w * (d_ptr->m_scaleFactor + max) / d_ptr->m_scaleFactor - viewBegin;
|
---|
| 854 | p.save();
|
---|
| 855 | QColor c = stop->color();
|
---|
| 856 | #ifndef QT_NO_DRAGANDDROP
|
---|
| 857 | if (stop == d_ptr->m_dragStop)
|
---|
| 858 | c = d_ptr->m_dragColor;
|
---|
| 859 | #endif
|
---|
| 860 | if ((0.3 * c.redF() + 0.59 * c.greenF() + 0.11 * c.blueF()) * c.alphaF() +
|
---|
| 861 | (0.3 * back.redF() + 0.59 * back.greenF() + 0.11 * back.blueF()) * (1.0 - c.alphaF()) < 0.5) {
|
---|
| 862 | drawColor = QColor::fromRgb(0xC0, 0xC0, 0xC0, 0xB0);
|
---|
| 863 | } else {
|
---|
| 864 | drawColor = QColor::fromRgb(0x40, 0x40, 0x40, 0x80);
|
---|
| 865 | }
|
---|
| 866 | QRectF rect(viewX - d_ptr->m_handleSize / 2, 0, d_ptr->m_handleSize, d_ptr->m_handleSize);
|
---|
| 867 | rect.adjust(0.5, 0.5, -0.5, -0.5);
|
---|
| 868 | if (h > 0) {
|
---|
| 869 | pen.setWidthF(1);
|
---|
| 870 | QLinearGradient lg(0, d_ptr->m_handleSize, 0, d_ptr->m_handleSize + h / 2);
|
---|
| 871 | lg.setColorAt(0, drawColor);
|
---|
| 872 | QColor alphaZero = drawColor;
|
---|
| 873 | alphaZero.setAlpha(0);
|
---|
| 874 | lg.setColorAt(1, alphaZero);
|
---|
| 875 | pen.setBrush(lg);
|
---|
| 876 | p.setPen(pen);
|
---|
| 877 | p.drawLine(QPointF(viewX, d_ptr->m_handleSize), QPointF(viewX, d_ptr->m_handleSize + h / 2));
|
---|
| 878 |
|
---|
| 879 | pen.setWidthF(1);
|
---|
| 880 | pen.setBrush(drawColor);
|
---|
| 881 | p.setPen(pen);
|
---|
| 882 | QRectF r1 = rect.adjusted(0.5, 0.5, -0.5, -0.5);
|
---|
| 883 | QRectF r2 = rect.adjusted(1.5, 1.5, -1.5, -1.5);
|
---|
| 884 | QColor inColor = QColor::fromRgb(0x80, 0x80, 0x80, 0x80);
|
---|
| 885 | if (!d_ptr->m_model->isSelected(stop)) {
|
---|
| 886 | p.setBrush(c);
|
---|
| 887 | p.drawEllipse(rect);
|
---|
| 888 | } else {
|
---|
| 889 | pen.setBrush(insideColor);
|
---|
| 890 | pen.setWidthF(2);
|
---|
| 891 | p.setPen(pen);
|
---|
| 892 | p.setBrush(Qt::NoBrush);
|
---|
| 893 | p.drawEllipse(r1);
|
---|
| 894 |
|
---|
| 895 | pen.setBrush(inColor);
|
---|
| 896 | pen.setWidthF(1);
|
---|
| 897 | p.setPen(pen);
|
---|
| 898 | p.setBrush(c);
|
---|
| 899 | p.drawEllipse(r2);
|
---|
| 900 | }
|
---|
| 901 |
|
---|
| 902 | if (d_ptr->m_model->currentStop() == stop) {
|
---|
| 903 | p.setBrush(Qt::NoBrush);
|
---|
| 904 | pen.setWidthF(5);
|
---|
| 905 | pen.setBrush(drawColor);
|
---|
| 906 | int corr = 4;
|
---|
| 907 | if (!d_ptr->m_model->isSelected(stop)) {
|
---|
| 908 | corr = 3;
|
---|
| 909 | pen.setWidthF(7);
|
---|
| 910 | }
|
---|
| 911 | p.setPen(pen);
|
---|
| 912 | p.drawEllipse(rect.adjusted(corr, corr, -corr, -corr));
|
---|
| 913 | }
|
---|
| 914 |
|
---|
| 915 | }
|
---|
| 916 | p.restore();
|
---|
| 917 | }
|
---|
| 918 | }
|
---|
| 919 | if (d_ptr->m_backgroundCheckered) {
|
---|
| 920 | p.end();
|
---|
| 921 | p.begin(viewport());
|
---|
| 922 | p.drawPixmap(0, 0, pix);
|
---|
| 923 | }
|
---|
| 924 | p.end();
|
---|
| 925 | }
|
---|
| 926 |
|
---|
| 927 | void QtGradientStopsWidget::focusInEvent(QFocusEvent *e)
|
---|
| 928 | {
|
---|
| 929 | Q_UNUSED(e)
|
---|
| 930 | viewport()->update();
|
---|
| 931 | }
|
---|
| 932 |
|
---|
| 933 | void QtGradientStopsWidget::focusOutEvent(QFocusEvent *e)
|
---|
| 934 | {
|
---|
| 935 | Q_UNUSED(e)
|
---|
| 936 | viewport()->update();
|
---|
| 937 | }
|
---|
| 938 |
|
---|
| 939 | void QtGradientStopsWidget::contextMenuEvent(QContextMenuEvent *e)
|
---|
| 940 | {
|
---|
| 941 | if (!d_ptr->m_model)
|
---|
| 942 | return;
|
---|
| 943 |
|
---|
| 944 | d_ptr->m_clickPos = e->pos();
|
---|
| 945 |
|
---|
| 946 | QMenu menu(this);
|
---|
| 947 | QAction *newStopAction = new QAction(tr("New Stop"), &menu);
|
---|
| 948 | QAction *deleteAction = new QAction(tr("Delete"), &menu);
|
---|
| 949 | QAction *flipAllAction = new QAction(tr("Flip All"), &menu);
|
---|
| 950 | QAction *selectAllAction = new QAction(tr("Select All"), &menu);
|
---|
| 951 | QAction *zoomInAction = new QAction(tr("Zoom In"), &menu);
|
---|
| 952 | QAction *zoomOutAction = new QAction(tr("Zoom Out"), &menu);
|
---|
| 953 | QAction *zoomAllAction = new QAction(tr("Reset Zoom"), &menu);
|
---|
| 954 | if (d_ptr->m_model->selectedStops().isEmpty() && !d_ptr->m_model->currentStop())
|
---|
| 955 | deleteAction->setEnabled(false);
|
---|
| 956 | if (zoom() <= 1) {
|
---|
| 957 | zoomOutAction->setEnabled(false);
|
---|
| 958 | zoomAllAction->setEnabled(false);
|
---|
| 959 | } else if (zoom() >= 100) {
|
---|
| 960 | zoomInAction->setEnabled(false);
|
---|
| 961 | }
|
---|
| 962 | connect(newStopAction, SIGNAL(triggered()), this, SLOT(slotNewStop()));
|
---|
| 963 | connect(deleteAction, SIGNAL(triggered()), this, SLOT(slotDelete()));
|
---|
| 964 | connect(flipAllAction, SIGNAL(triggered()), this, SLOT(slotFlipAll()));
|
---|
| 965 | connect(selectAllAction, SIGNAL(triggered()), this, SLOT(slotSelectAll()));
|
---|
| 966 | connect(zoomInAction, SIGNAL(triggered()), this, SLOT(slotZoomIn()));
|
---|
| 967 | connect(zoomOutAction, SIGNAL(triggered()), this, SLOT(slotZoomOut()));
|
---|
| 968 | connect(zoomAllAction, SIGNAL(triggered()), this, SLOT(slotResetZoom()));
|
---|
| 969 | menu.addAction(newStopAction);
|
---|
| 970 | menu.addAction(deleteAction);
|
---|
| 971 | menu.addAction(flipAllAction);
|
---|
| 972 | menu.addAction(selectAllAction);
|
---|
| 973 | menu.addSeparator();
|
---|
| 974 | menu.addAction(zoomInAction);
|
---|
| 975 | menu.addAction(zoomOutAction);
|
---|
| 976 | menu.addAction(zoomAllAction);
|
---|
| 977 | menu.exec(e->globalPos());
|
---|
| 978 | }
|
---|
| 979 |
|
---|
| 980 | void QtGradientStopsWidget::wheelEvent(QWheelEvent *e)
|
---|
| 981 | {
|
---|
| 982 | int numDegrees = e->delta() / 8;
|
---|
| 983 | int numSteps = numDegrees / 15;
|
---|
| 984 |
|
---|
| 985 | int shift = numSteps;
|
---|
| 986 | if (shift < 0)
|
---|
| 987 | shift = -shift;
|
---|
| 988 | int pow = 1 << shift;
|
---|
| 989 | //const double c = 0.7071067; // 2 steps per doubled value
|
---|
| 990 | const double c = 0.5946036; // 4 steps pre doubled value
|
---|
| 991 | // in general c = pow(2, 1 / n) / 2; where n is the step
|
---|
| 992 | double factor = pow * c;
|
---|
| 993 |
|
---|
| 994 | double newZoom = zoom();
|
---|
| 995 | if (numSteps < 0)
|
---|
| 996 | newZoom /= factor;
|
---|
| 997 | else
|
---|
| 998 | newZoom *= factor;
|
---|
| 999 | if (newZoom > 100)
|
---|
| 1000 | newZoom = 100;
|
---|
| 1001 | if (newZoom < 1)
|
---|
| 1002 | newZoom = 1;
|
---|
| 1003 |
|
---|
| 1004 | if (newZoom == zoom())
|
---|
| 1005 | return;
|
---|
| 1006 |
|
---|
| 1007 | setZoom(newZoom);
|
---|
| 1008 | emit zoomChanged(zoom());
|
---|
| 1009 | }
|
---|
| 1010 |
|
---|
| 1011 | #ifndef QT_NO_DRAGANDDROP
|
---|
| 1012 | void QtGradientStopsWidget::dragEnterEvent(QDragEnterEvent *event)
|
---|
| 1013 | {
|
---|
| 1014 | const QMimeData *mime = event->mimeData();
|
---|
| 1015 | if (!mime->hasColor())
|
---|
| 1016 | return;
|
---|
| 1017 | event->accept();
|
---|
| 1018 | d_ptr->m_dragModel = d_ptr->m_model->clone();
|
---|
| 1019 |
|
---|
| 1020 | d_ptr->m_dragColor = qvariant_cast<QColor>(mime->colorData());
|
---|
| 1021 | update();
|
---|
| 1022 | }
|
---|
| 1023 |
|
---|
| 1024 | void QtGradientStopsWidget::dragMoveEvent(QDragMoveEvent *event)
|
---|
| 1025 | {
|
---|
| 1026 | QRectF rect = viewport()->rect();
|
---|
| 1027 | rect.adjust(0, d_ptr->m_handleSize, 0, 0);
|
---|
| 1028 | double x = d_ptr->fromViewport(event->pos().x());
|
---|
| 1029 | QtGradientStop *dragStop = d_ptr->stopAt(event->pos());
|
---|
| 1030 | if (dragStop) {
|
---|
| 1031 | event->accept();
|
---|
| 1032 | d_ptr->removeClonedStop();
|
---|
| 1033 | d_ptr->changeStop(dragStop->position());
|
---|
| 1034 | } else if (rect.contains(event->pos())) {
|
---|
| 1035 | event->accept();
|
---|
| 1036 | if (d_ptr->m_model->at(x)) {
|
---|
| 1037 | d_ptr->removeClonedStop();
|
---|
| 1038 | d_ptr->changeStop(x);
|
---|
| 1039 | } else {
|
---|
| 1040 | d_ptr->restoreChangedStop();
|
---|
| 1041 | d_ptr->cloneStop(x);
|
---|
| 1042 | }
|
---|
| 1043 | } else {
|
---|
| 1044 | event->ignore();
|
---|
| 1045 | d_ptr->removeClonedStop();
|
---|
| 1046 | d_ptr->restoreChangedStop();
|
---|
| 1047 | }
|
---|
| 1048 |
|
---|
| 1049 | update();
|
---|
| 1050 | }
|
---|
| 1051 |
|
---|
| 1052 | void QtGradientStopsWidget::dragLeaveEvent(QDragLeaveEvent *event)
|
---|
| 1053 | {
|
---|
| 1054 | event->accept();
|
---|
| 1055 | d_ptr->clearDrag();
|
---|
| 1056 | update();
|
---|
| 1057 | }
|
---|
| 1058 |
|
---|
| 1059 | void QtGradientStopsWidget::dropEvent(QDropEvent *event)
|
---|
| 1060 | {
|
---|
| 1061 | event->accept();
|
---|
| 1062 | if (!d_ptr->m_dragModel)
|
---|
| 1063 | return;
|
---|
| 1064 |
|
---|
| 1065 | if (d_ptr->m_changedStop)
|
---|
| 1066 | d_ptr->m_model->changeStop(d_ptr->m_model->at(d_ptr->m_changedStop->position()), d_ptr->m_dragColor);
|
---|
| 1067 | else if (d_ptr->m_clonedStop)
|
---|
| 1068 | d_ptr->m_model->addStop(d_ptr->m_clonedStop->position(), d_ptr->m_dragColor);
|
---|
| 1069 |
|
---|
| 1070 | d_ptr->clearDrag();
|
---|
| 1071 | update();
|
---|
| 1072 | }
|
---|
| 1073 |
|
---|
| 1074 | void QtGradientStopsWidgetPrivate::clearDrag()
|
---|
| 1075 | {
|
---|
| 1076 | removeClonedStop();
|
---|
| 1077 | restoreChangedStop();
|
---|
| 1078 | delete m_dragModel;
|
---|
| 1079 | m_dragModel = 0;
|
---|
| 1080 | }
|
---|
| 1081 |
|
---|
| 1082 | void QtGradientStopsWidgetPrivate::removeClonedStop()
|
---|
| 1083 | {
|
---|
| 1084 | if (!m_clonedStop)
|
---|
| 1085 | return;
|
---|
| 1086 | m_dragModel->removeStop(m_clonedStop);
|
---|
| 1087 | m_clonedStop = 0;
|
---|
| 1088 | }
|
---|
| 1089 |
|
---|
| 1090 | void QtGradientStopsWidgetPrivate::restoreChangedStop()
|
---|
| 1091 | {
|
---|
| 1092 | if (!m_changedStop)
|
---|
| 1093 | return;
|
---|
| 1094 | m_dragModel->changeStop(m_changedStop, m_model->at(m_changedStop->position())->color());
|
---|
| 1095 | m_changedStop = 0;
|
---|
| 1096 | m_dragStop = 0;
|
---|
| 1097 | }
|
---|
| 1098 |
|
---|
| 1099 | void QtGradientStopsWidgetPrivate::changeStop(qreal pos)
|
---|
| 1100 | {
|
---|
| 1101 | QtGradientStop *stop = m_dragModel->at(pos);
|
---|
| 1102 | if (!stop)
|
---|
| 1103 | return;
|
---|
| 1104 |
|
---|
| 1105 | m_dragModel->changeStop(stop, m_dragColor);
|
---|
| 1106 | m_changedStop = stop;
|
---|
| 1107 | m_dragStop = m_model->at(stop->position());
|
---|
| 1108 | }
|
---|
| 1109 |
|
---|
| 1110 | void QtGradientStopsWidgetPrivate::cloneStop(qreal pos)
|
---|
| 1111 | {
|
---|
| 1112 | if (m_clonedStop) {
|
---|
| 1113 | m_dragModel->moveStop(m_clonedStop, pos);
|
---|
| 1114 | return;
|
---|
| 1115 | }
|
---|
| 1116 | QtGradientStop *stop = m_dragModel->at(pos);
|
---|
| 1117 | if (stop)
|
---|
| 1118 | return;
|
---|
| 1119 |
|
---|
| 1120 | m_clonedStop = m_dragModel->addStop(pos, m_dragColor);
|
---|
| 1121 | }
|
---|
| 1122 |
|
---|
| 1123 | #endif
|
---|
| 1124 |
|
---|
| 1125 | void QtGradientStopsWidget::setZoom(double zoom)
|
---|
| 1126 | {
|
---|
| 1127 | double z = zoom;
|
---|
| 1128 | if (z < 1)
|
---|
| 1129 | z = 1;
|
---|
| 1130 | else if (z > 100)
|
---|
| 1131 | z = 100;
|
---|
| 1132 |
|
---|
| 1133 | if (d_ptr->m_zoom == z)
|
---|
| 1134 | return;
|
---|
| 1135 |
|
---|
| 1136 | d_ptr->m_zoom = z;
|
---|
| 1137 | int oldMax = horizontalScrollBar()->maximum();
|
---|
| 1138 | int oldVal = horizontalScrollBar()->value();
|
---|
| 1139 | horizontalScrollBar()->setRange(0, qRound(d_ptr->m_scaleFactor * (d_ptr->m_zoom - 1)));
|
---|
| 1140 | int newMax = horizontalScrollBar()->maximum();
|
---|
| 1141 | double newVal = (oldVal + (double)d_ptr->m_scaleFactor / 2) * (newMax + d_ptr->m_scaleFactor)
|
---|
| 1142 | / (oldMax + d_ptr->m_scaleFactor) - (double)d_ptr->m_scaleFactor / 2;
|
---|
| 1143 | horizontalScrollBar()->setValue(qRound(newVal));
|
---|
| 1144 | viewport()->update();
|
---|
| 1145 | }
|
---|
| 1146 |
|
---|
| 1147 | double QtGradientStopsWidget::zoom() const
|
---|
| 1148 | {
|
---|
| 1149 | return d_ptr->m_zoom;
|
---|
| 1150 | }
|
---|
| 1151 |
|
---|
| 1152 | QT_END_NAMESPACE
|
---|
| 1153 |
|
---|
| 1154 | #include "moc_qtgradientstopswidget.cpp"
|
---|