Load and add streams!

This commit is contained in:
craig
2011-12-06 22:00:56 +00:00
committed by craig
parent 565d1037f3
commit 7fd749a31e
12 changed files with 568 additions and 21 deletions

View File

@@ -29,6 +29,7 @@ SET( CANTATA_SRCS
gui/serversettings.cpp
gui/outputsettings.cpp
gui/streamspage.cpp
gui/streamdialog.cpp
gui/librarypage.cpp
gui/folderpage.cpp
gui/playlistspage.cpp
@@ -49,6 +50,8 @@ SET( CANTATA_SRCS
models/dirviewitemfile.cpp
models/dirviewitemdir.cpp
models/dirviewitemroot.cpp
models/streamsmodel.cpp
models/streamsproxymodel.cpp
mpd/mpdconnection.cpp
mpd/mpdparseutils.cpp
mpd/mpdstats.cpp
@@ -72,6 +75,7 @@ SET( CANTATA_MOC_HDRS
gui/librarypage.h
gui/playlistspage.h
gui/streamspage.h
gui/streamdialog.h
gui/interfacesettings.h
gui/playbacksettings.h
gui/serversettings.h
@@ -85,6 +89,8 @@ SET( CANTATA_MOC_HDRS
models/playlisttableproxymodel.h
models/dirviewmodel.h
models/dirviewproxymodel.h
models/streamsmodel.h
models/streamsproxymodel.h
mpd/mpdconnection.h
mpd/song.h
widgets/fancytabwidget.h

View File

@@ -379,7 +379,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent),
foldersTabAction->setIcon(QIcon::fromTheme("inode-directory"));
playlistsTabAction->setIcon(QIcon::fromTheme("view-media-playlist"));
lyricsTabAction->setIcon(QIcon::fromTheme("view-media-lyrics"));
streamsTabAction->setIcon(QIcon::fromTheme("network-wireless"));
streamsTabAction->setIcon(QIcon::fromTheme("applications-internet"));
menuButton->setIcon(QIcon::fromTheme("configure"));
volumeButton->setIcon(QIcon::fromTheme("player-volume"));
@@ -607,6 +607,7 @@ MainWindow::~MainWindow()
Settings::self()->savePlaylistHeaderState(playlistTableViewHeader->saveState());
Settings::self()->saveSidebar((int)(tabWidget->mode()));
Settings::self()->save();
streamsPage->save();
disconnect(MPDConnection::self(), 0, 0, 0);
if (Settings::self()->stopOnExit()) {
emit stop();
@@ -727,6 +728,8 @@ void MainWindow::updateSettings()
libraryPage->refresh(LibraryPage::RefreshForce);
}
streamsPage->refresh();
if (Settings::self()->useSystemTray()) {
if (!trayIcon) {
setupTrayIcon();
@@ -892,7 +895,7 @@ void MainWindow::updateCurrentSong(const Song &song)
playlistModel.updateCurrentSong(song.id);
if (3==tabWidget->current_index()) {
if (4==tabWidget->current_index()) {
lyricsPage->update(song);
} else {
lyricsNeedUpdating=true;
@@ -1073,18 +1076,20 @@ void MainWindow::replacePlaylist()
{
emit clear();
emit getStatus();
searchPlaylistLineEdit->clear();
addToPlaylist();
}
void MainWindow::addToPlaylist()
{
searchPlaylistLineEdit->clear();
if (libraryPage->view->isVisible()) {
libraryPage->addSelectionToPlaylist();
} else if (folderPage->view->isVisible()) {
folderPage->addSelectionToPlaylist();
} else if (playlistTableView->isVisible()) {
} else if (playlistsPage->isVisible()) {
playlistsPage->addSelectionToPlaylist();
} else if (streamsPage->isVisible()) {
streamsPage->addSelectionToPlaylist();
}
}
@@ -1358,7 +1363,8 @@ enum Tabs
{
TAB_LIBRARY = 0x01,
TAB_DIRS = 0x02,
TAB_PLAYLISTS = 0x04
// TAB_STREAMS = 0x04,
TAB_PLAYLISTS = 0x08
};
void MainWindow::currentTabChanged(int index)
@@ -1383,6 +1389,8 @@ void MainWindow::currentTabChanged(int index)
}
break;
case 3:
break;
case 4:
if (lyricsNeedUpdating) {
lyricsPage->update(current);
lyricsNeedUpdating=false;

73
gui/streamdialog.cpp Normal file
View File

@@ -0,0 +1,73 @@
/*
* Cantata
*
* Copyright (c) 2011 Craig Drummond <craig.p.drummond@gmail.com>
*
* ----
*
* 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <QtGui/QFormLayout>
#include <QtGui/QLabel>
#include <QtGui/QIcon>
#include "streamdialog.h"
#include "mainwindow.h"
#include "settings.h"
#ifdef ENABLE_KDE_SUPPORT
#include <KDE/KLocale>
#endif
StreamDialog::StreamDialog(QWidget *parent)
#ifdef ENABLE_KDE_SUPPORT
: KDialog(parent)
#else
: QDialog(parent)
#endif
{
#ifdef ENABLE_KDE_SUPPORT
QWidget *wid = new QWidget(this);
#else
QWidget *wid = this;
#endif
QFormLayout *layout=new QFormLayout(wid);
nameEntry=new LineEdit(wid);
urlEntry=new LineEdit(wid);
#ifdef ENABLE_KDE_SUPPORT
layout->setWidget(0, QFormLayout::LabelRole, new QLabel(i18n("Name:"), wid));
#else
layout->setWidget(0, QFormLayout::LabelRole, new QLabel(tr("Name:"), wid));
#endif
layout->setWidget(0, QFormLayout::FieldRole, nameEntry);
#ifdef ENABLE_KDE_SUPPORT
layout->setWidget(1, QFormLayout::LabelRole, new QLabel(i18n("Stream:"), wid));
#else
layout->setWidget(1, QFormLayout::LabelRole, new QLabel(tr("Stream:"), wid));
#endif
layout->setWidget(1, QFormLayout::FieldRole, urlEntry);
urlEntry->setMinimumWidth(300);
#ifdef ENABLE_KDE_SUPPORT
setMainWidget(wid);
setButtons(KDialog::Ok|KDialog::Cancel);
setCaption(i18n("Add Stream"));
#else
setWindowTitle(tr("Add Stream"));
// TODO: Buttons!!!!
#endif
}

53
gui/streamdialog.h Normal file
View File

@@ -0,0 +1,53 @@
/*
* Cantata
*
* Copyright (c) 2011 Craig Drummond <craig.p.drummond@gmail.com>
*
* ----
*
* 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef STREAMDIALOG_H
#define STREAMDIALOG_H
#ifdef ENABLE_KDE_SUPPORT
#include <KDialog>
#else
#include <QDialog>
#endif
#include "lineedit.h"
#ifdef ENABLE_KDE_SUPPORT
class StreamDialog : public KDialog
#else
class StreamDialog : public QDialog
#endif
{
Q_OBJECT
public:
StreamDialog(QWidget *parent);
QString name() { return nameEntry->text(); }
QString url() { return urlEntry->text(); }
private:
LineEdit *nameEntry;
LineEdit *urlEntry;
};
#endif

View File

@@ -22,14 +22,19 @@
*/
#include "streamspage.h"
#include "streamsmodel.h"
#include "streamdialog.h"
#include "mpdconnection.h"
#include <QtGui/QIcon>
#include <QtGui/QToolButton>
#ifdef ENABLE_KDE_SUPPORT
#include <KAction>
#include <KLocale>
#include <KActionCollection>
#include <KDE/KAction>
#include <KDE/KLocale>
#include <KDE/KActionCollection>
#include <KDE/KMessageBox>
#else
#include <QAction>
#include <QtGui/QAction>
#include <QtGui/QMessageBox>
#endif
StreamsPage::StreamsPage(MainWindow *p)
@@ -41,9 +46,12 @@ StreamsPage::StreamsPage(MainWindow *p)
addAction->setText(i18n("Add Stream"));
removeAction = p->actionCollection()->addAction("removestream");
removeAction->setText(i18n("Remove Stream"));
renameAction = p->actionCollection()->addAction("renamestream");
renameAction->setText(i18n("Rename Stream"));
#else
addAction = new QAction(tr("Add Stream"), this);
removeAction = new QAction(tr("Remove Stream"), this);
renameAction = new QAction(tr("Rename Stream"), this);
#endif
addAction->setIcon(QIcon::fromTheme("list-add"));
removeAction->setIcon(QIcon::fromTheme("list-remove"));
@@ -56,6 +64,8 @@ StreamsPage::StreamsPage(MainWindow *p)
connect(view, SIGNAL(itemsSelected(bool)), removeStream, SLOT(setEnabled(bool)));
connect(addAction, SIGNAL(triggered(bool)), this, SLOT(add()));
connect(removeAction, SIGNAL(triggered(bool)), this, SLOT(remove()));
connect(renameAction, SIGNAL(triggered(bool)), this, SLOT(rename()));
connect(this, SIGNAL(add(const QStringList &)), MPDConnection::self(), SLOT(add(const QStringList &)));
addStream->setAutoRaise(true);
removeStream->setAutoRaise(true);
@@ -65,18 +75,119 @@ StreamsPage::StreamsPage(MainWindow *p)
addToPlaylist->setEnabled(false);
replacePlaylist->setEnabled(false);
view->setHeaderHidden(true);
view->addAction(p->addToPlaylistAction);
view->addAction(p->replacePlaylistAction);
view->addAction(removeAction);
view->addAction(renameAction);
proxy.setSourceModel(StreamsModel::self());
view->setModel(&proxy);
}
StreamsPage::~StreamsPage()
{
}
void StreamsPage::refresh()
{
StreamsModel::self()->reload();
}
void StreamsPage::save()
{
StreamsModel::self()->save();
}
void StreamsPage::addSelectionToPlaylist()
{
QStringList streams;
const QModelIndexList selected = view->selectionModel()->selectedIndexes();
if (0==selected.size()) {
return;
}
foreach (const QModelIndex &idx, selected) {
QString stream=StreamsModel::self()->data(proxy.mapToSource(idx), Qt::ToolTipRole).toString();
if (!streams.contains(stream)) {
streams << stream;
}
}
if (!streams.isEmpty()) {
emit add(streams);
view->selectionModel()->clearSelection();
}
}
static void showError(QWidget *parent, const QString &error)
{
#ifdef ENABLE_KDE_SUPPORT
KMessageBox::error(parent, error);
#else
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Error);
msgBox.setWindowTitle(tr("Error"));
msgBox.setText(error);
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.exec();
#endif
}
void StreamsPage::add()
{
StreamDialog dlg(this);
if (QDialog::Accepted==dlg.exec()) {
QString name=dlg.name();
QString url=dlg.url();
if (name.isEmpty()) {
#ifdef ENABLE_KDE_SUPPORT
showError(this, i18n("No name supplied!"));
#else
showError(this, tr("No name supplied!"));
#endif
return;
}
if (url.isEmpty()) {
#ifdef ENABLE_KDE_SUPPORT
showError(this, i18n("No stream supplied!"));
#else
showError(this, tr("No stream supplied!"));
#endif
return;
}
QString existing=StreamsModel::self()->name(url);
if (!existing.isEmpty()) {
#ifdef ENABLE_KDE_SUPPORT
showError(this, i18n("Stream already exists!</br><i>%1</i>", existing));
#else
showError(this, tr("Stream already exists!</br><i>%1</i>").arg(existing));
#endif
return;
}
if (!StreamsModel::self()->add(name, url)) {
#ifdef ENABLE_KDE_SUPPORT
showError(this, i18n("A stream named <i>%1</i> already exists!", name));
#else
showError(this, tr("A stream named <i>%1</i> already exists!").arg(name));
#endif
}
}
}
void StreamsPage::remove()
{
}
void StreamsPage::rename()
{
}

View File

@@ -26,6 +26,7 @@
#include "ui_streamspage.h"
#include "mainwindow.h"
#include "streamsproxymodel.h"
class StreamsPage : public QWidget, public Ui::StreamsPage
{
@@ -35,13 +36,24 @@ public:
StreamsPage(MainWindow *p);
virtual ~StreamsPage();
void refresh();
void save();
void addSelectionToPlaylist();
Q_SIGNALS:
// These are for communicating with MPD object (which is in its own thread, so need to talk via singal/slots)
void add(const QStringList &streams);
public Q_SLOTS:
void add();
void remove();
void rename();
private:
Action *addAction;
Action *removeAction;
Action *renameAction;
StreamsProxyModel proxy;
};
#endif

View File

@@ -42,7 +42,6 @@ public:
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &, int) const;
void getPlaylists();
void renamePlaylist(const QString oldname, const QString newname);
void clear();
private:

View File

@@ -33,6 +33,7 @@
#include <KDE/KLocale>
#endif
#include "playlisttablemodel.h"
#include "streamsmodel.h"
#include "mpdparseutils.h"
#include "mpdstats.h"
#include "mpdstatus.h"
@@ -124,33 +125,49 @@ QVariant PlaylistTableModel::data(const QModelIndex &index, int role) const
if (role == Qt::DisplayRole) {
const Song &song = songs.at(index.row());
switch (index.column()) {
case COL_TITLE:
return song.title; // displayTitle();
break;
case COL_ARTIST:
return song.artist; // albumArtist();
break;
case COL_TITLE: {
QString title=song.title;
if (title.isEmpty()) {
title=StreamsModel::self()->name(song.file);
return title.isEmpty() ? song.file : song.title;
}
return title;
}
case COL_ARTIST: {
QString artist=song.artist;
if (artist.isEmpty()) {
QString streamName=StreamsModel::self()->name(song.file);
if (streamName.isEmpty()) {
return QString();
}
#ifdef ENABLE_KDE_SUPPORT
return i18n("%1 (Stream)", streamName);
#else
return tr("%1 (Stream)").arg(streamName);
#endif
}
return artist;
}
case COL_ALBUM:
return song.album;
break;
case COL_TRACK:
if (song.track <= 0)
return QVariant();
return song.track;
break;
case COL_LENGTH:
return Song::formattedTime(song.time);
break;
case COL_DISC:
if (song.disc <= 0)
return QVariant();
return song.disc;
break;
case COL_YEAR:
if (song.year <= 0)
return QVariant();
return song.year;
break;
default:
break;
}

144
models/streamsmodel.cpp Normal file
View File

@@ -0,0 +1,144 @@
/*
* Cantata
*
* Copyright (c) 2011 Craig Drummond <craig.p.drummond@gmail.com>
*
* ----
*
* 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include <QtCore/QModelIndex>
#include "streamsmodel.h"
#include "settings.h"
#include <QDebug>
#ifdef ENABLE_KDE_SUPPORT
#include <KDE/KStandardDirs>
#include <KDE/KGlobal>
K_GLOBAL_STATIC(StreamsModel, instance)
#else
#endif
StreamsModel * StreamsModel::self()
{
#ifdef ENABLE_KDE_SUPPORT
return instance;
#else
static StreamsModel *instance=0;;
if(!instance) {
instance=new StreamsModel;
}
return instance;
#endif
}
StreamsModel::StreamsModel()
: QAbstractListModel(0)
{
reload();
}
StreamsModel::~StreamsModel()
{
}
QVariant StreamsModel::headerData(int /*section*/, Qt::Orientation /*orientation*/, int /*role*/) const
{
return QVariant();
}
int StreamsModel::rowCount(const QModelIndex &) const
{
return items.size();
}
QVariant StreamsModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) {
return QVariant();
}
if (index.row() >= items.size()) {
return QVariant();
}
if (Qt::DisplayRole == role) {
return items.at(index.row()).name;
} else if(Qt::ToolTipRole == role) {
return items.at(index.row()).url;
}
return QVariant();
}
static const QLatin1String constNameQuery("CantataStreamName");
void StreamsModel::reload()
{
beginResetModel();
QList<QUrl> urls=Settings::self()->streamUrls();
items.clear();
itemMap.clear();
foreach (const QUrl &u, urls) {
QUrl url(u);
QString name=url.queryItemValue(constNameQuery);
if (!name.isEmpty()) {
url.removeQueryItem(constNameQuery);
items.append(Stream(name, url));
itemMap.insert(url.toString(), name);
}
}
endResetModel();
}
void StreamsModel::save()
{
QList<QUrl> urls;
foreach (const Stream &s, items) {
QUrl u(s.url);
u.addQueryItem(constNameQuery, s.name);
urls.append(u);
}
Settings::self()->saveStreamUrls(urls);
}
bool StreamsModel::add(const QString &name, const QString &url)
{
QUrl u(url);
foreach (const Stream &s, items) {
if (s.name==name || s.url==url) {
return false;
}
}
int row=items.count();
beginInsertRows(createIndex(0, 0), row, row); // ????
items.append(Stream(name, u));
endInsertRows();
emit layoutChanged();
return true;
}
QString StreamsModel::name(const QString &url)
{
QHash<QString, QString>::ConstIterator it=itemMap.find(url);
return it==itemMap.end() ? QString() : it.value();
}

58
models/streamsmodel.h Normal file
View File

@@ -0,0 +1,58 @@
/*
* Cantata
*
* Copyright (c) 2011 Craig Drummond <craig.p.drummond@gmail.com>
*
* ----
*
* 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef STREAMSMODEL_H
#define STREAMSMODEL_H
#include <QtCore/QAbstractListModel>
#include <QtCore/QList>
#include <QtCore/QUrl>
#include <QtCore/QHash>
class StreamsModel : public QAbstractListModel
{
public:
struct Stream
{
Stream(const QString &n, const QUrl &u) : name(n), url(u) { }
QString name;
QUrl url;
};
static StreamsModel * self();
StreamsModel();
~StreamsModel();
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &, int) const;
void reload();
void save();
bool add(const QString &name, const QString &url);
QString name(const QString &url);
private:
QHash<QString, QString> itemMap;
QList<Stream> items;
};
#endif

View File

@@ -0,0 +1,31 @@
/*
* Cantata
*
* Copyright (c) 2011 Craig Drummond <craig.p.drummond@gmail.com>
*
* ----
*
* 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "streamsproxymodel.h"
StreamsProxyModel::StreamsProxyModel(QObject *parent) : QSortFilterProxyModel(parent)
{
setDynamicSortFilter(true);
setFilterCaseSensitivity(Qt::CaseInsensitive);
setSortCaseSensitivity(Qt::CaseInsensitive);
setSortLocaleAware(true);
}

View File

@@ -0,0 +1,35 @@
/*
* Cantata
*
* Copyright (c) 2011 Craig Drummond <craig.p.drummond@gmail.com>
*
* ----
*
* 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef STREAMSPROXYMODEL_H
#define STREAMSPROXYMODEL_H
#include <QtGui/QSortFilterProxyModel>
class StreamsProxyModel : public QSortFilterProxyModel
{
public:
StreamsProxyModel(QObject *parent = 0);
};
#endif