passwordfiltermodel.cpp (3458B)
1 /* 2 * Copyright (C) 2018 Daniel Vrátil <dvratil@kde.org> 3 * 2021 Willy Goiffon <contact@z3bra.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU Library General Public License as 7 * published by the Free Software Foundation; either version 2, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details 14 * 15 * You should have received a copy of the GNU Library General Public 16 * License along with this program; if not, write to the 17 * Free Software Foundation, Inc., 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 */ 20 21 #include "passwordfiltermodel.h" 22 #include "passwordsmodel.h" 23 #include "abbreviations.h" 24 25 #include "kdescendantsproxymodel.h" 26 27 #include <QDebug> 28 29 using namespace PlasmaPass; 30 31 PasswordFilterModel::PasswordFilterModel(QObject *parent) 32 : QSortFilterProxyModel(parent) 33 , mFlatModel(new KDescendantsProxyModel(this)) 34 { 35 mFlatModel->setDisplayAncestorData(false); 36 sort(0); // enable sorting 37 } 38 39 void PasswordFilterModel::setSourceModel(QAbstractItemModel *sourceModel) 40 { 41 mFlatModel->setSourceModel(sourceModel); 42 43 if (!this->sourceModel()) { 44 QSortFilterProxyModel::setSourceModel(mFlatModel); 45 } 46 } 47 48 QString PasswordFilterModel::filter() const 49 { 50 return mFilter; 51 } 52 53 void PasswordFilterModel::setFilter(const QString &filter) 54 { 55 if (mFilter != filter) { 56 mFilter = filter; 57 mParts = filter.splitRef(QLatin1Char('/'), QString::SkipEmptyParts); 58 Q_EMIT filterChanged(); 59 mSortingLookup.clear(); 60 invalidate(); 61 } 62 } 63 64 QVariant PasswordFilterModel::data(const QModelIndex &index, int role) const 65 { 66 if (role == Qt::DisplayRole) { 67 return data(index, PasswordsModel::FullNameRole); 68 } 69 70 return QSortFilterProxyModel::data(index, role); 71 } 72 73 74 bool PasswordFilterModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const 75 { 76 const auto src_index = sourceModel()->index(source_row, 0, source_parent); 77 const auto type = static_cast<PasswordsModel::EntryType>(sourceModel()->data(src_index, PasswordsModel::EntryTypeRole).toInt()); 78 if (type == PasswordsModel::FolderEntry) { 79 return false; 80 } 81 82 if (mFilter.isEmpty()) { 83 // nothing matches an empty filter 84 return false; 85 } 86 87 const auto path = sourceModel()->data(src_index, PasswordsModel::FullNameRole).toString(); 88 89 const auto weight = matchPathFilter(path.splitRef(QLatin1Char('/')), mParts); 90 if (weight > -1) { 91 mSortingLookup.insert(src_index, weight); 92 return true; 93 } 94 95 return false; 96 } 97 98 bool PasswordFilterModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const 99 { 100 const auto weightLeft = mSortingLookup.value(source_left, -1); 101 const auto weightRight = mSortingLookup.value(source_right, -1); 102 103 if (weightLeft == weightRight) { 104 const auto nameLeft = source_left.data(PasswordsModel::FullNameRole).toString(); 105 const auto nameRight = source_right.data(PasswordsModel::FullNameRole).toString(); 106 return QString::localeAwareCompare(nameLeft, nameRight) < 0; 107 } 108 109 return weightLeft < weightRight; 110 }