~ubuntu-branches/ubuntu/saucy/digikam/saucy

« back to all changes in this revision

Viewing changes to libs/models/imagefiltermodel.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-12-21 23:19:11 UTC
  • mfrom: (1.2.33 upstream) (3.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20101221231911-z9jip7s5aht1jqn9
Tags: 2:1.7.0-1ubuntu1
* Merge from Debian Experimental. Remaining Ubuntu changes:
  - Export .pot name and copy to plugins in debian/rules
  - Version build-depends on kipi-plugins-dev to ensure build is against the
    same version on all archs
* Drop debian/patches/kubuntu_01_linker.diff, incoporated upstream
* Remove patches directory and unused patches

Show diffs side-by-side

added added

removed removed

Lines of Context:
71
71
    delete filterer;
72
72
}
73
73
 
74
 
ImageFilterModelWorker::ImageFilterModelWorker(ImageFilterModelPrivate *d)
 
74
ImageFilterModelWorker::ImageFilterModelWorker(ImageFilterModelPrivate* d)
75
75
    : d(d) // do not install d as QObject parent, moveToThread wont work then
76
76
{
77
77
    thread = new Thread(this);
82
82
const int PrepareChunkSize = 101;
83
83
const int FilterChunkSize = 2001;
84
84
 
85
 
ImageFilterModel::ImageFilterModel(QObject *parent)
86
 
                : KCategorizedSortFilterProxyModel(parent),
87
 
                  d_ptr(new ImageFilterModelPrivate)
88
 
{
89
 
    d_ptr->init(this);
90
 
}
91
 
 
92
 
ImageFilterModel::ImageFilterModel(ImageFilterModelPrivate& dd, QObject *parent)
93
 
                : KCategorizedSortFilterProxyModel(parent),
94
 
                  d_ptr(&dd)
95
 
{
96
 
    d_ptr->init(this);
97
 
}
98
 
 
99
 
void ImageFilterModelPrivate::init(ImageFilterModel *_q)
 
85
ImageFilterModel::ImageFilterModel(QObject* parent)
 
86
    : KCategorizedSortFilterProxyModel(parent),
 
87
      d_ptr(new ImageFilterModelPrivate)
 
88
{
 
89
    d_ptr->init(this);
 
90
}
 
91
 
 
92
ImageFilterModel::ImageFilterModel(ImageFilterModelPrivate& dd, QObject* parent)
 
93
    : KCategorizedSortFilterProxyModel(parent),
 
94
      d_ptr(&dd)
 
95
{
 
96
    d_ptr->init(this);
 
97
}
 
98
 
 
99
void ImageFilterModelPrivate::init(ImageFilterModel* _q)
100
100
{
101
101
    q = _q;
102
102
 
117
117
    delete d;
118
118
}
119
119
 
120
 
void ImageFilterModel::setSourceModel(QAbstractItemModel *sourceModel)
 
120
void ImageFilterModel::setSourceModel(QAbstractItemModel* sourceModel)
121
121
{
122
122
    // made it protected, only setSourceImageModel is public
123
123
    QSortFilterProxyModel::setSourceModel(sourceModel);
124
124
}
125
125
 
126
 
ImageModel *ImageFilterModel::sourceModel() const
 
126
ImageModel* ImageFilterModel::sourceModel() const
127
127
{
128
128
    Q_D(const ImageFilterModel);
129
129
    return d->imageModel;
130
130
}
131
131
 
132
 
void ImageFilterModel::setSourceImageModel(ImageModel *sourceModel)
 
132
void ImageFilterModel::setSourceImageModel(ImageModel* sourceModel)
133
133
{
134
134
    Q_D(ImageFilterModel);
135
135
 
159
159
        connect(d->imageModel, SIGNAL(modelReset()),
160
160
                this, SLOT(slotModelReset()));
161
161
 
162
 
        connect(d->imageModel, SIGNAL(imageChange(const ImageChangeset &, const QItemSelection &)),
163
 
                this, SLOT(slotImageChange(const ImageChangeset &)));
 
162
        connect(d->imageModel, SIGNAL(imageChange(const ImageChangeset&, const QItemSelection&)),
 
163
                this, SLOT(slotImageChange(const ImageChangeset&)));
164
164
 
165
 
        connect(d->imageModel, SIGNAL(imageTagChange(const ImageTagChangeset &, const QItemSelection &)),
166
 
                this, SLOT(slotImageTagChange(const ImageTagChangeset &)));
 
165
        connect(d->imageModel, SIGNAL(imageTagChange(const ImageTagChangeset&, const QItemSelection&)),
 
166
                this, SLOT(slotImageTagChange(const ImageTagChangeset&)));
167
167
    }
168
168
 
169
169
    setSourceModel(d->imageModel);
172
172
QVariant ImageFilterModel::data(const QModelIndex& index, int role) const
173
173
{
174
174
    Q_D(const ImageFilterModel);
 
175
 
175
176
    if (!index.isValid())
 
177
    {
176
178
        return QVariant();
 
179
    }
177
180
 
178
181
    switch (role)
179
182
    {
183
186
            return d->sorter.categorizationMode;
184
187
        case SortOrderRole:
185
188
            return d->sorter.sortRole;
186
 
        //case CategoryCountRole:
187
 
          //  return categoryCount(d->imageModel->imageInfoRef(mapToSource(index)));
 
189
            //case CategoryCountRole:
 
190
            //  return categoryCount(d->imageModel->imageInfoRef(mapToSource(index)));
188
191
        case CategoryAlbumIdRole:
189
192
            return d->imageModel->imageInfoRef(mapToSource(index)).albumId();
190
193
        case CategoryFormatRole:
285
288
    Q_D(const ImageFilterModel);
286
289
    QList<ImageInfo> infos;
287
290
    const int size = rowCount();
 
291
 
288
292
    for (int i=0; i<size; ++i)
289
293
    {
290
294
        infos << d->imageModel->imageInfo(mapToSource(index(i, 0)));
291
295
    }
 
296
 
292
297
    return infos;
293
298
}
294
299
 
302
307
}
303
308
 
304
309
void ImageFilterModel::setTagFilter(const QList<int>& includedTags, const QList<int>& excludedTags, ImageFilterSettings::MatchingCondition matchingCond,
305
 
                               bool showUnTagged)
 
310
                                    bool showUnTagged)
