Last active
April 8, 2019 07:47
-
-
Save jkoenen/76282a98334c2bb272d3520fb8fc62c2 to your computer and use it in GitHub Desktop.
Qt Memory Allocator View+Model
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "game_memory_allocator_model.hpp" | |
#include "keen/gameconnectionserver/game_connection_memory_data.hpp" | |
#include "keen/qtbase/numbers.hpp" | |
namespace keen | |
{ | |
GameMemoryAllocatorModel::GameMemoryAllocatorModel( const GameMemoryDataAllocators* pAllocators, QObject* pParent /*= nullptr */ ) | |
: QAbstractItemModel( pParent ) | |
{ | |
KEEN_ASSERTE( pAllocators != nullptr ); | |
m_pAllocators = pAllocators; | |
m_allocationMode = AllocationMode_ShowLeft; | |
} | |
GameMemoryAllocatorModel::~GameMemoryAllocatorModel() | |
{ | |
} | |
int GameMemoryAllocatorModel::columnCount( const QModelIndex & parent /*= QModelIndex() */ ) const | |
{ | |
if( parent.isValid() ) | |
{ | |
return 0; | |
} | |
return Colums_Count; | |
} | |
int GameMemoryAllocatorModel::rowCount( const QModelIndex& parent /*= QModelIndex() */ ) const | |
{ | |
if( parent.isValid() ) | |
{ | |
return 0; | |
} | |
return (int)m_pAllocators->allocators.size(); | |
} | |
QVariant GameMemoryAllocatorModel::data( const QModelIndex& index, int role /*= Qt::DisplayRole */ ) const | |
{ | |
if( !index.isValid() ) | |
{ | |
return QVariant(); | |
} | |
const GameMemoryDataAllocatorPair& allocatorPair = m_pAllocators->allocators[ index.row() ]; | |
const GameMemoryDataAllocator& allocator0 = allocatorPair.data[ 0u ]; | |
const GameMemoryDataAllocator& allocator1 = allocatorPair.data[ 1u ]; | |
switch( role ) | |
{ | |
case Qt::DisplayRole: | |
switch( index.column() ) | |
{ | |
case Colums_NameLeft: | |
return ( allocatorPair.dataMask & 1u ? QString( allocatorPair.name ) : QString() ); | |
case Colums_Allocated: | |
return getAllocationString( allocator0.allocatedSize, allocator1.allocatedSize, allocatorPair.dataMask ); | |
case Colums_AllocatedMax: | |
return getAllocationString( allocator0.maxAllocatedSize, allocator1.maxAllocatedSize, allocatorPair.dataMask ); | |
case Colums_Capacity: | |
return getAllocationString( allocator0.totalSize, allocator1.totalSize, allocatorPair.dataMask ); | |
case Colums_Allocations: | |
return getAllocationString( allocator0.allocationCount, allocator1.allocationCount, allocatorPair.dataMask ); | |
case Colums_AllocationsMax: | |
return getAllocationString( allocator0.maxAllocationCount, allocator1.maxAllocationCount, allocatorPair.dataMask ); | |
case Colums_TotalAllocations: | |
return getAllocationString( allocator0.totalAllocationCount, allocator1.totalAllocationCount, allocatorPair.dataMask ); | |
case Colums_NameRight: | |
return ( allocatorPair.dataMask & 2u ? QString( allocatorPair.name ) : QString() ); | |
default: | |
break; | |
} | |
break; | |
case Qt::TextColorRole: | |
switch( index.column() ) | |
{ | |
case Colums_Allocated: | |
return getAllocationColor( allocator0.allocatedSize, allocator1.allocatedSize, allocatorPair.dataMask ); | |
case Colums_AllocatedMax: | |
return getAllocationColor( allocator0.maxAllocatedSize, allocator1.maxAllocatedSize, allocatorPair.dataMask ); | |
case Colums_Capacity: | |
return getAllocationColor( allocator0.totalSize, allocator1.totalSize, allocatorPair.dataMask ); | |
case Colums_Allocations: | |
return getAllocationColor( allocator0.allocationCount, allocator1.allocationCount, allocatorPair.dataMask ); | |
case Colums_AllocationsMax: | |
return getAllocationColor( allocator0.maxAllocationCount, allocator1.maxAllocationCount, allocatorPair.dataMask ); | |
case Colums_TotalAllocations: | |
return getAllocationColor( allocator0.totalAllocationCount, allocator1.totalAllocationCount, allocatorPair.dataMask ); | |
default: | |
break; | |
} | |
break; | |
case Qt::TextAlignmentRole: | |
return ( ( index.column() == Colums_NameLeft ) || ( index.column() == Colums_NameRight ) ) ? Qt::AlignLeft : Qt::AlignRight; | |
case UserRole_Sort: | |
switch( index.column() ) | |
{ | |
case Colums_NameLeft: | |
return ( allocatorPair.dataMask & 1u ? QString( allocatorPair.name ) : QString() ); | |
case Colums_Allocated: | |
return -(qlonglong)getAllocationValue( allocator0.allocatedSize, allocator1.allocatedSize, allocatorPair.dataMask ); | |
case Colums_AllocatedMax: | |
return -(qlonglong)getAllocationValue( allocator0.maxAllocatedSize, allocator1.maxAllocatedSize, allocatorPair.dataMask ); | |
case Colums_Capacity: | |
return -(qlonglong)getAllocationValue( allocator0.totalSize, allocator1.totalSize, allocatorPair.dataMask ); | |
case Colums_Allocations: | |
return -(qlonglong)getAllocationValue( allocator0.allocationCount, allocator1.allocationCount, allocatorPair.dataMask ); | |
case Colums_AllocationsMax: | |
return -(qlonglong)getAllocationValue( allocator0.maxAllocationCount, allocator1.maxAllocationCount, allocatorPair.dataMask ); | |
case Colums_TotalAllocations: | |
return -(qlonglong)getAllocationValue( allocator0.totalAllocationCount, allocator1.totalAllocationCount, allocatorPair.dataMask ); | |
case Colums_NameRight: | |
return ( allocatorPair.dataMask & 2u ? QString( allocatorPair.name ) : QString() ); | |
default: | |
break; | |
} | |
break; | |
case UserRole_AllocatorIndex: | |
return index.row(); | |
default: | |
break; | |
} | |
return QVariant(); | |
} | |
QVariant GameMemoryAllocatorModel::headerData( int section, Qt::Orientation orientation, int role /*= Qt::DisplayRole */ ) const | |
{ | |
static const char* s_columnNames[] = | |
{ | |
"Left Name", "Allocated", "Max Allocated", "Capacity", "Allocations", "Max Allocations", "Total Allocations", "Right Name" | |
}; | |
KEEN_COMPILE_TIME_ASSERT( KEEN_COUNTOF( s_columnNames ) == Colums_Count ); | |
static const char* s_columnToolTips[] = | |
{ | |
"Left allocator name", "Allocated bytes", "Maximum allocated bytes", "Allocator capacity in bytes", "Allocation count", "Maximum allocation count", "Total allocation count", "Right allocator name", | |
}; | |
KEEN_COMPILE_TIME_ASSERT( KEEN_COUNTOF( s_columnToolTips ) == Colums_Count ); | |
switch( role ) | |
{ | |
case Qt::DisplayRole: | |
return s_columnNames[ section ]; | |
case Qt::ToolTipRole: | |
return s_columnToolTips[ section ]; | |
case Qt::TextAlignmentRole: | |
return ( ( section == Colums_NameLeft ) || ( section == Colums_NameRight ) ) ? Qt::AlignLeft : Qt::AlignRight; | |
default: | |
break; | |
} | |
return QAbstractItemModel::headerData( section, orientation, role ); | |
} | |
QModelIndex GameMemoryAllocatorModel::index( int row, int column, const QModelIndex& ) const | |
{ | |
return createIndex( row, column ); | |
} | |
QModelIndex GameMemoryAllocatorModel::parent( const QModelIndex& ) const | |
{ | |
return QModelIndex(); | |
} | |
void GameMemoryAllocatorModel::updateMemoryData() | |
{ | |
beginResetModel(); | |
endResetModel(); | |
} | |
void GameMemoryAllocatorModel::setAllocationMode( AllocationMode allocationMode ) | |
{ | |
beginResetModel(); | |
m_allocationMode = allocationMode; | |
endResetModel(); | |
} | |
sint64 GameMemoryAllocatorModel::getAllocationValue( uint64 leftValue, uint64 rightValue, uint32 pairMask ) const | |
{ | |
switch( m_allocationMode ) | |
{ | |
case AllocationMode_ShowLeft: | |
return pairMask & 1u ? (sint64)leftValue : (sint64)0; | |
case AllocationMode_ShowRight: | |
return pairMask & 2u ? (sint64)rightValue : (sint64)0; | |
case AllocationMode_ShowDifference: | |
if( pairMask == 3u ) | |
{ | |
return (sint64)rightValue - (sint64)leftValue; | |
} | |
else | |
{ | |
return pairMask & 1u ? -(sint64)leftValue : (sint64)rightValue; | |
} | |
default: | |
return 0; | |
} | |
} | |
QString GameMemoryAllocatorModel::getAllocationString( uint64 leftValue, uint64 rightValue, uint32 pairMask ) const | |
{ | |
switch( m_allocationMode ) | |
{ | |
case AllocationMode_ShowLeft: | |
return pairMask & 1u ? QtBase::getNumberStringUint( leftValue ) : QString(); | |
case AllocationMode_ShowRight: | |
return pairMask & 2u ? QtBase::getNumberStringUint( rightValue ) : QString(); | |
case AllocationMode_ShowDifference: | |
if( pairMask == 3u ) | |
{ | |
return QtBase::getNumberStringDeltaInt( (sint64)rightValue - (sint64)leftValue ); | |
} | |
else | |
{ | |
return pairMask & 1u ? QtBase::getNumberStringDeltaInt( -(sint64)leftValue ) : QtBase::getNumberStringDeltaInt( rightValue ); | |
} | |
default: | |
return QString(); | |
} | |
} | |
QColor GameMemoryAllocatorModel::getAllocationColor( uint64 leftValue, uint64 rightValue, uint32 pairMask ) const | |
{ | |
if( m_allocationMode == AllocationMode_ShowDifference ) | |
{ | |
const sint64 value = getAllocationValue( leftValue, rightValue, pairMask ); | |
if( value < 0 ) | |
{ | |
return QColor( Qt::red ); | |
} | |
else if( value > 0 ) | |
{ | |
return QColor( Qt::darkGreen ); | |
} | |
} | |
return QColor( Qt::black ); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef KEEN_GAME_MEMORY_ALLOCATOR_MODEL_HPP | |
#define KEEN_GAME_MEMORY_ALLOCATOR_MODEL_HPP | |
#include "keen/base/types.hpp" | |
#include <QAbstractItemModel> | |
namespace keen | |
{ | |
struct GameMemoryDataAllocators; | |
class GameMemoryAllocatorModel : public QAbstractItemModel | |
{ | |
Q_OBJECT | |
public: | |
explicit GameMemoryAllocatorModel( const GameMemoryDataAllocators* pAllocators, QObject* pParent = nullptr ); | |
virtual ~GameMemoryAllocatorModel(); | |
virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; | |
virtual int rowCount( const QModelIndex& parent = QModelIndex() ) const; | |
virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const; | |
virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; | |
virtual QModelIndex index( int row, int column, const QModelIndex& parent = QModelIndex() ) const; | |
virtual QModelIndex parent( const QModelIndex& index ) const; | |
enum AllocationMode | |
{ | |
AllocationMode_ShowLeft, | |
AllocationMode_ShowRight, | |
AllocationMode_ShowDifference | |
}; | |
void updateMemoryData(); | |
void setAllocationMode( AllocationMode allocationMode ); | |
sint64 getAllocationValue( uint64 leftValue, uint64 rightValue, uint32 pairMask ) const; | |
QString getAllocationString( uint64 leftValue, uint64 rightValue, uint32 pairMask ) const; | |
QColor getAllocationColor( uint64 leftValue, uint64 rightValue, uint32 pairMask ) const; | |
enum UserRole | |
{ | |
UserRole_Sort = Qt::UserRole, | |
UserRole_AllocatorIndex | |
}; | |
enum Colums | |
{ | |
Colums_NameLeft, | |
Colums_Allocated, | |
Colums_AllocatedMax, | |
Colums_Capacity, | |
Colums_Allocations, | |
Colums_AllocationsMax, | |
Colums_TotalAllocations, | |
Colums_NameRight, | |
Colums_Count | |
}; | |
private: | |
const GameMemoryDataAllocators* m_pAllocators; | |
AllocationMode m_allocationMode; | |
}; | |
} | |
#endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "game_memory_allocator_view.hpp" | |
#include "game_memory_allocator_model.hpp" | |
#include "game_memory_data_object.hpp" | |
#include "keen/gameconnectionserver/game_connection_memory_data.hpp" | |
#include <QSortFilterProxyModel> | |
#include <QHeaderView> | |
namespace keen | |
{ | |
GameMemoryAllocatorView::GameMemoryAllocatorView( GameMemoryDataObject* pGameMemoryDataObject, QWidget* pParent /*= nullptr */ ) | |
: QTreeView( pParent ) | |
{ | |
KEEN_ASSERTE( pGameMemoryDataObject != nullptr ); | |
setUniformRowHeights( true ); | |
setRootIsDecorated( false ); | |
setSelectionBehavior( QAbstractItemView::SelectRows ); | |
setContextMenuPolicy( Qt::CustomContextMenu ); | |
setSortingEnabled( true ); | |
setAlternatingRowColors( true ); | |
m_pModel = new GameMemoryAllocatorModel( &pGameMemoryDataObject->getGameMemoryData()->allocators ); | |
QSortFilterProxyModel* pFilter = new QSortFilterProxyModel(); | |
pFilter->setSortRole( GameMemoryAllocatorModel::UserRole_Sort ); | |
pFilter->setSourceModel( m_pModel ); | |
setModel( pFilter ); | |
header()->setSectionResizeMode( QHeaderView::Interactive ); | |
header()->setStretchLastSection( false ); | |
setColumnWidth( GameMemoryAllocatorModel::Colums_NameLeft, 250 ); | |
setColumnWidth( GameMemoryAllocatorModel::Colums_NameRight, 250 ); | |
sortByColumn( GameMemoryAllocatorModel::Colums_NameLeft, Qt::AscendingOrder ); | |
KEEN_VERIFY( connect( pGameMemoryDataObject, SIGNAL( allocatorsChanged() ), SLOT( handleDataChanged() ) ) ); | |
} | |
GameMemoryAllocatorView::~GameMemoryAllocatorView() | |
{ | |
} | |
void GameMemoryAllocatorView::setAllocationMode( int mode ) | |
{ | |
m_pModel->setAllocationMode( (GameMemoryAllocatorModel::AllocationMode)mode ); | |
} | |
void GameMemoryAllocatorView::handleDataChanged() | |
{ | |
m_pModel->updateMemoryData(); | |
} | |
void GameMemoryAllocatorView::selectionChanged( const QItemSelection& selected, const QItemSelection& deselected ) | |
{ | |
QTreeView::selectionChanged( selected, deselected ); | |
const QModelIndexList indexes = selected.indexes(); | |
emit allocatorSelected( indexes.empty() ? -1 : model()->data( indexes[ 0 ], GameMemoryAllocatorModel::UserRole_AllocatorIndex ).toInt() ); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef KEEN_GAME_MEMORY_ALLOCATOR_VIEW_HPP | |
#define KEEN_GAME_MEMORY_ALLOCATOR_VIEW_HPP | |
#include "keen/base/types.hpp" | |
#include <QTreeView> | |
namespace keen | |
{ | |
class GameMemoryDataObject; | |
class GameMemoryAllocatorModel; | |
class GameMemoryAllocatorView : public QTreeView | |
{ | |
Q_OBJECT | |
public: | |
explicit GameMemoryAllocatorView( GameMemoryDataObject* pGameMemoryDataObject, QWidget* pParent = nullptr ); | |
virtual ~GameMemoryAllocatorView(); | |
signals: | |
void allocatorSelected( int index ); | |
public slots: | |
void setAllocationMode( int mode ); | |
private slots: | |
void handleDataChanged(); | |
protected: | |
virtual void selectionChanged( const QItemSelection& selected, const QItemSelection& deselected ); | |
private: | |
GameMemoryAllocatorModel* m_pModel; | |
}; | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment