File indexing completed on 2024-05-05 04:48:48

0001 /****************************************************************************************
0002  * Copyright (c) 2008-2010 Soren Harward <stharward@gmail.com>                          *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #include "TreeModel.h"
0018 
0019 #include "Constraint.h"
0020 #include "ConstraintFactory.h"
0021 
0022 #include <KLocalizedString>
0023 
0024 APG::TreeModel::TreeModel( ConstraintNode* r, QObject* p ) : QAbstractItemModel( p ), m_rootNode( r )
0025 {
0026     if ( m_rootNode->getRowCount() < 1 )
0027         ConstraintFactory::instance()->createGroup( m_rootNode, 0 );
0028 
0029     connectDCSlotToNode( m_rootNode );
0030 }
0031 
0032 APG::TreeModel::~TreeModel()
0033 {
0034 }
0035 
0036 QVariant
0037 APG::TreeModel::data( const QModelIndex &index, int role ) const
0038 {
0039     if ( !index.isValid() || ( role != Qt::DisplayRole ) )
0040         return QVariant();
0041 
0042     ConstraintNode* n = static_cast<ConstraintNode*>( index.internalPointer() );
0043     if ( index.column() == 0 ) {
0044         return QVariant( n->getName() );
0045     } else {
0046         return QVariant();
0047     }
0048 }
0049 
0050 Qt::ItemFlags
0051 APG::TreeModel::flags( const QModelIndex &index ) const
0052 {
0053     if ( !index.isValid() )
0054         return {};
0055 
0056     return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
0057 }
0058 
0059 QVariant
0060 APG::TreeModel::headerData( int section, Qt::Orientation orientation, int role ) const
0061 {
0062     if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) {
0063         if ( section == 0 ) {
0064             return QVariant( i18n("Name") );
0065         } else {
0066             return QVariant();
0067         }
0068     }
0069 
0070     return QVariant();
0071 }
0072 
0073 QModelIndex
0074 APG::TreeModel::index( int row, int column, const QModelIndex& parent ) const
0075 {
0076     if ( !hasIndex( row, column, parent ) )
0077         return QModelIndex();
0078 
0079     ConstraintNode* parentItem;
0080 
0081     if ( !parent.isValid() )
0082         parentItem = m_rootNode;
0083     else
0084         parentItem = static_cast<ConstraintNode*>( parent.internalPointer() );
0085 
0086     ConstraintNode* childItem = parentItem->getChild( row );
0087     if ( childItem )
0088         return createIndex( row, column, childItem );
0089     else
0090         return QModelIndex();
0091 }
0092 
0093 QModelIndex
0094 APG::TreeModel::parent( const QModelIndex& child ) const
0095 {
0096     if ( !child.isValid() )
0097         return QModelIndex();
0098 
0099     ConstraintNode* childItem = static_cast<ConstraintNode*>( child.internalPointer() );
0100     ConstraintNode* parentItem = static_cast<ConstraintNode*>( childItem->parent() );
0101 
0102     if ( !parentItem || parentItem == m_rootNode )
0103         return QModelIndex();
0104 
0105     return createIndex( parentItem->row(), 0, parentItem );
0106 }
0107 
0108 int
0109 APG::TreeModel::rowCount( const QModelIndex& parent ) const
0110 {
0111     if ( parent.column() > 0 )
0112         return 0;
0113 
0114     ConstraintNode* parentItem;
0115     if ( !parent.isValid() )
0116         parentItem = m_rootNode;
0117     else
0118         parentItem = static_cast<ConstraintNode*>( parent.internalPointer() );
0119 
0120     return parentItem->getRowCount();
0121 }
0122 
0123 bool
0124 APG::TreeModel::removeNode( const QModelIndex& index )
0125 {
0126     int row = index.row();
0127     bool r = false;
0128 
0129     QModelIndex parentIndex = index.parent();
0130     // prevent removal of root node
0131     if ( parentIndex.isValid() ) {
0132         ConstraintNode* parent;
0133         parent = static_cast<ConstraintNode*>( parentIndex.internalPointer() );
0134         beginRemoveRows( parentIndex, row, row );
0135         r = parent->removeChild( row );
0136         endRemoveRows();
0137         return r;
0138     } else {
0139         return r;
0140     }
0141 }
0142 
0143 QModelIndex
0144 APG::TreeModel::insertGroup( const QModelIndex& thisIdx )
0145 {
0146     int row = thisIdx.row();
0147     ConstraintNode* p = nullptr;
0148     ConstraintNode* n = nullptr;
0149 
0150     if ( thisIdx.isValid() )
0151         p = static_cast<ConstraintNode*>( thisIdx.internalPointer() );
0152     else
0153         p = m_rootNode;
0154 
0155     if ( p->getNodeType() == Constraint::ConstraintGroupType ) {
0156         beginInsertRows( thisIdx, 0, 0 );
0157         n = ConstraintFactory::instance()->createGroup( p, 0 );
0158         endInsertRows();
0159         if ( n != nullptr ) {
0160             connectDCSlotToNode( n );
0161             return createIndex( 0, 0, n );
0162         }
0163     } else {
0164         p = p->parent();
0165         QModelIndex parentIdx = parent( thisIdx );
0166         beginInsertRows( parentIdx, row + 1, row + 1 );
0167         n = ConstraintFactory::instance()->createGroup( p, row + 1 );
0168         endInsertRows();
0169         if ( n != nullptr ) {
0170             connectDCSlotToNode( n );
0171             return createIndex( row + 1, 0, n );
0172         }
0173     }
0174     return thisIdx;
0175 }
0176 
0177 QModelIndex
0178 APG::TreeModel::insertConstraint( const QModelIndex& thisIdx, const QString& constraintName )
0179 {
0180     int row = thisIdx.row();
0181     if ( thisIdx.isValid() ) {
0182         ConstraintNode* p = static_cast<ConstraintNode*>( thisIdx.internalPointer() );
0183         ConstraintNode* n = nullptr;
0184         if ( p->getNodeType() == Constraint::ConstraintGroupType ) {
0185             beginInsertRows( thisIdx, 0, 0 );
0186             QString constraintType = ConstraintFactory::instance()->untranslateName( constraintName );
0187             n = ConstraintFactory::instance()->createConstraint( constraintType, p, 0 );
0188             endInsertRows();
0189             if ( n != nullptr ) {
0190                 connectDCSlotToNode( n );
0191                 return createIndex( 0, 0, n );
0192             }
0193         } else {
0194             p = p->parent();
0195             QModelIndex parentIdx = parent( thisIdx );
0196             beginInsertRows( parentIdx, row + 1, row + 1 );
0197             QString constraintType = ConstraintFactory::instance()->untranslateName( constraintName );
0198             n = ConstraintFactory::instance()->createConstraint( constraintType, p, row + 1 );
0199             endInsertRows();
0200             if ( n != nullptr ) {
0201                 connectDCSlotToNode( n );
0202                 return createIndex( row + 1, 0, n );
0203             }
0204         }
0205     }
0206     return thisIdx;
0207 }
0208 
0209 void
0210 APG::TreeModel::slotConstraintDataChanged()
0211 {
0212     ConstraintNode* n = static_cast<ConstraintNode*>( sender() );
0213     if ( n ) {
0214         QModelIndex idx = createIndex( n->row(), 0, n );
0215         Q_EMIT dataChanged( idx, idx );
0216     }
0217 }
0218 
0219 void
0220 APG::TreeModel::connectDCSlotToNode( ConstraintNode* n )
0221 {
0222     if ( n ) {
0223         connect( n, &ConstraintNode::dataChanged, this, &TreeModel::slotConstraintDataChanged );
0224         int rc = n->getRowCount();
0225         for ( int i = 0; i < rc; i++ ) {
0226             connectDCSlotToNode( n->getChild( i ) );
0227         }
0228     }
0229 }