|
|
|
/// (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 <klocale.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, TQT_SIGNAL( toggled(bool) ), m_criteriaAnyGroupBox, TQT_SLOT( setEnabled(bool) ) );
|
|
|
|
connect( m_matchAllCheck, TQT_SIGNAL( toggled(bool) ), m_criteriaAllGroupBox, TQT_SLOT( setEnabled(bool) ) );
|
|
|
|
connect( m_orderCheck, TQT_SIGNAL( toggled(bool) ), orderBox, TQT_SLOT( setEnabled(bool) ) );
|
|
|
|
connect( m_limitCheck, TQT_SIGNAL( toggled(bool) ), limitBox, TQT_SLOT( setEnabled(bool) ) );
|
|
|
|
connect( m_expandCheck, TQT_SIGNAL( toggled(bool) ), expandBox, TQT_SLOT( setEnabled(bool) ) );
|
|
|
|
connect( m_orderCombo, TQT_SIGNAL( activated(int) ), this, TQT_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, TQT_SIGNAL( activated(int) ), TQT_SLOT( slotFieldSelected(int) ) );
|
|
|
|
connect( m_criteriaCombo, TQT_SIGNAL( activated(int) ), TQT_SLOT( loadEditWidgets() ) );
|
|
|
|
if (criteriaType == SmartPlaylistEditor::criteriaAny) {
|
|
|
|
connect( m_addButton, TQT_SIGNAL( clicked() ), editor, TQT_SLOT( addCriteriaAny() ) );
|
|
|
|
connect( m_removeButton, TQT_SIGNAL( clicked() ), TQT_SLOT( slotRemoveCriteriaAny() ) );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
connect( m_addButton, TQT_SIGNAL( clicked() ), editor, TQT_SLOT( addCriteriaAll() ) );
|
|
|
|
connect( m_removeButton, TQT_SIGNAL( clicked() ), TQT_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_OBJECT_NAME_STRING );
|
|
|
|
for( TQObject *obj = list->first(); obj; obj = list->next() )
|
|
|
|
TQT_TQWIDGET(obj)->deleteLater();
|
|
|
|
|
|
|
|
delete list;
|
|
|
|
|
|
|
|
switch( valueType ) {
|
|
|
|
|
|
|
|
case String:
|
|
|
|
{
|
|
|
|
m |