[kde-doc-english] [amarok] /: Add new collection filter to find exact matches

Matěj Laitl matej at laitl.cz
Sat Nov 5 19:40:45 UTC 2011


Git commit 3e7122a2879260b531f9b2df4bdeaf0710ae303f by Matěj Laitl, on behalf of Daniel Faust.
Committed on 05/11/2011 at 20:12.
Pushed by laitl into branch 'master'.

Add new collection filter to find exact matches

Searching for label:=pop finds songs labeled with 'pop' but not with
'electro pop'. While searching for label:pop finds songs labeled with
'pop' and 'electro pop'.

GUI is also updated.

REVIEW: 102252
BUG: 260004
GUI: edit collection search and edit dynamic playlist dialogs changed
     slightly
DIGEST: Feature: new "exact" field:=value match in collection search
FIXED-IN: 2.5

M  +2    -0    ChangeLog
M  +7    -2    src/core-impl/collections/support/Expression.cpp
M  +1    -1    src/core-impl/collections/support/Expression.h
M  +10   -8    src/core-impl/collections/support/TextualQueryFilter.cpp
M  +12   -4    src/dialogs/EditFilterDialog.cpp
M  +33   -16   src/widgets/MetaQueryWidget.cpp
M  +2    -2    src/widgets/MetaQueryWidget.h

http://commits.kde.org/amarok/3e7122a2879260b531f9b2df4bdeaf0710ae303f

diff --git a/ChangeLog b/ChangeLog
index 128b56a..382d07f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -4,6 +4,8 @@ Amarok ChangeLog
 
 Version 2.5.0-Beta 1
   FEATURES:
+    * New "equals" match in collection filter - e.g. label:=pop finds songs
+      with label "pop" but not songs with label "electro pop". (BR 260004)
     * Enable dropping tracks on empty area in Saved Playlists to create new
       playlist.
     * Addded a "create new playlist" action in the empty space of the Saved
diff --git a/src/core-impl/collections/support/Expression.cpp b/src/core-impl/collections/support/Expression.cpp
index 531850a..f341aba 100644
--- a/src/core-impl/collections/support/Expression.cpp
+++ b/src/core-impl/collections/support/Expression.cpp
@@ -63,7 +63,7 @@ void ExpressionParser::parseChar( const QChar &c )
         handleMinus( c );
     else if( c == ':' )
         handleColon( c );
-    else if( c == '>' || c == '<' )
+    else if( c == '=' || c == '>' || c == '<' )
         handleMod( c );
     else if( c == '"' )
         handleQuote( c );
@@ -104,7 +104,12 @@ void ExpressionParser::handleMod( const QChar &c )
 {
     if( m_state == ExpectMod )
     {
-        m_element.match = ( c == '>' ) ? expression_element::More : expression_element::Less;
+        if( c == '=' )
+            m_element.match = expression_element::Equals;
+        else if( c == '>' )
+            m_element.match = expression_element::More;
+        else if( c == '<' )
+            m_element.match = expression_element::Less;
         m_state = ExpectText;
     }
     else
diff --git a/src/core-impl/collections/support/Expression.h b/src/core-impl/collections/support/Expression.h
index 1e49f45..5f825a8 100644
--- a/src/core-impl/collections/support/Expression.h
+++ b/src/core-impl/collections/support/Expression.h
@@ -25,7 +25,7 @@ struct expression_element
     QString field;
     QString text;
     bool negate: 1;
-    enum { Contains, Less, More } match: 2;
+    enum { Contains, Equals, Less, More } match: 2;
     expression_element(): negate( false ), match( Contains ) { }
 };
 typedef QList<expression_element> or_list;
diff --git a/src/core-impl/collections/support/TextualQueryFilter.cpp b/src/core-impl/collections/support/TextualQueryFilter.cpp
index 735772b..2a44a30 100644
--- a/src/core-impl/collections/support/TextualQueryFilter.cpp
+++ b/src/core-impl/collections/support/TextualQueryFilter.cpp
@@ -101,40 +101,42 @@ Collections::addTextualFilter( Collections::QueryMaker *qm, const QString &filte
                         break;
                 }
 
