~ubuntu-branches/ubuntu/vivid/muon/vivid-proposed

« back to all changes in this revision

Viewing changes to installer/ApplicationModel/ApplicationProxyModel.cpp

Tags: upstream-1.3.65
ImportĀ upstreamĀ versionĀ 1.3.65

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
 *   Copyright Ā© 2010 Jonathan Thomas <echidnaman@kubuntu.org>             *
3
 
 *                                                                         *
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.                    *
11
 
 *                                                                         *
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.                          *
16
 
 *                                                                         *
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
 
 ***************************************************************************/
20
 
 
21
 
#include "ApplicationProxyModel.h"
22
 
 
23
 
#include <LibQApt/Backend>
24
 
 
25
 
// Own includes
26
 
#include "../Application.h"
27
 
#include "ApplicationModel.h"
28
 
 
29
 
ApplicationProxyModel::ApplicationProxyModel(QObject *parent)
30
 
    : QSortFilterProxyModel(parent)
31
 
    , m_backend(0)
32
 
    , m_stateFilter((QApt::Package::State)0)
33
 
    , m_sortByRelevancy(false)
34
 
    , m_showTechnical(false)
35
 
{
36
 
}
37
 
 
38
 
ApplicationProxyModel::~ApplicationProxyModel()
39
 
{
40
 
}
41
 
 
42
 
void ApplicationProxyModel::setBackend(QApt::Backend *backend)
43
 
{
44
 
    m_backend = backend;
45
 
    m_apps = static_cast<ApplicationModel *>(sourceModel())->applications();
46
 
}
47
 
 
48
 
void ApplicationProxyModel::search(const QString &searchText)
49
 
{
50
 
    // 1-character searches are painfully slow. >= 2 chars are fine, though
51
 
    m_packages.clear();
52
 
    if (searchText.size() > 1) {
53
 
        m_packages = m_backend->search(searchText);
54
 
        m_sortByRelevancy = true;
55
 
    } else {
56
 
        m_sortByRelevancy = false;
57
 
    }
58
 
    invalidate();
59
 
    emit invalidated();
60
 
}
61
 
 
62
 
void ApplicationProxyModel::setStateFilter(QApt::Package::State state)
63
 
{
64
 
    m_stateFilter = state;
65
 
    invalidate();
66
 
    emit invalidated();
67
 
}
68
 
 
69
 
void ApplicationProxyModel::setOriginFilter(const QString &origin)
70
 
{
71
 
    m_originFilter = origin;
72
 
    invalidate();
73
 
    emit invalidated();
74
 
}
75
 
 
76
 
void ApplicationProxyModel::setFiltersFromCategory(Category *category)
77
 
{
78
 
    m_andFilters = category->andFilters();
79
 
    m_orFilters = category->orFilters();
80
 
    m_notFilters = category->notFilters();
81
 
    invalidate();
82
 
    emit invalidated();
83
 
}
84
 
 
85
 
void ApplicationProxyModel::setShouldShowTechnical(bool show)
86
 
{
87
 
    m_showTechnical = show;
88
 
}
89
 
 
90
 
bool ApplicationProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
91
 
{
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()) {
95
 
        return false;
96
 
    }
97
 
 
98
 
    if (!m_showTechnical) {
99
 
        if (application->isTechnical()) {
100
 
            return false;
101
 
        }
102
 
    }
103
 
 
104
 
    if (m_stateFilter) {
105
 
        if ((bool)(application->package()->state() & m_stateFilter) == false) {
106
 
            return false;
107
 
        }
108
 
    }
109
 
 
110
 
    if (!m_originFilter.isEmpty()) {
111
 
        if (application->package()->origin() != m_originFilter) {
112
 
            return false;
113
 
        }
114
 
    }
115
 
 
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) {
123
 
            case CategoryFilter:
124
 
                if (application->categories().contains((*filter).second)) {
125
 
                    foundOrCondition = true;
126
 
                }
127
 
                break;
128
 
            case PkgSectionFilter:
129
 
                if (application->package()->latin1Section() == (*filter).second) {
130
 
                    foundOrCondition = true;
131
 
                }
132
 
                break;
133
 
            case PkgWildcardFilter: {
134
 
                QString wildcard = (*filter).second;
135
 
                wildcard.remove('*');
136
 
 
137
 
                if (application->package()->name().contains(wildcard)) {
138
 
                    foundOrCondition = true;
139
 
                }
140
 
                break;
141
 
            }
142
 
            case PkgNameFilter: // Only useful in the not filters
143
 
            case InvalidFilter:
144
 
            default:
145
 
                break;
146
 
            }
