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); } }