+                const bool matchEqual = ( elem.match == expression_element::Equals );
+
                 // TODO: Once we have MetaConstants.cpp use those functions here
                 if ( lcField.compare( "album", Qt::CaseInsensitive ) == 0 || lcField.compare( shortI18nForField( Meta::valAlbum ), Qt::CaseInsensitive ) == 0 )
                 {
                     if ( ( validFilters & Collections::QueryMaker::AlbumFilter ) == 0 ) continue;
-                    ADD_OR_EXCLUDE_FILTER( Meta::valAlbum, elem.text, false, false );
+                    ADD_OR_EXCLUDE_FILTER( Meta::valAlbum, elem.text, matchEqual, matchEqual );
                 }
                 else if ( lcField.compare( "artist", Qt::CaseInsensitive ) == 0 || lcField.compare( shortI18nForField( Meta::valArtist ), Qt::CaseInsensitive ) == 0 )
                 {
                     if ( ( validFilters & Collections::QueryMaker::ArtistFilter ) == 0 ) continue;
-                    ADD_OR_EXCLUDE_FILTER( Meta::valArtist, elem.text, false, false );
+                    ADD_OR_EXCLUDE_FILTER( Meta::valArtist, elem.text, matchEqual, matchEqual );
                 }
                 else if ( lcField.compare( "albumartist", Qt::CaseInsensitive ) == 0 || lcField.compare( shortI18nForField( Meta::valAlbumArtist ), Qt::CaseInsensitive ) == 0 )
                 {
                     if ( ( validFilters & Collections::QueryMaker::AlbumArtistFilter ) == 0 ) continue;
-                    ADD_OR_EXCLUDE_FILTER( Meta::valAlbumArtist, elem.text, false, false );
+                    ADD_OR_EXCLUDE_FILTER( Meta::valAlbumArtist, elem.text, matchEqual, matchEqual );
                 }
                 else if ( lcField.compare( "genre", Qt::CaseInsensitive ) == 0 || lcField.compare( shortI18nForField( Meta::valGenre ), Qt::CaseInsensitive ) == 0)
                 {
                     if ( ( validFilters & Collections::QueryMaker::GenreFilter ) == 0 ) continue;
-                    ADD_OR_EXCLUDE_FILTER( Meta::valGenre, elem.text, false, false );
+                    ADD_OR_EXCLUDE_FILTER( Meta::valGenre, elem.text, matchEqual, matchEqual );
                 }
                 else if ( lcField.compare( "title", Qt::CaseInsensitive ) == 0 || lcField.compare( shortI18nForField( Meta::valTitle ), Qt::CaseInsensitive ) == 0 )
                 {
                     if ( ( validFilters & Collections::QueryMaker::TitleFilter ) == 0 ) continue;
-                    ADD_OR_EXCLUDE_FILTER( Meta::valTitle, elem.text, false, false );
+                    ADD_OR_EXCLUDE_FILTER( Meta::valTitle, elem.text, matchEqual, matchEqual );
                 }
                 else if ( lcField.compare( "composer", Qt::CaseInsensitive ) == 0 || lcField.compare( shortI18nForField( Meta::valComposer ), Qt::CaseInsensitive ) == 0 )
                 {
                     if ( ( validFilters & Collections::QueryMaker::ComposerFilter ) == 0 ) continue;
-                    ADD_OR_EXCLUDE_FILTER( Meta::valComposer, elem.text, false, false );
+                    ADD_OR_EXCLUDE_FILTER( Meta::valComposer, elem.text, matchEqual, matchEqual );
                 }
                 else if( lcField.compare( "label", Qt::CaseInsensitive ) == 0 || lcField.compare( shortI18nForField( Meta::valLabel ), Qt::CaseInsensitive ) == 0 )
                 {
-                    ADD_OR_EXCLUDE_FILTER( Meta::valLabel, elem.text, false, false );
+                    ADD_OR_EXCLUDE_FILTER( Meta::valLabel, elem.text, matchEqual, matchEqual );
                 }
                 else if ( lcField.compare( "year", Qt::CaseInsensitive ) == 0 || lcField.compare( shortI18nForField( Meta::valYear ), Qt::CaseInsensitive ) == 0)
                 {
@@ -147,7 +149,7 @@ Collections::addTextualFilter( Collections::QueryMaker *qm, const QString &filte
                 }
                 else if( lcField.compare( "comment", Qt::CaseInsensitive ) == 0 || lcField.compare( shortI18nForField( Meta::valComment ), Qt::CaseInsensitive ) == 0 )
                 {
-                    ADD_OR_EXCLUDE_FILTER( Meta::valComment, elem.text, false, false );
+                    ADD_OR_EXCLUDE_FILTER( Meta::valComment, elem.text, matchEqual, matchEqual );
                 }
                 else if( lcField.compare( "filename", Qt::CaseInsensitive ) == 0 || lcField.compare( shortI18nForField( Meta::valUrl ), Qt::CaseInsensitive ) == 0 )
                 {
diff --git a/src/dialogs/EditFilterDialog.cpp b/src/dialogs/EditFilterDialog.cpp
index 91628ff..58c2956 100644
--- a/src/dialogs/EditFilterDialog.cpp
+++ b/src/dialogs/EditFilterDialog.cpp
@@ -300,20 +300,28 @@ EditFilterDialog::parseTextFilter( const QString &text )
             {
                 switch( elem.match )
                 {
-                    case 0:
+                    case expression_element::Equals:
                         filter.filter.condition = MetaQueryWidget::Equals;
                         break;
-                    case 1:
+                    case expression_element::Less:
                         filter.filter.condition = MetaQueryWidget::LessThan;
                         break;
-                    case 2:
+                    case expression_element::More:
                         filter.filter.condition = MetaQueryWidget::GreaterThan;
                         break;
                 }
             }
             else
             {
-                filter.filter.condition = MetaQueryWidget::Contains;
+                switch( elem.match )
+                {
+                    case expression_element::Contains:
+                        filter.filter.condition = MetaQueryWidget::Contains;
+                        break;
+                    case expression_element::Equals:
+                        filter.filter.condition = MetaQueryWidget::Equals;
+                        break;
+                }
                 filter.filter.value = elem.text;
             }
 
diff --git a/src/widgets/MetaQueryWidget.cpp b/src/widgets/MetaQueryWidget.cpp
index 5db1ded..57b622f 100644
--- a/src/widgets/MetaQueryWidget.cpp
+++ b/src/widgets/MetaQueryWidget.cpp
@@ -463,23 +463,27 @@ MetaQueryWidget::makeCompareSelection()
     else if( isDate(field) )
     {
         m_compareSelection = new KComboBox();
-        m_compareSelection->addItem( conditionToString( Equals, true ), (int)Equals );
-        m_compareSelection->addItem( conditionToString( LessThan, true ), (int)LessThan );
-        m_compareSelection->addItem( conditionToString( GreaterThan, true ), (int)GreaterThan );
-        
-        m_compareSelection->addItem( conditionToString( Between, true ), (int)Between );
-        m_compareSelection->addItem( conditionToString( OlderThan, true ), (int)OlderThan );
+        m_compareSelection->addItem( conditionToString( Equals, field ), (int)Equals );
+        m_compareSelection->addItem( conditionToString( LessThan, field ), (int)LessThan );
+        m_compareSelection->addItem( conditionToString( GreaterThan, field ), (int)GreaterThan );
+
+        m_compareSelection->addItem( conditionToString( Between, field ), (int)Between );
+        m_compareSelection->addItem( conditionToString( OlderThan, field ), (int)OlderThan );
     }
     else if( isNumeric(field) )
     {
         m_compareSelection = new KComboBox();
-        m_compareSelection->addItem( conditionToString( Equals ), (int)Equals );
-        m_compareSelection->addItem( conditionToString( LessThan ), (int)LessThan );
-        m_compareSelection->addItem( conditionToString( GreaterThan ), (int)GreaterThan );
-        m_compareSelection->addItem( conditionToString( Between ), (int)Between );
+        m_compareSelection->addItem( conditionToString( Equals, field ), (int)Equals );
+        m_compareSelection->addItem( conditionToString( LessThan, field ), (int)LessThan );
+        m_compareSelection->addItem( conditionToString( GreaterThan, field ), (int)GreaterThan );
+        m_compareSelection->addItem( conditionToString( Between, field ), (int)Between );
     }
     else
-        return;
+    {
+        m_compareSelection = new KComboBox();
+        m_compareSelection->addItem( conditionToString( Contains, field ), (int)Contains );
+        m_compareSelection->addItem( conditionToString( Equals, field ), (int)Equals );
+    }
 
     // -- select the correct entry (even if the condition is not one of the selection)
     int index = m_compareSelection->findData( int(m_filter.condition) );
@@ -632,7 +636,7 @@ MetaQueryWidget::makeFormatComboSelection()
     {
         combo->addItem(filetypes.at(listpos),listpos);
     }
-    
+
     int index = m_fieldSelection->findData( (int)m_filter.numValue );
     combo->setCurrentIndex( index == -1 ? 0 : index );
 
@@ -849,9 +853,9 @@ MetaQueryWidget::isDate( qint64 field )
 }
 
 QString
-MetaQueryWidget::conditionToString( FilterCondition condition, bool isDate )
+MetaQueryWidget::conditionToString( FilterCondition condition, qint64 field )
 {
-    if( isDate )
+    if( isDate(field) )
     {
         switch( condition )
         {
@@ -869,7 +873,7 @@ MetaQueryWidget::conditionToString( FilterCondition condition, bool isDate )
             ; // fall through
         }
     }
-    else
+    else if( isNumeric(field) )
     {
         switch( condition )
         {
@@ -881,6 +885,16 @@ MetaQueryWidget::conditionToString( FilterCondition condition, bool isDate )
             return i18n("greater than");
         case Between:
             return i18nc( "a numerical tag (like year or track number) is between two values", "between" );
+        default:
+            ; // fall through
+        }
+    }
+    else
+    {
+        switch( condition )
+        {
+        case Equals:
+            return i18nc("an alphabetical tag (like title or artist name) equals some string","equals");
         case Contains:
             return i18nc("an alphabetical tag (like title or artist name) contains some string", "contains");
         default:
@@ -932,7 +946,10 @@ QString MetaQueryWidget::Filter::toString( bool invert ) const
     {
     case Equals:
         {
-            result += strValue1;
+            if( MetaQueryWidget::isNumeric(field) )
+                result += strValue1;
+            else
+                result += '=' + QString( "\"%1\"" ).arg( value );
             if( invert )
                 result.prepend( QChar('-') );
             break;
diff --git a/src/widgets/MetaQueryWidget.h b/src/widgets/MetaQueryWidget.h
index 3db49d3..3974fb7 100644
--- a/src/widgets/MetaQueryWidget.h
+++ b/src/widgets/MetaQueryWidget.h
@@ -129,9 +129,9 @@ class MetaQueryWidget : public QWidget
         static bool isDate( qint64 field );
 
         /** Returns a localized text of the condition.
-            @param isDate True if the condition is meant for a date (as it has slightly different texts)
+            @param field Needed in order to test whether the field is a date, numeric or a string since the texts differ slightly
         */
-        static QString conditionToString( FilterCondition condition, bool isDate = false );
+        static QString conditionToString( FilterCondition condition, qint64 field );
 
 
     public slots:



More information about the kde-doc-english mailing list