File indexing completed on 2024-05-19 04:38:51

0001 /*
0002     SPDX-FileCopyrightText: 2008 Vladimir Prus <ghost@cs.msu.su>
0003     SPDX-FileCopyrightText: 2009 Niko Sams <niko.sams@gmail.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "variabletooltip.h"
0009 
0010 #include <QWidget>
0011 #include <QHBoxLayout>
0012 #include <QApplication>
0013 #include <QMouseEvent>
0014 #include <QHeaderView>
0015 #include <QPushButton>
0016 #include <QScrollBar>
0017 #include <QDesktopWidget>
0018 #include <KLocalizedString>
0019 #include <QPainter>
0020 
0021 #include "variablecollection.h"
0022 #include "../util/treeview.h"
0023 #include "../interfaces/ivariablecontroller.h"
0024 #include "../../util/activetooltip.h"
0025 #include "../../interfaces/icore.h"
0026 #include "../../interfaces/idebugcontroller.h"
0027 
0028 namespace KDevelop {
0029 
0030 class SizeGrip : public QWidget
0031 {
0032     Q_OBJECT
0033 public:
0034     explicit SizeGrip(QWidget* parent) : QWidget(parent) {
0035         m_parent = parent;
0036     }
0037 protected:
0038     void paintEvent(QPaintEvent *) override
0039     {
0040       QPainter painter(this);
0041       QStyleOptionSizeGrip opt;
0042       opt.init(this);
0043       opt.corner = Qt::BottomRightCorner;
0044       style()->drawControl(QStyle::CE_SizeGrip, &opt, &painter, this);
0045     }
0046 
0047     void mousePressEvent(QMouseEvent* e) override
0048     {
0049         if (e->button() == Qt::LeftButton) {
0050             m_pos = e->globalPos();
0051             m_startSize = m_parent->size();
0052             e->ignore();
0053         }
0054     }
0055     void mouseReleaseEvent(QMouseEvent*) override
0056     {
0057         m_pos = QPoint();
0058     }
0059     void mouseMoveEvent(QMouseEvent* e) override
0060     {
0061         if (!m_pos.isNull()) {
0062             m_parent->resize(
0063                 m_startSize.width() + (e->globalPos().x() - m_pos.x()),
0064                 m_startSize.height() + (e->globalPos().y() - m_pos.y())
0065             );
0066         }
0067     }
0068 private:
0069     QWidget *m_parent;
0070     QSize m_startSize;
0071     QPoint m_pos;
0072 };
0073 
0074 VariableToolTip::VariableToolTip(QWidget* parent, const QPoint& position,
0075                                  const QString& identifier)
0076 :  ActiveToolTip(parent, position)
0077 {
0078     setPalette( QApplication::palette() );
0079 
0080     m_model = new TreeModel(QVector<QString>{i18n("Name"), i18n("Value"), i18n("Type")}, this);
0081 
0082     auto* tr = new TooltipRoot(m_model);
0083     m_model->setRootItem(tr);
0084     m_var = ICore::self()->debugController()->currentSession()->
0085         variableController()->createVariable(
0086                m_model, tr, identifier);
0087     tr->init(m_var);
0088     m_var->attachMaybe(this, "variableCreated");
0089 
0090     auto* l = new QVBoxLayout(this);
0091     l->setContentsMargins(0, 0, 0, 0);
0092 
0093     m_view = new AsyncTreeView(*m_model, this);
0094     m_view->setModel(m_model);
0095     m_view->header()->resizeSection(0, 150);
0096     m_view->header()->resizeSection(1, 90);
0097     m_view->setSelectionBehavior(QAbstractItemView::SelectRows);
0098     m_view->setSelectionMode(QAbstractItemView::SingleSelection);
0099     m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
0100     m_view->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
0101     l->addWidget(m_view);
0102 
0103     const QModelIndex varIndex = m_model->indexForItem(m_var, 0);
0104     m_itemHeight = m_view->indexRowSizeHint(varIndex);
0105     connect(m_view->verticalScrollBar(),
0106             &QScrollBar::rangeChanged,
0107             this,
0108             &VariableToolTip::slotRangeChanged);
0109 
0110     m_selection = m_view->selectionModel();
0111     m_selection->select(varIndex,
0112                         QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect);
0113 
0114     auto* buttonBox = new QHBoxLayout();
0115     buttonBox->setContentsMargins(11, 0, 11, 6);
0116     auto* watchThisButton = new QPushButton(i18n("Watch This"));
0117     buttonBox->addWidget(watchThisButton);
0118     auto* stopOnChangeButton = new QPushButton(i18n("Stop on Change"));
0119     buttonBox->addWidget(stopOnChangeButton);
0120 
0121     connect(watchThisButton, &QPushButton::clicked,
0122             this, [this](){ slotLinkActivated(QStringLiteral("add_watch")); });
0123     connect(stopOnChangeButton, &QPushButton::clicked,
0124             this, [this](){ slotLinkActivated(QStringLiteral("add_watchpoint")); });
0125 
0126     auto* inner = new QHBoxLayout();
0127     l->addLayout(inner);
0128     inner->setContentsMargins(0, 0, 0, 0);
0129     inner->addLayout(buttonBox);
0130     inner->addStretch();
0131 
0132     auto* g = new SizeGrip(this);
0133     g->setFixedSize(16, 16);
0134     inner->addWidget(g, 0, (Qt::Alignment)(Qt::AlignRight | Qt::AlignBottom));
0135 
0136     move(position);
0137 }
0138 
0139 void VariableToolTip::variableCreated(bool hasValue)
0140 {
0141     m_view->resizeColumns();
0142     if (hasValue) {
0143         ActiveToolTip::showToolTip(this, 0.0);
0144     } else {
0145         close();
0146     }
0147 }
0148 
0149 void VariableToolTip::slotLinkActivated(const QString& link)
0150 {
0151     Variable* v = m_var;
0152     QItemSelection s = m_selection->selection();
0153     if (!s.empty())
0154     {
0155         TreeItem* const item = m_model->itemForIndex(s.front().topLeft());
0156         if (item)
0157         {
0158             auto* v2 = qobject_cast<Variable*>(item);
0159             if (v2)
0160                 v = v2;
0161         }
0162     }
0163 
0164     IDebugSession *session = ICore::self()->debugController()->currentSession();
0165     if (session && session->state() != IDebugSession::NotStartedState && session->state() != IDebugSession::EndedState) {
0166         if (link == QLatin1String("add_watch")) {
0167             session->variableController()->addWatch(v);
0168         } else if (link == QLatin1String("add_watchpoint")) {
0169             session->variableController()->addWatchpoint(v);
0170         }
0171     }
0172     close();
0173 }
0174 
0175 void VariableToolTip::slotRangeChanged(int min, int max)
0176 {
0177     Q_ASSERT(min == 0);
0178     Q_UNUSED(min);
0179     QRect rect = QApplication::desktop()->screenGeometry(this);
0180     if (pos().y() + height() + max*m_itemHeight < rect.bottom())
0181         resize(width(), height() + max*m_itemHeight);
0182     else
0183     {
0184         // Oh, well, I'm sorry, but here's the scrollbar you was
0185         // longing to see
0186         m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
0187     }
0188 }
0189 
0190 }
0191 
0192 #include "variabletooltip.moc"
0193 #include "moc_variabletooltip.cpp"