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 "vtkQtDebugLeaksModel.h"
17 #include "vtkObjectBase.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 <QVBoxLayout>
30 #include <QUrl>
31
32 //-----------------------------------------------------------------------------
33 class vtkQtDebugLeaksView::qInternal
34 {
35 public:
36
37 vtkQtDebugLeaksModel* Model;
38 QSortFilterProxyModel* ProxyModel;
39 QTableView* TableView;
40 QTableView* ReferenceTableView;
41 QCheckBox* FilterCheckBox;
42 QLineEdit* FilterLineEdit;
43 };
44
45 //----------------------------------------------------------------------------
vtkQtDebugLeaksView(QWidget * p)46 vtkQtDebugLeaksView::vtkQtDebugLeaksView(QWidget *p) : 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)),
89 SLOT(onFilterToggled()));
90
91 this->connect(filterHelpButton, SIGNAL(clicked()), SLOT(onFilterHelp()));
92
93 this->connect(this->Internal->TableView->selectionModel(),
94 SIGNAL(currentRowChanged(const QModelIndex&, const QModelIndex&)),
95 this, SLOT(onCurrentRowChanged(const QModelIndex&)));
96
97 this->connect(this->Internal->TableView,
98 SIGNAL(doubleClicked(const QModelIndex&)),
99 this, SLOT(onRowDoubleClicked(const QModelIndex&)));
100
101 this->connect(this->Internal->ReferenceTableView,
102 SIGNAL(doubleClicked(const QModelIndex&)),
103 this, SLOT(onRowDoubleClicked(const QModelIndex&)));
104
105 this->resize(400, 600);
106 this->setWindowTitle("VTK Debug Leaks View");
107 this->Internal->TableView->setColumnWidth(0, 200);
108 this->Internal->TableView->horizontalHeader()->setStretchLastSection(true);
109 this->Internal->TableView->verticalHeader()->setVisible(false);
110 this->Internal->TableView->setSelectionMode(QAbstractItemView::SingleSelection);
111 this->Internal->TableView->setSelectionBehavior(QAbstractItemView::SelectRows);
112
113 this->Internal->ReferenceTableView->setSelectionMode(QAbstractItemView::SingleSelection);
114 this->Internal->ReferenceTableView->setSelectionBehavior(QAbstractItemView::SelectRows);
115
116 this->setAttribute(Qt::WA_QuitOnClose, false);
117 }
118
119 //-----------------------------------------------------------------------------
~vtkQtDebugLeaksView()120 vtkQtDebugLeaksView::~vtkQtDebugLeaksView()
121 {
122 this->Internal->ReferenceTableView->setModel(0);
123 this->Internal->TableView->setModel(0);
124 delete this->Internal->Model;
125 delete this->Internal;
126 }
127
128 //-----------------------------------------------------------------------------
model()129 vtkQtDebugLeaksModel* vtkQtDebugLeaksView::model()
130 {
131 return this->Internal->Model;
132 }
133
134 //-----------------------------------------------------------------------------
onFilterHelp()135 void vtkQtDebugLeaksView::onFilterHelp()
136 {
137 QDesktopServices::openUrl(QUrl("http://doc.trolltech.com/4.6/qregexp.html#introduction"));
138 }
139
140 //-----------------------------------------------------------------------------
onCurrentRowChanged(const QModelIndex & current)141 void vtkQtDebugLeaksView::onCurrentRowChanged(const QModelIndex& current)
142 {
143 QStandardItemModel* newModel = 0;
144 QAbstractItemModel* previousModel = this->Internal->ReferenceTableView->model();
145
146 QModelIndex index = this->Internal->ProxyModel->mapToSource(current);
147 if (index.isValid())
148 {
149 QModelIndex classNameIndex = this->Internal->Model->index(index.row(), 0);
150 QString className = this->Internal->Model->data(classNameIndex).toString();
151 newModel = this->Internal->Model->referenceCountModel(className);
152 }
153
154 if (newModel != previousModel)
155 {
156 this->Internal->ReferenceTableView->setModel(newModel);
157 this->Internal->ReferenceTableView->resizeColumnsToContents();
158 this->Internal->ReferenceTableView->horizontalHeader()->setStretchLastSection(true);
159 delete previousModel;
160 }
161 }
162
163 //-----------------------------------------------------------------------------
onFilterTextChanged(const QString & text)164 void vtkQtDebugLeaksView::onFilterTextChanged(const QString& text)
165 {
166 if (this->filterEnabled())
167 {
168 this->Internal->ProxyModel->setFilterRegExp(text);
169 }
170 }
171
172 //-----------------------------------------------------------------------------
onFilterToggled()173 void vtkQtDebugLeaksView::onFilterToggled()
174 {
175 QString text = this->filterText();
176 if (!this->filterEnabled())
177 {
178 text = "";
179 }
180
181 this->Internal->ProxyModel->setFilterRegExp(text);
182 }
183
184 //-----------------------------------------------------------------------------
filterEnabled() const185 bool vtkQtDebugLeaksView::filterEnabled() const
186 {
187 return this->Internal->FilterCheckBox->isChecked();
188 }
189
190 //-----------------------------------------------------------------------------
setFilterEnabled(bool value)191 void vtkQtDebugLeaksView::setFilterEnabled(bool value)
192 {
193 this->Internal->FilterCheckBox->setChecked(value);
194 }
195
196 //-----------------------------------------------------------------------------
filterText() const197 QString vtkQtDebugLeaksView::filterText() const
198 {
199 return this->Internal->FilterLineEdit->text();
200 }
201
202 //-----------------------------------------------------------------------------
setFilterText(const QString & text)203 void vtkQtDebugLeaksView::setFilterText(const QString& text)
204 {
205 this->Internal->FilterLineEdit->setText(text);
206 }
207
208 //-----------------------------------------------------------------------------
209 Q_DECLARE_METATYPE(vtkObjectBase*);
210
211 //-----------------------------------------------------------------------------
onRowDoubleClicked(const QModelIndex & index)212 void vtkQtDebugLeaksView::onRowDoubleClicked(const QModelIndex& index)
213 {
214 if (index.model() == this->Internal->ReferenceTableView->model())
215 {
216 QModelIndex objectIndex = this->Internal->ReferenceTableView->model()->index(index.row(), 0);
217 QVariant objectVariant = this->Internal->ReferenceTableView->model()->data(objectIndex, Qt::UserRole);
218 vtkObjectBase* object = objectVariant.value<vtkObjectBase*>();
219 this->onObjectDoubleClicked(object);
220 }
221 else
222 {
223 QModelIndex sourceIndex = this->Internal->ProxyModel->mapToSource(index);
224 if (sourceIndex.isValid())
225 {
226 QString className = this->Internal->Model->data(
227 this->Internal->Model->index(sourceIndex.row(), 0)).toString();
228 this->onClassNameDoubleClicked(className);
229 }
230 }
231 }
232
233 //-----------------------------------------------------------------------------
onObjectDoubleClicked(vtkObjectBase * object)234 void vtkQtDebugLeaksView::onObjectDoubleClicked(vtkObjectBase* object)
235 {
236 Q_UNUSED(object);
237 }
238
239 //-----------------------------------------------------------------------------
onClassNameDoubleClicked(const QString & className)240 void vtkQtDebugLeaksView::onClassNameDoubleClicked(const QString& className)
241 {
242 Q_UNUSED(className);
243 }
244