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 "segmentsscrollbar.h" 0008 0009 #include "gitglobal.h" 0010 #include "segmentconnector.h" 0011 #include "widgets/codeeditor.h" 0012 0013 #include <QPaintEvent> 0014 #include <QPainter> 0015 #include <kommitwidgetsglobaloptions.h> 0016 0017 SegmentsScrollBar::SegmentsScrollBar(QWidget *parent) 0018 : QWidget{parent} 0019 { 0020 setMouseTracking(true); 0021 } 0022 0023 SegmentConnector *SegmentsScrollBar::segmentConnector() const 0024 { 0025 return mSegmentConnector; 0026 } 0027 0028 void SegmentsScrollBar::setSegmentConnector(SegmentConnector *newSegmentConnector) 0029 { 0030 if (mSegmentConnector) { 0031 disconnect(newSegmentConnector, &SegmentConnector::segmentsChanged, this, &SegmentsScrollBar::reload); 0032 disconnect(newSegmentConnector, &SegmentConnector::sameSizeChanged, this, &SegmentsScrollBar::reload); 0033 } 0034 mSegmentConnector = newSegmentConnector; 0035 connect(newSegmentConnector, &SegmentConnector::segmentsChanged, this, &SegmentsScrollBar::reload); 0036 connect(newSegmentConnector, &SegmentConnector::sameSizeChanged, this, &SegmentsScrollBar::reload); 0037 update(); 0038 } 0039 0040 void SegmentsScrollBar::paintEvent(QPaintEvent *event) 0041 { 0042 QPainter painter(this); 0043 painter.fillRect(event->rect(), Qt::white); 0044 0045 if (!Q_UNLIKELY(mSegmentConnector)) 0046 return; 0047 0048 painter.drawImage(0, 0, mSegmentsImage); 0049 0050 auto leftArea = mSegmentConnector->left()->visibleLines(); 0051 auto rightArea = mSegmentConnector->right()->visibleLines(); 0052 0053 QBrush br(Qt::gray); 0054 0055 painter.fillRect(QRect{int(width() * .4), 0, int(width() * .2), height() - 1}, palette().base()); 0056 painter.drawLine(width() * .4, 0, width() * .4, height() - 1); 0057 painter.drawLine(width() * .6, 0, width() * .6, height() - 1); 0058 0059 painter.setOpacity(.3); 0060 paintSection(painter, Left, leftArea.first, leftArea.second, br, true); 0061 paintSection(painter, Right, rightArea.first, rightArea.second, br, true); 0062 painter.setOpacity(1); 0063 painter.drawRect(QRect{0, 0, width() - 1, height() - 1}); 0064 } 0065 0066 void SegmentsScrollBar::mouseMoveEvent(QMouseEvent *event) 0067 { 0068 QWidget::mouseMoveEvent(event); 0069 Q_EMIT hover(event->y(), static_cast<double>(event->y()) / static_cast<double>(height())); 0070 } 0071 0072 void SegmentsScrollBar::resizeEvent(QResizeEvent *event) 0073 { 0074 Q_UNUSED(event) 0075 if (Q_LIKELY(mSegmentConnector)) 0076 generateSegmentsImage(); 0077 } 0078 0079 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0080 void SegmentsScrollBar::enterEvent(QEvent *event) 0081 #else 0082 void SegmentsScrollBar::enterEvent(QEnterEvent *event) 0083 #endif 0084 { 0085 QWidget::enterEvent(event); 0086 Q_EMIT mouseEntered(); 0087 } 0088 0089 void SegmentsScrollBar::leaveEvent(QEvent *event) 0090 { 0091 QWidget::leaveEvent(event); 0092 Q_EMIT mouseLeaved(); 0093 } 0094 0095 void SegmentsScrollBar::reload() 0096 { 0097 leftCount = rightCount = 0; 0098 for (const auto &segment : qAsConst(mSegmentConnector->segments())) { 0099 if (mSegmentConnector->sameSize()) { 0100 auto m = qMax(segment->oldText.size(), segment->newText.size()); 0101 leftCount += m; 0102 rightCount += m; 0103 } else { 0104 leftCount += segment->oldText.size(); 0105 rightCount += segment->newText.size(); 0106 } 0107 } 0108 update(); 0109 } 0110 0111 void SegmentsScrollBar::generateSegmentsImage() 0112 { 0113 mSegmentsImage = QImage{width(), height(), QImage::Format_ARGB32}; 0114 0115 mSegmentsImage.fill(Qt::white); 0116 QPainter painter{&mSegmentsImage}; 0117 0118 int countLeft{0}; 0119 int countRight{0}; 0120 0121 for (const auto &segment : qAsConst(mSegmentConnector->segments())) { 0122 QBrush brush; 0123 switch (segment->type) { 0124 case Diff::SegmentType::OnlyOnLeft: 0125 brush = KommitWidgetsGlobalOptions::instance()->statucColor(Git::ChangeStatus::Removed); 0126 break; 0127 case Diff::SegmentType::OnlyOnRight: 0128 brush = KommitWidgetsGlobalOptions::instance()->statucColor(Git::ChangeStatus::Added); 0129 break; 0130 case Diff::SegmentType::SameOnBoth: 0131 brush = Qt::white; 0132 break; 0133 case Diff::SegmentType::DifferentOnBoth: 0134 brush = KommitWidgetsGlobalOptions::instance()->statucColor(Git::ChangeStatus::Modified); 0135 break; 0136 default: 0137 break; 0138 } 0139 0140 paintSection(painter, Left, countLeft, segment->oldText.size(), brush); 0141 paintSection(painter, Right, countRight, segment->newText.size(), brush); 0142 0143 if (mSegmentConnector->sameSize()) { 0144 auto m = qMax(segment->oldText.size(), segment->newText.size()); 0145 0146 paintSection(painter, Left, countLeft + segment->oldText.size(), m - segment->oldText.size(), Qt::darkGray); 0147 paintSection(painter, Right, countRight + segment->newText.size(), m - segment->newText.size(), Qt::darkGray); 0148 0149 countLeft += m; 0150 countRight += m; 0151 } else { 0152 countLeft += segment->oldText.size(); 0153 countRight += segment->newText.size(); 0154 } 0155 } 0156 /* 0157 auto leftArea = mSegmentConnector->left()->visibleLines(); 0158 auto rightArea = mSegmentConnector->right()->visibleLines(); 0159 0160 QBrush br(Qt::gray); 0161 0162 painter.fillRect(QRect{int(width() * .4), 0, int(width() * .2), height() - 1}, palette().base()); 0163 painter.drawLine(width() * .4, 0, width() * .4, height() - 1); 0164 painter.drawLine(width() * .6, 0, width() * .6, height() - 1); 0165 0166 painter.setOpacity(.3); 0167 paintSection(painter, Left, leftArea.first, leftArea.second, br, true); 0168 paintSection(painter, Right, rightArea.first, rightArea.second, br, true); 0169 painter.setOpacity(1); 0170 painter.drawRect(QRect{0, 0, width() - 1, height() - 1});*/ 0171 } 0172 0173 void SegmentsScrollBar::paintSection(QPainter &painter, SegmentsScrollBar::Side side, int from, int len, const QBrush &brush, bool drawRect) 0174 { 0175 if (len <= 0) 0176 return; 0177 int w = width() * .4; 0178 int l = side == Left ? 0 : width() - w; 0179 int &c = side == Left ? leftCount : rightCount; 0180 0181 QRect rc{l, static_cast<int>((from / (double)c) * height()) - 1, w, static_cast<int>((len / (double)c) * height())}; 0182 painter.fillRect(rc, brush); 0183 if (drawRect) 0184 painter.drawRect(rc); 0185 } 0186 0187 #include "moc_segmentsscrollbar.cpp"