~ubuntu-branches/ubuntu/precise/gwenview/precise-proposed

« back to all changes in this revision

Viewing changes to app/filtercontroller.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2011-12-15 14:17:54 UTC
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: package-import@ubuntu.com-20111215141754-z043hyx69dulbggf
Tags: upstream-4.7.90
ImportĀ upstreamĀ versionĀ 4.7.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// vim: set tabstop=4 shiftwidth=4 noexpandtab:
 
1
// vim: set tabstop=4 shiftwidth=4 expandtab:
2
2
/*
3
3
Gwenview: an image viewer
4
4
Copyright 2008 AurĆ©lien GĆ¢teau <agateau@kde.org>
61
61
#include <lib/semanticinfo/tagmodel.h>
62
62
#endif
63
63
 
64
 
namespace Gwenview {
 
64
namespace Gwenview
 
65
{
65
66
 
66
67
/**
67
68
 * An AbstractSortedDirModelFilter which filters on the file names
68
69
 */
69
 
class NameFilter : public AbstractSortedDirModelFilter {
 
70
class NameFilter : public AbstractSortedDirModelFilter
 
71
{
70
72
public:
71
 
        enum Mode {
72
 
                Contains,
73
 
                DoesNotContain
74
 
        };
75
 
        NameFilter(SortedDirModel* model)
76
 
        : AbstractSortedDirModelFilter(model)
77
 
        , mText()
78
 
        , mMode(Contains)
79
 
        {}
80
 
 
81
 
        virtual bool needsSemanticInfo() const {
82
 
                return false;
83
 
        }
84
 
 
85
 
        virtual bool acceptsIndex(const QModelIndex& index) const {
86
 
                if (mText.isEmpty()) {
87
 
                        return true;
88
 
                }
89
 
                switch (mMode) {
90
 
                case Contains:
91
 
                        return index.data().toString().contains(mText, Qt::CaseInsensitive);
92
 
                default: /*DoesNotContain:*/
93
 
                        return !index.data().toString().contains(mText, Qt::CaseInsensitive);
94
 
                }
95
 
        }
96
 
 
97
 
        void setText(const QString& text) {
98
 
                mText = text;
99
 
                model()->applyFilters();
100
 
        }
101
 
 
102
 
        void setMode(Mode mode) {
103
 
                mMode = mode;
104
 
                model()->applyFilters();
105
 
        }
 
73
    enum Mode {
 
74
        Contains,
 
75
        DoesNotContain
 
76
    };
 
77
    NameFilter(SortedDirModel* model)
 
78
        : AbstractSortedDirModelFilter(model)
 
79
        , mText()
 
80
        , mMode(Contains)
 
81
    {}
 
82
 
 
83
    virtual bool needsSemanticInfo() const {
 
84
        return false;
 
85
    }
 
86
 
 
87
    virtual bool acceptsIndex(const QModelIndex& index) const {
 
88
        if (mText.isEmpty()) {
 
89
            return true;
 
90
        }
 
91
        switch (mMode) {
 
92
        case Contains:
 
93
            return index.data().toString().contains(mText, Qt::CaseInsensitive);
 
94
        default: /*DoesNotContain:*/
 
95
            return !index.data().toString().contains(mText, Qt::CaseInsensitive);
 
96
        }
 
97
    }
 
98
 
 
99
    void setText(const QString& text)
 
100
    {
 
101
        mText = text;
 
102
        model()->applyFilters();
 
103
    }
 
104
 
 
105
    void setMode(Mode mode)
 
106
    {
 
107
        mMode = mode;
 
108
        model()->applyFilters();
 
109
    }
106
110
 
107
111
private:
108
 
        QString mText;
109
 
        Mode mMode;
 
112
    QString mText;
 
113
    Mode mMode;
110
114
};
111
115
 
112
116
struct NameFilterWidgetPrivate {
113
 
        QPointer<NameFilter> mFilter;
114
 
        KComboBox* mModeComboBox;
115
 
