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 }