147
 
 
148
 
            ++filter;
149
 
        }
150
 
 
151
 
        if (!foundOrCondition) {
152
 
            return false;
153
 
        }
154
 
    }
155
 
 
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) {
162
 
            case CategoryFilter:
163
 
                if (!application->categories().contains((*filter).second)) {
164
 
                    andConditionsMet = false;
165
 
                }
166
 
                break;
167
 
            case PkgSectionFilter:
168
 
                if (!(application->package()->latin1Section() == (*filter).second)) {
169
 
                    andConditionsMet = false;
170
 
                }
171
 
                break;
172
 
            case PkgWildcardFilter: {
173
 
                QString wildcard = (*filter).second;
174
 
                wildcard.remove('*');
175
 
 
176
 
                if (application->package()->name().contains(wildcard)) {
177
 
                    andConditionsMet = false;
178
 
                }
179
 
            }
180
 
                break;
181
 
            case PkgNameFilter: // Only useful in the not filters
182
 
            case InvalidFilter:
183
 
            default:
184
 
                break;
185
 
            }
186
 
 
187
 
            ++filter;
188
 
        }
189
 
 
190
 
        if (!andConditionsMet) {
191
 
            return false;
192
 
        }
193
 
    }
194
 
 
195
 
    if (!m_notFilters.isEmpty()) {
196
 
        auto filter = m_notFilters.constBegin();
197
 
        while (filter != m_notFilters.constEnd()) {
198
 
            switch ((*filter).first) {
199
 
            case CategoryFilter:
200
 
                if (application->categories().contains((*filter).second)) {
201
 
                    return false;
202
 
                }
203
 
                break;
204
 
            case PkgSectionFilter:
205
 
                if (application->package()->latin1Section() == (*filter).second) {
206
 
                    return false;
207
 
                }
208
 
                break;
209
 
            case PkgWildcardFilter: {
210
 
                QString wildcard = (*filter).second;
211
 
                wildcard.remove('*');
212
 
 
213
 
                if (application->package()->name().contains(wildcard)) {
214
 
                    return false;
215
 
                }
216
 
            }
217
 
                break;
218
 
            case PkgNameFilter:
219
 
                if (application->package()->name() == (*filter).second) {
220
 
                    return false;
221
 
                }
222
 
                break;
223
 
            case InvalidFilter:
224
 
            default:
225
 
                break;
226
 
            }
227
 
 
228
 
            ++filter;
229
 
        }
230
 
    }
231
 
 
232
 
    if(m_sortByRelevancy) {
233
 
        return m_packages.contains(application->package());
234
 
    }
235
 
 
236
 
    return true;
237
 
}
238
 
 
239
 
Application *ApplicationProxyModel::applicationAt(const QModelIndex &index) const
240
 
{
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);
244
 
    return application;
245
 
}
246
 
 
247
 
void ApplicationProxyModel::reset()
248
 
{
249
 
    beginRemoveRows(QModelIndex(), 0, m_apps.size());
250
 
    m_apps = static_cast<ApplicationModel *>(sourceModel())->applications();
251
 
    endRemoveRows();
252
 
    invalidate();
253
 
}
254
 
 
255
 
void ApplicationProxyModel::parentDataChanged()
256
 
{
257
 
    m_apps = static_cast<ApplicationModel *>(sourceModel())->applications();
258
 
    invalidate();
259
 
}
260
 
 
261
 
bool ApplicationProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
262
 
{
263
 
    ApplicationModel *model = static_cast<ApplicationModel *>(sourceModel());
264
 
    QApt::Package *leftPackage = model->applicationAt(left)->package();
265
 
    QApt::Package *rightPackage = model->applicationAt(right)->package();
266
 
 
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)) {
272
 
            return false;
273
 
        } else {
274
 
            return true;
275
 
        }
276
 
    }
277
 
    QString leftString = left.data(ApplicationModel::NameRole).toString();
278
 
    QString rightString = right.data(ApplicationModel::NameRole).toString();
279
 
 
280
 
    return (QString::localeAwareCompare(leftString, rightString) < 0);
281
 
}