aboutsummaryrefslogtreecommitdiff
path: root/src/qmmpui
diff options
context:
space:
mode:
authortrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2012-12-22 19:16:29 +0000
committertrialuser02 <trialuser02@90c681e8-e032-0410-971d-27865f9a5e38>2012-12-22 19:16:29 +0000
commitaecf8592751e7beb682fcd5bc8c5b1d38335fa84 (patch)
treecf267363944faafb7b29370d27f6ae19fbcc7647 /src/qmmpui
parent954146ff9b69591f0cf3895e96922bb55ad88502 (diff)
downloadqmmp-aecf8592751e7beb682fcd5bc8c5b1d38335fa84.tar.gz
qmmp-aecf8592751e7beb682fcd5bc8c5b1d38335fa84.tar.bz2
qmmp-aecf8592751e7beb682fcd5bc8c5b1d38335fa84.zip
libqmmpui: added URL dialog implementation, added PlayListDownloader
class git-svn-id: http://svn.code.sf.net/p/qmmp-dev/code/trunk/qmmp@3089 90c681e8-e032-0410-971d-27865f9a5e38
Diffstat (limited to 'src/qmmpui')
-rw-r--r--src/qmmpui/addurldialog.cpp127
-rw-r--r--src/qmmpui/addurldialog_p.h57
-rw-r--r--src/qmmpui/forms/addurldialog.ui91
-rw-r--r--src/qmmpui/playlistdownloader.cpp112
-rw-r--r--src/qmmpui/playlistdownloader.h72
-rw-r--r--src/qmmpui/playlistmodel.cpp5
-rw-r--r--src/qmmpui/playlistparser.cpp17
-rw-r--r--src/qmmpui/playlistparser.h12
-rw-r--r--src/qmmpui/qmmpui.pro19
-rw-r--r--src/qmmpui/uihelper.cpp6
-rw-r--r--src/qmmpui/uihelper.h7
11 files changed, 517 insertions, 8 deletions
diff --git a/src/qmmpui/addurldialog.cpp b/src/qmmpui/addurldialog.cpp
new file mode 100644
index 000000000..cf845fe68
--- /dev/null
+++ b/src/qmmpui/addurldialog.cpp
@@ -0,0 +1,127 @@
+/***************************************************************************
+ * Copyright (C) 2006-2012 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * 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 <QSettings>
+#include <QDir>
+#include <QMessageBox>
+#include <QClipboard>
+#include <qmmpui/playlistparser.h>
+#include <qmmpui/playlistformat.h>
+#include <qmmpui/playlistmodel.h>
+#include <qmmpui/playlistdownloader.h>
+#include <qmmp/qmmpsettings.h>
+#include <qmmp/metadatamanager.h>
+#include <qmmp/qmmp.h>
+#include "addurldialog_p.h"
+
+#define HISTORY_SIZE 10
+
+AddUrlDialog::AddUrlDialog(QWidget *parent) : QDialog(parent)
+{
+ setupUi(this);
+ setAttribute(Qt::WA_DeleteOnClose);
+ setAttribute(Qt::WA_QuitOnClose, false);
+ QSettings settings(Qmmp::configFile(), QSettings::IniFormat);
+ m_history = settings.value("URLDialog/history").toStringList();
+ urlComboBox->addItems(m_history);
+ if(settings.value("URLDialog/use_clipboard", false).toBool())
+ {
+ QUrl url(QApplication::clipboard()->text().trimmed());
+ if(url.isValid() && MetaDataManager::instance()->protocols().contains(url.scheme()))
+ urlComboBox->setEditText(QApplication::clipboard()->text().trimmed());
+ }
+ m_downloader = new PlayListDownloader(this);
+ connect(m_downloader, SIGNAL(done(QStringList)), SLOT(add(QStringList)));
+ connect(m_downloader, SIGNAL(error(QString)), SLOT(showError(QString)));
+}
+
+AddUrlDialog::~AddUrlDialog()
+{
+ while (m_history.size() > HISTORY_SIZE)
+ m_history.removeLast();
+ QSettings settings(Qmmp::configFile(), QSettings::IniFormat);
+ settings.setValue("URLDialog/history", m_history);
+}
+
+QPointer<AddUrlDialog> AddUrlDialog::m_instance = 0;
+
+void AddUrlDialog::popup(QWidget* parent, PlayListModel* model)
+{
+ if (!m_instance)
+ {
+ m_instance = new AddUrlDialog(parent);
+ m_instance->setModel(model);
+ }
+ m_instance->show();
+ m_instance->raise();
+}
+
+void AddUrlDialog::accept()
+{
+ addButton->setEnabled(false);
+ if(urlComboBox->currentText().isEmpty())
+ {
+ QDialog::accept();
+ return;
+ }
+
+ QString s = urlComboBox->currentText().trimmed();
+
+ if(!s.startsWith("http://") && !s.contains("://"))
+ s.prepend("http://");
+
+ if(!MetaDataManager::instance()->protocols().contains(QUrl(s).scheme()))
+ {
+ qWarning("AddUrlDialog: unsupported protocol");
+ QDialog::accept();
+ return;
+ }
+
+ m_history.removeAll(s);
+ m_history.prepend(s);
+
+ if (s.startsWith("http://")) //try to download playlist
+ {
+ m_downloader->start(QUrl(s));
+ return;
+ }
+ m_model->add(s);
+ QDialog::accept();
+}
+
+void AddUrlDialog::setModel(PlayListModel *m)
+{
+ m_model = m;
+}
+
+void AddUrlDialog::add(const QStringList &urls)
+{
+ addButton->setEnabled(true);
+ m_model->add(urls);
+ QDialog::accept();
+}
+
+void AddUrlDialog::showError(const QString &message)
+{
+ QMessageBox::warning(this, tr("Error"), message);
+ addButton->setEnabled(true);
+}
+
+
diff --git a/src/qmmpui/addurldialog_p.h b/src/qmmpui/addurldialog_p.h
new file mode 100644
index 000000000..5835b3fbf
--- /dev/null
+++ b/src/qmmpui/addurldialog_p.h
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * Copyright (C) 2006-2012 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * 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. *
+ ***************************************************************************/
+
+#ifndef ADDURLDIALOG_P_H
+#define ADDURLDIALOG_P_H
+
+#include <QDialog>
+#include <QPointer>
+#include <QUrl>
+#include "ui_addurldialog.h"
+
+class QNetworkAccessManager;
+class QNetworkReply;
+class PlayListModel;
+class PlayListDownloader;
+
+/*! @internal
+ @author Vladimir Kuznetsov <vovanec@gmail.com>
+ */
+class AddUrlDialog : public QDialog , private Ui::AddUrlDialog
+{
+ Q_OBJECT
+public:
+ static void popup(QWidget* parent ,PlayListModel*);
+
+private slots:
+ void add(const QStringList &urls);
+ void showError(const QString &message);
+
+private:
+ AddUrlDialog(QWidget *parent);
+ ~AddUrlDialog();
+ void accept();
+ void setModel(PlayListModel*);
+ static QPointer<AddUrlDialog> m_instance;
+ PlayListModel *m_model;
+ PlayListDownloader *m_downloader;
+ QStringList m_history;
+};
+#endif //ADDURLDIALOG_P_H
diff --git a/src/qmmpui/forms/addurldialog.ui b/src/qmmpui/forms/addurldialog.ui
new file mode 100644
index 000000000..fd8925e49
--- /dev/null
+++ b/src/qmmpui/forms/addurldialog.ui
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AddUrlDialog</class>
+ <widget class="QDialog" name="AddUrlDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>379</width>
+ <height>58</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Enter URL to add</string>
+ </property>
+ <layout class="QGridLayout">
+ <property name="margin">
+ <number>5</number>
+ </property>
+ <item row="0" column="0" colspan="3">
+ <widget class="QComboBox" name="urlComboBox">
+ <property name="editable">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>181</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="addButton">
+ <property name="text">
+ <string>&amp;Add</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QPushButton" name="cancelButton">
+ <property name="text">
+ <string>&amp;Cancel</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>addButton</sender>
+ <signal>clicked()</signal>
+ <receiver>AddUrlDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>51</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>184</x>
+ <y>72</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>cancelButton</sender>
+ <signal>clicked()</signal>
+ <receiver>AddUrlDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>343</x>
+ <y>62</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>392</x>
+ <y>60</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/qmmpui/playlistdownloader.cpp b/src/qmmpui/playlistdownloader.cpp
new file mode 100644
index 000000000..2287747df
--- /dev/null
+++ b/src/qmmpui/playlistdownloader.cpp
@@ -0,0 +1,112 @@
+/***************************************************************************
+ * Copyright (C) 2012 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * 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 <QNetworkAccessManager>
+#include <QNetworkProxy>
+#include <QNetworkReply>
+#include <qmmp/qmmp.h>
+#include <qmmp/qmmpsettings.h>
+#include <qmmpui/playlistparser.h>
+#include "playlistdownloader.h"
+
+PlayListDownloader::PlayListDownloader(QObject *parent) : QObject(parent)
+{
+ m_getReply = 0;
+ m_ua = QString("qmmp/%1").arg(Qmmp::strVersion()).toAscii();
+ m_manager = new QNetworkAccessManager(this);
+ connect(m_manager, SIGNAL(finished (QNetworkReply *)), SLOT(readResponse(QNetworkReply *)));
+ //load global proxy settings
+ QmmpSettings *gs = QmmpSettings::instance();
+ if (gs->isProxyEnabled())
+ {
+ QNetworkProxy proxy(QNetworkProxy::HttpProxy, gs->proxy().host(), gs->proxy().port());
+ if(gs->useProxyAuth())
+ {
+ proxy.setUser(gs->proxy().userName());
+ proxy.setPassword(gs->proxy().password());
+ }
+ m_manager->setProxy(proxy);
+ }
+}
+
+void PlayListDownloader::start(const QUrl &url)
+{
+ if(!PlayListParser::findByUrl(url)) //is it playlist?
+ {
+ emit done(QStringList() << url.toString()); //just send initial URL
+ return;
+ }
+ m_url = url;
+ QNetworkRequest r;
+ r.setUrl(url);
+ r.setRawHeader("User-Agent", m_ua);
+ m_getReply = m_manager->get(r);
+ m_redirect_url.clear();
+}
+
+void PlayListDownloader::readResponse(QNetworkReply *reply)
+{
+ if(reply != m_getReply)
+ {
+ reply->deleteLater();
+ return;
+ }
+
+ if(reply->error() != QNetworkReply::NoError)
+ {
+ emit error(reply->errorString() + " (" + reply->error() + ")");
+ reply->deleteLater();
+ return;
+ }
+
+ QUrl url = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
+ if(!url.isEmpty() && url != m_redirect_url)
+ {
+ m_redirect_url = url;
+ qDebug("PlayListDownloader: redirect to %s", qPrintable(url.toString()));
+ QNetworkRequest request(url);
+ request.setRawHeader("User-Agent", m_ua);
+ if(reply == m_getReply)
+ m_getReply = m_manager->get(request);
+ reply->deleteLater();
+ return;
+ }
+ m_redirect_url.clear();
+
+ if(reply == m_getReply)
+ {
+ m_getReply = 0;
+ QString contentType = reply->header(QNetworkRequest::ContentTypeHeader).toString();
+ qDebug("PlayListDownloader: content type: %s", qPrintable(contentType));
+ PlayListFormat *fmt = PlayListParser::findByMime(contentType);
+ if(!fmt)
+ fmt = PlayListParser::findByUrl(m_url);
+ if(fmt)
+ {
+ QStringList list = fmt->decode(QString::fromUtf8(reply->readAll()));
+ emit done(list);
+ }
+ else
+ {
+ emit error(tr("Unsupported playlist format"));
+ }
+ }
+ reply->deleteLater();
+}
diff --git a/src/qmmpui/playlistdownloader.h b/src/qmmpui/playlistdownloader.h
new file mode 100644
index 000000000..df0a612db
--- /dev/null
+++ b/src/qmmpui/playlistdownloader.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * Copyright (C) 2012 by Ilya Kotov *
+ * forkotov02@hotmail.ru *
+ * *
+ * 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. *
+ ***************************************************************************/
+
+#ifndef PLAYLISTDOWNLOADER_H
+#define PLAYLISTDOWNLOADER_H
+
+#include <QObject>
+#include <QUrl>
+
+class QNetworkAccessManager;
+class QNetworkReply;
+
+/*! @brief The PlayListDownloader class downloads playlist from remote URL and extracts tracks
+ * @author Ilya Kotov <forkotov02@hotmail.ru>
+ */
+class PlayListDownloader : public QObject
+{
+ Q_OBJECT
+public:
+ /*!
+ * Object constructor.
+ */
+ explicit PlayListDownloader(QObject *parent = 0);
+
+signals:
+ /*!
+ * Emitted when downloading is finished without errors.
+ * @param urls A list of extracted URLs or argument of the \b PlayListDownloader::start()
+ * function if remote URL doesn't contain playlist.
+ */
+ void done(const QStringList &urls);
+ /*!
+ * Emitted when downloading is finished with error.
+ * @param message Error message.
+ */
+ void error(const QString &message);
+
+public slots:
+ /*!
+ * Starts playlist downloading
+ * @param url URL of remote playlist
+ */
+ void start(const QUrl &url);
+
+private slots:
+ void readResponse(QNetworkReply *reply);
+
+private:
+ QNetworkAccessManager *m_manager;
+ QUrl m_redirect_url, m_url;
+ QNetworkReply *m_getReply;
+ QByteArray m_ua;
+};
+
+#endif // PLAYLISTDOWNLOADER_H
diff --git a/src/qmmpui/playlistmodel.cpp b/src/qmmpui/playlistmodel.cpp
index 6f67e6e22..83038a2bd 100644
--- a/src/qmmpui/playlistmodel.cpp
+++ b/src/qmmpui/playlistmodel.cpp
@@ -841,11 +841,8 @@ void PlayListModel::doCurrentVisibleRequest()
void PlayListModel::loadPlaylist(const QString &f_name)
{
PlayListFormat* prs = PlayListParser::findByPath(f_name);
- if(!prs)
- {
- //qWarning("PlayListModel: unsupported playlist format");
+ if(!prs || !QFile::exists(f_name))
return;
- }
QFile file(f_name);
if (!file.open(QIODevice::ReadOnly))
diff --git a/src/qmmpui/playlistparser.cpp b/src/qmmpui/playlistparser.cpp
index 7f14901a5..830d634d8 100644
--- a/src/qmmpui/playlistparser.cpp
+++ b/src/qmmpui/playlistparser.cpp
@@ -46,6 +46,17 @@ QStringList PlayListParser::nameFilters()
return filters;
}
+PlayListFormat *PlayListParser::findByMime(const QString &mime)
+{
+ checkFormats();
+ foreach(PlayListFormat* format, *m_formats)
+ {
+ if(format->properties().contentTypes.contains(mime))
+ return format;
+ }
+ return 0;
+}
+
PlayListFormat *PlayListParser::findByPath(const QString &filePath)
{
checkFormats();
@@ -61,6 +72,12 @@ PlayListFormat *PlayListParser::findByPath(const QString &filePath)
return 0;
}
+PlayListFormat *PlayListParser::findByUrl(const QUrl &url)
+{
+ QString path = url.encodedPath();
+ return findByPath(path);
+}
+
void PlayListParser::checkFormats()
{
if (m_formats)
diff --git a/src/qmmpui/playlistparser.h b/src/qmmpui/playlistparser.h
index d78e3ad7d..00dc4d24d 100644
--- a/src/qmmpui/playlistparser.h
+++ b/src/qmmpui/playlistparser.h
@@ -20,6 +20,8 @@
#ifndef PLAYLISTPARSER_H
#define PLAYLISTPARSER_H
+#include <QStringList>
+#include <QUrl>
#include "playlistformat.h"
/*! @brief The PlaylistParser class provides a simple api to access playlist format plugins.
@@ -37,10 +39,20 @@ public:
*/
static QStringList nameFilters();
/*!
+ * Returns PlayListFormat pointer which supports mime type \b mime
+ * or \b 0 if mime type \b mime is unsupported
+ */
+ static PlayListFormat *findByMime(const QString &mime);
+ /*!
* Finds playlist format by file path \b filePath
* Returns \b 0 if file \b filePath is unsupported.
*/
static PlayListFormat *findByPath(const QString &filePath);
+ /*!
+ * Finds playlist format by url path \b url
+ * Returns \b 0 if file \b filePath is unsupported.
+ */
+ static PlayListFormat *findByUrl(const QUrl &url);
private:
PlayListParser(){}
diff --git a/src/qmmpui/qmmpui.pro b/src/qmmpui/qmmpui.pro
index 5ef7d6908..7861bb10c 100644
--- a/src/qmmpui/qmmpui.pro
+++ b/src/qmmpui/qmmpui.pro
@@ -46,7 +46,9 @@ HEADERS += general.h \
pluginitem_p.h \
aboutdialog_p.h \
qmmpuisettings.h \
- radioitemdelegate_p.h
+ radioitemdelegate_p.h \
+ playlistdownloader.h \
+ addurldialog_p.h
SOURCES += general.cpp \
playlistparser.cpp \
commandlinemanager.cpp \
@@ -69,13 +71,16 @@ SOURCES += general.cpp \
pluginitem.cpp \
aboutdialog.cpp \
qmmpuisettings.cpp \
- radioitemdelegate.cpp
+ radioitemdelegate.cpp \
+ playlistdownloader.cpp \
+ addurldialog.cpp
FORMS += forms/detailsdialog.ui \
forms/tageditor.ui \
forms/templateeditor.ui \
forms/jumptotrackdialog.ui \
forms/configdialog.ui \
- forms/aboutdialog.ui
+ forms/aboutdialog.ui \
+ forms/addurldialog.ui
unix:DESTDIR = .
RESOURCES += translations/libqmmpui_locales.qrc \
images/qmmpui_images.qrc \
@@ -114,7 +119,8 @@ unix {
uifactory.h \
uiloader.h \
uihelper.h \
- qmmpuisettings.h
+ qmmpuisettings.h \
+ playlistdownloader.h
devel.path = /include/qmmpui
INSTALLS += target \
devel
@@ -125,3 +131,8 @@ unix {
+
+
+
+
+
diff --git a/src/qmmpui/uihelper.cpp b/src/qmmpui/uihelper.cpp
index 2dfb7b9e8..e2984619f 100644
--- a/src/qmmpui/uihelper.cpp
+++ b/src/qmmpui/uihelper.cpp
@@ -31,6 +31,7 @@
#include "generalfactory.h"
#include "jumptotrackdialog_p.h"
#include "aboutdialog_p.h"
+#include "addurldialog_p.h"
#include "uihelper.h"
UiHelper *UiHelper::m_instance = 0;
@@ -145,6 +146,11 @@ void UiHelper::addDirectory(QWidget *parent, PlayListModel *model)
tr("Choose a directory"));
}
+void UiHelper::addUrl(QWidget *parent, PlayListModel *model)
+{
+ AddUrlDialog::popup(parent, model);
+}
+
void UiHelper::loadPlayList(QWidget *parent, PlayListModel *model)
{
if(PlayListParser::nameFilters().isEmpty())
diff --git a/src/qmmpui/uihelper.h b/src/qmmpui/uihelper.h
index 8722e3e8b..867fc9931 100644
--- a/src/qmmpui/uihelper.h
+++ b/src/qmmpui/uihelper.h
@@ -102,6 +102,13 @@ public:
void addDirectory(QWidget *parent = qApp->activeWindow(),
PlayListModel *model = PlayListManager::instance()->selectedPlayList());
/*!
+ * Opens 'Add URL' dialog
+ * @param parent Parent widget
+ * @param model Destination playlist model
+ */
+ void addUrl(QWidget *parent = qApp->activeWindow(),
+ PlayListModel *model = PlayListManager::instance()->selectedPlayList());
+ /*!
* Opens 'Load Playlist' dialog
* @param parent Parent widget
* @param model Destination playlist model