/*
 * playlist.cpp
 *
 * Copyright (C) 2003-2005 Jürgen Kofler <kaffeine@gmx.net>
 * Copyright (C) 2005-2006 Christophe Thommeret <hftom@free.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <krandomsequence.h>
#include <tdeapplication.h>
#include <tdeglobalsettings.h>
#include <kiconloader.h>
#include <tdelocale.h>
#include <tdefiledialog.h>
#include <tdemessagebox.h>
#include <kmimetype.h>
#include <kstandarddirs.h>
#include <tdemessagebox.h>
#include <tdeio/netaccess.h>
#include <tdeio/job.h>
#include <kprogress.h>
#include <tdefilemetainfo.h>
#include <klineedit.h>
#include <kcombobox.h>
#include <kpushbutton.h>
#include <kdebug.h>
#include <kurl.h>
#include <tdeaccel.h>
#include <dcopref.h>
#include <tdetoolbar.h>
#include <kcolordialog.h>
#include <kurlcombobox.h>
#include <kurlcompletion.h>

#include <tqlabel.h>
#include <tqclipboard.h>
#include <tqdragobject.h>
#include <tqstringlist.h>
#include <tqdom.h>
#include <tqxml.h>
#include <tqregexp.h>
#include <tqheader.h>
#include <tqlayout.h>
#include <tqpixmap.h>
#include <tqvbox.h>
#include <tqlistbox.h>
#include <tqtextcodec.h>
#include <tqtooltip.h>
#include <tqinputdialog.h>
#include <tqtimer.h>
#include <tqwhatsthis.h>
#include <tqpopupmenu.h>

#include "googlefetcher.h"
#include "mrl.h"
#include "playlistimport.h"
#include "playlistitem.h"
#include "playlist.h"
#include "playlist.moc"



RollTitle::RollTitle( TQWidget *parent ) : TQLabel( "I", parent )
{
	TQColorGroup cg = parentWidget()->colorGroup();
	TQColor base = cg.base();
	TQColor selection = cg.highlight();
	int r = (base.red() + selection.red()) / 2;
	int b = (base.blue() + selection.blue()) / 2;
	int g = (base.green() + selection.green()) / 2;
	back = TQColor(r, g, b);
	fore = parentWidget()->colorGroup().text();
	setPaletteBackgroundColor( back );
	setPaletteForegroundColor( fore );
	setFrameStyle( TQFrame::StyledPanel | TQFrame::Sunken );
	title = " ##### ";
	titleOffset = 0;
	setTitle( title );
	connect( &titleTimer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( rollTitle() ) );
	titleTimer.start( 50 );
}

void RollTitle::setTitle( MRL mrl )
{
	title = " ##### ";
	TQString s1 = mrl.artist().stripWhiteSpace();
	TQString s2 = mrl.album().stripWhiteSpace();
	TQString s3 = mrl.title().stripWhiteSpace();
	if ( !s1.isEmpty() )
		title+= s1+" - ";
	if ( !s2.isEmpty() )
		title+= s2+" - ";
	if ( s3.isEmpty() )
		title+= mrl.url();
	else
		title+= s3;
	titleOffset = 0;
	setTitle( title );
}

void RollTitle::setTitle( TQString t )
{
	TQLabel *lab = new TQLabel( t, this );
	lab->setFrameStyle( TQFrame::StyledPanel | TQFrame::Sunken );
	lab->resize( lab->sizeHint() );
	int x = 2*lab->frameWidth();
	titlePix = TQPixmap( lab->width()-x, height()-x, -1, TQPixmap::BestOptim );
	delete lab;
	TQPainter p( &titlePix );
	p.fillRect( 0, 0, titlePix.width(), titlePix.height(), back );
	p.setPen( fore );
	p.setFont( font() );
	p.drawText( TQRect(0,(titlePix.height()-TQFontInfo(font()).pointSize())/2,titlePix.width(),TQFontInfo(font()).pointSize()*2), TQt::AlignAuto|TQt::SingleLine, t );
	p.end();
}

void RollTitle::rollTitle()
{
	int w = 2*frameWidth();
	TQPixmap pix( width()-w, height()-w, -1, TQPixmap::BestOptim );
	TQPainter p1( &pix );
	p1.fillRect( 0, 0, pix.width(), pix.height(), back );
	p1.end();
	int x = titlePix.width()-titleOffset;
	bitBlt( &pix, 0, 0, &titlePix, titleOffset, 0, x, titlePix.height(), CopyROP );
	while ( x<pix.width() ) {
		bitBlt( &pix, x, 0, &titlePix, 0, 0, titlePix.width(), titlePix.height(), CopyROP );
		x+= titlePix.width();
	}
	++titleOffset;
	if ( titleOffset>titlePix.width() )
		titleOffset = 0;
	bitBlt( this, w/2, w/2, &pix, 0, 0, width()-w, height()-w, CopyROP );
}

void RollTitle::paintEvent( TQPaintEvent *pe )
{
	TQLabel::paintEvent( pe );
	TQColorGroup cg = parentWidget()->colorGroup();
	TQColor base = cg.base();
	TQColor selection = cg.highlight();
	int r = (base.red() + selection.red()) / 2;
	int b = (base.blue() + selection.blue()) / 2;
	int g = (base.green() + selection.green()) / 2;
	back=TQColor(r,g,b);
	setPaletteBackgroundColor( back );
	fore = parentWidget()->colorGroup().text();
	setPaletteForegroundColor( fore );
	setTitle( title );
}



struct CoverPopup : public TQWidget
{
    CoverPopup(const TQPixmap &image, const TQPoint &p) :
        TQWidget(0, 0, WDestructiveClose | WX11BypassWM)
    {
        TQHBoxLayout *layout = new TQHBoxLayout(this);
        TQLabel *label = new TQLabel(this);

        layout->addWidget(label);
        label->setFrameStyle(TQFrame::Box | TQFrame::Raised);
        label->setLineWidth(1);
        label->setPixmap(image);

        setGeometry(p.x(), p.y(), label->width(), label->height());
        show();
    }
    virtual void leaveEvent(TQEvent *) { close(); }
    virtual void mouseReleaseEvent(TQMouseEvent *) { close(); }
};

CoverFrame::CoverFrame( TQWidget *parent ) : TQFrame( parent )
{
	imagePath = "";
	TQString path = locate("appdata", "nocover.png");
	if ( !path )
		path = locate("data", "kaffeine/nocover.png");
	noCoverPix.convertFromImage( TQImage(path) );
	setPaletteBackgroundPixmap( noCoverPix );
}

CoverFrame::~CoverFrame()
{
}

void CoverFrame::setCoverPixmap( const TQString &path )
{
	TQPixmap pix;
	TQImage img;

	img = TQImage( path );
	if ( !img.isNull() ) {
		img = img.smoothScale( 80, 80 );
		pix.convertFromImage( img );
		setPaletteBackgroundPixmap( pix );
		imagePath = path;
	}
	else {
		setPaletteBackgroundPixmap( noCoverPix );
		imagePath = "";
	}
}

void CoverFrame::popup( const TQPixmap &pix ) const
{
    TQPoint mouse  = TQCursor::pos();
    TQRect desktop = TDEApplication::desktop()->screenGeometry(mouse);
    int x = mouse.x();
    int y = mouse.y();
    int height = pix.height() + 4;
    int width  = pix.width() + 4;

    // Detect the right direction to pop up (always towards the center of the
    // screen), try to pop up with the mouse pointer 10 pixels into the image in
    // both directions.  If we're too close to the screen border for this margin,
    // show it at the screen edge, accounting for the four pixels (two on each
    // side) for the window border.

    if(x - desktop.x() < desktop.width() / 2)
        x = (x - desktop.x() < 10) ? desktop.x() : (x - 10);
    else
        x = (x - desktop.x() > desktop.width() - 10) ? desktop.width() - width +desktop.x() : (x - width + 10);

    if(y - desktop.y() < desktop.height() / 2)
        y = (y - desktop.y() < 10) ? desktop.y() : (y - 10);
    else
        y = (y - desktop.y() > desktop.height() - 10) ? desktop.height() - height + desktop.y() : (y - height + 10);

    new CoverPopup( pix, TQPoint(x, y) );
}

void CoverFrame::mousePressEvent( TQMouseEvent *e )
{
	int i;
	TQPixmap pix;

	switch ( e->button() ) {
		case TQt::LeftButton: {
			if ( imagePath.isEmpty() )
				break;
			pix.convertFromImage( TQImage( imagePath ) );
			if ( !pix.isNull() )
				popup( pix );
			break;
		}
		case TQt::RightButton: {
			TQPopupMenu pop( this );
			pop.insertItem( i18n("Choose a Cover..."), 1 );
			pop.insertItem( i18n("Gallery..."), 2 );
			i = pop.exec( TQCursor::pos() );
			if ( i==1 )
				emit changeCurrentCover();
			else if ( i==2 )
				emit gallery();
			break;
		}
		default:
			break;
	}
}


PlayList::PlayList( TQWidget* parent, TQObject *objParent, const char *name ) : KaffeineInput(objParent , name),
		m_playTime(0), m_playTimeVisible(0), m_countVisible(0), m_searchSelection(false),
		m_metaOnLoading(true), m_sortAscending(true), m_currentEntry(NULL), m_currentRandomListEntry(-1),
		m_endless(false), m_random(false), m_useAlternateEncoding(false), m_alternateEncoding("ISO 8859-1")
{
	google = NULL;

	mainWidget = new TQVBox( parent );
	//mainWidget->setSizePolicy( TQSizePolicy (TQSizePolicy::Preferred, TQSizePolicy::Preferred) );
	hSplit = new TQSplitter( mainWidget );
	hSplit->setOpaqueResize( true );
	panel = new TQVBox( hSplit );
	playlist = new TQWidget( hSplit );
	hSplit->moveToFirst( panel );
	hSplit->setResizeMode( panel, TQSplitter::KeepSize );

	vSplit = new TQSplitter( TQt::Vertical, panel );
	vSplit->setOpaqueResize( true );
	TQWidget *vb = new TQWidget( vSplit );
	TDEToolBar *tb = new TDEToolBar( vb );
	TQVBoxLayout *v = new TQVBoxLayout( vb, 0, 0 );
	v->addWidget( tb );
	tb->setIconSize( 16 );

	browserComb = new KURLComboBox( KURLComboBox::Directories, true, vb );
	browserComb->setCompletionObject( new KURLCompletion( KURLCompletion::DirCompletion ) );
	browserComb->setAutoDeleteCompletionObject( true );
        browserComb->setMaxItems( 10 );
        browserComb->setFocusPolicy(TQWidget::ClickFocus);


       /* if (!m_medium)
            m_combo->lineEdit()->setText( location->path() );
        else
            m_combo->lineEdit()->setText( "/" );*/

	TQVBoxLayout *v1 = new TQVBoxLayout( 0, 3, 3 );
	v1->addWidget( browserComb );
	fileBrowser = new KDirOperator( KURL("/"), vb );
	fileBrowser->setupMenu( KDirOperator::SortActions|KDirOperator::NavActions|KDirOperator::ViewActions );
	view = new KFileIconView( fileBrowser, "view" );
	view->setSelectionMode( KFile::Multi );
	fileBrowser->setMode( KFile::Files );
	fileBrowser->setView( view );
	fileBrowser->setViewConfig( TDEGlobal::config(), "PlaylistFileBrowser" );
	fileBrowser->setOnlyDoubleClickSelectsFiles( true );
	v1->addWidget( fileBrowser );
	v->addLayout( v1 );

	TDEActionCollection *col = fileBrowser->actionCollection();
	col->action( "up" )->plug( tb );
	col->action( "back" )->plug( tb );
	col->action( "forward" )->plug( tb );
	col->action( "reload" )->plug( tb );
	col->action( "home" )->plug( tb );

	vSplit->moveToFirst( vb );
	playerBox = new TQVBox( vSplit );
	playerBox->setMinimumHeight( 50 );
	playerBox->setMinimumWidth( 200 );
	vSplit->moveToLast( playerBox );

	m_playlistDirectory = locateLocal("appdata", "playlists");
	m_playlistDirectory.append("/");
	TDEIO::NetAccess::mkdir(m_playlistDirectory, mainWidget);
	kdDebug() << "PLAYLIST" << endl;

	TQGridLayout* layout = new TQGridLayout( playlist, 4, 2, 3 );

	m_list = new UrlListView(playlist);
	mainWidget->setAcceptDrops(true);
	m_list->setHScrollBarMode(TDEListView::AlwaysOff);
	m_list->setItemMargin(2);
	m_list->setMargin(0);
	m_list->setSelectionMode(TQListView::Extended);
	m_list->addColumn("");
	m_list->addColumn(i18n("Title"));
	m_list->addColumn(i18n("Artist"));
	m_list->addColumn(i18n("Album"));
	m_list->addColumn(i18n("Track"));
	m_list->addColumn(i18n("Length"));
	m_list->setShowToolTips(true);
	m_list->setColumnWidthMode(MIME_COLUMN, TQListView::Manual);
	m_list->setColumnWidthMode(TITLE_COLUMN, TQListView::Manual);
	m_list->setColumnWidthMode(ARTIST_COLUMN, TQListView::Manual);
	m_list->setColumnWidthMode(ALBUM_COLUMN, TQListView::Manual);
	m_list->setColumnWidthMode(TRACK_COLUMN, TQListView::Manual);
	m_list->setColumnWidthMode(LENGTH_COLUMN, TQListView::Manual);
	m_list->setResizeMode(TQListView::NoColumn);
	TDEConfig* config = kapp->config();
	m_list->restoreLayout(config, "Playlist Layout");
	m_list->setFullWidth(true);
	m_list->setSorting(-1);
	m_list->setDragEnabled(true);
	m_list->setAcceptDrops(true);
	m_list->setDropVisualizer(true);
	m_list->setItemsMovable(true);
	m_list->setItemsRenameable(true);
	m_list->setRenameable(TITLE_COLUMN);
	m_list->setRenameable(ARTIST_COLUMN);
	m_list->setRenameable(ALBUM_COLUMN);
	m_list->setRenameable(TRACK_COLUMN);
	m_list->setAllColumnsShowFocus(true);
	m_list->setShowSortIndicator(true);
	layout->addMultiCellWidget(m_list, 3, 3, 0, 1);

	coverFrame = new CoverFrame( playlist );
	coverFrame->setFixedWidth( 80 );
	coverFrame->setFixedHeight( 80 );
	layout->addMultiCellWidget(coverFrame, 0, 2, 0, 0);

	TQHBoxLayout *h1 = new TQHBoxLayout();
	searchBtn = new TQToolButton( playlist );
	searchBtn->setAutoRaise( true );
	TQToolTip::add( searchBtn, i18n("Search"));
	searchBtn->setIconSet( TDEGlobal::iconLoader()->loadIconSet("locationbar_erase", TDEIcon::Small) );
	h1->addWidget( searchBtn );
	TQLabel* filterLabel = new TQLabel(i18n("Filter") + ":", playlist);
	h1->addWidget(filterLabel);
	m_playlistFilter = new KLineEdit(playlist);
	m_playlistFilter->setFocusPolicy(TQWidget::ClickFocus);
	h1->addWidget(m_playlistFilter);
	layout->addLayout( h1, 2, 1 );

	TQHBoxLayout *h2 = new TQHBoxLayout();
	TQLabel* playlistLabel = new TQLabel(i18n("Playlist:"), playlist);
	h2->addWidget(playlistLabel);
	m_playlistSelector = new KComboBox( playlist );
	m_playlistSelector->setMinimumWidth(10);
	m_playlistSelector->setSizePolicy( TQSizePolicy (TQSizePolicy::MinimumExpanding, TQSizePolicy::Preferred) );
	m_playlistSelector->setEditable(true);
	m_playlistSelector->setDuplicatesEnabled(false);
	m_playlistSelector->setFocusPolicy(TQWidget::ClickFocus);
	TQToolTip::add(m_playlistSelector, i18n("Select the active playlist. To change playlist name edit it and confirm with 'Return'."));
	h2->addWidget(m_playlistSelector);
	layout->addLayout( h2, 1, 1 );

	roller = new RollTitle( playlist );
	layout->addWidget( roller, 0, 1 );

	TDEAccel* accel = new TDEAccel(mainWidget);
	accel->insert("Delete selected", TQt::Key_Delete, this, TQ_SLOT(slotRemoveSelected()));

	m_isCurrentEntry = UserIcon("playing");
	m_cdPixmap = TDEGlobal::iconLoader()->loadIcon("application-x-cda", TDEIcon::Small);

	setXMLFile("kaffeineplaylist.rc");
	setupActions();

	TQStrList formats = TQImageIO::outputFormats();
	coverImageFormat = "PNG";
	for (int i=0; i<(int)formats.count(); i++ ) {
		if ( TQString(formats.at(i))=="JPEG" ) {
			coverImageFormat = "JPEG";
			break;
		}
	}

	loadConfig( TDEGlobal::config() );

	connect(coverFrame, TQ_SIGNAL(changeCurrentCover()), this, TQ_SLOT(chooseCurrentCover()));
	connect(coverFrame, TQ_SIGNAL(gallery()), this, TQ_SLOT(showGallery()));
	connect(browserComb, TQ_SIGNAL(urlActivated( const KURL& )), this, TQ_SLOT(setBrowserURL( const KURL& )));
	connect(browserComb, TQ_SIGNAL(returnPressed( const TQString& )), this, TQ_SLOT(setBrowserURL( const TQString& )));
	connect(fileBrowser, TQ_SIGNAL(urlEntered( const KURL& )), this, TQ_SLOT(browserURLChanged( const KURL& )));
	connect(fileBrowser, TQ_SIGNAL(fileSelected(const KFileItem*)), this, TQ_SLOT(fileSelected(const KFileItem*)));
	connect(m_playlistFilter, TQ_SIGNAL(textChanged(const TQString&)), this, TQ_SLOT(slotFindText(const TQString&)));
	connect( searchBtn, TQ_SIGNAL(clicked()), this, TQ_SLOT(resetSearch()) );
	connect(m_playlistSelector, TQ_SIGNAL(returnPressed(const TQString&)), this, TQ_SLOT(slotNewPlaylistName(const TQString&)));
	connect(m_playlistSelector, TQ_SIGNAL(activated(int)),this, TQ_SLOT(slotPlaylistActivated(int)));
	connect(m_list, TQ_SIGNAL(dropped(TQDropEvent*, TQListViewItem*)), this, TQ_SLOT(slotDropEvent(TQDropEvent*, TQListViewItem*)));
	connect(m_list, TQ_SIGNAL(aboutToMove()), this, TQ_SLOT(slotPreDropEvent()));
	connect(m_list, TQ_SIGNAL(doubleClicked(TQListViewItem*)), this, TQ_SLOT(slotPlayDirect(TQListViewItem*)));
	connect(m_list, TQ_SIGNAL(returnPressed(TQListViewItem*)), this, TQ_SLOT(slotPlayDirect(TQListViewItem*)));
	connect(m_list, TQ_SIGNAL(signalCut()), this, TQ_SLOT(slotCut()));
	connect(m_list, TQ_SIGNAL(signalCopy()), this, TQ_SLOT(slotCopy()));
	connect(m_list, TQ_SIGNAL(signalPaste()), this, TQ_SLOT(slotPaste()));
	connect(m_list, TQ_SIGNAL(signalSelectAll()), this, TQ_SLOT(slotSelectAll()));
	connect(m_list, TQ_SIGNAL(signalPlayItem(TQListViewItem*)), this, TQ_SLOT(slotPlayDirect(TQListViewItem*)));
	connect(m_list, TQ_SIGNAL(signalPlaylistFromSelected()), this, TQ_SLOT(slotPlaylistFromSelected()));
	connect(m_list, TQ_SIGNAL(signalAddToQueue(MRL)), this, TQ_SLOT(slotAddToQueue(MRL)));
	connect(m_list->header(), TQ_SIGNAL(clicked(int)), this, TQ_SLOT(slotSort(int)));
}

