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 #define DEBUG_PREFIX "Constraint::PlaylistLength"
0018 
0019 #include "PlaylistLength.h"
0020 
0021 #include "playlistgenerator/Constraint.h"
0022 #include "playlistgenerator/ConstraintFactory.h"
0023 
0024 #include <cmath>
0025 #include <cstdlib>
0026 
0027 Constraint*
0028 ConstraintTypes::PlaylistLength::createFromXml( QDomElement& xmlelem, ConstraintNode* p )
0029 {
0030     if ( p ) {
0031         return new PlaylistLength( xmlelem, p );
0032     } else {
0033         return nullptr;
0034     }
0035 }
0036 
0037 Constraint*
0038 ConstraintTypes::PlaylistLength::createNew( ConstraintNode* p )
0039 {
0040     if ( p ) {
0041         return new PlaylistLength( p );
0042     } else {
0043         return nullptr;
0044     }
0045 }
0046 
0047 ConstraintFactoryEntry*
0048 ConstraintTypes::PlaylistLength::registerMe()
0049 {
0050     return new ConstraintFactoryEntry( QStringLiteral("PlaylistLength"),
0051                                        i18n("Playlist Length"),
0052                                        i18n("Sets the preferred number of tracks in the playlist"),
0053                                        &PlaylistLength::createFromXml, &PlaylistLength::createNew );
0054 }
0055 
0056 ConstraintTypes::PlaylistLength::PlaylistLength( QDomElement& xmlelem, ConstraintNode* p )
0057         : Constraint( p )
0058         , m_length( 30 )
0059         , m_comparison( CompareNumEquals )
0060         , m_strictness( 1.0 )
0061 {
0062     QDomAttr a;
0063 
0064     a = xmlelem.attributeNode( QStringLiteral("length") );
0065     if ( !a.isNull() ) {
0066         m_length = a.value().toInt();
0067         /* after 2.3.2, what was the PlaylistLength constraint became the
0068          * PlaylistDuration constraint, so this works around the instance when
0069          * a user loads an XML file generated with the old code -- sth*/
0070         if ( m_length > 1000 )
0071             m_length /= 240000;
0072     }
0073 
0074     a = xmlelem.attributeNode( QStringLiteral("comparison") );
0075     if ( !a.isNull() )
0076         m_comparison = a.value().toInt();
0077 
0078     a = xmlelem.attributeNode( QStringLiteral("strictness") );
0079     if ( !a.isNull() )
0080         m_strictness = a.value().toDouble();
0081 }
0082 
0083 ConstraintTypes::PlaylistLength::PlaylistLength( ConstraintNode* p )
0084         : Constraint( p )
0085         , m_length( 30 )
0086         , m_comparison( CompareNumEquals )
0087         , m_strictness( 1.0 )
0088 {
0089 }
0090 
0091 QWidget*
0092 ConstraintTypes::PlaylistLength::editWidget() const
0093 {
0094     PlaylistLengthEditWidget* e = new PlaylistLengthEditWidget( m_length, m_comparison, static_cast<int>( 10*m_strictness ) );
0095     connect( e, &PlaylistLengthEditWidget::comparisonChanged, this, &PlaylistLength::setComparison );
0096     connect( e, &PlaylistLengthEditWidget::lengthChanged, this, &PlaylistLength::setLength );
0097     connect( e, &PlaylistLengthEditWidget::strictnessChanged, this, &PlaylistLength::setStrictness );
0098     return e;
0099 }
0100 
0101 void
0102 ConstraintTypes::PlaylistLength::toXml( QDomDocument& doc, QDomElement& elem ) const
0103 {
0104     QDomElement c = doc.createElement( QStringLiteral("constraint") );
0105     c.setAttribute( QStringLiteral("type"), QStringLiteral("PlaylistLength") );
0106     c.setAttribute( QStringLiteral("length"), QString::number( m_length ) );
0107     c.setAttribute( QStringLiteral("comparison"), QString::number( m_comparison ) );
0108     c.setAttribute( QStringLiteral("strictness"), QString::number( m_strictness ) );
0109     elem.appendChild( c );
0110 }
0111 
0112 QString
0113 ConstraintTypes::PlaylistLength::getName() const
0114 {
0115 
0116     KLocalizedString v;
0117     if ( m_comparison == CompareNumEquals ) {
0118         v = ki18ncp( "%1 is a number", "Playlist length: 1 track", "Playlist length: %1 tracks");
0119     } else if ( m_comparison == CompareNumGreaterThan ) {
0120         v = ki18ncp( "%1 is a number", "Playlist length: more than 1 track",
0121                      "Playlist length: more than %1 tracks");
0122     } else if ( m_comparison == CompareNumLessThan ) {
0123         v = ki18ncp( "%1 is a number", "Playlist length: less than 1 track",
0124                      "Playlist length: less than %1 tracks");
0125     } else {
0126         v = ki18n( "Playlist length: unknown");
0127     }
0128     v = v.subs( m_length );
0129     return v.toString();
0130 }
0131 
0132 double
0133 ConstraintTypes::PlaylistLength::satisfaction( const Meta::TrackList& tl ) const
0134 {
0135     quint32 l = static_cast<quint32>( tl.size() );
0136     if ( m_comparison == CompareNumEquals ) {
0137         if ( l > m_length )
0138             return ( l == m_length ) ? 1.0 : transformLength( l - m_length );
0139         else
0140             return ( l == m_length ) ? 1.0 : transformLength( m_length - l );
0141     } else if ( m_comparison == CompareNumGreaterThan ) {
0142         return ( l > m_length ) ? 1.0 : transformLength( m_length - l );
0143     } else if ( m_comparison == CompareNumLessThan ) {
0144         return ( l < m_length ) ? 1.0 : transformLength( l - m_length );
0145     } else {
0146         return 0.0;
0147     }
0148 }
0149 
0150 quint32
0151 ConstraintTypes::PlaylistLength::suggestPlaylistSize() const
0152 {
0153     return m_length;
0154 }
0155 
0156 double
0157 ConstraintTypes::PlaylistLength::transformLength( const int delta ) const
0158 {
0159     // Note: delta must be positive
0160     const double w = 5.0;
0161     return exp( -2.0 * ( 0.01 + m_strictness ) / w * ( delta + 1 ) );
0162 }
0163 
0164 void
0165 ConstraintTypes::PlaylistLength::setComparison( const int c )
0166 {
0167     m_comparison = c;
0168     Q_EMIT dataChanged();
0169 }
0170 
0171 void
0172 ConstraintTypes::PlaylistLength::setLength( const int l )
0173 {
0174     m_length = static_cast<quint32>(l);
0175     Q_EMIT dataChanged();
0176 }
0177 
0178 void
0179 ConstraintTypes::PlaylistLength::setStrictness( const int sv )
0180 {
0181     m_strictness = static_cast<double>(sv)/10.0;
0182 }
0183 
0184 /******************************
0185  * Edit Widget                *
0186  ******************************/
0187 
0188 ConstraintTypes::PlaylistLengthEditWidget::PlaylistLengthEditWidget( const int length,
0189                                                                      const int comparison,
0190                                                                      const int strictness ) : QWidget( nullptr )
0191 {
0192     ui.setupUi( this );
0193 
0194     ui.spinBox_Length->setValue( length );
0195     ui.comboBox_Comparison->setCurrentIndex( comparison );
0196     ui.slider_Strictness->setValue( strictness );
0197 }
0198 
0199 void
0200 ConstraintTypes::PlaylistLengthEditWidget::on_spinBox_Length_valueChanged( const int l )
0201 {
0202     Q_EMIT lengthChanged( l );
0203     Q_EMIT updated();
0204 }
0205 
0206 void
0207 ConstraintTypes::PlaylistLengthEditWidget::on_comboBox_Comparison_currentIndexChanged( const int v )
0208 {
0209     Q_EMIT comparisonChanged( v );
0210     Q_EMIT updated();
0211 }
0212 
0213 void
0214 ConstraintTypes::PlaylistLengthEditWidget::on_slider_Strictness_valueChanged( const int v )
0215 {
0216     Q_EMIT strictnessChanged( v );
0217     Q_EMIT updated();
0218 }