Version: 0.8.0-beta2 (using KDE 3.4.3, Kubuntu Package 4:3.4.3-0ubuntu1 ) Compiler: Target: i486-linux-gnu OS: Linux (i686) release 2.6.12-9-686 This was originally report in debians BTS: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=329014 After using Tags more extensivly I agree with the submitter. In my cases I always wanted 'and' and not 'or' in 'filter tags'. But I'm sure 'or' is needed too ;) Nevertheless, that more images match when one applies more filter rules (aka selecting more tags) is strange. More filter usually means less output. Maybe 'Filter Tags' is better labeled 'Show Tags'?? So 'Show Tags' with 'or' and 'Filter Tags' with 'and'? Achim
Achim, I'm not favorable to dupplicate sidebar tab only for that. The more simple way is to adda 2 toolbar boutton on the top on the sidebar (like Metadata tab for example) to choose OR or AND condition using by the filter. Your viewpoints... Gilles
El Domingo, 3 de Septiembre de 2006 14:25, Gilles Caulier escribi
Ok, i have seen where we can implement the _AND_ condition with tags filter view (AlbumLister::matchesFilter() from albumlister.cpp) I will try to do it using a new sub option in contextual menu (more simple to do it against to use toolbar buttons) Gilles
SVN commit 580718 by cgilles: digiKam from trunk: tag filters view: new options to set the matching condition to use between tags : OR condition or AND condition The settings is stored in digiKAm config file and is restored between session. BUG: 115160 M +42 -20 albumlister.cpp M +13 -1 albumlister.h M +46 -8 tagfilterview.cpp --- trunk/extragear/graphics/digikam/digikam/albumlister.cpp #580717:580718 @@ -66,28 +66,31 @@ AlbumListerPriv() { - filterTimer = 0; - job = 0; - currAlbum = 0; - filter = "*"; + filterTimer = 0; + job = 0; + currAlbum = 0; + filter = "*"; + matchingCond = AlbumLister::OrCondition; } - bool untaggedFilter; + bool untaggedFilter; - QString filter; + QString filter; - QMap<Q_LLONG, ImageInfo*> itemMap; - QMap<int,bool> dayFilter; + QMap<Q_LLONG, ImageInfo*> itemMap; + QMap<int,bool> dayFilter; - QValueList<int> tagFilter; + QValueList<int> tagFilter; - QTimer *filterTimer; + QTimer *filterTimer; - KIO::TransferJob *job; + KIO::TransferJob *job; - ImageInfoList itemList; + ImageInfoList itemList; - Album *currAlbum; + Album *currAlbum; + + AlbumLister::MatchingCondition matchingCond; }; AlbumLister* AlbumLister::m_instance = 0; @@ -202,9 +205,11 @@ d->filterTimer->start(100, true); } -void AlbumLister::setTagFilter(const QValueList<int>& tags, bool showUnTagged) +void AlbumLister::setTagFilter(const QValueList<int>& tags, const MatchingCondition& matchingCond, + bool showUnTagged) { - d->tagFilter = tags; + d->tagFilter = tags; + d->matchingCond = matchingCond; d->untaggedFilter = showUnTagged; d->filterTimer->start(100, true); } @@ -220,16 +225,33 @@ if (!d->tagFilter.isEmpty()) { QValueList<int> tagIDs = info->tagIDs(); - for (QValueList<int>::iterator it = d->tagFilter.begin(); - it != d->tagFilter.end(); ++it) + QValueList<int>::iterator it; + + if (d->matchingCond == OrCondition) { - if (tagIDs.contains(*it)) + for (it = d->tagFilter.begin(); it != d->tagFilter.end(); ++it) { - match = true; - break; + if (tagIDs.contains(*it)) + { + match = true; + break; + } } } + else + { + // AND matching condition... + for (it = d->tagFilter.begin(); it != d->tagFilter.end(); ++it) + { + if (!tagIDs.contains(*it)) + break; + } + + if (it == d->tagFilter.end()) + match = true; + } + match |= (d->untaggedFilter && tagIDs.isEmpty()); } else if (d->untaggedFilter) --- trunk/extragear/graphics/digikam/digikam/albumlister.h #580717:580718 @@ -58,6 +58,17 @@ public: + /** @enum MatchingCondition + * Possible logical matching condition used to sort tags id. + */ + enum MatchingCondition + { + OrCondition = 0, + AndCondition + }; + +public: + static AlbumLister* instance(); ~AlbumLister(); @@ -76,7 +87,8 @@ void setNameFilter(const QString& nameFilter); void setDayFilter(const QValueList<int>& days); - void setTagFilter(const QValueList<int>& tags, bool showUnTagged=false); + void setTagFilter(const QValueList<int>& tags, const MatchingCondition& matchingCond, + bool showUnTagged=false); signals: --- trunk/extragear/graphics/digikam/digikam/tagfilterview.cpp #580717:580718 @@ -34,6 +34,7 @@ #include <klocale.h> #include <kdebug.h> #include <kapplication.h> +#include <kconfig.h> #include <kiconloader.h> #include <kglobalsettings.h> #include <kcursor.h> @@ -72,7 +73,7 @@ : FolderCheckListItem(parent, tag ? tag->title() : i18n("Not Tagged"), QCheckListItem::CheckBoxController) { - m_tag = tag; + m_tag = tag; m_untagged = untagged; setDragEnabled(!untagged); @@ -83,7 +84,7 @@ TagFilterViewItem(QListViewItem* parent, TAlbum* tag) : FolderCheckListItem(parent, tag->title(), QCheckListItem::CheckBoxController) { - m_tag = tag; + m_tag = tag; m_untagged = false; setDragEnabled(true); @@ -132,7 +133,7 @@ FolderCheckListItem::paintCell(p, mcg, column, width, align); } - TAlbum* m_tag; + TAlbum *m_tag; bool m_untagged; }; @@ -145,10 +146,13 @@ TagFilterViewPriv() { - timer = 0; + timer = 0; + matchingCond = AlbumLister::OrCondition; } - QTimer *timer; + QTimer *timer; + + AlbumLister::MatchingCondition matchingCond; }; TagFilterView::TagFilterView(QWidget* parent) @@ -168,6 +172,8 @@ TagFilterViewItem* notTaggedItem = new TagFilterViewItem(this, 0, true); notTaggedItem->setPixmap(0, AlbumThumbnailLoader::instance()->getStandardTagIcon()); + // -- setup slots --------------------------------------------------------- + connect(AlbumManager::instance(), SIGNAL(signalAlbumAdded(Album*)), this, SLOT(slotTagAdded(Album*))); @@ -199,10 +205,22 @@ connect(d->timer, SIGNAL(timeout()), this, SLOT(slotTimeOut())); + + // -- read config --------------------------------------------------------- + + KConfig* config = kapp->config(); + config->setGroup("Tag Filters View"); + d->matchingCond = (AlbumLister::MatchingCondition)(config->readNumEntry("Matching Condition", + AlbumLister::OrCondition)); } TagFilterView::~TagFilterView() { + KConfig* config = kapp->config(); + config->setGroup("Tag Filters View"); + config->writeEntry("Matching Condition", (int)(d->matchingCond)); + config->sync(); + delete d->timer; delete d; } @@ -297,10 +315,10 @@ else { QPopupMenu popMenu(this); - popMenu.insertItem( SmallIcon("tag"), i18n("Assign Tag '%1' to Dropped Items") + popMenu.insertItem(SmallIcon("tag"), i18n("Assign Tag '%1' to Dropped Items") .arg(destAlbum->prettyURL()), 10) ; popMenu.insertSeparator(-1); - popMenu.insertItem( SmallIcon("cancel"), i18n("C&ancel") ); + popMenu.insertItem(SmallIcon("cancel"), i18n("C&ancel")); popMenu.setMouseTracking(true); id = popMenu.exec(QCursor::pos()); @@ -497,7 +515,7 @@ ++it; } - AlbumLister::instance()->setTagFilter(filterTags, showUnTagged); + AlbumLister::instance()->setTagFilter(filterTags, d->matchingCond, showUnTagged); } void TagFilterView::slotContextMenu(QListViewItem* it, const QPoint&, int) @@ -521,7 +539,15 @@ popmenu.insertItem(i18n("Select All"), 14); popmenu.insertItem(i18n("Deselect"), 15); popmenu.insertItem(i18n("Invert Selection"), 16); + popmenu.insertSeparator(); + QPopupMenu matchingCongMenu; + matchingCongMenu.setCheckable(true); + matchingCongMenu.insertItem(i18n("Or Between Tags"), 17); + matchingCongMenu.insertItem(i18n("And Between Tags"), 18); + matchingCongMenu.setItemChecked((d->matchingCond == AlbumLister::OrCondition) ? 17 : 18, true); + popmenu.insertItem(i18n("Matching Condition"), &matchingCongMenu); + int choice = popmenu.exec((QCursor::pos())); switch( choice ) { @@ -592,6 +618,18 @@ triggerChange(); break; } + case 17: + { + d->matchingCond = AlbumLister::OrCondition; + triggerChange(); + break; + } + case 18: + { + d->matchingCond = AlbumLister::AndCondition; + triggerChange(); + break; + } default: break; }
Created attachment 17633 [details] new matching condition options available into popup menu