1 /**************************************************************************************** 2 * Copyright (c) 2008-2012 Soren Harward <stharward@gmail.com> * 3 * * 4 * This program is free software; you can redistribute it and/or modify it under * 5 * the terms of the GNU General Public License as published by the Free Software * 6 * Foundation; either version 2 of the License, or (at your option) any later * 7 * version. * 8 * * 9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY * 10 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 11 * PARTICULAR PURPOSE. See the GNU General Public License for more details. * 12 * * 13 * You should have received a copy of the GNU General Public License along with * 14 * this program. If not, see <http://www.gnu.org/licenses/>. * 15 ****************************************************************************************/ 16 17 #ifndef APG_TAGMATCH_CONSTRAINT 18 #define APG_TAGMATCH_CONSTRAINT 19 20 #include "ui_TagMatchEditWidget.h" 21 22 #include "Matching.h" 23 24 #include "core/meta/forward_declarations.h" 25 26 #include <QAbstractListModel> 27 #include <QBitArray> 28 #include <QHash> 29 #include <QString> 30 #include <QVariant> 31 32 class Constraint; 33 class ConstraintFactoryEntry; 34 35 namespace Collections { 36 class QueryMaker; 37 } 38 39 namespace ConstraintTypes { 40 41 class TagMatchFieldsModel; 42 43 /* Puts tracks with the specified tag into the playlist. "Tag" is used a 44 * bit loosely here; a more accurate term would probably be "metadata", 45 * since the matchable properties include parameters like "rating" and 46 * "last played" that aren't in the actual file that corresponds to the 47 * track being played. -- sth */ 48 49 class TagMatch : public MatchingConstraint { 50 Q_OBJECT 51 52 /* support classes declared below */ 53 class Comparer; 54 55 public: 56 enum FieldTypes { FieldTypeInt, FieldTypeDate, FieldTypeString }; 57 enum NumComparison { CompareNumLessThan, CompareNumEquals, CompareNumGreaterThan }; 58 enum StrComparison { CompareStrEquals, CompareStrStartsWith, CompareStrEndsWith, CompareStrContains, CompareStrRegExp }; 59 enum DateComparison { CompareDateBefore, CompareDateOn, CompareDateAfter, CompareDateWithin }; 60 61 static Constraint* createFromXml(QDomElement&, ConstraintNode*); 62 static Constraint* createNew(ConstraintNode*); 63 static ConstraintFactoryEntry* registerMe(); 64 65 QWidget* editWidget() const override; 66 void toXml(QDomDocument&, QDomElement&) const override; 67 68 QString getName() const override; 69 70 Collections::QueryMaker* initQueryMaker(Collections::QueryMaker*) const override; 71 double satisfaction(const Meta::TrackList&) const override; 72 73 // Implementation of MatchingConstraint virtuals 74 const QBitArray whatTracksMatch( const Meta::TrackList& ) override; 75 int constraintMatchType() const override; 76 77 private Q_SLOTS: 78 void setComparison( int ); 79 void setField( const QString& ); 80 void setInvert( bool ); 81 void setStrictness( int ); 82 void setValue( const QVariant& ); 83 84 private: 85 TagMatch( QDomElement&, ConstraintNode* ); 86 explicit TagMatch( ConstraintNode* ); 87 ~TagMatch() override; 88 89 // constraint parameters 90 int m_comparison; 91 QString m_field; 92 bool m_invert; 93 double m_strictness; 94 QVariant m_value; 95 96 // convenience classes 97 const Comparer* const m_comparer; 98 const TagMatchFieldsModel* const m_fieldsModel; 99 100 // convenience functions 101 QString comparisonToString() const; 102 QString valueToString() const; 103 104 bool matches( const Meta::TrackPtr ) const; // match values are fuzzily calculated 105 mutable QHash<Meta::TrackPtr, bool> m_matchCache; // internal cache for per-track true/false data 106 107 108 /* support class that does fuzzy comparisons */ 109 class Comparer { 110 public: 111 Comparer(); 112 ~Comparer(); 113 114 double compareNum( const double, const int, const double, const double, const qint64 ) const; 115 double compareStr( const QString&, const int, const QString& ) const; 116 double compareDate( const uint, const int, const QVariant&, const double ) const; 117 double compareLabels( const Meta::TrackPtr&, const int, const QString& ) const; 118 119 // rough inverses of the comparison 120 uint rangeDate( const double ) const; 121 int rangeNum( const double, const qint64 ) const; 122 123 private: 124 QHash<qint64, double> m_numFieldWeight; 125 const double m_dateWeight; 126 127 double fuzzyProb( const double, const double, const double, const double ) const; 128 }; 129 130 }; 131 132 /* support class that manages data relationships for the various fields */ 133 class TagMatchFieldsModel : public QAbstractListModel { 134 Q_OBJECT 135 136 public: 137 TagMatchFieldsModel(); 138 ~TagMatchFieldsModel() override; 139 140 // required by QAbstractListModel 141 QVariant data( const QModelIndex&, int role = Qt::DisplayRole ) const override; 142 int rowCount( const QModelIndex& parent = QModelIndex() ) const override; 143 144 bool contains( const QString& ) const; 145 int index_of( const QString& ) const; 146 QString field_at( int ) const; 147 qint64 meta_value_of( const QString& ) const; 148 QString pretty_name_of( const QString& ) const; 149 TagMatch::FieldTypes type_of( const QString& ) const; 150 151 private: 152 QList<QString> m_fieldNames; 153 QHash<QString, TagMatch::FieldTypes> m_fieldTypes; 154 QHash<QString, qint64> m_fieldMetaValues; 155 QHash<QString, QString> m_fieldPrettyNames; 156 }; 157 158 class TagMatchEditWidget : public QWidget { 159 Q_OBJECT 160 161 public: 162 TagMatchEditWidget( const int, const QString&, const bool, const int, const QVariant& ); 163 ~TagMatchEditWidget(); 164 165 Q_SIGNALS: 166 void comparisonChanged( int ); 167 void fieldChanged( const QString& ); 168 void invertChanged( bool ); 169 void strictnessChanged( int ); 170 void valueChanged( const QVariant& ); 171 void updated(); 172 173 private Q_SLOTS: 174 // comparison 175 void on_comboBox_ComparisonDate_currentIndexChanged( int ); 176 void on_comboBox_ComparisonInt_currentIndexChanged( int ); 177 void on_comboBox_ComparisonRating_currentIndexChanged( int ); 178 void on_comboBox_ComparisonString_currentIndexChanged( int ); 179 void on_comboBox_ComparisonTime_currentIndexChanged( int ); 180 181 // field 182 void on_comboBox_Field_currentIndexChanged( int ); 183 184 // invert 185 void on_checkBox_Invert_clicked( bool ); 186 187 // strictness 188 void on_slider_StrictnessDate_valueChanged( int ); 189 void on_slider_StrictnessInt_valueChanged( int ); 190 void on_slider_StrictnessRating_valueChanged( int ); 191 void on_slider_StrictnessTime_valueChanged( int ); 192 193 // value 194 void on_kdatewidget_DateSpecific_changed( const QDate& ); 195 void on_spinBox_ValueDateValue_valueChanged( int ); 196 void on_comboBox_ValueDateUnit_currentIndexChanged( int ); 197 void on_spinBox_ValueInt_valueChanged( int ); 198 void on_lineEdit_StringValue_textChanged( const QString& ); 199 void on_rating_RatingValue_ratingChanged( int ); 200 void on_timeEdit_TimeValue_timeChanged( const QTime& ); 201 void slotUpdateComboBoxLabels( int ); 202 203 private: 204 Ui::TagMatchEditWidget ui; 205 TagMatchFieldsModel* const m_fieldsModel; 206 }; 207 208 } // namespace ConstraintTypes 209 210 typedef QPair<int,int> DateRange; 211 Q_DECLARE_METATYPE( DateRange ) 212 213 #endif 214