void PlayList::togglePanel()
{
	if ( panel->isHidden() )
		panel->show();
	else
		panel->hide();
}

void PlayList::getTargets( TQStringList &uiNames, TQStringList &iconNames, TQStringList &targetNames )
{
	uiNames.append( i18n("Play Playlist") );
	iconNames.append( "view_text" );
	targetNames.append( "PLAYLIST" );
}

bool PlayList::execTarget( const TQString &target )
{
	if ( target=="PLAYLIST" ) {
		emit showMe( this );
		TQTimer::singleShot( 100, this, TQ_SLOT(startPlaylist()) );
		return true;
	}
	return false;
}

void PlayList::setFileFilter( const TQString& filter )
{
	m_fileFilter = filter;
	fileBrowser->setNameFilter( m_fileFilter );
}

PlayList::~PlayList()
{
	delete m_list;
}

void PlayList::setupActions()
{
	m_repeat = new TDEToggleAction(i18n("&Repeat"), 0 , CTRL|Key_E, this, TQ_SLOT(slotRepeat()), actionCollection(),"playlist_repeat");
	m_repeat->setStatusText(i18n("Loop playlist"));
	m_shuffle = new TDEToggleAction(i18n("Sh&uffle"), 0 , CTRL|Key_R, this, TQ_SLOT(slotShuffle()), actionCollection(),"playlist_shuffle");
	m_shuffle->setStatusText(i18n("Play items in random order"));
	m_autoCover = new TDEToggleAction(i18n("Autodownload covers"), 0 , 0, this, TQ_SLOT(slotAutoCover()), actionCollection(),"playlist_autocover");
	m_autoCover->setStatusText(i18n("Automatic dowloading of covers"));
	m_showPlayer = new TDEToggleAction(i18n("Don't switch to player window"), 0 , 0, this, TQ_SLOT(slotShowPlayer()), actionCollection(),"playlist_showplayer");
	m_showPlayer->setStatusText(i18n("Don't switch automatically to player window"));
	new TDEAction(i18n("&Clear Current Playlist"), "eraser", 0, this, TQ_SLOT(slotClearList()), actionCollection(), "playlist_clear");
	new TDEAction(i18n("Ne&w Playlist"), "document-new", 0, this, TQ_SLOT(slotNewList()), actionCollection(), "playlist_new");
	new TDEAction(i18n("&Import Playlist..."), "project_open", 0, this, TQ_SLOT(slotPlaylistLoad()), actionCollection(), "playlist_load");
	new TDEAction(i18n("&Save Current Playlist As..."), "document-save-as", 0, this, TQ_SLOT(slotPlaylistSaveAs()), actionCollection(), "playlist_save_as");
	new TDEAction(i18n("Re&move Current Playlist"), "window-close", 0, this, TQ_SLOT(slotPlaylistRemove()), actionCollection(), "playlist_remove");
}

