File indexing completed on 2024-05-12 05:09:52

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 "entrysortmodel.h"
0026 #include "models.h"
0027 #include "fieldcomparison.h"
0028 #include "../field.h"
0029 #include "../entry.h"
0030 
0031 using Tellico::EntrySortModel;
0032 
0033 EntrySortModel::EntrySortModel(QObject* parent) : AbstractSortModel(parent) {
0034   setDynamicSortFilter(true);
0035   setSortLocaleAware(true);
0036   connect(this, &QAbstractItemModel::modelReset, this, &EntrySortModel::clearData);
0037 }
0038 
0039 void EntrySortModel::setFilter(Tellico::FilterPtr filter_) {
0040   if(m_filter != filter_ || (m_filter && *m_filter != *filter_)) {
0041     m_filter = filter_;
0042     invalidateFilter();
0043   }
0044 }
0045 
0046 Tellico::FilterPtr EntrySortModel::filter() const {
0047   return m_filter;
0048 }
0049 
0050 bool EntrySortModel::filterAcceptsRow(int row_, const QModelIndex& parent_) const {
0051   if(!m_filter) {
0052     return true;
0053   }
0054   QModelIndex index = sourceModel()->index(row_, 0, parent_);
0055   Q_ASSERT(index.isValid());
0056   Data::EntryPtr entry = index.data(EntryPtrRole).value<Data::EntryPtr>();
0057   Q_ASSERT(entry);
0058   return m_filter->matches(entry);
0059 }
0060 
0061 bool EntrySortModel::lessThan(const QModelIndex& left_, const QModelIndex& right_) const {
0062   if(sortRole() != EntryPtrRole) {
0063     // for RowCount sorting, if there are no children, then sort by title
0064     if(sortRole() == RowCountRole) {
0065       const int leftCount = left_.data(RowCountRole).toInt();
0066       const int rightCount = right_.data(RowCountRole).toInt();
0067       if(leftCount == 0 && rightCount == 0) {
0068         // also, never sort descending by title when sorting parent by count
0069         const int res = left_.data().toString().localeAwareCompare(right_.data().toString());
0070         return sortOrder() == Qt::DescendingOrder ? (res >= 0) : (res < 0);
0071       }
0072     }
0073     return AbstractSortModel::lessThan(left_, right_);
0074   }
0075   Data::EntryPtr leftEntry = left_.data(EntryPtrRole).value<Data::EntryPtr>();
0076   Data::EntryPtr rightEntry = right_.data(EntryPtrRole).value<Data::EntryPtr>();
0077   if(!leftEntry) {
0078     if(rightEntry) {
0079       return true;
0080     } else {
0081       return false;
0082     }
0083   } else if(leftEntry && !rightEntry) {
0084     return false;
0085   }
0086 
0087   QModelIndex left = left_;
0088   QModelIndex right = right_;
0089 
0090   for(int i = 0; i < 3; ++i) {
0091     FieldComparison* comp = getComparison(left);
0092     if(!comp || !left.isValid() || !right.isValid()) {
0093       return false;
0094     }
0095 
0096     const int res = comp->compare(leftEntry, rightEntry);
0097     if(res == 0) {
0098       switch (i) {
0099         case 0:
0100           left = left.model()->index(left.row(), secondarySortColumn());
0101           right = right.model()->index(right.row(), secondarySortColumn());
0102           break;
0103         case 1:
0104           left = left.model()->index(left.row(), tertiarySortColumn());
0105           right = right.model()->index(right.row(), tertiarySortColumn());
0106           break;
0107         case 2:
0108           return false;
0109       }
0110     } else {
0111       return res < 0;
0112     }
0113   }
0114   return AbstractSortModel::lessThan(left_, right_);
0115 }
0116 
0117 void EntrySortModel::clearData() {
0118   m_filter = FilterPtr();
0119   qDeleteAll(m_comparisons);
0120   m_comparisons.clear();
0121 }
0122 
0123 Tellico::FieldComparison* EntrySortModel::getComparison(const QModelIndex& index_) const {
0124   if(m_comparisons.contains(index_.column())) {
0125     return m_comparisons.value(index_.column());
0126   }
0127   FieldComparison* comp = nullptr;
0128   if(index_.isValid()) {
0129     Data::FieldPtr field = index_.model()->headerData(index_.column(), Qt::Horizontal, FieldPtrRole).value<Data::FieldPtr>();
0130     if(field) {
0131       comp = FieldComparison::create(field);
0132       m_comparisons.insert(index_.column(), comp);
0133     }
0134   }
0135   return comp;
0136 }