1// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4
5#include "breakpointmodel.h"
6
7#include <QStyledItemDelegate>
8
9BreakpointModel::BreakpointModel(QObject *parent)
10 : QAbstractTableModel(parent)
11{
12 setObjectName("BreakpointModel");
13}
14
15BreakpointModel::~BreakpointModel() = default;
16
17void BreakpointModel::setBreakpoints(const Internal::Breakpoints &breakpoints, bool canExpand)
18{
19 beginResetModel();
20 contentsValid = true;
21 this->canExpand = canExpand;
22 bps.clear();
23 for (auto it : breakpoints) {
24 bps.push_back(BreakpointItem(it));
25 }
26 if (bps.size() >= 0)
27 setCurrentIndex(0);
28 else
29 currentIndex = -1;
30 endResetModel();
31 emit breakpointChanged();
32}
33
34void BreakpointModel::insertBreakpoint(const Internal::Breakpoint &breakpoint)
35{
36 beginResetModel();
37 auto it = bps.begin();
38 for (; it != bps.end(); ++it) {
39 if (it->breakpoint() == breakpoint) {
40 return;
41 }
42 }
43 contentsValid = true;
44 bps.push_back(BreakpointItem(breakpoint));
45 endResetModel();
46 emit breakpointChanged();
47}
48
49void BreakpointModel::removeBreakpoint(const Internal::Breakpoint &breakpoint)
50{
51 beginResetModel();
52 auto it = bps.begin();
53 for (; it != bps.end();) {
54 if (it->breakpoint() == breakpoint) {
55 it = bps.erase(it);
56 } else {
57 ++it;
58 }
59 }
60 endResetModel();
61 emit breakpointChanged();
62}
63
64void BreakpointModel::setCurrentIndex(int level)
65{
66 if (level == -1 || level == currentIndex)
67 return;
68
69 // Emit changed for previous frame
70 QModelIndex i = index(currentIndex, 0);
71 emit dataChanged(i, i);
72
73 currentIndex = level;
74 emit currentIndexChanged();
75
76 // Emit changed for new frame
77 i = index(currentIndex, 0);
78 emit dataChanged(i, i);
79}
80
81void BreakpointModel::removeAll()
82{
83 beginResetModel();
84 bps.clear();
85 setCurrentIndex(-1);
86 endResetModel();
87}
88
89Internal::Breakpoint BreakpointModel::currentBreakpoint() const
90{
91 if (currentIndex == -1)
92 return Internal::Breakpoint();
93
94 return bps.at(currentIndex).breakpoint();
95}
96
97int BreakpointModel::rowCount(const QModelIndex &parent) const
98{
99 // Since the stack is not a tree, row count is 0 for any valid parent
100 return parent.isValid() ? 0 : (bps.size() + canExpand);
101}
102
103int BreakpointModel::columnCount(const QModelIndex &parent) const
104{
105 return parent.isValid() ? 0 : kStackColumnCount;
106}
107
108QVariant BreakpointModel::data(const QModelIndex &index, int role) const
109{
110 if (!index.isValid() || index.row() >= bps.size() + canExpand)
111 return QVariant();
112
113 if (index.row() == bps.size()) {
114 if (role == Qt::DisplayRole && index.column() == kIndexColumn)
115 return tr("...");
116 if (role == Qt::DisplayRole && index.column() == kFunctionNameColumn)
117 return tr("<More>");
118 if (role == Qt::DecorationRole && index.column() == kIndexColumn)
119 return "";
120 return QVariant();
121 }
122
123 const BreakpointItem &bp = bps.at(index.row());
124 return bp.data(index.row(), index.column(), role);
125}
126
127QVariant BreakpointModel::headerData(int section, Qt::Orientation orient, int role) const
128{
129 if (orient == Qt::Horizontal && role == Qt::DisplayRole) {
130 switch (section) {
131 case kIndexColumn:
132 return tr("Index");
133 case kFunctionNameColumn:
134 return tr("Function");
135 case kFileNameColumn:
136 return tr("File");
137 case kLineNumberColumn:
138 return tr("Line");
139 case kAddressColumn:
140 return tr("Address");
141 };
142 }
143 return QVariant();
144}
145
146bool BreakpointModel::setData(const QModelIndex &idx, const QVariant &data, int role)
147{
148 Q_UNUSED(data)
149 if (role == ItemActivatedRole || role == ItemClickedRole) {
150 setCurrentIndex(idx.row());
151 return true;
152 }
153
154 return false;
155}
156