void PlayList::slotClearList()
{
	clearList();
}

void PlayList::slotRepeat()
{
	setEndless(m_repeat->isChecked());
}

void PlayList::slotShuffle()
{
	setRandom(m_shuffle->isChecked());
}

void PlayList::slotAutoCover()
{
	m_cover = m_autoCover->isChecked();
}

void PlayList::slotShowPlayer()
{
}

void PlayList::slotToggleShuffle()
{
	m_shuffle->setChecked(!m_shuffle->isChecked());
	slotShuffle();
}

void PlayList::slotPlaylistLoad()
{
	TQString path = KFileDialog::getOpenFileName(":kaffeine_openPlaylist", TQString("*.kaffeine|") + i18n("Kaffeine Playlists") + "\n*.*|" + i18n("All Files"), 0, i18n("Open Playlist"));
	if (path.isEmpty() || (!path.contains(".kaffeine", false)))
		return;

	loadPlaylist(path);
}

void PlayList::slotPlaylistSaveAs()
{
	TQString startPath = ":kaffeine_savePlaylist";
	//if (!lastPlaylist.isEmpty()) startPath = lastPlaylist;
	TQString path = KFileDialog::getSaveFileName(startPath,
		TQString("*.kaffeine|") + i18n("Kaffeine Playlists") + "\n" +
		TQString("*.m3u|") + i18n("M3U Playlists") + "\n" +
		TQString("*.pls|") + i18n("PLS Playlists") + "\n" +
		"*.*|" + i18n("All Files"), 0, i18n("Save Playlist"));

	if ( path.isEmpty() )
		return;
	if ( path.right(4).lower() == ".m3u" ) {
		exportM3UPlaylist(path);
	} else if ( path.right(4).lower() == ".pls" ) {
		exportPLSPlaylist(path);
	} else if ( path.right(9).lower() == ".kaffeine" ) {
		savePlaylist(path);
	} else {
		path.append(".kaffeine");
		savePlaylist(path);
	}
}

void PlayList::slotPlaylistRemove()
{
	removeCurrentPlaylist();
}

TQWidget* PlayList::wantPlayerWindow()
{
	return playerBox;
}

TQWidget* PlayList::inputMainWidget()
{
	return mainWidget;
}

void PlayList::loadConfig(TDEConfig* config)
{
	TQValueList<int> sl;
	bool b;

	config->setGroup("Playlist");
	b = config->readBoolEntry("Endless Mode", false);
	m_repeat->setChecked(b);
	setEndless(b);
	b = config->readBoolEntry("Random Mode", false);
	m_shuffle->setChecked(b);
	setRandom(b);
	b = config->readBoolEntry("AutoCover", false);
	m_autoCover->setChecked(b);
	m_cover = b;
	b = config->readBoolEntry("DontShowPlayer", false);
	m_showPlayer->setChecked(b);

	sl = config->readIntListEntry("HSplitSizes");
	if ( sl.count() )
		hSplit->setSizes( sl );
	else {
		sl.append( 200 );
		sl.append( 200 );
		hSplit->setSizes( sl );
	}
	vSplit->setSizes( config->readIntListEntry("VSplitSizes") );
	TQStringList list;
	list = config->readListEntry("Playlists");
	if (!list.count())
	{
		list.append(i18n("Playlist") + "1");
	}
	int lastRegularPlaylist = list.count();
	list.append(i18n("NEW"));
	m_playlistSelector->insertStringList(list);
	m_currentPlaylist = config->readNumEntry("Current", 0);
	if (m_currentPlaylist > lastRegularPlaylist)
		m_currentPlaylist = 0;
	m_playlistSelector->setCurrentItem(m_currentPlaylist);
	add(m_playlistDirectory + m_playlistSelector->text(m_currentPlaylist) + ".kaffeine", NULL);
	m_nextPlaylistNumber = config->readNumEntry("Next Playlist", 2);
	TQString currentEntry = config->readEntry("Current Entry", TQString());
	if ((!currentEntry.isEmpty()) && (m_list->childCount()))
	{
		TQListViewItem* tmp = findByURL(currentEntry);
		if (tmp)
			setCurrentEntry(tmp, false);
	}
	fileBrowser->readConfig( config, "PlaylistFileBrowser" );
	fileBrowser->setURL( KURL(config->readEntry( "FileBrowserURL", "/" )), true );
	browserComb->setURL( KURL(config->readEntry( "FileBrowserURL", "/" )) );
}

void PlayList::saveConfig()
{
	saveConfig( TDEGlobal::config() );
}

void PlayList::saveConfig(TDEConfig* config)
{
	saveCurrentPlaylist();
	config->setGroup("Playlist");
	config->writeEntry("Endless Mode", m_repeat->isChecked());
	config->writeEntry("Random Mode", m_shuffle->isChecked());
	config->writeEntry("AutoCover", m_autoCover->isChecked());
	config->writeEntry("DontShowPlayer", m_showPlayer->isChecked());
	config->writeEntry( "HSplitSizes", hSplit->sizes() );
	config->writeEntry( "VSplitSizes", vSplit->sizes() );
	TQStringList list;
	TQString text;
	for (uint i=0; i < m_playlistSelector->listBox()->count(); i++)
	{
		text = m_playlistSelector->text(i);
		if ( text != i18n("NEW") )
			list.append(text);
	}
	config->writeEntry("Playlists", list);
	config->writeEntry("Current", m_currentPlaylist);
	config->writeEntry("Next Playlist", m_nextPlaylistNumber);
	config->writeEntry("Current Entry", m_currentEntryMRL.url());
	m_list->saveLayout(config, "Playlist Layout");
	fileBrowser->writeConfig( config, "PlaylistFileBrowser" );
	config->writeEntry( "FileBrowserURL", fileBrowser->url().url() );
}

void PlayList::closeEvent(TQCloseEvent* ce)
{
	kdDebug() << "Playlist: close Event" << endl;
	ce->ignore();
}

/******************************************
 *      get the urls from playlist
 ******************************************/
void PlayList::startPlaylist()
{
	MRL mrl;
	if ( trackNumber( 1, mrl ) )
		emit play( mrl, this );
}

bool PlayList::currentTrack( MRL &mrl )
{
	mrl = getCurrent();
	if ( !mrl.isEmpty() )
		return true;
	else
		return false;
}

MRL PlayList::getCurrent()
{
	if (isQueueMode())
	{
		m_queue.clear();
		updateStatus();
	}

	if (m_random)
	{
		if (m_currentRandomListEntry == -1) return MRL();
		setCurrentEntry(m_randomList.at(m_currentRandomListEntry));
		return m_currentEntryMRL;
	}

	if (!m_currentEntry)
		if (m_list->childCount() > 0)
		{
			if (m_list->firstChild()->isVisible())
				setCurrentEntry(m_list->firstChild());
			else
			{
				if (m_list->firstChild()->itemBelow())
					setCurrentEntry(m_list->firstChild()->itemBelow());
				else
					return MRL();
			}
		}
		else
			return MRL();

	setCurrentEntry(m_currentEntry);
	return m_currentEntryMRL;
}

