File indexing completed on 2024-04-28 04:52:23

0001 /*
0002     SPDX-FileCopyrightText: 2010 Simon Andreas Eugster <simon.eu@gmail.com>
0003     This file is part of kdenlive. See www.kdenlive.org.
0004 
0005 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006 */
0007 
0008 #include "waveform.h"
0009 #include "waveformgenerator.h"
0010 // For reading out the project resolution
0011 #include "core.h"
0012 #include "profiles/profilemodel.hpp"
0013 
0014 #include "klocalizedstring.h"
0015 #include <KConfigGroup>
0016 #include <KSharedConfig>
0017 #include <QActionGroup>
0018 #include <QElapsedTimer>
0019 #include <QPainter>
0020 #include <QPoint>
0021 
0022 const QSize Waveform::m_textWidth(35, 0);
0023 const int Waveform::m_paddingBottom(20);
0024 
0025 Waveform::Waveform(QWidget *parent)
0026     : AbstractGfxScopeWidget(true, parent)
0027 
0028 {
0029     m_ui = new Ui::Waveform_UI();
0030     m_ui->setupUi(this);
0031 
0032     m_ui->paintMode->addItem(i18n("Yellow"), QVariant(WaveformGenerator::PaintMode_Yellow));
0033     m_ui->paintMode->addItem(i18n("White"), QVariant(WaveformGenerator::PaintMode_White));
0034     m_ui->paintMode->addItem(i18n("Green"), QVariant(WaveformGenerator::PaintMode_Green));
0035 
0036     m_aRec601 = new QAction(i18n("Rec. 601"), this);
0037     m_aRec601->setCheckable(true);
0038     m_aRec709 = new QAction(i18n("Rec. 709"), this);
0039     m_aRec709->setCheckable(true);
0040     m_agRec = new QActionGroup(this);
0041     m_agRec->addAction(m_aRec601);
0042     m_agRec->addAction(m_aRec709);
0043     m_menu->addSeparator()->setText(i18n("Luma mode"));
0044     m_menu->addAction(m_aRec601);
0045     m_menu->addAction(m_aRec709);
0046 
0047     connect(m_ui->paintMode, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &Waveform::forceUpdateScope);
0048     connect(this, &Waveform::signalMousePositionChanged, this, &Waveform::forceUpdateHUD);
0049     connect(m_aRec601, &QAction::toggled, this, &Waveform::forceUpdateScope);
0050     connect(m_aRec709, &QAction::toggled, this, &Waveform::forceUpdateScope);
0051 
0052     init();
0053     m_waveformGenerator = new WaveformGenerator();
0054 }
0055 
0056 Waveform::~Waveform()
0057 {
0058     writeConfig();
0059 
0060     delete m_waveformGenerator;
0061     delete m_aRec601;
0062     delete m_aRec709;
0063     delete m_agRec;
0064     delete m_ui;
0065 }
0066 
0067 void Waveform::readConfig()
0068 {
0069     AbstractGfxScopeWidget::readConfig();
0070 
0071     KSharedConfigPtr config = KSharedConfig::openConfig();
0072     KConfigGroup scopeConfig(config, configName());
0073     m_ui->paintMode->setCurrentIndex(scopeConfig.readEntry("paintmode", 0));
0074     m_aRec601->setChecked(scopeConfig.readEntry("rec601", false));
0075     m_aRec709->setChecked(!m_aRec601->isChecked());
0076 }
0077 
0078 void Waveform::writeConfig()
0079 {
0080     KSharedConfigPtr config = KSharedConfig::openConfig();
0081     KConfigGroup scopeConfig(config, configName());
0082     scopeConfig.writeEntry("paintmode", m_ui->paintMode->currentIndex());
0083     scopeConfig.writeEntry("rec601", m_aRec601->isChecked());
0084     scopeConfig.sync();
0085 }
0086 
0087 QRect Waveform::scopeRect()
0088 {
0089     // Distance from top/left/right
0090     int border = 6;
0091     QPoint topleft(border, m_ui->verticalSpacer->geometry().y() + border);
0092 
0093     return QRect(topleft, this->size() - QSize(border + topleft.x(), border + topleft.y()));
0094 }
0095 
0096 ///// Implemented methods /////
0097 
0098 QString Waveform::widgetName() const
0099 {
0100     return QStringLiteral("Waveform");
0101 }
0102 bool Waveform::isHUDDependingOnInput() const
0103 {
0104     return false;
0105 }
0106 bool Waveform::isScopeDependingOnInput() const
0107 {
0108     return true;
0109 }
0110 bool Waveform::isBackgroundDependingOnInput() const
0111 {
0112     return false;
0113 }
0114 
0115 QImage Waveform::renderHUD(uint)
0116 {
0117     QImage hud(m_scopeRect.size(), QImage::Format_ARGB32);
0118     hud.fill(qRgba(0, 0, 0, 0));
0119 
0120     QPainter davinci;
0121     bool ok = davinci.begin(&hud);
0122     if (!ok) {
0123         qDebug() << "Could not initialise QPainter for Waveform HUD.";
0124         return hud;
0125     }
0126     davinci.setPen(penLight);
0127 
0128     //    qCDebug(KDENLIVE_LOG) << values.value("width");
0129 
0130     const int rightX = scopeRect().width() - m_textWidth.width() + 3;
0131     const int x = m_mousePos.x() - scopeRect().x();
0132     const int y = m_mousePos.y() - scopeRect().y();
0133 
0134     if (scopeRect().height() > 0 && m_mouseWithinWidget) {
0135         int val = 255 - (255 * y) / scopeRect().height();
0136 
0137         if (val >= 0 && val <= 255) {
0138             // Draw a horizontal line through the current mouse position
0139             // and show the value of the waveform there
0140             davinci.drawLine(0, y, scopeRect().size().width() - m_textWidth.width(), y);
0141 
0142             // Make the value stick to the line unless it is at the top/bottom of the scope
0143             int valY = y + 5;
0144             const int top = 30;
0145             const int bottom = 20;
0146             if (valY < top) {
0147                 valY = top;
0148             } else if (valY > scopeRect().height() - bottom) {
0149                 valY = scopeRect().height() - bottom;
0150             }
0151             davinci.drawText(rightX, valY, QVariant(val).toString());
0152         }
0153 
0154         if (scopeRect().width() > 0) {
0155             // Draw a vertical line and the x position of the source clip
0156             const int profileWidth = pCore->getCurrentProfile()->width();
0157 
0158             const int clipX = (x * (profileWidth - 1)) / (scopeRect().width() - m_textWidth.width() - 1);
0159 
0160             if (clipX >= 0 && clipX <= profileWidth) {
0161                 int valX = x - 15;
0162                 if (valX < 0) {
0163                     valX = 0;
0164                 }
0165                 if (valX > scopeRect().width() - 55 - m_textWidth.width()) {
0166                     valX = scopeRect().width() - 55 - m_textWidth.width();
0167                 }
0168 
0169                 davinci.drawLine(x, y, x, scopeRect().height() - m_paddingBottom);
0170                 davinci.drawText(valX, scopeRect().height() - 5, QVariant(clipX).toString() + QStringLiteral(" px"));
0171             }
0172         }
0173     }
0174     davinci.drawText(rightX, scopeRect().height() - m_paddingBottom, QStringLiteral("0"));
0175     davinci.drawText(rightX, 10, QStringLiteral("255"));
0176 
0177     Q_EMIT signalHUDRenderingFinished(0, 1);
0178     return hud;
0179 }
0180 
0181 QImage Waveform::renderGfxScope(uint accelFactor, const QImage &qimage)
0182 {
0183     QElapsedTimer timer;
0184     timer.start();
0185 
0186     const int paintmode = m_ui->paintMode->itemData(m_ui->paintMode->currentIndex()).toInt();
0187     ITURec rec = m_aRec601->isChecked() ? ITURec::Rec_601 : ITURec::Rec_709;
0188     QImage wave = m_waveformGenerator->calculateWaveform(scopeRect().size() - m_textWidth - QSize(0, m_paddingBottom), qimage,
0189                                                          WaveformGenerator::PaintMode(paintmode), true, rec, accelFactor);
0190 
0191     Q_EMIT signalScopeRenderingFinished(uint(timer.elapsed()), 1);
0192     return wave;
0193 }
0194 
0195 QImage Waveform::renderBackground(uint)
0196 {
0197     Q_EMIT signalBackgroundRenderingFinished(0, 1);
0198     return QImage();
0199 }