1
/***************************************************************************
2
* Copyright Ā© 2010 Jonathan Thomas <echidnaman@kubuntu.org> *
4
* This program is free software; you can redistribute it and/or *
5
* modify it under the terms of the GNU General Public License as *
6
* published by the Free Software Foundation; either version 2 of *
7
* the License or (at your option) version 3 or any later version *
8
* accepted by the membership of KDE e.V. (or its successor approved *
9
* by the membership of KDE e.V.), which shall act as a proxy *
10
* defined in Section 14 of version 3 of the license. *
12
* This program is distributed in the hope that it will be useful, *
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15
* GNU General Public License for more details. *
17
* You should have received a copy of the GNU General Public License *
18
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
19
***************************************************************************/
21
#include "ApplicationProxyModel.h"
23
#include <LibQApt/Backend>
26
#include "../Application.h"
27
#include "ApplicationModel.h"
29
ApplicationProxyModel::ApplicationProxyModel(QObject *parent)
30
: QSortFilterProxyModel(parent)
32
, m_stateFilter((QApt::Package::State)0)
33
, m_sortByRelevancy(false)
34
, m_showTechnical(false)
38
ApplicationProxyModel::~ApplicationProxyModel()
42
void ApplicationProxyModel::setBackend(QApt::Backend *backend)
45
m_apps = static_cast<ApplicationModel *>(sourceModel())->applications();
48
void ApplicationProxyModel::search(const QString &searchText)
50
// 1-character searches are painfully slow. >= 2 chars are fine, though
52
if (searchText.size() > 1) {
53
m_packages = m_backend->search(searchText);
54
m_sortByRelevancy = true;
56
m_sortByRelevancy = false;
62
void ApplicationProxyModel::setStateFilter(QApt::Package::State state)
64
m_stateFilter = state;
69
void ApplicationProxyModel::setOriginFilter(const QString &origin)
71
m_originFilter = origin;
76
void ApplicationProxyModel::setFiltersFromCategory(Category *category)
78
m_andFilters = category->andFilters();
79
m_orFilters = category->orFilters();
80
m_notFilters = category->notFilters();
85
void ApplicationProxyModel::setShouldShowTechnical(bool show)
87
m_showTechnical = show;
90
bool ApplicationProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
92
Application *application = static_cast<ApplicationModel *>(sourceModel())->applicationAt(sourceModel()->index(sourceRow, 0, sourceParent));
93
//We have a package as internal pointer
94
if (!application || !application->package()) {
98
if (!m_showTechnical) {
99
if (application->isTechnical()) {
105
if ((bool)(application->package()->state() & m_stateFilter) == false) {
110
if (!m_originFilter.isEmpty()) {
111
if (application->package()->origin() != m_originFilter) {
116
if (!m_orFilters.isEmpty()) {
117
// Set a boolean value to true when any of the conditions are found.
118
// It is set to false by default so that if none are found, we return false
119
auto filter = m_orFilters.constBegin();
120
bool foundOrCondition = false;
121
while (filter != m_orFilters.constEnd()) {
122
switch ((*filter).first) {
124
if (application->categories().contains((*filter).second)) {
125
foundOrCondition = true;
128
case PkgSectionFilter:
129
if (application->package()->latin1Section() == (*filter).second) {
130
foundOrCondition = true;
133
case PkgWildcardFilter: {
134
QString wildcard = (*filter).second;
135
wildcard.remove('*');
137
if (application->package()->name().contains(wildcard)) {
138
foundOrCondition = true;
142
case PkgNameFilter: // Only useful in the not filters
151
if (!foundOrCondition) {
156
if (!m_andFilters.isEmpty()) {
157
// Set a boolean value to false when any conditions fail to meet
158
auto filter = m_andFilters.constBegin();
159
bool andConditionsMet = true;
160
while (filter != m_andFilters.constEnd()) {
161
switch ((*filter).first) {
163
if (!application->categories().contains((*filter).second)) {
164
andConditionsMet = false;
167
case PkgSectionFilter:
168
if (!(application->package()->latin1Section() == (*filter).second)) {
169
andConditionsMet = false;
172
case PkgWildcardFilter: {
173
QString wildcard = (*filter).second;
174
wildcard.remove('*');
176
if (application->package()->name().contains(wildcard)) {
177
andConditionsMet = false;
181
case PkgNameFilter: // Only useful in the not filters
190
if (!andConditionsMet) {
195
if (!m_notFilters.isEmpty()) {
196
auto filter = m_notFilters.constBegin();
197
while (filter != m_notFilters.constEnd()) {
198
switch ((*filter).first) {
200
if (application->categories().contains((*filter).second)) {
204
case PkgSectionFilter:
205
if (application->package()->latin1Section() == (*filter).second) {
209
case PkgWildcardFilter: {
210
QString wildcard = (*filter).second;
211
wildcard.remove('*');
213
if (application->package()->name().contains(wildcard)) {
219
if (application->package()->name() == (*filter).second) {
232
if(m_sortByRelevancy) {
233
return m_packages.contains(application->package());
239
Application *ApplicationProxyModel::applicationAt(const QModelIndex &index) const
241
// Since our representation is almost bound to change, we need to grab the parent model's index
242
QModelIndex sourceIndex = mapToSource(index);
243
Application *application = static_cast<ApplicationModel *>(sourceModel())->applicationAt(sourceIndex);
247
void ApplicationProxyModel::reset()
249
beginRemoveRows(QModelIndex(), 0, m_apps.size());
250
m_apps = static_cast<ApplicationModel *>(sourceModel())->applications();
255
void ApplicationProxyModel::parentDataChanged()
257
m_apps = static_cast<ApplicationModel *>(sourceModel())->applications();
261
bool ApplicationProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
263
ApplicationModel *model = static_cast<ApplicationModel *>(sourceModel());
264
QApt::Package *leftPackage = model->applicationAt(left)->package();
265
QApt::Package *rightPackage = model->applicationAt(right)->package();
267
if (m_sortByRelevancy) {
268
// This is expensive for very large datasets. It takes about 3 seconds with 30,000 packages
269
// The order in m_packages is based on relevancy when returned by m_backend->search()
270
// Use this order to determine less than
271
if (m_packages.indexOf(leftPackage) > m_packages.indexOf(rightPackage)) {
277
QString leftString = left.data(ApplicationModel::NameRole).toString();
278
QString rightString = right.data(ApplicationModel::NameRole).toString();
280
return (QString::localeAwareCompare(leftString, rightString) < 0);