bool PlayList::playbackFinished( MRL &mrl )
{
	return nextTrack( mrl );
}

bool PlayList::nextTrack( MRL &mrl )
{
	if (isQueueMode())
	{
		mrl = m_queue.first();
		m_queue.remove(m_queue.begin());
		updateStatus();
		return true;
	}

	if (!m_currentEntry) {
		mrl = getCurrent();
		if ( !mrl.isEmpty() )
			return true;
		else
			return false;
	}

	if (m_random)
	{
		if ((m_currentRandomListEntry+1) < (int)m_randomList.count())
			m_currentRandomListEntry += 1;
		else
		{
			if (m_endless)
				m_currentRandomListEntry = 0;
			else
				return false;
		}
		setCurrentEntry(m_randomList.at(m_currentRandomListEntry));
		mrl = m_currentEntryMRL;
		return true;
	}

	TQListViewItem* tmpItem;
	tmpItem = m_currentEntry->itemBelow();

	if (tmpItem)
	{
		setCurrentEntry(tmpItem);
		mrl = m_currentEntryMRL;
		return true;
	}
	else
	{
		if (m_endless)
		{
			setCurrentEntry(m_list->firstChild());
			mrl =  m_currentEntryMRL;
			return true;
		}
		else
			return false;
	}
}

bool PlayList::previousTrack( MRL &mrl )
{
	if (isQueueMode())
	{
		m_queue.clear();
		updateStatus();
	}

	if (!m_currentEntry) {
		mrl = getCurrent();
		if ( !mrl.isEmpty() )
			return true;
		else
			return false;
	}

	if (m_random) {
		if (m_currentRandomListEntry > 0)
			m_currentRandomListEntry -= 1;
		else {
			if (m_endless)
				m_currentRandomListEntry = m_randomList.count()-1;
			else
				return false;
		}
		setCurrentEntry(m_randomList.at(m_currentRandomListEntry));
		mrl = m_currentEntryMRL;
		return true;
	}

	TQListViewItem* tmpItem;
	tmpItem = m_currentEntry->itemAbove();

	if (tmpItem) {
		setCurrentEntry(tmpItem);
		mrl = m_currentEntryMRL;
		return true;
	}
	else {
		if (m_endless) {
			setCurrentEntry(getLast());
			mrl = m_currentEntryMRL;
			return true;
		}
		else
			return false;
	}
}

bool PlayList::trackNumber( int number, MRL &mrl )
{
	if (number > m_list->childCount())
		return false;

	TQListViewItem * item = m_list->firstChild();
	for (int i = 1; i < number; i++)
		item = item->nextSibling();

	setCurrentEntry(item);
	mrl = m_currentEntryMRL;
	return true;
}

TQListViewItem* PlayList::getLast()
{
	return m_list->lastItem();
}

TQListViewItem* PlayList::getFirst()
{
	return m_list->firstChild();
}

TQListViewItem* PlayList::findByURL(const TQString& url)
{
	TQListViewItemIterator it(m_list);
	while (it.current())
	{
		if (dynamic_cast<PlaylistItem*>(*it)->url() == url)
		{
			return (*it);
		}
		++it;
	}

	/* fallback */
	return getFirst();
}

/********* set current entry (with play icon) ****************/

void PlayList::setCurrentEntry(TQListViewItem* item, bool playIcon)
{
	PlaylistItem* newItem = dynamic_cast<PlaylistItem*>(item);
	PlaylistItem* oldItem = dynamic_cast<PlaylistItem*>(m_currentEntry);
	if (m_currentEntry)
	{
		oldItem->setPlaying(false);
		m_currentEntry->setPixmap(TITLE_COLUMN, TQPixmap());
	}
	if (playIcon)
	{
		newItem->setPlaying(true);
		item->setPixmap(TITLE_COLUMN, m_isCurrentEntry);
	}
	m_currentEntry = item;
	if (m_random)
		m_currentRandomListEntry = m_randomList.find(item);
	m_currentEntryMRL = newItem->toMRL();
	roller->setTitle( m_currentEntryMRL );
	m_list->setCurrentItem(m_currentEntry);

	m_list->ensureVisible(10, m_list->itemPos(m_currentEntry), 10, 30);
}

TQListViewItem* PlayList::insertItem(TQListViewItem* after, const MRL& m)
{
	PlaylistItem* tmp = NULL;
	MRL mrl(m);

	m_list->setSorting(-1);
	TQListViewItemIterator it(m_list);
	while (it.current())
	{
		if (dynamic_cast<PlaylistItem*>(*it)->url() == mrl.url())
		{
			kdDebug() << "PlayList: Source '" << mrl.url() << "' still exists. Skipped." << endl;
			return after;
		}
		++it;
	}

	if (mrl.mime().isNull())
	{
		KMimeType::Ptr mime = KMimeType::findByURL(mrl.kurl().path());
		mrl.setMime(mime->name());
	}

	tmp = new PlaylistItem(m_list, dynamic_cast<TDEListViewItem *>(after), mrl);
	if (!tmp) return after;

	if ((mrl.mime() == "video/dvd") || (mrl.mime() == "video/vcd") || (mrl.mime() == "audio/cd"))
		tmp->setPixmap(MIME_COLUMN, m_cdPixmap);
	else
		tmp->setPixmap(MIME_COLUMN, KMimeType::mimeType(mrl.mime())->pixmap(TDEIcon::Small));

	if (tmp->length().contains(':'))
		m_playTime += timeStringToMs(tmp->length());

	if (m_searchSelection)
	{
		TQString text = m_playlistFilter->text();
		if ((!tmp->title().contains(text, false)) && (!tmp->url().contains(text, false))
		        && (!tmp->artist().contains(text, false)) && (!tmp->album().contains(text, false)))
		{
			tmp->setVisible(false);
		}
	}

	if (tmp->isVisible())
	{
		if (tmp->length().contains(':'));
		m_playTimeVisible += timeStringToMs(tmp->length());
		m_countVisible++;
	}

	return tmp;
}

void PlayList::fileSelected( const KFileItem *item )
{
	if ( !item )
		return;
	add( TQStringList( item->url().path() ), NULL );
	TQListViewItem* tmp = findByURL(item->url().path());
	if (tmp) {
		setCurrentEntry(tmp);
		emit play(m_currentEntryMRL, this);
	}
}

void PlayList::setBrowserURL( const TQString &path )
{
	fileBrowser->setURL( KURL(path), true );
}

void PlayList::setBrowserURL( const KURL &path )
{
	fileBrowser->setURL( path, true );
}

void PlayList::browserURLChanged( const KURL &u )
{
	TQString url;

	 if ( u.isLocalFile() )
	 	url = u.path();
	 else
	 	url = u.prettyURL();

	TQStringList urls = browserComb->urls();
	urls.remove( url ); // do not duplicate
	urls.prepend( url );
	browserComb->setURLs( urls, KURLComboBox::RemoveBottom );
}

void PlayList::add(const TQString& url, TQListViewItem* after)
{
	add(TQStringList(url), after);
}


