widgets/audiospectrum_ui.ui
widgets/spectrogram_ui.ui
widgets/smconfig_ui.ui
+ widgets/bezierspline_ui.ui
)
set(kdenlive_SRCS
kiss_fft/kiss_fft.c
kiss_fft/tools/kiss_fftr.c
beziercurve/cubicbezierspline.cpp
+ beziercurve/beziersplineeditor.cpp
beziercurve/beziersplinewidget.cpp
)
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2010 by Till Theato (root@ttill.de) *
+ * This file is part of Kdenlive (www.kdenlive.org). *
+ * *
+ * Kdenlive is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * Kdenlive is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with Kdenlive. If not, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#include "beziersplineeditor.h"
+
+#include <QPainter>
+#include <QMouseEvent>
+
+#include <KDebug>
+
+BezierSplineEditor::BezierSplineEditor(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 BezierSplineEditor::spline()
+{
+ return m_spline;
+}
+
+void BezierSplineEditor::setSpline(const CubicBezierSpline& spline)
+{
+ // TODO: cleanup
+ m_spline.fromString(spline.toString());
+}
+
+BPoint BezierSplineEditor::getCurrentPoint()
+{
+ if (m_currentPointIndex >= 0)
+ return m_spline.points()[m_currentPointIndex];
+ else
+ return BPoint();
+}
+
+void BezierSplineEditor::updateCurrentPoint(const BPoint& p)
+{
+ if (m_currentPointIndex >= 0) {
+ m_spline.setPoint(m_currentPointIndex, p);
+ // during validation the point might have changed
+ emit currentPoint(m_spline.points()[m_currentPointIndex]);
+ update();
+ }
+}
+
+void BezierSplineEditor::paintEvent(QPaintEvent* event)
+{
+ 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));
+ }
+}
+
+void BezierSplineEditor::resizeEvent(QResizeEvent* event)
+{
+ m_spline.setPrecision(width());
+ QWidget::resizeEvent(event);
+}
+
+void BezierSplineEditor::mousePressEvent(QMouseEvent* event)
+{
+ 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();
+ if (m_currentPointIndex >= 0)
+ emit currentPoint(m_spline.points()[m_currentPointIndex]);
+ else
+ emit currentPoint(BPoint());
+ emit modified();
+ return;
+ } else if (event->button() != Qt::LeftButton) {
+ return;
+ }
+
+ 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;*/
+ } else {
+ m_currentPointIndex = closestPointIndex;
+ m_currentPointType = selectedPoint;
+ }
+
+ 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;
+ }
+
+ 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;
+
+ m_mode = ModeDrag;
+
+ emit currentPoint(point);
+ update();
+}
+
+void BezierSplineEditor::mouseReleaseEvent(QMouseEvent* event)
+{
+ if (event->button() != Qt::LeftButton)
+ return;
+
+ setCursor(Qt::ArrowCursor);
+ m_mode = ModeNormal;
+
+ emit modified();
+}
+
+void BezierSplineEditor::mouseMoveEvent(QMouseEvent* event)
+{
+ 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.);
+
+ // move handles by same offset
+ point.h1 += QPointF(x, y) - point.p;
+ point.h2 += QPointF(x, y) - point.p;
+
+ 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();*/
+ emit currentPoint(point);
+ update();
+ }
+}
+
+void BezierSplineEditor::leaveEvent(QEvent* event)
+{
+ QWidget::leaveEvent(event);
+}
+
+int BezierSplineEditor::nearestPointInRange(QPointF p, int wWidth, int wHeight, BezierSplineEditor::point_types* sel)
+{
+ 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;
+ }
+ }
+
+ return -1;
+}
+
+#include "beziersplineeditor.moc"
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2010 by Till Theato (root@ttill.de) *
+ * This file is part of Kdenlive (www.kdenlive.org). *
+ * *
+ * Kdenlive is free software: you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation, either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * Kdenlive is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with Kdenlive. If not, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifndef BEZIERSPLINEEDITOR_H
+#define BEZIERSPLINEEDITOR_H
+
+#include "cubicbezierspline.h"
+
+#include <QtCore>
+#include <QWidget>
+
+class BezierSplineEditor : public QWidget
+{
+ Q_OBJECT
+
+public:
+ BezierSplineEditor(QWidget* parent = 0);
+
+ CubicBezierSpline spline();
+ void setSpline(const CubicBezierSpline &spline);
+
+ BPoint getCurrentPoint();
+ void updateCurrentPoint(const BPoint &p);
+
+protected:
+ //void keyPressEvent(QKeyEvent *event);
+ void paintEvent(QPaintEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent * event);
+ void mouseMoveEvent(QMouseEvent * event);
+ void leaveEvent(QEvent *event);
+ void resizeEvent(QResizeEvent *event);
+
+private:
+ CubicBezierSpline m_spline;
+ enum modes { ModeDrag, ModeNormal };
+ enum point_types { PTypeH1, PTypeP, PTypeH2 };
+ modes m_mode;
+ int m_currentPointIndex;
+ point_types m_currentPointType;
+ double m_grabOffsetX;
+ double m_grabOffsetY;
+ double m_grabOriginalX;
+ double m_grabOriginalY;
+ //QPointF m_draggedAwayPoint;
+ //int m_draggedAwayPointIndex;
+
+ //inline void drawGrid(QPainter &p, int width, int height);
+ int nearestPointInRange(QPointF p, int wWidth, int wHeight, point_types *sel);
+
+signals:
+ void modified();
+ void currentPoint(const BPoint &p);
+};
+
+#endif
#include "beziersplinewidget.h"
-#include <QPainter>
-#include <QMouseEvent>
+#include <QVBoxLayout>
-#include <KDebug>
+#include <KIcon>
-BezierSplineWidget::BezierSplineWidget(QWidget* parent) :
- QWidget(parent),
- m_mode(ModeNormal),
- m_currentPointIndex(-1)
+BezierSplineWidget::BezierSplineWidget(const QString& spline, QWidget* parent) :
+ QWidget(parent)
{
- setMouseTracking(true);
- setAutoFillBackground(false);
- setAttribute(Qt::WA_OpaquePaintEvent);
- setMinimumSize(150, 150);
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ 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("insert-link"));
+ m_ui.buttonLinkHandles->setEnabled(false);
+ m_ui.widgetPoint->setEnabled(false);
+
+ CubicBezierSpline s;
+ s.fromString(spline);
+ m_edit.setSpline(s);
+
+ connect(&m_edit, SIGNAL(modified()), this, SIGNAL(modified()));
+ connect(&m_edit, SIGNAL(currentPoint(const BPoint&)), this, SLOT(slotUpdatePoint(const BPoint&)));
+
+ connect(m_ui.spinPX, SIGNAL(editingFinished()), this, SLOT(slotUpdateSpline()));
+ connect(m_ui.spinPY, SIGNAL(editingFinished()), this, SLOT(slotUpdateSpline()));
+ connect(m_ui.spinH1X, SIGNAL(editingFinished()), this, SLOT(slotUpdateSpline()));
+ connect(m_ui.spinH1Y, SIGNAL(editingFinished()), this, SLOT(slotUpdateSpline()));
+ connect(m_ui.spinH2X, SIGNAL(editingFinished()), this, SLOT(slotUpdateSpline()));
+ connect(m_ui.spinH2Y, SIGNAL(editingFinished()), this, SLOT(slotUpdateSpline()));
}
-CubicBezierSpline BezierSplineWidget::spline()
+QString BezierSplineWidget::spline()
{
- return m_spline;
+ return m_edit.spline().toString();
}
-void BezierSplineWidget::setSpline(const CubicBezierSpline& spline)
+void BezierSplineWidget::slotUpdatePoint(const BPoint &p)
{
- // TODO: cleanup
- m_spline.fromString(spline.toString());
-}
-
-void BezierSplineWidget::paintEvent(QPaintEvent* event)
-{
- 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));
- }
-}
-
-void BezierSplineWidget::resizeEvent(QResizeEvent* event)
-{
- m_spline.setPrecision(width());
- QWidget::resizeEvent(event);
-}
-
-void BezierSplineWidget::mousePressEvent(QMouseEvent* event)
-{
- 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 (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;*/
+ blockSignals(true);
+ if (p == BPoint()) {
+ m_ui.widgetPoint->setEnabled(false);
} else {
- m_currentPointIndex = closestPointIndex;
- m_currentPointType = selectedPoint;
- }
-
- 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;
+ m_ui.widgetPoint->setEnabled(true);
+ m_ui.spinPX->setValue(qRound(p.p.x() * 255));
+ m_ui.spinPY->setValue(qRound(p.p.y() * 255));
+ m_ui.spinH1X->setValue(qRound(p.h1.x() * 255));
+ m_ui.spinH1Y->setValue(qRound(p.h1.y() * 255));
+ m_ui.spinH2X->setValue(qRound(p.h2.x() * 255));
+ m_ui.spinH2Y->setValue(qRound(p.h2.y() * 255));
}
-
- 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;
-
- m_mode = ModeDrag;
-
- update();
+ blockSignals(false);
}
-void BezierSplineWidget::mouseReleaseEvent(QMouseEvent* event)
+void BezierSplineWidget::slotUpdateSpline()
{
- if (event->button() != Qt::LeftButton)
- return;
+ BPoint p = m_edit.getCurrentPoint();
- setCursor(Qt::ArrowCursor);
- m_mode = ModeNormal;
-
- emit modified();
-}
-
-void BezierSplineWidget::mouseMoveEvent(QMouseEvent* event)
-{
- 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.);
+ // check for every value, so we do not lose too much info through rounding
+ if (m_ui.spinPX->value() != qRound(p.p.x() * 255))
+ p.p.setX(m_ui.spinPX->value() / 255.);
+ if (m_ui.spinPY->value() != qRound(p.p.y() * 255))
+ p.p.setY(m_ui.spinPY->value() / 255.);
- // move handles by same offset
- point.h1 += QPointF(x, y) - point.p;
- point.h2 += QPointF(x, y) - point.p;
+ if (m_ui.spinH1X->value() != qRound(p.h1.x() * 255))
+ p.h1.setX(m_ui.spinH1X->value() / 255.);
+ if (m_ui.spinH1Y->value() != qRound(p.h1.y() * 255))
+ p.h1.setY(m_ui.spinH1Y->value() / 255.);
- 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);
- };
+ if (m_ui.spinH2X->value() != qRound(p.h2.x() * 255))
+ p.h2.setX(m_ui.spinH2X->value() / 255.);
+ if (m_ui.spinH2Y->value() != qRound(p.h2.y() * 255))
+ p.h2.setY(m_ui.spinH2Y->value() / 255.);
- 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();
- }
-}
-
-void BezierSplineWidget::leaveEvent(QEvent* event)
-{
- QWidget::leaveEvent(event);
-}
-
-int BezierSplineWidget::nearestPointInRange(QPointF p, int wWidth, int wHeight, BezierSplineWidget::point_types* sel)
-{
- 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;
- }
- }
-
- return -1;
+ m_edit.updateCurrentPoint(p);
+ emit modified();
}
#include "beziersplinewidget.moc"
#define BEZIERSPLINEWIDGET_H
#include "cubicbezierspline.h"
+#include "beziersplineeditor.h"
+#include "ui_bezierspline_ui.h"
#include <QtCore>
#include <QWidget>
class BezierSplineWidget : public QWidget
{
Q_OBJECT
-
+
public:
- BezierSplineWidget(QWidget* parent = 0);
+ BezierSplineWidget(const QString &spline, QWidget* parent = 0);
- CubicBezierSpline spline();
- void setSpline(const CubicBezierSpline &spline);
+ QString spline();
-protected:
- //void keyPressEvent(QKeyEvent *event);
- void paintEvent(QPaintEvent *event);
- void mousePressEvent(QMouseEvent *event);
- void mouseReleaseEvent(QMouseEvent * event);
- void mouseMoveEvent(QMouseEvent * event);
- void leaveEvent(QEvent *event);
- void resizeEvent(QResizeEvent *event);
+private slots:
+ void slotUpdatePoint(const BPoint &p);
+ void slotUpdateSpline();
private:
- CubicBezierSpline m_spline;
- enum modes { ModeDrag, ModeNormal };
- enum point_types { PTypeH1, PTypeP, PTypeH2 };
- modes m_mode;
- int m_currentPointIndex;
- point_types m_currentPointType;
- double m_grabOffsetX;
- double m_grabOffsetY;
- double m_grabOriginalX;
- double m_grabOriginalY;
- //QPointF m_draggedAwayPoint;
- //int m_draggedAwayPointIndex;
-
- //inline void drawGrid(QPainter &p, int width, int height);
- int nearestPointInRange(QPointF p, int wWidth, int wHeight, point_types *sel);
+ Ui::BezierSpline_UI m_ui;
+ BezierSplineEditor m_edit;
signals:
void modified();
QPointF p; // point
QPointF h2; // handle 2
+ BPoint() { p = QPointF(-1,-1); } // makes it illegal -> cannot be equal any point
bool operator==(const BPoint &point) const { return point.h1 == h1 && point.p == p && point.h2 == h2; }
};
#include "doubleparameterwidget.h"
#include "cornerswidget.h"
#include "beziercurve/beziersplinewidget.h"
-#include "beziercurve/cubicbezierspline.h"
#include <KDebug>
#include <KLocale>
if (!depends.isEmpty())
meetDependency(paramName, type, EffectsList::parameter(e, depends));
} else if (type == "bezier_spline") {
- BezierSplineWidget *widget = new BezierSplineWidget(this);
- CubicBezierSpline spline;
- spline.fromString(value);
- widget->setSpline(spline);
+ BezierSplineWidget *widget = new BezierSplineWidget(value, this);
stretch = false;
m_vbox->addWidget(widget);
m_valueItems[paramName] = widget;
meetDependency(paramName, type, EffectsList::parameter(newparam, depends));
} else if (type == "bezier_spline") {
BezierSplineWidget *widget = (BezierSplineWidget*)m_valueItems.value(paramName);
- setValue = widget->spline().toString();
+ setValue = widget->spline();
} else if (type == "corners") {
CornersWidget *corners = ((CornersWidget*)m_valueItems.value(paramName));
QString xName = pa.attributes().namedItem("xpoints").nodeValue();
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>BezierSpline_UI</class>
+ <widget class="QWidget" name="BezierSpline_UI">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>471</width>
+ <height>84</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="1" column="5">
+ <widget class="QWidget" name="widgetPoint" native="true">
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0" colspan="9">
+ <widget class="QWidget" name="widget" native="true">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="spinPX">
+ <property name="toolTip">
+ <string>Point In</string>
+ </property>
+ <property name="maximum">
+ <number>255</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Point</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QSpinBox" name="spinPY">
+ <property name="toolTip">
+ <string>Point Out</string>
+ </property>
+ <property name="maximum">
+ <number>255</number>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QSpinBox" name="spinH1X">
+ <property name="toolTip">
+ <string>Handle 1 X</string>
+ </property>
+ <property name="minimum">
+ <number>-100</number>
+ </property>
+ <property name="maximum">
+ <number>400</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLabel" name="label_2">
+ <property name="toolTip">
+ <string>Handle 1</string>
+ </property>
+ <property name="text">
+ <string>H1</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QSpinBox" name="spinH1Y">
+ <property name="toolTip">
+ <string>Handle 1 Y</string>
+ </property>
+ <property name="minimum">
+ <number>-100</number>
+ </property>
+ <property name="maximum">
+ <number>400</number>
+ </property>
+ <property name="value">
+ <number>0</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="3">
+ <spacer name="horizontalSpacer_3">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="4">
+ <widget class="QToolButton" name="buttonLinkHandles">
+ <property name="toolTip">
+ <string>Link the Handles' position so you draw a line through Handle -> Point -> Handle.<br />Results in a natural spline.</string>
+ </property>
+ <property name="text">
+ <string>...</string>
+ </property>
+ <property name="checkable">
+ <bool>true</bool>
+ </property>
+ <property name="autoRaise">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="5">
+ <spacer name="horizontalSpacer_4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="6">
+ <widget class="QSpinBox" name="spinH2X">
+ <property name="toolTip">
+ <string>Handle 2 X</string>
+ </property>
+ <property name="minimum">
+ <number>-100</number>
+ </property>
+ <property name="maximum">
+ <number>400</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="7">
+ <widget class="QLabel" name="label_3">
+ <property name="toolTip">
+ <string>Handle 2</string>
+ </property>
+ <property name="text">
+ <string>H2</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="8">
+ <widget class="QSpinBox" name="spinH2Y">
+ <property name="toolTip">
+ <string>Handle 2 Y</string>
+ </property>
+ <property name="minimum">
+ <number>-100</number>
+ </property>
+ <property name="maximum">
+ <number>400</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>