File indexing completed on 2024-05-12 05:09:51
0001 /*************************************************************************** 0002 Copyright (C) 2008-2009 Robby Stephenson <robby@periapsis.org> 0003 ***************************************************************************/ 0004 0005 /*************************************************************************** 0006 * * 0007 * This program is free software; you can redistribute it and/or * 0008 * modify it under the terms of the GNU General Public License as * 0009 * published by the Free Software Foundation; either version 2 of * 0010 * the License or (at your option) version 3 or any later version * 0011 * accepted by the membership of KDE e.V. (or its successor approved * 0012 * by the membership of KDE e.V.), which shall act as a proxy * 0013 * defined in Section 14 of version 3 of the license. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0022 * * 0023 ***************************************************************************/ 0024 0025 #include "borrowermodel.h" 0026 #include "models.h" 0027 #include "../collectionfactory.h" 0028 #include "../entry.h" 0029 #include "../tellico_debug.h" 0030 0031 #include <KLocalizedString> 0032 0033 #include <QIcon> 0034 0035 using Tellico::BorrowerModel; 0036 0037 class BorrowerModel::Node { 0038 public: 0039 Node(Node* parent_) : m_parent(parent_) {} 0040 ~Node() { qDeleteAll(m_children); } 0041 0042 Node* parent() const { return m_parent; } 0043 Node* child(int row) const { return m_children.at(row); } 0044 int row() const { return m_parent ? m_parent->m_children.indexOf(const_cast<Node*>(this)) : 0; } 0045 int childCount() const { return m_children.count(); } 0046 0047 void addChild(Node* child) { m_children.append(child); } 0048 void replaceChild(int i, Node* child) { m_children.replace(i, child); } 0049 void removeChild(int i) { delete m_children.takeAt(i); } 0050 void removeAll() { qDeleteAll(m_children); m_children.clear(); } 0051 0052 private: 0053 Node* m_parent; 0054 QList<Node*> m_children; 0055 }; 0056 0057 BorrowerModel::BorrowerModel(QObject* parent) : QAbstractItemModel(parent), m_rootNode(new Node(nullptr)) { 0058 } 0059 0060 BorrowerModel::~BorrowerModel() { 0061 delete m_rootNode; 0062 m_rootNode = nullptr; 0063 } 0064 0065 int BorrowerModel::rowCount(const QModelIndex& index_) const { 0066 if(!index_.isValid()) { 0067 return m_borrowers.count(); 0068 } 0069 QModelIndex parent = index_.parent(); 0070 if(parent.isValid()) { 0071 return 0; // a parent index means it points to an entry, not a filter, so there are no children 0072 } 0073 Node* node = static_cast<Node*>(index_.internalPointer()); 0074 Q_ASSERT(node); 0075 return node->childCount(); 0076 } 0077 0078 int BorrowerModel::columnCount(const QModelIndex&) const { 0079 return 1; 0080 } 0081 0082 QVariant BorrowerModel::headerData(int section_, Qt::Orientation orientation_, int role_) const { 0083 if(section_ < 0 || section_ >= columnCount() || orientation_ != Qt::Horizontal) { 0084 return QVariant(); 0085 } 0086 if(role_ == Qt::DisplayRole) { 0087 return m_header; 0088 } 0089 return QVariant(); 0090 } 0091 0092 bool BorrowerModel::setHeaderData(int section_, Qt::Orientation orientation_, 0093 const QVariant& value_, int role_) { 0094 if(section_ < 0 || section_ >= columnCount() || orientation_ != Qt::Horizontal || role_ != Qt::EditRole) { 0095 return false; 0096 } 0097 m_header = value_.toString(); 0098 emit headerDataChanged(orientation_, section_, section_); 0099 return true; 0100 } 0101 0102 QVariant BorrowerModel::data(const QModelIndex& index_, int role_) const { 0103 if(!index_.isValid()) { 0104 return QVariant(); 0105 } 0106 0107 QModelIndex parent = index_.parent(); 0108 0109 if(index_.row() >= rowCount(parent)) { 0110 return QVariant(); 0111 } 0112 0113 switch(role_) { 0114 case Qt::DisplayRole: 0115 if(parent.isValid()) { 0116 // it points to an entry 0117 return entry(index_)->title(); 0118 } 0119 // it points to a borrower 0120 return borrower(index_)->name(); 0121 case Qt::DecorationRole: 0122 return parent.isValid() ? QIcon(QLatin1String(":/icons/") + CollectionFactory::typeName(entry(index_)->collection())) 0123 : QIcon::fromTheme(QLatin1String("kaddressbook")); 0124 case RowCountRole: 0125 return rowCount(index_); 0126 case EntryPtrRole: 0127 return QVariant::fromValue(entry(index_)); 0128 } 0129 0130 return QVariant(); 0131 } 0132 0133 QModelIndex BorrowerModel::index(int row_, int column_, const QModelIndex& parent_) const { 0134 if(!hasIndex(row_, column_, parent_)) { 0135 return QModelIndex(); 0136 } 0137 0138 Node* parentNode; 0139 if(parent_.isValid()) { 0140 parentNode = static_cast<Node*>(parent_.internalPointer()); 0141 } else { 0142 parentNode = m_rootNode; 0143 } 0144 0145 Node* child = parentNode->child(row_); 0146 if(!child) { 0147 return QModelIndex(); 0148 } 0149 return createIndex(row_, column_, child); 0150 } 0151 0152 QModelIndex BorrowerModel::parent(const QModelIndex& index_) const { 0153 if(!index_.isValid()) { 0154 return QModelIndex(); 0155 } 0156 0157 Node* node = static_cast<Node*>(index_.internalPointer()); 0158 Q_ASSERT(node); 0159 Node* parentNode = node->parent(); 0160 Q_ASSERT(parentNode); 0161 0162 // if it's top-level, it has no parent 0163 if(parentNode == m_rootNode) { 0164 return QModelIndex(); 0165 } 0166 return createIndex(parentNode->row(), 0, parentNode); 0167 } 0168 0169 void BorrowerModel::clear() { 0170 beginResetModel(); 0171 m_borrowers.clear(); 0172 delete m_rootNode; 0173 m_rootNode = new Node(nullptr); 0174 endResetModel(); 0175 } 0176 0177 void BorrowerModel::addBorrowers(const Tellico::Data::BorrowerList& borrowers_) { 0178 beginInsertRows(QModelIndex(), rowCount(), rowCount()+borrowers_.count()-1); 0179 m_borrowers += borrowers_; 0180 foreach(Data::BorrowerPtr borrower, borrowers_) { 0181 Node* borrowerNode = new Node(m_rootNode); 0182 m_rootNode->addChild(borrowerNode); 0183 for(int i = 0; i < borrower->count(); ++i) { 0184 Node* childNode = new Node(borrowerNode); 0185 borrowerNode->addChild(childNode); 0186 } 0187 } 0188 endInsertRows(); 0189 } 0190 0191 QModelIndex BorrowerModel::addBorrower(Tellico::Data::BorrowerPtr borrower_) { 0192 Q_ASSERT(borrower_); 0193 addBorrowers(Data::BorrowerList() << borrower_); 0194 // rowCount() has increased now 0195 return index(rowCount()-1, 0); 0196 } 0197 0198 QModelIndex BorrowerModel::modifyBorrower(Tellico::Data::BorrowerPtr borrower_) { 0199 Q_ASSERT(borrower_); 0200 Q_ASSERT(!borrower_->isEmpty()); 0201 int idx = m_borrowers.indexOf(borrower_); 0202 if(idx < 0) { 0203 myWarning() << "no borrower named" << borrower_->name(); 0204 return QModelIndex(); 0205 } 0206 0207 QModelIndex borrowerIndex = index(idx, 0); 0208 Node* borrowerNode = m_rootNode->child(idx); 0209 0210 beginRemoveRows(borrowerIndex, 0, borrowerNode->childCount() - 1); 0211 borrowerNode->removeAll(); 0212 endRemoveRows(); 0213 0214 beginInsertRows(borrowerIndex, 0, borrower_->count() - 1); 0215 for(int i = 0; i < borrower_->count(); ++i) { 0216 Node* childNode = new Node(borrowerNode); 0217 borrowerNode->addChild(childNode); 0218 } 0219 endInsertRows(); 0220 0221 emit dataChanged(borrowerIndex, borrowerIndex); 0222 return borrowerIndex; 0223 } 0224 0225 void BorrowerModel::removeBorrower(Tellico::Data::BorrowerPtr borrower_) { 0226 Q_ASSERT(borrower_); 0227 int idx = m_borrowers.indexOf(borrower_); 0228 if(idx < 0) { 0229 myWarning() << "no borrower named" << borrower_->name(); 0230 return; 0231 } 0232 0233 beginRemoveRows(QModelIndex(), idx, idx); 0234 m_borrowers.removeAt(idx); 0235 m_rootNode->removeChild(idx); 0236 endRemoveRows(); 0237 } 0238 0239 Tellico::Data::BorrowerPtr BorrowerModel::borrower(const QModelIndex& index_) const { 0240 // if the parent isn't invalid, then it's not a top-level borrower 0241 if(!index_.isValid() || index_.parent().isValid() || index_.row() >= m_borrowers.count()) { 0242 return Data::BorrowerPtr(); 0243 } 0244 return m_borrowers.at(index_.row()); 0245 } 0246 0247 Tellico::Data::EntryPtr BorrowerModel::entry(const QModelIndex& index_) const { 0248 // if there's not a parent, then it's a top-level item, no entry 0249 if(!index_.parent().isValid()) { 0250 return Data::EntryPtr(); 0251 } 0252 Data::EntryPtr entry; 0253 Data::LoanPtr loan = this->loan(index_); 0254 if(loan) { 0255 entry = loan->entry(); 0256 } 0257 return entry; 0258 } 0259 0260 Tellico::Data::LoanPtr BorrowerModel::loan(const QModelIndex& index_) const { 0261 // if there's not a parent, then it's a top-level item, no entry 0262 if(!index_.parent().isValid()) { 0263 return Data::LoanPtr(); 0264 } 0265 Data::LoanPtr loan; 0266 Data::BorrowerPtr borrower = this->borrower(index_.parent()); 0267 // could have already removed the loan from the borrower 0268 if(borrower && index_.row() < borrower->loans().size()) { 0269 loan = borrower->loans().at(index_.row()); 0270 } 0271 return loan; 0272 }