void PlayList::add(const TQStringList& urlList, TQListViewItem* after)
{
	TQListViewItem* tmp = NULL;
	TQStringList urls(urlList);

	TQString ext;
	TQString subtitleURL;
	TQStringList subs;
	KURL tmpKURL;
	bool playlist;
	MRL mrl;
	TQValueList<MRL> mrlList;
	TQString mediadevice="";

	KProgressDialog* progress = NULL;
	progress = new KProgressDialog(mainWidget, "importprogress", TQString(), i18n("Importing media resources..."));
	progress->progressBar()->setTotalSteps(urls.count());
	progress->show();

	kdDebug() << "PlayList: add " << urls.count() << " items to playlist" << endl;

	for (uint i = 0; i < urls.count(); i++)
	{
		mrl = MRL(urls[i]);
		TQString url(mrl.kurl().prettyURL());

		if (mrl.kurl().protocol() == "media" || url.startsWith("system:/media/"))
		{
			TQString mediaName;
			if (url.startsWith("system:/media/"))
				mediaName = url.mid(14);
			else
				mediaName = url.mid(7);
			int slash = mediaName.find("/");
			TQString filePath(mediaName.mid(slash));
			if (filePath == "/")
				filePath = "";
			mediaName = mediaName.left(slash);

			DCOPRef mediamanager("kded","mediamanager");
			DCOPReply reply = mediamanager.call("properties(TQString)",mediaName);
			if (reply.isValid())
			{
				TQStringList properties = reply;
				if (properties.isEmpty()) break;
				url = properties[6]  + filePath;
				if (filePath.isEmpty())
				{
					if (properties[10] == "media/audiocd")
					{
						mediadevice = properties[5];
						delete progress;
						emit signalRequestForAudioCD(mediadevice);
						return;
					}
					if (properties[10] == "media/dvdvideo" || properties[10] == "media/blurayvideo")
					{
						mediadevice = properties[5];
						delete progress;
						emit signalRequestForDVD(mediadevice);
						return;
					}
					if ((properties[10] == "media/vcd") || (properties[10] == "media/svcd"))
					{
						mediadevice = properties[5];
						delete progress;
						emit signalRequestForVCD(mediadevice);
						return;
					}
				}
				mrl = MRL(url);
			}
		}

		if (mrl.kurl().isLocalFile())
		{
			if (!TQFile::exists(mrl.kurl().path()))
				continue;
			mrl.setTitle(mrl.kurl().fileName());
			mrl.setURL(mrl.kurl().path());
		}
		else
		{
			mrl.setTitle(mrl.url());
		}

		//kdDebug() << "PlayList: Check url " << mrl.url() << endl;
		/*********** determine extension and mime type ************/

		ext = mrl.kurl().fileName();
		ext = ext.remove(0 , ext.findRev('.') +1).lower();
		// kdDebug() << "Extension: " << ext << endl;

		//kdDebug() << "PlayList: Try to determine mime of: " << mrl.url() << endl;
		KMimeType::Ptr mime = KMimeType::findByURL(mrl.kurl().path()); /* works only with path() (without protocol)
		                                                                      e.g. http://www.somafm.com/indipop.pls
		                                                                      path: /indipop.pls */
		//kdDebug() << "Mime: " << mime->name() << endl;
		/*** check for kaffeine/noatun/pls/asx/m3u playlist ***/
		mrl.setMime(mime->name());

		/******** some special processing for local files! *******/
		if (mrl.kurl().isLocalFile())
		{
			/* playlist ? */
			if ((mime->name() == "text/plain") || (mime->name() == "text/xml") || (mime->name() == "application/x-kaffeine")
			        || (mime->name() == "audio/x-scpls") || (mime->name() == "audio/x-mpegurl" || (mime->name() == "audio/mpegurl")
			                || (ext == "asx") || (ext == "asf") || (ext == "wvx") || (ext == "wax"))) /* windows meta files */
			{
				kdDebug() << "PlayList: Check for kaffeine/noatun/m3u/pls/asx playlist\n";

				mrlList.clear();
				playlist = false;
				TQFile file(mrl.url());
				file.open(IO_ReadOnly);

				TQTextStream stream(&file);
				TQString firstLine = stream.readLine();
				TQString secondLine = stream.readLine();
				file.close();

				if (secondLine.contains("kaffeine", false))
				{
					kdDebug() << "PlayList: Try loading kaffeine playlist\n";
					playlist = PlaylistImport::kaffeine(mrl.url(), mrlList);
					if (!playlist)
						continue;
				}
				if (secondLine.contains("noatun", false))
				{
					kdDebug() << "PlayList: Try loading noatun playlist\n";
					playlist = PlaylistImport::noatun(mrl.url(), mrlList);
				}
				if (firstLine.contains("asx", false))
				{
					kdDebug() << "PlayList: Try loading asx playlist\n";
					playlist = PlaylistImport::asx(mrl.url(), mrlList);
				}
				if ( (firstLine.contains("[playlist]", false)) || (ext == "pls") )
				{
					kdDebug() << "PlayList: Try loading pls playlist\n";
					playlist = PlaylistImport::pls(mrl.url(), mrlList);
				}
				if (ext == "m3u")  //identify by extension
				{
					kdDebug() << "PlayList: Try loading m3u playlist\n";
					playlist = PlaylistImport::m3u(mrl.url(), mrlList);
				}
				if (playlist)
				{
					TQValueList<MRL>::ConstIterator end(mrlList.end());
					for (TQValueList<MRL>::ConstIterator it = mrlList.begin(); it != end; ++it)
						after = insertItem(after, *it);
					continue;
				}

			}

			/* check for ram playlist */
			if ( (ext == "ra") || (ext == "rm") || (ext == "ram") || (ext == "lsc") || (ext == "pl") )
			{
				mrlList.clear();
				kdDebug() << "PlayList: Try loading ram playlist\n";
				if (PlaylistImport::ram(mrl, mrlList, mainWidget->parentWidget()))
				{
					TQValueList<MRL>::ConstIterator end(mrlList.end());
					for (TQValueList<MRL>::ConstIterator it = mrlList.begin(); it != end; ++it)
						after = insertItem(after, *it);
					continue;
				}
			}

			/**** a directory ? ****/
			if (mime->name() == "inode/directory")
			{
				kdDebug() << "PlayList: Add Directory: " << mrl.url() << endl;

				TQDir d(mrl.url());
				uint x;

				/* subdirs */
				TQStringList entryList = d.entryList(TQDir::Dirs, TQDir::Name);
				for (x = 0; x < entryList.count(); x++)
				{
					if (entryList[x][0] != '.')
					{
						urls.append(mrl.url() + "/" + entryList[x]);
					}
				}

				/* Media files */
				/* Exclude subtitles because they are examined twice : */
				/* Once for movie and once per subtitle - very annoying*/
				TQString fileFilter = m_fileFilter;
				fileFilter.remove("*.srt",false);
				fileFilter.remove("*.ssa",false);
				fileFilter.remove("*.txt",false);
				fileFilter.remove("*.asc",false);
				fileFilter.remove("*.smi",false);
				fileFilter.remove("*.sub",false);
				entryList = d.entryList(fileFilter, TQDir::Files, TQDir::Name );
				for (x = 0; x < entryList.count(); x++)
				{
					urls.append(mrl.url() + "/" + entryList[x]);
				}

				progress->progressBar()->setTotalSteps(urls.count());
				continue; /* dont add directory to playlist */
			}

			/*** append subtitle files to the movie ***/
			if ((ext == "srt") || (ext == "ssa") || (ext == "txt") ||
			        (ext == "asc") || (ext == "smi") || (ext == "sub"))
			{
				TQStringList movies;
				TQString movieURL;
				TQListViewItemIterator it(m_list);
				while (it.current())
				{
					if (dynamic_cast<PlaylistItem*>(*it)->mime().contains("video"))
						movies << dynamic_cast<PlaylistItem*>(*it)->url();
					++it;
				}
				if (movies.count() == 1)
					movieURL = movies[0];
				else if (movies.count() >= 2)
				{
					MovieChooser *mc = new MovieChooser(movies, mrl.url(), mainWidget);
					if(mc->exec() == TQDialog::Accepted)
						movieURL = mc->getSelection();
					delete mc;
				}
				it = m_list;
				while (it.current())
				{
					if (dynamic_cast<PlaylistItem*>(*it)->url() == movieURL)
					{
						kdDebug() << "PlayList: adding subtitle to movie " << dynamic_cast<PlaylistItem*>(*it)->url() << endl;
						(dynamic_cast<PlaylistItem*>(*it))->addSubtitle(mrl.url());
						break;
					}
					++it;
				}
				continue;
			}

			/*** get meta tags ****/
			if (m_metaOnLoading)
				getMetaInfo(mrl, mime->name());

			/* Get all suported subs in movie dir, clear out
			 * those starting with a different name than the movie,
			 * prompt the user to select a sub
			 */
			if (mime->name().contains("video"))
			{
				kdDebug() << "PlayList: Check for subtitle files" << endl;
				subtitleURL = TQString();
				TQDir *d = new TQDir(mrl.url().section('/',0,-2));
				TQString filename = mrl.url().section('/',-1,-1);
				subs = TQStringList();
				//Do a case insensitive search for subs
				TQStringList dirListing = d->entryList(TQDir::Files|TQDir::NoSymLinks); //cache directory listing
				bool matches = false;
				TQStringList::Iterator end(dirListing.end());
				for(TQStringList::Iterator it = dirListing.begin(); it != end; ++it )
				{
					if(startsWith(*it, filename.section('.',0,-2), false)) //If filenames (without extensions) match
					{
						if( endsWith(*it, ".srt", false) || endsWith(*it, ".ssa", false) ||
						        endsWith(*it, ".txt", false) || endsWith(*it, ".smi", false) ||
						        endsWith(*it, ".asc", false) || endsWith(*it, ".sub", false) )
							matches = true;

						if(matches) {
							subs.append(*it); //This is a subtitle for our movie
						}
						matches = false;
					}
				}

				if((subs.count() > 1)) {
					subs.prepend(i18n("(no subtitles)"));
					subs.append(i18n("Other subtitle..."));
					subtitleURL = TQString();
					SubtitleChooser *sc = new SubtitleChooser(subs, filename, mainWidget);

				THERE:     if(sc->exec() == TQDialog::Accepted)
					{
						if((sc->getSelection() != i18n("(no subtitles)")) && (sc->getSelection() != i18n("Other subtitle...")))
							subtitleURL = d->path()+"/"+sc->getSelection();
						if((sc->getSelection() == i18n("Other subtitle...")))
						{
							subtitleURL = KFileDialog::getOpenURL(d->path(), i18n("*.smi *.srt *.sub *.txt *.ssa *.asc|Subtitle Files\n*.*|All Files"), 0, i18n("Select Subtitle File")).path();
							if(subtitleURL.isEmpty())
							{
								subtitleURL = TQString();
								goto THERE;
							}
							else //The user has selected another sub, so add this to the list
							{
								subs.clear();
								subs.append(subtitleURL);
							}
						}
					}
					delete sc;
					subs.remove(i18n("(no subtitles)"));
					subs.remove(i18n("Other subtitle..."));
				}

				//Add the full path to the subtitle name
				for (unsigned int i = 0; i < subs.size(); i++ )
					if(!subs[i].startsWith(d->path()))
						subs[i] = d->path()+"/"+subs[i];

				mrl.setSubtitleFiles(subs);
				if ( subs.count()==1 )
					subtitleURL = subs[0]; // Use this one.
				if (!subtitleURL.isNull())
				{
					kdDebug() << "PlayList: Use subtitle file: " << subtitleURL << " for: " << mrl.url() << endl;
					mrl.setCurrentSubtitle(subs.findIndex(subtitleURL));
				}
			}
		} /* if localFile() */

		tmp = insertItem(after, mrl);
		if (tmp)
			after = tmp;

		if ( progress->wasCancelled() )
			break;
		progress->progressBar()->setProgress(i+1);
		progress->setLabel(TQString::number(i+1) + " / " + TQString::number(progress->progressBar()->totalSteps()) + " " + i18n("Files"));
		TDEApplication::kApplication()->processEvents();
	}

	delete progress;
	if (m_random) createRandomList();
	updateStatus();
}

void PlayList::add(const TQValueList<MRL>& mrlList, TQListViewItem* after)
{
	TQValueList<MRL>::ConstIterator end(mrlList.end());
	for (TQValueList<MRL>::ConstIterator it = mrlList.begin(); it != end; ++it)
		after = insertItem(after, *it);
	updateStatus();
	if (m_random) createRandomList();
}

