Wireshark 4.7.0
The Wireshark network protocol analyzer
Loading...
Searching...
No Matches
lua_debugger_utils.h
Go to the documentation of this file.
1/* lua_debugger_utils.h
2 *
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <[email protected]>
5 * Copyright 1998 Gerald Combs
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
15#ifndef LUA_DEBUGGER_UTILS_H
16#define LUA_DEBUGGER_UTILS_H
17
18#include <QBrush>
19#include <QChar>
20#include <QFont>
21#include <QHash>
22#include <QIcon>
23#include <QKeySequence>
24#include <QModelIndex>
25#include <QSet>
26#include <QStandardItem>
27#include <QStandardItemModel>
28#include <QString>
29#include <QStringList>
30#include <QTreeView>
31#include <QVariant>
32#include <QtGlobal>
33
34#include "epan/wslua/wslua_debugger.h"
35
37class QFont;
38class QKeyEvent;
39class QObject;
40class QPalette;
41class QToolButton;
42class QTreeView;
43class QWidget;
44
45namespace Ui
46{
48}
49
50/* ===== from internal ===== */
51
52
54inline QStandardItem *luaDbgWatchRootItem(QStandardItem *item)
55{
56 while (item && item->parent())
57 {
58 item = item->parent();
59 }
60 return item;
61}
62
65{
66 bool rootExpanded = false;
67 QStringList subpaths;
68};
69
73void luaDbgRecordTreeSectionRootExpansion(QHash<QString, LuaDbgTreeSectionExpansionState> &map, const QString &rootKey,
74 bool expanded);
75
79void luaDbgRecordTreeSectionSubpathExpansion(QHash<QString, LuaDbgTreeSectionExpansionState> &map,
80 const QString &rootKey, const QString &key, bool expanded);
81
83QStringList luaDbgTreeSectionExpandedSubpaths(const QHash<QString, LuaDbgTreeSectionExpansionState> &map,
84 const QString &rootKey);
85
88
89namespace LuaDebuggerSettingsKeys
90{
91constexpr const char *Theme = "theme";
93constexpr const char *DebuggerEnabled = "debuggerEnabled";
94constexpr const char *MainSplitter = "mainSplitterState";
95constexpr const char *LeftSplitter = "leftSplitterState";
96constexpr const char *EvalSplitter = "evalSplitterState";
97constexpr const char *SectionVariables = "sectionVariables";
98constexpr const char *SectionStack = "sectionStack";
99constexpr const char *SectionFiles = "sectionFiles";
100constexpr const char *SectionBreakpoints = "sectionBreakpoints";
101constexpr const char *SectionEval = "sectionEval";
102constexpr const char *SectionSettings = "sectionSettings";
103constexpr const char *SectionWatch = "sectionWatch";
104constexpr const char *Breakpoints = "breakpoints";
105constexpr const char *Watches = "watches";
106} // namespace LuaDebuggerSettingsKeys
107
108// Tree widget UserRoles (must stay stable for persisted settings / model code).
109constexpr qint32 FileTreePathRole = static_cast<qint32>(Qt::UserRole);
110constexpr qint32 FileTreeIsDirectoryRole = static_cast<qint32>(Qt::UserRole + 1);
111constexpr qint32 BreakpointFileRole = static_cast<qint32>(Qt::UserRole + 2);
112constexpr qint32 BreakpointLineRole = static_cast<qint32>(Qt::UserRole + 3);
113constexpr qint32 BreakpointConditionRole = static_cast<qint32>(Qt::UserRole + 30);
114constexpr qint32 BreakpointHitCountRole = static_cast<qint32>(Qt::UserRole + 31);
115constexpr qint32 BreakpointHitTargetRole = static_cast<qint32>(Qt::UserRole + 32);
116constexpr qint32 BreakpointConditionErrRole = static_cast<qint32>(Qt::UserRole + 33);
117constexpr qint32 BreakpointLogMessageRole = static_cast<qint32>(Qt::UserRole + 34);
118constexpr qint32 BreakpointHitModeRole = static_cast<qint32>(Qt::UserRole + 35);
119constexpr qint32 BreakpointLogAlsoPauseRole = static_cast<qint32>(Qt::UserRole + 36);
120constexpr qint32 StackItemFileRole = static_cast<qint32>(Qt::UserRole + 4);
121constexpr qint32 StackItemLineRole = static_cast<qint32>(Qt::UserRole + 5);
122constexpr qint32 StackItemNavigableRole = static_cast<qint32>(Qt::UserRole + 6);
123constexpr qint32 StackItemLevelRole = static_cast<qint32>(Qt::UserRole + 7);
124constexpr qint32 VariablePathRole = static_cast<qint32>(Qt::UserRole + 8);
125constexpr qint32 VariableTypeRole = static_cast<qint32>(Qt::UserRole + 9);
126constexpr qint32 VariableCanExpandRole = static_cast<qint32>(Qt::UserRole + 10);
127constexpr qint32 WatchSpecRole = static_cast<qint32>(Qt::UserRole + 11);
128constexpr qint32 WatchSubpathRole = static_cast<qint32>(Qt::UserRole + 13);
129constexpr qint32 WatchPendingNewRole = static_cast<qint32>(Qt::UserRole + 15);
130constexpr qint32 ChangedFlashSerialRole = static_cast<qint32>(Qt::UserRole + 20);
131
132constexpr qsizetype WATCH_TOOLTIP_MAX_CHARS = 4096;
133constexpr int WATCH_EXPR_MAX_CHARS = 65536;
134constexpr int CHANGED_FLASH_MS = 500;
135constexpr int WATCH_PLACEHOLDER_DEFER_MS = 250;
136constexpr QChar CHANGE_KEY_SEP = QChar(0x1F);
137
139constexpr int kLuaDbgEvalOutputMaxLines = 5000;
140
141extern const QKeySequence kLuaDbgCtxGoToLine;
142extern const QKeySequence kLuaDbgCtxRunToLine;
143extern const QKeySequence kLuaDbgCtxWatchEdit;
144extern const QKeySequence kLuaDbgCtxWatchCopyValue;
145extern const QKeySequence kLuaDbgCtxWatchDuplicate;
146extern const QKeySequence kLuaDbgCtxWatchRemoveAll;
147extern const QKeySequence kLuaDbgCtxAddWatch;
148extern const QKeySequence kLuaDbgCtxToggleBreakpoint;
149extern const QKeySequence kLuaDbgCtxReloadLuaPlugins;
150extern const QKeySequence kLuaDbgCtxRemoveAllBreakpoints;
151
155QKeySequence luaDbgSeqFromKeyEvent(const QKeyEvent *ke);
156
157/* ===== from item_utils ===== */
158
159namespace LuaDebuggerItems
160{
161
163inline QString rowColumnDisplayText(const QModelIndex &indexInRow, int col)
164{
165 if (!indexInRow.isValid())
166 {
167 return QString();
168 }
169 return indexInRow.sibling(indexInRow.row(), col).data(Qt::DisplayRole).toString();
170}
171
173inline QStandardItem *rowCol0(QStandardItemModel *model, QStandardItem *cell)
174{
175 if (!model || !cell)
176 {
177 return nullptr;
178 }
179 const QModelIndex ix = model->indexFromItem(cell);
180 if (!ix.isValid())
181 {
182 return nullptr;
183 }
184 return model->itemFromIndex(ix.sibling(ix.row(), 0));
185}
186
188inline QStandardItem *cellAt(QStandardItemModel *model, QStandardItem *col0, int col)
189{
190 if (!model || !col0 || col0->column() != 0)
191 {
192 return nullptr;
193 }
194 QStandardItem *par = col0->parent();
195 if (!par)
196 {
197 return model->item(col0->row(), col);
198 }
199 return par->child(col0->row(), col);
200}
201
202inline QString text(QStandardItemModel *model, QStandardItem *col0, int col)
203{
204 QStandardItem *c = cellAt(model, col0, col);
205 return c ? c->text() : QString();
206}
207
208inline void setText(QStandardItemModel *model, QStandardItem *col0, int col, const QString &t)
209{
210 QStandardItem *c = cellAt(model, col0, col);
211 if (c)
212 {
213 c->setText(t);
214 }
215}
216
217inline void setToolTip(QStandardItemModel *model, QStandardItem *col0, int col, const QString &tip)
218{
219 QStandardItem *c = cellAt(model, col0, col);
220 if (c)
221 {
222 c->setToolTip(tip);
223 }
224}
225
226inline void setFont(QStandardItemModel *model, QStandardItem *col0, int col, const QFont &font)
227{
228 QStandardItem *c = cellAt(model, col0, col);
229 if (c)
230 {
231 c->setFont(font);
232 }
233}
234
235inline void setForeground(QStandardItemModel *model, QStandardItem *col0, int col, const QBrush &brush)
236{
237 QStandardItem *c = cellAt(model, col0, col);
238 if (c)
239 {
240 c->setForeground(brush);
241 }
242}
243
244inline void setBackground(QStandardItemModel *model, QStandardItem *col0, int col, const QBrush &brush)
245{
246 QStandardItem *c = cellAt(model, col0, col);
247 if (c)
248 {
249 c->setBackground(brush);
250 }
251}
252
253inline void setIcon(QStandardItemModel *model, QStandardItem *col0, int col, const QIcon &icon)
254{
255 QStandardItem *c = cellAt(model, col0, col);
256 if (c)
257 {
258 c->setIcon(icon);
259 }
260}
261
262inline void setTextAlignment(QStandardItemModel *model, QStandardItem *col0, int col, Qt::Alignment align)
263{
264 QStandardItem *c = cellAt(model, col0, col);
265 if (c)
266 {
267 c->setTextAlignment(align);
268 }
269}
270
271inline QModelIndex indexCol0(QStandardItemModel *model, QStandardItem *col0)
272{
273 if (!model || !col0 || col0->column() != 0)
274 {
275 return QModelIndex();
276 }
277 return model->indexFromItem(col0);
278}
279
280inline bool isExpanded(QTreeView *tree, QStandardItemModel *model, QStandardItem *col0)
281{
282 const QModelIndex ix = indexCol0(model, col0);
283 return ix.isValid() && tree->isExpanded(ix);
284}
285
286inline void setExpanded(QTreeView *tree, QStandardItemModel *model, QStandardItem *col0, bool expanded)
287{
288 const QModelIndex ix = indexCol0(model, col0);
289 if (ix.isValid())
290 {
291 tree->setExpanded(ix, expanded);
292 }
293}
294
295} // namespace LuaDebuggerItems
296
297/* ===== from path_utils ===== */
298
299namespace LuaDebuggerPath
300{
301
302bool watchSpecIsGlobalScoped(const QString &spec);
303
304bool variablesPathIsGlobalScoped(const QString &path);
305
306QString changeKey(int stackLevel, const QString &path);
307
308QString watchSpecFromChangeKey(const QString &key);
309
310QString stripWatchExpressionErrorPrefix(const QString &errStr);
311
312template <class Key, class Map>
313bool shouldMarkChanged(const Map &baseline, const Key &key, const QString &newVal, bool flashNew = false)
314{
315 const auto it = baseline.constFind(key);
316 if (it != baseline.constEnd())
317 {
318 return *it != newVal;
319 }
320 return flashNew && !baseline.isEmpty();
321}
322
323QString variableSectionRootKeyFromItem(const QStandardItem *item);
324
325bool watchSpecUsesPathResolution(const QString &spec);
326
327QString variableTreeChildPath(const QString &parentPath, const QString &nameText);
328
329QString expressionWatchChildSubpath(const QString &parentSubpath, const QString &nameText);
330
331bool variableChildrenShouldSortByName(const QString &parentPath);
332
334{
335 QString name;
336 QString value;
337 QString type;
338 bool canExpand = false;
339 QString childPath;
340};
341
342VariableRowFields readVariableRowFields(const wslua_variable_t &v, const QString &parentPath);
343
344void applyVariableExpansionIndicator(QStandardItem *anchor, bool canExpand, bool enabledOnlyPlaceholder,
345 int columnCount = 3);
346
347QString watchVariablePathForSpec(const QString &spec);
348
349QString watchResolvedVariablePathForTooltip(const QString &spec);
350
351void watchRootSetVariablePathRoleFromSpec(QStandardItem *row, const QString &spec);
352
353QString watchPathOriginSuffix(const QStandardItem *item, const QString &spec);
354
355QString capWatchTooltipText(const QString &s);
356
357QString watchPathParentKey(const QString &path);
358
359void applyWatchChildRowTextAndTooltip(QStandardItem *specItem, const QString &rawVal, const QString &typeText);
360
361int watchSubpathBoundaryCount(const QString &subpath);
362
363QStandardItem *findWatchItemBySubpathOrPathKey(QStandardItem *subtree, const QString &key);
364
365QStandardItem *findVariableTreeItemByPathKey(QStandardItem *subtree, const QString &key);
366
367using TreePathKeyFinder = QStandardItem *(*)(QStandardItem *, const QString &);
368
369void reexpandTreeDescendantsByPathKeys(QTreeView *tree, QStandardItemModel *model, QStandardItem *subtree,
370 QStringList pathKeys, TreePathKeyFinder findByKey);
371
372void reexpandWatchDescendantsByPathKeys(QTreeView *tree, QStandardItemModel *model, QStandardItem *subtree,
373 QStringList pathKeys);
374
375void clearWatchFilterErrorChrome(QStandardItem *specItem, QTreeView *tree);
376
377void applyWatchFilterErrorChrome(QStandardItem *specItem, QTreeView *tree);
378
379void setupWatchRootItemFromSpec(QStandardItem *specItem, QStandardItem *valueItem, const QString &spec);
380
381QStandardItem *findVariableItemByPathRecursive(QStandardItem *node, const QString &path);
382
383QString watchItemExpansionKey(const QStandardItem *item);
384
385} // namespace LuaDebuggerPath
386
387/* ===== from header_styles ===== */
388
390QIcon luaDbgMakeSelectionAwareIcon(const QIcon &base, const QPalette &palette);
391
395QIcon luaDbgPaintedGlyphIcon(const QString &glyph, int side, qreal dpr,
396 const QFont &baseFont, const QColor &color,
397 int margin = 1);
398
407QIcon luaDbgPaintedGlyphButtonIcon(const QString &glyph, int side, qreal dpr,
408 const QFont &baseFont, const QPalette &palette,
409 int margin = 2);
410
412extern const QString kLuaDbgHeaderPlus;
413extern const QString kLuaDbgHeaderMinus;
416extern const QString kLuaDbgHeaderEdit;
419extern const QString kLuaDbgRowLog;
422extern const QString kLuaDbgRowExtras;
425extern const QString kLuaDbgHeaderRemoveAll;
426extern const QString kLuaDbgHeaderToolButtonStyle;
427
428enum class LuaDbgBpHeaderIconMode
429{
430 NoBreakpoints,
431 ActivateAll,
432 DeactivateAll,
433};
434
435QIcon luaDbgBreakpointHeaderIconForMode(const QFont *editorFont, LuaDbgBpHeaderIconMode mode, int headerSide,
436 qreal dpr);
437
438void styleLuaDebuggerHeaderBreakpointToggleButton(QToolButton *btn, int side);
439
440void styleLuaDebuggerHeaderFittedTextButton(QToolButton *btn, int side, const QFont &titleFont,
441 const QStringList &glyphs);
442
443void styleLuaDebuggerHeaderPlusMinusButton(QToolButton *btn, int side, const QFont &titleFont);
444
445void styleLuaDebuggerHeaderIconOnlyButton(QToolButton *btn, int side);
446
447/* ===== from key_router ===== */
448
470{
471public:
473
478 void attach(Ui::LuaDebuggerDialog *ui, QTreeView *breakpointsTree);
479
486 bool reserveShortcutOverride(const QKeyEvent *ke) const;
487
492 bool handleKeyPress(QObject *obj, const QKeyEvent *ke);
493
494private:
495 LuaDebuggerDialog *host_;
496 Ui::LuaDebuggerDialog *ui_ = nullptr;
497 QTreeView *breakpointsTree_ = nullptr;
498};
499
500/* ===== from change_tracker ===== */
501
534{
535 public:
537
538 void refreshChangedValueBrushes(QTreeView *watchTree, QWidget *paletteFallback);
539
540 void snapshotBaselinesOnPauseEntry();
541
542 void updatePauseEntryFrameIdentity();
543
544 void setPauseEntryStackLevel(int level) { pauseEntryStackLevel_ = level; }
545
550 void setPauseEntryRefresh(bool active) { isPauseEntryRefresh_ = active; }
551
560 void applyChangedVisuals(QObject *timerOwner, QStandardItem *anchor, bool changed);
561
562 void clearAllChangeBaselines();
563
567 void clearWatchBaselines();
568
569 void clearChangeBaselinesForWatchSpec(const QString &spec);
570
571 void pruneChangeBaselinesToLiveWatchSpecs(QStandardItemModel *watchModel);
572
573 bool changeHighlightAllowed(int stackSelectionLevel) const;
574
578 bool observeWatchRootValue(const QString &rootKey, const QString &value);
579
584 bool observeWatchChildParent(const QString &rootKey, const QString &parentPath);
585
590 bool observeWatchChildValue(const QString &rootKey, const QString &childPath, const QString &value,
591 bool parentVisited);
592
594 bool observeVariablesParent(const QString &parentKey);
595
597 bool observeVariablesValue(const QString &variablesKey, const QString &value, bool parentVisited);
598
599 private:
600 QHash<QString /* rootKey */, QString> watchRootBaseline_;
601 QHash<QString /* rootKey */, QString> watchRootCurrent_;
602 QHash<QString /* rootKey */, QHash<QString /* childPath */, QString>> watchChildBaseline_;
603 QHash<QString /* rootKey */, QHash<QString /* childPath */, QString>> watchChildCurrent_;
604 QHash<QString /* variablesKey */, QString> variablesBaseline_;
605 QHash<QString /* variablesKey */, QString> variablesCurrent_;
606
607 QSet<QString /* variablesKey of parent */> variablesBaselineParents_;
608 QSet<QString /* variablesKey of parent */> variablesCurrentParents_;
609 QHash<QString /* rootKey */, QSet<QString /* parentPath */>> watchChildBaselineParents_;
610 QHash<QString /* rootKey */, QSet<QString /* parentPath */>> watchChildCurrentParents_;
611
612 QBrush changedValueBrush_;
613 QBrush changedFlashBrush_;
614 bool isPauseEntryRefresh_ = false;
615 qint32 flashSerial_ = 0;
616 int pauseEntryStackLevel_ = 0;
617 QString pauseEntryFrame0Identity_;
618 bool pauseEntryFrame0MatchesPrev_ = false;
619};
620
621#endif
"Value changed since last pause" highlighter for the Watch and Variables trees.
Definition lua_debugger_utils.h:534
bool observeWatchRootValue(const QString &rootKey, const QString &value)
Record the latest value for a watch root keyed by the composite rootKey. Returns true if the new valu...
Definition lua_debugger_utils.cpp:1318
void setPauseEntryRefresh(bool active)
Toggle the pause-entry refresh flag. The dialog turns it on for the duration of the pause-entry refre...
Definition lua_debugger_utils.h:550
bool observeVariablesValue(const QString &variablesKey, const QString &value, bool parentVisited)
Variables-tree counterpart to observeWatchChildValue.
Definition lua_debugger_utils.cpp:1348
bool observeVariablesParent(const QString &parentKey)
Variables-tree counterpart to observeWatchChildParent.
Definition lua_debugger_utils.cpp:1341
void applyChangedVisuals(QObject *timerOwner, QStandardItem *anchor, bool changed)
Stamp the anchor row with the change visuals; isPauseEntryRefresh_ is consulted internally so callers...
Definition lua_debugger_utils.cpp:1246
bool observeWatchChildValue(const QString &rootKey, const QString &childPath, const QString &value, bool parentVisited)
Record the latest value for a watch-child row at rootKey/childPath. parentVisited is the result of ob...
Definition lua_debugger_utils.cpp:1332
void clearWatchBaselines()
Wipe watch-side baselines (root + child value maps and visited-parent sets). Variables-tree maps are ...
Definition lua_debugger_utils.cpp:1308
bool observeWatchChildParent(const QString &rootKey, const QString &parentPath)
Record parentPath as a visited parent in the watch-child visited-parents set keyed by rootKey....
Definition lua_debugger_utils.cpp:1325
Top-level dialog hosting the Lua debugger UI components.
Definition lua_debugger_dialog.h:165
Centralised keyboard-shortcut dispatcher for the Lua debugger dialog's eventFilter().
Definition lua_debugger_utils.h:470
bool reserveShortcutOverride(const QKeyEvent *ke) const
Pre-empt a debugger-owned shortcut on QEvent::ShortcutOverride.
Definition lua_debugger_utils.cpp:1007
bool handleKeyPress(QObject *obj, const QKeyEvent *ke)
Handle a QEvent::KeyPress delivered to the debugger UI.
Definition lua_debugger_utils.cpp:1023
void attach(Ui::LuaDebuggerDialog *ui, QTreeView *breakpointsTree)
Wire the router to the dialog's Ui struct and breakpoints tree. Must be called once,...
Definition lua_debugger_utils.cpp:1001
const QString kLuaDbgHeaderEdit
Definition lua_debugger_utils.cpp:651
QStringList luaDbgTreeSectionExpandedSubpaths(const QHash< QString, LuaDbgTreeSectionExpansionState > &map, const QString &rootKey)
Expanded-descendant subpaths recorded for rootKey, or empty.
Definition lua_debugger_utils.cpp:120
const QString kLuaDbgRowExtras
Definition lua_debugger_utils.cpp:654
void luaDbgRecordTreeSectionRootExpansion(QHash< QString, LuaDbgTreeSectionExpansionState > &map, const QString &rootKey, bool expanded)
Record / clear root-level expansion for rootKey in map. Mutates map in place; collapsing a root with ...
Definition lua_debugger_utils.cpp:71
QIcon luaDbgPaintedGlyphIcon(const QString &glyph, int side, qreal dpr, const QFont &baseFont, const QColor &color, int margin=1)
Definition lua_debugger_utils.cpp:701
QStandardItem * luaDbgWatchRootItem(QStandardItem *item)
Definition lua_debugger_utils.h:54
void luaDbgRecordTreeSectionSubpathExpansion(QHash< QString, LuaDbgTreeSectionExpansionState > &map, const QString &rootKey, const QString &key, bool expanded)
Add / remove one descendant subpath key under rootKey in map. Mirrors luaDbgRecordTreeSectionRootExpa...
Definition lua_debugger_utils.cpp:90
const QString kLuaDbgHeaderPlus
Definition lua_debugger_utils.cpp:649
const QString kLuaDbgHeaderRemoveAll
Definition lua_debugger_utils.cpp:652
constexpr const char * DebuggerEnabled
Definition lua_debugger_utils.h:93
QString rowColumnDisplayText(const QModelIndex &indexInRow, int col)
Definition lua_debugger_utils.h:163
QKeySequence luaDbgSeqFromKeyEvent(const QKeyEvent *ke)
Build a key sequence from a key event for matching against QAction shortcuts. Wraps the Qt5/Qt6 modif...
Definition lua_debugger_utils.cpp:146
QString luaDebuggerSettingsFilePath()
Definition lua_debugger_utils.cpp:65
QIcon luaDbgMakeSelectionAwareIcon(const QIcon &base, const QPalette &palette)
Definition lua_debugger_utils.cpp:862
constexpr int kLuaDbgEvalOutputMaxLines
Definition lua_debugger_utils.h:139
QIcon luaDbgPaintedGlyphButtonIcon(const QString &glyph, int side, qreal dpr, const QFont &baseFont, const QPalette &palette, int margin=2)
Definition lua_debugger_utils.cpp:776
QStandardItem * rowCol0(QStandardItemModel *model, QStandardItem *cell)
Definition lua_debugger_utils.h:173
const QString kLuaDbgRowLog
Definition lua_debugger_utils.cpp:653
QStandardItem * cellAt(QStandardItemModel *model, QStandardItem *col0, int col)
Definition lua_debugger_utils.h:188
Definition lua_debugger_utils.h:65
Definition lua_debugger_utils.h:334
Variable structure for inspection.
Definition wslua_debugger.h:421