306
311
{
307
312
    Q_D(ImageFilterModel);
308
313
    d->filter.setTagFilter(includedTags, excludedTags, matchingCond, showUnTagged);
356
361
    }
357
362
 
358
363
    d->filterResults.clear();
 
364
 
359
365
    //d->categoryCountHashInt.clear();
360
366
    //d->categoryCountHashString.clear();
361
367
    if (d->imageModel)
 
368
    {
362
369
        d->infosToProcess(d->imageModel->imageInfos(), false);
 
370
    }
 
371
 
363
372
    emit filterSettingsChanged(settings);
364
373
}
365
374
 
402
411
bool ImageFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const
403
412
{
404
413
    Q_D(const ImageFilterModel);
 
414
 
405
415
    if (source_parent.isValid())
 
416
    {
406
417
        return false;
 
418
    }
407
419
 
408
420
    qlonglong id = d->imageModel->imageId(source_row);
409
421
    QHash<qlonglong, bool>::const_iterator it = d->filterResults.constFind(id);
 
422
 
410
423
    if (it != d->filterResults.constEnd())
 
424
    {
411
425
        return it.value();
 
426
    }
412
427
 
413
428
    // usually done in thread and cache, unless source model changed
414
429
    return d->filter.matches(d->imageModel->imageInfo(source_row));
431
446
    // If no preparation is needed, the first step is skipped.
432
447
    // If filter version changes, both will discard old package and send them to packageDiscarded.
433
448
 
434
 
    connect(this, SIGNAL(packageToPrepare(const ImageFilterModelTodoPackage &)),
 
449
    connect(this, SIGNAL(packageToPrepare(const ImageFilterModelTodoPackage&)),
435
450
            preparer, SLOT(process(ImageFilterModelTodoPackage)));
436
451
 
437
 
    connect(this, SIGNAL(packageToFilter(const ImageFilterModelTodoPackage &)),
438
 
            filterer, SLOT(process(ImageFilterModelTodoPackage)));
439
 
 
440
 
    connect(preparer, SIGNAL(processed(const ImageFilterModelTodoPackage &)),
441
 
            filterer, SLOT(process(ImageFilterModelTodoPackage)));
442
 
 
443
 
    connect(filterer, SIGNAL(processed(const ImageFilterModelTodoPackage &)),
444
 
            this, SLOT(packageFinished(const ImageFilterModelTodoPackage &)));
445
 
 
446
 
    connect(preparer, SIGNAL(discarded(const ImageFilterModelTodoPackage &)),
447
 
            this, SLOT(packageDiscarded(const ImageFilterModelTodoPackage &)));
448
 
 
449
 
    connect(filterer, SIGNAL(discarded(const ImageFilterModelTodoPackage &)),
450
 
            this, SLOT(packageDiscarded(const ImageFilterModelTodoPackage &)));
 
452
    connect(this, SIGNAL(packageToFilter(const ImageFilterModelTodoPackage&)),
 
453
            filterer, SLOT(process(ImageFilterModelTodoPackage)));
 
454
 
 
455
    connect(preparer, SIGNAL(processed(const ImageFilterModelTodoPackage&)),
 
456
            filterer, SLOT(process(ImageFilterModelTodoPackage)));
 
457
 
 
458
    connect(filterer, SIGNAL(processed(const ImageFilterModelTodoPackage&)),
 
459
            this, SLOT(packageFinished(const ImageFilterModelTodoPackage&)));
 
460
 
 
461
    connect(preparer, SIGNAL(discarded(const ImageFilterModelTodoPackage&)),
 
462
            this, SLOT(packageDiscarded(const ImageFilterModelTodoPackage&)));
 
463
 
 
464
    connect(filterer, SIGNAL(discarded(const ImageFilterModelTodoPackage&)),
 
465
            this, SLOT(packageDiscarded(const ImageFilterModelTodoPackage&)));
451
466
}
452
467
 
453
468
void ImageFilterModelPrivate::infosToProcess(const QList<ImageInfo>& infos, bool forReAdd)
457
472
    const int maxChunkSize = needPrepare ? PrepareChunkSize : FilterChunkSize;
458
473
    QList<ImageInfo>::const_iterator it = infos.constBegin();
459
474
    int index = 0;
 
475
 
460
476
    while (it != infos.constEnd())
461
477
    {
462
478
        QVector<ImageInfo> vector(qMin(maxChunkSize, size - index));
466
482
        index += vector.size();
467
483
 
468
484
        ++sentOut;
 
485
 
469
486
        if (forReAdd)
 
487
        {
470
488
            ++sentOutForReAdd;
 
489
        }
471
490
 
472
491
        if (needPrepare)
 
492
        {
473
493
            emit packageToPrepare(ImageFilterModelTodoPackage(vector, version, forReAdd));
 
494
        }
474
495
        else
 
496
        {
475
497
            emit packageToFilter(ImageFilterModelTodoPackage(vector, version, forReAdd));
 
498
        }
476
499
    }
477
500
}
478
501
 
