File indexing completed on 2024-05-12 04:37:36

0001 /*
0002     SPDX-FileCopyrightText: 2009 Niko Sams <niko.sams@gmail.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "ivariablecontroller.h"
0008 
0009 #include "idebugsession.h"
0010 #include "../../interfaces/icore.h"
0011 #include "../../interfaces/idebugcontroller.h"
0012 #include "../variable/variablecollection.h"
0013 #include <debug.h>
0014 #include "iframestackmodel.h"
0015 
0016 
0017 namespace KDevelop {
0018 
0019 class IVariableControllerPrivate
0020 {
0021 public:
0022     QFlags<IVariableController::UpdateType> autoUpdate;
0023     int activeThread = -1;
0024     int activeFrame = -1;
0025 };
0026 
0027 IVariableController::IVariableController(IDebugSession* parent)
0028     : QObject(parent)
0029     , d_ptr(new IVariableControllerPrivate)
0030 {
0031     connect(parent, &IDebugSession::stateChanged,
0032             this, &IVariableController::stateChanged);
0033 }
0034 
0035 IVariableController::~IVariableController() = default;
0036 
0037 VariableCollection* IVariableController::variableCollection()
0038 {
0039     if (!ICore::self()) return nullptr;
0040     return ICore::self()->debugController()->variableCollection();
0041 }
0042 
0043 IDebugSession* IVariableController::session() const
0044 {
0045     return static_cast<IDebugSession*>(parent());
0046 }
0047 
0048 void IVariableController::stateChanged(IDebugSession::DebuggerState state)
0049 {
0050     Q_D(IVariableController);
0051 
0052     if (!ICore::self() || ICore::self()->shuttingDown()) {
0053         return;
0054     }
0055 
0056     if (state == IDebugSession::ActiveState) {
0057         //variables are now outdated, update them
0058         d->activeThread = -1;
0059         d->activeFrame = -1;
0060     } else if (state == IDebugSession::EndedState || state == IDebugSession::NotStartedState) {
0061         // Remove all locals.
0062         const auto locals = variableCollection()->allLocals();
0063         for (Locals* l : locals) {
0064             l->deleteChildren();
0065             l->setHasMore(false);
0066         }
0067 
0068         for (int i=0; i < variableCollection()->watches()->childCount(); ++i) {
0069             auto *var = qobject_cast<Variable*>(variableCollection()->watches()->child(i));
0070             if (var) {
0071                 var->setInScope(false);
0072             }
0073         }
0074     }
0075 }
0076 
0077 void IVariableController::updateIfFrameOrThreadChanged()
0078 {
0079     Q_D(IVariableController);
0080 
0081     IFrameStackModel *sm = session()->frameStackModel();
0082     if (sm->currentThread() != d->activeThread || sm->currentFrame() != d->activeFrame) {
0083         variableCollection()->root()->resetChanged();
0084         update();
0085     }
0086 }
0087 
0088 void IVariableController::handleEvent(IDebugSession::event_t event)
0089 {
0090     Q_D(IVariableController);
0091 
0092     if (!variableCollection()) return;
0093 
0094     switch (event) {
0095     case IDebugSession::thread_or_frame_changed:
0096         qCDebug(DEBUGGER) << d->autoUpdate;
0097         if (!(d->autoUpdate & UpdateLocals)) {
0098             const auto locals = variableCollection()->allLocals();
0099             for (Locals* l : locals) {
0100                 if (!l->isExpanded() && !l->childCount()) {
0101                     l->setHasMore(true);
0102                 }
0103             }
0104         }
0105         if (d->autoUpdate != UpdateNone) {
0106             updateIfFrameOrThreadChanged();
0107         }
0108 
0109         // update our cache of active thread/frame regardless of d->autoUpdate
0110         // to keep them synced when user currently hides the variable list
0111         d->activeThread = session()->frameStackModel()->currentThread();
0112         d->activeFrame = session()->frameStackModel()->currentFrame();
0113         break;
0114 
0115     default:
0116         break;
0117     }
0118 }
0119 
0120 void IVariableController::setAutoUpdate(QFlags<UpdateType> autoUpdate)
0121 {
0122     Q_D(IVariableController);
0123 
0124     IDebugSession::DebuggerState state = session()->state();
0125     d->autoUpdate = autoUpdate;
0126     qCDebug(DEBUGGER) << d->autoUpdate;
0127     if (d->autoUpdate != UpdateNone && state == IDebugSession::PausedState) {
0128         update();
0129     }
0130 }
0131 
0132 QFlags<IVariableController::UpdateType> IVariableController::autoUpdate()
0133 {
0134     Q_D(IVariableController);
0135 
0136     return d->autoUpdate;
0137 }
0138 
0139 }
0140 
0141 #include "moc_ivariablecontroller.cpp"