File indexing completed on 2024-04-21 04:52:24

0001 /*
0002 SPDX-FileCopyrightText: 2016 Jean-Baptiste Mardelle <jb@kdenlive.org>
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 "gradientwidget.h"
0009 
0010 #include <QLinearGradient>
0011 #include <QPainter>
0012 #include <QPainterPath>
0013 #include <QPixmap>
0014 #include <QtMath>
0015 
0016 #include <KConfigGroup>
0017 #include <KSharedConfig>
0018 
0019 GradientWidget::GradientWidget(const QMap<QString, QString> &gradients, int ix, QWidget *parent)
0020     : QDialog(parent)
0021     , Ui::GradientEdit_UI()
0022 {
0023     setupUi(this);
0024     updatePreview();
0025     connect(color1_pos, &QAbstractSlider::valueChanged, this, &GradientWidget::updatePreview);
0026     connect(color2_pos, &QAbstractSlider::valueChanged, this, &GradientWidget::updatePreview);
0027     connect(angle, &QAbstractSlider::valueChanged, this, &GradientWidget::updatePreview);
0028     connect(color1, &KColorButton::changed, this, &GradientWidget::updatePreview);
0029     connect(color2, &KColorButton::changed, this, &GradientWidget::updatePreview);
0030     connect(add_gradient, SIGNAL(clicked()), this, SLOT(saveGradient()));
0031     connect(remove_gradient, &QAbstractButton::clicked, this, &GradientWidget::deleteGradient);
0032     QFontMetrics metrics(font());
0033     m_height = metrics.lineSpacing();
0034     gradient_list->setIconSize(QSize(6 * m_height, m_height));
0035     connect(gradient_list, &QListWidget::currentRowChanged, this, &GradientWidget::loadGradient);
0036     loadGradients(gradients);
0037     gradient_list->setCurrentRow(ix);
0038 }
0039 
0040 void GradientWidget::resizeEvent(QResizeEvent *event)
0041 {
0042     QDialog::resizeEvent(event);
0043     updatePreview();
0044 }
0045 
0046 QString GradientWidget::gradientToString() const
0047 {
0048     QStringList result;
0049     result << color1->color().name(QColor::HexArgb) << color2->color().name(QColor::HexArgb) << QString::number(color1_pos->value())
0050            << QString::number(color2_pos->value()) << QString::number(angle->value());
0051     return result.join(QLatin1Char(';'));
0052 }
0053 
0054 QLinearGradient GradientWidget::gradientFromString(const QString &str, int width, int height)
0055 {
0056     QStringList values = str.split(QLatin1Char(';'));
0057     QLinearGradient gr;
0058     if (values.count() < 5) {
0059         // invalid gradient data
0060         return gr;
0061     }
0062     gr.setColorAt(values.at(2).toDouble() / 100, values.at(0));
0063     gr.setColorAt(values.at(3).toDouble() / 100, values.at(1));
0064     double angle = values.at(4).toDouble();
0065     if (angle <= 90) {
0066         gr.setStart(0, 0);
0067         gr.setFinalStop(width * qCos(qDegreesToRadians(angle)), height * qSin(qDegreesToRadians(angle)));
0068     } else {
0069         gr.setStart(width, 0);
0070         gr.setFinalStop(width + width * qCos(qDegreesToRadians(angle)), height * qSin(qDegreesToRadians(angle)));
0071     }
0072     return gr;
0073 }
0074 
0075 void GradientWidget::updatePreview()
0076 {
0077     QPixmap p(preview->width(), preview->height());
0078     m_gradient = QLinearGradient();
0079     m_gradient.setColorAt(color1_pos->value() / 100.0, color1->color());
0080     m_gradient.setColorAt(color2_pos->value() / 100.0, color2->color());
0081     double ang = angle->value();
0082     if (ang <= 90) {
0083         m_gradient.setStart(0, 0);
0084         m_gradient.setFinalStop(p.width() / 2 * qCos(qDegreesToRadians(ang)), p.height() * qSin(qDegreesToRadians(ang)));
0085     } else {
0086         m_gradient.setStart(p.width() / 2, 0);
0087         m_gradient.setFinalStop(p.width() / 2 + (p.width() / 2) * qCos(qDegreesToRadians(ang)), p.height() * qSin(qDegreesToRadians(ang)));
0088     }
0089     // qCDebug(KDENLIVE_LOG)<<"* * * ANGLE: "<<angle->value()<<" = "<<p.height() * tan(angle->value() * 3.1415926 / 180.0);
0090 
0091     QLinearGradient copy = m_gradient;
0092     QPointF gradStart = m_gradient.start() + QPointF(p.width() / 2, 0);
0093     QPointF gradStop = m_gradient.finalStop() + QPointF(p.width() / 2, 0);
0094     copy.setStart(gradStart);
0095     copy.setFinalStop(gradStop);
0096     QBrush br(m_gradient);
0097     QBrush br2(copy);
0098     p.fill(Qt::transparent);
0099     QPainter painter(&p);
0100     painter.fillRect(0, 0, p.width() / 2, p.height(), br);
0101     QPainterPath path;
0102     QFont f = font();
0103     f.setPixelSize(p.height());
0104     int margin = p.height() / 8;
0105     path.addText(p.width() / 2 + 2 * margin, p.height() - margin, f, QStringLiteral("Ax"));
0106     painter.fillPath(path, br2);
0107     painter.end();
0108     preview->setPixmap(p);
0109     // save changes to currently active gradient
0110     QListWidgetItem *current = gradient_list->currentItem();
0111     if (!current) {
0112         return;
0113     }
0114     saveGradient(current->text());
0115 }
0116 
0117 int GradientWidget::selectedGradient() const
0118 {
0119     return gradient_list->currentRow();
0120 }
0121 
0122 void GradientWidget::saveGradient(const QString &name)
0123 {
0124     QPixmap pix(6 * m_height, m_height);
0125     pix.fill(Qt::transparent);
0126     m_gradient.setStart(0, pix.height() / 2);
0127     m_gradient.setFinalStop(pix.width(), pix.height() / 2);
0128     QPainter painter(&pix);
0129     painter.fillRect(0, 0, pix.width(), pix.height(), QBrush(m_gradient));
0130     painter.end();
0131     QIcon icon(pix);
0132     QListWidgetItem *item = nullptr;
0133     if (!name.isEmpty()) {
0134         item = gradient_list->currentItem();
0135         item->setIcon(icon);
0136     } else {
0137         // Create new gradient
0138         int ct = gradient_list->count();
0139         QStringList existing = getNames();
0140         QString test = i18n("Gradient %1", ct);
0141         while (existing.contains(test)) {
0142             ct++;
0143             test = i18n("Gradient %1", ct);
0144         }
0145         item = new QListWidgetItem(icon, test, gradient_list);
0146         item->setFlags(Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled);
0147     }
0148     item->setData(Qt::UserRole, gradientToString());
0149 }
0150 
0151 QStringList GradientWidget::getNames() const
0152 {
0153     QStringList result;
0154     result.reserve(gradient_list->count());
0155     for (int i = 0; i < gradient_list->count(); i++) {
0156         result << gradient_list->item(i)->text();
0157     }
0158     return result;
0159 }
0160 
0161 void GradientWidget::deleteGradient()
0162 {
0163     QListWidgetItem *item = gradient_list->currentItem();
0164     delete item;
0165 }
0166 
0167 void GradientWidget::loadGradient()
0168 {
0169     QListWidgetItem *item = gradient_list->currentItem();
0170     if (!item) {
0171         return;
0172     }
0173     QString grad_data = item->data(Qt::UserRole).toString();
0174     QStringList res = grad_data.split(QLatin1Char(';'));
0175     color1->setColor(QColor(res.at(0)));
0176     color2->setColor(QColor(res.at(1)));
0177     color1_pos->setValue(res.at(2).toInt());
0178     color2_pos->setValue(res.at(3).toInt());
0179     angle->setValue(res.at(4).toInt());
0180 }
0181 
0182 QMap<QString, QString> GradientWidget::gradients() const
0183 {
0184     QMap<QString, QString> gradients;
0185     for (int i = 0; i < gradient_list->count(); i++) {
0186         gradients.insert(gradient_list->item(i)->text(), gradient_list->item(i)->data(Qt::UserRole).toString());
0187     }
0188     return gradients;
0189 }
0190 
0191 QList<QIcon> GradientWidget::icons() const
0192 {
0193     QList<QIcon> icons;
0194     icons.reserve(gradient_list->count());
0195     for (int i = 0; i < gradient_list->count(); i++) {
0196         QPixmap pix = gradient_list->item(i)->icon().pixmap(6 * m_height, m_height);
0197         QIcon icon(pix.scaled(30, 30));
0198         icons << icon;
0199     }
0200     return icons;
0201 }
0202 
0203 void GradientWidget::loadGradients(QMap<QString, QString> gradients)
0204 {
0205     gradient_list->clear();
0206     if (gradients.isEmpty()) {
0207         KSharedConfigPtr config = KSharedConfig::openConfig();
0208         KConfigGroup group(config, "TitleGradients");
0209         gradients = group.entryMap();
0210     }
0211     QMapIterator<QString, QString> k(gradients);
0212     while (k.hasNext()) {
0213         k.next();
0214         QPixmap pix(6 * m_height, m_height);
0215         pix.fill(Qt::transparent);
0216         QLinearGradient gr = gradientFromString(k.value(), pix.width(), pix.height());
0217         gr.setStart(0, pix.height() / 2);
0218         gr.setFinalStop(pix.width(), pix.height() / 2);
0219         QPainter painter(&pix);
0220         painter.fillRect(0, 0, pix.width(), pix.height(), QBrush(gr));
0221         painter.end();
0222         QIcon icon(pix);
0223         auto *item = new QListWidgetItem(icon, k.key(), gradient_list);
0224         item->setData(Qt::UserRole, k.value());
0225         item->setFlags(Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled);
0226     }
0227 }