1 /// (c) Pierpaolo Di Panfilo 2004
2 // (c) Alexandre Pereira de Oliveira 2005
3 // (c) 2005 Isaiah Damron <xepo@trifault.net>
4 // (c) 2006 Peter C. Ndikuwera <pndiku@gmail.com>
5 // (c) 2007 Seb Ruiz <ruiz@kde.org>
6 // See COPYING file for licensing information
8 #define DEBUG_PREFIX "SmartPlaylistEditor"
10 #include "SmartPlaylistEditor.h"
13 #include "querybuilder.h"
14 #include "metabundle.h"
15 #include "mountpointmanager.h"
20 #include <kmountpoint.h>
30 #include <QStringList>
31 #include <QToolButton>
32 #include <q3vgroupbox.h>
61 QStringList m_dbFields
;
62 QStringList m_expandableFields
;
63 QStringList m_expandableDbFields
;
67 SmartPlaylistEditor::SmartPlaylistEditor( QString defaultName
, QWidget
*parent
, const char *name
)
70 setObjectName( name
);
71 setCaption( i18n("Create Smart Playlist") );
73 setButtons( Ok
| Cancel
);
74 setDefaultButton( Ok
);
75 showButtonSeparator( true );
83 SmartPlaylistEditor::SmartPlaylistEditor( QWidget
*parent
, QDomElement xml
, const char *name
)
86 setObjectName( name
);
87 setCaption( i18n("Edit Smart Playlist") );
89 setButtons( Ok
| Cancel
);
90 setDefaultButton( Ok
);
91 showButtonSeparator( true );
94 init( xml
.attribute( "name" ) );
96 QDomNodeList matchesList
= xml
.elementsByTagName( "matches" );
97 bool matchedANY
= false, matchedALL
= false;
99 m_matchAllCheck
->setChecked( true );
100 m_matchAnyCheck
->setChecked( true );
102 for (int i
= 0, m
= matchesList
.count(); i
<m
; i
++) {
103 QDomElement matches
= matchesList
.item(i
).toElement();
104 QDomNodeList criteriaList
= matches
.elementsByTagName( "criteria" );
106 if ( criteriaList
.count() ) {
107 for (int j
= 0, c
=criteriaList
.count() ; j
<c
; ++j
) {
108 QDomElement criteria
= criteriaList
.item(j
).toElement();
110 if (matches
.attribute( "glue" ) == "OR") {
112 addCriteriaAny( criteria
);
116 addCriteriaAll( criteria
);
124 m_matchAllCheck
->setChecked( false );
128 m_matchAnyCheck
->setChecked( false );
133 QDomNodeList orderbyList
= xml
.elementsByTagName( "orderby" );
134 if ( orderbyList
.count() ) {
135 m_orderCheck
->setChecked( true );
136 QDomElement orderby
= orderbyList
.item(0).toElement(); // we only allow one orderby node
138 //random is always the last one.
139 int dbfield
= orderby
.attribute( "field" ) == "random" ? m_dbFields
.count() : m_dbFields
.indexOf( orderby
.attribute( "field" ) );
141 m_orderCombo
->setCurrentIndex( dbfield
);
142 updateOrderTypes( dbfield
);
143 if ( orderby
.attribute( "order" ) == "DESC" || orderby
.attribute( "order" ) == "weighted" )
144 m_orderTypeCombo
->setCurrentIndex( 1 );
145 else if ( orderby
.attribute( "order" ) == "ratingweighted" )
146 m_orderTypeCombo
->setCurrentIndex( 2 );
148 m_orderTypeCombo
->setCurrentIndex( 0 );
151 if ( xml
.hasAttribute( "maxresults" ) ) {
152 m_limitCheck
->setChecked( true );
153 m_limitSpin
->setValue( xml
.attribute( "maxresults" ).toInt() );
157 QDomNodeList expandbyList
= xml
.elementsByTagName( "expandby" );
158 if ( expandbyList
.count() ) {
159 m_expandCheck
->setChecked( true );
160 QDomElement expandby
= expandbyList
.item(0).toElement(); // we only allow one orderby node
162 int dbfield
= m_expandableFields
.indexOf( expandby
.attribute( "field" ) );
163 m_expandCombo
->setCurrentIndex( dbfield
);
168 void SmartPlaylistEditor::init(QString defaultName
)
170 KVBox
*vbox
= new KVBox( this );
171 setMainWidget( vbox
);
175 m_fields
<< i18n("Artist") << i18n("Composer") << i18n("Album") << i18n("Genre") << i18n("Title") << i18n("Length")
176 << i18n("Track #") << i18n("Year") << i18n("Comment") << i18n("Play Counter")
177 << i18n("Score") << i18n( "Rating" ) << i18n("First Play")
178 << i18n("Last Play") << i18n("Modified Date") << i18n("File Path")
179 << i18n("BPM") << i18n("Mount Point") << i18n( "Bitrate" ) << i18n( "Label" );
182 m_dbFields
<< "artist.name" << "composer.name" << "album.name" << "genre.name" << "tags.title" << "tags.length"
183 << "tags.track" << "year.name" << "tags.comment" << "statistics.playcounter"
184 << "statistics.percentage" << "statistics.rating" << "statistics.createdate"
185 << "statistics.accessdate" << "tags.createdate" << "tags.url"
186 << "tags.bpm" << "devices.lastmountpoint" << "tags.bitrate" << "labels.name";
188 m_expandableFields
.clear();
189 m_expandableFields
<< i18n("Artist") << i18n("Composer") << i18n("Album") << i18n("Genre") << i18n("Year") << i18n( "Label" );
191 m_expandableDbFields
.clear();
192 m_expandableDbFields
<< "artist.name" << "composer.name" << "album.name" << "genre.name" << "year.name" << "labels.name";
194 KHBox
*hbox
= new KHBox( mainWidget() );
195 hbox
->setSpacing( 5 );
196 new QLabel( i18n("Playlist name:"), hbox
);
197 m_nameLineEdit
= new KLineEdit( defaultName
, hbox
);
199 QFrame
*sep
= new QFrame( mainWidget() );
200 sep
->setFrameStyle( QFrame::HLine
| QFrame::Sunken
);
203 KHBox
*matchAnyBox
= new KHBox( mainWidget() );
204 m_matchAnyCheck
= new QCheckBox( i18n("Match Any of the following conditions" ), matchAnyBox
);
205 matchAnyBox
->setStretchFactor( new QWidget( matchAnyBox
), 1 );
208 m_criteriaAnyGroupBox
= new QGroupBox( QString(), mainWidget() );
209 QVBoxLayout
*anyBoxLayout
= new QVBoxLayout();
210 m_criteriaAnyGroupBox
->setLayout( anyBoxLayout
);
213 KHBox
*matchAllBox
= new KHBox( mainWidget() );
214 m_matchAllCheck
= new QCheckBox( i18n("Match All of the following conditions" ), matchAllBox
);
215 matchAllBox
->setStretchFactor( new QWidget( matchAllBox
), 1 );
218 m_criteriaAllGroupBox
= new QGroupBox( QString(), mainWidget() );
219 QVBoxLayout
*allBoxLayout
= new QVBoxLayout();
220 m_criteriaAllGroupBox
->setLayout( allBoxLayout
);
223 KHBox
*hbox2
= new KHBox( mainWidget() );
224 m_orderCheck
= new QCheckBox( i18n("Order by"), hbox2
);
225 KHBox
*orderBox
= new KHBox( hbox2
);
226 orderBox
->setSpacing( 5 );
228 m_orderCombo
= new KComboBox( orderBox
);
229 m_orderCombo
->insertItems( 0, m_fields
);
230 m_orderCombo
->addItem( i18n("Random") );
232 m_orderTypeCombo
= new KComboBox( orderBox
);
233 updateOrderTypes(0); // populate the new m_orderTypeCombo
234 hbox2
->setStretchFactor( new QWidget( hbox2
), 1 );
237 KHBox
*hbox1
= new KHBox( mainWidget() );
238 m_limitCheck
= new QCheckBox( i18n("Limit to"), hbox1
);
239 KHBox
*limitBox
= new KHBox( hbox1
);
240 limitBox
->setSpacing( 5 );
241 m_limitSpin
= new QSpinBox( limitBox
);
242 m_limitSpin
->setMinimum( 1 );
243 m_limitSpin
->setMaximum( 100000 );
244 m_limitSpin
->setValue( 15 );
245 new QLabel( i18n("tracks"), limitBox
);
246 hbox1
->setStretchFactor( new QWidget( hbox1
), 1 );
249 KHBox
*hbox3
= new KHBox( mainWidget() );
250 m_expandCheck
= new QCheckBox( i18n("Expand by"), hbox3
);
251 KHBox
*expandBox
= new KHBox( hbox3
);
252 expandBox
->setSpacing( 5 );
253 m_expandCombo
= new KComboBox( expandBox
);
254 m_expandCombo
->insertItems( 0, m_expandableFields
);
255 hbox3
->setStretchFactor( new QWidget( hbox3
), 1 );
258 static_cast<KHBox
*>(mainWidget())->setStretchFactor(new QWidget(mainWidget()), 1);
260 connect( m_matchAnyCheck
, SIGNAL( toggled(bool) ), m_criteriaAnyGroupBox
, SLOT( setEnabled(bool) ) );
261 connect( m_matchAllCheck
, SIGNAL( toggled(bool) ), m_criteriaAllGroupBox
, SLOT( setEnabled(bool) ) );
262 connect( m_orderCheck
, SIGNAL( toggled(bool) ), orderBox
, SLOT( setEnabled(bool) ) );
263 connect( m_limitCheck
, SIGNAL( toggled(bool) ), limitBox
, SLOT( setEnabled(bool) ) );
264 connect( m_expandCheck
, SIGNAL( toggled(bool) ), expandBox
, SLOT( setEnabled(bool) ) );
265 connect( m_orderCombo
, SIGNAL( activated(int) ), this, SLOT( updateOrderTypes(int) ) );
267 m_criteriaAnyGroupBox
->setEnabled( false );
268 m_criteriaAllGroupBox
->setEnabled( false );
270 orderBox
->setEnabled( false );
271 limitBox
->setEnabled( false );
272 expandBox
->setEnabled( false );
274 m_nameLineEdit
->setFocus();
280 void SmartPlaylistEditor::addCriteriaAny()
282 CriteriaEditor
*criteria
= new CriteriaEditor( this, m_criteriaAnyGroupBox
, criteriaAny
);
283 m_criteriaAnyGroupBox
->layout()->addWidget( criteria
);
284 m_criteriaEditorAnyList
.append( criteria
);
285 m_criteriaEditorAnyList
.first()->enableRemove( m_criteriaEditorAnyList
.count() > 1 );
288 void SmartPlaylistEditor::addCriteriaAll()
290 CriteriaEditor
*criteria
= new CriteriaEditor( this, m_criteriaAllGroupBox
, criteriaAll
);
291 m_criteriaAllGroupBox
->layout()->addWidget( criteria
);
292 m_criteriaEditorAllList
.append( criteria
);
293 m_criteriaEditorAllList
.first()->enableRemove( m_criteriaEditorAllList
.count() > 1 );
296 void SmartPlaylistEditor::addCriteriaAny( QDomElement
&xml
)
298 CriteriaEditor
*criteria
= new CriteriaEditor( this, m_criteriaAnyGroupBox
, criteriaAny
, xml
);
299 m_criteriaAnyGroupBox
->layout()->addWidget( criteria
);
300 m_criteriaEditorAnyList
.append( criteria
);
301 m_criteriaEditorAnyList
.first()->enableRemove( m_criteriaEditorAnyList
.count() > 1 );
304 void SmartPlaylistEditor::addCriteriaAll( QDomElement
&xml
)
306 CriteriaEditor
*criteria
= new CriteriaEditor( this, m_criteriaAllGroupBox
, criteriaAll
, xml
);
307 m_criteriaAllGroupBox
->layout()->addWidget( criteria
);
308 m_criteriaEditorAllList
.append( criteria
);
309 m_criteriaEditorAllList
.first()->enableRemove( m_criteriaEditorAllList
.count() > 1 );
312 void SmartPlaylistEditor::removeCriteriaAny( CriteriaEditor
*criteria
)
314 m_criteriaEditorAnyList
.removeAll( criteria
);
315 criteria
->deleteLater();
316 resize( size().width(), sizeHint().height() );
318 if( m_criteriaEditorAnyList
.count() == 1 )
319 m_criteriaEditorAnyList
.first()->enableRemove( false );
322 void SmartPlaylistEditor::removeCriteriaAll( CriteriaEditor
*criteria
)
324 m_criteriaEditorAllList
.removeAll( criteria
);
325 criteria
->deleteLater();
326 resize( size().width(), sizeHint().height() );
328 if( m_criteriaEditorAllList
.count() == 1 )
329 m_criteriaEditorAllList
.first()->enableRemove( false );
332 void SmartPlaylistEditor::updateOrderTypes( int index
)
334 int currentOrderType
= m_orderTypeCombo
->currentIndex();
335 if( index
== m_orderCombo
->count()-1 ) { // random order selected
336 m_orderTypeCombo
->clear();
337 m_orderTypeCombo
->addItem( i18n("Completely Random") );
338 m_orderTypeCombo
->addItem( i18n("Score Weighted") );
339 m_orderTypeCombo
->addItem( i18n("Rating Weighted") );
341 else { // ordinary order column selected
342 m_orderTypeCombo
->clear();
343 m_orderTypeCombo
->addItem( i18n("Ascending") );
344 m_orderTypeCombo
->addItem( i18n("Descending") );
346 if( currentOrderType
< m_orderTypeCombo
->count() )
347 m_orderTypeCombo
->setCurrentIndex( currentOrderType
);
348 m_orderTypeCombo
->setFont(m_orderTypeCombo
->font()); // invalidate size hint
349 m_orderTypeCombo
->updateGeometry();
352 QDomElement
SmartPlaylistEditor::result()
355 QDomNode node
= doc
.namedItem( "smartplaylists" );
357 nodeE
= node
.toElement();
359 QDomElement smartplaylist
= doc
.createElement( "smartplaylist" );
361 smartplaylist
.setAttribute( "name", name() );
364 if ( m_limitCheck
->isChecked() )
365 smartplaylist
.setAttribute( "maxresults", m_limitSpin
->value() );
367 nodeE
.appendChild( smartplaylist
);
369 if( m_matchAnyCheck
->isChecked() )
371 QDomElement matches
= doc
.createElement("matches");
372 smartplaylist
.appendChild( matches
);
373 // Iterate through all criteria list
374 foreach( CriteriaEditor
*criteriaeditor
, m_criteriaEditorAnyList
)
375 matches
.appendChild( doc
.importNode( criteriaeditor
->getDomSearchCriteria( doc
), true ) );
377 matches
.setAttribute( "glue", "OR" );
378 smartplaylist
.appendChild( matches
);
381 if( m_matchAllCheck
->isChecked() )
383 QDomElement matches
= doc
.createElement("matches");
384 smartplaylist
.appendChild( matches
);
385 // Iterate through all criteria list
386 foreach( CriteriaEditor
*criteriaeditor
, m_criteriaEditorAllList
)
387 matches
.appendChild( doc
.importNode( criteriaeditor
->getDomSearchCriteria( doc
), true ) );
389 matches
.setAttribute( "glue", "AND" );
390 smartplaylist
.appendChild( matches
);
394 if( m_orderCheck
->isChecked() ) {
395 QDomElement orderby
= doc
.createElement("orderby");
396 if (m_orderCombo
->currentIndex() != m_orderCombo
->count()-1) {
397 orderby
.setAttribute( "field", m_dbFields
[ m_orderCombo
->currentIndex() ] );
398 orderby
.setAttribute( "order", m_orderTypeCombo
->currentIndex() == 1 ? "DESC" : "ASC" );
400 orderby
.setAttribute( "field", "random" );
402 if ( m_orderTypeCombo
->currentIndex() == 0 )
404 else if ( m_orderTypeCombo
->currentIndex() == 1 )
407 order
= "ratingweighted";
408 orderby
.setAttribute( "order", order
);
411 smartplaylist
.appendChild( orderby
);
414 if( m_expandCheck
->isChecked() ) {
415 QDomElement expandBy
= doc
.createElement("expandby");
416 expandBy
.setAttribute( "field", m_expandableFields
[ m_expandCombo
->currentIndex() ] );
417 smartplaylist
.appendChild( expandBy
);
420 return (smartplaylist
);
423 /////////////////////////////////////////////////////////////////////////////
424 // CLASS CriteriaEditor
425 ////////////////////////////////////////////////////////////////////////////
427 CriteriaEditor::CriteriaEditor( SmartPlaylistEditor
*editor
, QWidget
*parent
, int criteriaType
, QDomElement criteria
)
429 , m_playlistEditor( editor
)
430 , m_currentValueType( -1 )
434 m_fieldCombo
= new KComboBox( this );
435 m_fieldCombo
->insertItems( 0, m_fields
);
437 m_criteriaCombo
= new KComboBox( this );
439 m_editBox
= new KHBox( this );
440 m_editBox
->setSpacing( 5 );
441 setStretchFactor( m_editBox
, 1 );
443 m_addButton
= new QToolButton( this );
444 m_addButton
->setToolButtonStyle( Qt::ToolButtonTextOnly
);
445 m_addButton
->setText( "+" );
446 m_removeButton
= new QToolButton( this );
447 m_removeButton
->setToolButtonStyle( Qt::ToolButtonTextOnly
);
448 m_removeButton
->setText( "-" );
450 connect( m_fieldCombo
, SIGNAL( activated(int) ), SLOT( slotFieldSelected(int) ) );
451 connect( m_criteriaCombo
, SIGNAL( activated(int) ), SLOT( loadEditWidgets() ) );
452 if (criteriaType
== SmartPlaylistEditor::criteriaAny
) {
453 connect( m_addButton
, SIGNAL( clicked() ), editor
, SLOT( addCriteriaAny() ) );
454 connect( m_removeButton
, SIGNAL( clicked() ), SLOT( slotRemoveCriteriaAny() ) );
457 connect( m_addButton
, SIGNAL( clicked() ), editor
, SLOT( addCriteriaAll() ) );
458 connect( m_removeButton
, SIGNAL( clicked() ), SLOT( slotRemoveCriteriaAll() ) );
461 if ( !criteria
.isNull() ) {
462 int field
= m_dbFields
.indexOf( criteria
.attribute( "field" ) );
463 QString condition
= criteria
.attribute("condition");
466 QStringList values
; //List of the values (only one item, unless condition is "is between")
467 QDomNodeList domvalueList
= criteria
.elementsByTagName( "value" );
468 for (int j
= 0, c
=domvalueList
.count() ; j
<c
; ++j
) {
469 values
<< domvalueList
.item(j
).toElement().text();
472 //Set the selected field
474 m_fieldCombo
->setCurrentIndex( field
);
475 slotFieldSelected( field
);
476 int valueType
= getValueType( field
);
477 //Load the right set of criterias for this type, in the dialog
478 loadCriteriaList( valueType
, condition
);
482 switch( valueType
) {
483 case String
: //fall through
484 case AutoCompletionString
:
486 m_lineEdit
->setText( values
.first() );
489 case Year
: //fall through
492 m_intSpinBox1
->setValue( values
.first().toInt() );
493 if( condition
== i18n("is between") )
494 m_intSpinBox2
->setValue( values
.last().toInt() );
499 m_comboBox
->setCurrentIndex( ratingToIndex( values
.first().toInt() ) );
500 if( condition
== i18n("is between") )
501 m_comboBox2
->setCurrentIndex( ratingToIndex( values
.last().toInt() ) );
506 if( condition
== i18n("is in the last") || condition
== i18n("is not in the last") ) {
507 m_intSpinBox1
->setValue( values
.first().toInt() );
508 QString period
= criteria
.attribute("period");
509 if (period
=="days" || period
.isEmpty() )
510 m_dateCombo
->setCurrentIndex(0);
511 else if (period
=="months")
512 m_dateCombo
->setCurrentIndex(1);
514 m_dateCombo
->setCurrentIndex(2);
518 dt
.setTime_t( values
.first().toUInt() );
519 m_dateEdit1
->setDate( dt
.date() );
520 if( condition
== i18n("is between") ) {
521 dt
.setTime_t( values
.last().toUInt() );
522 m_dateEdit2
->setDate( dt
.date() );
529 m_intSpinBox1
->setValue( values
.first().toInt() );
530 if( condition
== i18n("is between") )
531 m_intSpinBox2
->setValue( values
.last().toInt() );
532 QString period
= criteria
.attribute( "period" );
533 if ( period
== "seconds" || period
.isEmpty() ) //for compatibility
534 m_lengthCombo
->setCurrentIndex( 0 );
535 else if ( period
== "minutes" )
536 m_lengthCombo
->setCurrentIndex( 1 );
538 m_lengthCombo
->setCurrentIndex( 2 );
545 slotFieldSelected( 0 );
550 CriteriaEditor::~CriteriaEditor()
554 QDomElement
CriteriaEditor::getDomSearchCriteria( QDomDocument
&doc
)
556 QDomElement criteria
= doc
.createElement( "criteria" );
557 QString field
= m_dbFields
[ m_fieldCombo
->currentIndex() ];
558 QString condition
= m_criteriaCombo
->currentText();
560 criteria
.setAttribute( "condition", condition
);
561 criteria
.setAttribute( "field", field
);
564 // Get the proper value(s)
565 switch( getValueType( m_fieldCombo
->currentIndex() ) ) {
566 case String
: // fall through
567 case AutoCompletionString
:
568 values
<< m_lineEdit
->text();
570 case Year
: // fall through
573 values
<< QString::number( m_intSpinBox1
->value() );
574 if( condition
== i18n("is between") )
575 values
<< QString::number( m_intSpinBox2
->value() );
580 values
<< QString::number( indexToRating( m_comboBox
->currentIndex() ) );
581 if( condition
== i18n("is between") )
582 values
<< QString::number( indexToRating( m_comboBox2
->currentIndex() ) );
587 if( condition
== i18n("is in the last") || condition
== i18n("is not in the last") ) {
588 values
<< QString::number( m_intSpinBox1
->value() );
589 // 0 = days; 1=months; 2=years
590 criteria
.setAttribute( "period", !m_dateCombo
->currentIndex() ? "days" : (m_dateCombo
->currentIndex() == 1 ? "months" : "years") );
593 values
<< QString::number( QDateTime( m_dateEdit1
->date() ).toTime_t() );
594 if( condition
== i18n("is between") ) {
595 values
<< QString::number( QDateTime( m_dateEdit2
->date() ).toTime_t() );
602 values
<< QString::number( m_intSpinBox1
->value() );
603 // 0 = seconds, 1=minutes, 2=hours
604 criteria
.setAttribute( "period", !m_lengthCombo
->currentIndex() ? "seconds" : (m_lengthCombo
->currentIndex() == 1 ? "minutes" : "hours") );
605 if( condition
== i18n( "is between" ) ) {
606 values
<< QString::number( m_intSpinBox2
->value() );
612 oldForeach( values
) {
613 QDomElement value
= doc
.createElement( "value" );
614 QDomText t
= doc
.createTextNode( *it
);
615 value
.appendChild( t
);
616 criteria
.appendChild( value
);
622 QString
CriteriaEditor::getSearchCriteria()
624 QString searchCriteria
;
625 QString field
= m_dbFields
[ m_fieldCombo
->currentIndex() ];
626 QString criteria
= m_criteriaCombo
->currentText();
628 if( field
.isEmpty() )
631 if ( ( field
=="statistics.playcounter" || field
=="statistics.rating" || field
=="statistics.percentage" || field
=="statistics.accessdate" || field
=="statistics.createdate") )
632 searchCriteria
+= "COALESCE(" + field
+ ",0)";
634 searchCriteria
+= field
;
637 switch( getValueType( m_fieldCombo
->currentIndex() ) ) {
639 case AutoCompletionString
:
640 value
= m_lineEdit
->text();
642 case Year
: //fall through
644 value
= QString::number( m_intSpinBox1
->value() );
645 if( criteria
== i18n("is between") )
646 value
+= " AND " + QString::number( m_intSpinBox2
->value() );
650 value
= QString::number( indexToRating( m_comboBox
->currentIndex() ) );
651 if( criteria
== i18n("is between") )
652 value
+= " AND " + QString::number( indexToRating( m_comboBox2
->currentIndex() ) );
657 if( criteria
== i18n("is in the last") || criteria
== i18n("is not in the last") ) {
658 int n
= m_intSpinBox1
->value();
660 if( m_dateCombo
->currentIndex() == 0 ) //days
662 else if( m_dateCombo
->currentIndex() == 1 ) //months
664 else time
=86400*365*n
; //years
665 value
+= "(*CurrentTimeT*)" + QString(" - %1 AND ").arg(time
) + "(*CurrentTimeT*)";
668 QDateTime
datetime1( m_dateEdit1
->date() );
669 value
+= QString::number( datetime1
.toTime_t() );
670 if( criteria
== i18n("is between") ) {
671 QDateTime
datetime2( m_dateEdit2
->date() );
672 value
+= " AND " + QString::number( datetime2
.toTime_t() );
675 value
+= " AND " + QString::number( datetime1
.addDays( 1 ).toTime_t() );
681 int n
= m_intSpinBox1
->value();
683 if( m_lengthCombo
->currentIndex() == 0 ) //seconds
685 else if( m_lengthCombo
->currentIndex() == 1 ) //minutes
688 time
= 3600*n
; //hours
689 value
= QString::number( time
);
690 if( criteria
== i18n("is between") ) {
691 int n2
= m_intSpinBox2
->value();
693 if( m_lengthCombo
->currentIndex() == 0 ) //seconds
695 else if( m_lengthCombo
->currentIndex() == 1 ) //minutes
698 time2
= 3600*n2
; //hours
699 value
+= " AND " + QString::number( time2
);
707 if( criteria
== i18n("contains") )
708 searchCriteria
+= CollectionDB::likeCondition( value
, true, true );
709 else if( criteria
== i18n("does not contain") )
710 searchCriteria
+= " NOT " + CollectionDB::likeCondition( value
, true, true );
711 else if( criteria
== i18n("is") ) {
712 if( m_currentValueType
== Date
)
713 searchCriteria
+= " BETWEEN ";
715 searchCriteria
+= " = ";
716 if( m_currentValueType
== String
|| m_currentValueType
== AutoCompletionString
)
717 value
.prepend("'").append("'");
718 searchCriteria
+= value
;
720 else if( criteria
== i18n("is not") ) {
721 if( m_currentValueType
== Date
)
722 searchCriteria
+= " NOT BETWEEN ";
724 searchCriteria
+= " <> ";
725 if( m_currentValueType
== String
|| m_currentValueType
== AutoCompletionString
)
726 value
.prepend("'").append("'");
727 searchCriteria
+= value
;
729 else if( criteria
== i18n("starts with") )
731 if( field
== "tags.url" )
733 if( value
.startsWith( '/' ) )
735 if( !value
.startsWith( "./" ) )
736 value
= "./" + value
;
738 searchCriteria
+= CollectionDB::likeCondition( value
, false, true );
740 else if( criteria
== i18n("does not start with") )
742 if( field
== "tags.url" )
744 if( value
.startsWith( '/' ) )
746 if( !value
.startsWith( "./" ) )
747 value
= "./" + value
;
749 searchCriteria
+= " NOT " + CollectionDB::likeCondition( value
, false, true );
751 else if( criteria
== i18n("ends with") )
752 searchCriteria
+= CollectionDB::likeCondition( value
, true, false );
753 else if( criteria
== i18n("does not end with") )
754 searchCriteria
+= " NOT " + CollectionDB::likeCondition( value
, true, false );
755 else if( criteria
== i18n("is greater than") || criteria
== i18n("is after") )
756 searchCriteria
+= " > " + value
;
757 else if( criteria
== i18n("is smaller than") || criteria
== i18n("is before" ) )
758 searchCriteria
+= " < " + value
;
759 else if( criteria
== i18n("is between") || criteria
== i18n("is in the last") )
760 searchCriteria
+= " BETWEEN " + value
;
761 else if( criteria
== i18n("is not in the last") )
762 searchCriteria
+= " NOT BETWEEN " + value
;
764 return searchCriteria
;
768 void CriteriaEditor::setSearchCriteria( const QString
& )
774 void CriteriaEditor::enableRemove( bool enable
)
776 m_removeButton
->setEnabled( enable
);
780 void CriteriaEditor::slotRemoveCriteriaAny()
782 m_playlistEditor
->removeCriteriaAny( this );
785 void CriteriaEditor::slotRemoveCriteriaAll()
787 m_playlistEditor
->removeCriteriaAll( this );
790 void CriteriaEditor::slotAddCriteriaAny()
792 m_playlistEditor
->addCriteriaAny();
795 void CriteriaEditor::slotAddCriteriaAll()
797 m_playlistEditor
->addCriteriaAll();
800 void CriteriaEditor::slotFieldSelected( int field
)
802 int valueType
= getValueType( field
);
803 loadCriteriaList( valueType
);
805 m_currentValueType
= valueType
;
807 //enable auto-completion for artist, album, composer, label, mountpoint and genre
808 if( valueType
== AutoCompletionString
) {
811 m_comboBox
->completionObject()->clear();
813 int currentField
= m_fieldCombo
->currentIndex();
814 if( currentField
== FArtist
) //artist
815 items
= CollectionDB::instance()->artistList();
816 else if( currentField
== FComposer
) //composer
817 items
= CollectionDB::instance()->composerList();
818 else if( currentField
== FAlbum
) //album
819 items
= CollectionDB::instance()->albumList();
820 else if (currentField
== FLabel
) //label
821 items
= CollectionDB::instance()->labelList();
822 else if (currentField
== FMountPoint
) //mount point
824 KMountPoint::List mountpoints
= KMountPoint::currentMountPoints( KMountPoint::NeedRealDeviceName
);
825 oldForeachType( KMountPoint::List
, mountpoints
)
827 /* This code is adapted from KDE mediamanager's fstabbackend.cpp
828 * Copyright Kévin Ottens, Bernhard Rosenkraenzer, and from looking
829 * at the commit messages a few other guys who didn't add their name to the header.
831 QString device
= (*it
)->realDeviceName();
832 QString fs
= (*it
)->mountType();
833 QString mountpoint
= (*it
)->mountPoint();
840 && !fs
.contains( "proc" )
846 && device
.indexOf("shm") == -1
847 && mountpoint
!= "/dev/swap"
848 && mountpoint
!= "/dev/pts"
849 && mountpoint
.indexOf("/proc") != 0
850 && mountpoint
.indexOf("/sys") != 0
851 || fs
.indexOf( "smb" ) != -1
852 || fs
.indexOf( "cifs" ) != -1
853 || fs
.indexOf( "nfs" ) != -1
859 items
= CollectionDB::instance()->genreList();
861 m_comboBox
->insertItems( 0, items
);
862 m_comboBox
->completionObject()->insertItems( items
);
863 m_comboBox
->completionObject()->setIgnoreCase( true );
864 m_comboBox
->setItemText( m_comboBox
->currentIndex(), "" );
865 m_comboBox
->setFocus();
870 void CriteriaEditor::loadEditWidgets()
872 int valueType
= getValueType( m_fieldCombo
->currentIndex() );
874 if( m_currentValueType
== valueType
&& !(
875 m_criteriaCombo
->currentText() == i18n( "is between" ) ||
876 m_criteriaCombo
->currentText() == i18n( "is in the last" ) ||
877 m_criteriaCombo
->currentText() == i18n( "is not in the last" ) ||
878 m_lastCriteria
== i18n( "is between" ) ||
879 m_lastCriteria
== i18n( "is in the last" ) ||
880 m_lastCriteria
== i18n( "is not in the last" ) ) )
883 /* Store lastCriteria. This information is used above to decide whether it's necessary to change the Widgets */
884 m_lastCriteria
= m_criteriaCombo
->currentText();
886 QList
<QWidget
*> list
= qFindChildren
<QWidget
*>( m_editBox
);
887 foreach( QWidget
*w
, list
)
890 switch( valueType
) {
894 m_lineEdit
= new KLineEdit( m_editBox
);
895 m_lineEdit
->setFocus();
900 case AutoCompletionString
: //artist, composer, album, genre, label
902 m_comboBox
= new KComboBox( true, m_editBox
);
903 m_lineEdit
= static_cast<KLineEdit
*>( m_comboBox
->lineEdit() );
904 m_lineEdit
->setFocus();
905 m_comboBox
->setMinimumSize( QSize( 240, 20 ) );
910 case Year
: //fall through
913 bool yearField
= m_fieldCombo
->currentText() == i18n("Year");
915 m_intSpinBox1
= new QSpinBox( m_editBox
);
918 maxValue
= QDate::currentDate().year();
919 m_intSpinBox1
->setValue( maxValue
);
921 m_intSpinBox1
->setMaximum( maxValue
);
922 m_intSpinBox1
->setFocus();
923 m_intSpinBox1
->show();
925 if( m_criteriaCombo
->currentText() == i18n("is between") ) {
926 m_rangeLabel
= new QLabel( i18n("and"), m_editBox
);
927 m_rangeLabel
->setAlignment( Qt::AlignHCenter
);
928 m_rangeLabel
->show();
929 m_intSpinBox2
= new QSpinBox( m_editBox
);
931 maxValue
= QDate::currentDate().year();
932 m_intSpinBox2
->setValue( maxValue
);
934 m_intSpinBox2
->setMaximum( maxValue
);
935 m_intSpinBox2
->show();
942 const QStringList list
= MetaBundle::ratingList();
943 m_comboBox
= new KComboBox( false, m_editBox
);
944 m_comboBox
->insertItems( 0, list
);
947 if( m_criteriaCombo
->currentText() == i18n("is between") ) {
948 m_rangeLabel
= new QLabel( i18n("and"), m_editBox
);
949 m_rangeLabel
->setAlignment( Qt::AlignHCenter
);
950 m_rangeLabel
->show();
951 m_comboBox2
= new KComboBox( false, m_editBox
);
952 m_comboBox2
->insertItems( 0, list
);
960 if( m_criteriaCombo
->currentText() == i18n("is in the last") ||
961 m_criteriaCombo
->currentText() == i18n("is not in the last") ) {
962 m_intSpinBox1
= new QSpinBox( m_editBox
);
963 m_intSpinBox1
->setMinimum( 1 );
964 m_intSpinBox1
->show();
965 m_dateCombo
= new KComboBox( m_editBox
);
966 m_dateCombo
->addItem( i18n("Days") );
967 m_dateCombo
->addItem( i18n("Months") );
968 m_dateCombo
->addItem( i18n("Years") );
972 m_dateEdit1
= new QDateEdit( QDate::currentDate(), m_editBox
);
973 m_dateEdit1
->setFocus();
975 if( m_criteriaCombo
->currentText() == i18n("is between") ) {
976 m_rangeLabel
= new QLabel( i18n("and"), m_editBox
);
977 m_rangeLabel
->setAlignment( Qt::AlignHCenter
);
978 m_rangeLabel
->show();
979 m_dateEdit2
= new QDateEdit( QDate::currentDate(), m_editBox
);
989 m_intSpinBox1
= new QSpinBox( m_editBox
);
991 m_intSpinBox1
->setMaximum( maxValue
);
992 m_intSpinBox1
->setFocus();
993 m_intSpinBox1
->show();
994 if( m_criteriaCombo
->currentText() == i18n("is between") ) {
995 m_rangeLabel
= new QLabel( i18n("and"), m_editBox
);
996 m_rangeLabel
->setAlignment( Qt::AlignHCenter
);
997 m_rangeLabel
->show();
998 m_intSpinBox2
= new QSpinBox( m_editBox
);
999 m_intSpinBox2
->setMaximum( maxValue
);
1000 m_intSpinBox2
->show();
1002 m_lengthCombo
= new KComboBox( m_editBox
);
1003 m_lengthCombo
->addItem( i18n( "Seconds" ) );
1004 m_lengthCombo
->addItem( i18n( "Minutes" ) );
1005 m_lengthCombo
->addItem( i18n( "Hours" ) );
1006 m_lengthCombo
->show();
1015 void CriteriaEditor::loadCriteriaList( int valueType
, QString condition
)
1017 if( m_currentValueType
== valueType
&& condition
.isNull() )
1022 switch( valueType
) {
1024 case AutoCompletionString
:
1025 items
<< i18n( "contains" ) << i18n( "does not contain" ) << i18n( "is" ) << i18n( "is not" )
1026 << i18n( "starts with" ) << i18n( "does not start with" )
1027 << i18n( "ends with" ) << i18n( "does not end with" );
1033 items
<< i18n( "is" ) << i18n( "is not" ) << i18n( "is greater than" ) << i18n( "is smaller than" )
1034 << i18n( "is between" );
1037 case Year
: //fall through
1039 items
<< i18n( "is" ) << i18n( "is not" ) << i18n( "is before" ) << i18n( "is after" )
1040 << i18n( "is in the last" ) << i18n( "is not in the last" ) << i18n( "is between" );
1045 m_criteriaCombo
->clear();
1046 m_criteriaCombo
->insertItems( 0, items
);
1048 if( !condition
.isEmpty() )
1050 int index
= items
.indexOf( condition
);
1052 m_criteriaCombo
->setCurrentIndex( index
);
1057 int CriteriaEditor::getValueType( int index
)
1068 valueType
= AutoCompletionString
;
1091 default: valueType
= Date
;
1098 #include "SmartPlaylistEditor.moc"