File indexing completed on 2024-05-19 04:49:57
0001 /**************************************************************************************** 0002 * Copyright (c) 2008-2012 Soren Harward <stharward@gmail.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 #ifndef APG_TAGMATCH_CONSTRAINT 0018 #define APG_TAGMATCH_CONSTRAINT 0019 0020 #include "ui_TagMatchEditWidget.h" 0021 0022 #include "Matching.h" 0023 0024 #include "core/meta/forward_declarations.h" 0025 0026 #include <QAbstractListModel> 0027 #include <QBitArray> 0028 #include <QHash> 0029 #include <QString> 0030 #include <QVariant> 0031 0032 class Constraint; 0033 class ConstraintFactoryEntry; 0034 0035 namespace Collections { 0036 class QueryMaker; 0037 } 0038 0039 namespace ConstraintTypes { 0040 0041 class TagMatchFieldsModel; 0042 0043 /* Puts tracks with the specified tag into the playlist. "Tag" is used a 0044 * bit loosely here; a more accurate term would probably be "metadata", 0045 * since the matchable properties include parameters like "rating" and 0046 * "last played" that aren't in the actual file that corresponds to the 0047 * track being played. -- sth */ 0048 0049 class TagMatch : public MatchingConstraint { 0050 Q_OBJECT 0051 0052 /* support classes declared below */ 0053 class Comparer; 0054 0055 public: 0056 enum FieldTypes { FieldTypeInt, FieldTypeDate, FieldTypeString }; 0057 enum NumComparison { CompareNumLessThan, CompareNumEquals, CompareNumGreaterThan }; 0058 enum StrComparison { CompareStrEquals, CompareStrStartsWith, CompareStrEndsWith, CompareStrContains, CompareStrRegExp }; 0059 enum DateComparison { CompareDateBefore, CompareDateOn, CompareDateAfter, CompareDateWithin }; 0060 0061 static Constraint* createFromXml(QDomElement&, ConstraintNode*); 0062 static Constraint* createNew(ConstraintNode*); 0063 static ConstraintFactoryEntry* registerMe(); 0064 0065 QWidget* editWidget() const override; 0066 void toXml(QDomDocument&, QDomElement&) const override; 0067 0068 QString getName() const override; 0069 0070 Collections::QueryMaker* initQueryMaker(Collections::QueryMaker*) const override; 0071 double satisfaction(const Meta::TrackList&) const override; 0072 0073 // Implementation of MatchingConstraint virtuals 0074 const QBitArray whatTracksMatch( const Meta::TrackList& ) override; 0075 int constraintMatchType() const override; 0076 0077 private Q_SLOTS: 0078 void setComparison( int ); 0079 void setField( const QString& ); 0080 void setInvert( bool ); 0081 void setStrictness( int ); 0082 void setValue( const QVariant& ); 0083 0084 private: 0085 TagMatch( QDomElement&, ConstraintNode* ); 0086 explicit TagMatch( ConstraintNode* ); 0087 ~TagMatch() override; 0088 0089 // constraint parameters 0090 int m_comparison; 0091 QString m_field; 0092 bool m_invert; 0093 double m_strictness; 0094 QVariant m_value; 0095 0096 // convenience classes 0097 const Comparer* const m_comparer; 0098 const TagMatchFieldsModel* const m_fieldsModel; 0099 0100 // convenience functions 0101 QString comparisonToString() const; 0102 QString valueToString() const; 0103 0104 bool matches( const Meta::TrackPtr ) const; // match values are fuzzily calculated 0105 mutable QHash<Meta::TrackPtr, bool> m_matchCache; // internal cache for per-track true/false data 0106 0107 0108 /* support class that does fuzzy comparisons */ 0109 class Comparer { 0110 public: 0111 Comparer(); 0112 ~Comparer(); 0113 0114 double compareNum( const double, const int, const double, const double, const qint64 ) const; 0115 double compareStr( const QString&, const int, const QString& ) const; 0116 double compareDate( const uint, const int, const QVariant&, const double ) const; 0117 double compareLabels( const Meta::TrackPtr&, const int, const QString& ) const; 0118 0119 // rough inverses of the comparison 0120 uint rangeDate( const double ) const; 0121 int rangeNum( const double, const qint64 ) const; 0122 0123 private: 0124 QHash<qint64, double> m_numFieldWeight; 0125 const double m_dateWeight; 0126 0127 double fuzzyProb( const double, const double, const double, const double ) const; 0128 }; 0129 0130 }; 0131 0132 /* support class that manages data relationships for the various fields */ 0133 class TagMatchFieldsModel : public QAbstractListModel { 0134 Q_OBJECT 0135 0136 public: 0137 TagMatchFieldsModel(); 0138 ~TagMatchFieldsModel() override; 0139 0140 // required by QAbstractListModel 0141 QVariant data( const QModelIndex&, int role = Qt::DisplayRole ) const override; 0142 int rowCount( const QModelIndex& parent = QModelIndex() ) const override; 0143 0144 bool contains( const QString& ) const; 0145 int index_of( const QString& ) const; 0146 QString field_at( int ) const; 0147 qint64 meta_value_of( const QString& ) const; 0148 QString pretty_name_of( const QString& ) const; 0149 TagMatch::FieldTypes type_of( const QString& ) const; 0150 0151 private: 0152 QList<QString> m_fieldNames; 0153 QHash<QString, TagMatch::FieldTypes> m_fieldTypes; 0154 QHash<QString, qint64> m_fieldMetaValues; 0155 QHash<QString, QString> m_fieldPrettyNames; 0156 }; 0157 0158 class TagMatchEditWidget : public QWidget { 0159 Q_OBJECT 0160 0161 public: 0162 TagMatchEditWidget( const int, const QString&, const bool, const int, const QVariant& ); 0163 ~TagMatchEditWidget(); 0164 0165 Q_SIGNALS: 0166 void comparisonChanged( int ); 0167 void fieldChanged( const QString& ); 0168 void invertChanged( bool ); 0169 void strictnessChanged( int ); 0170 void valueChanged( const QVariant& ); 0171 void updated(); 0172 0173 private Q_SLOTS: 0174 // comparison 0175 void on_comboBox_ComparisonDate_currentIndexChanged( int ); 0176 void on_comboBox_ComparisonInt_currentIndexChanged( int ); 0177 void on_comboBox_ComparisonRating_currentIndexChanged( int ); 0178 void on_comboBox_ComparisonString_currentIndexChanged( int ); 0179 void on_comboBox_ComparisonTime_currentIndexChanged( int ); 0180 0181 // field 0182 void on_comboBox_Field_currentIndexChanged( int ); 0183 0184 // invert 0185 void on_checkBox_Invert_clicked( bool ); 0186 0187 // strictness 0188 void on_slider_StrictnessDate_valueChanged( int ); 0189 void on_slider_StrictnessInt_valueChanged( int ); 0190 void on_slider_StrictnessRating_valueChanged( int ); 0191 void on_slider_StrictnessTime_valueChanged( int ); 0192 0193 // value 0194 void on_kdatewidget_DateSpecific_changed( const QDate& ); 0195 void on_spinBox_ValueDateValue_valueChanged( int ); 0196 void on_comboBox_ValueDateUnit_currentIndexChanged( int ); 0197 void on_spinBox_ValueInt_valueChanged( int ); 0198 void on_lineEdit_StringValue_textChanged( const QString& ); 0199 void on_rating_RatingValue_ratingChanged( int ); 0200 void on_timeEdit_TimeValue_timeChanged( const QTime& ); 0201 void slotUpdateComboBoxLabels( int ); 0202 0203 private: 0204 Ui::TagMatchEditWidget ui; 0205 TagMatchFieldsModel* const m_fieldsModel; 0206 }; 0207 0208 } // namespace ConstraintTypes 0209 0210 typedef QPair<int,int> DateRange; 0211 Q_DECLARE_METATYPE( DateRange ) 0212 0213 #endif