487
510
 
488
511
    // incorporate result
489
512
    QHash<qlonglong, bool>::const_iterator it = package.filterResults.constBegin();
 
513
 
490
514
    for (; it != package.filterResults.constEnd(); ++it)
 
515
    {
491
516
        filterResults.insert(it.key(), it.value());
 
517
    }
492
518
 
493
519
    // re-add if necessary
494
520
    if (package.isForReAdd)
495
521
    {
496
522
        emit reAddImageInfos(package.infos.toList());
 
523
 
497
524
        if (sentOutForReAdd == 1) // last package
 
525
        {
498
526
            emit reAddingFinished();
 
527
        }
499
528
    }
500
529
 
501
530
    // decrement counters
502
531
    --sentOut;
 
532
 
503
533
    if (package.isForReAdd)
 
534
    {
504
535
        --sentOutForReAdd;
 
536
    }
505
537
 
506
538
    // If all packages have returned, filtered and readded, and no more are expected,
507
539
    // and there is need to tell the filter result to the view, do that
522
554
        // Do not increment sentOut or sentOutForReAdd here: it was not decremented!
523
555
 
524
556
        if (needPrepare)
 
557
        {
525
558
            emit packageToPrepare(ImageFilterModelTodoPackage(package.infos, version, package.isForReAdd));
 
559
        }
526
560
        else
 
561
        {
527
562
            emit packageToFilter(ImageFilterModelTodoPackage(package.infos, version, package.isForReAdd));
 
563
        }
528
564
    }
529
565
}
530
566
 
604
640
        foreach (const ImageInfo& info, package.infos)
605
641
        {
606
642
            package.filterResults[info.id()] = localFilter.matches(info, &matchForText);
 
643
 
607
644
            if (matchForText)
 
645
            {
608
646
                hasOneMatchForText = true;
 
647
            }
609
648
        }
610
649
    }
611
650
    else
