-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathMainWindow.cpp
165 lines (144 loc) · 5.5 KB
/
MainWindow.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QFileDialog>
#include <fstream>
namespace visual_lldb {
MainWindow::MainWindow(const QString &executablePath, QWidget *parent)
: QMainWindow(parent), debugger(executablePath.toStdString()),
ui(new Ui::MainWindow) {
// Call this before manipulating the window.
ui->setupUi(this);
ui->frameView->setModel(&frameModel);
ui->bpView->setModel(&bpModel);
QObject::connect(ui->runButton, &QAbstractButton::clicked, this,
&MainWindow::onRun);
QObject::connect(ui->continueButton, &QAbstractButton::clicked, this,
&MainWindow::onContinue);
QObject::connect(ui->nextButton, &QAbstractButton::clicked, this,
&MainWindow::onNext);
QObject::connect(ui->stepDownButton, &QAbstractButton::clicked, this,
&MainWindow::onStepDown);
QObject::connect(ui->stepUpButton, &QAbstractButton::clicked, this,
&MainWindow::onStepUp);
QObject::connect(ui->openFileButton, &QAbstractButton::clicked, this,
&MainWindow::onOpenFile);
QObject::connect(ui->codeBrowser, &CodeBrowser::breakpointToggled, this,
&MainWindow::onBreakpointToggle);
}
MainWindow::~MainWindow() { delete ui; }
void MainWindow::onRun() {
debugger.run();
updateView();
}
void MainWindow::onContinue() {
debugger.resume();
updateView();
}
void MainWindow::onNext() {
debugger.next();
updateView();
}
void MainWindow::onStepDown() {
debugger.stepDown();
updateView();
}
void MainWindow::onStepUp() {
debugger.stepUp();
updateView();
}
void MainWindow::onOpenFile() {
const QString openFile = QFileDialog::getOpenFileName();
if (openFile.isEmpty())
return;
// FIXME: Breakpoints markings will disappear if you open a file manually.
populateCodeBrowser(openFile.toStdString(), 0, {});
}
void MainWindow::onBreakpointToggle(size_t lineNumber) {
if (lineNumber == 0)
return;
debugger.toggleBreakpoint(currentFile, lineNumber);
// Consolidate this with `updateView`.
const auto bps = updateBreakpointModel();
size_t currentLine = 0;
if (debugger.isActive()) {
auto loc = debugger.getLocation();
currentLine = loc.getLine();
}
populateCodeBrowser(currentFile, currentLine, bps);
}
void MainWindow::updateView() {
if (!debugger.isActive())
return;
// Not sure what this could should look but this ain't it.
//
// Since multiple components care about breakpoints, maybe we should be using
// that signal/slot mechanism?
const auto bps = updateBreakpointModel();
updateCodeBrowser(bps);
updateFrameModel();
}
void MainWindow::updateCodeBrowser(const std::vector<Breakpoint> &bps) {
const auto codeLoc = debugger.getLocation();
// Do something smarter than this.
const std::string filePath =
codeLoc.getDirectory() + '/' + codeLoc.getFileName();
populateCodeBrowser(filePath, codeLoc.getLine(), bps);
}
void MainWindow::populateCodeBrowser(const std::string &filePath,
size_t lineNumber,
const std::vector<Breakpoint> &bps) {
if (currentFile != filePath) {
// Read the contents off the disk and populate the code view.
std::ifstream file(filePath);
assert(file);
const std::string contents((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
auto *codeDoc = new QTextDocument(contents.c_str());
codeDoc->setDocumentLayout(new QPlainTextDocumentLayout(codeDoc));
ui->codeBrowser->setDocument(codeDoc);
currentFile = filePath;
}
// Mark the breakpoints visually as well as the current position.
ui->codeBrowser->updateHighlightedLines(bps, lineNumber);
}
void MainWindow::updateFrameModel() {
auto frameVariables = debugger.getFrameVariables();
std::vector<FrameVariable> modelFrame;
for (int i = 0; i < frameVariables.GetSize(); ++i) {
auto val = frameVariables.GetValueAtIndex(i);
FrameVariable newFrame;
newFrame.name = val.GetName();
newFrame.value = val.GetValue();
modelFrame.push_back(std::move(newFrame));
}
logMsg("Displaying " + std::to_string(modelFrame.size()) +
" frame variables");
frameModel.setFrameVariables(std::move(modelFrame));
}
std::vector<Breakpoint> MainWindow::updateBreakpointModel() {
// Debugger should just return this instead of doing transformation here.
auto &debuggerBps = debugger.getBreakpoints();
std::vector<Breakpoint> modelBps;
std::transform(debuggerBps.begin(), debuggerBps.end(),
std::back_inserter(modelBps), [](lldb::SBBreakpoint &bp) {
Breakpoint modelBp;
lldb::SBAddress addr = bp.GetLocationAtIndex(0).GetAddress();
lldb::SBLineEntry lineEntry = addr.GetLineEntry();
lldb::SBFileSpec fileSpec = lineEntry.GetFileSpec();
modelBp.filePath = std::string(fileSpec.GetDirectory()) +
'/' + fileSpec.GetFilename();
modelBp.lineNumber = lineEntry.GetLine();
return modelBp;
});
logMsg("Added " + std::to_string(modelBps.size()) + " breakpoints");
bpModel.setBreakpoints(modelBps);
return modelBps;
}
void MainWindow::logMsg(const std::string &msg) {
// I'm a Qt noob so let's do this. It'll be helpful for debugging so I don't
// need to keep printing stuff to stdout.
msgLog.append(msg);
msgLog.push_back('\n');
ui->logView->setPlainText(msgLog.c_str());
}
} // namespace visual_lldb