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