File indexing completed on 2024-05-05 05:45:46

0001 /*
0002     SPDX-FileCopyrightText: 2001-2003 John Firebaugh <jfirebaugh@kde.org>
0003     SPDX-FileCopyrightText: 2001-2009 Otto Bruggeman <bruggie@gmail.com>
0004     SPDX-FileCopyrightText: 2004 Jeff Snyder <jeff@caffeinated.me.uk>
0005     SPDX-FileCopyrightText: 2007-2011 Kevin Kofler <kevin.kofler@chello.at>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 
0010 #include "kompareconnectwidget.h"
0011 
0012 #include <QApplication>
0013 #include <QPainter>
0014 #include <QPainterPath>
0015 #include <QPixmap>
0016 #include <QStyle>
0017 #include <QTimer>
0018 #include <QPaintEvent>
0019 #include <QFrame>
0020 #include <QMouseEvent>
0021 #include <QDebug>
0022 
0023 #include "viewsettings.h"
0024 #include "komparelistview.h"
0025 #include "komparesplitter.h"
0026 
0027 using namespace KompareDiff2;
0028 
0029 KompareConnectWidgetFrame::KompareConnectWidgetFrame(ViewSettings* settings,
0030         KompareSplitter* parent,
0031         const char* name) :
0032     QSplitterHandle(Qt::Horizontal, (QSplitter*)parent),
0033     m_wid(settings, this, name),
0034     m_label(QStringLiteral(" "), this), // putting a space here because Qt 4 computes different size hints for empty labels
0035     m_layout(this)
0036 {
0037     setObjectName(QLatin1String(name));
0038     setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Ignored));
0039     m_wid.setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored));
0040     m_label.setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed));
0041     m_label.setMargin(3);
0042     QFrame* bottomLine = new QFrame(this);
0043     bottomLine->setFrameShape(QFrame::HLine);
0044     bottomLine->setFrameShadow(QFrame::Plain);
0045     bottomLine->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed));
0046     bottomLine->setFixedHeight(1);
0047     m_layout.setSpacing(0);
0048     m_layout.setContentsMargins(0, 0, 0, 0);
0049     m_layout.addWidget(&m_label);
0050     m_layout.addWidget(bottomLine);
0051     m_layout.addWidget(&m_wid);
0052 }
0053 
0054 KompareConnectWidgetFrame::~KompareConnectWidgetFrame()
0055 {
0056 }
0057 
0058 QSize KompareConnectWidgetFrame::sizeHint() const
0059 {
0060     return QSize(50, style()->pixelMetric(QStyle::PM_ScrollBarExtent));
0061 }
0062 
0063 #if 0
0064 static int kMouseOffset;
0065 
0066 void KompareConnectWidgetFrame::mouseMoveEvent(QMouseEvent* e)
0067 {
0068 
0069     if (!(e->state()&Qt::LeftButton))
0070         return;
0071 
0072     QCOORD pos = s->pick(parentWidget()->mapFromGlobal(e->globalPos()))
0073                  - kMouseOffset;
0074 
0075     ((KompareSplitter*)s)->moveSplitter(pos, id());
0076 }
0077 
0078 void KompareConnectWidgetFrame::mousePressEvent(QMouseEvent* e)
0079 {
0080     if (e->button() == Qt::LeftButton)
0081         kMouseOffset = s->pick(e->pos());
0082     QSplitterHandle::mousePressEvent(e);
0083 }
0084 
0085 void KompareConnectWidgetFrame::mouseReleaseEvent(QMouseEvent* e)
0086 {
0087     if (!opaque() && e->button() == Qt::LeftButton) {
0088         QCOORD pos = s->pick(parentWidget()->mapFromGlobal(e->globalPos()))
0089                      - kMouseOffset;
0090         ((KompareSplitter*)s)->moveSplitter(pos, id());
0091     }
0092 }
0093 #endif
0094 
0095 KompareConnectWidget::KompareConnectWidget(ViewSettings* settings, QWidget* parent, const char* name)
0096     : QWidget(parent),
0097       m_settings(settings),
0098       m_selectedModel(nullptr),
0099       m_selectedDifference(nullptr)
0100 {
0101     setObjectName(QLatin1String(name));
0102 //     connect( m_settings, SIGNAL( settingsChanged() ), this, SLOT( slotDelayedRepaint() ) );
0103     setAttribute(Qt::WA_NoSystemBackground, true);
0104     setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum));
0105     setFocusProxy(parent->parentWidget());
0106 }
0107 
0108 KompareConnectWidget::~KompareConnectWidget()
0109 {
0110     m_settings = nullptr;
0111     m_selectedModel = nullptr;
0112     m_selectedDifference = nullptr;
0113 }
0114 
0115 void KompareConnectWidget::slotSetSelection(const DiffModel* model, const Difference* diff)
0116 {
0117     if (m_selectedModel == model && m_selectedDifference == diff)
0118         return;
0119 
0120     if (m_selectedModel == model && m_selectedDifference != diff)
0121     {
0122         m_selectedDifference = diff;
0123         slotDelayedRepaint();
0124         return;
0125     }
0126 
0127     m_selectedModel = model;
0128     m_selectedDifference = diff;
0129 
0130     slotDelayedRepaint();
0131 }
0132 
0133 void KompareConnectWidget::slotDelayedRepaint()
0134 {
0135     QTimer::singleShot(0, this, static_cast<void(KompareConnectWidget::*)()>(&KompareConnectWidget::repaint));
0136 }
0137 
0138 void KompareConnectWidget::slotSetSelection(const Difference* diff)
0139 {
0140     if (m_selectedDifference == diff)
0141         return;
0142 
0143     m_selectedDifference = diff;
0144 
0145     slotDelayedRepaint();
0146 }
0147 
0148 void KompareConnectWidget::paintEvent(QPaintEvent* /* e */)
0149 {
0150     QPixmap pixbuf(size());
0151     QPainter paint(&pixbuf);
0152     QPainter* p = &paint;
0153 
0154     p->setRenderHint(QPainter::Antialiasing);
0155     p->fillRect(0, 0, pixbuf.width(), pixbuf.height(), palette().color(QPalette::Window));
0156     p->translate(QPointF(0, 0.5));
0157 
0158     KompareSplitter* splitter = static_cast<KompareSplitter*>(parent()->parent());
0159     int count = splitter->count();
0160     KompareListView* leftView = count >= 2 ? static_cast<KompareListViewFrame*>(splitter->widget(0))->view() : nullptr;
0161     KompareListView* rightView = count >= 2 ? static_cast<KompareListViewFrame*>(splitter->widget(1))->view() : nullptr;
0162 
0163     if (m_selectedModel && leftView && rightView)
0164     {
0165         int firstL = leftView->firstVisibleDifference();
0166         int firstR = rightView->firstVisibleDifference();
0167         int lastL = leftView->lastVisibleDifference();
0168         int lastR = rightView->lastVisibleDifference();
0169 
0170         int first = firstL < 0 ? firstR : qMin(firstL, firstR);
0171         int last = lastL < 0 ? lastR : qMax(lastL, lastR);
0172 //         qCDebug(KOMPAREPART) << "    left: " << firstL << " - " << lastL ;
0173 //         qCDebug(KOMPAREPART) << "   right: " << firstR << " - " << lastR ;
0174 //         qCDebug(KOMPAREPART) << " drawing: " << first << " - " << last ;
0175         if (first >= 0 && last >= 0 && first <= last)
0176         {
0177             const DifferenceList* differences  = const_cast<DiffModel*>(m_selectedModel)->differences();
0178             QRect leftRect, rightRect;
0179             for (int i = first; i <= last; ++i)
0180             {
0181                 Difference* diff = differences->at(i);
0182                 bool selected = (diff == m_selectedDifference);
0183 
0184                 if (QApplication::isRightToLeft())
0185                 {
0186                     leftRect = rightView->itemRect(i);
0187                     rightRect = leftView->itemRect(i);
0188                 }
0189                 else
0190                 {
0191                     leftRect = leftView->itemRect(i);
0192                     rightRect = rightView->itemRect(i);
0193                 }
0194 
0195                 int tl = leftRect.top();
0196                 int tr = rightRect.top();
0197                 int bl = leftRect.bottom();
0198                 int br = rightRect.bottom();
0199 
0200                 // Bah, stupid 16-bit signed shorts in that crappy X stuff...
0201                 tl = tl >= -32768 ? tl : -32768;
0202                 tr = tr >= -32768 ? tr : -32768;
0203                 bl = bl <=  32767 ? bl :  32767;
0204                 br = br <=  32767 ? br :  32767;
0205 
0206                 QPainterPath topBezier = makeBezier(tl, tr);
0207                 QPainterPath bottomBezier = makeBezier(bl, br);
0208 
0209                 QPainterPath poly(topBezier);
0210                 poly.connectPath(bottomBezier.toReversed());
0211                 poly.closeSubpath();
0212 
0213                 QColor bg = m_settings->colorForDifferenceType(diff->type(), selected, diff->applied());
0214                 p->setPen(bg);
0215                 p->setBrush(bg);
0216                 p->drawPath(poly);
0217 
0218                 if (selected)
0219                 {
0220                     p->setPen(bg.darker(135));
0221                     p->setBrush(Qt::NoBrush);
0222                     p->drawPath(topBezier);
0223                     p->drawPath(bottomBezier.toReversed());
0224                 }
0225             }
0226         }
0227     }
0228 
0229 //     p->flush();
0230     QPainter widgetPainter(this);
0231     widgetPainter.drawImage(0, 0, pixbuf.toImage());
0232 }
0233 
0234 QPainterPath KompareConnectWidget::makeBezier(int leftHeight, int rightHeight) const
0235 {
0236     int r = width();
0237     int o = (int)((double)r * 0.4); // 40% of width
0238 
0239     QPainterPath p(QPointF(0, leftHeight));
0240     if (leftHeight == rightHeight) {
0241         p.lineTo(QPointF(r, rightHeight));
0242     } else {
0243         p.cubicTo(QPointF(o, leftHeight), QPointF(r - o, rightHeight), QPointF(r, rightHeight));
0244     }
0245     return p;
0246 }
0247 
0248 #include "moc_kompareconnectwidget.cpp"