X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fbeziercurve%2Fbeziersplinewidget.cpp;h=dca3f40f4c207e6eaa220c4368094bc72c4b1525;hb=ac8c99168f151e2f351043d13500741ce1ca8966;hp=8f6eff0de98102de8b4656fa63af9f6271ebe55e;hpb=6962205e2e8db1148bc418236652121c16341d68;p=kdenlive diff --git a/src/beziercurve/beziersplinewidget.cpp b/src/beziercurve/beziersplinewidget.cpp index 8f6eff0d..dca3f40f 100644 --- a/src/beziercurve/beziersplinewidget.cpp +++ b/src/beziercurve/beziersplinewidget.cpp @@ -17,336 +17,199 @@ ***************************************************************************/ #include "beziersplinewidget.h" +#include "colortools.h" +#include "dragvalue.h" +#include "kdenlivesettings.h" -#include -#include +#include -#include +#include +#include -BezierSplineWidget::BezierSplineWidget(QWidget* parent) : - QWidget(parent), - m_mode(ModeNormal), - m_currentPointIndex(-1) -{ - setMouseTracking(true); - setAutoFillBackground(false); - setAttribute(Qt::WA_OpaquePaintEvent); - setMinimumSize(150, 150); - setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); -} -CubicBezierSpline BezierSplineWidget::spline() +BezierSplineWidget::BezierSplineWidget(const QString& spline, QWidget* parent) : + QWidget(parent), + m_mode(ModeRGB), + m_showPixmap(true) { - return m_spline; + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addWidget(&m_edit); + QWidget *widget = new QWidget(this); + m_ui.setupUi(widget); + layout->addWidget(widget); + + m_ui.buttonLinkHandles->setIcon(KIcon(QLatin1String("insert-link"))); + m_ui.buttonZoomIn->setIcon(KIcon(QLatin1String("zoom-in"))); + m_ui.buttonZoomOut->setIcon(KIcon(QLatin1String("zoom-out"))); + m_ui.buttonGridChange->setIcon(KIcon(QLatin1String("view-grid"))); + m_ui.buttonShowPixmap->setIcon(QIcon(QPixmap::fromImage(ColorTools::rgbCurvePlane(QSize(16, 16), ColorTools::COL_Luma, 0.8)))); + m_ui.buttonResetSpline->setIcon(KIcon(QLatin1String("view-refresh"))); + m_ui.buttonShowAllHandles->setIcon(KIcon(QLatin1String("draw-bezier-curves"))); + m_ui.widgetPoint->setEnabled(false); + + m_pX = new DragValue(i18n("In"), 0, 3, 0, 1, -1, QString(), false, this); + m_pX->setStep(0.001); + m_pY = new DragValue(i18n("Out"), 0, 3, 0, 1, -1, QString(), false, this); + m_pY->setStep(0.001); + m_h1X = new DragValue(i18n("X"), 0, 3, -2, 2, -1, QString(), false, this); + m_h1X->setStep(0.001); + m_h1Y = new DragValue(i18n("Y"), 0, 3, -2, 2, -1, QString(), false, this); + m_h1Y->setStep(0.001); + m_h2X = new DragValue(i18n("X"), 0, 3, -2, 2, -1, QString(), false, this); + m_h2X->setStep(0.001); + m_h2Y = new DragValue(i18n("Y"), 0, 3, -2, 2, -1, QString(), false, this); + m_h2Y->setStep(0.001); + + m_ui.layoutP->addWidget(m_pX); + m_ui.layoutP->addWidget(m_pY); + m_ui.layoutH1->addWidget(new QLabel(i18n("Handle 1:"))); + m_ui.layoutH1->addWidget(m_h1X); + m_ui.layoutH1->addWidget(m_h1Y); + m_ui.layoutH2->addWidget(new QLabel(i18n("Handle 2:"))); + m_ui.layoutH2->addWidget(m_h2X); + m_ui.layoutH2->addWidget(m_h2Y); + + CubicBezierSpline s; + s.fromString(spline); + m_edit.setSpline(s); + + connect(&m_edit, SIGNAL(modified()), this, SIGNAL(modified())); + connect(&m_edit, SIGNAL(currentPoint(BPoint)), this, SLOT(slotUpdatePointEntries(BPoint))); + + connect(m_pX, SIGNAL(valueChanged(double,bool)), this, SLOT(slotUpdatePointP(double,bool))); + connect(m_pY, SIGNAL(valueChanged(double,bool)), this, SLOT(slotUpdatePointP(double,bool))); + connect(m_h1X, SIGNAL(valueChanged(double,bool)), this, SLOT(slotUpdatePointH1(double,bool))); + connect(m_h1Y, SIGNAL(valueChanged(double,bool)), this, SLOT(slotUpdatePointH1(double,bool))); + connect(m_h2X, SIGNAL(valueChanged(double,bool)), this, SLOT(slotUpdatePointH2(double,bool))); + connect(m_h2Y, SIGNAL(valueChanged(double,bool)), this, SLOT(slotUpdatePointH2(double,bool))); + + connect(m_ui.buttonLinkHandles, SIGNAL(toggled(bool)), this, SLOT(slotSetHandlesLinked(bool))); + connect(m_ui.buttonZoomIn, SIGNAL(clicked()), &m_edit, SLOT(slotZoomIn())); + connect(m_ui.buttonZoomOut, SIGNAL(clicked()), &m_edit, SLOT(slotZoomOut())); + connect(m_ui.buttonGridChange, SIGNAL(clicked()), this, SLOT(slotGridChange())); + connect(m_ui.buttonShowPixmap, SIGNAL(toggled(bool)), this, SLOT(slotShowPixmap(bool))); + connect(m_ui.buttonResetSpline, SIGNAL(clicked()), this, SLOT(slotResetSpline())); + connect(m_ui.buttonShowAllHandles, SIGNAL(toggled(bool)), this, SLOT(slotShowAllHandles(bool))); + + m_edit.setGridLines(KdenliveSettings::bezier_gridlines()); + m_ui.buttonShowPixmap->setChecked(KdenliveSettings::bezier_showpixmap()); + slotShowPixmap(m_ui.buttonShowPixmap->isChecked()); + m_ui.buttonShowAllHandles->setChecked(KdenliveSettings::bezier_showallhandles()); } -void BezierSplineWidget::setSpline(const CubicBezierSpline& spline) +QString BezierSplineWidget::spline() const { - // TODO: cleanup - m_spline.fromString(spline.toString()); + return m_edit.spline().toString(); } -void BezierSplineWidget::paintEvent(QPaintEvent* event) +void BezierSplineWidget::setMode(BezierSplineWidget::CurveModes mode) { - Q_UNUSED(event); - - QPainter p(this); - - p.fillRect(rect(), palette().background()); - - int wWidth = width() - 1; - int wHeight = height() - 1; - - /* - * Spline - */ - double prevY = wHeight - m_spline.value(0.) * wHeight; - double prevX = 0.; - double curY; - double normalizedX = -1; - int x; - - p.setPen(QPen(Qt::black, 1, Qt::SolidLine)); - for (x = 0 ; x < wWidth ; ++x) { - normalizedX = x / (double)wWidth; - curY = wHeight - m_spline.value(normalizedX, true) * wHeight; - - /* - * Keep in mind that QLineF rounds doubles - * to ints mathematically, not just rounds down - * like in C - */ - p.drawLine(QLineF(prevX, prevY, - x, curY)); - prevX = x; - prevY = curY; - } - p.drawLine(QLineF(prevX, prevY , - x, wHeight - m_spline.value(1.0, true) * wHeight)); - - /* - * Points + Handles - */ - p.setPen(QPen(Qt::red, 1, Qt::SolidLine)); - BPoint point; - QPolygon handle(4); - handle.setPoints(4, - 1, -2, - 4, 1, - 1, 4, - -2, 1); - for (int i = 0; i < m_spline.points().count(); ++i) { - point = m_spline.points().at(i); - if (i == m_currentPointIndex) - p.setBrush(QBrush(QColor(Qt::red), Qt::SolidPattern)); - - p.drawConvexPolygon(handle.translated(point.h1.x() * wWidth, wHeight - point.h1.y() * wHeight)); - p.drawEllipse(QRectF(point.p.x() * wWidth - 3, - wHeight - 3 - point.p.y() * wHeight, 6, 6)); - p.drawConvexPolygon(handle.translated(point.h2.x() * wWidth, wHeight - point.h2.y() * wHeight)); - - if ( i == m_currentPointIndex) - p.setBrush(QBrush(Qt::NoBrush)); + if (m_mode != mode) { + m_mode = mode; + if (m_showPixmap) + slotShowPixmap(); } } -void BezierSplineWidget::resizeEvent(QResizeEvent* event) +void BezierSplineWidget::slotGridChange() { - m_spline.setPrecision(width()); - QWidget::resizeEvent(event); + m_edit.setGridLines((m_edit.gridLines() + 1) % 9); + KdenliveSettings::setBezier_gridlines(m_edit.gridLines()); } -void BezierSplineWidget::mousePressEvent(QMouseEvent* event) +void BezierSplineWidget::slotShowPixmap(bool show) { - double x = event->pos().x() / (double)(width() - 1); - double y = 1.0 - event->pos().y() / (double)(height() - 1); - - point_types selectedPoint; - int closestPointIndex = nearestPointInRange(QPointF(x, y), width(), height(), &selectedPoint); - - if (event->button() == Qt::RightButton && closestPointIndex > 0 && closestPointIndex < m_spline.points().count() - 1 && selectedPoint == PTypeP) { - m_spline.removePoint(closestPointIndex); - setCursor(Qt::ArrowCursor); - m_mode = ModeNormal; - if (closestPointIndex < m_currentPointIndex) - --m_currentPointIndex; - update(); - emit modified(); - return; - } else if (event->button() != Qt::LeftButton) { - return; + if (m_showPixmap != show) { + m_showPixmap = show; + KdenliveSettings::setBezier_showpixmap(show); + if (show && (int)m_mode < 6) + m_edit.setPixmap(QPixmap::fromImage(ColorTools::rgbCurvePlane(m_edit.size(), (ColorTools::ColorsRGB)((int)m_mode), 1, palette().background().color().rgb()))); + else if (show && m_mode == ModeHue) + m_edit.setPixmap(QPixmap::fromImage(ColorTools::hsvCurvePlane(m_edit.size(), QColor::fromHsv(200, 200, 200), ColorTools::COM_H, ColorTools::COM_H))); + else + m_edit.setPixmap(QPixmap()); } +} - if (closestPointIndex < 0) { - BPoint po; - po.p = QPointF(x, y); - po.h1 = QPointF(x-0.05, y-0.05); - po.h2 = QPointF(x+0.05, y+0.05); - m_currentPointIndex = m_spline.addPoint(po); - m_currentPointType = PTypeP; - /*if (!d->jumpOverExistingPoints(newPoint, -1)) return;*/ +void BezierSplineWidget::slotUpdatePointEntries(const BPoint &p) +{ + blockSignals(true); + if (p == BPoint()) { + m_ui.widgetPoint->setEnabled(false); } else { - m_currentPointIndex = closestPointIndex; - m_currentPointType = selectedPoint; + m_ui.widgetPoint->setEnabled(true); + m_pX->blockSignals(true); + m_pY->blockSignals(true); + m_h1X->blockSignals(true); + m_h1Y->blockSignals(true); + m_h2X->blockSignals(true); + m_h2Y->blockSignals(true); + m_pX->setValue(p.p.x()); + m_pY->setValue(p.p.y()); + m_h1X->setValue(p.h1.x()); + m_h1Y->setValue(p.h1.y()); + m_h2X->setValue(p.h2.x()); + m_h2Y->setValue(p.h2.y()); + m_pX->blockSignals(false); + m_pY->blockSignals(false); + m_h1X->blockSignals(false); + m_h1Y->blockSignals(false); + m_h2X->blockSignals(false); + m_h2Y->blockSignals(false); + m_ui.buttonLinkHandles->setChecked(p.handlesLinked); } + blockSignals(false); +} - BPoint point = m_spline.points()[m_currentPointIndex]; - QPointF p; - switch (m_currentPointType) { - case PTypeH1: - p = point.h1; - break; - case PTypeP: - p = point.p; - break; - case PTypeH2: - p = point.h2; - } +void BezierSplineWidget::slotUpdatePointP(double value, bool final) +{ + Q_UNUSED(value) - m_grabOriginalX = p.x(); - m_grabOriginalY = p.y(); - m_grabOffsetX = p.x() - x; - m_grabOffsetY = p.y() - y; - - switch (m_currentPointType) { - case PTypeH1: - point.h1 = QPointF(x + m_grabOffsetX, y + m_grabOffsetY); - break; - case PTypeP: - point.p = QPointF(x + m_grabOffsetX, y + m_grabOffsetY); - break; - case PTypeH2: - point.h2 = QPointF(x + m_grabOffsetX, y + m_grabOffsetY); - } - m_spline.setPoint(m_currentPointIndex, point); - - //d->m_draggedAwayPointIndex = -1; + BPoint p = m_edit.getCurrentPoint(); - m_mode = ModeDrag; + p.setP(QPointF(m_pX->value(), m_pY->value())); - update(); + m_edit.updateCurrentPoint(p, final); } -void BezierSplineWidget::mouseReleaseEvent(QMouseEvent* event) +void BezierSplineWidget::slotUpdatePointH1(double value, bool final) { - if (event->button() != Qt::LeftButton) - return; + Q_UNUSED(value) - setCursor(Qt::ArrowCursor); - m_mode = ModeNormal; - - emit modified(); + BPoint p = m_edit.getCurrentPoint(); + + p.setH1(QPointF(m_h1X->value(), m_h1Y->value())); + + m_edit.updateCurrentPoint(p, final); } -void BezierSplineWidget::mouseMoveEvent(QMouseEvent* event) +void BezierSplineWidget::slotUpdatePointH2(double value, bool final) { - double x = event->pos().x() / (double)(width() - 1); - double y = 1.0 - event->pos().y() / (double)(height() - 1); - - if (m_mode == ModeNormal) { // If no point is selected set the the cursor shape if on top - point_types type; - int nearestPointIndex = nearestPointInRange(QPointF(x, y), width(), height(), &type); - - if (nearestPointIndex < 0) - setCursor(Qt::ArrowCursor); - else - setCursor(Qt::CrossCursor); - } else { // Else, drag the selected point - /*bool crossedHoriz = event->pos().x() - width() > MOUSE_AWAY_THRES || - event->pos().x() < -MOUSE_AWAY_THRES; - bool crossedVert = event->pos().y() - height() > MOUSE_AWAY_THRES || - event->pos().y() < -MOUSE_AWAY_THRES; - - bool removePoint = (crossedHoriz || crossedVert); - - if (!removePoint && d->m_draggedAwayPointIndex >= 0) { - // point is no longer dragged away so reinsert it - QPointF newPoint(d->m_draggedAwayPoint); - d->m_grab_point_index = d->m_curve.addPoint(newPoint); - d->m_draggedAwayPointIndex = -1; - } - - if (removePoint && - (d->m_draggedAwayPointIndex >= 0)) - return; - */ - - setCursor(Qt::CrossCursor); - - x += m_grabOffsetX; - y += m_grabOffsetY; - - double leftX, rightX; - BPoint point = m_spline.points()[m_currentPointIndex]; - switch (m_currentPointType) { - case PTypeH1: - rightX = point.p.x(); - if (m_currentPointIndex == 0) - leftX = -1000; - else - leftX = m_spline.points()[m_currentPointIndex - 1].p.x(); - x = qBound(leftX, x, rightX); - point.h1 = QPointF(x, y); - break; - case PTypeP: - if (m_currentPointIndex == 0) { - leftX = 0.0; - rightX = 0.0; - /*if (d->m_curve.points().count() > 1) - * rightX = d->m_curve.points()[d->m_grab_point_index + 1].x() - POINT_AREA; - * else - * rightX = 1.0;*/ - } else if (m_currentPointIndex == m_spline.points().count() - 1) { - leftX = 1.0;//m_spline.points()[m_currentPointIndex - 1].p.x(); - rightX = 1.0; - } else { - //// the 1E-4 addition so we can grab the dot later. - leftX = m_spline.points()[m_currentPointIndex - 1].p.x();// + POINT_AREA; - rightX = m_spline.points()[m_currentPointIndex + 1].p.x();// - POINT_AREA; - } - x = qBound(leftX, x, rightX); - y = qBound(0., y, 1.); - point.p = QPointF(x, y); - break; - case PTypeH2: - leftX = point.p.x(); - if (m_currentPointIndex == m_spline.points().count() - 1) - rightX = 1001; - else - rightX = m_spline.points()[m_currentPointIndex + 1].p.x(); - x = qBound(leftX, x, rightX); - point.h2 = QPointF(x, y); - }; - - m_spline.setPoint(m_currentPointIndex, point); - - /*if (removePoint && d->m_curve.points().count() > 2) { - d->m_draggedAwayPoint = d->m_curve.points()[d->m_grab_point_index]; - d->m_draggedAwayPointIndex = d->m_grab_point_index; - d->m_curve.removePoint(d->m_grab_point_index); - d->m_grab_point_index = bounds(d->m_grab_point_index, 0, d->m_curve.points().count() - 1); - } - - d->setCurveModified();*/ - update(); - } + Q_UNUSED(value) + + BPoint p = m_edit.getCurrentPoint(); + + p.setH2(QPointF(m_h2X->value(), m_h2Y->value())); + + m_edit.updateCurrentPoint(p, final); } -void BezierSplineWidget::leaveEvent(QEvent* event) +void BezierSplineWidget::slotSetHandlesLinked(bool linked) { - QWidget::leaveEvent(event); + BPoint p = m_edit.getCurrentPoint(); + p.handlesLinked = linked; + m_edit.updateCurrentPoint(p); } -int BezierSplineWidget::nearestPointInRange(QPointF p, int wWidth, int wHeight, BezierSplineWidget::point_types* sel) +void BezierSplineWidget::slotResetSpline() { - double nearestDistanceSquared = 1000; - point_types selectedPoint; - int nearestIndex = -1; - int i = 0; - - double distanceSquared; - foreach(const BPoint & point, m_spline.points()) { - distanceSquared = pow(point.h1.x() - p.x(), 2) + pow(point.h1.y() - p.y(), 2); - if (distanceSquared < nearestDistanceSquared) { - nearestIndex = i; - nearestDistanceSquared = distanceSquared; - selectedPoint = PTypeH1; - } - distanceSquared = pow(point.p.x() - p.x(), 2) + pow(point.p.y() - p.y(), 2); - if (distanceSquared < nearestDistanceSquared) { - nearestIndex = i; - nearestDistanceSquared = distanceSquared; - selectedPoint = PTypeP; - } - distanceSquared = pow(point.h2.x() - p.x(), 2) + pow(point.h2.y() - p.y(), 2); - if (distanceSquared < nearestDistanceSquared) { - nearestIndex = i; - nearestDistanceSquared = distanceSquared; - selectedPoint = PTypeH2; - } - ++i; - } - - if (nearestIndex >= 0) { - BPoint point = m_spline.points()[nearestIndex]; - QPointF p2; - switch (selectedPoint) { - case PTypeH1: - p2 = point.h1; - break; - case PTypeP: - p2 = point.p; - break; - case PTypeH2: - p2 = point.h2; - } - if (qAbs(p.x() - p2.x()) * (wWidth - 1) < 5 && qAbs(p.y() - p2.y()) * (wHeight - 1) < 5) { - *sel = selectedPoint; - return nearestIndex; - } - } + m_edit.setSpline(CubicBezierSpline()); +} - return -1; +void BezierSplineWidget::slotShowAllHandles(bool show) +{ + m_edit.setShowAllHandles(show); + KdenliveSettings::setBezier_showallhandles(show); } #include "beziersplinewidget.moc"