File indexing completed on 2024-05-19 04:49:17

0001 /****************************************************************************************
0002  * Copyright (c) 2008 Maximilian Kossick <maximilian.kossick@googlemail.com>            *
0003  *                                                                                      *
0004  * This program is free software; you can redistribute it and/or modify it under        *
0005  * the terms of the GNU General Public License as published by the Free Software        *
0006  * Foundation; either version 2 of the License, or (at your option) any later           *
0007  * version.                                                                             *
0008  *                                                                                      *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
0012  *                                                                                      *
0013  * You should have received a copy of the GNU General Public License along with         *
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
0015  ****************************************************************************************/
0016 
0017 #include "MemoryFilter.h"
0018 
0019 #include "core/meta/Meta.h"
0020 #include "core/meta/support/MetaConstants.h"
0021 
0022 #include <QDateTime>
0023 
0024 class UrlMemoryFilter : public StringMemoryFilter
0025 {
0026 protected:
0027     QString value( const Meta::TrackPtr &track ) const override
0028     { return track->playableUrl().url(); }
0029 
0030 };
0031 
0032 class GenericStringMemoryFilter : public StringMemoryFilter
0033 {
0034     public:
0035         GenericStringMemoryFilter( qint64 value, const QString &filter,
0036                                    bool matchBegin, bool matchEnd )
0037         : m_value( value )
0038         { setFilter( filter, matchBegin, matchEnd ); }
0039 
0040     protected:
0041         QString value( const Meta::TrackPtr &track ) const override
0042         { return Meta::valueForField( m_value, track ).toString(); }
0043 
0044     private:
0045         qint64 m_value;
0046 };
0047 
0048 class GenericNumberMemoryFilter : public NumberMemoryFilter
0049 {
0050     public:
0051         GenericNumberMemoryFilter( qint64 value, qint64 filter,
0052                                    Collections::QueryMaker::NumberComparison compare )
0053         : m_value( value )
0054         { setFilter( filter, compare ); }
0055 
0056     protected:
0057         qint64 value( const Meta::TrackPtr &track ) const override
0058         {
0059             QVariant v = Meta::valueForField( m_value, track );
0060             if( v.type() == QVariant::DateTime )
0061                 return v.toDateTime().toSecsSinceEpoch();
0062             else
0063                 return v.toLongLong();
0064         }
0065 
0066     private:
0067         qint64 m_value;
0068 };
0069 
0070 namespace FilterFactory
0071 {
0072 
0073     MemoryFilter* filter( qint64 value, const QString &filter, bool matchBegin, bool matchEnd )
0074     {
0075         MemoryFilter *result = new GenericStringMemoryFilter( value, filter, matchBegin, matchEnd );
0076         return result;
0077     }
0078 
0079     MemoryFilter* numberFilter( qint64 value, qint64 filter, Collections::QueryMaker::NumberComparison compare )
0080     {
0081         NumberMemoryFilter *result = new GenericNumberMemoryFilter( value, filter, compare );
0082         return result;
0083     }
0084 }
0085 
0086 MemoryFilter::MemoryFilter()
0087 {
0088 }
0089 
0090 MemoryFilter::~MemoryFilter()
0091 {
0092 }
0093 
0094 ContainerMemoryFilter::ContainerMemoryFilter()
0095     : MemoryFilter()
0096 {
0097 }
0098 
0099 ContainerMemoryFilter::~ContainerMemoryFilter()
0100 {
0101     qDeleteAll( m_filters );
0102 }
0103 
0104 void
0105 ContainerMemoryFilter::addFilter( MemoryFilter *filter )
0106 {
0107     if( filter )
0108         m_filters.append( filter );
0109 }
0110 
0111 AndContainerMemoryFilter::AndContainerMemoryFilter()
0112     : ContainerMemoryFilter()
0113 {
0114 }
0115 
0116 AndContainerMemoryFilter::~AndContainerMemoryFilter()
0117 {
0118 }
0119 
0120 bool
0121 AndContainerMemoryFilter::filterMatches( const Meta::TrackPtr &track ) const
0122 {
0123     if( m_filters.isEmpty() )
0124         return false;
0125 
0126     foreach( MemoryFilter *filter, m_filters )
0127     {
0128         if( filter && !filter->filterMatches( track ) )
0129             return false;
0130     }
0131     return true;
0132 }
0133 
0134 OrContainerMemoryFilter::OrContainerMemoryFilter()
0135     : ContainerMemoryFilter()
0136 {
0137 }
0138 
0139 OrContainerMemoryFilter::~OrContainerMemoryFilter()
0140 {
0141 }
0142 
0143 bool
0144 OrContainerMemoryFilter::filterMatches( const Meta::TrackPtr &track ) const
0145 {
0146     if( m_filters.isEmpty() )
0147         return false;
0148 
0149     foreach( MemoryFilter *filter, m_filters )
0150     {
0151         if( filter && filter->filterMatches( track ) )
0152             return true;
0153     }
0154     return false;
0155 }
0156 
0157 NegateMemoryFilter::NegateMemoryFilter( MemoryFilter *filter )
0158     :MemoryFilter()
0159     , m_filter( filter )
0160 {
0161 }
0162 
0163 NegateMemoryFilter::~NegateMemoryFilter()
0164 {
0165     delete m_filter;
0166 }
0167 
0168 bool
0169 NegateMemoryFilter::filterMatches( const Meta::TrackPtr &track ) const
0170 {
0171     return !m_filter->filterMatches( track );
0172 }
0173 
0174 StringMemoryFilter::StringMemoryFilter()
0175     : MemoryFilter()
0176     , m_matchBegin( false )
0177     , m_matchEnd( false )
0178 {
0179 }
0180 
0181 StringMemoryFilter::~StringMemoryFilter()
0182 {
0183 
0184 }
0185 
0186 void
0187 StringMemoryFilter::setFilter( const QString &filter, bool matchBegin, bool matchEnd )
0188 {
0189     m_filter = filter;
0190     m_matchBegin = matchBegin;
0191     m_matchEnd = matchEnd;
0192 }
0193 
0194 bool
0195 StringMemoryFilter::filterMatches( const Meta::TrackPtr &track ) const
0196 {
0197     const QString &str = value( track );
0198     if( m_matchBegin && m_matchEnd )
0199     {
0200         return QString::compare( str, m_filter, Qt::CaseInsensitive ) == 0;
0201     }
0202     else if( m_matchBegin )
0203     {
0204         return str.startsWith( m_filter, Qt::CaseInsensitive );
0205     }
0206     else if( m_matchEnd )
0207     {
0208         return str.endsWith( m_filter, Qt::CaseInsensitive );
0209     }
0210     else
0211     {
0212         return str.contains( m_filter, Qt::CaseInsensitive );
0213     }
0214 }
0215 
0216 NumberMemoryFilter::NumberMemoryFilter()
0217     : MemoryFilter()
0218     , m_filter( 0 )
0219     , m_compare( Collections::QueryMaker::Equals )
0220 {
0221 }
0222 
0223 NumberMemoryFilter::~NumberMemoryFilter()
0224 {
0225 }
0226 
0227 void
0228 NumberMemoryFilter::setFilter( qint64 filter, Collections::QueryMaker::NumberComparison compare )
0229 {
0230     m_filter = filter;
0231     m_compare = compare;
0232 }
0233 
0234 bool
0235 NumberMemoryFilter::filterMatches( const Meta::TrackPtr &track ) const
0236 {
0237     qint64 currentValue = value( track );
0238     switch( m_compare )
0239     {
0240         case Collections::QueryMaker::Equals:
0241             return currentValue == m_filter;
0242         case Collections::QueryMaker::GreaterThan:
0243             return currentValue > m_filter;
0244         case Collections::QueryMaker::LessThan:
0245             return currentValue < m_filter;
0246     }
0247     return false;
0248 }
0249 
0250 LabelFilter::LabelFilter( const QString &filter, bool matchBegin, bool matchEnd )
0251     : MemoryFilter()
0252 {
0253     QString pattern;
0254     if( matchBegin )
0255         pattern += '^';
0256     pattern += filter;
0257     if( matchEnd )
0258         pattern += '$';
0259 
0260     m_expression = QRegExp( pattern, Qt::CaseInsensitive );
0261 }
0262 
0263 LabelFilter::~LabelFilter()
0264 {
0265     //nothing to do
0266 }
0267 
0268 bool
0269 LabelFilter::filterMatches(const Meta::TrackPtr &track ) const
0270 {
0271     foreach( const Meta::LabelPtr &label, track->labels() )
0272     {
0273         if( m_expression.indexIn( label->name() ) != -1 )
0274             return true;
0275     }
0276     return false;
0277 }