1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkQtDebugLeaksView.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 #include "vtkQtDebugLeaksView.h"
16 #include "vtkObjectBase.h"
17 #include "vtkQtDebugLeaksModel.h"
18
19 #include <QCheckBox>
20 #include <QDesktopServices>
21 #include <QHBoxLayout>
22 #include <QHeaderView>
23 #include <QItemSelectionModel>
24 #include <QLineEdit>
25 #include <QPushButton>
26 #include <QSortFilterProxyModel>
27 #include <QSplitter>
28 #include <QTableView>
29 #include <QUrl>
30 #include <QVBoxLayout>
31
32 //------------------------------------------------------------------------------
33 class vtkQtDebugLeaksView::qInternal
34 {
35 public:
36 vtkQtDebugLeaksModel* Model;
37 QSortFilterProxyModel* ProxyModel;
38 QTableView* TableView;
39 QTableView* ReferenceTableView;
40 QCheckBox* FilterCheckBox;
41 QLineEdit* FilterLineEdit;
42 };
43
44 //------------------------------------------------------------------------------
vtkQtDebugLeaksView(QWidget * p)45 vtkQtDebugLeaksView::vtkQtDebugLeaksView(QWidget* p)
46 : QWidget(p)
47 {
48 this->Internal = new qInternal;
49
50 this->Internal->Model = new vtkQtDebugLeaksModel(this);
51 this->Internal->ProxyModel = new QSortFilterProxyModel(this->Internal->Model);
52 this->Internal->ProxyModel->setSourceModel(this->Internal->Model);
53 this->Internal->ProxyModel->setDynamicSortFilter(true);
54 this->Internal->ProxyModel->setFilterKeyColumn(0);
55
56 this->Internal->TableView = new QTableView;
57 this->Internal->TableView->setSortingEnabled(true);
58 this->Internal->TableView->setModel(this->Internal->ProxyModel);
59 this->Internal->TableView->setObjectName("ClassTable");
60 this->Internal->ReferenceTableView = new QTableView;
61 this->Internal->ReferenceTableView->setObjectName("ReferenceTable");
62
63 this->Internal->FilterCheckBox = new QCheckBox("Filter RegExp");
64 this->Internal->FilterCheckBox->setChecked(true);
65 this->Internal->FilterLineEdit = new QLineEdit();
66
67 QVBoxLayout* mainLayout = new QVBoxLayout(this);
68 QSplitter* splitter = new QSplitter();
69 QPushButton* filterHelpButton = new QPushButton("RegExp Help");
70 QHBoxLayout* filterLayout = new QHBoxLayout();
71
72 filterLayout->addWidget(this->Internal->FilterCheckBox);
73 filterLayout->addWidget(this->Internal->FilterLineEdit);
74 filterLayout->addWidget(filterHelpButton);
75 mainLayout->addLayout(filterLayout);
76 mainLayout->addWidget(splitter);
77
78 splitter->setOrientation(Qt::Vertical);
79 splitter->addWidget(this->Internal->TableView);
80 splitter->addWidget(this->Internal->ReferenceTableView);
81 QList<int> sizes;
82 sizes << 1 << 0;
83 splitter->setSizes(sizes);
84
85 this->connect(this->Internal->FilterLineEdit, SIGNAL(textChanged(const QString&)),
86 SLOT(onFilterTextChanged(const QString&)));
87
88 this->connect(this->Internal->FilterCheckBox, SIGNAL(stateChanged(int)), SLOT(onFilterToggled()));
89
90 this->connect(filterHelpButton, SIGNAL(clicked()), SLOT(onFilterHelp()));
91
92 vtkQtDebugLeaksView::connect(this->Internal->TableView->selectionModel(),
93 SIGNAL(currentRowChanged(const QModelIndex&, const QModelIndex&)), this,
94 SLOT(onCurrentRowChanged(const QModelIndex&)));
95
96 vtkQtDebugLeaksView::connect(this->Internal->TableView, SIGNAL(doubleClicked(const QModelIndex&)),
97 this, SLOT(onRowDoubleClicked(const QModelIndex&)));
98
99 vtkQtDebugLeaksView::connect(this->Internal->ReferenceTableView,
100 SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(onRowDoubleClicked(const QModelIndex&)));
101
102 this->resize(400, 600);
103 this->setWindowTitle("VTK Debug Leaks View");
104 this->Internal->TableView->setColumnWidth(0, 200);
105 this->Internal->TableView->horizontalHeader()->setStretchLastSection(true);
106 this->Internal->TableView->verticalHeader()->setVisible(false);
107 this->Internal->TableView->setSelectionMode(QAbstractItemView::SingleSelection);
108 this->Internal->TableView->setSelectionBehavior(QAbstractItemView::SelectRows);
109
110 this->Internal->ReferenceTableView->setSelectionMode(QAbstractItemView::SingleSelection);
111 this->Internal->ReferenceTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
112
113 this->setAttribute(Qt::WA_QuitOnClose, false);
114 }
115
116 //------------------------------------------------------------------------------
~vtkQtDebugLeaksView()117 vtkQtDebugLeaksView::~vtkQtDebugLeaksView()
118 {
119 this->Internal->ReferenceTableView->setModel(nullptr);
120 this->Internal->TableView->setModel(nullptr);
121 delete this->Internal->Model;
122 delete this->Internal;
123 }
124
125 //------------------------------------------------------------------------------
model()126 vtkQtDebugLeaksModel* vtkQtDebugLeaksView::model()
127 {
128 return this->Internal->Model;
129 }
130
131 //------------------------------------------------------------------------------
onFilterHelp()132 void vtkQtDebugLeaksView::onFilterHelp()
133 {
134 QDesktopServices::openUrl(QUrl("http://doc.trolltech.com/4.6/qregexp.html#introduction"));
135 }
136
137 //------------------------------------------------------------------------------
onCurrentRowChanged(const QModelIndex & current)138 void vtkQtDebugLeaksView::onCurrentRowChanged(const QModelIndex& current)
139 {
140 QStandardItemModel* newModel = nullptr;
141 QAbstractItemModel* previousModel = this->Internal->ReferenceTableView->model();
142
143 QModelIndex index = this->Internal->ProxyModel->mapToSource(current);
144 if (index.isValid())
145 {
146 QModelIndex classNameIndex = this->Internal->Model->index(index.row(), 0);
147 QString className = this->Internal->Model->data(classNameIndex).toString();
148 newModel = this->Internal->Model->referenceCountModel(className);
149 }
150
151 if (newModel != previousModel)
152 {
153 this->Internal->ReferenceTableView->setModel(newModel);
154 this->Internal->ReferenceTableView->resizeColumnsToContents();
155 this->Internal->ReferenceTableView->horizontalHeader()->setStretchLastSection(true);
156 delete previousModel;
157 }
158 }
159
160 //------------------------------------------------------------------------------
onFilterTextChanged(const QString & text)161 void vtkQtDebugLeaksView::onFilterTextChanged(const QString& text)
162 {
163 if (this->filterEnabled())
164 {
165 #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
166 this->Internal->ProxyModel->setFilterRegularExpression(text);
167 #else
168 this->Internal->ProxyModel->setFilterRegExp(text);
169 #endif
170 }
171 }
172
173 //------------------------------------------------------------------------------
onFilterToggled()174 void vtkQtDebugLeaksView::onFilterToggled()
175 {
176 QString text = this->filterText();
177 if (!this->filterEnabled())
178 {
179 text = "";
180 }
181
182 #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
183 this->Internal->ProxyModel->setFilterRegularExpression(text);
184 #else
185 this->Internal->ProxyModel->setFilterRegExp(text);
186 #endif
187 }
188
189 //------------------------------------------------------------------------------
filterEnabled() const190 bool vtkQtDebugLeaksView::filterEnabled() const
191 {
192 return this->Internal->FilterCheckBox->isChecked();
193 }
194
195 //------------------------------------------------------------------------------
setFilterEnabled(bool value)196 void vtkQtDebugLeaksView::setFilterEnabled(bool value)
197 {
198 this->Internal->FilterCheckBox->setChecked(value);
199 }
200
201 //------------------------------------------------------------------------------
filterText() const202 QString vtkQtDebugLeaksView::filterText() const
203 {
204 return this->Internal->FilterLineEdit->text();
205 }
206
207 //------------------------------------------------------------------------------
setFilterText(const QString & text)208 void vtkQtDebugLeaksView::setFilterText(const QString& text)
209 {
210 this->Internal->FilterLineEdit->setText(text);
211 }
212
213 //------------------------------------------------------------------------------
214 Q_DECLARE_METATYPE(vtkObjectBase*);
215
216 //------------------------------------------------------------------------------
onRowDoubleClicked(const QModelIndex & index)217 void vtkQtDebugLeaksView::onRowDoubleClicked(const QModelIndex& index)
218 {
219 if (index.model() == this->Internal->ReferenceTableView->model())
220 {
221 QModelIndex objectIndex = this->Internal->ReferenceTableView->model()->index(index.row(), 0);
222 QVariant objectVariant =
223 this->Internal->ReferenceTableView->model()->data(objectIndex, Qt::UserRole);
224 vtkObjectBase* object = objectVariant.value<vtkObjectBase*>();
225 this->onObjectDoubleClicked(object);
226 }
227 else
228 {
229 QModelIndex sourceIndex = this->Internal->ProxyModel->mapToSource(index);
230 if (sourceIndex.isValid())
231 {
232 QString className =
233 this->Internal->Model->data(this->Internal->Model->index(sourceIndex.row(), 0)).toString();
234 this->onClassNameDoubleClicked(className);
235 }
236 }
237 }
238
239 //------------------------------------------------------------------------------
onObjectDoubleClicked(vtkObjectBase * object)240 void vtkQtDebugLeaksView::onObjectDoubleClicked(vtkObjectBase* object)
241 {
242 Q_UNUSED(object);
243 }
244
245 //------------------------------------------------------------------------------
onClassNameDoubleClicked(const QString & className)246 void vtkQtDebugLeaksView::onClassNameDoubleClicked(const QString& className)
247 {
248 Q_UNUSED(className);
249 }
250