56 setObjectName(
"KisCurveWidget");
58 connect(&
d->m_modifiedSignalsCompressor, SIGNAL(timeout()), SLOT(
notifyModified()));
61 setMouseTracking(
true);
62 setAutoFillBackground(
false);
63 setAttribute(Qt::WA_OpaquePaintEvent);
64 setMinimumSize(150, 50);
65 setMaximumSize(250, 250);
69 setContextMenuPolicy(Qt::PreventContextMenu);
71 setFocusPolicy(Qt::StrongFocus);
82 Q_ASSERT(
d->m_grab_point_index >= 0);
84 bool needResyncControls =
true;
88 d->m_curve.setPointAsCorner(
d->m_grab_point_index, setAsCorner);
89 isCorner = setAsCorner;
94 QPointF newPosition(position);
96 if (
d->jumpOverExistingPoints(newPosition,
d->m_grab_point_index)) {
97 needResyncControls =
false;
98 d->m_curve.setPointPosition(
d->m_grab_point_index, newPosition);
99 d->m_grab_point_index =
d->m_curve.curvePoints().indexOf(
105 d->setCurveModified(
false);
106 return needResyncControls;
203 if (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace) {
204 if (
d->m_grab_point_index > 0 &&
d->m_grab_point_index <
d->m_curve.curvePoints().count() - 1) {
206 double grab_point_x =
d->m_curve.curvePoints()[
d->m_grab_point_index].x();
208 int left_of_grab_point_index =
d->m_grab_point_index - 1;
209 int right_of_grab_point_index =
d->m_grab_point_index + 1;
210 int new_grab_point_index;
212 if (fabs(
d->m_curve.curvePoints()[left_of_grab_point_index].x() - grab_point_x) <
213 fabs(
d->m_curve.curvePoints()[right_of_grab_point_index].x() - grab_point_x)) {
214 new_grab_point_index = left_of_grab_point_index;
216 new_grab_point_index =
d->m_grab_point_index;
218 d->m_curve.removePoint(
d->m_grab_point_index);
219 d->m_grab_point_index = new_grab_point_index;
221 setCursor(Qt::ArrowCursor);
225 d->setCurveModified();
226 }
else if (e->key() == Qt::Key_Escape &&
d->state() !=
ST_NORMAL) {
227 d->m_curve.setPointPosition(
d->m_grab_point_index, QPointF(
d->m_grabOriginalX,
d->m_grabOriginalY) );
228 setCursor(Qt::ArrowCursor);
232 d->setCurveModified();
233 }
else if ((e->key() == Qt::Key_A || e->key() == Qt::Key_Insert) &&
d->state() ==
ST_NORMAL) {
237 }
else if (e->key() == Qt::Key_S &&
245 QWidget::keyPressEvent(e);
272 int wWidth = width() - 1;
273 int wHeight = height() - 1;
282 QPalette appPalette = QApplication::palette();
283 p.fillRect(
rect(), appPalette.color(QPalette::Base));
286 if (!this->isEnabled()) {
293 if (!
d->m_pix.isNull()) {
294 if (
d->m_pixmapDirty || !
d->m_pixmapCache) {
295 delete d->m_pixmapCache;
296 d->m_pixmapCache =
new QPixmap(width(), height());
297 QPainter cachePainter(
d->m_pixmapCache);
299 cachePainter.scale(1.0*width() /
d->m_pix.width(), 1.0*height() /
d->m_pix.height());
300 cachePainter.drawPixmap(0, 0,
d->m_pix);
301 d->m_pixmapDirty =
false;
303 p.drawPixmap(0, 0, *
d->m_pixmapCache);
306 d->drawGrid(
p, wWidth, wHeight);
310 p.setRenderHint(QPainter::Antialiasing);
320 p.setPen(QPen(appPalette.color(QPalette::Text), 2, Qt::SolidLine));
321 for (x = 0 ; x < wWidth ; x++) {
322 normalizedX = double(x) / wWidth;
323 curY = wHeight -
d->m_curve.value(normalizedX) * wHeight;
330 poly.append(QPointF(x, curY));
332 poly.append(QPointF(x, wHeight -
d->m_curve.value(1.0) * wHeight));
333 p.drawPolyline(poly);
335 QPainterPath fillCurvePath;
336 QPolygonF fillPoly = poly;
337 fillPoly.append(QPoint(
rect().width(),
rect().height()));
338 fillPoly.append(QPointF(0,
rect().height()));
342 QColor fillColor = appPalette.color(QPalette::Text);
343 fillColor.setAlphaF(0.2);
345 fillCurvePath.addPolygon(fillPoly);
346 p.fillPath(fillCurvePath, fillColor);
351 if (!
d->m_readOnlyMode) {
352 const qreal halfHandleSize =
d->m_handleSize * 0.5;
354 for (
int i = 0; i <
d->m_curve.curvePoints().count(); ++i) {
357 if (i ==
d->m_grab_point_index) {
359 p.setPen(QPen(appPalette.color(QPalette::Text), 4, Qt::SolidLine));
361 p.setPen(QPen(appPalette.color(QPalette::Text), 2, Qt::SolidLine));
364 const QPointF handleCenter(point.
x() * wWidth, wHeight - point.
y() * wHeight);
367 QPolygonF rhombusHandle;
368 rhombusHandle.append(QPointF(handleCenter.x() - halfHandleSize, handleCenter.y()));
369 rhombusHandle.append(QPointF(handleCenter.x(), handleCenter.y() - halfHandleSize));
370 rhombusHandle.append(QPointF(handleCenter.x() + halfHandleSize, handleCenter.y()));
371 rhombusHandle.append(QPointF(handleCenter.x(), handleCenter.y() + halfHandleSize));
372 p.drawPolygon(rhombusHandle);
374 p.drawEllipse(handleCenter, halfHandleSize, halfHandleSize);
380 QPainterPath widgetBoundsPath;
381 widgetBoundsPath.addRect(
rect());
382 p.strokePath(widgetBoundsPath, appPalette.color(QPalette::Text));
390 if (
d->m_readOnlyMode)
return;
392 if (e->button() != Qt::LeftButton)
395 double x = e->pos().x() / (double)(width() - 1);
396 double y = 1.0 - e->pos().y() / (double)(height() - 1);
400 int closest_point_index =
d->nearestPointInRange(QPointF(x, y), width(), height());
401 if (closest_point_index < 0) {
402 QPointF newPoint(x, y);
403 if (!
d->jumpOverExistingPoints(newPoint, -1))
407 d->m_grab_point_index =
d->m_curve.addPoint(newPoint, setAsCorner);
410 d->m_grab_point_index = closest_point_index;
420 if (e->modifiers().testFlag(Qt::ControlModifier) &&
d->m_globalPointConstrain ==
PointConstrain_None) {
421 d->m_curve.setPointAsCorner(
d->m_grab_point_index, !
currentPoint.isSetAsCorner());
423 d->m_curve.setPointPosition(
d->m_grab_point_index, QPointF(x +
d->m_grabOffsetX, y +
d->m_grabOffsetY));
425 d->m_draggedAwayPointIndex = -1;
429 d->setCurveModified();
449 if (
d->m_readOnlyMode)
return;
451 double x = e->pos().x() / (double)(width() - 1);
452 double y = 1.0 - e->pos().y() / (double)(height() - 1);
455 int nearestPointIndex =
d->nearestPointInRange(QPointF(x, y), width(), height());
457 if (nearestPointIndex < 0)
458 setCursor(Qt::ArrowCursor);
460 setCursor(Qt::CrossCursor);
467 bool removePoint = (crossedHoriz || crossedVert);
469 if (!removePoint &&
d->m_draggedAwayPointIndex >= 0) {
472 d->m_grab_point_index =
d->m_curve.addPoint(newPoint);
473 d->m_draggedAwayPointIndex = -1;
477 (
d->m_draggedAwayPointIndex >= 0))
481 setCursor(Qt::CrossCursor);
483 x +=
d->m_grabOffsetX;
484 y +=
d->m_grabOffsetY;
488 if (
d->m_grab_point_index == 0) {
490 if (
d->m_curve.curvePoints().count() > 1)
491 rightX =
d->m_curve.curvePoints()[
d->m_grab_point_index + 1].x() -
POINT_AREA;
494 }
else if (
d->m_grab_point_index ==
d->m_curve.curvePoints().count() - 1) {
495 leftX =
d->m_curve.curvePoints()[
d->m_grab_point_index - 1].x() +
POINT_AREA;
498 Q_ASSERT(
d->m_grab_point_index > 0 &&
d->m_grab_point_index <
d->m_curve.curvePoints().count() - 1);
501 leftX =
d->m_curve.curvePoints()[
d->m_grab_point_index - 1].x() +
POINT_AREA;
502 rightX =
d->m_curve.curvePoints()[
d->m_grab_point_index + 1].x() -
POINT_AREA;
505 x =
bounds(x, leftX, rightX);
508 d->m_curve.setPointPosition(
d->m_grab_point_index, QPointF(x, y));
510 if (removePoint &&
d->m_curve.curvePoints().count() > 2) {
511 d->m_draggedAwayPoint =
d->m_curve.curvePoints()[
d->m_grab_point_index];
512 d->m_draggedAwayPointIndex =
d->m_grab_point_index;
513 d->m_curve.removePoint(
d->m_grab_point_index);
514 d->m_grab_point_index =
bounds(
d->m_grab_point_index, 0,
d->m_curve.curvePoints().count() - 1);
518 d->setCurveModified();