void PlayList::slotPlayDirect(TQListViewItem* item)
{
	if (!item) return;

	setCurrentEntry(item);
	emit play(m_currentEntryMRL, this);
}

void PlayList::setEndless(bool e)
{
	m_endless = e;
}

void PlayList::setRandom(bool r)
{
	m_random = r;
	if (m_random) createRandomList();
}

void PlayList::createRandomList()
{
	kdDebug() << "PlayList: Create a random playlist" << endl;
	m_randomList.clear();
	m_currentRandomListEntry = 0;

	TQListViewItem* tmpItem = NULL;
	tmpItem = m_list->firstChild();
	if ( (tmpItem) && (!tmpItem->isVisible()) )
		tmpItem = tmpItem->itemBelow();

	while (tmpItem)
	{
		m_randomList.append(tmpItem);
		tmpItem = tmpItem->itemBelow();
	}

	if (!(m_randomList.count() > 0))
	{
		m_currentRandomListEntry = -1;
		return;
	}

	KRandomSequence r(TDEApplication::random());
	r.randomize(&m_randomList);
}

void PlayList::clearList()
{
	m_list->clear();
	m_randomList.clear();
	m_playTime = 0;
	m_playTimeVisible = 0;
	m_countVisible = 0;
	if (m_searchSelection)
	{
		m_playlistFilter->clear();
		m_searchSelection = false;
	}
	updateStatus();
	m_currentEntry = NULL;
	m_currentRandomListEntry = -1;
}

void PlayList::slotDropEvent(TQDropEvent* dev, TQListViewItem* after)
{
	TQStringList urls ,newurls;

	m_list->setSorting(-1);
	if (TQUriDrag::decodeLocalFiles(dev, urls))
	{
		if (urls.count())
		{
			for (uint i=0; i < urls.count() ;i++)
			{
				//KURL url(TQUriDrag::unicodeUriToUri(urls[i]));
				//newurls << url.path(-1);
				//kdDebug() << "PlayList: Dropped " << url.path() << endl;
				newurls << urls[i];
				kdDebug() << "PlayList: Dropped " << urls[i] << endl;
			}
			add(newurls, after);
		}
		else
		{
			TQUriDrag::decodeToUnicodeUris(dev, urls);
			if (urls.count())
				add(urls, after);
		}
	}
	else
		if (strcmp(dev->format(), "text/x-moz-url") == 0)    /* for mozilla drops */
		{
			TQByteArray data = dev->encodedData("text/plain");
			TQString md(data);
			add(md, after);
		}
}

void PlayList::slotPreDropEvent()
{
	m_list->setSorting(-1);
}

void PlayList::slotSetAlternateColor( const TQColor& col )
{
	m_list->setAlternateBackground( col );
	m_altCol = col;
	m_list->triggerUpdate();
}

void PlayList::useAlternateEncoding(bool useEncoding)
{
	m_useAlternateEncoding = useEncoding;
}

void PlayList::setAlternateEncoding(const TQString& encoding)
{
	m_alternateEncoding = encoding;
}


void PlayList::getMetaInfo(MRL& mrl, const TQString& mimeName)
{
	KFileMetaInfo* metaInfo = NULL;
	KFileMetaInfoGroup metaGroup;
	uint m, n;

	metaInfo = new KFileMetaInfo(mrl.url(), mimeName);
	TQStringList groups = metaInfo->groups();
	TQStringList keys;
	TQString title;
	TQString artist;
	TQString album;

	TQTextCodec *altCodec;
	TQTextCodec *CodecUtf8;

	altCodec = TQTextCodec::codecForName(m_alternateEncoding.ascii());
	CodecUtf8 = TQTextCodec::codecForName("UTF-8");
	//kdDebug() << "playlist: locale " << Codec->name << " index: " << m_alternateEncoding << endl;

	for (m = 0; m < groups.count(); m++)
	{
		//kdDebug() << "Metainfo-Group: " << groups[m] << endl;
		metaGroup = metaInfo->group(groups[m]);
		keys = metaGroup.keys();
		for (n = 0; n < keys.count(); n++)
		{
			//kdDebug() << "Metainfo-Key: " << keys[n] << endl;
			if (keys[n] == "Length")
			{
				mrl.setLength(TQTime().addSecs(metaGroup.item(keys[n]).value().toUInt()));
			}

			if (keys[n] == "Title")
			{
				title = metaGroup.item(keys[n]).value().toString().simplifyWhiteSpace();
				if ((!title.isEmpty()) && (title.contains(TQRegExp("\\w")) > 2) && (title.left(5).lower() != "track"))
				{
					if ((m_useAlternateEncoding) && (CodecUtf8->heuristicContentMatch(title.ascii(), title.length()) < 0))
					{
						mrl.setTitle(altCodec->toUnicode(title.ascii()));
						//kdDebug() << "playlist: Convert, locale name: " << altCodec->name() << title << endl;
					}
					else
					{
						mrl.setTitle(title);
						//kdDebug() << "playlist: non Convert, locale name: " << CodecUtf8->name() << title << endl;
					}
				}
			}

			if (keys[n] == "Artist")
			{
				artist = (metaGroup.item(keys[n]).value().toString().simplifyWhiteSpace());
				if (!artist.isEmpty())
				{
					if ((m_useAlternateEncoding) && (CodecUtf8->heuristicContentMatch(artist.ascii(),artist.length()) < 0 ))
					{
						mrl.setArtist(altCodec->toUnicode(artist.ascii()));
					}
					else
					{
						mrl.setArtist(artist);
					}
				}
			}

			if (keys[n] == "Album")
			{
				album = (metaGroup.item(keys[n]).value().toString().simplifyWhiteSpace());
				if (!album.isEmpty())
				{
					if ((m_useAlternateEncoding) && (CodecUtf8->heuristicContentMatch(album.ascii(),album.length()) < 0 ))
					{
						mrl.setAlbum(altCodec->toUnicode(album.ascii()));
					}
					else
					{
						mrl.setAlbum(album);
					}
				}
			}

			if (keys[n] == "Tracknumber")
				mrl.setTrack(metaGroup.item(keys[n]).value().toString().simplifyWhiteSpace());
			if (keys[n] == "Date")
				mrl.setYear(metaGroup.item(keys[n]).value().toString().simplifyWhiteSpace());
			if (keys[n] == "Genre")
				mrl.setGenre(metaGroup.item(keys[n]).value().toString().simplifyWhiteSpace());
		}
	}

	delete metaInfo;
}

void PlayList::mergeMeta(const MRL& mrl)
{
	if (!m_currentEntry) return;
	PlaylistItem* tmp = dynamic_cast<PlaylistItem*>(m_currentEntry);
	bool addTime = (tmp->length() == TQString("00:00:00"));
	if ((tmp) && (tmp->url() == mrl.url()))
	{
		tmp->setTitle(mrl.title());
		tmp->setArtist(mrl.artist());
		tmp->setAlbum(mrl.album());
		tmp->setTrack(mrl.track());
		tmp->setYear(mrl.year());
		tmp->setGenre(mrl.genre());
		tmp->setLength(mrl.length().toString("h:mm:ss"));
		tmp->setCurrentSubtitle(mrl.currentSubtitle());
		tmp->setSubtitles(mrl.subtitleFiles());
	}
	if (addTime)
	{
		if (tmp->length().contains(':'));
		{
			m_playTime += timeStringToMs(tmp->length());
			if (tmp->isVisible())
				m_playTimeVisible += timeStringToMs(tmp->length());

			updateStatus();
		}
	}

	roller->setTitle( mrl );
	setCover( mrl.artist().stripWhiteSpace(), mrl.album().stripWhiteSpace() );
}

GalleryDialog::GalleryDialog( TQWidget *parent, GoogleFetcher *goog )
	: KDialogBase( parent, TQString(i18n("Gallery")).latin1(), true, TQString(), Ok, NoDefault, true )
{
	google = goog;
	hbox = new TQHBox(this);
	imageFrame = new TQFrame( hbox );
	imageFrame->setFixedSize(500,500);
	setMainWidget(hbox);
	connect( &next, TQ_SIGNAL(timeout()), this, TQ_SLOT(slotNext()) );
	next.start(1000,true);
}

void GalleryDialog::slotNext()
{
	TQPixmap pix;
	bool end;

	actionButton(Ok)->setEnabled(false);
loop:
	TQImage img = google->galleryNext( end );
	if ( end ) {
		slotOk();
		return;
	}
	if ( !img.isNull() ) {
		if ( img.width()>img.height() )
			imageFrame->setFixedSize(500, 500*img.height()/img.width());
		else
			imageFrame->setFixedSize(500*img.width()/img.height(), 500);
		img = img.smoothScale(imageFrame->width(),imageFrame->height());
		pix.convertFromImage( img );
		imageFrame->setPaletteBackgroundPixmap( pix );
	}
	else
		goto loop;

	actionButton(Ok)->setEnabled(true);
	next.start(5000,true);
}

void GalleryDialog::slotOk()
{
	if ( next.isActive() )
		next.stop();
	hide();
}

void PlayList::showGallery()
{
	if ( google )
		return;
	TQString s = getCurrent().artist().stripWhiteSpace();
	if ( s.isEmpty() )
		return;
	google = new GoogleFetcher( s, "", true );
	GalleryDialog dlg( 0, google );
	dlg.exec();
	delete google;
	google = NULL;
}

