diff --git a/src/assets/view/widgets/curves/bezier/beziersplineeditor.cpp b/src/assets/view/widgets/curves/bezier/beziersplineeditor.cpp
index 91641c60c..cea14bc9f 100644
--- a/src/assets/view/widgets/curves/bezier/beziersplineeditor.cpp
+++ b/src/assets/view/widgets/curves/bezier/beziersplineeditor.cpp
@@ -1,320 +1,321 @@
/***************************************************************************
* Copyright (C) 2010 by Till Theato (root@ttill.de) *
* This file is part of Kdenlive (www.kdenlive.org). *
* *
* Kdenlive is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 2 of the License, or *
* (at your option) any later version. *
* *
* Kdenlive is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with Kdenlive. If not, see . *
***************************************************************************/
#include "beziersplineeditor.h"
#include "cubicbezierspline.h"
#include "kdenlivesettings.h"
#include "complex"
#include
#include
+#include
BezierSplineEditor::BezierSplineEditor(QWidget *parent)
: AbstractCurveWidget(parent)
{
m_curve = CubicBezierSpline();
}
BezierSplineEditor::~BezierSplineEditor() = default;
void BezierSplineEditor::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter p(this);
paintBackground(&p);
/*
* Prepare Spline, Points
*/
int max = m_curve.count() - 1;
if (max < 1) {
return;
}
BPoint point(m_curve.getPoint(0, m_wWidth, m_wHeight, true));
/*
* Spline
*/
BPoint next;
QPainterPath splinePath(QPointF(point.p.x(), point.p.y()));
for (int i = 0; i < max; ++i) {
point = m_curve.getPoint(i, m_wWidth, m_wHeight, true);
next = m_curve.getPoint(i + 1, m_wWidth, m_wHeight, true);
splinePath.cubicTo(point.h2, next.h1, next.p);
}
p.setPen(QPen(palette().text().color(), 1, Qt::SolidLine));
p.drawPath(splinePath);
/*
* Points + Handles
*/
p.setPen(QPen(Qt::red, 1, Qt::SolidLine));
QPolygonF handle = QPolygonF() << QPointF(0, -3) << QPointF(3, 0) << QPointF(0, 3) << QPointF(-3, 0);
for (int i = 0; i <= max; ++i) {
point = m_curve.getPoint(i, m_wWidth, m_wHeight, true);
if (i == m_currentPointIndex) {
// selected point: fill p and handles
p.setBrush(QBrush(QColor(Qt::red), Qt::SolidPattern));
// connect p and handles with lines
if (i != 0) {
p.drawLine(QLineF(point.h1.x(), point.h1.y(), point.p.x(), point.p.y()));
}
if (i != max) {
p.drawLine(QLineF(point.p.x(), point.p.y(), point.h2.x(), point.h2.y()));
}
}
p.drawEllipse(QRectF(point.p.x() - 3, point.p.y() - 3, 6, 6));
if (i != 0 && (i == m_currentPointIndex || m_showAllHandles)) {
p.drawConvexPolygon(handle.translated(point.h1.x(), point.h1.y()));
}
if (i != max && (i == m_currentPointIndex || m_showAllHandles)) {
p.drawConvexPolygon(handle.translated(point.h2.x(), point.h2.y()));
}
if (i == m_currentPointIndex) {
p.setBrush(QBrush(Qt::NoBrush));
}
}
}
void BezierSplineEditor::mousePressEvent(QMouseEvent *event)
{
int wWidth = width() - 1;
int wHeight = height() - 1;
int offsetX = 1 / 8. * m_zoomLevel * wWidth;
int offsetY = 1 / 8. * m_zoomLevel * wHeight;
wWidth -= 2 * offsetX;
wHeight -= 2 * offsetY;
double x = (event->pos().x() - offsetX) / (double)(wWidth);
double y = 1.0 - (event->pos().y() - offsetY) / (double)(wHeight);
BPoint::PointType selectedPoint;
int closestPointIndex = nearestPointInRange(QPointF(x, y), wWidth, wHeight, &selectedPoint);
if (event->button() == Qt::RightButton && closestPointIndex > 0 && closestPointIndex < m_curve.count() - 1 && selectedPoint == BPoint::PointType::P) {
m_currentPointIndex = closestPointIndex;
slotDeleteCurrentPoint();
return;
}
if (event->button() != Qt::LeftButton) {
return;
}
if (closestPointIndex < 0) {
if (m_curve.count() < m_maxPoints) {
m_currentPointIndex = m_curve.addPoint(QPointF(x, y));
m_currentPointType = BPoint::PointType::P;
}
} else {
m_currentPointIndex = closestPointIndex;
m_currentPointType = selectedPoint;
}
BPoint point = m_curve.getPoint(m_currentPointIndex);
m_grabPOriginal = point;
if (m_currentPointIndex > 0) {
m_grabPPrevious = m_curve.getPoint(m_currentPointIndex - 1);
}
if (m_currentPointIndex < m_curve.count() - 1) {
m_grabPNext = m_curve.getPoint(m_currentPointIndex + 1);
}
m_grabOffsetX = point[(int)m_currentPointType].x() - x;
m_grabOffsetY = point[(int)m_currentPointType].y() - y;
point[(int)m_currentPointType] = QPointF(x + m_grabOffsetX, y + m_grabOffsetY);
m_curve.setPoint(m_currentPointIndex, point);
m_state = State_t::DRAG;
emit currentPoint(point, isCurrentPointExtremal());
emit modified();
update();
}
void BezierSplineEditor::mouseMoveEvent(QMouseEvent *event)
{
int wWidth = width() - 1;
int wHeight = height() - 1;
int offsetX = 1 / 8. * m_zoomLevel * wWidth;
int offsetY = 1 / 8. * m_zoomLevel * wHeight;
wWidth -= 2 * offsetX;
wHeight -= 2 * offsetY;
double x = (event->pos().x() - offsetX) / (double)(wWidth);
double y = 1.0 - (event->pos().y() - offsetY) / (double)(wHeight);
if (m_state == State_t::NORMAL) {
// If no point is selected set the cursor shape if on top
BPoint::PointType type;
int nearestPointIndex = nearestPointInRange(QPointF(x, y), wWidth, wHeight, &type);
if (nearestPointIndex < 0) {
setCursor(Qt::ArrowCursor);
} else {
setCursor(Qt::CrossCursor);
}
} else {
// Else, drag the selected point
setCursor(Qt::CrossCursor);
x += m_grabOffsetX;
y += m_grabOffsetY;
double leftX = 0.;
double rightX = 1.;
BPoint point = m_curve.getPoint(m_currentPointIndex);
switch (m_currentPointType) {
case BPoint::PointType::H1:
rightX = point.p.x();
if (m_currentPointIndex == 0) {
leftX = -4;
} else {
leftX = m_curve.getPoint(m_currentPointIndex - 1).p.x();
}
x = qBound(leftX, x, rightX);
point.setH1(QPointF(x, y));
break;
case BPoint::PointType::P:
if (m_currentPointIndex == 0) {
rightX = 0.0;
} else if (m_currentPointIndex == m_curve.count() - 1) {
leftX = 1.0;
}
x = qBound(leftX, x, rightX);
y = qBound(0., y, 1.);
// handles might have changed because we neared another point
// try to restore
point.h1 = m_grabPOriginal.h1;
point.h2 = m_grabPOriginal.h2;
// and move by same offset
// (using update handle in point.setP won't work because the offset between new and old point is very small)
point.h1 += QPointF(x, y) - m_grabPOriginal.p;
point.h2 += QPointF(x, y) - m_grabPOriginal.p;
point.setP(QPointF(x, y), false);
break;
case BPoint::PointType::H2:
leftX = point.p.x();
if (m_currentPointIndex == m_curve.count() - 1) {
rightX = 5;
} else {
rightX = m_curve.getPoint(m_currentPointIndex + 1).p.x();
}
x = qBound(leftX, x, rightX);
point.setH2(QPointF(x, y));
};
int index = m_currentPointIndex;
m_currentPointIndex = m_curve.setPoint(m_currentPointIndex, point);
if (m_currentPointType == BPoint::PointType::P) {
// we might have changed the handles of other points
// try to restore
if (index == m_currentPointIndex) {
if (m_currentPointIndex > 0) {
m_curve.setPoint(m_currentPointIndex - 1, m_grabPPrevious);
}
if (m_currentPointIndex < m_curve.count() - 1) {
m_curve.setPoint(m_currentPointIndex + 1, m_grabPNext);
}
} else {
if (m_currentPointIndex < index) {
m_curve.setPoint(index, m_grabPPrevious);
m_grabPNext = m_grabPPrevious;
if (m_currentPointIndex > 0) {
m_grabPPrevious = m_curve.getPoint(m_currentPointIndex - 1);
}
} else {
m_curve.setPoint(index, m_grabPNext);
m_grabPPrevious = m_grabPNext;
if (m_currentPointIndex < m_curve.count() - 1) {
m_grabPNext = m_curve.getPoint(m_currentPointIndex + 1);
}
}
}
}
emit currentPoint(point, isCurrentPointExtremal());
if (KdenliveSettings::dragvalue_directupdate()) {
emit modified();
}
update();
}
}
void BezierSplineEditor::mouseDoubleClickEvent(QMouseEvent * /*event*/)
{
if (m_currentPointIndex >= 0) {
BPoint p = m_curve.getPoint(m_currentPointIndex);
p.handlesLinked = !p.handlesLinked;
m_curve.setPoint(m_currentPointIndex, p);
emit currentPoint(p, isCurrentPointExtremal());
}
}
int BezierSplineEditor::nearestPointInRange(const QPointF &p, int wWidth, int wHeight, BPoint::PointType *sel)
{
auto nearest = m_curve.closestPoint(p);
int nearestIndex = nearest.first;
BPoint::PointType pointType = nearest.second;
if (nearestIndex >= 0 && (nearestIndex == m_currentPointIndex || pointType == BPoint::PointType::P || m_showAllHandles)) {
// a point was found and it is not a hidden handle
BPoint point = m_curve.getPoint(nearestIndex);
double dx = (p.x() - point[(int)pointType].x()) * wWidth;
double dy = (p.y() - point[(int)pointType].y()) * wHeight;
if (dx * dx + dy * dy <= m_grabRadius * m_grabRadius) {
*sel = pointType;
return nearestIndex;
}
}
return -1;
}
void BezierSplineEditor::setShowAllHandles(bool show)
{
if (m_showAllHandles != show) {
m_showAllHandles = show;
update();
}
}
QList BezierSplineEditor::getPoints() const
{
return m_curve.getPoints();
}
diff --git a/src/bin/abstractprojectitem.cpp b/src/bin/abstractprojectitem.cpp
index f37591be3..e36ab5d3a 100644
--- a/src/bin/abstractprojectitem.cpp
+++ b/src/bin/abstractprojectitem.cpp
@@ -1,333 +1,334 @@
/*
Copyright (C) 2012 Till Theato
Copyright (C) 2014 Jean-Baptiste Mardelle
This file is part of Kdenlive. See www.kdenlive.org.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License or (at your option) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor approved
by the membership of KDE e.V.), which shall act as a proxy
defined in Section 14 of version 3 of the license.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "abstractprojectitem.h"
#include "bin.h"
#include "core.h"
#include "jobs/jobmanager.h"
#include "macros.hpp"
#include "projectitemmodel.h"
#include "jobs/audiothumbjob.hpp"
#include "jobs/loadjob.hpp"
#include "jobs/thumbjob.hpp"
#include
+#include
#include
#include
AbstractProjectItem::AbstractProjectItem(PROJECTITEMTYPE type, QString id, const std::shared_ptr &model, bool isRoot)
: TreeItem(QList(), std::static_pointer_cast(model), isRoot)
, m_name()
, m_description()
, m_thumbnail(QIcon())
, m_date()
, m_binId(std::move(id))
, m_usage(0)
, m_rating(0)
, m_clipStatus(StatusReady)
, m_itemType(type)
, m_lock(QReadWriteLock::Recursive)
, m_isCurrent(false)
{
Q_ASSERT(!isRoot || type == FolderItem);
}
bool AbstractProjectItem::operator==(const std::shared_ptr &projectItem) const
{
// FIXME: only works for folders
bool equal = this->m_childItems == projectItem->m_childItems;
// equal = equal && (m_parentItem == projectItem->m_parentItem);
return equal;
}
std::shared_ptr AbstractProjectItem::parent() const
{
return std::static_pointer_cast(m_parentItem.lock());
}
void AbstractProjectItem::setRefCount(uint count)
{
m_usage = count;
if (auto ptr = m_model.lock())
std::static_pointer_cast(ptr)->onItemUpdated(std::static_pointer_cast(shared_from_this()),
AbstractProjectItem::UsageCount);
}
uint AbstractProjectItem::refCount() const
{
return m_usage;
}
void AbstractProjectItem::addRef()
{
m_usage++;
if (auto ptr = m_model.lock())
std::static_pointer_cast(ptr)->onItemUpdated(std::static_pointer_cast(shared_from_this()),
AbstractProjectItem::UsageCount);
}
void AbstractProjectItem::removeRef()
{
m_usage--;
if (auto ptr = m_model.lock())
std::static_pointer_cast(ptr)->onItemUpdated(std::static_pointer_cast(shared_from_this()),
AbstractProjectItem::UsageCount);
}
const QString &AbstractProjectItem::clipId() const
{
return m_binId;
}
QPixmap AbstractProjectItem::roundedPixmap(const QPixmap &source)
{
QPixmap pix(source.size());
pix.fill(Qt::transparent);
QPainter p(&pix);
p.setRenderHint(QPainter::Antialiasing, true);
QPainterPath path;
path.addRoundedRect(0.5, 0.5, pix.width() - 1, pix.height() - 1, 4, 4);
p.setClipPath(path);
p.drawPixmap(0, 0, source);
p.end();
return pix;
}
AbstractProjectItem::PROJECTITEMTYPE AbstractProjectItem::itemType() const
{
return m_itemType;
}
QVariant AbstractProjectItem::getData(DataType type) const
{
QVariant data;
switch (type) {
case DataName:
data = QVariant(m_name);
break;
case DataDescription:
data = QVariant(m_description);
break;
case DataThumbnail:
data = QVariant(m_thumbnail);
break;
case DataId:
data = QVariant(m_binId);
break;
case DataDuration:
data = QVariant(m_duration);
break;
case ParentDuration:
data = QVariant(m_parentDuration);
break;
case DataInPoint:
data = QVariant(m_inPoint);
break;
case DataOutPoint:
data = QVariant(m_outPoint);
break;
case DataDate:
data = QVariant(m_date);
break;
case UsageCount:
data = QVariant(m_usage);
break;
case ItemTypeRole:
data = QVariant(m_itemType);
break;
case ClipType:
data = clipType();
break;
case DataTag:
data = QVariant(m_tags);
break;
case DataRating:
data = QVariant(m_rating);
break;
case ClipHasAudioAndVideo:
data = hasAudioAndVideo();
break;
case JobType:
if (itemType() == ClipItem) {
auto jobIds = pCore->jobManager()->getPendingJobsIds(clipId());
if (jobIds.empty()) {
jobIds = pCore->jobManager()->getFinishedJobsIds(clipId());
}
if (jobIds.size() > 0) {
data = QVariant(pCore->jobManager()->getJobType(jobIds[0]));
}
}
break;
case JobStatus:
if (itemType() == ClipItem) {
auto jobIds = pCore->jobManager()->getPendingJobsIds(clipId());
if (jobIds.empty()) {
jobIds = pCore->jobManager()->getFinishedJobsIds(clipId());
}
if (jobIds.size() > 0) {
data = QVariant::fromValue(pCore->jobManager()->getJobStatus(jobIds[0]));
} else {
data = QVariant::fromValue(JobManagerStatus::NoJob);
}
}
break;
case JobProgress:
if (itemType() == ClipItem) {
auto jobIds = pCore->jobManager()->getPendingJobsIds(clipId());
if (jobIds.size() > 0) {
data = QVariant(pCore->jobManager()->getJobProgressForClip(jobIds[0], clipId()));
} else {
data = QVariant(0);
}
}
break;
case JobSuccess:
if (itemType() == ClipItem) {
auto jobIds = pCore->jobManager()->getFinishedJobsIds(clipId());
if (jobIds.size() > 0) {
// Check the last job status
data = QVariant(pCore->jobManager()->jobSucceded(jobIds[jobIds.size() - 1]));
} else {
data = QVariant(true);
}
}
break;
case ClipStatus:
data = QVariant(m_clipStatus);
break;
case ClipToolTip:
data = QVariant(getToolTip());
break;
default:
break;
}
return data;
}
int AbstractProjectItem::supportedDataCount() const
{
return 8;
}
QString AbstractProjectItem::name() const
{
return m_name;
}
void AbstractProjectItem::setName(const QString &name)
{
m_name = name;
}
QString AbstractProjectItem::description() const
{
return m_description;
}
void AbstractProjectItem::setDescription(const QString &description)
{
m_description = description;
}
QPoint AbstractProjectItem::zone() const
{
return {};
}
void AbstractProjectItem::setClipStatus(CLIPSTATUS status)
{
m_clipStatus = status;
}
bool AbstractProjectItem::statusReady() const
{
return m_clipStatus == StatusReady;
}
AbstractProjectItem::CLIPSTATUS AbstractProjectItem::clipStatus() const
{
return m_clipStatus;
}
std::shared_ptr AbstractProjectItem::getEnclosingFolder(bool strict)
{
if (!strict && itemType() == AbstractProjectItem::FolderItem) {
return std::static_pointer_cast(shared_from_this());
}
if (auto ptr = m_parentItem.lock()) {
return std::static_pointer_cast(ptr)->getEnclosingFolder(false);
}
return std::shared_ptr();
}
bool AbstractProjectItem::selfSoftDelete(Fun &undo, Fun &redo)
{
pCore->jobManager()->slotDiscardClipJobs(clipId());
Fun local_undo = []() { return true; };
Fun local_redo = []() { return true; };
for (const auto &child : m_childItems) {
bool res = std::static_pointer_cast(child)->selfSoftDelete(local_undo, local_redo);
if (!res) {
bool undone = local_undo();
Q_ASSERT(undone);
return false;
}
}
UPDATE_UNDO_REDO(local_redo, local_undo, undo, redo);
return true;
}
QString AbstractProjectItem::lastParentId() const
{
return m_lastParentId;
}
void AbstractProjectItem::updateParent(std::shared_ptr newParent)
{
// bool reload = !m_lastParentId.isEmpty();
m_lastParentId.clear();
if (newParent) {
m_lastParentId = std::static_pointer_cast(newParent)->clipId();
}
TreeItem::updateParent(newParent);
}
const QString & AbstractProjectItem::tags() const
{
return m_tags;
}
void AbstractProjectItem::setTags(const QString tags)
{
m_tags = tags;
}
uint AbstractProjectItem::rating() const
{
return m_rating;
}
void AbstractProjectItem::setRating(uint rating)
{
m_rating = rating;
}
diff --git a/src/titler/gradientwidget.cpp b/src/titler/gradientwidget.cpp
index 6ad1e8373..a259f5fad 100644
--- a/src/titler/gradientwidget.cpp
+++ b/src/titler/gradientwidget.cpp
@@ -1,242 +1,243 @@
/*
Copyright (C) 2016 Jean-Baptiste Mardelle
This file is part of Kdenlive. See www.kdenlive.org.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of
the License or (at your option) version 3 or any later version
accepted by the membership of KDE e.V. (or its successor approved
by the membership of KDE e.V.), which shall act as a proxy
defined in Section 14 of version 3 of the license.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "gradientwidget.h"
#include
#include
+#include
#include
#include
#include
#include
GradientWidget::GradientWidget(const QMap &gradients, int ix, QWidget *parent)
: QDialog(parent)
, Ui::GradientEdit_UI()
{
setupUi(this);
updatePreview();
connect(color1_pos, &QAbstractSlider::valueChanged, this, &GradientWidget::updatePreview);
connect(color2_pos, &QAbstractSlider::valueChanged, this, &GradientWidget::updatePreview);
connect(angle, &QAbstractSlider::valueChanged, this, &GradientWidget::updatePreview);
connect(color1, &KColorButton::changed, this, &GradientWidget::updatePreview);
connect(color2, &KColorButton::changed, this, &GradientWidget::updatePreview);
add_gradient->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
remove_gradient->setIcon(QIcon::fromTheme(QStringLiteral("list-remove")));
connect(add_gradient, SIGNAL(clicked()), this, SLOT(saveGradient()));
connect(remove_gradient, &QAbstractButton::clicked, this, &GradientWidget::deleteGradient);
QFontMetrics metrics(font());
m_height = metrics.lineSpacing();
gradient_list->setIconSize(QSize(6 * m_height, m_height));
connect(gradient_list, &QListWidget::currentRowChanged, this, &GradientWidget::loadGradient);
loadGradients(gradients);
gradient_list->setCurrentRow(ix);
}
void GradientWidget::resizeEvent(QResizeEvent *event)
{
QDialog::resizeEvent(event);
updatePreview();
}
QString GradientWidget::gradientToString() const
{
QStringList result;
result << color1->color().name(QColor::HexArgb) << color2->color().name(QColor::HexArgb) << QString::number(color1_pos->value())
<< QString::number(color2_pos->value()) << QString::number(angle->value());
return result.join(QLatin1Char(';'));
}
QLinearGradient GradientWidget::gradientFromString(const QString &str, int width, int height)
{
QStringList values = str.split(QLatin1Char(';'));
QLinearGradient gr;
if (values.count() < 5) {
// invalid gradient data
return gr;
}
gr.setColorAt(values.at(2).toDouble() / 100, values.at(0));
gr.setColorAt(values.at(3).toDouble() / 100, values.at(1));
double angle = values.at(4).toDouble();
if (angle <= 90) {
gr.setStart(0, 0);
gr.setFinalStop(width * qCos(qDegreesToRadians(angle)), height * qSin(qDegreesToRadians(angle)));
} else {
gr.setStart(width, 0);
gr.setFinalStop(width + width * qCos(qDegreesToRadians(angle)), height * qSin(qDegreesToRadians(angle)));
}
return gr;
}
void GradientWidget::updatePreview()
{
QPixmap p(preview->width(), preview->height());
m_gradient = QLinearGradient();
m_gradient.setColorAt(color1_pos->value() / 100.0, color1->color());
m_gradient.setColorAt(color2_pos->value() / 100.0, color2->color());
double ang = angle->value();
if (ang <= 90) {
m_gradient.setStart(0, 0);
m_gradient.setFinalStop(p.width() / 2 * qCos(qDegreesToRadians(ang)), p.height() * qSin(qDegreesToRadians(ang)));
} else {
m_gradient.setStart(p.width() / 2, 0);
m_gradient.setFinalStop(p.width() / 2 + (p.width() / 2) * qCos(qDegreesToRadians(ang)), p.height() * qSin(qDegreesToRadians(ang)));
}
// qCDebug(KDENLIVE_LOG)<<"* * * ANGLE: "<value()<<" = "<value() * 3.1415926 / 180.0);
QLinearGradient copy = m_gradient;
QPointF gradStart = m_gradient.start() + QPointF(p.width() / 2, 0);
QPointF gradStop = m_gradient.finalStop() + QPointF(p.width() / 2, 0);
copy.setStart(gradStart);
copy.setFinalStop(gradStop);
QBrush br(m_gradient);
QBrush br2(copy);
p.fill(Qt::transparent);
QPainter painter(&p);
painter.fillRect(0, 0, p.width() / 2, p.height(), br);
QPainterPath path;
QFont f = font();
f.setPixelSize(p.height());
int margin = p.height() / 8;
path.addText(p.width() / 2 + 2 * margin, p.height() - margin, f, QStringLiteral("Ax"));
painter.fillPath(path, br2);
painter.end();
preview->setPixmap(p);
// save changes to currently active gradient
QListWidgetItem *current = gradient_list->currentItem();
if (!current) {
return;
}
saveGradient(current->text());
}
int GradientWidget::selectedGradient() const
{
return gradient_list->currentRow();
}
void GradientWidget::saveGradient(const QString &name)
{
QPixmap pix(6 * m_height, m_height);
pix.fill(Qt::transparent);
m_gradient.setStart(0, pix.height() / 2);
m_gradient.setFinalStop(pix.width(), pix.height() / 2);
QPainter painter(&pix);
painter.fillRect(0, 0, pix.width(), pix.height(), QBrush(m_gradient));
painter.end();
QIcon icon(pix);
QListWidgetItem *item = nullptr;
if (!name.isEmpty()) {
item = gradient_list->currentItem();
item->setIcon(icon);
} else {
// Create new gradient
int ct = gradient_list->count();
QStringList existing = getNames();
QString test = i18n("Gradient %1", ct);
while (existing.contains(test)) {
ct++;
test = i18n("Gradient %1", ct);
}
item = new QListWidgetItem(icon, test, gradient_list);
item->setFlags(Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled);
}
item->setData(Qt::UserRole, gradientToString());
}
QStringList GradientWidget::getNames() const
{
QStringList result;
result.reserve(gradient_list->count());
for (int i = 0; i < gradient_list->count(); i++) {
result << gradient_list->item(i)->text();
}
return result;
}
void GradientWidget::deleteGradient()
{
QListWidgetItem *item = gradient_list->currentItem();
delete item;
}
void GradientWidget::loadGradient()
{
QListWidgetItem *item = gradient_list->currentItem();
if (!item) {
return;
}
QString grad_data = item->data(Qt::UserRole).toString();
QStringList res = grad_data.split(QLatin1Char(';'));
color1->setColor(QColor(res.at(0)));
color2->setColor(QColor(res.at(1)));
color1_pos->setValue(res.at(2).toInt());
color2_pos->setValue(res.at(3).toInt());
angle->setValue(res.at(4).toInt());
}
QMap GradientWidget::gradients() const
{
QMap gradients;
for (int i = 0; i < gradient_list->count(); i++) {
gradients.insert(gradient_list->item(i)->text(), gradient_list->item(i)->data(Qt::UserRole).toString());
}
return gradients;
}
QList GradientWidget::icons() const
{
QList icons;
icons.reserve(gradient_list->count());
for (int i = 0; i < gradient_list->count(); i++) {
QPixmap pix = gradient_list->item(i)->icon().pixmap(6 * m_height, m_height);
QIcon icon(pix.scaled(30, 30));
icons << icon;
}
return icons;
}
void GradientWidget::loadGradients(QMap gradients)
{
gradient_list->clear();
if (gradients.isEmpty()) {
KSharedConfigPtr config = KSharedConfig::openConfig();
KConfigGroup group(config, "TitleGradients");
gradients = group.entryMap();
}
QMapIterator k(gradients);
while (k.hasNext()) {
k.next();
QPixmap pix(6 * m_height, m_height);
pix.fill(Qt::transparent);
QLinearGradient gr = gradientFromString(k.value(), pix.width(), pix.height());
gr.setStart(0, pix.height() / 2);
gr.setFinalStop(pix.width(), pix.height() / 2);
QPainter painter(&pix);
painter.fillRect(0, 0, pix.width(), pix.height(), QBrush(gr));
painter.end();
QIcon icon(pix);
auto *item = new QListWidgetItem(icon, k.key(), gradient_list);
item->setData(Qt::UserRole, k.value());
item->setFlags(Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsEnabled);
}
}