File indexing completed on 2025-01-05 05:14:52

0001 /*
0002 SPDX-FileCopyrightText: 2021 Hamed Masafi <hamed.masfi@gmail.com>
0003 
0004 SPDX-License-Identifier: GPL-3.0-or-later
0005 */
0006 
0007 #include "segmentconnector.h"
0008 #include "widgets/codeeditor.h"
0009 
0010 #include <QPainter>
0011 #include <QPainterPath>
0012 #include <kommitwidgetsglobaloptions.h>
0013 
0014 SegmentConnector::SegmentConnector(QWidget *parent)
0015     : QWidget(parent)
0016 {
0017 }
0018 
0019 SegmentConnector::~SegmentConnector()
0020 {
0021     qDeleteAll(mSegments);
0022 }
0023 
0024 const QList<Diff::DiffSegment *> &SegmentConnector::segments() const
0025 {
0026     return mSegments;
0027 }
0028 
0029 void SegmentConnector::setSegments(const QList<Diff::DiffSegment *> &newSegments)
0030 {
0031     mSegments = newSegments;
0032 
0033     int oldIndex{0};
0034     int newIndex{0};
0035     mSegmentPos.clear();
0036 
0037     for (auto &s : mSegments) {
0038         if (m_sameSize) {
0039             auto sizeMax = qMax(s->oldText.size(), s->newText.size());
0040 
0041             SegmentPos pos{oldIndex, static_cast<int>(oldIndex + s->oldText.size() - 1), newIndex, static_cast<int>(newIndex + s->newText.size() - 1)};
0042 
0043             //            if (s->oldText.isEmpty())
0044             //                pos.leftEnd = -1;
0045             //            if (s->newText.isEmpty())
0046             //                pos.rightEnd = -1;
0047             mSegmentPos.insert(s, pos);
0048 
0049             oldIndex += sizeMax;
0050             newIndex += sizeMax;
0051         } else {
0052             SegmentPos pos{oldIndex, static_cast<int>(oldIndex + s->oldText.size() - 1), newIndex, static_cast<int>(newIndex + s->newText.size() - 1)};
0053 
0054             if (s->oldText.isEmpty())
0055                 pos.leftEnd = -1;
0056             if (s->newText.isEmpty())
0057                 pos.rightEnd = -1;
0058             mSegmentPos.insert(s, pos);
0059 
0060             oldIndex += s->oldText.size();
0061             newIndex += s->newText.size();
0062         }
0063     }
0064     Q_EMIT segmentsChanged();
0065 }
0066 
0067 Diff::Segment *SegmentConnector::currentSegment() const
0068 {
0069     return mCurrentSegment;
0070 }
0071 
0072 void SegmentConnector::setCurrentSegment(Diff::Segment *newCurrentSegment)
0073 {
0074     mCurrentSegment = newCurrentSegment;
0075     update();
0076 }
0077 
0078 bool SegmentConnector::sameSize() const
0079 {
0080     return m_sameSize;
0081 }
0082 
0083 void SegmentConnector::setSameSize(bool newSameSize)
0084 {
0085     m_sameSize = newSameSize;
0086     Q_EMIT sameSizeChanged();
0087 }
0088 
0089 CodeEditor *SegmentConnector::left() const
0090 {
0091     return mLeft;
0092 }
0093 
0094 void SegmentConnector::setLeft(CodeEditor *newLeft)
0095 {
0096     mLeft = newLeft;
0097 }
0098 
0099 CodeEditor *SegmentConnector::right() const
0100 {
0101     return mRight;
0102 }
0103 
0104 void SegmentConnector::setRight(CodeEditor *newRight)
0105 {
0106     mRight = newRight;
0107 }
0108 
0109 void SegmentConnector::paintEvent(QPaintEvent *event)
0110 {
0111     Q_UNUSED(event)
0112 
0113     if (!mLeft || !mRight)
0114         return;
0115 
0116     QPainter painter(this);
0117 
0118     if (m_topMargin)
0119         painter.translate(QPoint(0, m_topMargin));
0120 
0121     painter.setRenderHint(QPainter::Antialiasing, true);
0122     painter.fillRect(rect(), Qt::white);
0123 
0124     for (auto s = mSegmentPos.begin(); s != mSegmentPos.end(); ++s) {
0125         if (s.key()->type == Diff::SegmentType::SameOnBoth)
0126             continue;
0127         const auto leftArea = mLeft->blockArea(s->leftStart, s->leftEnd);
0128         const auto rightArea = mRight->blockArea(s->rightStart, s->rightEnd);
0129 
0130         //        if (s == _currentSegment)
0131         //            painter.setBrush(Qt::yellow);
0132         //        else
0133         switch (s.key()->type) {
0134         case Diff::SegmentType::SameOnBoth:
0135             //            painter.setBrush(Qt::magenta);
0136             continue;
0137         case Diff::SegmentType::OnlyOnRight:
0138             painter.setBrush(KommitWidgetsGlobalOptions::instance()->statucColor(Git::ChangeStatus::Added));
0139             break;
0140         case Diff::SegmentType::OnlyOnLeft:
0141             painter.setBrush(KommitWidgetsGlobalOptions::instance()->statucColor(Git::ChangeStatus::Removed));
0142             break;
0143         case Diff::SegmentType::DifferentOnBoth:
0144             painter.setBrush(KommitWidgetsGlobalOptions::instance()->statucColor(Git::ChangeStatus::Modified));
0145             break;
0146         }
0147 
0148         QPainterPath poly;
0149         poly.moveTo(0, leftArea.first);
0150 
0151         poly.cubicTo(QPointF(30, leftArea.first), QPointF(width() - 30, rightArea.first), QPointF(width() - 1, rightArea.first));
0152         poly.lineTo(width() - 1, rightArea.second);
0153 
0154         poly.cubicTo(QPoint(width() - 30, rightArea.second), QPoint(30, leftArea.second), QPoint(0, leftArea.second));
0155         painter.setPen(Qt::NoPen);
0156         painter.drawPath(poly);
0157     }
0158 }
0159 
0160 int SegmentConnector::topMargin() const
0161 {
0162     return m_topMargin;
0163 }
0164 
0165 void SegmentConnector::setTopMargin(int newTopMargin)
0166 {
0167     m_topMargin = newTopMargin;
0168     update();
0169 }
0170 
0171 #include "moc_segmentconnector.cpp"