File indexing completed on 2024-05-12 15:26:42

0001 /***************************************************************************
0002     File                 : Segment.cpp
0003     Project              : LabPlot
0004     Description          : Graphics-item for curve of Datapicker
0005     --------------------------------------------------------------------
0006     Copyright            : (C) 2015 by Ankit Wagadre (wagadre.ankit@gmail.com)
0007  ***************************************************************************/
0008 /***************************************************************************
0009  *                                                                         *
0010  *  This program is free software; you can redistribute it and/or modify   *
0011  *  it under the terms of the GNU General Public License as published by   *
0012  *  the Free Software Foundation; either version 2 of the License, or      *
0013  *  (at your option) any later version.                                    *
0014  *                                                                         *
0015  *  This program is distributed in the hope that it will be useful,        *
0016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
0017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
0018  *  GNU General Public License for more details.                           *
0019  *                                                                         *
0020  *   You should have received a copy of the GNU General Public License     *
0021  *   along with this program; if not, write to the Free Software           *
0022  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
0023  *   Boston, MA  02110-1301  USA                                           *
0024  *                                                                         *
0025  ***************************************************************************/
0026 
0027 #include "Segment.h"
0028 #include "SegmentPrivate.h"
0029 #include "backend/datapicker/DatapickerImage.h"
0030 #include "backend/datapicker/DatapickerPoint.h"
0031 #include "backend/worksheet/Worksheet.h"
0032 #include "backend/datapicker/Datapicker.h"
0033 
0034 #include <QPainter>
0035 #include <QGraphicsScene>
0036 #include <QDesktopWidget>
0037 
0038 #include <KLocalizedString>
0039 
0040 /**
0041  * \class Segment
0042  * \brief graphics-item class for curve-segment
0043  */
0044 
0045 Segment::Segment(DatapickerImage* image) : m_image(image), d_ptr(new SegmentPrivate(this)) {
0046     m_image->scene()->addItem(this->graphicsItem());
0047 }
0048 
0049 QGraphicsItem* Segment::graphicsItem() const {
0050     return d_ptr;
0051 }
0052 
0053 void Segment::setParentGraphicsItem(QGraphicsItem* item) {
0054     Q_D(Segment);
0055     d->setParentItem(item);
0056 }
0057 
0058 void Segment::retransform() {
0059     Q_D(Segment);
0060     d->retransform();
0061 }
0062 
0063 bool Segment::isVisible() const {
0064     Q_D(const Segment);
0065     return d->isVisible();
0066 }
0067 
0068 void Segment::setVisible(bool on) {
0069     Q_D(Segment);
0070     d->setVisible(on);
0071 }
0072 
0073 //##############################################################################
0074 //####################### Private implementation ###############################
0075 //##############################################################################
0076 SegmentPrivate::SegmentPrivate(Segment *owner) :
0077     scaleFactor(Worksheet::convertToSceneUnits(1, Worksheet::Unit::Inch)/QApplication::desktop()->physicalDpiX()),
0078     q(owner) {
0079 
0080     setFlag(QGraphicsItem::ItemIsSelectable);
0081     setFlag(QGraphicsItem::ItemSendsGeometryChanges);
0082     setAcceptHoverEvents(true);
0083     setVisible(false);
0084 
0085     pen = QPen(Qt::green, 3, Qt::SolidLine);
0086 }
0087 
0088 /*!
0089     calculates the position and the bounding box of the item. Called on geometry or properties changes.
0090  */
0091 void SegmentPrivate::retransform() {
0092     QMatrix matrix;
0093     matrix.scale(scaleFactor, scaleFactor);
0094     for (auto* line : q->path) {
0095         const QLine& scaledLine = matrix.map(*line);
0096         linePath.moveTo(scaledLine.p1());
0097         linePath.lineTo(scaledLine.p2());
0098     }
0099     recalcShapeAndBoundingRect();
0100 }
0101 
0102 /*!
0103     Returns the outer bounds of the item as a rectangle.
0104  */
0105 QRectF SegmentPrivate::boundingRect() const {
0106     return boundingRectangle;
0107 }
0108 
0109 /*!
0110     Returns the shape of this item as a QPainterPath in local coordinates.
0111 */
0112 QPainterPath SegmentPrivate::shape() const {
0113     return itemShape;
0114 }
0115 
0116 /*!
0117   recalculates the outer bounds and the shape of the item.
0118 */
0119 void SegmentPrivate::recalcShapeAndBoundingRect() {
0120     prepareGeometryChange();
0121     boundingRectangle = linePath.boundingRect();
0122     itemShape = QPainterPath();
0123     itemShape.addRect(boundingRectangle);
0124 }
0125 
0126 void SegmentPrivate::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
0127     Q_UNUSED(option)
0128     Q_UNUSED(widget)
0129 
0130     painter->setPen(pen);
0131     painter->drawPath(linePath);
0132 
0133     if (m_hovered && !isSelected()) {
0134         painter->setPen(QPen(QApplication::palette().color(QPalette::Highlight), 2, Qt::SolidLine));
0135         painter->drawPath(linePath);
0136     }
0137 
0138 //  if (isSelected()) {
0139 //      painter->setPen(QPen(QApplication::palette().color(QPalette::Highlight), 2, Qt::SolidLine));
0140 //      painter->setOpacity(selectedOpacity);
0141 //      painter->drawPath(itemShape);
0142 //  }
0143 }
0144 
0145 void SegmentPrivate::hoverEnterEvent(QGraphicsSceneHoverEvent*) {
0146     if (!isSelected()) {
0147         m_hovered = true;
0148         update();
0149     }
0150 }
0151 
0152 void SegmentPrivate::hoverLeaveEvent(QGraphicsSceneHoverEvent*) {
0153     if (m_hovered) {
0154         m_hovered = false;
0155         update();
0156     }
0157 }
0158 
0159 QVariant SegmentPrivate::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) {
0160     if (change == QGraphicsItem::ItemSelectedChange && value == true) {
0161         auto* datapicker = static_cast<Datapicker*>(q->m_image->parentAspect());
0162         if (datapicker->activeCurve()) {
0163             int count = 0;
0164             QList<QPointF> posList;
0165             posList.clear();
0166             for (QLine* line : q->path) {
0167                 const int l = (line->y1() > line->y2())?line->y2():line->y1();
0168                 const int h = (line->y1() > line->y2())?line->y1():line->y2();
0169 
0170                 for (int i = l; i <= h; ++i) {
0171                     if (count%q->m_image->pointSeparation() == 0) {
0172                         bool positionUsed = false;
0173                         const auto points = datapicker->activeCurve()->children<DatapickerPoint>(AbstractAspect::ChildIndexFlag::IncludeHidden);
0174                         for (const auto* point : points) {
0175                             if (point->position() == QPoint(line->x1(), i)*scaleFactor)
0176                                 positionUsed = true;
0177                         }
0178 
0179                         if (!positionUsed)
0180                             posList<<QPoint(line->x1(), i)*scaleFactor;
0181                     }
0182                     count++;
0183                 }
0184             }
0185 
0186             if (!posList.isEmpty()) {
0187                 datapicker->activeCurve()->beginMacro(i18n("%1: draw points over segment", datapicker->activeCurve()->name()));
0188                 for (const QPointF& pos : posList)
0189                     datapicker->addNewPoint(pos, datapicker->activeCurve());
0190                 datapicker->activeCurve()->endMacro();
0191             }
0192         }
0193 
0194         //no need to keep segment selected
0195         return false;
0196     }
0197 
0198     return QGraphicsItem::itemChange(change, value);
0199 }