You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
amarok/amarok/src/smartplaylisteditor.cpp

1079 lines
38 KiB

/// (c) Pierpaolo Di Panfilo 2004
// (c) Alexandre Pereira de Oliveira 2005
// (c) 2005 Isaiah Damron <xepo@trifault.net>
// (c) 2006 Peter C. Ndikuwera <pndiku@gmail.com>
// See COPYING file for licensing information
#define DEBUG_PREFIX "SmartPlaylistEditor"
#include "amarok.h" //foreach
#include "debug.h"
#include "collectiondb.h"
#include "metabundle.h"
#include "mountpointmanager.h"
#include "smartplaylisteditor.h"
#include <kcombobox.h>
#include <klineedit.h>
#include <tdelocale.h>
#include <kmountpoint.h>
#include <knuminput.h>
#include <tqcheckbox.h>
#include <tqdatetime.h>
#include <tqdatetimeedit.h> //loadEditWidgets()
#include <tqframe.h>
#include <tqhbox.h>
#include <tqlabel.h>
#include <tqlayout.h>
#include <tqobjectlist.h>
#include <tqstringlist.h>
#include <tqtoolbutton.h>
#include <tqvbox.h>
#include <tqvgroupbox.h>
enum Fields
{
FArtist = 0,
FComposer,
FAlbum,
FGenre,
FTitle,
FLength,
FTrack,
FYear,
FComment,
FPlayCounter,
FScore,
FRating,
FFirstPlay,
FLastPlay,
FModfiedDate,
FFilePath,
FBPM,
FMountPoint,
FBitRate,
FLabel
};
TQStringList m_fields;
TQStringList m_dbFields;
TQStringList m_expandableFields;
TQStringList m_expandableDbFields;
SmartPlaylistEditor::SmartPlaylistEditor( TQString defaultName, TQWidget *parent, const char *name )
: KDialogBase( parent, name, true, i18n("Create Smart Playlist"),
Ok|Cancel, Ok, true )
{
init(defaultName);
addCriteriaAny();
addCriteriaAll();
}
SmartPlaylistEditor::SmartPlaylistEditor( TQWidget *parent, TQDomElement xml, const char *name)
: KDialogBase( parent, name, true, i18n("Edit Smart Playlist"),
Ok|Cancel, Ok, true )
{
init( xml.attribute( "name" ) );
// matches
TQDomNodeList matchesList = xml.elementsByTagName( "matches" );
bool matchedANY = false, matchedALL = false;
m_matchAllCheck->setChecked( true );
m_matchAnyCheck->setChecked( true );
for (int i = 0, m = matchesList.count(); i<m; i++) {
TQDomElement matches = matchesList.item(i).toElement();
TQDomNodeList criteriaList = matches.elementsByTagName( "criteria" );
if ( criteriaList.count() ) {
for (int j = 0, c=criteriaList.count() ; j<c; ++j ) {
TQDomElement criteria = criteriaList.item(j).toElement();
if (matches.attribute( "glue" ) == "OR") {
matchedANY = true;
addCriteriaAny( criteria );
}
else {
matchedALL = true;
addCriteriaAll( criteria );
}
}
}
}
if ( !matchedALL ) {
addCriteriaAll();
m_matchAllCheck->setChecked( false );
}
if ( !matchedANY ) {
m_matchAnyCheck->setChecked( false );
addCriteriaAny( );
}
// orderby
TQDomNodeList orderbyList = xml.elementsByTagName( "orderby" );
if ( orderbyList.count() ) {
m_orderCheck->setChecked( true );
TQDomElement orderby = orderbyList.item(0).toElement(); // we only allow one orderby node
//random is always the last one.
int dbfield = orderby.attribute( "field" ) == "random" ? m_dbFields.count() : m_dbFields.findIndex( orderby.attribute( "field" ) );
m_orderCombo->setCurrentItem( dbfield );
updateOrderTypes( dbfield );
if ( orderby.attribute( "order" ) == "DESC" || orderby.attribute( "order" ) == "weighted" )
m_orderTypeCombo->setCurrentItem( 1 );
else if ( orderby.attribute( "order" ) == "ratingweighted" )
m_orderTypeCombo->setCurrentItem( 2 );
else
m_orderTypeCombo->setCurrentItem( 0 );
}
// limit
if ( xml.hasAttribute( "maxresults" ) ) {
m_limitCheck->setChecked( true );
m_limitSpin->setValue( xml.attribute( "maxresults" ).toInt() );
}
// expand by
TQDomNodeList expandbyList = xml.elementsByTagName( "expandby" );
if ( expandbyList.count() ) {
m_expandCheck->setChecked( true );
TQDomElement expandby = expandbyList.item(0).toElement(); // we only allow one orderby node
int dbfield = m_expandableFields.findIndex( expandby.attribute( "field" ) );
m_expandCombo->setCurrentItem( dbfield );
}
}
void SmartPlaylistEditor::init(TQString defaultName)
{
makeVBoxMainWidget();
m_fields.clear();
m_fields << i18n("Artist") << i18n("Composer") << i18n("Album") << i18n("Genre") << i18n("Title") << i18n("Length")
<< i18n("Track #") << i18n("Year") << i18n("Comment") << i18n("Play Counter")
<< i18n("Score") << i18n( "Rating" ) << i18n("First Play")
<< i18n("Last Play") << i18n("Modified Date") << i18n("File Path")
<< i18n("BPM") << i18n("Mount Point") << i18n( "Bitrate" ) << i18n( "Label" );
m_dbFields.clear();
m_dbFields << "artist.name" << "composer.name" << "album.name" << "genre.name" << "tags.title" << "tags.length"
<< "tags.track" << "year.name" << "tags.comment" << "statistics.playcounter"
<< "statistics.percentage" << "statistics.rating" << "statistics.createdate"
<< "statistics.accessdate" << "tags.createdate" << "tags.url"
<< "tags.bpm" << "devices.lastmountpoint" << "tags.bitrate" << "labels.name";
m_expandableFields.clear();
m_expandableFields << i18n("Artist") << i18n("Composer") << i18n("Album") << i18n("Genre") << i18n("Year") << i18n( "Label" );
m_expandableDbFields.clear();
m_expandableDbFields << "artist.name" << "composer.name" << "album.name" << "genre.name" << "year.name" << "labels.name";
TQHBox *hbox = new TQHBox( mainWidget() );
hbox->setSpacing( 5 );
new TQLabel( i18n("Playlist name:"), hbox );
m_nameLineEdit = new KLineEdit( defaultName, hbox );
TQFrame *sep = new TQFrame( mainWidget() );
sep->setFrameStyle( TQFrame::HLine | TQFrame::Sunken );
//match box (any)
TQHBox *matchAnyBox = new TQHBox( mainWidget() );
m_matchAnyCheck = new TQCheckBox( i18n("Match Any of the following conditions" ), matchAnyBox );
matchAnyBox->setStretchFactor( new TQWidget( matchAnyBox ), 1 );
//criteria box
m_criteriaAnyGroupBox = new TQVGroupBox( TQString(), mainWidget() );
//match box (all)
TQHBox *matchAllBox = new TQHBox( mainWidget() );
m_matchAllCheck = new TQCheckBox( i18n("Match All of the following conditions" ), matchAllBox );
matchAllBox->setStretchFactor( new TQWidget( matchAllBox ), 1 );
//criteria box
m_criteriaAllGroupBox = new TQVGroupBox( TQString(), mainWidget() );
//order box
TQHBox *hbox2 = new TQHBox( mainWidget() );
m_orderCheck = new TQCheckBox( i18n("Order by"), hbox2 );
TQHBox *orderBox = new TQHBox( hbox2 );
orderBox->setSpacing( 5 );
//fields combo
m_orderCombo = new KComboBox( orderBox );
m_orderCombo->insertStringList( m_fields );
m_orderCombo->insertItem( i18n("Random") );
//order type
m_orderTypeCombo = new KComboBox( orderBox );
updateOrderTypes(0); // populate the new m_orderTypeCombo
hbox2->setStretchFactor( new TQWidget( hbox2 ), 1 );
//limit box
TQHBox *hbox1 = new TQHBox( mainWidget() );
m_limitCheck = new TQCheckBox( i18n("Limit to"), hbox1 );
TQHBox *limitBox = new TQHBox( hbox1 );
limitBox->setSpacing( 5 );
m_limitSpin = new KIntSpinBox( limitBox );
m_limitSpin->setMinValue( 1 );
m_limitSpin->setMaxValue( 100000 );
m_limitSpin->setValue( 15 );
new TQLabel( i18n("tracks"), limitBox );
hbox1->setStretchFactor( new TQWidget( hbox1 ), 1 );
//Expand By
TQHBox *hbox3 = new TQHBox( mainWidget() );
m_expandCheck = new TQCheckBox( i18n("Expand by"), hbox3 );
TQHBox *expandBox = new TQHBox( hbox3 );
expandBox->setSpacing( 5 );
m_expandCombo = new KComboBox( expandBox );
m_expandCombo->insertStringList( m_expandableFields );
hbox3->setStretchFactor( new TQWidget( hbox3 ), 1 );
//add stretch
static_cast<TQHBox *>(mainWidget())->setStretchFactor(new TQWidget(mainWidget()), 1);
connect( m_matchAnyCheck, TQ_SIGNAL( toggled(bool) ), m_criteriaAnyGroupBox, TQ_SLOT( setEnabled(bool) ) );
connect( m_matchAllCheck, TQ_SIGNAL( toggled(bool) ), m_criteriaAllGroupBox, TQ_SLOT( setEnabled(bool) ) );
connect( m_orderCheck, TQ_SIGNAL( toggled(bool) ), orderBox, TQ_SLOT( setEnabled(bool) ) );
connect( m_limitCheck, TQ_SIGNAL( toggled(bool) ), limitBox, TQ_SLOT( setEnabled(bool) ) );
connect( m_expandCheck, TQ_SIGNAL( toggled(bool) ), expandBox, TQ_SLOT( setEnabled(bool) ) );
connect( m_orderCombo, TQ_SIGNAL( activated(int) ), this, TQ_SLOT( updateOrderTypes(int) ) );
m_criteriaAnyGroupBox->setEnabled( false );
m_criteriaAllGroupBox->setEnabled( false );
orderBox->setEnabled( false );
limitBox->setEnabled( false );
expandBox->setEnabled( false );
m_nameLineEdit->setFocus();
resize( 550, 200 );
}
void SmartPlaylistEditor::addCriteriaAny()
{
CriteriaEditor *criteria= new CriteriaEditor( this, m_criteriaAnyGroupBox, criteriaAny );
m_criteriaEditorAnyList.append( criteria );
m_criteriaEditorAnyList.first()->enableRemove( m_criteriaEditorAnyList.count() > 1 );
}
void SmartPlaylistEditor::addCriteriaAll()
{
CriteriaEditor *criteria= new CriteriaEditor( this, m_criteriaAllGroupBox, criteriaAll );
m_criteriaEditorAllList.append( criteria );
m_criteriaEditorAllList.first()->enableRemove( m_criteriaEditorAllList.count() > 1 );
}
void SmartPlaylistEditor::addCriteriaAny( TQDomElement &xml )
{
CriteriaEditor *criteria = new CriteriaEditor( this, m_criteriaAnyGroupBox, criteriaAny, xml );
m_criteriaEditorAnyList.append( criteria );
m_criteriaEditorAnyList.first()->enableRemove( m_criteriaEditorAnyList.count() > 1 );
}
void SmartPlaylistEditor::addCriteriaAll( TQDomElement &xml )
{
CriteriaEditor *criteria = new CriteriaEditor( this, m_criteriaAllGroupBox, criteriaAll, xml );
m_criteriaEditorAllList.append( criteria );
m_criteriaEditorAllList.first()->enableRemove( m_criteriaEditorAllList.count() > 1 );
}
void SmartPlaylistEditor::removeCriteriaAny( CriteriaEditor *criteria )
{
m_criteriaEditorAnyList.remove( criteria );
criteria->deleteLater();
resize( size().width(), sizeHint().height() );
if( m_criteriaEditorAnyList.count() == 1 )
m_criteriaEditorAnyList.first()->enableRemove( false );
}
void SmartPlaylistEditor::removeCriteriaAll( CriteriaEditor *criteria )
{
m_criteriaEditorAllList.remove( criteria );
criteria->deleteLater();
resize( size().width(), sizeHint().height() );
if( m_criteriaEditorAllList.count() == 1 )
m_criteriaEditorAllList.first()->enableRemove( false );
}
void SmartPlaylistEditor::updateOrderTypes( int index )
{
int currentOrderType = m_orderTypeCombo->currentItem();
if( index == m_orderCombo->count()-1 ) { // random order selected
m_orderTypeCombo->clear();
m_orderTypeCombo->insertItem( i18n("Completely Random") );
m_orderTypeCombo->insertItem( i18n("Score Weighted") );
m_orderTypeCombo->insertItem( i18n("Rating Weighted") );
}
else { // ordinary order column selected
m_orderTypeCombo->clear();
m_orderTypeCombo->insertItem( i18n("Ascending") );
m_orderTypeCombo->insertItem( i18n("Descending") );
}
if( currentOrderType < m_orderTypeCombo->count() )
m_orderTypeCombo->setCurrentItem( currentOrderType );
m_orderTypeCombo->setFont(m_orderTypeCombo->font()); // invalidate size hint
m_orderTypeCombo->updateGeometry();
}
TQDomElement SmartPlaylistEditor::result()
{
TQDomDocument doc;
TQDomNode node = doc.namedItem( "smartplaylists" );
TQDomElement nodeE;
nodeE = node.toElement();
TQDomElement smartplaylist = doc.createElement( "smartplaylist" );
smartplaylist.setAttribute( "name", name() );
// Limit
if ( m_limitCheck->isChecked() )
smartplaylist.setAttribute( "maxresults", m_limitSpin->value() );
nodeE.appendChild( smartplaylist );
// Matches
if( m_matchAnyCheck->isChecked() )
{
TQDomElement matches = doc.createElement("matches");
smartplaylist.appendChild( matches );
// Iterate through all criteria list
CriteriaEditor *criteriaeditor = m_criteriaEditorAnyList.first();
for( int i=0; criteriaeditor; criteriaeditor = m_criteriaEditorAnyList.next(), ++i )
matches.appendChild( doc.importNode( criteriaeditor->getDomSearchCriteria( doc ), true ) );
matches.setAttribute( "glue", "OR" );
smartplaylist.appendChild( matches );
}
if( m_matchAllCheck->isChecked() )
{
TQDomElement matches = doc.createElement("matches");
smartplaylist.appendChild( matches );
// Iterate through all criteria list
CriteriaEditor *criteriaeditor = m_criteriaEditorAllList.first();
for( int i=0; criteriaeditor; criteriaeditor = m_criteriaEditorAllList.next(), ++i )
matches.appendChild( doc.importNode( criteriaeditor->getDomSearchCriteria( doc ), true ) );
matches.setAttribute( "glue", "AND" );
smartplaylist.appendChild( matches );
}
// Order By
if( m_orderCheck->isChecked() ) {
TQDomElement orderby = doc.createElement("orderby");
if (m_orderCombo->currentItem() != m_orderCombo->count()-1) {
orderby.setAttribute( "field", m_dbFields[ m_orderCombo->currentItem() ] );
orderby.setAttribute( "order", m_orderTypeCombo->currentItem() == 1 ? "DESC" : "ASC" );
} else {
orderby.setAttribute( "field", "random" );
TQString order;
if ( m_orderTypeCombo->currentItem() == 0 )
order = "random";
else if ( m_orderTypeCombo->currentItem() == 1 )
order = "weighted";
else
order = "ratingweighted";
orderby.setAttribute( "order", order );
}
smartplaylist.appendChild( orderby );
}
if( m_expandCheck->isChecked() ) {
TQDomElement expandBy = doc.createElement("expandby");
expandBy.setAttribute( "field", m_expandableFields[ m_expandCombo->currentItem() ] );
smartplaylist.appendChild( expandBy );
}
return (smartplaylist);
}
/////////////////////////////////////////////////////////////////////////////
// CLASS CriteriaEditor
////////////////////////////////////////////////////////////////////////////
CriteriaEditor::CriteriaEditor( SmartPlaylistEditor *editor, TQWidget *parent, int criteriaType, TQDomElement criteria )
: TQHBox( parent )
, m_playlistEditor( editor )
, m_currentValueType( -1 )
{
setSpacing( 5 );
m_fieldCombo = new KComboBox( this );
m_fieldCombo->insertStringList( m_fields );
m_criteriaCombo = new KComboBox( this );
m_editBox = new TQHBox( this );
m_editBox->setSpacing( 5 );
setStretchFactor( m_editBox, 1 );
m_addButton = new TQToolButton( this );
m_addButton->setUsesTextLabel( true );
m_addButton->setTextLabel("+");
m_removeButton = new TQToolButton( this );
m_removeButton->setUsesTextLabel( true );
m_removeButton->setTextLabel("-");
connect( m_fieldCombo, TQ_SIGNAL( activated(int) ), TQ_SLOT( slotFieldSelected(int) ) );
connect( m_criteriaCombo, TQ_SIGNAL( activated(int) ), TQ_SLOT( loadEditWidgets() ) );
if (criteriaType == SmartPlaylistEditor::criteriaAny) {
connect( m_addButton, TQ_SIGNAL( clicked() ), editor, TQ_SLOT( addCriteriaAny() ) );
connect( m_removeButton, TQ_SIGNAL( clicked() ), TQ_SLOT( slotRemoveCriteriaAny() ) );
}
else {
connect( m_addButton, TQ_SIGNAL( clicked() ), editor, TQ_SLOT( addCriteriaAll() ) );
connect( m_removeButton, TQ_SIGNAL( clicked() ), TQ_SLOT( slotRemoveCriteriaAll() ) );
}
if ( !criteria.isNull() ) {
int field = m_dbFields.findIndex( criteria.attribute( "field" ) );
TQString condition = criteria.attribute("condition");
TQStringList values; //List of the values (only one item, unless condition is "is between")
TQDomNodeList domvalueList = criteria.elementsByTagName( "value" );
for (int j = 0, c=domvalueList.count() ; j<c; ++j ) {
values << domvalueList.item(j).toElement().text();
}
//Set the selected field
m_fieldCombo->setCurrentItem( field );
slotFieldSelected( field );
int valueType = getValueType( field );
//Load the right set of criterias for this type, in the dialog
loadCriteriaList( valueType, condition );
loadEditWidgets();
switch( valueType ) {
case String: //fall through
case AutoCompletionString:
{
m_lineEdit->setText( values.first() );
break;
}
case Year: //fall through
case Number:
{
m_intSpinBox1->setValue( values.first().toInt() );
if( condition == i18n("is between") )
m_intSpinBox2->setValue( values.last().toInt() );
break;
}
case Rating:
{
m_comboBox->setCurrentItem( ratingToIndex( values.first().toInt() ) );
if( condition == i18n("is between") )
m_comboBox2->setCurrentItem( ratingToIndex( values.last().toInt() ) );
break;
}
case Date:
{
if( condition == i18n("is in the last") || condition == i18n("is not in the last") ) {
m_intSpinBox1->setValue( values.first().toInt() );
TQString period = criteria.attribute("period");
if (period=="days" || period.isEmpty() )
m_dateCombo->setCurrentItem(0);
else if (period=="months")
m_dateCombo->setCurrentItem(1);
else
m_dateCombo->setCurrentItem(2);
}
else {
TQDateTime dt;
dt.setTime_t( values.first().toUInt() );
m_dateEdit1->setDate( dt.date() );
if( condition == i18n("is between") ) {
dt.setTime_t( values.last().toUInt() );
m_dateEdit2->setDate( dt.date() );
}
}
break;
}
case Length:
{
m_intSpinBox1->setValue( values.first().toInt() );
if( condition == i18n("is between") )
m_intSpinBox2->setValue( values.last().toInt() );
TQString period = criteria.attribute( "period" );
if ( period == "seconds" || period.isEmpty() ) //for compatibility
m_lengthCombo->setCurrentItem( 0 );
else if ( period == "minutes" )
m_lengthCombo->setCurrentItem( 1 );
else
m_lengthCombo->setCurrentItem( 2 );
break;
}
default: ;
};
}
else
slotFieldSelected( 0 );
show();
}
CriteriaEditor::~CriteriaEditor()
{
}
TQDomElement CriteriaEditor::getDomSearchCriteria( TQDomDocument &doc )
{
TQDomElement criteria = doc.createElement( "criteria" );
TQString field = m_dbFields[ m_fieldCombo->currentItem() ];
TQString condition = m_criteriaCombo->currentText();
criteria.setAttribute( "condition", condition );
criteria.setAttribute( "field", field );
TQStringList values;
// Get the proper value(s)
switch( getValueType( m_fieldCombo->currentItem() ) ) {
case String: // fall through
case AutoCompletionString:
values << m_lineEdit->text();
break;
case Year: // fall through
case Number:
{
values << TQString::number( m_intSpinBox1->value() );
if( condition == i18n("is between") )
values << TQString::number( m_intSpinBox2->value() );
break;
}
case Rating:
{
values << TQString::number( indexToRating( m_comboBox->currentItem() ) );
if( condition == i18n("is between") )
values << TQString::number( indexToRating( m_comboBox2->currentItem() ) );
break;
}
case Date:
{
if( condition == i18n("is in the last") || condition == i18n("is not in the last") ) {
values << TQString::number( m_intSpinBox1->value() );
// 0 = days; 1=months; 2=years
criteria.setAttribute( "period", !m_dateCombo->currentItem() ? "days" : (m_dateCombo->currentItem() == 1 ? "months" : "years") );
}
else {
values << TQString::number( TQDateTime( m_dateEdit1->date() ).toTime_t() );
if( condition == i18n("is between") ) {
values << TQString::number( TQDateTime( m_dateEdit2->date() ).toTime_t() );
}
}
break;
}
case Length:
{
values << TQString::number( m_intSpinBox1->value() );
// 0 = seconds, 1=minutes, 2=hours
criteria.setAttribute( "period", !m_lengthCombo->currentItem() ? "seconds" : (m_lengthCombo->currentItem() == 1 ? "minutes" : "hours") );
if( condition == i18n( "is between" ) ) {
values << TQString::number( m_intSpinBox2->value() );
}
break;
}
default: ;
}
foreach( values ) {
TQDomElement value = doc.createElement( "value" );
TQDomText t = doc.createTextNode( *it );
value.appendChild( t );
criteria.appendChild( value );
}
return (criteria);
}
TQString CriteriaEditor::getSearchCriteria()
{
TQString searchCriteria;
TQString field = m_dbFields[ m_fieldCombo->currentItem() ];
TQString criteria = m_criteriaCombo->currentText();
if( field.isEmpty() )
return TQString();
if ( ( field=="statistics.playcounter" || field=="statistics.rating" || field=="statistics.percentage" || field=="statistics.accessdate" || field=="statistics.createdate") )
searchCriteria += "COALESCE(" + field + ",0)";
else
searchCriteria += field;
TQString value;
switch( getValueType( m_fieldCombo->currentItem() ) ) {
case String:
case AutoCompletionString:
value = m_lineEdit->text();
break;
case Year: //fall through
case Number:
value = TQString::number( m_intSpinBox1->value() );
if( criteria == i18n("is between") )
value += " AND " + TQString::number( m_intSpinBox2->value() );
break;
case Rating:
{
value = TQString::number( indexToRating( m_comboBox->currentItem() ) );
if( criteria == i18n("is between") )
value += " AND " + TQString::number( indexToRating( m_comboBox2->currentItem() ) );
break;
}
case Date:
{
if( criteria == i18n("is in the last") || criteria == i18n("is not in the last") ) {
int n = m_intSpinBox1->value();
int time;
if( m_dateCombo->currentItem() == 0 ) //days
time=86400*n;
else if( m_dateCombo->currentItem() == 1 ) //months
time=86400*30*n;
else time=86400*365*n; //years
value += "(*CurrentTimeT*)" + TQString(" - %1 AND ").arg(time) + "(*CurrentTimeT*)";
}
else {
TQDateTime datetime1( m_dateEdit1->date() );
value += TQString::number( datetime1.toTime_t() );
if( criteria == i18n("is between") ) {
TQDateTime datetime2( m_dateEdit2->date() );
value += " AND " + TQString::number( datetime2.toTime_t() );
}
else
value += " AND " + TQString::number( datetime1.addDays( 1 ).toTime_t() );
}
break;
}
case Length:
{
int n = m_intSpinBox1->value();
int time;
if( m_lengthCombo->currentItem() == 0 ) //seconds
time = n;
else if( m_lengthCombo->currentItem() == 1 ) //minutes
time = 60*n;
else
time = 3600*n; //hours
value = TQString::number( time );
if( criteria == i18n("is between") ) {
int n2 = m_intSpinBox2->value();
int time2;
if( m_lengthCombo->currentItem() == 0 ) //seconds
time2 = n2;
else if( m_lengthCombo->currentItem() == 1 ) //minutes
time2 = 60*n2;
else
time2 = 3600*n2; //hours
value += " AND " + TQString::number( time2 );
}
break;
}
default: ;
};
if( criteria == i18n("contains") )
searchCriteria += CollectionDB::likeCondition( value, true, true );
else if( criteria == i18n("does not contain") )
searchCriteria += " NOT " + CollectionDB::likeCondition( value, true, true );
else if( criteria == i18n("is") ) {
if( m_currentValueType == Date )
searchCriteria += " BETWEEN ";
else
searchCriteria += " = ";
if( m_currentValueType == String || m_currentValueType == AutoCompletionString )
value.prepend("'").append("'");
searchCriteria += value;
}
else if( criteria == i18n("is not") ) {
if( m_currentValueType == Date )
searchCriteria += " NOT BETWEEN ";
else
searchCriteria += " <> ";
if( m_currentValueType == String || m_currentValueType == AutoCompletionString )
value.prepend("'").append("'");
searchCriteria += value;
}
else if( criteria == i18n("starts with") )
{
if( field == "tags.url" )
{
if( value.startsWith( "/" ) )
value = '.' + value;
if( !value.startsWith( "./" ) )
value = "./" + value;
}
searchCriteria += CollectionDB::likeCondition( value, false, true );
}
else if( criteria == i18n("does not start with") )
{
if( field == "tags.url" )
{
if( value.startsWith( "/" ) )
value = '.' + value;
if( !value.startsWith( "./" ) )
value = "./" + value;
}
searchCriteria += " NOT " + CollectionDB::likeCondition( value, false, true );
}
else if( criteria == i18n("ends with") )
searchCriteria += CollectionDB::likeCondition( value, true, false );
else if( criteria == i18n("does not end with") )
searchCriteria += " NOT " + CollectionDB::likeCondition( value, true, false );
else if( criteria == i18n("is greater than") || criteria == i18n("is after") )
searchCriteria += " > " + value;
else if( criteria == i18n("is smaller than") || criteria == i18n("is before" ) )
searchCriteria += " < " + value;
else if( criteria == i18n("is between") || criteria == i18n("is in the last") )
searchCriteria += " BETWEEN " + value;
else if( criteria == i18n("is not in the last") )
searchCriteria += " NOT BETWEEN " + value;
return searchCriteria;
}
void CriteriaEditor::setSearchCriteria( const TQString & )
{
//TODO
}
void CriteriaEditor::enableRemove( bool enable )
{
m_removeButton->setEnabled( enable );
}
void CriteriaEditor::slotRemoveCriteriaAny()
{
m_playlistEditor->removeCriteriaAny( this );
}
void CriteriaEditor::slotRemoveCriteriaAll()
{
m_playlistEditor->removeCriteriaAll( this );
}
void CriteriaEditor::slotAddCriteriaAny()
{
m_playlistEditor->addCriteriaAny();
}
void CriteriaEditor::slotAddCriteriaAll()
{
m_playlistEditor->addCriteriaAll();
}
void CriteriaEditor::slotFieldSelected( int field )
{
int valueType = getValueType( field );
loadCriteriaList( valueType );
loadEditWidgets();
m_currentValueType = valueType;
//enable auto-completion for artist, album, composer, label, mountpoint and genre
if( valueType == AutoCompletionString ) {
TQStringList items;
m_comboBox->clear();
m_comboBox->completionObject()->clear();
int currentField = m_fieldCombo->currentItem();
if( currentField == FArtist ) //artist
items = CollectionDB::instance()->artistList();
else if( currentField == FComposer ) //composer
items = CollectionDB::instance()->composerList();
else if( currentField == FAlbum ) //album
items = CollectionDB::instance()->albumList();
else if (currentField == FLabel ) //label
items = CollectionDB::instance()->labelList();
else if (currentField == FMountPoint ) //mount point
{
KMountPoint::List mountpoints = KMountPoint::currentMountPoints( KMountPoint::NeedRealDeviceName );
foreachType( KMountPoint::List, mountpoints )
{
/* This code is adapted from KDE mediamanager's fstabbackend.cpp
* Copyright Kévin Ottens, Bernhard Rosenkraenzer, and from looking
* at the commit messages a few other guys who didn't add their name to the header.
*/
TQString device = (*it)->realDeviceName();
TQString fs = (*it)->mountType();
TQString mountpoint = (*it)->mountPoint();
if ( fs != "swap"
&& fs != "tmpfs"
&& fs != "sysfs"
&& fs != "fdescfs"
&& fs != "kernfs"
&& fs != "usbfs"
&& !fs.contains( "proc" )
&& fs != "unknown"
&& fs != "none"
&& fs != "sunrpc"
&& fs != "none"
&& device != "tmpfs"
&& device.find("shm") == -1
&& mountpoint != "/dev/swap"
&& mountpoint != "/dev/pts"
&& mountpoint.find("/proc") != 0
&& mountpoint.find("/sys") != 0
|| fs.find( "smb" ) != -1
|| fs.find( "cifs" ) != -1
|| fs.find( "nfs" ) != -1
)
items << mountpoint;
}
}
else //genre
items = CollectionDB::instance()->genreList();
m_comboBox->insertStringList( items );
m_comboBox->completionObject()->insertItems( items );
m_comboBox->completionObject()->setIgnoreCase( true );
m_comboBox->setCurrentText( "" );
m_comboBox->setFocus();
}
}
void CriteriaEditor::loadEditWidgets()
{
int valueType = getValueType( m_fieldCombo->currentItem() );
if( m_currentValueType == valueType && !(
m_criteriaCombo->currentText() == i18n( "is between" ) ||
m_criteriaCombo->currentText() == i18n( "is in the last" ) ||
m_criteriaCombo->currentText() == i18n( "is not in the last" ) ||
m_lastCriteria == i18n( "is between" ) ||
m_lastCriteria == i18n( "is in the last" ) ||
m_lastCriteria == i18n( "is not in the last" ) ) )
return;
/* Store lastCriteria. This information is used above to decide whether it's necessary to change the Widgets */
m_lastCriteria = m_criteriaCombo->currentText();
TQObjectList* list = m_editBox->queryList( "TQWidget" );
for( TQObject *obj = list->first(); obj; obj = list->next() )
obj->deleteLater();
delete list;
switch( valueType ) {
case String:
{
m_lineEdit = new KLineEdit( m_editBox );
m_lineEdit->setFocus();
m_lineEdit->show();
break;
}
case AutoCompletionString: //artist, composer, album, genre, label
{
m_comboBox = new KComboBox( true, m_editBox );
m_lineEdit = static_cast<KLineEdit*>( m_comboBox->lineEdit() );
m_lineEdit->setFocus();
m_comboBox->setMinimumSize( TQSize( 240, 20 ) );
m_comboBox->show();
break;
}
case Year: //fall through
case Number:
{
bool yearField = m_fieldCombo->currentText() == i18n("Year");
m_intSpinBox1 = new KIntSpinBox( m_editBox );
int maxValue = 1000;
if( yearField ) {
maxValue = TQDate::currentDate().year();
m_intSpinBox1->setValue( maxValue );
}
m_intSpinBox1->setMaxValue( maxValue );
m_intSpinBox1->setFocus();
m_intSpinBox1->show();
if( m_criteriaCombo->currentText() == i18n("is between") ) {
m_rangeLabel = new TQLabel( i18n("and"), m_editBox );
m_rangeLabel->setAlignment( AlignCenter );
m_rangeLabel->show();
m_intSpinBox2 = new KIntSpinBox( m_editBox );
if( yearField ) {
maxValue = TQDate::currentDate().year();
m_intSpinBox2->setValue( maxValue );
}
m_intSpinBox2->setMaxValue( maxValue );
m_intSpinBox2->show();
}
break;
}
case Rating:
{
const TQStringList list = MetaBundle::ratingList();
m_comboBox = new KComboBox( false, m_editBox );
m_comboBox->insertStringList( list );
m_comboBox->show();
if( m_criteriaCombo->currentText() == i18n("is between") ) {
m_rangeLabel = new TQLabel( i18n("and"), m_editBox );
m_rangeLabel->setAlignment( AlignCenter );
m_rangeLabel->show();
m_comboBox2 = new KComboBox( false, m_editBox );
m_comboBox2->insertStringList( list );
m_comboBox2->show();
}
break;
}
case Date:
{
if( m_criteriaCombo->currentText() == i18n("is in the last") ||
m_criteriaCombo->currentText() == i18n("is not in the last") ) {
m_intSpinBox1 = new KIntSpinBox( m_editBox );
m_intSpinBox1->setMinValue( 1 );
m_intSpinBox1->show();
m_dateCombo = new KComboBox( m_editBox );
m_dateCombo->insertItem( i18n("Days") );
m_dateCombo->insertItem( i18n("Months") );
m_dateCombo->insertItem( i18n("Years") );
m_dateCombo->show();
}
else {
m_dateEdit1 = new TQDateEdit( TQDate::currentDate(), m_editBox);
m_dateEdit1->setFocus();
m_dateEdit1->show();
if( m_criteriaCombo->currentText() == i18n("is between") ) {
m_rangeLabel = new TQLabel( i18n("and"), m_editBox );
m_rangeLabel->setAlignment( AlignCenter );
m_rangeLabel->show();
m_dateEdit2 = new TQDateEdit( TQDate::currentDate(), m_editBox);
m_dateEdit2->show();
}
}
break;
}
case Length:
{
m_intSpinBox1 = new KIntSpinBox( m_editBox );
int maxValue = 1000;
m_intSpinBox1->setMaxValue( maxValue );
m_intSpinBox1->setFocus();
m_intSpinBox1->show();
if( m_criteriaCombo->currentText() == i18n("is between") ) {
m_rangeLabel = new TQLabel( i18n("and"), m_editBox );
m_rangeLabel->setAlignment( AlignCenter );
m_rangeLabel->show();
m_intSpinBox2 = new KIntSpinBox( m_editBox );
m_intSpinBox2->setMaxValue( maxValue );
m_intSpinBox2->show();
}
m_lengthCombo = new KComboBox( m_editBox );
m_lengthCombo->insertItem( i18n( "Seconds" ) );
m_lengthCombo->insertItem( i18n( "Minutes" ) );
m_lengthCombo->insertItem( i18n( "Hours" ) );
m_lengthCombo->show();
}
default: ;
};
}
void CriteriaEditor::loadCriteriaList( int valueType, TQString condition )
{
if( m_currentValueType == valueType && condition.isNull() )
return;
TQStringList items;
switch( valueType ) {
case String:
case AutoCompletionString:
items << i18n( "contains" ) << i18n( "does not contain" ) << i18n( "is" ) << i18n( "is not" )
<< i18n( "starts with" ) << i18n( "does not start with" )
<< i18n( "ends with" ) << i18n( "does not end with" );
break;
case Rating:
case Length:
case Number:
items << i18n( "is" ) << i18n( "is not" ) << i18n( "is greater than" ) << i18n( "is smaller than" )
<< i18n( "is between" );
break;
case Year: //fall through
case Date:
items << i18n( "is" ) << i18n( "is not" ) << i18n( "is before" ) << i18n( "is after" )
<< i18n( "is in the last" ) << i18n( "is not in the last" ) << i18n( "is between" );
break;
default: ;
};
m_criteriaCombo->clear();
m_criteriaCombo->insertStringList( items );
if ( !condition.isEmpty() ) {
int index = items.findIndex( condition );
if (index!=-1)
m_criteriaCombo->setCurrentItem( index );
}
}
int CriteriaEditor::getValueType( int index )
{
int valueType;
switch( index ) {
case FArtist:
case FComposer:
case FAlbum:
case FGenre:
case FLabel:
case FMountPoint:
valueType = AutoCompletionString;
break;
case FTitle:
case FComment:
case FFilePath:
valueType = String;
break;
case FLength:
valueType = Length;
break;
case FTrack:
case FScore:
case FPlayCounter:
case FBPM:
case FBitRate:
valueType = Number;
break;
case FRating:
valueType = Rating;
break;
case FYear:
valueType = Year;
break;
default: valueType = Date;
};
return valueType;
}
#include "smartplaylisteditor.moc"