615
654
        {
616
655
            result = localFilter.matches(info, &matchForText);
617
656
            package.filterResults[info.id()] = result;
 
657
 
618
658
            if (result)
 
659
            {
619
660
                hasOneMatch = true;
 
661
            }
 
662
 
620
663
            if (matchForText)
 
664
            {
621
665
                hasOneMatchForText = true;
 
666
            }
622
667
        }
623
668
    }
624
669
 
634
679
 
635
680
// -------------- Sorting and Categorization --------------
636
681
 
637
 
void ImageFilterModel::setImageSortSettings(const ImageSortSettings &sorter)
 
682
void ImageFilterModel::setImageSortSettings(const ImageSortSettings& sorter)
638
683
{
639
684
    Q_D(ImageFilterModel);
640
685
    d->sorter = sorter;
667
712
{
668
713
    // source indexes
669
714
    Q_D(const ImageFilterModel);
 
715
 
670
716
    if (!left.isValid() || !right.isValid())
 
717
    {
671
718
        return -1;
 
719
    }
 
720
 
672
721
    return compareInfosCategories(d->imageModel->imageInfoRef(left), d->imageModel->imageInfoRef(right));
673
722
}
674
723
 
676
725
{
677
726
    // source indexes
678
727
    Q_D(const ImageFilterModel);
 
728
 
679
729
    if (!left.isValid() || !right.isValid())
 
730
    {
680
731
        return true;
 
732
    }
 
733
 
681
734
    return infosLessThan(d->imageModel->imageInfoRef(left), d->imageModel->imageInfoRef(right));
682
735
}
683
736
 
694
747
    const int size = sizeof(int) * 2;
695
748
    char c[size+1];
696
749
    c[size] = '\0';
697
 
    char *p = c;
 
750
    char* p = c;
698
751
    int number = id;
 
752
 
699
753
    for (int i=0; i<size; i++)
700
754
    {
701
755
        *p = 'a' + (number & 0xF);
702
756
        number >>= 4;
703
757
        p++;
704
758
    }
 
759
 
705
760
    return QString::fromLatin1(c);
706
761
}
707
762
 
708
763
QString ImageFilterModel::categoryIdentifier(const ImageInfo& info) const
709
764
{
710
765
    Q_D(const ImageFilterModel);
 
766
 
711
767
    switch (d->sorter.categorizationMode)
712
768
    {
713
769
        case ImageSortSettings::NoCategories:
736
792
    Q_D(ImageFilterModel);
737
793
 
738
794
    if (!d->imageModel || d->imageModel->isEmpty())
 
795
    {
739
796
        return;
 
797
    }
740
798
 
741
799
    // already scheduled to re-filter?
742
800
    if (d->updateFilterTimer->isActive())
 
801
    {
743
802
        return;
 
803
    }
744
804
 
745
805
    // do we filter at all?
746
806
    if (!d->filter.isFilteringByTags() && !d->filter.isFilteringByText())
 
807
    {
747
808
        return;
 
809
    }
748
810
 
749
811
    // is one of our images affected?
750
812
    foreach (const qlonglong& id, changeset.ids())
763
825
    Q_D(ImageFilterModel);
764
826
 
765
827
    if (!d->imageModel || d->imageModel->isEmpty())
 
828
    {
766
829
        return;
 
830
    }
767
831
 
768
832
    // already scheduled to re-filter?
769
833
    if (d->updateFilterTimer->isActive())
 
834
    {
770
835
        return;
 
836
    }
771
837
 
772
838
    // is one of the values affected that we filter or sort by?
773
839
    DatabaseFields::Set set = changeset.changes();
775
841
    bool filterAffected = (set & d->filter.watchFlags());
776
842
 
777
843
    if (!sortAffected && !filterAffected)
 
844
    {
778
845
        return;
 
846
    }
779
847
 
780
848
    // is one of our images affected?
781
849
    bool imageAffected = false;
788
856
            break;
789
857
        }
790
858
    }
 
859
 
791
860
    if (!imageAffected)
 
861
    {
792
862
        return;
 
863
    }
793
864
 
794
865
    if (filterAffected)
 
866
    {
795
867
        d->updateFilterTimer->start();
 
868
    }
796
869
    else
797
 
        invalidate(); // just resort, reuse filter results
 
870
    {
 
871
        invalidate();    // just resort, reuse filter results
 
872
    }
798
873
}
799
874
 
800
875
} // namespace Digikam