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 }