void PlayList::setCover( TQString s1, TQString s2, bool forceFetch )
{
	if ( s1.isEmpty() || s2.isEmpty() ) {
		coverFrame->setCoverPixmap( "" );
		return;
	}
	TQString s = locateLocal("appdata", "");
	TQImage img;
	TQPixmap pix;
	TQString fname = s1+"_"+s2;
	fname = fname.replace( TQChar( '/' ), "_" );
	fname = fname.upper();
	fname = s+"covers/"+fname;
	if ( !forceFetch && TQFile( fname ).exists() )
		coverFrame->setCoverPixmap( fname );
	else {
		if ( !forceFetch )
			coverFrame->setCoverPixmap( "" );
		if ( google )
			return;
		if ( m_cover || forceFetch ) {
			google = new GoogleFetcher( s1, s2 );
			pix = google->pixmap( forceFetch );
			delete google;
			google = NULL;
		}
		if ( !TQDir( s+"covers" ).exists() )
			TQDir().mkdir( s+"covers" );
		if ( !pix.isNull() ) {
			img = pix.convertToImage();
			img.save( fname, coverImageFormat.latin1() );
			MRL mrl = getCurrent();
			if ( s1==mrl.artist().stripWhiteSpace() && s2==mrl.album().stripWhiteSpace() )
				coverFrame->setCoverPixmap( fname );
		}
		else if ( !forceFetch && m_cover ) {
			TQString path = locate("appdata", "nocover.png");
			if ( !path )
				path = locate("data", "kaffeine/nocover.png");
			TDEIO::file_copy( KURL::fromPathOrURL( path ), KURL::fromPathOrURL( fname ), -1, true );
		}
	}
}

void PlayList::chooseCurrentCover()
{
	MRL mrl = getCurrent();
	setCover( mrl.artist().stripWhiteSpace(), mrl.album().stripWhiteSpace(), true );
}

/************ sort playlist ******************/

void PlayList::slotSort(int section)
{
	m_list->setSorting(section, m_sortAscending);
	m_list->sort();
	m_sortAscending = !m_sortAscending;
}


/***  remove items ***/

void PlayList::slotRemoveSelected()
{
	TQPtrList<TQListViewItem> selected;

	if (m_currentEntry)
		if (m_currentEntry->isSelected())
		{
			m_currentEntry = NULL;
			m_currentRandomListEntry = -1;
		}

	selected = m_list->selectedItems();
	PlaylistItem* item = NULL;

	for(uint i = 0; i<selected.count(); i++)
	{
		// kdDebug() << "Remove " << selected.at(i)->text(TITLE_COLUMN) << "\n";
		item = dynamic_cast<PlaylistItem *>(selected.at(i));
		if (item->length().contains(':'))
		{
			m_playTime -= timeStringToMs(item->length());
			m_playTimeVisible -= timeStringToMs(item->length());
		}

		m_countVisible--;
		delete selected.at(i);
	}

	if (m_random) createRandomList();
	updateStatus();
}

void PlayList::updateStatus()
{
	TQString status;
	if (isQueueMode())
	{
		TQTime total;
		TQValueList<MRL>::ConstIterator end(m_queue.end());
		for (TQValueList<MRL>::ConstIterator it = m_queue.begin(); it != end; ++it)
			total = total.addSecs(TQTime().secsTo((*it).length()));
		status = i18n("Queue: %1 Entries, Playtime: %2").arg(m_queue.count()).arg(total.toString("h:mm:ss"));
	}
	else
	{
		//status = i18n("Entries: %1, Playtime: %2  (Total: %3, %4)").arg(TQString::number(m_countVisible)).arg(msToTimeString(m_playTimeVisible)).arg(TQString::number(m_list->childCount())).arg(msToTimeString(m_playTime));


		status = i18n("Entries: %1, Playtime: %2").arg(TQString::number(m_countVisible)).arg(msToTimeString(m_playTimeVisible));
	}
	emit statusBarMessage(status);
}

void PlayList::slotNewList()
{
	m_list->setSorting(-1);
	saveCurrentPlaylist();
	m_playlistSelector->insertItem(i18n("Playlist") + TQString::number(m_nextPlaylistNumber), 0);
	m_nextPlaylistNumber++;
	m_playlistSelector->setCurrentItem(0);
	m_currentPlaylist = 0;
	clearList();
}

void PlayList::setPlaylist(const TQString& name, bool clear)
{
	saveCurrentPlaylist();
	if (clear)
		clearList();
	int index = 0;
	if (m_playlistSelector->listBox()->findItem(name))
		index = m_playlistSelector->listBox()->index(m_playlistSelector->listBox()->findItem(name));
	else
		m_playlistSelector->insertItem(name, 0);
	m_playlistSelector->setCurrentItem(index);
	m_currentPlaylist = index;
}

void PlayList::nextPlaylist()
{
	int nextPlaylist = m_playlistSelector->currentItem();
	TQString pl = NULL;
	do
	{
		nextPlaylist++;
		if (nextPlaylist == m_playlistSelector->count())
			nextPlaylist = 0;
		pl = m_playlistSelector->text(nextPlaylist);
	}
	while (nextPlaylist != m_playlistSelector->currentItem());

	saveCurrentPlaylist();
	clearList();
	m_playlistSelector->setCurrentItem(nextPlaylist);
	m_currentPlaylist = nextPlaylist;
	add(m_playlistDirectory + pl + ".kaffeine", NULL);
	if (mainWidget->parentWidget())
		mainWidget->parentWidget()->setFocus();
}

void PlayList::slotPlaylistActivated(int index)
{
	kdDebug() << "PlayList: Switch to playlist: " << m_playlistSelector->text(index) << endl;
	TQString pl = m_playlistSelector->text(index);

	saveCurrentPlaylist();
	clearList();
	m_currentPlaylist = index;
	add(m_playlistDirectory + pl + ".kaffeine", NULL);
	if (mainWidget->parentWidget())
		mainWidget->parentWidget()->setFocus();
	/*  if (!isQueueMode())
	  {
	    getCurrent();
	    emit signalPlay(m_currentEntryMRL);
	  }  */
}

void PlayList::slotNewPlaylistName(const TQString& text)
{
	if ((text.isEmpty()) || (text == m_playlistSelector->text(m_currentPlaylist)))
		return;
	if (m_playlistSelector->listBox()->findItem(text))
	{
		kdDebug() << "PlayList: Name still exists!" << endl;
		return;
	}
	TQString oldPl = m_playlistDirectory + m_playlistSelector->text(m_currentPlaylist) + ".kaffeine";
	kdDebug() << "Playlist: removing file: " << oldPl << endl;
	if (!TDEIO::NetAccess::del(oldPl, mainWidget))
		kdError() << "Playlist: " << TDEIO::NetAccess::lastErrorString() << endl;

	kdDebug() << "PlayList: Set playlist name to: " << text << endl;
	m_playlistSelector->changeItem(text, m_currentPlaylist);
	saveCurrentPlaylist();
	if (mainWidget->parentWidget())
		mainWidget->parentWidget()->setFocus();
}

TQString PlayList::queryCurrentPlaylist()
{
	TQString pl = m_playlistSelector->text(m_currentPlaylist);
	return (m_playlistDirectory + pl + ".kaffeine");
}

void PlayList::saveCurrentPlaylist()
{
	TQString pl = m_playlistSelector->text(m_currentPlaylist);
	savePlaylist(m_playlistDirectory + pl + ".kaffeine");
}

void PlayList::removeCurrentPlaylist()
{
	int code = KMessageBox::warningContinueCancel(0, i18n("Remove '%1' from list and from disk?").arg(m_playlistSelector->text(m_currentPlaylist)),TQString(),KStdGuiItem::del());
	if (code == KMessageBox::Continue)
	{
		TQString pl = m_playlistDirectory + m_playlistSelector->text(m_currentPlaylist) + ".kaffeine";
		if (!TDEIO::NetAccess::del(pl, mainWidget))
			kdError() << "Playlist: " << TDEIO::NetAccess::lastErrorString() << endl;

		m_playlistSelector->removeItem(m_currentPlaylist);
		m_currentPlaylist = m_playlistSelector->currentItem();
		clearList();
		add(m_playlistDirectory + m_playlistSelector->text(m_currentPlaylist) + ".kaffeine", NULL);
	}
}

void PlayList::loadPlaylist(const TQString& pl)
{
	saveCurrentPlaylist();
	TQString plName = KURL(pl).fileName();
	plName = plName.remove(".kaffeine", false);
	if (m_playlistSelector->listBox()->findItem(plName))
	{
		TQString plNewName = NULL;
		while (true)
		{
			bool ok;
			plNewName = TQInputDialog::getText(i18n("Playlist Name Already Exists"),
			                                  i18n("Enter different playlist name:"), TQLineEdit::Normal, plName, &ok);
			if ((ok) && (!plNewName.isEmpty()))
			{
				if (m_playlistSelector->listBox()->findItem(plNewName))
					continue;
				else
					break;
			}
			else
			{
				kdDebug() << "Playlist: Import aborted, playlist not added" << endl;
				return;
			}
		}
		plName = plNewName;
	}
	m_playlistSelector->insertItem(plName, 0);
	m_playlistSelector->setCurrentItem(0);
	m_currentPlaylist = 0;
	clearList();
	add(pl, NULL);
}

/******************************************
 *         save xml playlist
 ******************************************/

void PlayList::savePlaylist(const TQString& pl)
{
	TQDomDocument doc("playlist");
	doc.setContent(TQString("<!DOCTYPE XMLPlaylist>"));
	TQDomElement root = doc.createElement("playlist");
	root.setAttribute("client", "kaffeine");
	doc.appendChild(root);

	TQDomElement entry;
	PlaylistItem * tmp = NULL;

	TQListViewItemIterator it(m_list);
	while (it.current())
	{
		tmp = dynamic_cast<PlaylistItem *>(it.current());

		entry = doc.createElement("entry");

		entry.setAttribute("title", tmp->title());
		entry.setAttribute("artist", tmp->artist());
		entry.setAttribute("album", tmp->album());
		entry.setAttribute("track", tmp->track());
		entry.setAttribute("year", tmp->year());
		entry.setAttribute("genre", tmp->genre());
		entry.setAttribute("url", tmp->url());
		entry.setAttribute("mime", tmp->mime());
		entry.setAttribute("length", tmp->length());

		if(!(tmp->subtitles().isEmpty()))
		{
			TQString subList;
			for(unsigned int i=0; i<tmp->subtitles().count(); i++)
				subList += tmp->subtitles()[i] + "&";

			entry.setAttribute("subs", subList);
		}
		entry.setAttribute("currentSub", TQString::number(tmp->currentSubtitle()));
		root.appendChild(entry);

		++it;
	}

	TQFile file(pl);
	if (!file.open(IO_WriteOnly)) return;
	TQTextStream stream(&file);
	stream.setEncoding(TQTextStream::UnicodeUTF8);

	stream << doc.toString();

	file.close();
	m_list->setCleared(false);
}

