32DeclContextView::DeclContextView(QWidget *parent) : QWidget(parent) {
33 setObjectName(
"declContextView");
34 setAttribute(Qt::WA_StyledBackground,
true);
38void DeclContextView::setupUI() {
39 auto *layout =
new QVBoxLayout(
this);
40 layout->setContentsMargins(4, 4, 4, 4);
41 layout->setSpacing(4);
44 semanticLabel_ =
new QLabel(tr(
"Semantic Context"),
this);
45 layout->addWidget(semanticLabel_);
47 semanticTree_ =
new QTreeWidget(
this);
48 semanticTree_->setHeaderHidden(
true);
49 semanticTree_->setRootIsDecorated(
true);
50 semanticTree_->setAnimated(
false);
51 semanticTree_->setUniformRowHeights(
true);
52 semanticTree_->setIndentation(16);
53 semanticTree_->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
54 semanticTree_->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
55 semanticTree_->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
56 semanticTree_->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
57 semanticTree_->header()->setStretchLastSection(
false);
58 semanticTree_->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
59 layout->addWidget(semanticTree_, 1);
62 auto *separator =
new QFrame(
this);
63 separator->setFrameShape(QFrame::HLine);
64 separator->setFrameShadow(QFrame::Sunken);
65 layout->addWidget(separator);
68 lexicalLabel_ =
new QLabel(tr(
"Lexical Context"),
this);
69 layout->addWidget(lexicalLabel_);
71 lexicalTree_ =
new QTreeWidget(
this);
72 lexicalTree_->setHeaderHidden(
true);
73 lexicalTree_->setRootIsDecorated(
true);
74 lexicalTree_->setAnimated(
false);
75 lexicalTree_->setUniformRowHeights(
true);
76 lexicalTree_->setIndentation(16);
77 lexicalTree_->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
78 lexicalTree_->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
79 lexicalTree_->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
80 lexicalTree_->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
81 lexicalTree_->header()->setStretchLastSection(
false);
82 lexicalTree_->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
83 layout->addWidget(lexicalTree_, 1);
86 connect(semanticTree_, &QTreeWidget::currentItemChanged,
this,
87 &DeclContextView::onContextItemChanged);
88 connect(lexicalTree_, &QTreeWidget::currentItemChanged,
this,
89 &DeclContextView::onContextItemChanged);
99 populateContextHierarchy(node);
103 semanticTree_->clear();
104 lexicalTree_->clear();
108 semanticTree_->setFocus();
112 lexicalTree_->setFocus();
117 semanticLabel_->setFont(font);
118 lexicalLabel_->setFont(font);
119 semanticTree_->setFont(font);
120 lexicalTree_->setFont(font);
123void DeclContextView::populateContextHierarchy(
AstViewNode *node) {
131 bool isDecl = props.contains(
"isDecl") && props.at(
"isDecl").is_boolean() &&
132 props.at(
"isDecl").get<
bool>();
143 if (props.contains(
"semanticDeclContext") &&
144 props.at(
"semanticDeclContext").is_array()) {
145 semantic = &props.at(
"semanticDeclContext");
147 if (props.contains(
"lexicalDeclContext") &&
148 props.at(
"lexicalDeclContext").is_array()) {
149 lexical = &props.at(
"lexicalDeclContext");
152 populateContextTree(semanticTree_, semantic,
true);
153 populateContextTree(lexicalTree_, lexical,
true);
155 semanticTree_->expandAll();
156 lexicalTree_->expandAll();
159void DeclContextView::showNotApplicable() {
160 auto *semanticItem =
new QTreeWidgetItem({tr(
"Not applicable.")});
161 semanticItem->setForeground(0, QColor(128, 128, 128));
162 semanticTree_->addTopLevelItem(semanticItem);
164 auto *lexicalItem =
new QTreeWidgetItem({tr(
"Not applicable.")});
165 lexicalItem->setForeground(0, QColor(128, 128, 128));
166 lexicalTree_->addTopLevelItem(lexicalItem);
169void DeclContextView::populateContextTree(QTreeWidget *tree,
170 const AcavJson *contextArray,
171 bool highlightLast) {
176 if (!contextArray || contextArray->empty()) {
181 QTreeWidgetItem *parentItem =
nullptr;
182 const int count =
static_cast<int>(contextArray->size());
183 for (
int i = 0; i < count; ++i) {
184 const auto &entry = contextArray->at(i);
185 if (!entry.is_object()) {
189 QString kind = tr(
"(Unknown)");
191 if (entry.contains(
"kind") && entry.at(
"kind").is_string()) {
192 kind = QString::fromStdString(
193 entry.at(
"kind").get<InternedString>().str());
195 if (entry.contains(
"name") && entry.at(
"name").is_string()) {
196 name = QString::fromStdString(
197 entry.at(
"name").get<InternedString>().str());
200 QString display = name.isEmpty() ? kind : QString(
"%1 %2").arg(kind, name);
201 auto *item =
new QTreeWidgetItem({display});
202 applyKindStyling(item, kind);
205 if (entry.contains(
"nodePtr") && entry.at(
"nodePtr").is_number_unsigned()) {
206 auto ptr = entry.at(
"nodePtr").get<uint64_t>();
207 item->setData(0, Qt::UserRole, QVariant::fromValue(ptr));
210 const bool isSelected = highlightLast && i == count - 1;
212 QFont font = item->font(0);
214 item->setFont(0, font);
218 parentItem->addChild(item);
220 tree->addTopLevelItem(item);
224 tree->setCurrentItem(item);
225 item->setSelected(
true);
232void DeclContextView::onContextItemChanged(QTreeWidgetItem *current,
233 QTreeWidgetItem *previous) {
239 QVariant data = current->data(0, Qt::UserRole);
240 if (!data.isValid()) {
244 auto ptr = data.value<uint64_t>();
249 auto *node =
reinterpret_cast<AstViewNode *
>(ptr);
250 emit contextNodeClicked(node);
253void DeclContextView::applyKindStyling(QTreeWidgetItem *item,
254 const QString &kind)
const {
255 if (kind ==
"TranslationUnitDecl") {
256 item->setForeground(0, QColor(100, 100, 100));
257 }
else if (kind ==
"NamespaceDecl") {
258 item->setForeground(0, QColor(0, 100, 0));
259 }
else if (kind.contains(
"Record") || kind.contains(
"Class")) {
260 item->setForeground(0, QColor(0, 0, 150));
261 }
else if (kind.contains(
"Function") || kind.contains(
"Method") ||
262 kind.contains(
"Constructor") || kind.contains(
"Destructor")) {
263 item->setForeground(0, QColor(150, 0, 150));
264 }
else if (kind ==
"EnumDecl") {
265 item->setForeground(0, QColor(150, 100, 0));
nlohmann::basic_json< std::map, std::vector, InternedString, bool, int64_t, uint64_t, double, std::allocator, nlohmann::adl_serializer, std::vector< uint8_t > > AcavJson
Custom JSON type using InternedString for automatic string deduplication.
Declaration context hierarchy display panel.
Memory-efficient immutable string with automatic deduplication.
Represents node in AST tree hierarchy.
const AcavJson & getProperties() const
Get node properties (delegates to data node).
void clear()
Clear the display.
void applyFont(const QFont &font)
Propagate font to all internal widgets (labels + trees).
void focusLexicalTree()
Set focus to lexical context tree.
void setSelectedNode(AstViewNode *node)
Update display for selected node.
void focusSemanticTree()
Set focus to semantic context tree.