Warning, /multimedia/kdenlive/src/assets/view/widgets/curves/abstractcurvewidget.ipp is written in an unsupported language. File is not indexed.

0001 /*
0002  *   SPDX-FileCopyrightText: 2016 Nicolas Carion
0003  *   SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0004  */
0005 
0006 #include <QKeyEvent>
0007 #include <QMouseEvent>
0008 #include <QResizeEvent>
0009 #include <QFontInfo>
0010 
0011 template <typename Curve_t>
0012 AbstractCurveWidget<Curve_t>::AbstractCurveWidget(QWidget *parent)
0013     : __dummy_AbstractCurveWidget(parent)
0014     , m_pixmapCache(nullptr)
0015 
0016 {
0017     setMouseTracking(true);
0018     setAutoFillBackground(false);
0019     setAttribute(Qt::WA_OpaquePaintEvent);
0020     setMinimumSize(150, QFontInfo(font()).pixelSize() * 12);
0021     QSizePolicy sp(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
0022     sp.setHeightForWidth(true); // force widget to have a height dependent on width;
0023     setSizePolicy(sp);
0024     setFocusPolicy(Qt::StrongFocus);
0025 }
0026 
0027 template <typename Curve_t> void AbstractCurveWidget<Curve_t>::paintBackground(QPainter *p)
0028 {
0029     /*
0030      * Zoom
0031      */
0032     m_wWidth = width() - 1;
0033     m_wHeight = height() - 1;
0034     int offsetX = int(1 / 8. * m_zoomLevel * m_wWidth);
0035     int offsetY = int(1 / 8. * m_zoomLevel * m_wHeight);
0036     m_wWidth -= 2 * offsetX;
0037     m_wHeight -= 2 * offsetY;
0038 
0039     p->translate(offsetX, offsetY);
0040 
0041     /*
0042      * Background
0043      */
0044     p->fillRect(rect().translated(-offsetX, -offsetY), palette().window());
0045     if (!m_pixmap.isNull()) {
0046         if (m_pixmapIsDirty || !m_pixmapCache) {
0047             m_pixmapCache = std::make_shared<QPixmap>(m_wWidth + 1, m_wHeight + 1);
0048             QPainter cachePainter(m_pixmapCache.get());
0049 
0050             cachePainter.scale(1.0 * (m_wWidth + 1) / m_pixmap.width(), 1.0 * (m_wHeight + 1) / m_pixmap.height());
0051             cachePainter.drawPixmap(0, 0, m_pixmap);
0052             m_pixmapIsDirty = false;
0053         }
0054         p->drawPixmap(0, 0, *m_pixmapCache);
0055     }
0056 
0057     // select color of the grid, depending on whether we have a palette or not
0058     if (!m_pixmap.isNull()) {
0059         p->setPen(QPen(palette().mid().color(), 1, Qt::SolidLine));
0060     } else {
0061         int h, s, l, a;
0062         auto bg = palette().color(QPalette::Window);
0063         bg.getHsl(&h, &s, &l, &a);
0064         l = (l > 128) ? l - 30 : l + 30;
0065         bg.setHsl(h, s, l, a);
0066         p->setPen(QPen(bg, 1, Qt::SolidLine));
0067     }
0068 
0069     /*
0070      * Borders
0071      */
0072     p->drawRect(0, 0, m_wWidth, m_wHeight);
0073 
0074     /*
0075      * Grid
0076      */
0077     if (m_gridLines != 0) {
0078         double stepH = m_wWidth / double(m_gridLines + 1);
0079         double stepV = m_wHeight / double(m_gridLines + 1);
0080         for (int i = 1; i <= m_gridLines; ++i) {
0081             p->drawLine(QLineF(i * stepH, 0, i * stepH, m_wHeight));
0082             p->drawLine(QLineF(0, i * stepV, m_wWidth, i * stepV));
0083         }
0084     }
0085 
0086     p->setRenderHint(QPainter::Antialiasing);
0087 
0088     /*
0089      * Standard line
0090      */
0091     p->drawLine(QLineF(0, m_wHeight, m_wWidth, 0));
0092 }
0093 
0094 template <typename Curve_t> void AbstractCurveWidget<Curve_t>::setMaxPoints(int max)
0095 {
0096     Q_ASSERT(max >= 2);
0097     m_maxPoints = max;
0098 }
0099 
0100 template <typename Curve_t> void AbstractCurveWidget<Curve_t>::setPixmap(const QPixmap &pix)
0101 {
0102     m_pixmap = pix;
0103     m_pixmapIsDirty = true;
0104     update();
0105 }
0106 
0107 template <typename Curve_t> int AbstractCurveWidget<Curve_t>::gridLines() const
0108 {
0109     return m_gridLines;
0110 }
0111 
0112 template <typename Curve_t> void AbstractCurveWidget<Curve_t>::setGridLines(int lines)
0113 {
0114     m_gridLines = qBound(0, lines, 8);
0115     update();
0116 }
0117 
0118 template <typename Curve_t> void AbstractCurveWidget<Curve_t>::slotZoomIn()
0119 {
0120     m_zoomLevel = qMax(m_zoomLevel - 1, 0);
0121     m_pixmapIsDirty = true;
0122     update();
0123 }
0124 
0125 template <typename Curve_t> void AbstractCurveWidget<Curve_t>::slotZoomOut()
0126 {
0127     m_zoomLevel = qMin(m_zoomLevel + 1, 3);
0128     m_pixmapIsDirty = true;
0129     update();
0130 }
0131 
0132 template <typename Curve_t> void AbstractCurveWidget<Curve_t>::setFromString(const QString &str)
0133 {
0134     m_curve.fromString(str);
0135     m_currentPointIndex = -1;
0136     Q_EMIT currentPoint(Point_t(), true);
0137     update();
0138 }
0139 
0140 template <typename Curve_t> void AbstractCurveWidget<Curve_t>::reset()
0141 {
0142     setFromString(Curve_t().toString());
0143     m_currentPointIndex = -1;
0144     Q_EMIT currentPoint(Point_t(), true);
0145     Q_EMIT modified();
0146     update();
0147 }
0148 
0149 template <typename Curve_t> QString AbstractCurveWidget<Curve_t>::toString()
0150 {
0151     return m_curve.toString();
0152 }
0153 
0154 template <typename Curve_t> void AbstractCurveWidget<Curve_t>::updateCurrentPoint(const Point_t &p, bool final)
0155 {
0156     if (m_currentPointIndex >= 0) {
0157         m_curve.setPoint(m_currentPointIndex, p);
0158         // during validation the point might have changed
0159         Q_EMIT currentPoint(m_curve.getPoint(m_currentPointIndex), isCurrentPointExtremal());
0160         if (final) {
0161             Q_EMIT modified();
0162         }
0163         update();
0164     }
0165 }
0166 
0167 template <typename Curve_t> typename AbstractCurveWidget<Curve_t>::Point_t AbstractCurveWidget<Curve_t>::getCurrentPoint()
0168 {
0169     if (m_currentPointIndex >= 0) {
0170         return m_curve.getPoint(m_currentPointIndex);
0171     } else {
0172         return Point_t();
0173     }
0174 }
0175 
0176 template <typename Curve_t> bool AbstractCurveWidget<Curve_t>::isCurrentPointExtremal()
0177 {
0178     return m_currentPointIndex == 0 || m_currentPointIndex == m_curve.points().size() - 1;
0179 }
0180 
0181 template <typename Curve_t> void AbstractCurveWidget<Curve_t>::slotDeleteCurrentPoint()
0182 {
0183     if (m_currentPointIndex > 0 && m_currentPointIndex < m_curve.points().size() - 1) {
0184         m_curve.removePoint(m_currentPointIndex);
0185         m_currentPointIndex--;
0186         Q_EMIT currentPoint(m_curve.getPoint(m_currentPointIndex), isCurrentPointExtremal());
0187         update();
0188         Q_EMIT modified();
0189         setCursor(Qt::ArrowCursor);
0190         m_state = State_t::NORMAL;
0191     }
0192 }
0193 
0194 template <typename Curve_t> void AbstractCurveWidget<Curve_t>::resizeEvent(QResizeEvent *e)
0195 {
0196     m_pixmapIsDirty = true;
0197     QWidget::resizeEvent(e);
0198 }
0199 
0200 template <typename Curve_t> void AbstractCurveWidget<Curve_t>::leaveEvent(QEvent *event)
0201 {
0202     QWidget::leaveEvent(event);
0203 }
0204 
0205 template <typename Curve_t> void AbstractCurveWidget<Curve_t>::mouseReleaseEvent(QMouseEvent *event)
0206 {
0207     if (event->button() != Qt::LeftButton) {
0208         return;
0209     }
0210 
0211     setCursor(Qt::ArrowCursor);
0212     m_state = State_t::NORMAL;
0213 
0214     Q_EMIT modified();
0215 }
0216 
0217 template <typename Curve_t> void AbstractCurveWidget<Curve_t>::keyPressEvent(QKeyEvent *e)
0218 {
0219     if (e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace) {
0220         slotDeleteCurrentPoint();
0221     } else {
0222         QWidget::keyPressEvent(e);
0223     }
0224 }
0225 
0226 template <typename Curve_t> int AbstractCurveWidget<Curve_t>::heightForWidth(int w) const
0227 {
0228     return w;
0229 }