File indexing completed on 2024-05-19 04:48:14
0001 /* 0002 * <one line to give the program's name and a brief idea of what it does.> 0003 * Copyright (C) 2019 camilo <chiguitar@unal.edu.co> 0004 * 0005 * This program is free software: you can redistribute it and/or modify 0006 * it under the terms of the GNU General Public License as published by 0007 * the Free Software Foundation, either version 3 of the License, or 0008 * (at your option) any later version. 0009 * 0010 * This program is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU General Public License 0016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0017 */ 0018 0019 #include "mauimodel.h" 0020 #include "mauilist.h" 0021 #include <QDebug> 0022 #include <QDateTime> 0023 #include <QRegularExpression> 0024 0025 MauiModel::MauiModel(QObject *parent) 0026 : QSortFilterProxyModel(parent) 0027 , m_model(new PrivateAbstractListModel(this)) 0028 { 0029 0030 } 0031 0032 QVariantMap MauiModel::get(const int &index) const 0033 { 0034 QVariantMap res; 0035 if (index >= this->rowCount() || index < 0) 0036 return res; 0037 0038 const auto roleNames = this->roleNames(); 0039 for (const auto &role : roleNames) 0040 res.insert(role, this->index(index, 0).data(FMH::MODEL_NAME_KEY[role]).toString()); 0041 0042 return res; 0043 } 0044 0045 QVariantList MauiModel::getAll() const 0046 { 0047 QVariantList res; 0048 for (auto i = 0; i < this->rowCount(); i++) 0049 res << this->get(i); 0050 0051 return res; 0052 } 0053 0054 void MauiModel::setFilter(const QString &filter) 0055 { 0056 if (this->m_filter == filter) 0057 return; 0058 0059 0060 this->m_filter = filter; 0061 this->setFilterRegularExpression(this->m_filter); 0062 Q_EMIT this->filterChanged(this->m_filter); 0063 qDebug() << "Setting model filter" << m_filter; 0064 0065 } 0066 0067 const QString MauiModel::getFilter() const 0068 { 0069 return this->m_filter; 0070 } 0071 0072 void MauiModel::setFilters(const QStringList& filters) 0073 { 0074 if (this->m_filters == filters) 0075 return; 0076 0077 this->m_filters = filters; 0078 QString rx; 0079 for( int i = 0; i < m_filters.count(); ++i ) 0080 { 0081 QString filter = QRegularExpression::escape( m_filters.at(i) ); 0082 if( i > 0 ) 0083 rx += '|'; 0084 rx += filter; 0085 } 0086 qDebug() << "FILTERS" << filters << m_filters << m_filter << rx << filterCaseSensitivity() << ( filterCaseSensitivity() == Qt::CaseSensitivity::CaseSensitive); 0087 QRegularExpression reg(rx, filterCaseSensitivity() == Qt::CaseSensitivity::CaseInsensitive ? QRegularExpression::CaseInsensitiveOption : QRegularExpression::NoPatternOption); 0088 // reg.setCaseSensitivity(filterCaseSensitivity()); 0089 this->setFilterRegularExpression(reg); 0090 Q_EMIT this->filtersChanged(this->m_filters); 0091 } 0092 0093 const QStringList MauiModel::getFilters() const 0094 { 0095 return m_filters; 0096 } 0097 0098 void MauiModel::clearFilters() 0099 { 0100 this->m_filter.clear(); 0101 this->m_filters.clear(); 0102 this->setFilterFixedString(""); 0103 this->setFilterRegularExpression(""); 0104 this->invalidateFilter(); 0105 Q_EMIT this->filtersChanged(this->m_filters); 0106 Q_EMIT this->filterChanged(this->m_filter); 0107 0108 } 0109 0110 void MauiModel::PrivateAbstractListModel::reset() 0111 { 0112 this->beginResetModel(); 0113 this->endResetModel(); 0114 } 0115 0116 QString MauiModel::getFilterRoleName() const 0117 { 0118 return m_filter; 0119 } 0120 0121 void MauiModel::setSortOrder(const Qt::SortOrder &sortOrder) 0122 { 0123 if (this->m_sortOrder == sortOrder) 0124 return; 0125 0126 this->m_sortOrder = sortOrder; 0127 Q_EMIT this->sortOrderChanged(this->m_sortOrder); 0128 this->sort(0, this->m_sortOrder); 0129 } 0130 0131 Qt::SortOrder MauiModel::getSortOrder() const 0132 { 0133 return this->m_sortOrder; 0134 } 0135 0136 void MauiModel::setSort(const QString &sort) 0137 { 0138 if (this->m_sort == sort) 0139 return; 0140 0141 this->m_sort = sort; 0142 Q_EMIT this->sortChanged(this->m_sort); 0143 this->setSortRole(FMH::MODEL_NAME_KEY[sort]); 0144 this->sort(0, this->m_sortOrder); 0145 } 0146 0147 QString MauiModel::getSort() const 0148 { 0149 return this->m_sort; 0150 } 0151 0152 int MauiModel::count() const 0153 { 0154 return this->rowCount(); 0155 } 0156 0157 int MauiModel::mappedFromSource(const int &index) const 0158 { 0159 return this->mapFromSource(this->m_model->index(index, 0)).row(); 0160 } 0161 0162 int MauiModel::mappedToSource(const int &index) const 0163 { 0164 return this->mapToSource(this->index(index, 0)).row(); 0165 } 0166 0167 void MauiModel::setFilterRoleName(QString filter) 0168 { 0169 if (m_filterRoleName == filter) 0170 return; 0171 0172 m_filterRoleName = filter; 0173 Q_EMIT filterRoleNameChanged(m_filterRoleName); 0174 this->setFilterRole(FMH::MODEL_NAME_KEY[m_filterRoleName]); 0175 } 0176 0177 bool MauiModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const 0178 { 0179 if (this->filterRole() != Qt::DisplayRole) { 0180 QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); 0181 const auto data = this->sourceModel()->data(index, this->filterRole()).toString(); 0182 return data.contains(this->filterRegularExpression()); 0183 } 0184 0185 const auto roleNames = this->sourceModel()->roleNames(); 0186 for (const auto &role : roleNames) { 0187 QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); 0188 const auto data = this->sourceModel()->data(index, FMH::MODEL_NAME_KEY[role]).toString(); 0189 if (data.contains(this->filterRegularExpression())) 0190 return true; 0191 else 0192 continue; 0193 } 0194 0195 return false; 0196 } 0197 0198 MauiList *MauiModel::getList() const 0199 { 0200 return this->m_list; 0201 } 0202 0203 void MauiModel::PrivateAbstractListModel::setUpList() 0204 { 0205 beginResetModel(); 0206 0207 if (m_model->getList()) 0208 m_model->getList()->disconnect(this); 0209 0210 if (m_model->getList()) { 0211 connect( 0212 m_model->getList(), 0213 &MauiList::preItemAppendedAt, 0214 this, 0215 [this](int index) { 0216 beginInsertRows(QModelIndex(), index, index); 0217 }, 0218 Qt::DirectConnection); 0219 0220 connect( 0221 m_model->getList(), 0222 &MauiList::preItemAppended, 0223 this, 0224 [this]() { 0225 const int index = m_model->getList()->getCount(); 0226 beginInsertRows(QModelIndex(), index, index); 0227 }, 0228 Qt::DirectConnection); 0229 0230 connect( 0231 m_model->getList(), 0232 &MauiList::preItemsAppended, 0233 this, 0234 [this](uint count) { 0235 const int index = m_model->getList()->getCount(); 0236 beginInsertRows(QModelIndex(), index, index + count - 1); 0237 }, 0238 Qt::DirectConnection); 0239 0240 connect( 0241 m_model->getList(), 0242 &MauiList::postItemAppended, 0243 this, 0244 [this]() { 0245 endInsertRows(); 0246 }, 0247 Qt::DirectConnection); 0248 0249 connect( 0250 m_model->getList(), 0251 &MauiList::preItemRemoved, 0252 this, 0253 [this](int index) { 0254 beginRemoveRows(QModelIndex(), index, index); 0255 }, 0256 Qt::DirectConnection); 0257 0258 connect( 0259 m_model->getList(), 0260 &MauiList::postItemRemoved, 0261 this, 0262 [this]() { 0263 endRemoveRows(); 0264 }, 0265 Qt::DirectConnection); 0266 0267 connect( 0268 m_model->getList(), 0269 &MauiList::updateModel, 0270 this, 0271 [this](int index, QVector<int> roles) { 0272 Q_EMIT this->dataChanged(this->m_model->index(index, 0), this->m_model->index(index, 0), roles); 0273 }, 0274 Qt::DirectConnection); 0275 0276 connect( 0277 m_model->getList(), 0278 &MauiList::preListChanged, 0279 this, 0280 [this]() { 0281 beginResetModel(); 0282 }, 0283 Qt::DirectConnection); 0284 0285 connect( 0286 m_model->getList(), 0287 &MauiList::postListChanged, 0288 this, 0289 [this]() { 0290 endResetModel(); 0291 }, 0292 Qt::DirectConnection); 0293 0294 connect( 0295 m_model->getList(), 0296 &MauiList::itemMoved, 0297 m_model, &MauiModel::move, 0298 Qt::DirectConnection); 0299 } 0300 0301 endResetModel(); 0302 } 0303 0304 void MauiModel::setList(MauiList *value) 0305 { 0306 if(value && value != this->m_list) 0307 { 0308 this->m_list = value; 0309 this->m_list->modelHooked(); 0310 0311 this->m_model->setUpList(); 0312 Q_EMIT this->listChanged(); 0313 0314 this->setSourceModel(this->m_model); 0315 this->setDynamicSortFilter(true); 0316 } 0317 } 0318 0319 MauiModel::PrivateAbstractListModel::PrivateAbstractListModel(MauiModel *model) 0320 : QAbstractListModel(model) 0321 , m_model(model) 0322 { 0323 connect( 0324 this, 0325 &QAbstractListModel::rowsInserted, 0326 this, 0327 [this](QModelIndex, int, int) { 0328 if (m_model->getList()) { 0329 Q_EMIT this->m_model->countChanged(); 0330 } 0331 }, 0332 Qt::DirectConnection); 0333 0334 connect( 0335 this, 0336 &QAbstractListModel::rowsRemoved, 0337 this, 0338 [this](QModelIndex, int, int) { 0339 if (m_model->getList()) { 0340 Q_EMIT this->m_model->countChanged(); 0341 } 0342 }, 0343 Qt::DirectConnection); 0344 } 0345 0346 int MauiModel::PrivateAbstractListModel::rowCount(const QModelIndex &parent) const 0347 { 0348 if (parent.isValid() || !m_model->getList()) 0349 { 0350 return 0; 0351 } 0352 0353 return m_model->getList()->getCount(); 0354 } 0355 0356 0357 QVariant MauiModel::PrivateAbstractListModel::data(const QModelIndex &index, int role) const 0358 { 0359 if (!index.isValid() || !m_model->getList()) 0360 return QVariant(); 0361 0362 auto value = m_model->getList()->getItem(index.row()).value(static_cast<FMH::MODEL_KEY>(role)); 0363 0364 if (role == FMH::MODEL_KEY::ADDDATE || role == FMH::MODEL_KEY::DATE || role == FMH::MODEL_KEY::MODIFIED || role == FMH::MODEL_KEY::RELEASEDATE) { 0365 const auto date = QDateTime::fromString(value, Qt::TextDate); 0366 if (date.isValid()) 0367 return date; 0368 } 0369 0370 return value; 0371 } 0372 0373 bool MauiModel::PrivateAbstractListModel::setData(const QModelIndex &index, const QVariant &value, int role) 0374 { 0375 Q_UNUSED(index); 0376 Q_UNUSED(value); 0377 Q_UNUSED(role); 0378 0379 return false; 0380 } 0381 0382 Qt::ItemFlags MauiModel::PrivateAbstractListModel::flags(const QModelIndex &index) const 0383 { 0384 if (!index.isValid()) 0385 return Qt::NoItemFlags; 0386 0387 return Qt::ItemIsEditable; // FIXME: Implement me! 0388 } 0389 0390 QHash<int, QByteArray> MauiModel::PrivateAbstractListModel::roleNames() const 0391 { 0392 QHash<int, QByteArray> names; 0393 const auto keys = FMH::MODEL_NAME.keys(); 0394 0395 for (const auto &key : keys) 0396 { 0397 names[key] = QString(FMH::MODEL_NAME[key]).toUtf8(); 0398 } 0399 0400 return names; 0401 } 0402 0403 bool MauiModel::move(const int &index, const int &to) 0404 { 0405 if(index == to) 0406 return false; 0407 0408 if(index>=0 && index< count()) 0409 { 0410 if(to >= count() || to < 0) 0411 return false; 0412 0413 beginMoveRows(QModelIndex(), index, index, QModelIndex(), index < to ? to+1 : to); 0414 endMoveRows(); 0415 } 0416 0417 return true; 0418 } 0419 0420 /*! 0421 * Must be reimplemented, because moving rows should be possible 0422 * \brief ListModel::moveRows 0423 * \param sourceParent 0424 * \param sourceRow 0425 * \param count 0426 * \param destinationParent 0427 * \param destinationChild 0428 * \return 0429 */ 0430 bool MauiModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destinationParent, int destinationChild) { 0431 if (sourceRow < 0 0432 //|| sourceRow + count - 1 >= rowCount(sourceParent) 0433 || destinationChild <= 0 0434 //|| destinationChild > rowCount(destinationParent) 0435 || sourceRow == destinationChild - 1 0436 || count <= 0) { 0437 return false; 0438 } 0439 0440 return true; 0441 } 0442 0443 bool MauiModel::moveRow(const QModelIndex &sourceParent, int sourceRow, const QModelIndex &destinationParent, int destinationChild) { 0444 0445 return true; 0446 } 0447