        KLineEdit* mLineEdit;
 
117
    QPointer<NameFilter> mFilter;
 
118
    KComboBox* mModeComboBox;
 
119
    KLineEdit* mLineEdit;
116
120
};
117
121
 
118
122
NameFilterWidget::NameFilterWidget(SortedDirModel* model)
119
123
: d(new NameFilterWidgetPrivate)
120
124
{
121
 
        d->mFilter = new NameFilter(model);
122
 
 
123
 
        d->mModeComboBox = new KComboBox;
124
 
        d->mModeComboBox->addItem(i18n("Name contains"), QVariant(NameFilter::Contains));
125
 
        d->mModeComboBox->addItem(i18n("Name does not contain"), QVariant(NameFilter::DoesNotContain));
126
 
 
127
 
        d->mLineEdit = new KLineEdit;
128
 
 
129
 
        QHBoxLayout* layout = new QHBoxLayout(this);
130
 
        layout->setMargin(0);
131
 
        layout->setSpacing(2);
132
 
        layout->addWidget(d->mModeComboBox);
133
 
        layout->addWidget(d->mLineEdit);
134
 
 
135
 
        QTimer* timer = new QTimer(this);
136
 
        timer->setInterval(350);
137
 
        timer->setSingleShot(true);
138
 
        connect(timer, SIGNAL(timeout()), SLOT(applyNameFilter()));
139
 
 
140
 
        connect(d->mLineEdit, SIGNAL(textChanged(const QString &)),
141
 
                timer, SLOT(start()));
142
 
 
143
 
        connect(d->mModeComboBox, SIGNAL(currentIndexChanged(int)),
144
 
                SLOT(applyNameFilter()));
145
 
 
146
 
        QTimer::singleShot(0, d->mLineEdit, SLOT(setFocus()));
 
125
    d->mFilter = new NameFilter(model);
 
126
 
 
127
    d->mModeComboBox = new KComboBox;
 
128
    d->mModeComboBox->addItem(i18n("Name contains"), QVariant(NameFilter::Contains));
 
129
    d->mModeComboBox->addItem(i18n("Name does not contain"), QVariant(NameFilter::DoesNotContain));
 
130
 
 
131
    d->mLineEdit = new KLineEdit;
 
132
 
 
133
    QHBoxLayout* layout = new QHBoxLayout(this);
 
134
    layout->setMargin(0);
 
135
    layout->setSpacing(2);
 
136
    layout->addWidget(d->mModeComboBox);
 
137
    layout->addWidget(d->mLineEdit);
 
138
 
 
139
    QTimer* timer = new QTimer(this);
 
140
    timer->setInterval(350);
 
141
    timer->setSingleShot(true);
 
142
    connect(timer, SIGNAL(timeout()), SLOT(applyNameFilter()));
 
143
 
 
144
    connect(d->mLineEdit, SIGNAL(textChanged(QString)),
 
145
            timer, SLOT(start()));
 
146
 
 
147
    connect(d->mModeComboBox, SIGNAL(currentIndexChanged(int)),
 
148
            SLOT(applyNameFilter()));
 
149
 
 
150
    QTimer::singleShot(0, d->mLineEdit, SLOT(setFocus()));
147
151
}
148
152
 
149
153
NameFilterWidget::~NameFilterWidget()
150
154
{
151
 
        delete d->mFilter;
152
 
        delete d;
 
155
    delete d->mFilter;
 
156
    delete d;
153
157
}
154
158
 
155
 
void NameFilterWidget::applyNameFilter() {
156
 
        QVariant data = d->mModeComboBox->itemData(d->mModeComboBox->currentIndex());
157
 
        d->mFilter->setMode(NameFilter::Mode(data.toInt()));
158
 
        d->mFilter->setText(d->mLineEdit->text());
 
159
void NameFilterWidget::applyNameFilter()
 
160
{
 
161
    QVariant data = d->mModeComboBox->itemData(d->mModeComboBox->currentIndex());
 
162
    d->mFilter->setMode(NameFilter::Mode(data.toInt()));
 
163
    d->mFilter->setText(d->mLineEdit->text());
159
164
}
160
165
 
161
166
/**
162
167
 * An AbstractSortedDirModelFilter which filters on the file dates
163
168
 */
164
 
class DateFilter : public AbstractSortedDirModelFilter {
 
169
class DateFilter : public AbstractSortedDirModelFilter
 
170
{
165
171
public:
166
 
        enum Mode {
167
 
                GreaterOrEqual,
168
 
                Equal,
169
 
                LessOrEqual
170
 
        };
171
 
        DateFilter(SortedDirModel* model)
172
 
        : AbstractSortedDirModelFilter(model)
173
 
        , mMode(GreaterOrEqual)
174
 
        {}
175
 
 
176
 
        virtual bool needsSemanticInfo() const {
177
 
                return false;
178
 
        }
179
 
 
180
 
        virtual bool acceptsIndex(const QModelIndex& index) const {
181
 
                if (!mDate.isValid()) {
182
 
                        return true;
183
 
                }
184
 
                KFileItem fileItem = model()->itemForSourceIndex(index);
185
 
                QDate date = TimeUtils::dateTimeForFileItem(fileItem).date();
186
 
                switch (mMode) {
187
 
                case GreaterOrEqual:
188
 
                        return date >= mDate;
189
 
                case Equal:
190
 
                        return date == mDate;
191
 
                default: /* LessOrEqual */
192
 
                        return date <= mDate;
193
 
                }
194
 
        }
195
 
 
196
 
        void setDate(const QDate& date) {
197
 
                mDate = date;
198
 
                model()->applyFilters();
199
 
        }
200
 
 
201
 
        void setMode(Mode mode) {
202
 
                mMode = mode;
203
 
                model()->applyFilters();
204
 
        }
 
172
    enum Mode {
 
173
        GreaterOrEqual,
 
174
        Equal,
 
175
        LessOrEqual
 
176
    };
 
177
    DateFilter(SortedDirModel* model)
 
178
        : AbstractSortedDirModelFilter(model)
 
179
        , mMode(GreaterOrEqual)
 
180
    {}
 
181
 
 
182
    virtual bool needsSemanticInfo() const {
 
183
        return false;
 
184
    }
 
185
 
 
186
    virtual bool acceptsIndex(const QModelIndex& index) const {
 
187
        if (!mDate.isValid()) {
 
188
            return true;
 
189
        }
 
190
        KFileItem fileItem = model()->itemForSourceIndex(index);
 
191
        QDate date = TimeUtils::dateTimeForFileItem(fileItem).date();
 
192
        switch (mMode) {
 
193
        case GreaterOrEqual:
 
194
            return date >= mDate;
 
195
        case Equal:
 
196
            return date == mDate;
 
197
        default: /* LessOrEqual */
 
198
            return date <= mDate;
 
199
        }
 
200
    }
 
201
 
 
202
    void setDate(const QDate& date)
 
203
    {
 
204
        mDate = date;
 
205
        model()->applyFilters();
 
206
    }
 
207
 
 
208
    void setMode(Mode mode)
 
209
    {
 
210
        mMode = mode;
 
211
        model()->applyFilters();
 
212
    }
205
213
 
206
214
private:
207
 
        QDate mDate;
208
 
        Mode mMode;
 
215
    QDate mDate;
 
216
    Mode mMode;
209
217
};
210
218
 
211
219
struct DateFilterWidgetPrivate {
212
 
        QPointer<DateFilter> mFilter;
213
 
        KComboBox* mModeComboBox;
214
 
        DateWidget* mDateWidget;
 
220
    QPointer<DateFilter> mFilter;
 
221
    KComboBox* mModeComboBox;
 
222
    DateWidget* mDateWidget;
215
223
};
216
224
 
217
225
DateFilterWidget::DateFilterWidget(SortedDirModel* model)
218
226
: d(new DateFilterWidgetPrivate)
219
227
{
220
 
        d->mFilter = new DateFilter(model);
221
 
 
222
 
        d->mModeComboBox = new KComboBox;
223
 
        d->mModeComboBox->addItem(i18n("Date >="), DateFilter::GreaterOrEqual);
224
 
        d->mModeComboBox->addItem(i18n("Date ="),  DateFilter::Equal);
225
 
        d->mModeComboBox->addItem(i18n("Date <="), DateFilter::LessOrEqual);
226
 
 
227
 
        d->mDateWidget = new DateWidget;
228
 
 
229
 
        QHBoxLayout* layout = new QHBoxLayout(this);
230
 
        layout->setMargin(0);
231
 
        layout->addWidget(d->mModeComboBox);
232
 
        layout->addWidget(d->mDateWidget);
233
 
 
234
 
        connect(d->mDateWidget, SIGNAL(dateChanged(const QDate&)),
235
 
                SLOT(applyDateFilter()));
236
 
        connect(d->mModeComboBox, SIGNAL(currentIndexChanged(int)),
237
 
                SLOT(applyDateFilter()));
238
 
 
239
 
        applyDateFilter();
 
228
    d->mFilter = new DateFilter(model);
 
229
 
 
230
    d->mModeComboBox = new KComboBox;
 
231
    d->mModeComboBox->addItem(i18n("Date >="), DateFilter::GreaterOrEqual);
 
232
    d->mModeComboBox->addItem(i18n("Date ="),  DateFilter::Equal);
 
233
    d->mModeComboBox->addItem(i18n("Date <="), DateFilter::LessOrEqual);
 
234
 
 
235
    d->mDateWidget = new DateWidget;
 
236
 
 
237
    QHBoxLayout* layout = new QHBoxLayout(this);
 
238
    layout->setMargin(0);
 
239
    layout->addWidget(d->mModeComboBox);
 
240
    layout->addWidget(d->mDateWidget);
 
241
 
 
242
    connect(d->mDateWidget, SIGNAL(dateChanged(QDate)),
 
243
            SLOT(applyDateFilter()));
 
244
    connect(d->mModeComboBox, SIGNAL(currentIndexChanged(int)),
 
245
            SLOT(applyDateFilter()));
 
246
 
 
247
    applyDateFilter();
240
248
}
241
249
 
242
250
DateFilterWidget::~DateFilterWidget()
243
251
{
244
 
        delete d->mFilter;
245
 
        delete d;
 
252
    delete d->mFilter;
 
253
    delete d;
246
254
}
247
255
 
248
 
void DateFilterWidget::applyDateFilter() {
249
 
        QVariant data = d->mModeComboBox->itemData(d->mModeComboBox->currentIndex());
250
 
        d->mFilter->setMode(DateFilter::Mode(data.toInt()));
251
 
        d->mFilter->setDate(d->mDateWidget->date());
 
256
void DateFilterWidget::applyDateFilter()
 
257
{
 
258
    QVariant data = d->mModeComboBox->itemData(d->mModeComboBox->currentIndex());
 
259
    d->mFilter->setMode(DateFilter::Mode(data.toInt()));
 
260
    d->mFilter->setDate(d->mDateWidget->date());
252
261
}
253
262
 
254
263
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
255
264
/**
256
265
 * An AbstractSortedDirModelFilter which filters on file ratings
257
266
 */
258
 
class RatingFilter : public AbstractSortedDirModelFilter {
 
267
class RatingFilter : public AbstractSortedDirModelFilter
 
268
{
259
269
public:
260
 
        enum Mode {
261
 
                GreaterOrEqual,
262
 
                Equal,
263
 
                LessOrEqual
264
 
        };
265
 
 
266
 
        RatingFilter(SortedDirModel* model)
267
 
        : AbstractSortedDirModelFilter(model)
268
 
        , mRating(0)
269
 
        , mMode(GreaterOrEqual) {}
270
 
 
271
 
        virtual bool needsSemanticInfo() const {
272
 
                return true;
273
 
        }
274
 
 
275
 
        virtual bool acceptsIndex(const QModelIndex& index) const {
276
 
                SemanticInfo info = model()->semanticInfoForSourceIndex(index);
277
 
                switch (mMode) {
278
 
                case GreaterOrEqual:
279
 
                        return info.mRating >= mRating;
280
 
                case Equal:
281
 
                        return info.mRating == mRating;
282
 
                default: /* LessOrEqual */
283
 
                        return info.mRating <= mRating;
284
 
                }
285
 
        }
286
 
 
287
 
        void setRating(int value) {
288
 
                mRating = value;
289
 
                model()->applyFilters();
290
 
        }
291
 
 
292
 
        void setMode(Mode mode) {
293
 
                mMode = mode;
294
 
                model()->applyFilters();
295
 
        }
 
270
    enum Mode {
 
271
        GreaterOrEqual,
 
272
        Equal,
 
273
        LessOrEqual
 
274
    };
 
275
 
 
276
    RatingFilter(SortedDirModel* model)
 
277
        : AbstractSortedDirModelFilter(model)
 
278
        , mRating(0)
 
279
        , mMode(GreaterOrEqual) {}
 
280
 
 
281
    virtual bool needsSemanticInfo() const {
 
282
        return true;
 
283
    }
 
284
 
 
285
    virtual bool acceptsIndex(const QModelIndex& index) const {
 
286
        SemanticInfo info = model()->semanticInfoForSourceIndex(index);
 
287
        switch (mMode) {
 
288
        case GreaterOrEqual:
 
289
            return info.mRating >= mRating;
 
290
        case Equal:
 
291
            return info.mRating == mRating;
 
292
        default: /* LessOrEqual */
 
293
            return info.mRating <= mRating;
 
294
        }
 
295
    }
 
296
 
 
297
    void setRating(int value)
 
298
    {
 
299
        mRating = value;
 
300
        model()->applyFilters();
 
301
    }
 
302
 
 
303
    void setMode(Mode mode)
 
304
    {
 
305
        mMode = mode;
 
306
        model()->applyFilters();
 
307
    }
296
308
 
297
309
private:
298
 
        int mRating;
299
 
        Mode mMode;
 
310
    int mRating;
 
311
    Mode mMode;
300
312
};
301
313
 
302
314
struct RatingWidgetPrivate {
303
 
        KComboBox* mModeComboBox;
304
 
        KRatingWidget* mRatingWidget;
305
 
        QPointer<RatingFilter> mFilter;
 
315
    KComboBox* mModeComboBox;
 
316
    KRatingWidget* mRatingWidget;
 
317
    QPointer<RatingFilter> mFilter;
306
318
};
307
319
 
308
320
RatingFilterWidget::RatingFilterWidget(SortedDirModel* model)
309
 
: d(new RatingWidgetPrivate) {
310
 
        d->mModeComboBox = new KComboBox;
311
 
        d->mModeComboBox->addItem(i18n("Rating >="), RatingFilter::GreaterOrEqual);
312
 
        d->mModeComboBox->addItem(i18n("Rating =") , RatingFilter::Equal);
313
 
        d->mModeComboBox->addItem(i18n("Rating <="), RatingFilter::LessOrEqual);
314
 
 
315
 
        d->mRatingWidget = new KRatingWidget;
316
 
        d->mRatingWidget->setHalfStepsEnabled(true);
317
 
        d->mRatingWidget->setMaxRating(10);
318
 
 
319
 
        QHBoxLayout* layout = new QHBoxLayout(this);
320
 
        layout->setMargin(0);
321
 
        layout->addWidget(d->mModeComboBox);
322
 
        layout->addWidget(d->mRatingWidget);
323
 
 
324
 
        d->mFilter = new RatingFilter(model);
325
 
 
326
 
        QObject::connect(d->mModeComboBox, SIGNAL(currentIndexChanged(int)),
327
 
                SLOT(updateFilterMode()));
328
 
 
329
 
        QObject::connect(d->mRatingWidget, SIGNAL(ratingChanged(int)),
330
 
                SLOT(slotRatingChanged(int)));
331
 
 
332
 
        updateFilterMode();
333
 
}
334
 
 
335
 
 
336
 
RatingFilterWidget::~RatingFilterWidget() {
337
 
        delete d->mFilter;
338
 
        delete d;
339
 
}
340
 
 
341
 
 
342
 
void RatingFilterWidget::slotRatingChanged(int value) {
343
 
        d->mFilter->setRating(value);
344
 
}
345
 
 
346
 
 
347
 
void RatingFilterWidget::updateFilterMode() {
348
 
        QVariant data = d->mModeComboBox->itemData(d->mModeComboBox->currentIndex());
349
 
        d->mFilter->setMode(RatingFilter::Mode(data.toInt()));
350
 
}
351
 
 
 
321
: d(new RatingWidgetPrivate)
 
322
{
 
323
    d->mModeComboBox = new KComboBox;
 
324
    d->mModeComboBox->addItem(i18n("Rating >="), RatingFilter::GreaterOrEqual);
 
325
    d->mModeComboBox->addItem(i18n("Rating =") , RatingFilter::Equal);
 
326
    d->mModeComboBox->addItem(i18n("Rating <="), RatingFilter::LessOrEqual);
 
327
 
 
328
    d->mRatingWidget = new KRatingWidget;
 
329
    d->mRatingWidget->setHalfStepsEnabled(true);
 
330
    d->mRatingWidget->setMaxRating(10);
 
331
 
 
332
    QHBoxLayout* layout = new QHBoxLayout(this);
 
333
    layout->setMargin(0);
 
334
    layout->addWidget(d->mModeComboBox);
 
335
    layout->addWidget(d->mRatingWidget);
 
336
 
 
337
    d->mFilter = new RatingFilter(model);
 
338
 
 
339
    QObject::connect(d->mModeComboBox, SIGNAL(currentIndexChanged(int)),
 
340
                     SLOT(updateFilterMode()));
 
341
 
 
342
    QObject::connect(d->mRatingWidget, SIGNAL(ratingChanged(int)),
 
343
                     SLOT(slotRatingChanged(int)));
 
344
 
 
345
    updateFilterMode();
 
346
}
 
347
 
 
348
RatingFilterWidget::~RatingFilterWidget()
 
349
{
 
350
    delete d->mFilter;
 
351
    delete d;
 
352
}
 
353
 
 
354
void RatingFilterWidget::slotRatingChanged(int value)
 
355
{
 
356
    d->mFilter->setRating(value);
 
357
}
 
358
 
 
359
void RatingFilterWidget::updateFilterMode()
 
360
{
 
361
    QVariant data = d->mModeComboBox->itemData(d->mModeComboBox->currentIndex());
 
362
    d->mFilter->setMode(RatingFilter::Mode(data.toInt()));
 
363
}
352
364
 
353
365
/**
354
366
 * An AbstractSortedDirModelFilter which filters on associated tags
355
367
 */
356
 
class TagFilter : public AbstractSortedDirModelFilter {
 
368
class TagFilter : public AbstractSortedDirModelFilter
 
369
{
357
370
public:
358
 
        TagFilter(SortedDirModel* model)
359
 
        : AbstractSortedDirModelFilter(model)
360
 
        , mWantMatchingTag(true)
361
 
        {}
362
 
 
363
 
        virtual bool needsSemanticInfo() const {
364
 
                return true;
365
 
        }
366
 
 
367
 
        virtual bool acceptsIndex(const QModelIndex& index) const {
368
 
                if (mTag.isEmpty()) {
369
 
                        return true;
370
 
                }
371
 
                SemanticInfo info = model()->semanticInfoForSourceIndex(index);
372
 
                if (mWantMatchingTag) {
373
 
                        return info.mTags.contains(mTag);
374
 
                } else {
375
 
                        return !info.mTags.contains(mTag);
376
 
                }
377
 
        }
378
 
 
379
 
        void setTag(const SemanticInfoTag& tag) {
380
 
                mTag = tag;
381
 
                model()->applyFilters();
382
 
        }
383
 
 
384
 
        void setWantMatchingTag(bool value) {
385
 
                mWantMatchingTag = value;
386
 
                model()->applyFilters();
387
 
        }
 
371
    TagFilter(SortedDirModel* model)
 
372
        : AbstractSortedDirModelFilter(model)
 
373
        , mWantMatchingTag(true)
 
374
    {}
 
375
 
 
376
    virtual bool needsSemanticInfo() const {
 
377
        return true;
 
378
    }
 
379
 
 
380
    virtual bool acceptsIndex(const QModelIndex& index) const {
 
381
        if (mTag.isEmpty()) {
 
382
            return true;
 
383
        }
 
384
        SemanticInfo info = model()->semanticInfoForSourceIndex(index);
 
385
        if (mWantMatchingTag) {
 
386
            return info.mTags.contains(mTag);
 
387
        } else {
 
388
            return !info.mTags.contains(mTag);
 
389
        }
 
390
    }
 
391
 
 
392
    void setTag(const SemanticInfoTag& tag)
 
393
    {
 
394
        mTag = tag;
 
395
        model()->applyFilters();
 
396
    }
 
397
 
 
398
    void setWantMatchingTag(bool value)
 
399
    {
 
400
        mWantMatchingTag = value;
 
401
        model()->applyFilters();
 
402
    }
388
403
 
389
404
private:
390
 
        SemanticInfoTag mTag;
391
 
        bool mWantMatchingTag;
 
405
    SemanticInfoTag mTag;
 
406
    bool mWantMatchingTag;
392
407
};
393
408
 
394
409
struct TagFilterWidgetPrivate {
395
 
        KComboBox* mModeComboBox;
396
 
        QComboBox* mTagComboBox;
397
 
        QPointer<TagFilter> mFilter;
 
410
    KComboBox* mModeComboBox;
 
411
    QComboBox* mTagComboBox;
 
412
    QPointer<TagFilter> mFilter;
398
413
};
399
414
 
400
415
TagFilterWidget::TagFilterWidget(SortedDirModel* model)
401
 
: d(new TagFilterWidgetPrivate) {
402
 
        d->mFilter = new TagFilter(model);
403
 
 
404
 
        d->mModeComboBox = new KComboBox;
405
 
        d->mModeComboBox->addItem(i18n("Tagged"), QVariant(true));
406
 
        d->mModeComboBox->addItem(i18n("Not Tagged"), QVariant(false));
407
 
 
408
 
        d->mTagComboBox = new QComboBox;
409
 
 
410
 
        QHBoxLayout* layout = new QHBoxLayout(this);
411
 
        layout->setMargin(0);
412
 
        layout->addWidget(d->mModeComboBox);
413
 
        layout->addWidget(d->mTagComboBox);
414
 
 
415
 
        AbstractSemanticInfoBackEnd* backEnd = model->semanticInfoBackEnd();
416
 
        backEnd->refreshAllTags();
417
 
        TagModel* tagModel = TagModel::createAllTagsModel(this, backEnd);
418
 
 
419
 
        QCompleter* completer = new QCompleter(d->mTagComboBox);
420
 
        completer->setCaseSensitivity(Qt::CaseInsensitive);
421
 
        completer->setModel(tagModel);
422
 
        d->mTagComboBox->setCompleter(completer);
423
 
        d->mTagComboBox->setInsertPolicy(QComboBox::NoInsert);
424
 
        d->mTagComboBox->setEditable(true);
425
 
        d->mTagComboBox->setModel(tagModel);
426
 
        d->mTagComboBox->setCurrentIndex(-1);
427
 
 
428
 
        connect(d->mTagComboBox, SIGNAL(currentIndexChanged(int)), SLOT(updateTagSetFilter()) );
429
 
 
430
 
        connect(d->mModeComboBox, SIGNAL(currentIndexChanged(int)), SLOT(updateTagSetFilter()) );
431
 
 
432
 
        QTimer::singleShot(0, d->mTagComboBox, SLOT(setFocus()));
433
 
}
434
 
 
435
 
TagFilterWidget::~TagFilterWidget() {
436
 
        delete d->mFilter;
437
 
        delete d;
438
 
}
439
 
 
440
 
 
441
 
void TagFilterWidget::updateTagSetFilter() {
442
 
        QModelIndex index = d->mTagComboBox->model()->index(d->mTagComboBox->currentIndex(), 0);
443
 
        if (!index.isValid()) {
444
 
                kWarning() << "Invalid index";
445
 
                return;
446
 
        }
447
 
        SemanticInfoTag tag = index.data(TagModel::TagRole).toString();
448
 
        d->mFilter->setTag(tag);
449
 
 
450
 
        bool wantMatchingTag = d->mModeComboBox->itemData(d->mModeComboBox->currentIndex()).toBool();
451
 
        d->mFilter->setWantMatchingTag(wantMatchingTag);
 
416
: d(new TagFilterWidgetPrivate)
 
417
{
 
418
    d->mFilter = new TagFilter(model);
 
419
 
 
420
    d->mModeComboBox = new KComboBox;
 
421
    d->mModeComboBox->addItem(i18n("Tagged"), QVariant(true));
 
422
    d->mModeComboBox->addItem(i18n("Not Tagged"), QVariant(false));
 
423
 
 
424
    d->mTagComboBox = new QComboBox;
 
425
 
 
426
    QHBoxLayout* layout = new QHBoxLayout(this);
 
427
    layout->setMargin(0);
 
428
    layout->addWidget(d->mModeComboBox);
 
429
    layout->addWidget(d->mTagComboBox);
 
430
 
 
431
    AbstractSemanticInfoBackEnd* backEnd = model->semanticInfoBackEnd();
 
432
    backEnd->refreshAllTags();
 
433
    TagModel* tagModel = TagModel::createAllTagsModel(this, backEnd);
 
434
 
 
435
    QCompleter* completer = new QCompleter(d->mTagComboBox);
 
436
    completer->setCaseSensitivity(Qt::CaseInsensitive);
 
437
    completer->setModel(tagModel);
 
438
    d->mTagComboBox->setCompleter(completer);
 
439
    d->mTagComboBox->setInsertPolicy(QComboBox::NoInsert);
 
440
    d->mTagComboBox->setEditable(true);
 
441
    d->mTagComboBox->setModel(tagModel);
 
442
    d->mTagComboBox->setCurrentIndex(-1);
 
443
 
 
444
    connect(d->mTagComboBox, SIGNAL(currentIndexChanged(int)), SLOT(updateTagSetFilter()));
 
445
 
 
446
    connect(d->mModeComboBox, SIGNAL(currentIndexChanged(int)), SLOT(updateTagSetFilter()));
 
447
 
 
448
    QTimer::singleShot(0, d->mTagComboBox, SLOT(setFocus()));
 
449
}
 
450
 
 
451
TagFilterWidget::~TagFilterWidget()
 
452
{
 
453
    delete d->mFilter;
 
454
    delete d;
 
455
}
 
456
 
 
457
void TagFilterWidget::updateTagSetFilter()
 
458
{
 
459
    QModelIndex index = d->mTagComboBox->model()->index(d->mTagComboBox->currentIndex(), 0);
 
460
    if (!index.isValid()) {
 
461
        kWarning() << "Invalid index";
 
462
        return;
 
463
    }
 
464
    SemanticInfoTag tag = index.data(TagModel::TagRole).toString();
 
465
    d->mFilter->setTag(tag);
 
466
 
 
467
    bool wantMatchingTag = d->mModeComboBox->itemData(d->mModeComboBox->currentIndex()).toBool();
 
468
    d->mFilter->setWantMatchingTag(wantMatchingTag);
452
469
}
453
470
#endif
454
471
 
455
 
 
456
472
/**
457
473
 * A container for all filter widgets. It features a close button on the right.
458
474
 */
459
 
class FilterWidgetContainer : public QFrame {
 
475
class FilterWidgetContainer : public QFrame
 
476
{
460
477
public:
461
 
        FilterWidgetContainer() {
462
 
                QPalette pal = palette();
463
 
                pal.setColor(QPalette::Window, pal.color(QPalette::Highlight));
464
 
                setPalette(pal);
465
 
        }
 
478
    FilterWidgetContainer() {
 
479
        QPalette pal = palette();
 
480
        pal.setColor(QPalette::Window, pal.color(QPalette::Highlight));
 
481
        setPalette(pal);
 
482
    }
466
483
 
467
 
        void setFilterWidget(QWidget* widget) {
468
 
                QToolButton* closeButton = new QToolButton;
469
 
                closeButton->setIcon(KIcon("window-close"));
470
 
                closeButton->setAutoRaise(true);
471
 
                closeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
472
 
                int size = IconSize(KIconLoader::Small);
473
 
                closeButton->setIconSize(QSize(size, size));
474
 
                connect(closeButton, SIGNAL(clicked()), SLOT(deleteLater()));
475
 
                QHBoxLayout* layout = new QHBoxLayout(this);
476
 
                layout->setMargin(2);
477
 
                layout->setSpacing(2);
478
 
                layout->addWidget(widget);
479
 
                layout->addWidget(closeButton);
480
 
        }
 
484
    void setFilterWidget(QWidget* widget)
 
485
    {
 
486
        QToolButton* closeButton = new QToolButton;
 
487
        closeButton->setIcon(KIcon("window-close"));
 
488
        closeButton->setAutoRaise(true);
 
489
        closeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
 
490
        int size = IconSize(KIconLoader::Small);
 
491
        closeButton->setIconSize(QSize(size, size));
 
492
        connect(closeButton, SIGNAL(clicked()), SLOT(deleteLater()));
 
493
        QHBoxLayout* layout = new QHBoxLayout(this);
 
494
        layout->setMargin(2);
 
495
        layout->setSpacing(2);
 
496
        layout->addWidget(widget);
 
497
        layout->addWidget(closeButton);
 
498
    }
481
499
 
482
500
protected:
483
 
        virtual void paintEvent(QPaintEvent*) {
484
 
                QPainter painter(this);
485
 
                painter.setRenderHint(QPainter::Antialiasing);
486
 
                QPainterPath path = PaintUtils::roundedRectangle(QRectF(rect()).adjusted(0.5, 0.5, -0.5, -0.5), 6);
 
501
    virtual void paintEvent(QPaintEvent*)
 
502
    {
 
503
        QPainter painter(this);
 
504
        painter.setRenderHint(QPainter::Antialiasing);
 
505
        QPainterPath path = PaintUtils::roundedRectangle(QRectF(rect()).adjusted(0.5, 0.5, -0.5, -0.5), 6);
487
506
 
488
 
                QColor color = palette().color(QPalette::Highlight);
489
 
                painter.fillPath(path, PaintUtils::alphaAdjustedF(color, 0.5));
490
 
                painter.setPen(color);
491
 
                painter.drawPath(path);
492
 
        }
 
507
        QColor color = palette().color(QPalette::Highlight);
 
508
        painter.fillPath(path, PaintUtils::alphaAdjustedF(color, 0.5));
 
509
        painter.setPen(color);
 
510
        painter.drawPath(path);
 
511
    }
493
512
};
494
513
 
495
 
 
496
514
struct FilterControllerPrivate {
497
 
        FilterController* that;
498
 
        QFrame* mFrame;
499
 
        SortedDirModel* mDirModel;
500
 
        QList<QAction*> mActionList;
501
 
 
502
 
        int mFilterWidgetCount; /**< How many filter widgets are in mFrame */
503
 
 
504
 
        void addAction(const QString& text, const char* slot) {
505
 
                QAction* action = new QAction(text, that);
506
 
                QObject::connect(action, SIGNAL(triggered()), that, slot);
507
 
                mActionList << action;
508
 
        }
509
 
 
510
 
        void addFilter(QWidget* widget) {
511
 
                if (mFrame->isHidden()) {
512
 
                        mFrame->show();
513
 
                }
514
 
                FilterWidgetContainer* container = new FilterWidgetContainer;
515
 
                container->setFilterWidget(widget);
516
 
                mFrame->layout()->addWidget(container);
517
 
 
518
 
                mFilterWidgetCount++;
519
 
                QObject::connect(container, SIGNAL(destroyed()), that, SLOT(slotFilterWidgetClosed()));
520
 
        }
 
515
    FilterController* q;
 
516
    QFrame* mFrame;
 
517
    SortedDirModel* mDirModel;
 
518
    QList<QAction*> mActionList;
 
519
 
 
520
    int mFilterWidgetCount; /**< How many filter widgets are in mFrame */
 
521
 
 
522
    void addAction(const QString& text, const char* slot)
 
523
    {
 
524
        QAction* action = new QAction(text, q);
 
525
        QObject::connect(action, SIGNAL(triggered()), q, slot);
 
526
        mActionList << action;
 
527
    }
 
528
 
 
529
    void addFilter(QWidget* widget)
 
530
    {
 
531
        if (mFrame->isHidden()) {
 
532
            mFrame->show();
 
533
        }
 
534
        FilterWidgetContainer* container = new FilterWidgetContainer;
 
535
        container->setFilterWidget(widget);
 
536
        mFrame->layout()->addWidget(container);
 
537
 
 
538
        mFilterWidgetCount++;
 
539
        QObject::connect(container, SIGNAL(destroyed()), q, SLOT(slotFilterWidgetClosed()));
 
540
    }
521
541
};
522
542
 
523
 
 
524
543
FilterController::FilterController(QFrame* frame, SortedDirModel* dirModel)
525
544
: QObject(frame)
526
 
, d(new FilterControllerPrivate) {
527
 
        d->that = this;
528
 
        d->mFrame = frame;
529
 
        d->mDirModel = dirModel;
530
 
        d->mFilterWidgetCount = 0;
531
 
 
532
 
        d->mFrame->hide();
533
 
        FlowLayout* layout = new FlowLayout(d->mFrame);
534
 
        layout->setSpacing(2);
535
 
 
536
 
        d->addAction(i18nc("@action:inmenu", "Filter by Name"), SLOT(addFilterByName()));
537
 
        d->addAction(i18nc("@action:inmenu", "Filter by Date"), SLOT(addFilterByDate()));
538
 
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
539
 
#ifdef GWENVIEW_SEMANTICINFO_BACKEND_NEPOMUK
540
 
        // Only add filters if Nepomuk is running
541
 
        if (Nepomuk::ResourceManager::instance()->init() == 0) {
542
 
#endif
543
 
                d->addAction(i18nc("@action:inmenu", "Filter by Rating"), SLOT(addFilterByRating()));
544
 
                d->addAction(i18nc("@action:inmenu", "Filter by Tag"), SLOT(addFilterByTag()));
545
 
#ifdef GWENVIEW_SEMANTICINFO_BACKEND_NEPOMUK
546
 
        }
547
 
#endif
548
 
#endif
549
 
}
550
 
 
551
 
 
552
 
FilterController::~FilterController() {
553
 
        delete d;
554
 
}
555
 
 
556
 
 
557
 
QList<QAction*> FilterController::actionList() const {
558
 
        return d->mActionList;
559
 
}
560
 
 
561
 
 
562
 
void FilterController::addFilterByName() {
563
 
        d->addFilter(new NameFilterWidget(d->mDirModel));
564
 
}
565
 
 
566
 
 
567
 
void FilterController::addFilterByDate() {
568
 
        d->addFilter(new DateFilterWidget(d->mDirModel));
569
 
}
570
 
 
571
 
 
572
 
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
573
 
void FilterController::addFilterByRating() {
574
 
        d->addFilter(new RatingFilterWidget(d->mDirModel));
575
 
}
576
 
 
577
 
 
578
 
void FilterController::addFilterByTag() {
579
 
        d->addFilter(new TagFilterWidget(d->mDirModel));
580
 
}
581
 
#endif
582
 
 
583
 
 
584
 
void FilterController::slotFilterWidgetClosed() {
585
 
        d->mFilterWidgetCount--;
586
 
        if (d->mFilterWidgetCount == 0) {
587
 
                d->mFrame->hide();
588
 
        }
589
 
}
590
 
 
 
545
, d(new FilterControllerPrivate)
 
546
{
 
547
    d->q = this;
 
548
    d->mFrame = frame;
 
549
    d->mDirModel = dirModel;
 
550
    d->mFilterWidgetCount = 0;
 
551
 
 
552
    d->mFrame->hide();
 
553
    FlowLayout* layout = new FlowLayout(d->mFrame);
 
554
    layout->setSpacing(2);
 
555
 
 
556
    d->addAction(i18nc("@action:inmenu", "Filter by Name"), SLOT(addFilterByName()));
 
557
    d->addAction(i18nc("@action:inmenu", "Filter by Date"), SLOT(addFilterByDate()));
 
558
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
 
559
#ifdef GWENVIEW_SEMANTICINFO_BACKEND_NEPOMUK
 
560
    // Only add filters if Nepomuk is running
 
561
    if (Nepomuk::ResourceManager::instance()->init() == 0) {
 
562
#endif
 
563
        d->addAction(i18nc("@action:inmenu", "Filter by Rating"), SLOT(addFilterByRating()));
 
564
        d->addAction(i18nc("@action:inmenu", "Filter by Tag"), SLOT(addFilterByTag()));
 
565
#ifdef GWENVIEW_SEMANTICINFO_BACKEND_NEPOMUK
 
566
    }
 
567
#endif
 
568
#endif
 
569
}
 
570
 
 
571
FilterController::~FilterController()
 
572
{
 
573
    delete d;
 
574
}
 
575
 
 
576
QList<QAction*> FilterController::actionList() const
 
577
{
 
578
    return d->mActionList;
 
579
}
 
580
 
 
581
void FilterController::addFilterByName()
 
582
{
 
583
    d->addFilter(new NameFilterWidget(d->mDirModel));
 
584
}
 
585
 
 
586
void FilterController::addFilterByDate()
 
587
{
 
588
    d->addFilter(new DateFilterWidget(d->mDirModel));
 
589
}
 
590
 
 
591
#ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE
 
592
void FilterController::addFilterByRating()
 
593
{
 
594
    d->addFilter(new RatingFilterWidget(d->mDirModel));
 
595
}
 
596
 
 
597
void FilterController::addFilterByTag()
 
598
{
 
599
    d->addFilter(new TagFilterWidget(d->mDirModel));
 
600
}
 
601
#endif
 
602
 
 
603
void FilterController::slotFilterWidgetClosed()
 
604
{
 
605
    d->mFilterWidgetCount--;
 
606
    if (d->mFilterWidgetCount == 0) {
 
607
        d->mFrame->hide();
 
608
    }
 
609
}
591
610
 
592
611
} // namespace