Radium Engine  1.5.20
Loading...
Searching...
No Matches
TreeModel.cpp
2
3#include <Core/Utils/Log.hpp>
4#include <stack>
5
6#include <QApplication>
7
8namespace Ra {
9namespace Gui {
10
11using namespace Ra::Core::Utils;
12
13int TreeModel::rowCount( const QModelIndex& parent ) const {
15 if ( parent.column() > 0 ) { return 0; }
16 TreeItem* parentItem = getItem( parent );
17 return int( parentItem->m_children.size() );
18}
19
20TreeItem* TreeModel::getItem( const QModelIndex& index ) const {
21 if ( index.isValid() ) {
22 TreeItem* item = static_cast<TreeItem*>( index.internalPointer() );
23 CORE_ASSERT( item, "Null item found" );
24 // This can indicate that you have invalid pointers in your model index.
25 // e.g. after rebuilding the model.
26 CORE_ASSERT( findInTree( item ), "Item is not in tree" );
27 return item;
28 }
29 return m_rootItem.get();
30}
31
32QVariant TreeModel::data( const QModelIndex& index, int role ) const {
33 if ( index.isValid() && index.column() == 0 ) {
34 if ( role == Qt::DisplayRole ) {
35 return QVariant( QString::fromStdString( getItem( index )->getName() ) );
36 }
37 else if ( role == Qt::CheckStateRole ) {
38 return static_cast<int>( getItem( index )->isChecked() ? Qt::Checked : Qt::Unchecked );
39 }
40 }
41 return QVariant();
42}
43
44bool TreeModel::setData( const QModelIndex& index, const QVariant& value, int role ) {
45 if ( index.isValid() && index.column() == 0 && role == Qt::CheckStateRole ) {
46 if ( QApplication::keyboardModifiers() == Qt::CTRL ) {
47 setAllItemsChecked( false );
48 setItemChecked( index, true );
49 }
50 else { setItemChecked( index, value.toBool() ); }
51 return true;
52 }
53 return false;
54}
55
56QVariant TreeModel::headerData( int section, Qt::Orientation orientation, int role ) const {
57 if ( section == 0 && orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
58 return QVariant( QString::fromStdString( getHeaderString() ) );
59 }
60 else { return QVariant(); }
61}
62
63QModelIndex TreeModel::index( int row, int column, const QModelIndex& parent ) const {
64 if ( !hasIndex( row, column, parent ) ) { return QModelIndex(); }
65 // Only items from the first column may have a parent
66 if ( parent.isValid() && parent.column() != 0 ) { return QModelIndex(); }
67 // Grab the parent and make an index of the child.
68 TreeItem* parentItem = getItem( parent );
69 if ( parentItem && size_t( row ) < parentItem->m_children.size() ) {
70 return createIndex( row, column, parentItem->m_children[row].get() );
71 }
72 else { return QModelIndex(); }
73}
74
75QModelIndex TreeModel::parent( const QModelIndex& child ) const {
76 if ( child.isValid() ) {
77 TreeItem* childItem = getItem( child );
78 TreeItem* parentItem = childItem->m_parent;
79
80 // No parents of the root item are indexed.
81 if ( parentItem && parentItem != m_rootItem.get() ) {
82 // Figure out which row the parent is in.
83 return createIndex( parentItem->getIndexInParent(), 0, parentItem );
84 }
85 }
86 return QModelIndex();
87}
88
89Qt::ItemFlags TreeModel::flags( const QModelIndex& index ) const {
90 return index.isValid() && getItem( index )->isValid() && getItem( index )->isSelectable()
91 ? QAbstractItemModel::flags( index ) | Qt::ItemIsUserCheckable
92 : Qt::ItemFlags();
93}
94
96 // Need to call these function to invalidate the pointers
97 // in the QModelIndex.
98 beginResetModel();
99 buildModel();
100 endResetModel();
101 emit modelRebuilt();
102}
103
104bool TreeModel::findInTree( const TreeItem* item ) const {
106 stack.push( m_rootItem.get() );
107 while ( !stack.empty() ) {
108 const TreeItem* current = stack.top();
109 stack.pop();
110 if ( current == item ) { return true; }
111 for ( const auto& child : current->m_children ) {
112 stack.push( child.get() );
113 }
114 }
115 return false;
116}
117
119#if defined CORE_DEBUG
120 LOG( logDEBUG ) << " Printing tree model";
122 stack.push( m_rootItem.get() );
123 while ( !stack.empty() ) {
124 const TreeItem* current = stack.top();
125 stack.pop();
126 LOG( logDEBUG ) << current->getName();
127 for ( const auto& child : current->m_children ) {
128 stack.push( child.get() );
129 }
130 }
131#endif
132}
133
134void TreeModel::setAllItemsChecked( bool checked ) {
135 for ( int row = 0; row < rowCount(); ++row ) {
136 const QModelIndex index = this->index( row, 0 );
137 setItemChecked( index, checked );
138 }
139}
140
141void TreeModel::setItemChecked( const QModelIndex& index, bool checked ) {
142 if ( index.isValid() ) {
143 TreeItem* item = getItem( index );
144 if ( item->isSelectable() ) {
145 item->setChecked( checked );
146 emit dataChanged( index, index, { Qt::CheckStateRole } );
147
148 // recursion on all children
149 for ( int i = 0; i < rowCount( index ); ++i ) {
150 const QModelIndex child = this->index( i, 0, index );
151 setItemChecked( child, checked );
152 }
153 }
154 }
155}
156
157} // namespace Gui
158} // namespace Ra
Base class for element of the tree representation.
Definition TreeModel.hpp:31
int getIndexInParent() const
std::vector< std::unique_ptr< TreeItem > > m_children
Children of item in the tree.
Definition TreeModel.hpp:70
virtual bool isValid() const =0
Return true if the represented object is valid.
virtual bool isSelectable() const =0
Return true if the represented object can be selected.
void modelRebuilt()
Emitted when the model has been rebuilt.
TreeItem * getItem(const QModelIndex &index) const
Get the tree item corresponding to the given index.
Definition TreeModel.cpp:20
void setAllItemsChecked(bool checked=true)
Set the check state of all items.
void setItemChecked(const QModelIndex &index, bool checked=true)
Set the check state of one item and all of its children.
virtual void buildModel()=0
QModelIndex parent(const QModelIndex &child) const override
Definition TreeModel.cpp:75
std::unique_ptr< TreeItem > m_rootItem
Root of the tree.
Qt::ItemFlags flags(const QModelIndex &index) const override
Definition TreeModel.cpp:89
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Definition TreeModel.cpp:13
QVariant data(const QModelIndex &index, int role) const override
Definition TreeModel.cpp:32
void printModel() const
Prints elements in the model to stdout (debug only)
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
Definition TreeModel.cpp:56
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
Definition TreeModel.cpp:63
bool findInTree(const TreeItem *item) const
Internal functions to check if an item is in the tree.
T empty(T... args)
hepler function to manage enum as underlying types in VariableSet
Definition Cage.cpp:3
T pop(T... args)
T push(T... args)
T top(T... args)