RetroShare/plugins/smplayer_plugin/playlist.cpp
defnax 87344de7d4 added for plugins own dir
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@1850 b45a01b8-16f6-495d-af2f-9b41ad6348cc
2009-11-28 14:21:11 +00:00

1327 lines
33 KiB
C++

/* smplayer, GUI front-end for mplayer.
Copyright (C) 2006-2008 Ricardo Villalba <rvm@escomposlinux.org>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "playlist.h"
#include <QToolBar>
#include <QFile>
#include <QTextStream>
#include <QDir>
#include <QFileInfo>
#include <QMessageBox>
#include <QPushButton>
#include <QRegExp>
#include <QMenu>
#include <QDateTime>
#include <QSettings>
#include <QInputDialog>
#include <QToolButton>
#include <QTimer>
#include <QVBoxLayout>
#include <QUrl>
#include <QDragEnterEvent>
#include <QDropEvent>
#include <QHeaderView>
#include <QTextCodec>
#include <QApplication>
#include "mytablewidget.h"
#include "myaction.h"
#include "filedialog.h"
#include "helper.h"
#include "images.h"
#include "preferences.h"
#include "version.h"
#include "global.h"
#include "core.h"
#include "extensions.h"
#include "guiconfig.h"
#include "playlistpreferences.h"
#include <stdlib.h>
#if USE_INFOPROVIDER
#include "infoprovider.h"
#endif
#define DRAG_ITEMS 0
#define COL_PLAY 0
#define COL_NAME 1
#define COL_TIME 2
using namespace Global;
Playlist::Playlist( Core *c, QWidget * parent, Qt::WindowFlags f)
: QWidget(parent,f)
{
save_playlist_in_config = true;
recursive_add_directory = false;
#ifdef Q_OS_WIN
automatically_get_info = false;
#else
automatically_get_info = true;
#endif
play_files_from_start = true;
modified = false;
core = c;
playlist_path = "";
latest_dir = "";
createTable();
createActions();
createToolbar();
connect( core, SIGNAL(mediaFinished()), this, SLOT(playNext()), Qt::QueuedConnection );
connect( core, SIGNAL(mediaLoaded()), this, SLOT(getMediaInfo()) );
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget( listView );
layout->addWidget( toolbar );
setLayout(layout);
clear();
retranslateStrings();
#if !DOCK_PLAYLIST
setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Expanding );
adjustSize();
#else
//setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Expanding );
//setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred );
#endif
setAcceptDrops(true);
setAttribute(Qt::WA_NoMousePropagation);
// Random seed
QTime t;
t.start();
srand( t.hour() * 3600 + t.minute() * 60 + t.second() );
loadSettings();
// Save config every 5 minutes.
save_timer = new QTimer(this);
connect( save_timer, SIGNAL(timeout()), this, SLOT(maybeSaveSettings()) );
save_timer->start( 5 * 60000 );
}
Playlist::~Playlist() {
saveSettings();
}
void Playlist::setModified(bool mod) {
qDebug("Playlist::setModified: %d", mod);
modified = mod;
emit modifiedChanged(modified);
}
void Playlist::createTable() {
listView = new MyTableWidget( 0, COL_TIME + 1, this);
listView->setObjectName("playlist_table");
listView->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
listView->setSelectionBehavior(QAbstractItemView::SelectRows);
listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
listView->setContextMenuPolicy( Qt::CustomContextMenu );
listView->setShowGrid(false);
listView->setSortingEnabled(false);
//listView->setAlternatingRowColors(true);
listView->horizontalHeader()->setResizeMode(QHeaderView::Interactive);
listView->horizontalHeader()->setResizeMode(COL_NAME, QHeaderView::Stretch);
/*
listView->horizontalHeader()->setResizeMode(COL_TIME, QHeaderView::ResizeToContents);
listView->horizontalHeader()->setResizeMode(COL_PLAY, QHeaderView::ResizeToContents);
*/
listView->setIconSize( Images::icon("ok_small").size() );
#if DRAG_ITEMS
listView->setSelectionMode(QAbstractItemView::SingleSelection);
listView->setDragEnabled(true);
listView->setAcceptDrops(true);
listView->setDropIndicatorShown(true);
listView->setDragDropMode(QAbstractItemView::InternalMove);
#endif
connect( listView, SIGNAL(cellActivated(int,int)),
this, SLOT(itemDoubleClicked(int)) );
}
void Playlist::createActions() {
openAct = new MyAction(this, "pl_open", false);
connect( openAct, SIGNAL(triggered()), this, SLOT(load()) );
saveAct = new MyAction(this, "pl_save", false);
connect( saveAct, SIGNAL(triggered()), this, SLOT(save()) );
playAct = new MyAction(this, "pl_play", false);
connect( playAct, SIGNAL(triggered()), this, SLOT(playCurrent()) );
nextAct = new MyAction(Qt::Key_N /*Qt::Key_Greater*/, this, "pl_next", false);
connect( nextAct, SIGNAL(triggered()), this, SLOT(playNext()) );
prevAct = new MyAction(Qt::Key_P /*Qt::Key_Less*/, this, "pl_prev", false);
connect( prevAct, SIGNAL(triggered()), this, SLOT(playPrev()) );
moveUpAct = new MyAction(this, "pl_move_up", false);
connect( moveUpAct, SIGNAL(triggered()), this, SLOT(upItem()) );
moveDownAct = new MyAction(this, "pl_move_down", false);
connect( moveDownAct, SIGNAL(triggered()), this, SLOT(downItem()) );
repeatAct = new MyAction(this, "pl_repeat", false);
repeatAct->setCheckable(true);
shuffleAct = new MyAction(this, "pl_shuffle", false);
shuffleAct->setCheckable(true);
preferencesAct = new MyAction(this, "pl_preferences", false);
connect( preferencesAct, SIGNAL(triggered()), this, SLOT(editPreferences()) );
// Add actions
addCurrentAct = new MyAction(this, "pl_add_current", false);
connect( addCurrentAct, SIGNAL(triggered()), this, SLOT(addCurrentFile()) );
addFilesAct = new MyAction(this, "pl_add_files", false);
connect( addFilesAct, SIGNAL(triggered()), this, SLOT(addFiles()) );
addDirectoryAct = new MyAction(this, "pl_add_directory", false);
connect( addDirectoryAct, SIGNAL(triggered()), this, SLOT(addDirectory()) );
// Remove actions
removeSelectedAct = new MyAction(this, "pl_remove_selected", false);
connect( removeSelectedAct, SIGNAL(triggered()), this, SLOT(removeSelected()) );
removeAllAct = new MyAction(this, "pl_remove_all", false);
connect( removeAllAct, SIGNAL(triggered()), this, SLOT(removeAll()) );
// Edit
editAct = new MyAction(this, "pl_edit", false);
connect( editAct, SIGNAL(triggered()), this, SLOT(editCurrentItem()) );
}
void Playlist::createToolbar() {
toolbar = new QToolBar(this);
toolbar->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum );
toolbar->addAction(openAct);
toolbar->addAction(saveAct);;
toolbar->addSeparator();
add_menu = new QMenu( this );
add_menu->addAction(addCurrentAct);
add_menu->addAction(addFilesAct );
add_menu->addAction(addDirectoryAct);
add_button = new QToolButton( this );
add_button->setMenu( add_menu );
add_button->setPopupMode(QToolButton::InstantPopup);
remove_menu = new QMenu( this );
remove_menu->addAction(removeSelectedAct);
remove_menu->addAction(removeAllAct);
remove_button = new QToolButton( this );
remove_button->setMenu( remove_menu );
remove_button->setPopupMode(QToolButton::InstantPopup);
toolbar->addWidget(add_button);
toolbar->addWidget(remove_button);
toolbar->addSeparator();
toolbar->addAction(playAct);
toolbar->addSeparator();
toolbar->addAction(prevAct);
toolbar->addAction(nextAct);
toolbar->addSeparator();
toolbar->addAction(repeatAct);
toolbar->addAction(shuffleAct);
toolbar->addSeparator();
toolbar->addAction(moveUpAct);
toolbar->addAction(moveDownAct);
toolbar->addSeparator();
toolbar->addAction(preferencesAct);
// Popup menu
popup = new QMenu(this);
popup->addAction(playAct);
popup->addAction(removeSelectedAct);
popup->addAction(editAct);
connect( listView, SIGNAL(customContextMenuRequested(const QPoint &)),
this, SLOT(showPopup(const QPoint &)) );
}
void Playlist::retranslateStrings() {
listView->setHorizontalHeaderLabels( QStringList() << " " <<
tr("Name") << tr("Length") );
openAct->change( Images::icon("open"), tr("&Load") );
saveAct->change( Images::icon("save"), tr("&Save") );
playAct->change( tr("&Play") );
nextAct->change( tr("&Next") );
prevAct->change( tr("Pre&vious") );
if (qApp->isLeftToRight()) {
playAct->setIcon( Images::icon("play") );
nextAct->setIcon( Images::icon("next") );
prevAct->setIcon( Images::icon("previous") );
} else {
playAct->setIcon( Images::flippedIcon("play") );
nextAct->setIcon( Images::flippedIcon("next") );
prevAct->setIcon( Images::flippedIcon("previous") );
}
moveUpAct->change( Images::icon("up"), tr("Move &up") );
moveDownAct->change( Images::icon("down"), tr("Move &down") );
repeatAct->change( Images::icon("repeat"), tr("&Repeat") );
shuffleAct->change( Images::icon("shuffle"), tr("S&huffle") );
preferencesAct->change( Images::icon("prefs"), tr("Preferences") );
// Add actions
addCurrentAct->change( tr("Add &current file") );
addFilesAct->change( tr("Add &file(s)") );
addDirectoryAct->change( tr("Add &directory") );
// Remove actions
removeSelectedAct->change( tr("Remove &selected") );
removeAllAct->change( tr("Remove &all") );
// Edit
editAct->change( tr("&Edit") );
// Tool buttons
add_button->setIcon( Images::icon("plus") );
add_button->setToolTip( tr("Add...") );
remove_button->setIcon( Images::icon("minus") );
remove_button->setToolTip( tr("Remove...") );
// Icon
setWindowIcon( Images::icon("logo", 64) );
setWindowTitle( tr( "SMPlayer - Playlist" ) );
}
void Playlist::list() {
qDebug("Playlist::list");
PlaylistItemList::iterator it;
for ( it = pl.begin(); it != pl.end(); ++it ) {
qDebug( "filename: '%s', name: '%s' duration: %f",
(*it).filename().toUtf8().data(), (*it).name().toUtf8().data(),
(*it).duration() );
}
}
void Playlist::updateView() {
qDebug("Playlist::updateView");
listView->setRowCount( pl.count() );
//QString number;
QString name;
QString time;
for (int n=0; n < pl.count(); n++) {
name = pl[n].name();
if (name.isEmpty()) name = pl[n].filename();
time = Helper::formatTime( (int) pl[n].duration() );
//listView->setText(n, COL_POS, number);
qDebug("Playlist::updateView: name: '%s'", name.toUtf8().data());
listView->setText(n, COL_NAME, name);
listView->setText(n, COL_TIME, time);
if (pl[n].played()) {
listView->setIcon(n, COL_PLAY, Images::icon("ok_small") );
} else {
listView->setIcon(n, COL_PLAY, QPixmap() );
}
}
//listView->resizeColumnsToContents();
listView->resizeColumnToContents(COL_PLAY);
listView->resizeColumnToContents(COL_TIME);
setCurrentItem(current_item);
//adjustSize();
}
void Playlist::setCurrentItem(int current) {
QIcon play_icon;
if (qApp->isLeftToRight()) {
play_icon = Images::icon("play");
} else {
play_icon = Images::flippedIcon("play");
}
int old_current = current_item;
current_item = current;
if ((current_item > -1) && (current_item < pl.count())) {
pl[current_item].setPlayed(TRUE);
}
if ( (old_current >= 0) && (old_current < listView->rowCount()) ) {
listView->setIcon(old_current, COL_PLAY, QPixmap() );
}
if ( (current_item >= 0) && (current_item < listView->rowCount()) ) {
listView->setIcon(current_item, COL_PLAY, play_icon );
}
//if (current_item >= 0) listView->selectRow(current_item);
if (current_item >= 0) {
listView->clearSelection();
listView->setCurrentCell( current_item, 0);
}
}
void Playlist::clear() {
pl.clear();
listView->clearContents();
listView->setRowCount(0);
setCurrentItem(0);
setModified( false );
}
int Playlist::count() {
return pl.count();
}
bool Playlist::isEmpty() {
return pl.isEmpty();
}
void Playlist::addItem(QString filename, QString name, double duration) {
qDebug("Playlist::addItem: '%s'", filename.toUtf8().data());
#ifdef Q_OS_WIN
filename = Helper::changeSlashes(filename);
#endif
// Test if already is in the list
bool exists = FALSE;
PlaylistItemList::iterator it;
for ( it = pl.begin(); it != pl.end(); ++it ) {
if ( (*it).filename() == filename ) {
exists = TRUE;
break;
}
}
if (!exists) {
if (name.isEmpty()) {
QFileInfo fi(filename);
if (fi.exists()) {
// Local file
name = fi.fileName(); //fi.baseName(TRUE);
} else {
// Stream
name = filename;
}
}
pl.append( PlaylistItem(filename, name, duration) );
//setModified( true ); // Better set the modified on a higher level
} else {
qDebug(" Not added. File already in the list");
}
}
void Playlist::load_m3u(QString file) {
qDebug("Playlist::load_m3u");
bool utf8 = (QFileInfo(file).suffix().toLower() == "m3u8");
QRegExp m3u_id("^#EXTM3U|^#M3U");
QRegExp info("^#EXTINF:(.*),(.*)");
QFile f( file );
if ( f.open( QIODevice::ReadOnly ) ) {
playlist_path = QFileInfo(file).path();
clear();
QString filename="";
QString name="";
double duration=0;
QTextStream stream( &f );
if (utf8)
stream.setCodec("UTF-8");
else
stream.setCodec(QTextCodec::codecForLocale());
QString line;
while ( !stream.atEnd() ) {
line = stream.readLine(); // line of text excluding '\n'
qDebug( " * line: '%s'", line.toUtf8().data() );
if (m3u_id.indexIn(line)!=-1) {
//#EXTM3U
// Ignore line
}
else
if (info.indexIn(line)!=-1) {
duration = info.cap(1).toDouble();
name = info.cap(2);
qDebug(" * name: '%s', duration: %f", name.toUtf8().data(), duration );
}
else
if (line.startsWith("#")) {
// Comment
// Ignore
} else {
filename = line;
QFileInfo fi(filename);
if (fi.exists()) {
filename = fi.absoluteFilePath();
}
if (!fi.exists()) {
if (QFileInfo( playlist_path + "/" + filename).exists() ) {
filename = playlist_path + "/" + filename;
}
}
addItem( filename, name, duration );
name="";
duration = 0;
}
}
f.close();
list();
updateView();
setModified( false );
startPlay();
}
}
void Playlist::load_pls(QString file) {
qDebug("Playlist::load_pls");
playlist_path = QFileInfo(file).path();
QSettings set(file, QSettings::IniFormat);
set.beginGroup( "playlist");
if (set.status() == QSettings::NoError) {
clear();
QString filename;
QString name;
double duration;
int num_items = set.value("NumberOfEntries", 0).toInt();
for (int n=0; n < num_items; n++) {
filename = set.value("File"+QString::number(n+1), "").toString();
name = set.value("Title"+QString::number(n+1), "").toString();
duration = (double) set.value("Length"+QString::number(n+1), 0).toInt();
QFileInfo fi(filename);
if (fi.exists()) {
filename = fi.absoluteFilePath();
}
if (!fi.exists()) {
if (QFileInfo( playlist_path + "/" + filename).exists() ) {
filename = playlist_path + "/" + filename;
}
}
addItem( filename, name, duration );
}
}
set.endGroup();
list();
updateView();
setModified( false );
if (set.status() == QSettings::NoError) startPlay();
}
bool Playlist::save_m3u(QString file) {
qDebug("Playlist::save_m3u: '%s'", file.toUtf8().data());
QString dir_path = QFileInfo(file).path();
if (!dir_path.endsWith("/")) dir_path += "/";
#ifdef Q_OS_WIN
dir_path = Helper::changeSlashes(dir_path);
#endif
qDebug(" * dirPath: '%s'", dir_path.toUtf8().data());
bool utf8 = (QFileInfo(file).suffix().toLower() == "m3u8");
QFile f( file );
if ( f.open( QIODevice::WriteOnly ) ) {
QTextStream stream( &f );
if (utf8)
stream.setCodec("UTF-8");
else
stream.setCodec(QTextCodec::codecForLocale());
QString filename;
stream << "#EXTM3U" << "\n";
stream << "# Playlist created by SMPlayer " << smplayerVersion() << " \n";
PlaylistItemList::iterator it;
for ( it = pl.begin(); it != pl.end(); ++it ) {
filename = (*it).filename();
#ifdef Q_OS_WIN
filename = Helper::changeSlashes(filename);
#endif
stream << "#EXTINF:";
stream << (*it).duration() << ",";
stream << (*it).name() << "\n";
// Try to save the filename as relative instead of absolute
if (filename.startsWith( dir_path )) {
filename = filename.mid( dir_path.length() );
}
stream << filename << "\n";
}
f.close();
setModified( false );
return true;
} else {
return false;
}
}
bool Playlist::save_pls(QString file) {
qDebug("Playlist::save_pls: '%s'", file.toUtf8().data());
QString dir_path = QFileInfo(file).path();
if (!dir_path.endsWith("/")) dir_path += "/";
#ifdef Q_OS_WIN
dir_path = Helper::changeSlashes(dir_path);
#endif
qDebug(" * dirPath: '%s'", dir_path.toUtf8().data());
QSettings set(file, QSettings::IniFormat);
set.beginGroup( "playlist");
QString filename;
PlaylistItemList::iterator it;
for ( int n=0; n < pl.count(); n++ ) {
filename = pl[n].filename();
#ifdef Q_OS_WIN
filename = Helper::changeSlashes(filename);
#endif
// Try to save the filename as relative instead of absolute
if (filename.startsWith( dir_path )) {
filename = filename.mid( dir_path.length() );
}
set.setValue("File"+QString::number(n+1), filename);
set.setValue("Title"+QString::number(n+1), pl[n].name());
set.setValue("Length"+QString::number(n+1), (int) pl[n].duration());
}
set.setValue("NumberOfEntries", pl.count());
set.setValue("Version", 2);
set.endGroup();
set.sync();
bool ok = (set.status() == QSettings::NoError);
if (ok) setModified( false );
return ok;
}
void Playlist::load() {
if (maybeSave()) {
Extensions e;
QString s = MyFileDialog::getOpenFileName(
this, tr("Choose a file"),
lastDir(),
tr("Playlists") + e.playlist().forFilter());
if (!s.isEmpty()) {
latest_dir = QFileInfo(s).absolutePath();
if (QFileInfo(s).suffix().toLower() == "pls")
load_pls(s);
else
load_m3u(s);
}
}
}
bool Playlist::save() {
Extensions e;
QString s = MyFileDialog::getSaveFileName(
this, tr("Choose a filename"),
lastDir(),
tr("Playlists") + e.playlist().forFilter());
if (!s.isEmpty()) {
// If filename has no extension, add it
if (QFileInfo(s).suffix().isEmpty()) {
s = s + ".m3u";
}
if (QFileInfo(s).exists()) {
int res = QMessageBox::question( this,
tr("Confirm overwrite?"),
tr("The file %1 already exists.\n"
"Do you want to overwrite?").arg(s),
QMessageBox::Yes,
QMessageBox::No,
QMessageBox::NoButton);
if (res == QMessageBox::No ) {
return false;
}
}
latest_dir = QFileInfo(s).absolutePath();
if (QFileInfo(s).suffix().toLower() == "pls")
return save_pls(s);
else
return save_m3u(s);
} else {
return false;
}
}
bool Playlist::maybeSave() {
if (!isModified()) return true;
int res = QMessageBox::question( this,
tr("Playlist modified"),
tr("There are unsaved changes, do you want to save the playlist?"),
QMessageBox::Yes,
QMessageBox::No,
QMessageBox::Cancel);
switch (res) {
case QMessageBox::No : return true; // Discard changes
case QMessageBox::Cancel : return false; // Cancel operation
default : return save();
}
}
void Playlist::playCurrent() {
int current = listView->currentRow();
if (current > -1) {
playItem(current);
}
}
void Playlist::itemDoubleClicked(int row) {
qDebug("Playlist::itemDoubleClicked: row: %d", row );
playItem(row);
}
void Playlist::showPopup(const QPoint & pos) {
qDebug("Playlist::showPopup: x: %d y: %d", pos.x(), pos.y() );
if (!popup->isVisible()) {
popup->move( listView->viewport()->mapToGlobal(pos) );
popup->show();
}
}
void Playlist::startPlay() {
// Start to play
if ( shuffleAct->isChecked() )
playItem( chooseRandomItem() );
else
playItem(0);
}
void Playlist::playItem( int n ) {
qDebug("Playlist::playItem: %d (count:%d)", n, pl.count());
if ( (n >= pl.count()) || (n < 0) ) {
qDebug("Playlist::playItem: out of range");
emit playlistEnded();
return;
}
qDebug(" playlist_path: '%s'", playlist_path.toUtf8().data() );
QString filename = pl[n].filename();
QString filename_with_path = playlist_path + "/" + filename;
if (!filename.isEmpty()) {
//pl[n].setPlayed(TRUE);
setCurrentItem(n);
if (play_files_from_start)
core->open(filename, 0);
else
core->open(filename);
}
}
void Playlist::playNext() {
qDebug("Playlist::playNext");
if (shuffleAct->isChecked()) {
// Shuffle
int chosen_item = chooseRandomItem();
if (chosen_item == -1) {
clearPlayedTag();
if (repeatAct->isChecked()) chosen_item = chooseRandomItem();
}
playItem( chosen_item );
} else {
bool finished_list = (current_item+1 >= pl.count());
if (finished_list) clearPlayedTag();
if ( (repeatAct->isChecked()) && (finished_list) ) {
playItem(0);
} else {
playItem( current_item+1 );
}
}
}
void Playlist::playPrev() {
qDebug("Playlist::playPrev");
if (current_item > 0) {
playItem( current_item-1 );
} else {
if (pl.count() > 1) playItem( pl.count() -1 );
}
}
void Playlist::getMediaInfo() {
qDebug("Playlist:: getMediaInfo");
QString filename = core->mdat.filename;
double duration = core->mdat.duration;
QString name = core->mdat.clip_name;
QString artist = core->mdat.clip_artist;
#ifdef Q_OS_WIN
filename = Helper::changeSlashes(filename);
#endif
if (name.isEmpty()) {
QFileInfo fi(filename);
if (fi.exists()) {
// Local file
name = fi.fileName();
} else {
// Stream
name = filename;
}
}
if (!artist.isEmpty()) name = artist + " - " + name;
int pos=0;
PlaylistItemList::iterator it;
for ( it = pl.begin(); it != pl.end(); ++it ) {
if ( (*it).filename() == filename ) {
if ((*it).duration()<1) {
if (!name.isEmpty()) {
(*it).setName(name);
}
(*it).setDuration(duration);
//setModified( true );
}
else
// Edited name (sets duration to 1)
if ((*it).duration()==1) {
(*it).setDuration(duration);
//setModified( true );
}
setCurrentItem(pos);
}
pos++;
}
updateView();
}
// Add current file to playlist
void Playlist::addCurrentFile() {
qDebug("Playlist::addCurrentFile");
if (!core->mdat.filename.isEmpty()) {
addItem( core->mdat.filename, "", 0 );
getMediaInfo();
}
}
void Playlist::addFiles() {
QStringList files = MyFileDialog::getOpenFileNames(
this, tr("Select one or more files to open"),
lastDir(),
tr("All files") +" (*.*)" );
if (files.count()!=0) addFiles(files);
}
void Playlist::addFiles(QStringList files, AutoGetInfo auto_get_info) {
qDebug("Playlist::addFiles");
#if USE_INFOPROVIDER
bool get_info = (auto_get_info == GetInfo);
if (auto_get_info == UserDefined) {
get_info = automatically_get_info;
}
MediaData data;
setCursor(Qt::WaitCursor);
#endif
QStringList::Iterator it = files.begin();
while( it != files.end() ) {
#if USE_INFOPROVIDER
if ( (get_info) && (QFile::exists((*it))) ) {
data = InfoProvider::getInfo( (*it) );
addItem( (*it), data.displayName(), data.duration );
//updateView();
//qApp->processEvents();
} else {
addItem( (*it), "", 0 );
}
#else
addItem( (*it), "", 0 );
#endif
if (QFile::exists(*it)) {
latest_dir = QFileInfo((*it)).absolutePath();
}
++it;
}
#if USE_INFOPROVIDER
unsetCursor();
#endif
updateView();
qDebug( "Playlist::addFiles: latest_dir: '%s'", latest_dir.toUtf8().constData() );
}
void Playlist::addFile(QString file, AutoGetInfo auto_get_info) {
addFiles( QStringList() << file, auto_get_info );
}
void Playlist::addDirectory() {
QString s = MyFileDialog::getExistingDirectory(
this, tr("Choose a directory"),
lastDir() );
if (!s.isEmpty()) {
addDirectory(s);
latest_dir = s;
}
}
void Playlist::addOneDirectory(QString dir) {
QStringList filelist;
Extensions e;
QRegExp rx_ext(e.multimedia().forRegExp());
rx_ext.setCaseSensitivity(Qt::CaseInsensitive);
QStringList dir_list = QDir(dir).entryList();
QString filename;
QStringList::Iterator it = dir_list.begin();
while( it != dir_list.end() ) {
filename = dir;
if (filename.right(1)!="/") filename += "/";
filename += (*it);
QFileInfo fi(filename);
if (!fi.isDir()) {
if (rx_ext.indexIn(fi.suffix()) > -1) {
filelist << filename;
}
}
++it;
}
addFiles(filelist);
}
void Playlist::addDirectory(QString dir) {
addOneDirectory(dir);
if (recursive_add_directory) {
QFileInfoList dir_list = QDir(dir).entryInfoList(QStringList() << "*", QDir::AllDirs | QDir::NoDotAndDotDot);
for (int n=0; n < dir_list.count(); n++) {
if (dir_list[n].isDir()) {
qDebug("Playlist::addDirectory: adding directory: %s", dir_list[n].filePath().toUtf8().data());
addDirectory(dir_list[n].filePath());
}
}
}
}
// Remove selected items
void Playlist::removeSelected() {
qDebug("Playlist::removeSelected");
int first_selected = -1;
int number_previous_item = 0;
for (int n=0; n < listView->rowCount(); n++) {
if (listView->isSelected(n, 0)) {
qDebug(" row %d selected", n);
pl[n].setMarkForDeletion(TRUE);
number_previous_item++;
if (first_selected == -1) first_selected = n;
}
}
PlaylistItemList::iterator it;
for ( it = pl.begin(); it != pl.end(); ++it ) {
if ( (*it).markedForDeletion() ) {
qDebug("Remove '%s'", (*it).filename().toUtf8().data());
it = pl.erase(it);
it--;
setModified( true );
}
}
if (first_selected < current_item) {
current_item -= number_previous_item;
}
if (isEmpty()) setModified(false);
updateView();
if (first_selected >= listView->rowCount())
first_selected = listView->rowCount() - 1;
if ( ( first_selected > -1) && ( first_selected < listView->rowCount() ) ) {
listView->clearSelection();
listView->setCurrentCell( first_selected, 0);
//listView->selectRow( first_selected );
}
}
void Playlist::removeAll() {
/*
pl.clear();
updateView();
setModified( false );
*/
clear();
}
void Playlist::clearPlayedTag() {
PlaylistItemList::iterator it;
for ( it = pl.begin(); it != pl.end(); ++it ) {
(*it).setPlayed(FALSE);
}
updateView();
}
int Playlist::chooseRandomItem() {
qDebug( "Playlist::chooseRandomItem");
QList <int> fi; //List of not played items (free items)
int n=0;
PlaylistItemList::iterator it;
for ( it = pl.begin(); it != pl.end(); ++it ) {
if (! (*it).played() ) fi.append(n);
n++;
}
qDebug(" * free items: %d", fi.count() );
if (fi.count()==0) return -1; // none free
qDebug(" * items: ");
for (int i=0; i < fi.count(); i++) {
qDebug(" * item: %d", fi[i]);
}
int selected = (int) ((double) fi.count() * rand()/(RAND_MAX+1.0));
qDebug(" * selected item: %d (%d)", selected, fi[selected]);
return fi[selected];
}
void Playlist::swapItems(int item1, int item2 ) {
PlaylistItem it1 = pl[item1];
pl[item1] = pl[item2];
pl[item2] = it1;
setModified( true );
}
void Playlist::upItem() {
qDebug("Playlist::upItem");
int current = listView->currentRow();
qDebug(" currentRow: %d", current );
if (current >= 1) {
swapItems( current, current-1 );
if (current_item == (current-1)) current_item = current;
else
if (current_item == current) current_item = current-1;
updateView();
listView->clearSelection();
listView->setCurrentCell( current-1, 0);
}
}
void Playlist::downItem() {
qDebug("Playlist::downItem");
int current = listView->currentRow();
qDebug(" currentRow: %d", current );
if ( (current > -1) && (current < (pl.count()-1)) ) {
swapItems( current, current+1 );
if (current_item == (current+1)) current_item = current;
else
if (current_item == current) current_item = current+1;
updateView();
listView->clearSelection();
listView->setCurrentCell( current+1, 0);
}
}
void Playlist::editCurrentItem() {
int current = listView->currentRow();
if (current > -1) editItem(current);
}
void Playlist::editItem(int item) {
QString current_name = pl[item].name();
if (current_name.isEmpty()) current_name = pl[item].filename();
bool ok;
QString text = QInputDialog::getText( this,
tr("Edit name"),
tr("Type the name that will be displayed in the playlist for this file:"),
QLineEdit::Normal,
current_name, &ok );
if ( ok && !text.isEmpty() ) {
// user entered something and pressed OK
pl[item].setName(text);
// If duration == 0 the name will be overwritten!
if (pl[item].duration()<1) pl[item].setDuration(1);
updateView();
setModified( true );
}
}
void Playlist::editPreferences() {
PlaylistPreferences d(this);
d.setDirectoryRecursion(recursive_add_directory);
d.setAutoGetInfo(automatically_get_info);
d.setSavePlaylistOnExit(save_playlist_in_config);
d.setPlayFilesFromStart(play_files_from_start);
if (d.exec() == QDialog::Accepted) {
recursive_add_directory = d.directoryRecursion();
automatically_get_info = d.autoGetInfo();
save_playlist_in_config = d.savePlaylistOnExit();
play_files_from_start = d.playFilesFromStart();
}
}
// Drag&drop
void Playlist::dragEnterEvent( QDragEnterEvent *e ) {
qDebug("Playlist::dragEnterEvent");
if (e->mimeData()->hasUrls()) {
e->acceptProposedAction();
}
}
void Playlist::dropEvent( QDropEvent *e ) {
qDebug("Playlist::dropEvent");
QStringList files;
if (e->mimeData()->hasUrls()) {
QList <QUrl> l = e->mimeData()->urls();
QString s;
for (int n=0; n < l.count(); n++) {
if (l[n].isValid()) {
qDebug("Playlist::dropEvent: scheme: '%s'", l[n].scheme().toUtf8().data());
if (l[n].scheme() == "file")
s = l[n].toLocalFile();
else
s = l[n].toString();
/*
qDebug(" * '%s'", l[n].toString().toUtf8().data());
qDebug(" * '%s'", l[n].toLocalFile().toUtf8().data());
*/
qDebug("Playlist::dropEvent: file: '%s'", s.toUtf8().data());
files.append(s);
}
}
}
QStringList only_files;
for (int n = 0; n < files.count(); n++) {
if ( QFileInfo( files[n] ).isDir() ) {
addDirectory( files[n] );
} else {
only_files.append( files[n] );
}
}
addFiles( only_files );
}
void Playlist::hideEvent( QHideEvent * ) {
emit visibilityChanged(false);
}
void Playlist::showEvent( QShowEvent * ) {
emit visibilityChanged(true);
}
void Playlist::closeEvent( QCloseEvent * e ) {
saveSettings();
e->accept();
}
void Playlist::maybeSaveSettings() {
qDebug("Playlist::maybeSaveSettings");
if (isModified()) saveSettings();
}
void Playlist::saveSettings() {
qDebug("Playlist::saveSettings");
QSettings * set = settings;
set->beginGroup( "playlist");
set->setValue( "repeat", repeatAct->isChecked() );
set->setValue( "shuffle", shuffleAct->isChecked() );
set->setValue( "auto_get_info", automatically_get_info );
set->setValue( "recursive_add_directory", recursive_add_directory );
set->setValue( "save_playlist_in_config", save_playlist_in_config );
set->setValue( "play_files_from_start", play_files_from_start );
#if !DOCK_PLAYLIST
set->setValue( "size", size() );
#endif
set->setValue( "latest_dir", latest_dir );
set->endGroup();
if (save_playlist_in_config) {
//Save current list
set->beginGroup( "playlist_contents");
set->setValue( "count", (int) pl.count() );
for ( int n=0; n < pl.count(); n++ ) {
set->setValue( QString("item_%1_filename").arg(n), pl[n].filename() );
set->setValue( QString("item_%1_duration").arg(n), pl[n].duration() );
set->setValue( QString("item_%1_name").arg(n), pl[n].name() );
}
set->setValue( "current_item", current_item );
set->setValue( "modified", modified );
set->endGroup();
}
}
void Playlist::loadSettings() {
qDebug("Playlist::loadSettings");
QSettings * set = settings;
set->beginGroup( "playlist");
repeatAct->setChecked( set->value( "repeat", repeatAct->isChecked() ).toBool() );
shuffleAct->setChecked( set->value( "shuffle", shuffleAct->isChecked() ).toBool() );
automatically_get_info = set->value( "auto_get_info", automatically_get_info ).toBool();
recursive_add_directory = set->value( "recursive_add_directory", recursive_add_directory ).toBool();
save_playlist_in_config = set->value( "save_playlist_in_config", save_playlist_in_config ).toBool();
play_files_from_start = set->value( "play_files_from_start", play_files_from_start ).toBool();
#if !DOCK_PLAYLIST
resize( set->value("size", size()).toSize() );
#endif
latest_dir = set->value( "latest_dir", latest_dir ).toString();
set->endGroup();
if (save_playlist_in_config) {
//Load latest list
set->beginGroup( "playlist_contents");
int count = set->value( "count", 0 ).toInt();
QString filename, name;
double duration;
for ( int n=0; n < count; n++ ) {
filename = set->value( QString("item_%1_filename").arg(n), "" ).toString();
duration = set->value( QString("item_%1_duration").arg(n), -1 ).toDouble();
name = set->value( QString("item_%1_name").arg(n), "" ).toString();
addItem( filename, name, duration );
}
setCurrentItem( set->value( "current_item", -1 ).toInt() );
setModified( set->value( "modified", false ).toBool() );
updateView();
set->endGroup();
}
}
QString Playlist::lastDir() {
QString last_dir = latest_dir;
if (last_dir.isEmpty()) last_dir = pref->latest_dir;
return last_dir;
}
// Language change stuff
void Playlist::changeEvent(QEvent *e) {
if (e->type() == QEvent::LanguageChange) {
retranslateStrings();
} else {
QWidget::changeEvent(e);
}
}
#include "moc_playlist.cpp"