1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "cppcodemodelinspectordialog.h"
27 #include "ui_cppcodemodelinspectordialog.h"
28 #include "cppeditorwidget.h"
29 #include "cppeditordocument.h"
30
31 #include <coreplugin/editormanager/editormanager.h>
32 #include <coreplugin/icore.h>
33 #include <cpptools/baseeditordocumentprocessor.h>
34 #include <cpptools/cppcodemodelinspectordumper.h>
35 #include <cpptools/cppmodelmanager.h>
36 #include <cpptools/cpptoolsbridge.h>
37 #include <cpptools/cppworkingcopy.h>
38 #include <projectexplorer/projectmacro.h>
39 #include <projectexplorer/project.h>
40
41 #include <cplusplus/CppDocument.h>
42 #include <cplusplus/Overview.h>
43 #include <cplusplus/Token.h>
44 #include <utils/qtcassert.h>
45 #include <utils/fancylineedit.h>
46
47 #include <QAbstractTableModel>
48 #include <QLabel>
49 #include <QLineEdit>
50 #include <QPushButton>
51 #include <QSortFilterProxyModel>
52
53 #include <algorithm>
54 #include <numeric>
55
56 using namespace CPlusPlus;
57 using namespace CppTools;
58 namespace CMI = CppCodeModelInspector;
59
60 namespace {
61
resizeColumns(QTreeView * view)62 template <class T> void resizeColumns(QTreeView *view)
63 {
64 for (int column = 0; column < T::ColumnCount - 1; ++column)
65 view->resizeColumnToContents(column);
66 }
67
currentEditor()68 TextEditor::BaseTextEditor *currentEditor()
69 {
70 return qobject_cast<TextEditor::BaseTextEditor*>(Core::EditorManager::currentEditor());
71 }
72
fileInCurrentEditor()73 QString fileInCurrentEditor()
74 {
75 if (TextEditor::BaseTextEditor *editor = currentEditor())
76 return editor->document()->filePath().toString();
77 return QString();
78 }
79
sizePolicyWithStretchFactor(int stretchFactor)80 QSizePolicy sizePolicyWithStretchFactor(int stretchFactor)
81 {
82 QSizePolicy policy(QSizePolicy::Expanding, QSizePolicy::Expanding);
83 policy.setHorizontalStretch(stretchFactor);
84 return policy;
85 }
86
87 class DepthFinder : public SymbolVisitor {
88 public:
operator ()(const Document::Ptr & document,Symbol * symbol)89 int operator()(const Document::Ptr &document, Symbol *symbol)
90 {
91 m_symbol = symbol;
92 accept(document->globalNamespace());
93 return m_foundDepth;
94 }
95
preVisit(Symbol * symbol)96 bool preVisit(Symbol *symbol) override
97 {
98 if (m_stop)
99 return false;
100
101 if (symbol->asScope()) {
102 ++m_depth;
103 if (symbol == m_symbol) {
104 m_foundDepth = m_depth;
105 m_stop = true;
106 }
107 return true;
108 }
109
110 return false;
111 }
112
postVisit(Symbol * symbol)113 void postVisit(Symbol *symbol) override
114 {
115 if (symbol->asScope())
116 --m_depth;
117 }
118
119 private:
120 Symbol *m_symbol = nullptr;
121 int m_depth = -1;
122 int m_foundDepth = -1;
123 bool m_stop = false;
124 };
125
126 } // anonymous namespace
127
128 namespace CppEditor {
129 namespace Internal {
130
131 // --- FilterableView -----------------------------------------------------------------------------
132
133 class FilterableView : public QWidget
134 {
135 Q_OBJECT
136 public:
137 FilterableView(QWidget *parent);
138
139 void setModel(QAbstractItemModel *model);
140 QItemSelectionModel *selectionModel() const;
141 void selectIndex(const QModelIndex &index);
142 void resizeColumns(int columnCount);
143 void clearFilter();
144
145 signals:
146 void filterChanged(const QString &filterText);
147
148 private:
149 QTreeView *view;
150 Utils::FancyLineEdit *lineEdit;
151 };
152
FilterableView(QWidget * parent)153 FilterableView::FilterableView(QWidget *parent)
154 : QWidget(parent)
155 {
156 view = new QTreeView(this);
157 view->setAlternatingRowColors(true);
158 view->setTextElideMode(Qt::ElideMiddle);
159 view->setSortingEnabled(true);
160
161 lineEdit = new Utils::FancyLineEdit(this);
162 lineEdit->setFiltering(true);
163 lineEdit->setPlaceholderText(QLatin1String("File Path"));
164 QObject::connect(lineEdit, &QLineEdit::textChanged, this, &FilterableView::filterChanged);
165
166 QLabel *label = new QLabel(QLatin1String("&Filter:"), this);
167 label->setBuddy(lineEdit);
168
169 auto filterBarLayout = new QHBoxLayout();
170 filterBarLayout->addWidget(label);
171 filterBarLayout->addWidget(lineEdit);
172
173 auto mainLayout = new QVBoxLayout();
174 mainLayout->addWidget(view);
175 mainLayout->addLayout(filterBarLayout);
176
177 setLayout(mainLayout);
178 }
179
setModel(QAbstractItemModel * model)180 void FilterableView::setModel(QAbstractItemModel *model)
181 {
182 view->setModel(model);
183 }
184
selectionModel() const185 QItemSelectionModel *FilterableView::selectionModel() const
186 {
187 return view->selectionModel();
188 }
189
selectIndex(const QModelIndex & index)190 void FilterableView::selectIndex(const QModelIndex &index)
191 {
192 if (index.isValid()) {
193 view->selectionModel()->setCurrentIndex(index,
194 QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
195 }
196 }
197
resizeColumns(int columnCount)198 void FilterableView::resizeColumns(int columnCount)
199 {
200 for (int column = 0; column < columnCount - 1; ++column)
201 view->resizeColumnToContents(column);
202 }
203
clearFilter()204 void FilterableView::clearFilter()
205 {
206 lineEdit->clear();
207 }
208
209 // --- ProjectFilesModel --------------------------------------------------------------------------
210
211 class ProjectFilesModel : public QAbstractListModel
212 {
213 Q_OBJECT
214 public:
215 ProjectFilesModel(QObject *parent);
216 void configure(const ProjectFiles &files);
217 void clear();
218
219 enum Columns { FileKindColumn, FilePathColumn, ColumnCount };
220
221 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
222 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
223 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
224 QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
225
226 private:
227 ProjectFiles m_files;
228 };
229
ProjectFilesModel(QObject * parent)230 ProjectFilesModel::ProjectFilesModel(QObject *parent) : QAbstractListModel(parent)
231 {
232 }
233
configure(const ProjectFiles & files)234 void ProjectFilesModel::configure(const ProjectFiles &files)
235 {
236 emit layoutAboutToBeChanged();
237 m_files = files;
238 emit layoutChanged();
239 }
240
clear()241 void ProjectFilesModel::clear()
242 {
243 emit layoutAboutToBeChanged();
244 m_files.clear();
245 emit layoutChanged();
246 }
247
rowCount(const QModelIndex &) const248 int ProjectFilesModel::rowCount(const QModelIndex &/*parent*/) const
249 {
250 return m_files.size();
251 }
252
columnCount(const QModelIndex &) const253 int ProjectFilesModel::columnCount(const QModelIndex &/*parent*/) const
254 {
255 return ProjectFilesModel::ColumnCount;
256 }
257
data(const QModelIndex & index,int role) const258 QVariant ProjectFilesModel::data(const QModelIndex &index, int role) const
259 {
260 if (role == Qt::DisplayRole) {
261 const int row = index.row();
262 const int column = index.column();
263 if (column == FileKindColumn) {
264 return CMI::Utils::toString(m_files.at(row).kind);
265 } else if (column == FilePathColumn) {
266 return m_files.at(row).path;
267 }
268 } else if (role == Qt::ForegroundRole) {
269 if (!m_files.at(index.row()).active) {
270 return QApplication::palette().color(QPalette::ColorGroup::Disabled,
271 QPalette::ColorRole::Text);
272 }
273 }
274 return QVariant();
275 }
276
headerData(int section,Qt::Orientation orientation,int role) const277 QVariant ProjectFilesModel::headerData(int section, Qt::Orientation orientation, int role) const
278 {
279 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
280 switch (section) {
281 case FileKindColumn:
282 return QLatin1String("File Kind");
283 case FilePathColumn:
284 return QLatin1String("File Path");
285 default:
286 return QVariant();
287 }
288 }
289 return QVariant();
290 }
291
292 // --- ProjectHeaderPathModel --------------------------------------------------------------------
293
294 class ProjectHeaderPathsModel : public QAbstractListModel
295 {
296 Q_OBJECT
297 public:
298 ProjectHeaderPathsModel(QObject *parent);
299 void configure(const ProjectExplorer::HeaderPaths &paths);
300 void clear();
301
302 enum Columns { TypeColumn, PathColumn, ColumnCount };
303
304 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
305 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
306 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
307 QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
308
309 private:
310 ProjectExplorer::HeaderPaths m_paths;
311 };
312
ProjectHeaderPathsModel(QObject * parent)313 ProjectHeaderPathsModel::ProjectHeaderPathsModel(QObject *parent) : QAbstractListModel(parent)
314 {
315 }
316
configure(const ProjectExplorer::HeaderPaths & paths)317 void ProjectHeaderPathsModel::configure(const ProjectExplorer::HeaderPaths &paths)
318 {
319 emit layoutAboutToBeChanged();
320 m_paths = paths;
321 emit layoutChanged();
322 }
323
clear()324 void ProjectHeaderPathsModel::clear()
325 {
326 emit layoutAboutToBeChanged();
327 m_paths.clear();
328 emit layoutChanged();
329 }
330
rowCount(const QModelIndex &) const331 int ProjectHeaderPathsModel::rowCount(const QModelIndex &/*parent*/) const
332 {
333 return m_paths.size();
334 }
335
columnCount(const QModelIndex &) const336 int ProjectHeaderPathsModel::columnCount(const QModelIndex &/*parent*/) const
337 {
338 return ProjectFilesModel::ColumnCount;
339 }
340
data(const QModelIndex & index,int role) const341 QVariant ProjectHeaderPathsModel::data(const QModelIndex &index, int role) const
342 {
343 if (role == Qt::DisplayRole) {
344 const int row = index.row();
345 const int column = index.column();
346 if (column == TypeColumn) {
347 return CMI::Utils::toString(m_paths.at(row).type);
348 } else if (column == PathColumn) {
349 return m_paths.at(row).path;
350 }
351 }
352 return QVariant();
353 }
354
headerData(int section,Qt::Orientation orientation,int role) const355 QVariant ProjectHeaderPathsModel::headerData(int section, Qt::Orientation orientation, int role) const
356 {
357 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
358 switch (section) {
359 case TypeColumn:
360 return QLatin1String("Type");
361 case PathColumn:
362 return QLatin1String("Path");
363 default:
364 return QVariant();
365 }
366 }
367 return QVariant();
368 }
369
370 // --- KeyValueModel ------------------------------------------------------------------------------
371
372 class KeyValueModel : public QAbstractListModel
373 {
374 Q_OBJECT
375 public:
376 using Table = QList<QPair<QString, QString>>;
377
378 KeyValueModel(QObject *parent);
379 void configure(const Table &table);
380 void clear();
381
382 enum Columns { KeyColumn, ValueColumn, ColumnCount };
383
384 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
385 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
386 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
387 QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
388
389 private:
390 Table m_table;
391 };
392
KeyValueModel(QObject * parent)393 KeyValueModel::KeyValueModel(QObject *parent) : QAbstractListModel(parent)
394 {
395 }
396
configure(const Table & table)397 void KeyValueModel::configure(const Table &table)
398 {
399 emit layoutAboutToBeChanged();
400 m_table = table;
401 emit layoutChanged();
402 }
403
clear()404 void KeyValueModel::clear()
405 {
406 emit layoutAboutToBeChanged();
407 m_table.clear();
408 emit layoutChanged();
409 }
410
rowCount(const QModelIndex &) const411 int KeyValueModel::rowCount(const QModelIndex &/*parent*/) const
412 {
413 return m_table.size();
414 }
415
columnCount(const QModelIndex &) const416 int KeyValueModel::columnCount(const QModelIndex &/*parent*/) const
417 {
418 return KeyValueModel::ColumnCount;
419 }
420
data(const QModelIndex & index,int role) const421 QVariant KeyValueModel::data(const QModelIndex &index, int role) const
422 {
423 if (role == Qt::DisplayRole) {
424 const int row = index.row();
425 const int column = index.column();
426 if (column == KeyColumn) {
427 return m_table.at(row).first;
428 } else if (column == ValueColumn) {
429 return m_table.at(row).second;
430 }
431 }
432 return QVariant();
433 }
434
headerData(int section,Qt::Orientation orientation,int role) const435 QVariant KeyValueModel::headerData(int section, Qt::Orientation orientation, int role) const
436 {
437 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
438 switch (section) {
439 case KeyColumn:
440 return QLatin1String("Key");
441 case ValueColumn:
442 return QLatin1String("Value");
443 default:
444 return QVariant();
445 }
446 }
447 return QVariant();
448 }
449
450 // --- SnapshotModel ------------------------------------------------------------------------------
451
452 class SnapshotModel : public QAbstractListModel
453 {
454 Q_OBJECT
455 public:
456 SnapshotModel(QObject *parent);
457 void configure(const Snapshot &snapshot);
458 void setGlobalSnapshot(const Snapshot &snapshot);
459
460 QModelIndex indexForDocument(const QString &filePath);
461
462 enum Columns { SymbolCountColumn, SharedColumn, FilePathColumn, ColumnCount };
463
464 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
465 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
466 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
467 QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
468
469 private:
470 QList<Document::Ptr> m_documents;
471 Snapshot m_globalSnapshot;
472 };
473
SnapshotModel(QObject * parent)474 SnapshotModel::SnapshotModel(QObject *parent) : QAbstractListModel(parent)
475 {
476 }
477
configure(const Snapshot & snapshot)478 void SnapshotModel::configure(const Snapshot &snapshot)
479 {
480 emit layoutAboutToBeChanged();
481 m_documents = CMI::Utils::snapshotToList(snapshot);
482 emit layoutChanged();
483 }
484
setGlobalSnapshot(const Snapshot & snapshot)485 void SnapshotModel::setGlobalSnapshot(const Snapshot &snapshot)
486 {
487 m_globalSnapshot = snapshot;
488 }
489
indexForDocument(const QString & filePath)490 QModelIndex SnapshotModel::indexForDocument(const QString &filePath)
491 {
492 for (int i = 0, total = m_documents.size(); i < total; ++i) {
493 const Document::Ptr document = m_documents.at(i);
494 if (document->fileName() == filePath)
495 return index(i, FilePathColumn);
496 }
497 return {};
498 }
499
rowCount(const QModelIndex &) const500 int SnapshotModel::rowCount(const QModelIndex &/*parent*/) const
501 {
502 return m_documents.size();
503 }
504
columnCount(const QModelIndex &) const505 int SnapshotModel::columnCount(const QModelIndex &/*parent*/) const
506 {
507 return SnapshotModel::ColumnCount;
508 }
509
data(const QModelIndex & index,int role) const510 QVariant SnapshotModel::data(const QModelIndex &index, int role) const
511 {
512 if (role == Qt::DisplayRole) {
513 const int column = index.column();
514 Document::Ptr document = m_documents.at(index.row());
515 if (column == SymbolCountColumn) {
516 return document->control()->symbolCount();
517 } else if (column == SharedColumn) {
518 Document::Ptr globalDocument = m_globalSnapshot.document(document->fileName());
519 const bool isShared
520 = globalDocument && globalDocument->fingerprint() == document->fingerprint();
521 return CMI::Utils::toString(isShared);
522 } else if (column == FilePathColumn) {
523 return QDir::toNativeSeparators(document->fileName());
524 }
525 }
526 return QVariant();
527 }
528
headerData(int section,Qt::Orientation orientation,int role) const529 QVariant SnapshotModel::headerData(int section, Qt::Orientation orientation, int role) const
530 {
531 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
532 switch (section) {
533 case SymbolCountColumn:
534 return QLatin1String("Symbols");
535 case SharedColumn:
536 return QLatin1String("Shared");
537 case FilePathColumn:
538 return QLatin1String("File Path");
539 default:
540 return QVariant();
541 }
542 }
543 return QVariant();
544 }
545
546 // --- IncludesModel ------------------------------------------------------------------------------
547
includesSorter(const Document::Include & i1,const Document::Include & i2)548 static bool includesSorter(const Document::Include &i1,
549 const Document::Include &i2)
550 {
551 return i1.line() < i2.line();
552 }
553
554 class IncludesModel : public QAbstractListModel
555 {
556 Q_OBJECT
557 public:
558 IncludesModel(QObject *parent);
559 void configure(const QList<Document::Include> &includes);
560 void clear();
561
562 enum Columns { ResolvedOrNotColumn, LineNumberColumn, FilePathsColumn, ColumnCount };
563
564 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
565 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
566 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
567 QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
568
569 private:
570 QList<Document::Include> m_includes;
571 };
572
IncludesModel(QObject * parent)573 IncludesModel::IncludesModel(QObject *parent) : QAbstractListModel(parent)
574 {
575 }
576
configure(const QList<Document::Include> & includes)577 void IncludesModel::configure(const QList<Document::Include> &includes)
578 {
579 emit layoutAboutToBeChanged();
580 m_includes = includes;
581 std::stable_sort(m_includes.begin(), m_includes.end(), includesSorter);
582 emit layoutChanged();
583 }
584
clear()585 void IncludesModel::clear()
586 {
587 emit layoutAboutToBeChanged();
588 m_includes.clear();
589 emit layoutChanged();
590 }
591
rowCount(const QModelIndex &) const592 int IncludesModel::rowCount(const QModelIndex &/*parent*/) const
593 {
594 return m_includes.size();
595 }
596
columnCount(const QModelIndex &) const597 int IncludesModel::columnCount(const QModelIndex &/*parent*/) const
598 {
599 return IncludesModel::ColumnCount;
600 }
601
data(const QModelIndex & index,int role) const602 QVariant IncludesModel::data(const QModelIndex &index, int role) const
603 {
604 if (role != Qt::DisplayRole && role != Qt::ForegroundRole)
605 return QVariant();
606
607 static const QBrush greenBrush(QColor(0, 139, 69));
608 static const QBrush redBrush(QColor(205, 38, 38));
609
610 const Document::Include include = m_includes.at(index.row());
611 const QString resolvedFileName = QDir::toNativeSeparators(include.resolvedFileName());
612 const bool isResolved = !resolvedFileName.isEmpty();
613
614 if (role == Qt::DisplayRole) {
615 const int column = index.column();
616 if (column == ResolvedOrNotColumn) {
617 return CMI::Utils::toString(isResolved);
618 } else if (column == LineNumberColumn) {
619 return include.line();
620 } else if (column == FilePathsColumn) {
621 return QVariant(CMI::Utils::unresolvedFileNameWithDelimiters(include)
622 + QLatin1String(" --> ") + resolvedFileName);
623 }
624 } else if (role == Qt::ForegroundRole) {
625 return isResolved ? greenBrush : redBrush;
626 }
627
628 return QVariant();
629 }
630
headerData(int section,Qt::Orientation orientation,int role) const631 QVariant IncludesModel::headerData(int section, Qt::Orientation orientation, int role) const
632 {
633 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
634 switch (section) {
635 case ResolvedOrNotColumn:
636 return QLatin1String("Resolved");
637 case LineNumberColumn:
638 return QLatin1String("Line");
639 case FilePathsColumn:
640 return QLatin1String("File Paths");
641 default:
642 return QVariant();
643 }
644 }
645 return QVariant();
646 }
647
648 // --- DiagnosticMessagesModel --------------------------------------------------------------------
649
diagnosticMessagesModelSorter(const Document::DiagnosticMessage & m1,const Document::DiagnosticMessage & m2)650 static bool diagnosticMessagesModelSorter(const Document::DiagnosticMessage &m1,
651 const Document::DiagnosticMessage &m2)
652 {
653 return m1.line() < m2.line();
654 }
655
656 class DiagnosticMessagesModel : public QAbstractListModel
657 {
658 Q_OBJECT
659 public:
660 DiagnosticMessagesModel(QObject *parent);
661 void configure(const QList<Document::DiagnosticMessage> &messages);
662 void clear();
663
664 enum Columns { LevelColumn, LineColumnNumberColumn, MessageColumn, ColumnCount };
665
666 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
667 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
668 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
669 QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
670
671 private:
672 QList<Document::DiagnosticMessage> m_messages;
673 };
674
DiagnosticMessagesModel(QObject * parent)675 DiagnosticMessagesModel::DiagnosticMessagesModel(QObject *parent) : QAbstractListModel(parent)
676 {
677 }
678
configure(const QList<Document::DiagnosticMessage> & messages)679 void DiagnosticMessagesModel::configure(
680 const QList<Document::DiagnosticMessage> &messages)
681 {
682 emit layoutAboutToBeChanged();
683 m_messages = messages;
684 std::stable_sort(m_messages.begin(), m_messages.end(), diagnosticMessagesModelSorter);
685 emit layoutChanged();
686 }
687
clear()688 void DiagnosticMessagesModel::clear()
689 {
690 emit layoutAboutToBeChanged();
691 m_messages.clear();
692 emit layoutChanged();
693 }
694
rowCount(const QModelIndex &) const695 int DiagnosticMessagesModel::rowCount(const QModelIndex &/*parent*/) const
696 {
697 return m_messages.size();
698 }
699
columnCount(const QModelIndex &) const700 int DiagnosticMessagesModel::columnCount(const QModelIndex &/*parent*/) const
701 {
702 return DiagnosticMessagesModel::ColumnCount;
703 }
704
data(const QModelIndex & index,int role) const705 QVariant DiagnosticMessagesModel::data(const QModelIndex &index, int role) const
706 {
707 if (role != Qt::DisplayRole && role != Qt::ForegroundRole)
708 return QVariant();
709
710 static const QBrush yellowOrangeBrush(QColor(237, 145, 33));
711 static const QBrush redBrush(QColor(205, 38, 38));
712 static const QBrush darkRedBrushQColor(QColor(139, 0, 0));
713
714 const Document::DiagnosticMessage message = m_messages.at(index.row());
715 const auto level = static_cast<Document::DiagnosticMessage::Level>(message.level());
716
717 if (role == Qt::DisplayRole) {
718 const int column = index.column();
719 if (column == LevelColumn) {
720 return CMI::Utils::toString(level);
721 } else if (column == LineColumnNumberColumn) {
722 return QVariant(QString::number(message.line()) + QLatin1Char(':')
723 + QString::number(message.column()));
724 } else if (column == MessageColumn) {
725 return message.text();
726 }
727 } else if (role == Qt::ForegroundRole) {
728 switch (level) {
729 case Document::DiagnosticMessage::Warning:
730 return yellowOrangeBrush;
731 case Document::DiagnosticMessage::Error:
732 return redBrush;
733 case Document::DiagnosticMessage::Fatal:
734 return darkRedBrushQColor;
735 default:
736 return QVariant();
737 }
738 }
739
740 return QVariant();
741 }
742
headerData(int section,Qt::Orientation orientation,int role) const743 QVariant DiagnosticMessagesModel::headerData(int section, Qt::Orientation orientation, int role)
744 const
745 {
746 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
747 switch (section) {
748 case LevelColumn:
749 return QLatin1String("Level");
750 case LineColumnNumberColumn:
751 return QLatin1String("Line:Column");
752 case MessageColumn:
753 return QLatin1String("Message");
754 default:
755 return QVariant();
756 }
757 }
758 return QVariant();
759 }
760
761 // --- MacrosModel --------------------------------------------------------------------------------
762
763 class MacrosModel : public QAbstractListModel
764 {
765 Q_OBJECT
766 public:
767 MacrosModel(QObject *parent);
768 void configure(const QList<CPlusPlus::Macro> ¯os);
769 void clear();
770
771 enum Columns { LineNumberColumn, MacroColumn, ColumnCount };
772
773 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
774 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
775 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
776 QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
777
778 private:
779 QList<CPlusPlus::Macro> m_macros;
780 };
781
MacrosModel(QObject * parent)782 MacrosModel::MacrosModel(QObject *parent) : QAbstractListModel(parent)
783 {
784 }
785
configure(const QList<CPlusPlus::Macro> & macros)786 void MacrosModel::configure(const QList<CPlusPlus::Macro> ¯os)
787 {
788 emit layoutAboutToBeChanged();
789 m_macros = macros;
790 emit layoutChanged();
791 }
792
clear()793 void MacrosModel::clear()
794 {
795 emit layoutAboutToBeChanged();
796 m_macros.clear();
797 emit layoutChanged();
798 }
799
rowCount(const QModelIndex &) const800 int MacrosModel::rowCount(const QModelIndex &/*parent*/) const
801 {
802 return m_macros.size();
803 }
804
columnCount(const QModelIndex &) const805 int MacrosModel::columnCount(const QModelIndex &/*parent*/) const
806 {
807 return MacrosModel::ColumnCount;
808 }
809
data(const QModelIndex & index,int role) const810 QVariant MacrosModel::data(const QModelIndex &index, int role) const
811 {
812 const int column = index.column();
813 if (role == Qt::DisplayRole || (role == Qt::ToolTipRole && column == MacroColumn)) {
814 const CPlusPlus::Macro macro = m_macros.at(index.row());
815 if (column == LineNumberColumn)
816 return macro.line();
817 else if (column == MacroColumn)
818 return macro.toString();
819 } else if (role == Qt::TextAlignmentRole) {
820 return QVariant::fromValue(Qt::AlignTop | Qt::AlignLeft);
821 }
822 return QVariant();
823 }
824
headerData(int section,Qt::Orientation orientation,int role) const825 QVariant MacrosModel::headerData(int section, Qt::Orientation orientation, int role) const
826 {
827 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
828 switch (section) {
829 case LineNumberColumn:
830 return QLatin1String("Line");
831 case MacroColumn:
832 return QLatin1String("Macro");
833 default:
834 return QVariant();
835 }
836 }
837 return QVariant();
838 }
839
840 // --- SymbolsModel -------------------------------------------------------------------------------
841
842 class SymbolsModel : public QAbstractItemModel
843 {
844 Q_OBJECT
845 public:
846 SymbolsModel(QObject *parent);
847 void configure(const Document::Ptr &document);
848 void clear();
849
850 enum Columns { SymbolColumn, LineNumberColumn, ColumnCount };
851
852 QModelIndex index(int row, int column, const QModelIndex &parent) const override;
853 QModelIndex parent(const QModelIndex &child) const override;
854 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
855 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
856 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
857 QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
858
859 private:
860 Document::Ptr m_document;
861 };
862
SymbolsModel(QObject * parent)863 SymbolsModel::SymbolsModel(QObject *parent) : QAbstractItemModel(parent)
864 {
865 }
866
configure(const Document::Ptr & document)867 void SymbolsModel::configure(const Document::Ptr &document)
868 {
869 QTC_CHECK(document);
870 emit layoutAboutToBeChanged();
871 m_document = document;
872 emit layoutChanged();
873 }
874
clear()875 void SymbolsModel::clear()
876 {
877 emit layoutAboutToBeChanged();
878 m_document.clear();
879 emit layoutChanged();
880 }
881
indexToSymbol(const QModelIndex & index)882 static Symbol *indexToSymbol(const QModelIndex &index)
883 {
884 return static_cast<Symbol*>(index.internalPointer());
885 }
886
indexToScope(const QModelIndex & index)887 static Scope *indexToScope(const QModelIndex &index)
888 {
889 if (Symbol *symbol = indexToSymbol(index))
890 return symbol->asScope();
891 return nullptr;
892 }
893
index(int row,int column,const QModelIndex & parent) const894 QModelIndex SymbolsModel::index(int row, int column, const QModelIndex &parent) const
895 {
896 Scope *scope = nullptr;
897 if (parent.isValid())
898 scope = indexToScope(parent);
899 else if (m_document)
900 scope = m_document->globalNamespace();
901
902 if (scope) {
903 if (row < scope->memberCount())
904 return createIndex(row, column, scope->memberAt(row));
905 }
906
907 return {};
908 }
909
parent(const QModelIndex & child) const910 QModelIndex SymbolsModel::parent(const QModelIndex &child) const
911 {
912 if (!child.isValid())
913 return {};
914
915 if (Symbol *symbol = indexToSymbol(child)) {
916 if (Scope *scope = symbol->enclosingScope()) {
917 const int row = DepthFinder()(m_document, scope);
918 return createIndex(row, 0, scope);
919 }
920 }
921
922 return {};
923 }
924
rowCount(const QModelIndex & parent) const925 int SymbolsModel::rowCount(const QModelIndex &parent) const
926 {
927 if (parent.isValid()) {
928 if (Scope *scope = indexToScope(parent))
929 return scope->memberCount();
930 } else {
931 if (m_document)
932 return m_document->globalNamespace()->memberCount();
933 }
934 return 0;
935 }
936
columnCount(const QModelIndex &) const937 int SymbolsModel::columnCount(const QModelIndex &) const
938 {
939 return ColumnCount;
940 }
941
data(const QModelIndex & index,int role) const942 QVariant SymbolsModel::data(const QModelIndex &index, int role) const
943 {
944 const int column = index.column();
945 if (role == Qt::DisplayRole) {
946 Symbol *symbol = indexToSymbol(index);
947 if (!symbol)
948 return QVariant();
949 if (column == LineNumberColumn) {
950 return symbol->line();
951 } else if (column == SymbolColumn) {
952 QString name = Overview().prettyName(symbol->name());
953 if (name.isEmpty())
954 name = QLatin1String(symbol->isBlock() ? "<block>" : "<no name>");
955 return name;
956 }
957 }
958 return QVariant();
959 }
960
headerData(int section,Qt::Orientation orientation,int role) const961 QVariant SymbolsModel::headerData(int section, Qt::Orientation orientation, int role) const
962 {
963 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
964 switch (section) {
965 case SymbolColumn:
966 return QLatin1String("Symbol");
967 case LineNumberColumn:
968 return QLatin1String("Line");
969 default:
970 return QVariant();
971 }
972 }
973 return QVariant();
974 }
975
976 // --- TokensModel --------------------------------------------------------------------------------
977
978 class TokensModel : public QAbstractListModel
979 {
980 Q_OBJECT
981 public:
982 TokensModel(QObject *parent);
983 void configure(TranslationUnit *translationUnit);
984 void clear();
985
986 enum Columns { SpelledColumn, KindColumn, IndexColumn, OffsetColumn, LineColumnNumberColumn,
987 BytesAndCodePointsColumn, GeneratedColumn, ExpandedColumn, WhiteSpaceColumn,
988 NewlineColumn, ColumnCount };
989
990 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
991 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
992 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
993 QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
994
995 private:
996 struct TokenInfo {
997 Token token;
998 int line;
999 int column;
1000 };
1001 QList<TokenInfo> m_tokenInfos;
1002 };
1003
TokensModel(QObject * parent)1004 TokensModel::TokensModel(QObject *parent) : QAbstractListModel(parent)
1005 {
1006 }
1007
configure(TranslationUnit * translationUnit)1008 void TokensModel::configure(TranslationUnit *translationUnit)
1009 {
1010 if (!translationUnit)
1011 return;
1012
1013 emit layoutAboutToBeChanged();
1014 m_tokenInfos.clear();
1015 for (int i = 0, total = translationUnit->tokenCount(); i < total; ++i) {
1016 TokenInfo info;
1017 info.token = translationUnit->tokenAt(i);
1018 translationUnit->getPosition(info.token.utf16charsBegin(), &info.line, &info.column);
1019 m_tokenInfos.append(info);
1020 }
1021 emit layoutChanged();
1022 }
1023
clear()1024 void TokensModel::clear()
1025 {
1026 emit layoutAboutToBeChanged();
1027 m_tokenInfos.clear();
1028 emit layoutChanged();
1029 }
1030
rowCount(const QModelIndex &) const1031 int TokensModel::rowCount(const QModelIndex &/*parent*/) const
1032 {
1033 return m_tokenInfos.size();
1034 }
1035
columnCount(const QModelIndex &) const1036 int TokensModel::columnCount(const QModelIndex &/*parent*/) const
1037 {
1038 return TokensModel::ColumnCount;
1039 }
1040
data(const QModelIndex & index,int role) const1041 QVariant TokensModel::data(const QModelIndex &index, int role) const
1042 {
1043 const int column = index.column();
1044 if (role == Qt::DisplayRole) {
1045 const TokenInfo info = m_tokenInfos.at(index.row());
1046 const Token token = info.token;
1047 if (column == SpelledColumn)
1048 return QString::fromUtf8(token.spell());
1049 else if (column == KindColumn)
1050 return CMI::Utils::toString(static_cast<Kind>(token.kind()));
1051 else if (column == IndexColumn)
1052 return index.row();
1053 else if (column == OffsetColumn)
1054 return token.bytesBegin();
1055 else if (column == LineColumnNumberColumn)
1056 return QString::fromLatin1("%1:%2").arg(CMI::Utils::toString(info.line),
1057 CMI::Utils::toString(info.column));
1058 else if (column == BytesAndCodePointsColumn)
1059 return QString::fromLatin1("%1/%2").arg(CMI::Utils::toString(token.bytes()),
1060 CMI::Utils::toString(token.utf16chars()));
1061 else if (column == GeneratedColumn)
1062 return CMI::Utils::toString(token.generated());
1063 else if (column == ExpandedColumn)
1064 return CMI::Utils::toString(token.expanded());
1065 else if (column == WhiteSpaceColumn)
1066 return CMI::Utils::toString(token.whitespace());
1067 else if (column == NewlineColumn)
1068 return CMI::Utils::toString(token.newline());
1069 } else if (role == Qt::TextAlignmentRole) {
1070 return QVariant::fromValue(Qt::AlignTop | Qt::AlignLeft);
1071 }
1072 return QVariant();
1073 }
1074
headerData(int section,Qt::Orientation orientation,int role) const1075 QVariant TokensModel::headerData(int section, Qt::Orientation orientation, int role) const
1076 {
1077 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
1078 switch (section) {
1079 case SpelledColumn:
1080 return QLatin1String("Spelled");
1081 case KindColumn:
1082 return QLatin1String("Kind");
1083 case IndexColumn:
1084 return QLatin1String("Index");
1085 case OffsetColumn:
1086 return QLatin1String("Offset");
1087 case LineColumnNumberColumn:
1088 return QLatin1String("Line:Column");
1089 case BytesAndCodePointsColumn:
1090 return QLatin1String("Bytes/Codepoints");
1091 case GeneratedColumn:
1092 return QLatin1String("Generated");
1093 case ExpandedColumn:
1094 return QLatin1String("Expanded");
1095 case WhiteSpaceColumn:
1096 return QLatin1String("Whitespace");
1097 case NewlineColumn:
1098 return QLatin1String("Newline");
1099 default:
1100 return QVariant();
1101 }
1102 }
1103 return QVariant();
1104 }
1105
1106 // --- ProjectPartsModel --------------------------------------------------------------------------
1107
1108 class ProjectPartsModel : public QAbstractListModel
1109 {
1110 Q_OBJECT
1111 public:
1112 ProjectPartsModel(QObject *parent);
1113
1114 void configure(const QList<ProjectInfo> &projectInfos,
1115 const ProjectPart::Ptr ¤tEditorsProjectPart);
1116
1117 QModelIndex indexForCurrentEditorsProjectPart() const;
1118 ProjectPart::Ptr projectPartForProjectId(const QString &projectPartId) const;
1119
1120 enum Columns { PartNameColumn, PartFilePathColumn, ColumnCount };
1121
1122 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
1123 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
1124 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
1125 QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
1126
1127 private:
1128 QList<ProjectPart::Ptr> m_projectPartsList;
1129 int m_currentEditorsProjectPartIndex;
1130 };
1131
ProjectPartsModel(QObject * parent)1132 ProjectPartsModel::ProjectPartsModel(QObject *parent)
1133 : QAbstractListModel(parent), m_currentEditorsProjectPartIndex(-1)
1134 {
1135 }
1136
configure(const QList<ProjectInfo> & projectInfos,const ProjectPart::Ptr & currentEditorsProjectPart)1137 void ProjectPartsModel::configure(const QList<ProjectInfo> &projectInfos,
1138 const ProjectPart::Ptr ¤tEditorsProjectPart)
1139 {
1140 emit layoutAboutToBeChanged();
1141 m_projectPartsList.clear();
1142 foreach (const ProjectInfo &info, projectInfos) {
1143 foreach (const ProjectPart::Ptr &projectPart, info.projectParts()) {
1144 if (!m_projectPartsList.contains(projectPart)) {
1145 m_projectPartsList << projectPart;
1146 if (projectPart == currentEditorsProjectPart)
1147 m_currentEditorsProjectPartIndex = m_projectPartsList.size() - 1;
1148 }
1149 }
1150 }
1151 emit layoutChanged();
1152 }
1153
indexForCurrentEditorsProjectPart() const1154 QModelIndex ProjectPartsModel::indexForCurrentEditorsProjectPart() const
1155 {
1156 if (m_currentEditorsProjectPartIndex == -1)
1157 return {};
1158 return createIndex(m_currentEditorsProjectPartIndex, PartFilePathColumn);
1159 }
1160
projectPartForProjectId(const QString & projectPartId) const1161 ProjectPart::Ptr ProjectPartsModel::projectPartForProjectId(const QString &projectPartId) const
1162 {
1163 foreach (const ProjectPart::Ptr &part, m_projectPartsList) {
1164 if (part->id() == projectPartId)
1165 return part;
1166 }
1167 return ProjectPart::Ptr();
1168 }
1169
rowCount(const QModelIndex &) const1170 int ProjectPartsModel::rowCount(const QModelIndex &/*parent*/) const
1171 {
1172 return m_projectPartsList.size();
1173 }
1174
columnCount(const QModelIndex &) const1175 int ProjectPartsModel::columnCount(const QModelIndex &/*parent*/) const
1176 {
1177 return ProjectPartsModel::ColumnCount;
1178 }
1179
data(const QModelIndex & index,int role) const1180 QVariant ProjectPartsModel::data(const QModelIndex &index, int role) const
1181 {
1182 const int row = index.row();
1183 if (role == Qt::DisplayRole) {
1184 const int column = index.column();
1185 if (column == PartNameColumn)
1186 return m_projectPartsList.at(row)->displayName;
1187 else if (column == PartFilePathColumn)
1188 return QDir::toNativeSeparators(m_projectPartsList.at(row)->projectFile);
1189 } else if (role == Qt::ForegroundRole) {
1190 if (!m_projectPartsList.at(row)->selectedForBuilding) {
1191 return QApplication::palette().color(QPalette::ColorGroup::Disabled,
1192 QPalette::ColorRole::Text);
1193 }
1194 } else if (role == Qt::UserRole) {
1195 return m_projectPartsList.at(row)->id();
1196 }
1197 return QVariant();
1198 }
1199
headerData(int section,Qt::Orientation orientation,int role) const1200 QVariant ProjectPartsModel::headerData(int section, Qt::Orientation orientation, int role) const
1201 {
1202 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
1203 switch (section) {
1204 case PartNameColumn:
1205 return QLatin1String("Name");
1206 case PartFilePathColumn:
1207 return QLatin1String("Project File Path");
1208 default:
1209 return QVariant();
1210 }
1211 }
1212 return QVariant();
1213 }
1214
1215 // --- WorkingCopyModel ---------------------------------------------------------------------------
1216
1217 class WorkingCopyModel : public QAbstractListModel
1218 {
1219 Q_OBJECT
1220 public:
1221 WorkingCopyModel(QObject *parent);
1222
1223 void configure(const WorkingCopy &workingCopy);
1224 QModelIndex indexForFile(const QString &filePath);
1225
1226 enum Columns { RevisionColumn, FilePathColumn, ColumnCount };
1227
1228 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
1229 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
1230 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
1231 QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
1232
1233 private:
1234 struct WorkingCopyEntry {
WorkingCopyEntryCppEditor::Internal::WorkingCopyModel::WorkingCopyEntry1235 WorkingCopyEntry(const QString &filePath, const QByteArray &source, unsigned revision)
1236 : filePath(filePath), source(source), revision(revision)
1237 {}
1238
1239 QString filePath;
1240 QByteArray source;
1241 unsigned revision;
1242 };
1243
1244 QList<WorkingCopyEntry> m_workingCopyList;
1245 };
1246
WorkingCopyModel(QObject * parent)1247 WorkingCopyModel::WorkingCopyModel(QObject *parent) : QAbstractListModel(parent)
1248 {
1249 }
1250
configure(const WorkingCopy & workingCopy)1251 void WorkingCopyModel::configure(const WorkingCopy &workingCopy)
1252 {
1253 emit layoutAboutToBeChanged();
1254 m_workingCopyList.clear();
1255 const WorkingCopy::Table &elements = workingCopy.elements();
1256 for (auto it = elements.cbegin(), end = elements.cend(); it != end; ++it) {
1257 m_workingCopyList << WorkingCopyEntry(it.key().toString(), it.value().first,
1258 it.value().second);
1259 }
1260 emit layoutChanged();
1261 }
1262
indexForFile(const QString & filePath)1263 QModelIndex WorkingCopyModel::indexForFile(const QString &filePath)
1264 {
1265 for (int i = 0, total = m_workingCopyList.size(); i < total; ++i) {
1266 const WorkingCopyEntry entry = m_workingCopyList.at(i);
1267 if (entry.filePath == filePath)
1268 return index(i, FilePathColumn);
1269 }
1270 return {};
1271 }
1272
rowCount(const QModelIndex &) const1273 int WorkingCopyModel::rowCount(const QModelIndex &/*parent*/) const
1274 {
1275 return m_workingCopyList.size();
1276 }
1277
columnCount(const QModelIndex &) const1278 int WorkingCopyModel::columnCount(const QModelIndex &/*parent*/) const
1279 {
1280 return WorkingCopyModel::ColumnCount;
1281 }
1282
data(const QModelIndex & index,int role) const1283 QVariant WorkingCopyModel::data(const QModelIndex &index, int role) const
1284 {
1285 const int row = index.row();
1286 if (role == Qt::DisplayRole) {
1287 const int column = index.column();
1288 if (column == RevisionColumn)
1289 return m_workingCopyList.at(row).revision;
1290 else if (column == FilePathColumn)
1291 return m_workingCopyList.at(row).filePath;
1292 } else if (role == Qt::UserRole) {
1293 return m_workingCopyList.at(row).source;
1294 }
1295 return QVariant();
1296 }
1297
headerData(int section,Qt::Orientation orientation,int role) const1298 QVariant WorkingCopyModel::headerData(int section, Qt::Orientation orientation, int role) const
1299 {
1300 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
1301 switch (section) {
1302 case RevisionColumn:
1303 return QLatin1String("Revision");
1304 case FilePathColumn:
1305 return QLatin1String("File Path");
1306 default:
1307 return QVariant();
1308 }
1309 }
1310 return QVariant();
1311 }
1312
1313 // --- SnapshotInfo -------------------------------------------------------------------------------
1314
1315 class SnapshotInfo
1316 {
1317 public:
1318 enum Type { GlobalSnapshot, EditorSnapshot };
SnapshotInfo(const Snapshot & snapshot,Type type)1319 SnapshotInfo(const Snapshot &snapshot, Type type)
1320 : snapshot(snapshot), type(type) {}
1321
1322 Snapshot snapshot;
1323 Type type;
1324 };
1325
1326 // --- CppCodeModelInspectorDialog ----------------------------------------------------------------
1327
CppCodeModelInspectorDialog(QWidget * parent)1328 CppCodeModelInspectorDialog::CppCodeModelInspectorDialog(QWidget *parent)
1329 : QDialog(parent)
1330 , m_ui(new Ui::CppCodeModelInspectorDialog)
1331 , m_snapshotInfos(new QList<SnapshotInfo>())
1332 , m_snapshotView(new FilterableView(this))
1333 , m_snapshotModel(new SnapshotModel(this))
1334 , m_proxySnapshotModel(new QSortFilterProxyModel(this))
1335 , m_docGenericInfoModel(new KeyValueModel(this))
1336 , m_docIncludesModel(new IncludesModel(this))
1337 , m_docDiagnosticMessagesModel(new DiagnosticMessagesModel(this))
1338 , m_docMacrosModel(new MacrosModel(this))
1339 , m_docSymbolsModel(new SymbolsModel(this))
1340 , m_docTokensModel(new TokensModel(this))
1341 , m_projectPartsView(new FilterableView(this))
1342 , m_projectPartsModel(new ProjectPartsModel(this))
1343 , m_proxyProjectPartsModel(new QSortFilterProxyModel(this))
1344 , m_partGenericInfoModel(new KeyValueModel(this))
1345 , m_projectFilesModel(new ProjectFilesModel(this))
1346 , m_projectHeaderPathsModel(new ProjectHeaderPathsModel(this))
1347 , m_workingCopyView(new FilterableView(this))
1348 , m_workingCopyModel(new WorkingCopyModel(this))
1349 , m_proxyWorkingCopyModel(new QSortFilterProxyModel(this))
1350 {
1351 m_ui->setupUi(this);
1352 m_ui->snapshotSelectorAndViewLayout->addWidget(m_snapshotView);
1353 m_ui->projectPartsSplitter->insertWidget(0, m_projectPartsView);
1354 m_ui->workingCopySplitter->insertWidget(0, m_workingCopyView);
1355
1356 setAttribute(Qt::WA_DeleteOnClose);
1357 connect(Core::ICore::instance(), &Core::ICore::coreAboutToClose, this, &QWidget::close);
1358
1359 m_ui->partGeneralView->setSizePolicy(sizePolicyWithStretchFactor(2));
1360 m_ui->partGeneralCompilerFlagsEdit->setSizePolicy(sizePolicyWithStretchFactor(1));
1361
1362 m_proxySnapshotModel->setSourceModel(m_snapshotModel);
1363 m_proxySnapshotModel->setFilterKeyColumn(SnapshotModel::FilePathColumn);
1364 m_snapshotView->setModel(m_proxySnapshotModel);
1365 m_ui->docGeneralView->setModel(m_docGenericInfoModel);
1366 m_ui->docIncludesView->setModel(m_docIncludesModel);
1367 m_ui->docDiagnosticMessagesView->setModel(m_docDiagnosticMessagesModel);
1368 m_ui->docDefinedMacrosView->setModel(m_docMacrosModel);
1369 m_ui->docSymbolsView->setModel(m_docSymbolsModel);
1370 m_ui->docTokensView->setModel(m_docTokensModel);
1371
1372 m_proxyProjectPartsModel->setSourceModel(m_projectPartsModel);
1373 m_proxyProjectPartsModel->setFilterKeyColumn(ProjectPartsModel::PartFilePathColumn);
1374 m_projectPartsView->setModel(m_proxyProjectPartsModel);
1375 m_ui->partGeneralView->setModel(m_partGenericInfoModel);
1376 m_ui->projectFilesView->setModel(m_projectFilesModel);
1377 m_ui->projectHeaderPathsView->setModel(m_projectHeaderPathsModel);
1378
1379 m_proxyWorkingCopyModel->setSourceModel(m_workingCopyModel);
1380 m_proxyWorkingCopyModel->setFilterKeyColumn(WorkingCopyModel::FilePathColumn);
1381 m_workingCopyView->setModel(m_proxyWorkingCopyModel);
1382
1383 connect(m_snapshotView->selectionModel(),
1384 &QItemSelectionModel::currentRowChanged,
1385 this, &CppCodeModelInspectorDialog::onDocumentSelected);
1386 connect(m_snapshotView, &FilterableView::filterChanged,
1387 this, &CppCodeModelInspectorDialog::onSnapshotFilterChanged);
1388 connect(m_ui->snapshotSelector,
1389 QOverload<int>::of(&QComboBox::currentIndexChanged),
1390 this, &CppCodeModelInspectorDialog::onSnapshotSelected);
1391 connect(m_ui->docSymbolsView, &QTreeView::expanded,
1392 this, &CppCodeModelInspectorDialog::onSymbolsViewExpandedOrCollapsed);
1393 connect(m_ui->docSymbolsView, &QTreeView::collapsed,
1394 this, &CppCodeModelInspectorDialog::onSymbolsViewExpandedOrCollapsed);
1395
1396 connect(m_projectPartsView->selectionModel(),
1397 &QItemSelectionModel::currentRowChanged,
1398 this, &CppCodeModelInspectorDialog::onProjectPartSelected);
1399 connect(m_projectPartsView, &FilterableView::filterChanged,
1400 this, &CppCodeModelInspectorDialog::onProjectPartFilterChanged);
1401
1402 connect(m_workingCopyView->selectionModel(),
1403 &QItemSelectionModel::currentRowChanged,
1404 this, &CppCodeModelInspectorDialog::onWorkingCopyDocumentSelected);
1405 connect(m_workingCopyView, &FilterableView::filterChanged,
1406 this, &CppCodeModelInspectorDialog::onWorkingCopyFilterChanged);
1407
1408 connect(m_ui->refreshButton, &QAbstractButton::clicked, this, &CppCodeModelInspectorDialog::onRefreshRequested);
1409 connect(m_ui->closeButton, &QAbstractButton::clicked, this, &QWidget::close);
1410
1411 refresh();
1412 }
1413
~CppCodeModelInspectorDialog()1414 CppCodeModelInspectorDialog::~CppCodeModelInspectorDialog()
1415 {
1416 delete m_snapshotInfos;
1417 delete m_ui;
1418 }
1419
onRefreshRequested()1420 void CppCodeModelInspectorDialog::onRefreshRequested()
1421 {
1422 refresh();
1423 }
1424
onSnapshotFilterChanged(const QString & pattern)1425 void CppCodeModelInspectorDialog::onSnapshotFilterChanged(const QString &pattern)
1426 {
1427 m_proxySnapshotModel->setFilterWildcard(pattern);
1428 }
1429
onSnapshotSelected(int row)1430 void CppCodeModelInspectorDialog::onSnapshotSelected(int row)
1431 {
1432 if (row < 0 || row >= m_snapshotInfos->size())
1433 return;
1434
1435 m_snapshotView->clearFilter();
1436 const SnapshotInfo info = m_snapshotInfos->at(row);
1437 m_snapshotModel->configure(info.snapshot);
1438 m_snapshotView->resizeColumns(SnapshotModel::ColumnCount);
1439
1440 if (info.type == SnapshotInfo::GlobalSnapshot) {
1441 // Select first document
1442 const QModelIndex index = m_proxySnapshotModel->index(0, SnapshotModel::FilePathColumn);
1443 m_snapshotView->selectIndex(index);
1444 } else if (info.type == SnapshotInfo::EditorSnapshot) {
1445 // Select first document, unless we can find the editor document
1446 QModelIndex index = m_snapshotModel->indexForDocument(fileInCurrentEditor());
1447 index = m_proxySnapshotModel->mapFromSource(index);
1448 if (!index.isValid())
1449 index = m_proxySnapshotModel->index(0, SnapshotModel::FilePathColumn);
1450 m_snapshotView->selectIndex(index);
1451 }
1452 }
1453
onDocumentSelected(const QModelIndex & current,const QModelIndex &)1454 void CppCodeModelInspectorDialog::onDocumentSelected(const QModelIndex ¤t,
1455 const QModelIndex &)
1456 {
1457 if (current.isValid()) {
1458 const QModelIndex index = m_proxySnapshotModel->index(current.row(),
1459 SnapshotModel::FilePathColumn);
1460 const QString filePath = QDir::fromNativeSeparators(
1461 m_proxySnapshotModel->data(index, Qt::DisplayRole).toString());
1462 const SnapshotInfo info = m_snapshotInfos->at(m_ui->snapshotSelector->currentIndex());
1463 updateDocumentData(info.snapshot.document(filePath));
1464 } else {
1465 clearDocumentData();
1466 }
1467 }
1468
onSymbolsViewExpandedOrCollapsed(const QModelIndex &)1469 void CppCodeModelInspectorDialog::onSymbolsViewExpandedOrCollapsed(const QModelIndex &)
1470 {
1471 resizeColumns<SymbolsModel>(m_ui->docSymbolsView);
1472 }
1473
onProjectPartFilterChanged(const QString & pattern)1474 void CppCodeModelInspectorDialog::onProjectPartFilterChanged(const QString &pattern)
1475 {
1476 m_proxyProjectPartsModel->setFilterWildcard(pattern);
1477 }
1478
onProjectPartSelected(const QModelIndex & current,const QModelIndex &)1479 void CppCodeModelInspectorDialog::onProjectPartSelected(const QModelIndex ¤t,
1480 const QModelIndex &)
1481 {
1482 if (current.isValid()) {
1483 QModelIndex index = m_proxyProjectPartsModel->mapToSource(current);
1484 if (index.isValid()) {
1485 index = m_projectPartsModel->index(index.row(), ProjectPartsModel::PartFilePathColumn);
1486 const QString projectPartId = m_projectPartsModel->data(index, Qt::UserRole).toString();
1487 updateProjectPartData(m_projectPartsModel->projectPartForProjectId(projectPartId));
1488 }
1489 } else {
1490 clearProjectPartData();
1491 }
1492 }
1493
onWorkingCopyFilterChanged(const QString & pattern)1494 void CppCodeModelInspectorDialog::onWorkingCopyFilterChanged(const QString &pattern)
1495 {
1496 m_proxyWorkingCopyModel->setFilterWildcard(pattern);
1497 }
1498
onWorkingCopyDocumentSelected(const QModelIndex & current,const QModelIndex &)1499 void CppCodeModelInspectorDialog::onWorkingCopyDocumentSelected(const QModelIndex ¤t,
1500 const QModelIndex &)
1501 {
1502 if (current.isValid()) {
1503 const QModelIndex index = m_proxyWorkingCopyModel->mapToSource(current);
1504 if (index.isValid()) {
1505 const QString source
1506 = QString::fromUtf8(m_workingCopyModel->data(index, Qt::UserRole).toByteArray());
1507 m_ui->workingCopySourceEdit->setPlainText(source);
1508 }
1509 } else {
1510 m_ui->workingCopySourceEdit->clear();
1511 }
1512 }
1513
refresh()1514 void CppCodeModelInspectorDialog::refresh()
1515 {
1516 CppModelManager *cmmi = CppModelManager::instance();
1517
1518 const int oldSnapshotIndex = m_ui->snapshotSelector->currentIndex();
1519 const bool selectEditorRelevant
1520 = m_ui->selectEditorRelevantEntriesAfterRefreshCheckBox->isChecked();
1521
1522 // Snapshots and Documents
1523 m_snapshotInfos->clear();
1524 m_ui->snapshotSelector->clear();
1525
1526 const Snapshot globalSnapshot = cmmi->snapshot();
1527 CppCodeModelInspector::Dumper dumper(globalSnapshot);
1528 m_snapshotModel->setGlobalSnapshot(globalSnapshot);
1529
1530 m_snapshotInfos->append(SnapshotInfo(globalSnapshot, SnapshotInfo::GlobalSnapshot));
1531 const QString globalSnapshotTitle
1532 = QString::fromLatin1("Global/Indexing Snapshot (%1 Documents)").arg(globalSnapshot.size());
1533 m_ui->snapshotSelector->addItem(globalSnapshotTitle);
1534 dumper.dumpSnapshot(globalSnapshot, globalSnapshotTitle, /*isGlobalSnapshot=*/ true);
1535
1536 TextEditor::BaseTextEditor *editor = currentEditor();
1537 CppTools::CppEditorDocumentHandle *cppEditorDocument = nullptr;
1538 if (editor) {
1539 const QString editorFilePath = editor->document()->filePath().toString();
1540 cppEditorDocument = cmmi->cppEditorDocument(editorFilePath);
1541 if (auto documentProcessor = CppToolsBridge::baseEditorDocumentProcessor(editorFilePath)) {
1542 const Snapshot editorSnapshot = documentProcessor->snapshot();
1543 m_snapshotInfos->append(SnapshotInfo(editorSnapshot, SnapshotInfo::EditorSnapshot));
1544 const QString editorSnapshotTitle
1545 = QString::fromLatin1("Current Editor's Snapshot (%1 Documents)")
1546 .arg(editorSnapshot.size());
1547 dumper.dumpSnapshot(editorSnapshot, editorSnapshotTitle);
1548 m_ui->snapshotSelector->addItem(editorSnapshotTitle);
1549 }
1550 auto cppEditorWidget = qobject_cast<CppEditorWidget *>(editor->editorWidget());
1551 if (cppEditorWidget) {
1552 SemanticInfo semanticInfo = cppEditorWidget->semanticInfo();
1553 Snapshot snapshot;
1554
1555 // Add semantic info snapshot
1556 snapshot = semanticInfo.snapshot;
1557 m_snapshotInfos->append(SnapshotInfo(snapshot, SnapshotInfo::EditorSnapshot));
1558 m_ui->snapshotSelector->addItem(
1559 QString::fromLatin1("Current Editor's Semantic Info Snapshot (%1 Documents)")
1560 .arg(snapshot.size()));
1561
1562 // Add a pseudo snapshot containing only the semantic info document since this document
1563 // is not part of the semantic snapshot.
1564 snapshot = Snapshot();
1565 snapshot.insert(cppEditorWidget->semanticInfo().doc);
1566 m_snapshotInfos->append(SnapshotInfo(snapshot, SnapshotInfo::EditorSnapshot));
1567 const QString snapshotTitle
1568 = QString::fromLatin1("Current Editor's Pseudo Snapshot with Semantic Info Document (%1 Documents)")
1569 .arg(snapshot.size());
1570 dumper.dumpSnapshot(snapshot, snapshotTitle);
1571 m_ui->snapshotSelector->addItem(snapshotTitle);
1572 }
1573 }
1574
1575 int snapshotIndex = 0;
1576 if (selectEditorRelevant) {
1577 for (int i = 0, total = m_snapshotInfos->size(); i < total; ++i) {
1578 const SnapshotInfo info = m_snapshotInfos->at(i);
1579 if (info.type == SnapshotInfo::EditorSnapshot) {
1580 snapshotIndex = i;
1581 break;
1582 }
1583 }
1584 } else if (oldSnapshotIndex < m_snapshotInfos->size()) {
1585 snapshotIndex = oldSnapshotIndex;
1586 }
1587 m_ui->snapshotSelector->setCurrentIndex(snapshotIndex);
1588 onSnapshotSelected(snapshotIndex);
1589
1590 // Project Parts
1591 const ProjectPart::Ptr editorsProjectPart = cppEditorDocument
1592 ? cppEditorDocument->processor()->parser()->projectPartInfo().projectPart
1593 : ProjectPart::Ptr();
1594
1595 const QList<ProjectInfo> projectInfos = cmmi->projectInfos();
1596 dumper.dumpProjectInfos(projectInfos);
1597 m_projectPartsModel->configure(projectInfos, editorsProjectPart);
1598 m_projectPartsView->resizeColumns(ProjectPartsModel::ColumnCount);
1599 QModelIndex index = m_proxyProjectPartsModel->index(0, ProjectPartsModel::PartFilePathColumn);
1600 if (index.isValid()) {
1601 if (selectEditorRelevant && editorsProjectPart) {
1602 QModelIndex editorPartIndex = m_projectPartsModel->indexForCurrentEditorsProjectPart();
1603 editorPartIndex = m_proxyProjectPartsModel->mapFromSource(editorPartIndex);
1604 if (editorPartIndex.isValid())
1605 index = editorPartIndex;
1606 }
1607 m_projectPartsView->selectIndex(index);
1608 }
1609
1610 // Working Copy
1611 const WorkingCopy workingCopy = cmmi->workingCopy();
1612 dumper.dumpWorkingCopy(workingCopy);
1613 m_workingCopyModel->configure(workingCopy);
1614 m_workingCopyView->resizeColumns(WorkingCopyModel::ColumnCount);
1615 if (workingCopy.size() > 0) {
1616 QModelIndex index = m_proxyWorkingCopyModel->index(0, WorkingCopyModel::FilePathColumn);
1617 if (selectEditorRelevant) {
1618 const QModelIndex eindex = m_workingCopyModel->indexForFile(fileInCurrentEditor());
1619 if (eindex.isValid())
1620 index = m_proxyWorkingCopyModel->mapFromSource(eindex);
1621 }
1622 m_workingCopyView->selectIndex(index);
1623 }
1624
1625 // Merged entities
1626 dumper.dumpMergedEntities(cmmi->headerPaths(),
1627 ProjectExplorer::Macro::toByteArray(cmmi->definedMacros()));
1628 }
1629
1630 enum DocumentTabs {
1631 DocumentGeneralTab,
1632 DocumentIncludesTab,
1633 DocumentDiagnosticsTab,
1634 DocumentDefinedMacrosTab,
1635 DocumentPreprocessedSourceTab,
1636 DocumentSymbolsTab,
1637 DocumentTokensTab
1638 };
1639
docTabName(int tabIndex,int numberOfEntries=-1)1640 static QString docTabName(int tabIndex, int numberOfEntries = -1)
1641 {
1642 const char *names[] = {
1643 "&General",
1644 "&Includes",
1645 "&Diagnostic Messages",
1646 "(Un)Defined &Macros",
1647 "P&reprocessed Source",
1648 "&Symbols",
1649 "&Tokens"
1650 };
1651 QString result = QLatin1String(names[tabIndex]);
1652 if (numberOfEntries != -1)
1653 result += QString::fromLatin1(" (%1)").arg(numberOfEntries);
1654 return result;
1655 }
1656
clearDocumentData()1657 void CppCodeModelInspectorDialog::clearDocumentData()
1658 {
1659 m_docGenericInfoModel->clear();
1660
1661 m_ui->docTab->setTabText(DocumentIncludesTab, docTabName(DocumentIncludesTab));
1662 m_docIncludesModel->clear();
1663
1664 m_ui->docTab->setTabText(DocumentDiagnosticsTab, docTabName(DocumentDiagnosticsTab));
1665 m_docDiagnosticMessagesModel->clear();
1666
1667 m_ui->docTab->setTabText(DocumentDefinedMacrosTab, docTabName(DocumentDefinedMacrosTab));
1668 m_docMacrosModel->clear();
1669
1670 m_ui->docPreprocessedSourceEdit->clear();
1671
1672 m_docSymbolsModel->clear();
1673
1674 m_ui->docTab->setTabText(DocumentTokensTab, docTabName(DocumentTokensTab));
1675 m_docTokensModel->clear();
1676 }
1677
updateDocumentData(const Document::Ptr & document)1678 void CppCodeModelInspectorDialog::updateDocumentData(const Document::Ptr &document)
1679 {
1680 QTC_ASSERT(document, return);
1681
1682 // General
1683 const KeyValueModel::Table table = {
1684 {QString::fromLatin1("File Path"), QDir::toNativeSeparators(document->fileName())},
1685 {QString::fromLatin1("Last Modified"), CMI::Utils::toString(document->lastModified())},
1686 {QString::fromLatin1("Revision"), CMI::Utils::toString(document->revision())},
1687 {QString::fromLatin1("Editor Revision"), CMI::Utils::toString(document->editorRevision())},
1688 {QString::fromLatin1("Check Mode"), CMI::Utils::toString(document->checkMode())},
1689 {QString::fromLatin1("Tokenized"), CMI::Utils::toString(document->isTokenized())},
1690 {QString::fromLatin1("Parsed"), CMI::Utils::toString(document->isParsed())},
1691 {QString::fromLatin1("Project Parts"), CMI::Utils::partsForFile(document->fileName())}
1692 };
1693 m_docGenericInfoModel->configure(table);
1694 resizeColumns<KeyValueModel>(m_ui->docGeneralView);
1695
1696 // Includes
1697 m_docIncludesModel->configure(document->resolvedIncludes() + document->unresolvedIncludes());
1698 resizeColumns<IncludesModel>(m_ui->docIncludesView);
1699 m_ui->docTab->setTabText(DocumentIncludesTab,
1700 docTabName(DocumentIncludesTab, m_docIncludesModel->rowCount()));
1701
1702 // Diagnostic Messages
1703 m_docDiagnosticMessagesModel->configure(document->diagnosticMessages());
1704 resizeColumns<DiagnosticMessagesModel>(m_ui->docDiagnosticMessagesView);
1705 m_ui->docTab->setTabText(DocumentDiagnosticsTab,
1706 docTabName(DocumentDiagnosticsTab, m_docDiagnosticMessagesModel->rowCount()));
1707
1708 // Macros
1709 m_docMacrosModel->configure(document->definedMacros());
1710 resizeColumns<MacrosModel>(m_ui->docDefinedMacrosView);
1711 m_ui->docTab->setTabText(DocumentDefinedMacrosTab,
1712 docTabName(DocumentDefinedMacrosTab, m_docMacrosModel->rowCount()));
1713
1714 // Source
1715 m_ui->docPreprocessedSourceEdit->setPlainText(QString::fromUtf8(document->utf8Source()));
1716
1717 // Symbols
1718 m_docSymbolsModel->configure(document);
1719 resizeColumns<SymbolsModel>(m_ui->docSymbolsView);
1720
1721 // Tokens
1722 m_docTokensModel->configure(document->translationUnit());
1723 resizeColumns<TokensModel>(m_ui->docTokensView);
1724 m_ui->docTab->setTabText(DocumentTokensTab,
1725 docTabName(DocumentTokensTab, m_docTokensModel->rowCount()));
1726 }
1727
1728 enum ProjectPartTabs {
1729 ProjectPartGeneralTab,
1730 ProjectPartFilesTab,
1731 ProjectPartDefinesTab,
1732 ProjectPartHeaderPathsTab,
1733 ProjectPartPrecompiledHeadersTab
1734 };
1735
partTabName(int tabIndex,int numberOfEntries=-1)1736 static QString partTabName(int tabIndex, int numberOfEntries = -1)
1737 {
1738 const char *names[] = {
1739 "&General",
1740 "Project &Files",
1741 "&Defines",
1742 "&Header Paths",
1743 "Pre&compiled Headers"
1744 };
1745 QString result = QLatin1String(names[tabIndex]);
1746 if (numberOfEntries != -1)
1747 result += QString::fromLatin1(" (%1)").arg(numberOfEntries);
1748 return result;
1749 }
1750
clearProjectPartData()1751 void CppCodeModelInspectorDialog::clearProjectPartData()
1752 {
1753 m_partGenericInfoModel->clear();
1754 m_projectFilesModel->clear();
1755 m_projectHeaderPathsModel->clear();
1756
1757 m_ui->projectPartTab->setTabText(ProjectPartFilesTab, partTabName(ProjectPartFilesTab));
1758
1759 m_ui->partToolchainDefinesEdit->clear();
1760 m_ui->partProjectDefinesEdit->clear();
1761 m_ui->projectPartTab->setTabText(ProjectPartDefinesTab, partTabName(ProjectPartDefinesTab));
1762
1763 m_ui->projectPartTab->setTabText(ProjectPartHeaderPathsTab,
1764 partTabName(ProjectPartHeaderPathsTab));
1765
1766 m_ui->partPrecompiledHeadersEdit->clear();
1767 m_ui->projectPartTab->setTabText(ProjectPartPrecompiledHeadersTab,
1768 partTabName(ProjectPartPrecompiledHeadersTab));
1769 }
1770
defineCount(const ProjectExplorer::Macros & macros)1771 static int defineCount(const ProjectExplorer::Macros ¯os)
1772 {
1773 using ProjectExplorer::Macro;
1774 return int(std::count_if(
1775 macros.begin(),
1776 macros.end(),
1777 [](const Macro ¯o) { return macro.type == ProjectExplorer::MacroType::Define; }));
1778 }
1779
updateProjectPartData(const ProjectPart::Ptr & part)1780 void CppCodeModelInspectorDialog::updateProjectPartData(const ProjectPart::Ptr &part)
1781 {
1782 QTC_ASSERT(part, return);
1783
1784 // General
1785 QString projectName = QLatin1String("<None>");
1786 QString projectFilePath = QLatin1String("<None>");
1787 if (ProjectExplorer::Project *project = part->project) {
1788 projectName = project->displayName();
1789 projectFilePath = project->projectFilePath().toUserOutput();
1790 }
1791 const QString callGroupId = part->callGroupId.isEmpty() ? QString::fromLatin1("<None>")
1792 : part->callGroupId;
1793 const QString buildSystemTarget
1794 = part->buildSystemTarget.isEmpty() ? QString::fromLatin1("<None>")
1795 : part->buildSystemTarget;
1796
1797 const QString precompiledHeaders = part->precompiledHeaders.isEmpty()
1798 ? QString::fromLatin1("<None>")
1799 : part->precompiledHeaders.join(',');
1800
1801 KeyValueModel::Table table = {
1802 {QString::fromLatin1("Project Part Name"), part->displayName},
1803 {QString::fromLatin1("Project Part File"), part->projectFileLocation()},
1804 {QString::fromLatin1("Project Name"), projectName},
1805 {QString::fromLatin1("Project File"), projectFilePath},
1806 {QString::fromLatin1("Callgroup Id"), callGroupId},
1807 {QString::fromLatin1("Precompiled Headers"), precompiledHeaders},
1808 {QString::fromLatin1("Selected For Building"), CMI::Utils::toString(part->selectedForBuilding)},
1809 {QString::fromLatin1("Buildsystem Target"), buildSystemTarget},
1810 {QString::fromLatin1("Build Target Type"), CMI::Utils::toString(part->buildTargetType)},
1811 {QString::fromLatin1("ToolChain Type"), part->toolchainType.toString()},
1812 {QString::fromLatin1("ToolChain Target Triple"), part->toolChainTargetTriple},
1813 {QString::fromLatin1("ToolChain Word Width"), CMI::Utils::toString(part->toolChainWordWidth)},
1814 {QString::fromLatin1("ToolChain Install Dir"), part->toolChainInstallDir.toString()},
1815 {QString::fromLatin1("Language Version"), CMI::Utils::toString(part->languageVersion)},
1816 {QString::fromLatin1("Language Extensions"), CMI::Utils::toString(part->languageExtensions)},
1817 {QString::fromLatin1("Qt Version"), CMI::Utils::toString(part->qtVersion)}
1818 };
1819 if (!part->projectConfigFile.isEmpty())
1820 table.prepend({QString::fromLatin1("Project Config File"), part->projectConfigFile});
1821 m_partGenericInfoModel->configure(table);
1822 resizeColumns<KeyValueModel>(m_ui->partGeneralView);
1823
1824 // Compiler Flags
1825 m_ui->partGeneralCompilerFlagsEdit->setPlainText(part->compilerFlags.join("\n"));
1826
1827 // Project Files
1828 m_projectFilesModel->configure(part->files);
1829 m_ui->projectPartTab->setTabText(ProjectPartFilesTab,
1830 partTabName(ProjectPartFilesTab, part->files.size()));
1831
1832 int numberOfDefines = defineCount(part->toolChainMacros) + defineCount(part->projectMacros);
1833
1834 m_ui->partToolchainDefinesEdit->setPlainText(QString::fromUtf8(ProjectExplorer::Macro::toByteArray(part->toolChainMacros)));
1835 m_ui->partProjectDefinesEdit->setPlainText(QString::fromUtf8(ProjectExplorer::Macro::toByteArray(part->projectMacros)));
1836 m_ui->projectPartTab->setTabText(ProjectPartDefinesTab,
1837 partTabName(ProjectPartDefinesTab, numberOfDefines));
1838
1839 // Header Paths
1840 m_projectHeaderPathsModel->configure(part->headerPaths);
1841 m_ui->projectPartTab->setTabText(ProjectPartHeaderPathsTab,
1842 partTabName(ProjectPartHeaderPathsTab, part->headerPaths.size()));
1843
1844 // Precompiled Headers
1845 m_ui->partPrecompiledHeadersEdit->setPlainText(
1846 CMI::Utils::pathListToString(part->precompiledHeaders));
1847 m_ui->projectPartTab->setTabText(ProjectPartPrecompiledHeadersTab,
1848 partTabName(ProjectPartPrecompiledHeadersTab, part->precompiledHeaders.size()));
1849 }
1850
event(QEvent * e)1851 bool CppCodeModelInspectorDialog::event(QEvent *e)
1852 {
1853 if (e->type() == QEvent::ShortcutOverride) {
1854 auto ke = static_cast<QKeyEvent *>(e);
1855 if (ke->key() == Qt::Key_Escape && !ke->modifiers()) {
1856 ke->accept();
1857 close();
1858 return false;
1859 }
1860 }
1861 return QDialog::event(e);
1862 }
1863
1864 } // namespace Internal
1865 } // namespace CppEditor
1866
1867 #include "cppcodemodelinspectordialog.moc"
1868