/**********************/

void PlayList::exportM3UPlaylist(const TQString& pl)
{
	PlaylistItem * tmp = NULL;

	TQListViewItemIterator it(m_list);

	int length = -1;
	TQString m3uList = "#EXTM3U\n";

	while (it.current())
	{
		tmp = dynamic_cast<PlaylistItem *>(it.current());

		length = timeStringToMs(tmp->length()) / 1000;
		if ( length == 0 )
			length = -1;

		m3uList.append("#EXTINF:" + TQString::number(length) + "," + tmp->title());
		if (tmp->artist().isEmpty() )
			m3uList.append("\n");
		else
			m3uList.append(" - " + tmp->artist() + "\n");
		m3uList.append(tmp->url() + "\n");
		++it;
	}

	TQFile file(pl);
	if (!file.open(IO_WriteOnly)) return;
	TQTextStream stream(&file);
	stream.setEncoding(TQTextStream::UnicodeUTF8);

	stream << m3uList;

	file.close();
}

void PlayList::exportPLSPlaylist(const TQString& pl)
{
	PlaylistItem * tmp = NULL;

	TQListViewItemIterator it(m_list);

	int counter = 0;
	int length = -1;

	TQString plsList = "[playlist]\n";

	while (it.current())
	{
		tmp = dynamic_cast<PlaylistItem *>(it.current());
		++counter;

		length = timeStringToMs(tmp->length()) / 1000;

		if ( length == 0 ) {
			length = -1;
		}

		plsList.append("File" + TQString::number(counter) + "=" + tmp->url() + "\n");
		plsList.append("Title" + TQString::number(counter) + "=" + tmp->title());
		if (tmp->artist().isEmpty() )
			plsList.append("\n");
		else
			plsList.append(" - " + tmp->artist() + "\n");
		plsList.append("Length" + TQString::number(counter) + "=" + TQString::number(length) + "\n");
		++it;

	}

	plsList.append("NumberOfEntries=" + TQString::number(counter) + "\n");
	plsList.append("Version=2");

	TQFile file(pl);
	if (!file.open(IO_WriteOnly)) return;
	TQTextStream stream(&file);
	stream.setEncoding(TQTextStream::UnicodeUTF8);

	stream << plsList;

	file.close();
}

void PlayList::resetSearch()
{
	m_playlistFilter->clear();
	slotFindText( "" );
}

void PlayList::slotFindText(const TQString& text)
{
	if (text == i18n("Filter")) return;

	TQListViewItemIterator it(m_list);
	m_playTimeVisible = 0;
	m_countVisible = 0;
	PlaylistItem* tmp = NULL;
	while ( it.current() )
	{
		tmp = dynamic_cast<PlaylistItem *>(it.current());
		if (text.isEmpty() || tmp->title().contains(text, false) || tmp->url().contains(text, false)
		        || tmp->artist().contains(text, false) || tmp->album().contains(text, false) )
		{
			tmp->setVisible(true);
			if (tmp->length().contains(':'))
				m_playTimeVisible += timeStringToMs(tmp->length());

			m_countVisible++;
		}
		else
		{
			tmp->setVisible(false);
			if (tmp == m_currentEntry)
			{
				tmp->setPixmap(TITLE_COLUMN, TQPixmap());
				m_currentEntry = NULL;
				m_currentRandomListEntry = -1;
			}
		}
		++it;
	}

	if (text.isEmpty())
		m_searchSelection = false;
	else
		m_searchSelection = true;

	if (m_random) createRandomList();
	updateStatus();
}


/***************** cut/copy/paste *************************/

void PlayList::slotCut()
{
	slotCopy();
	slotRemoveSelected();
}

void PlayList::slotPaste()
{
	TQPtrList<TQListViewItem> selected;
	selected = m_list->selectedItems();
	TQListViewItem* lastSelected = NULL;
	if (selected.count())
		lastSelected = selected.at(selected.count() - 1);
	else
		lastSelected = m_list->lastItem();

	TQStrList list;

	if (TQUriDrag::decode(TQApplication::clipboard()->data(), list))
	{
		TQStringList urls;
		for (TQStrListIterator it(list); *it; ++it)
			urls.append(TQUriDrag::uriToUnicodeUri(*it));
		add(urls, lastSelected);
		return;
	}
	/** try to decode as text **/
	TQString text;
	if (TQTextDrag::decode(TQApplication::clipboard()->data(), text))
	{
		add(text, lastSelected);
	}
}

void PlayList::slotCopy()
{
	TQPtrList<TQListViewItem> selected;
	selected = m_list->selectedItems();

	TQStrList urlList;

	for (uint i=0; i<selected.count(); i++)
	{
		urlList.append(TQUriDrag::unicodeUriToUri(dynamic_cast<PlaylistItem *>(selected.at(i))->url()));
	}

	TQApplication::clipboard()->setData(new TQUriDrag(urlList));
}

void PlayList::slotSelectAll()
{
	TQListViewItemIterator it(m_list);
	while (it.current())
	{
		if ((*it)->isVisible())
			m_list->setSelected(*it, true);
		++it;
	}
}

void PlayList::slotPlaylistFromSelected()
{
	TQPtrList<TQListViewItem> selected;
	selected = m_list->selectedItems();

	TQValueList<MRL> mrlList;

	for (uint i=0; i<selected.count(); i++)
	{
		mrlList.append(dynamic_cast<PlaylistItem *>(selected.at(i))->toMRL());
	}

	if (mrlList.count())
	{
		slotNewList();
		add(mrlList, NULL);
	}
}

void PlayList::slotAddToQueue(MRL mrl)
{
	m_queue.append(mrl);
	updateStatus();
}

/**** helper ****/

TQString PlayList::msToTimeString(int msec)
{
	/*
	TQTime t;
	t = t.addMSecs(msec);
	return t.toString("h:mm:ss");
	*/
	/* can be >24h */
	int hours;
	int min;
	int sec;
	int my_msec=msec;
	TQString tmp;
	TQString t;

	msec = msec/1000;  //sec
	hours = msec/3600;
	my_msec -= hours*3600*1000;
	t = t.setNum(hours);
	t.append(":");

	msec = msec - (hours*3600);
	min = msec / 60;
	my_msec -= min*60*1000;
	tmp = tmp.setNum(min);
	tmp = tmp.rightJustify(2, '0');
	t.append(tmp);
	t.append(":");

	sec = msec - (min*60);
	my_msec -= sec*1000;
	if(my_msec > 500)
		sec++;
	tmp = tmp.setNum(sec);
	tmp = tmp.rightJustify(2, '0');
	t.append(tmp);

	return t;
}

int PlayList::timeStringToMs(const TQString& timeString)
{
	int sec = 0;
	TQStringList tokens = TQStringList::split(':',timeString);

	bool ok = false;
	sec += tokens[0].toInt(&ok)*3600; //hours
	if (!ok)
		return 0;
	sec += tokens[1].toInt(&ok)*60; //minutes
	if (!ok)
		return 0;
	sec += tokens[2].toInt(&ok); //secs

	if (ok)
		return sec*1000; //return millisecs
	else
		return 0;
}

bool PlayList::endsWith(TQString s1, TQString s2, bool caseSensitive )
{
	if ( s1.isNull() || s2.isNull() )
		return false;
	int startPos = s1.length() - s2.length();

	for (unsigned int i = 0; i < s2.length(); i++ )
	{
		if(caseSensitive)
		{
			if ( s1[startPos + i] != s2[i] )
				return false;
		}
		else
		{
			if ( s1[startPos + i].lower() != s2[i].lower() )
				return false;
		}
	}

	return true;
}

bool PlayList::startsWith(TQString s1, TQString s2, bool caseSensitive )
{
	if ( s1.isNull() || s2.isNull() )
		return false;

	if(s2.length() > s1.length())
		return false;

	for (unsigned int i = 0; i < s2.length(); i++ )
	{
		if(caseSensitive)
		{
			if ( s1[i] != s2[i] )
				return false;
		}
		else
		{
			if ( s1[i].lower() != s2[i].lower() )
				return false;
		}
	}

	return true;
}

SubtitleChooser::SubtitleChooser(TQStringList values, TQString filename,TQWidget *parent, const char * name) :
		KDialogBase(parent,name,true,i18n("Select Subtitle"), Ok|Cancel, Ok, true)
{
	TQVBox *page = makeVBoxMainWidget();
	TQLabel *label =  new TQLabel(page);
	label->setText("<qt>" + i18n("Media file:") + " <b>" + filename + "</b></qt>");
	table = new TQListBox(page);
	this->setMinimumSize(300,200);

	table->setFocus();
	table->insertStringList(values);
	table->setSelected(0, true);
}

SubtitleChooser::~SubtitleChooser(){}

TQString SubtitleChooser::getSelection()
{
	return table->selectedItem()->text();
}

MovieChooser::MovieChooser(TQStringList values, TQString filename,TQWidget *parent, const char * name) :
		KDialogBase(parent,name,true,i18n("Select Movie"), Ok|Cancel, Ok, true)
{
	TQVBox *page = makeVBoxMainWidget();
	TQLabel *label =  new TQLabel(page);
	label->setText("<qt> " + i18n("Subtitle file:") + " <b>" + filename + "</b></qt>");
	table = new TQListBox(page);
	this->setMinimumSize(450,200);

	table->setFocus();
	table->insertStringList(values);
	table->setSelected(0, true);
}

MovieChooser::~MovieChooser(){}

TQString MovieChooser::getSelection()
{
	return table->selectedItem()->text();
}
