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 }