Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Cory Quammen
VTK
Commits
9182f039
Commit
9182f039
authored
Jul 05, 2011
by
Pat Marion
Browse files
Add Qt widget for displaying objects tracked by vtkDebugLeaks
Change-Id: I3aed58d875bd7080d8e369769b476f59447fa5e5
parent
75ca1bd2
Changes
7
Hide whitespace changes
Inline
Side-by-side
GUISupport/Qt/CMakeLists.txt
View file @
9182f039
...
...
@@ -12,6 +12,8 @@ SET(QVTKLibSrcs
QVTKPaintEngine.h
vtkQtAbstractModelAdapter.cxx
vtkQtAnnotationLayersModelAdapter.cxx
vtkQtDebugLeaksModel.cxx
vtkQtDebugLeaksView.cxx
vtkQtSQLDatabase.cxx
vtkQtSQLQuery.cxx
vtkQtTableModelAdapter.cxx
...
...
@@ -28,6 +30,8 @@ SET(QVTKMocHeaders
QFilterTreeProxyModel.h
vtkQtAbstractModelAdapter.h
vtkQtAnnotationLayersModelAdapter.h
vtkQtDebugLeaksModel.h
vtkQtDebugLeaksView.h
vtkQtTableModelAdapter.h
vtkQtTreeModelAdapter.h
)
...
...
GUISupport/Qt/Testing/Cxx/CMakeLists.txt
View file @
9182f039
...
...
@@ -2,6 +2,7 @@
SET
(
KIT QVTK
)
# add tests that do not require data
SET
(
MyTests
TestQtDebugLeaksView.cxx
TestQtInitialization.cxx
TestQtSQLDatabase.cxx
TestQtTableModelAdapter.cxx
...
...
GUISupport/Qt/Testing/Cxx/TestQtDebugLeaksView.cxx
0 → 100644
View file @
9182f039
/*=========================================================================
Program: Visualization Toolkit
Module: TestQtTreeModelAdapter.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
// Tests vtkQtDebugLeaksModel and vtkQtDebugLeaksView.
#include
"vtkConeSource.h"
#include
"vtkDebugLeaks.h"
#include
"vtkSmartPointer.h"
#include
"vtkQtDebugLeaksModel.h"
#include
"vtkQtDebugLeaksView.h"
#include
<QApplication>
#include
<QStandardItemModel>
#include
<QTableView>
#define fail(msg) \
std::cout << msg << std::endl; \
return EXIT_FAILURE
int
TestQtDebugLeaksView
(
int
argc
,
char
*
argv
[])
{
QApplication
app
(
argc
,
argv
);
if
(
vtkDebugLeaks
::
GetDebugLeaksObserver
())
{
fail
(
"Expected debug leaks observer to be null at start of test."
);
}
vtkQtDebugLeaksView
view
;
vtkQtDebugLeaksModel
*
model
=
view
.
model
();
if
(
!
vtkDebugLeaks
::
GetDebugLeaksObserver
())
{
fail
(
"Expected debug leaks observer to be initialized after constructing view."
);
}
// Normally the model is updated asynchronously during the application event loop.
// Since there is no event loop running during this test we'll call processEvents()
// whenever we need the model to update.
app
.
processEvents
();
std
::
cout
<<
"Expect a warning message to be printed:"
<<
std
::
endl
;
QList
<
vtkObjectBase
*>
cones
=
model
->
getObjects
(
"vtkConeSource"
);
if
(
!
cones
.
isEmpty
())
{
fail
(
"Expected number of vtkConeSource to be 0"
);
}
// The rest of the test requires that VTK_DEBUG_LEAKS is enabled.
// The begining of this test is still useful to ensure that the widget
// opens without crashing when debug leaks is disabled.
#ifdef VTK_DEBUG_LEAKS
vtkSmartPointer
<
vtkConeSource
>
cone
=
vtkSmartPointer
<
vtkConeSource
>::
New
();
app
.
processEvents
();
cones
=
model
->
getObjects
(
"vtkConeSource"
);
if
(
cones
.
size
()
!=
1
||
cones
[
0
]
!=
cone
)
{
fail
(
"Debug leaks model failed to locate the cone"
);
}
view
.
setFilterEnabled
(
true
);
view
.
setFilterText
(
"vtkCone"
);
QTableView
*
classTable
=
view
.
findChild
<
QTableView
*>
(
"ClassTable"
);
if
(
classTable
->
model
()
->
rowCount
()
!=
1
)
{
fail
(
"Expected exactly 1 row in debug leaks view."
);
}
classTable
->
selectRow
(
0
);
QStandardItemModel
*
referenceModel
=
model
->
referenceCountModel
(
"vtkConeSource"
);
QTableView
*
referenceTable
=
view
.
findChild
<
QTableView
*>
(
"ReferenceTable"
);
if
(
referenceTable
->
model
()
!=
referenceModel
)
{
fail
(
"Reference table has incorrect model"
);
}
view
.
setFilterEnabled
(
false
);
if
(
classTable
->
model
()
->
rowCount
()
<=
1
)
{
fail
(
"Expected more than 1 row in the debug leaks view"
);
}
if
(
view
.
filterText
()
!=
"vtkCone"
)
{
fail
(
"Expected filter text to be 'vtkCone'"
);
}
int
baseReferenceCount
=
cone
->
GetReferenceCount
();
if
(
referenceModel
->
rowCount
()
!=
1
)
{
fail
(
"Expected reference model to have exactly 1 row"
);
}
if
(
referenceModel
->
data
(
referenceModel
->
index
(
0
,
1
))
!=
baseReferenceCount
)
{
fail
(
"Incorrect reference count"
);
}
vtkSmartPointer
<
vtkConeSource
>
newReference
=
cone
;
int
newReferenceCount
=
cone
->
GetReferenceCount
();
if
(
newReferenceCount
<=
baseReferenceCount
)
{
fail
(
"Expected reference count to increase after constructing smart pointer"
);
}
// Normally the reference count model is updated periodically during the application event loop.
// Since there is no event loop running in this test we'll directly invoke the update routine.
QMetaObject
::
invokeMethod
(
referenceModel
,
"updateReferenceCounts"
,
Qt
::
DirectConnection
);
if
(
referenceModel
->
data
(
referenceModel
->
index
(
0
,
1
))
!=
newReferenceCount
)
{
fail
(
"Incorrect reference count"
);
}
newReference
=
NULL
;
QMetaObject
::
invokeMethod
(
referenceModel
,
"updateReferenceCounts"
,
Qt
::
DirectConnection
);
if
(
referenceModel
->
data
(
referenceModel
->
index
(
0
,
1
))
!=
baseReferenceCount
)
{
fail
(
"Incorrect reference count"
);
}
newReference
=
vtkSmartPointer
<
vtkConeSource
>::
New
();
app
.
processEvents
();
if
(
referenceModel
->
rowCount
()
!=
2
)
{
fail
(
"Expected reference model to have exactly 2 rows"
);
}
newReference
=
NULL
;
cone
=
NULL
;
app
.
processEvents
();
view
.
setFilterEnabled
(
true
);
if
(
classTable
->
model
()
->
rowCount
()
!=
0
)
{
fail
(
"Expected 0 rows in the debug leaks view"
);
}
#endif
//uncomment to keep the widget open for interaction
//view.show();
//view.setAttribute(Qt::WA_QuitOnClose, true);
//app.exec();
return
EXIT_SUCCESS
;
}
GUISupport/Qt/vtkQtDebugLeaksModel.cxx
0 → 100644
View file @
9182f039
/*=========================================================================
Program: Visualization Toolkit
Module: vtkQtDebugLeaksModel.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include
"vtkQtDebugLeaksModel.h"
#include
"vtkDebugLeaks.h"
#include
<QCoreApplication>
#include
<QDebug>
#include
<QList>
#include
<QPointer>
#include
<QTextStream>
#include
<QTimer>
//-----------------------------------------------------------------------------
class
vtkQtDebugLeaksModel
::
qObserver
:
public
vtkDebugLeaksObserver
{
public:
qObserver
(
vtkQtDebugLeaksModel
&
model
)
:
Model
(
model
)
{
vtkDebugLeaks
::
SetDebugLeaksObserver
(
this
);
}
virtual
~
qObserver
()
{
vtkDebugLeaks
::
SetDebugLeaksObserver
(
0
);
}
virtual
void
ConstructingObject
(
vtkObjectBase
*
object
)
{
this
->
Model
.
addObject
(
object
);
}
virtual
void
DestructingObject
(
vtkObjectBase
*
object
)
{
this
->
Model
.
removeObject
(
object
);
}
vtkQtDebugLeaksModel
&
Model
;
};
//-----------------------------------------------------------------------------
class
VTKClassInfo
{
public:
VTKClassInfo
(
const
QString
&
className
)
:
Count
(
0
),
Name
(
className
)
{
}
int
Count
;
QString
Name
;
QList
<
vtkObjectBase
*>
Objects
;
};
//-----------------------------------------------------------------------------
class
vtkQtDebugLeaksModel
::
qInternal
{
public:
qInternal
()
:
ProcessPending
(
false
)
{
}
bool
ProcessPending
;
QList
<
QString
>
Classes
;
QList
<
VTKClassInfo
>
ClassInfo
;
QList
<
vtkObjectBase
*>
ObjectsToProcess
;
QHash
<
vtkObjectBase
*
,
VTKClassInfo
*>
ObjectMap
;
QHash
<
QString
,
QPointer
<
ReferenceCountModel
>
>
ReferenceModels
;
};
//-----------------------------------------------------------------------------
vtkQtDebugLeaksModel
::
vtkQtDebugLeaksModel
(
QObject
*
parent
)
:
QStandardItemModel
(
0
,
2
,
parent
)
{
this
->
Internal
=
new
qInternal
;
this
->
Observer
=
new
qObserver
(
*
this
);
this
->
setHeaderData
(
0
,
Qt
::
Horizontal
,
QObject
::
tr
(
"Class Name"
));
this
->
setHeaderData
(
1
,
Qt
::
Horizontal
,
QObject
::
tr
(
"Class Count"
));
this
->
connect
(
QCoreApplication
::
instance
(),
SIGNAL
(
aboutToQuit
()),
SLOT
(
onAboutToQuit
()));
}
//-----------------------------------------------------------------------------
vtkQtDebugLeaksModel
::~
vtkQtDebugLeaksModel
()
{
delete
this
->
Observer
;
delete
this
->
Internal
;
}
//-----------------------------------------------------------------------------
void
vtkQtDebugLeaksModel
::
onAboutToQuit
()
{
delete
this
->
Observer
;
this
->
Observer
=
0
;
}
//----------------------------------------------------------------------------
void
vtkQtDebugLeaksModel
::
addObject
(
vtkObjectBase
*
object
)
{
this
->
Internal
->
ObjectsToProcess
.
append
(
object
);
if
(
!
this
->
Internal
->
ProcessPending
)
{
this
->
Internal
->
ProcessPending
=
true
;
QTimer
::
singleShot
(
0
,
this
,
SLOT
(
processPendingObjects
()));
}
}
//----------------------------------------------------------------------------
void
vtkQtDebugLeaksModel
::
processPendingObjects
()
{
this
->
Internal
->
ProcessPending
=
false
;
foreach
(
vtkObjectBase
*
object
,
this
->
Internal
->
ObjectsToProcess
)
{
this
->
registerObject
(
object
);
}
this
->
Internal
->
ObjectsToProcess
.
clear
();
}
//----------------------------------------------------------------------------
void
vtkQtDebugLeaksModel
::
registerObject
(
vtkObjectBase
*
object
)
{
QString
className
=
object
->
GetClassName
();
int
indexOf
=
this
->
Internal
->
Classes
.
indexOf
(
className
);
if
(
indexOf
<
0
)
{
this
->
Internal
->
Classes
.
append
(
className
);
this
->
Internal
->
ClassInfo
.
append
(
VTKClassInfo
(
className
));
indexOf
=
this
->
rowCount
();
this
->
insertRow
(
indexOf
);
this
->
setData
(
this
->
index
(
indexOf
,
0
),
className
);
this
->
setData
(
this
->
index
(
indexOf
,
1
),
0
);
}
VTKClassInfo
&
classInfo
=
this
->
Internal
->
ClassInfo
[
indexOf
];
classInfo
.
Count
+=
1
;
classInfo
.
Objects
.
append
(
object
);
this
->
Internal
->
ObjectMap
[
object
]
=
&
classInfo
;
this
->
setData
(
this
->
index
(
indexOf
,
1
),
classInfo
.
Count
);
ReferenceCountModel
*
model
=
this
->
Internal
->
ReferenceModels
.
value
(
className
,
0
);
if
(
model
)
{
model
->
addObject
(
object
);
}
}
//----------------------------------------------------------------------------
void
vtkQtDebugLeaksModel
::
removeObject
(
vtkObjectBase
*
object
)
{
VTKClassInfo
*
classInfo
=
this
->
Internal
->
ObjectMap
.
value
(
object
,
0
);
if
(
classInfo
)
{
QString
className
=
classInfo
->
Name
;
int
row
=
this
->
Internal
->
Classes
.
indexOf
(
className
);
classInfo
->
Count
-=
1
;
classInfo
->
Objects
.
removeOne
(
object
);
this
->
Internal
->
ObjectMap
.
remove
(
object
);
if
(
classInfo
->
Count
<=
0
)
{
this
->
Internal
->
Classes
.
removeAt
(
row
);
this
->
Internal
->
ClassInfo
.
removeAt
(
row
);
this
->
removeRow
(
row
);
}
else
{
this
->
setData
(
this
->
index
(
row
,
1
),
classInfo
->
Count
);
}
ReferenceCountModel
*
model
=
this
->
Internal
->
ReferenceModels
.
value
(
className
,
0
);
if
(
model
)
{
model
->
removeObject
(
object
);
}
}
else
{
this
->
Internal
->
ObjectsToProcess
.
removeOne
(
object
);
}
}
//-----------------------------------------------------------------------------
QList
<
vtkObjectBase
*>
vtkQtDebugLeaksModel
::
getObjects
(
const
QString
&
className
)
{
int
indexOf
=
this
->
Internal
->
Classes
.
indexOf
(
className
);
if
(
indexOf
<
0
)
{
qWarning
()
<<
"vtkQtDebugLeaksModel::getObjects: bad class name:"
<<
className
;
return
QList
<
vtkObjectBase
*>
();
}
VTKClassInfo
&
classInfo
=
this
->
Internal
->
ClassInfo
[
indexOf
];
return
classInfo
.
Objects
;
}
//----------------------------------------------------------------------------
QStandardItemModel
*
vtkQtDebugLeaksModel
::
referenceCountModel
(
const
QString
&
className
)
{
ReferenceCountModel
*
model
=
this
->
Internal
->
ReferenceModels
.
value
(
className
,
0
);
if
(
!
model
)
{
model
=
new
ReferenceCountModel
(
this
);
this
->
Internal
->
ReferenceModels
[
className
]
=
model
;
foreach
(
vtkObjectBase
*
obj
,
this
->
getObjects
(
className
))
{
model
->
addObject
(
obj
);
}
}
return
model
;
}
//-----------------------------------------------------------------------------
Qt
::
ItemFlags
vtkQtDebugLeaksModel
::
flags
(
const
QModelIndex
&
index
)
const
{
Q_UNUSED
(
index
);
return
Qt
::
ItemIsSelectable
|
Qt
::
ItemIsEnabled
;
}
//-----------------------------------------------------------------------------
Q_DECLARE_METATYPE
(
vtkObjectBase
*
);
//-----------------------------------------------------------------------------
ReferenceCountModel
::
ReferenceCountModel
(
QObject
*
parent
)
:
QStandardItemModel
(
0
,
2
,
parent
)
{
this
->
setHeaderData
(
0
,
Qt
::
Horizontal
,
QObject
::
tr
(
"Pointer"
));
this
->
setHeaderData
(
1
,
Qt
::
Horizontal
,
QObject
::
tr
(
"Reference Count"
));
QTimer
::
singleShot
(
100
,
this
,
SLOT
(
updateReferenceCounts
()));
}
ReferenceCountModel
::~
ReferenceCountModel
()
{
}
//-----------------------------------------------------------------------------
QString
ReferenceCountModel
::
pointerAsString
(
void
*
ptr
)
{
QString
ptrStr
;
QTextStream
stream
(
&
ptrStr
);
stream
<<
ptr
;
return
ptrStr
;
}
//-----------------------------------------------------------------------------
void
ReferenceCountModel
::
addObject
(
vtkObjectBase
*
obj
)
{
int
row
=
this
->
rowCount
();
this
->
insertRow
(
row
);
this
->
setData
(
this
->
index
(
row
,
0
),
this
->
pointerAsString
(
obj
));
this
->
setData
(
this
->
index
(
row
,
0
),
qVariantFromValue
(
obj
),
Qt
::
UserRole
);
this
->
setData
(
this
->
index
(
row
,
1
),
obj
->
GetReferenceCount
());
}
//-----------------------------------------------------------------------------
void
ReferenceCountModel
::
removeObject
(
vtkObjectBase
*
obj
)
{
QString
pointerString
=
this
->
pointerAsString
(
obj
);
for
(
int
i
=
0
;
i
<
this
->
rowCount
();
++
i
)
{
if
(
this
->
data
(
this
->
index
(
i
,
0
))
==
pointerString
)
{
this
->
removeRow
(
i
);
return
;
}
}
}
//-----------------------------------------------------------------------------
void
ReferenceCountModel
::
updateReferenceCounts
()
{
for
(
int
row
=
0
;
row
<
this
->
rowCount
();
++
row
)
{
QVariant
pointerVariant
=
this
->
data
(
this
->
index
(
row
,
0
),
Qt
::
UserRole
);
vtkObjectBase
*
obj
=
pointerVariant
.
value
<
vtkObjectBase
*>
();
this
->
setData
(
this
->
index
(
row
,
1
),
obj
->
GetReferenceCount
());
}
QTimer
::
singleShot
(
100
,
this
,
SLOT
(
updateReferenceCounts
()));
}
//-----------------------------------------------------------------------------
Qt
::
ItemFlags
ReferenceCountModel
::
flags
(
const
QModelIndex
&
index
)
const
{
Q_UNUSED
(
index
);
return
Qt
::
ItemIsSelectable
|
Qt
::
ItemIsEnabled
;
}
GUISupport/Qt/vtkQtDebugLeaksModel.h
0 → 100644
View file @
9182f039
/*=========================================================================
Program: Visualization Toolkit
Module: vtkQtDebugLeaksModel.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
// .NAME vtkQtDebugLeaksModel - model class that observes the vtkDebugLeaks singleton
//
// .SECTION Description
// This class is used internally by the vtkQtDebugLeaksView. It installs an
// observer on the vtkDebugLeaks singleton and uses the observer to maintain
// a model of all vtkObjectBase dervied objects that are alive in memory.
#ifndef __vtkQtDebugLeaksModel_h
#define __vtkQtDebugLeaksModel_h
#include
"QVTKWin32Header.h"
#include
<QStandardItemModel>
class
vtkObjectBase
;
class
QVTK_EXPORT
vtkQtDebugLeaksModel
:
public
QStandardItemModel
{
Q_OBJECT
public:
vtkQtDebugLeaksModel
(
QObject
*
parent
=
0
);
virtual
~
vtkQtDebugLeaksModel
();
// Description:
// Get the list of objects in the model that have the given class name
QList
<
vtkObjectBase
*>
getObjects
(
const
QString
&
className
);
// Description:
// Return an item model that contains only objects with the given class name.
// The model has two columns: object address (string), object reference count (integer)
// The caller is allowed to reparent or delete the returned model.
QStandardItemModel
*
referenceCountModel
(
const
QString
&
className
);
protected
slots
:
void
addObject
(
vtkObjectBase
*
object
);
void
removeObject
(
vtkObjectBase
*
object
);
void
registerObject
(
vtkObjectBase
*
object
);
void
processPendingObjects
();
void
onAboutToQuit
();
// Inherited method from QAbstractItemModel
virtual
Qt
::
ItemFlags
flags
(
const
QModelIndex
&
index
)
const
;
private:
class
qInternal
;
qInternal
*
Internal
;
class
qObserver
;
qObserver
*
Observer
;
Q_DISABLE_COPY
(
vtkQtDebugLeaksModel
);
};
// TODO - move to private
//-----------------------------------------------------------------------------
class
ReferenceCountModel
:
public
QStandardItemModel
{
Q_OBJECT
public:
ReferenceCountModel
(
QObject
*
parent
=
0
);
~
ReferenceCountModel
();
void
addObject
(
vtkObjectBase
*
obj
);
void
removeObject
(
vtkObjectBase
*
obj
);
QString
pointerAsString
(
void
*
ptr
);
// Inherited method from QAbstractItemModel
virtual
Qt
::
ItemFlags
flags
(
const
QModelIndex
&
index
)
const
;
protected
slots
:
void
updateReferenceCounts
();
};
#endif
GUISupport/Qt/vtkQtDebugLeaksView.cxx
0 → 100644
View file @
9182f039
/*=========================================================================
Program: Visualization Toolkit
Module: vtkQtDebugLeaksView.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include
"vtkQtDebugLeaksView.h"
#include
"vtkQtDebugLeaksModel.h"
#include
<QCheckBox>
#include
<QDesktopServices>