From d93f2ee188f056ac7d59de930a33019ea8bb4996 Mon Sep 17 00:00:00 2001 From: Thomas Frauendorfer Date: Fri, 8 Feb 2008 14:36:30 +0100 Subject: [PATCH] Implement creation, deletion and switching of playlists (Idlists) --- README | 2 +- lib/lib.pro | 2 + lib/xclient.cpp | 4 +- lib/xclient.h | 6 ++ lib/xcollection.cpp | 145 ++++++++++++++++++++++++++++++++ lib/xcollection.h | 51 +++++++++++ lib/xconfig.cpp | 2 +- src/dialogs/dialogs.pri | 8 ++ src/dialogs/playlistchooser.cpp | 132 +++++++++++++++++++++++++++++ src/dialogs/playlistchooser.h | 46 ++++++++++ src/dialogs/playlistchooser.ui | 108 ++++++++++++++++++++++++ src/playlist/playlistwidget.cpp | 10 +++ src/playlist/playlistwidget.h | 3 + src/src.pri | 1 + 14 files changed, 517 insertions(+), 3 deletions(-) create mode 100644 lib/xcollection.cpp create mode 100644 lib/xcollection.h create mode 100644 src/dialogs/dialogs.pri create mode 100644 src/dialogs/playlistchooser.cpp create mode 100644 src/dialogs/playlistchooser.h create mode 100644 src/dialogs/playlistchooser.ui diff --git a/README b/README index 899f4df..a4f352c 100644 --- a/README +++ b/README @@ -16,4 +16,4 @@ Compiling: Known bugs: Tons of them. - + diff --git a/lib/lib.pro b/lib/lib.pro index 6a97f62..9e78fc2 100644 --- a/lib/lib.pro +++ b/lib/lib.pro @@ -8,6 +8,7 @@ OBJECTS_DIR = .obj SOURCES += xclient.cpp \ xclientcache.cpp \ xconfig.cpp \ + xcollection.cpp \ playlistmodel.cpp \ xmmsqt4.cpp @@ -15,6 +16,7 @@ SOURCES += xclient.cpp \ HEADERS += xclient.h \ xclientcache.h \ xconfig.h \ + xcollection.h \ playlistmodel.h \ xmmsqt4.h \ debug.h diff --git a/lib/xclient.cpp b/lib/xclient.cpp index a8450eb..93c7b56 100644 --- a/lib/xclient.cpp +++ b/lib/xclient.cpp @@ -24,6 +24,7 @@ #include #include "xclient.h" +#include "xcollection.h" #include "xmmsqt4.h" #include "debug.h" @@ -74,6 +75,7 @@ XClient::XClient (QObject *parent, const std::string &name) : QObject (parent), m_isconnected = false; m_cache = new XClientCache (this, this); m_config = new XConfig (this, this); + m_collection = new XCollection (this); m_name = name; } @@ -128,7 +130,7 @@ try_again: qWarning ("Couldn't establish sync connection!"); } } - + m_isconnected = true; emit gotConnection (this); diff --git a/lib/xclient.h b/lib/xclient.h index 980133f..9d41273 100644 --- a/lib/xclient.h +++ b/lib/xclient.h @@ -32,6 +32,7 @@ class XClient; #include "xconfig.h" class XConfig; +class XCollection; /* class XSettings : public QObject @@ -73,6 +74,10 @@ class XClient : public QObject { return m_config; }; + XCollection *xcollection () const { + return m_collection; + } + const Xmms::Client *sync () const { return &m_sync; }; @@ -106,6 +111,7 @@ class XClient : public QObject { // Xmms::Client *m_client; XClientCache *m_cache; XConfig *m_config; + XCollection *m_collection; bool m_isconnected; Xmms::Client m_sync; diff --git a/lib/xcollection.cpp b/lib/xcollection.cpp new file mode 100644 index 0000000..7c23e6b --- /dev/null +++ b/lib/xcollection.cpp @@ -0,0 +1,145 @@ +/** + * This file is a part of Promoe, an XMMS2 Client. + * + * Copyright (C) 2008 Thomas Frauendorfer + * + * 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; version 2 of the License. + * + * 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. + */ + +#include "xcollection.h" + +#include +#include + +XCollection::XCollection (XClient * client) : QObject ( client) +{ + m_client = client; + + connect (client, SIGNAL (gotConnection (XClient *)), + this, SLOT (on_connect (XClient *))); + + if (client->isConnected ()) { + on_connect (client); + } +} + +void +XCollection::on_connect (XClient *client) +{ + client->collection ()->broadcastCollectionChanged () + (Xmms::bind (&XCollection::on_collection_modified, this)); + + client->collection ()->list ("Playlists") + (Xmms::bind (&XCollection::handle_playlists_list, this)); + + m_client = client; +} + +bool +XCollection::on_collection_modified (const Xmms::Dict &value) +{ + QString newname = QString (); + QHash tmp = XClient::convert_dict (value); + int type = tmp["type"].toInt (); + QString name = tmp["name"].toString (); + + // FIXME: handle other namespaces than "Playlists" + if (tmp["namespace"].toString () != "Playlists") { + return true; + } + + if (type == XMMS_COLLECTION_CHANGED_RENAME) + newname = tmp["newname"].toString (); + + // FIXME: use namespace parameter + switch (type) { + case XMMS_COLLECTION_CHANGED_ADD: + m_playlists.append (name); + break; + case XMMS_COLLECTION_CHANGED_REMOVE: + m_playlists.removeAll (name); + break; + case XMMS_COLLECTION_CHANGED_RENAME: + m_playlists.removeAll (name); + m_playlists.append (newname); + break; + case XMMS_COLLECTION_CHANGED_UPDATE: + // do nothing here + break; + default: + qDebug ("Unhandled collection change type %i", type); + } + + m_playlists.sort (); + +/* + qDebug ("---"); + foreach (QString s, m_playlists) { + qDebug (s.toAscii ()); + } +*/ + + emit collectionModified (tmp["name"].toString (), + tmp["namespace"].toString (), + type, newname); + + return true; +} + +bool +XCollection::handle_playlists_list (const Xmms::List< std::string > &list) +{ + m_playlists.clear (); + + for (list.first (); list.isValid (); ++list) { + m_playlists.append (XClient::stdToQ(*list)); + } + m_playlists.sort (); + + return true; +} + + +QStringList +XCollection::list (QString ns) { + // FIXME: use the ns parameter. + // We will need to handle querying the serverside playlists bettter... + return m_playlists; +} + + +// FIXME: Probably should be in another file +bool +XCollection::setActivePlaylist (QString name) { + if (!m_client->isConnected ()) return false; + + m_client->playlist ()->load (name.toStdString ()); + + return true; +} + +// FIXME: should be done in a more generic way +bool +XCollection::addIdlist (QString name) { + if (!m_client->isConnected ()) return false; + + m_client->playlist ()->create (name.toStdString ()); + + return true; +} + +bool +XCollection::remove (QString name, QString ns) { + if (!m_client->isConnected ()) return false; + + m_client->collection ()->remove (name.toStdString (), ns.toAscii ()); + + return true; +} diff --git a/lib/xcollection.h b/lib/xcollection.h new file mode 100644 index 0000000..97dde19 --- /dev/null +++ b/lib/xcollection.h @@ -0,0 +1,51 @@ +/** + * This file is a part of Promoe, an XMMS2 Client. + * + * Copyright (C) 2008 Thomas Frauendorfer + * + * 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; version 2 of the License. + * + * 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. + */ + +#ifndef __XCollection_H__ +#define __XCollection_H__ + +#include "xclient.h" + +#include +class QString; +class QStringList; + +class XCollection : public QObject +{ + Q_OBJECT + + public: + XCollection (XClient *client); + QStringList list (QString ns = "Playlists"); + + bool setActivePlaylist (QString name); + bool addIdlist (QString name); + bool remove (QString name, QString ns); + + signals: + void collectionModified (QString collection, QString ns, int type, + QString newname); + + protected slots: + void on_connect (XClient *); + + private: + bool on_collection_modified (const Xmms::Dict &value); + bool handle_playlists_list (const Xmms::List< std::string > &list); + XClient *m_client; + QStringList m_playlists; +}; + +#endif diff --git a/lib/xconfig.cpp b/lib/xconfig.cpp index 5cf1821..80784ab 100644 --- a/lib/xconfig.cpp +++ b/lib/xconfig.cpp @@ -49,7 +49,7 @@ XConfig::value_get (QString key) bool XConfig::value_set (QString key, QString val) { - /* Only send change request to server here + /* Only send change request to server from here * update of local cache will be done through handle_config_value_changed */ if (!m_client->isConnected ()) { diff --git a/src/dialogs/dialogs.pri b/src/dialogs/dialogs.pri new file mode 100644 index 0000000..15b00ab --- /dev/null +++ b/src/dialogs/dialogs.pri @@ -0,0 +1,8 @@ +HEADERS += playlistchooser.h + +SOURCES += playlistchooser.cpp + +FORMS += playlistchooser.ui + +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD diff --git a/src/dialogs/playlistchooser.cpp b/src/dialogs/playlistchooser.cpp new file mode 100644 index 0000000..c154639 --- /dev/null +++ b/src/dialogs/playlistchooser.cpp @@ -0,0 +1,132 @@ +/** + * This file is a part of Promoe, an XMMS2 client + * + * Copyright (C) 2008 Thomas Frauendorfer + * + * 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. + */ + +// FIXME: because somewhere something with the includes is wrons, this line +// is needed +#include "XMMSHandler.h" + +#include +#include +#include +#include + +#include "playlistchooser.h" + +#include "xcollection.h" + +PlaylistChooser::PlaylistChooser (QWidget *parent, XCollection *coll) + : QDialog (parent) +{ + setupUi (this); + setAttribute (Qt::WA_DeleteOnClose); + + m_collection = coll; + + // FIXME: implement creation of new Playlists +// playlistCreateButton->setEnabled (false); +// playlistRemoveButton->setEnabled (false); + + // fill the List with Playlistnames. + // Sort out playlists that start with '_' + QRegExp regex = QRegExp ("^[^_]"); + QStringList lists = coll->list ("Playlists").filter (regex); + playlistsListWidget->setSortingEnabled (true); + playlistsListWidget->addItems (lists); + connect (coll, SIGNAL (collectionModified (QString, QString, int, QString)), + this, SLOT (handle_playlists_modified (QString, QString, int, + QString))); + +} + +void +PlaylistChooser::handle_playlists_modified (QString name, QString ns, + int type, QString newname) +{ + if (ns != "Playlists") { + return; + } + + switch (type) { + case XMMS_COLLECTION_CHANGED_ADD: + if (!name.startsWith("_")) { + playlistsListWidget->addItem(name); + } + break; + case XMMS_COLLECTION_CHANGED_REMOVE: { + QList list + = playlistsListWidget->findItems (name, Qt::MatchExactly); + if (!list.empty ()) { + // we should only have one exatly matching String + QListWidgetItem* item = list.first (); + int idx = playlistsListWidget->row (item); + item = playlistsListWidget->takeItem (idx); + delete item; + } + } + break; + case XMMS_COLLECTION_CHANGED_RENAME: { + // remove the old entry + QList list + = playlistsListWidget->findItems (name, Qt::MatchExactly); + if (!list.empty ()) { + // we should only have one exatly matching String + QListWidgetItem* item = list.first (); + int idx = playlistsListWidget->row (item); + item = playlistsListWidget->takeItem (idx); + delete item; + } + // and add the new one + if (!newname.startsWith("_")) { + playlistsListWidget->addItem(newname); + } + } + break; + + default: + break; + } +} + + +void +PlaylistChooser::on_playlistCreateButton_clicked () +{ + QString name = playlistTextEdit->text (); + // only create new playlist, if it doesn't already exist + if (m_collection->list ("Playlists").contains (name)) return; + + m_collection->addIdlist (name); +} + +void +PlaylistChooser::on_playlistRemoveButton_clicked () +{ + QList list = playlistsListWidget->selectedItems (); + if (list.empty ()) return; // nothing to do + + // TODO: if we change the selectionmodel to multiselection, + // change this tp remove more than one item + QListWidgetItem* item = list.first (); + QString name = item->text (); + m_collection->remove (name, "Playlists"); +} + +void +PlaylistChooser::on_playlistsListWidget_itemDoubleClicked (QListWidgetItem* item) +{ + QString name = item->text (); + m_collection->setActivePlaylist (name); +} diff --git a/src/dialogs/playlistchooser.h b/src/dialogs/playlistchooser.h new file mode 100644 index 0000000..225067f --- /dev/null +++ b/src/dialogs/playlistchooser.h @@ -0,0 +1,46 @@ +/** + * This file is a part of Promoe, an XMMS2 client + * + * Copyright (C) 2008 Thomas Frauendorfer + * + * 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. + */ + +#ifndef __PLAYLISTCHOOSER_H__ +#define __PLAYLISTCHOOSER_H__ + +#include "ui_playlistchooser.h" + +#include +class QListWidgetItem; + +class XCollection; + +class PlaylistChooser : public QDialog, private Ui::PlaylistChooser { + Q_OBJECT + + public: + PlaylistChooser (QWidget *parent, XCollection *coll); + + + private slots: + void handle_playlists_modified (QString, QString, int, QString); + + void on_playlistCreateButton_clicked (); + void on_playlistRemoveButton_clicked (); + + void on_playlistsListWidget_itemDoubleClicked (QListWidgetItem* item); + + private: + XCollection* m_collection; +}; + +#endif diff --git a/src/dialogs/playlistchooser.ui b/src/dialogs/playlistchooser.ui new file mode 100644 index 0000000..2c52be3 --- /dev/null +++ b/src/dialogs/playlistchooser.ui @@ -0,0 +1,108 @@ + + PlaylistChooser + + + + 0 + 0 + 260 + 301 + + + + Playlists + + + + + + + + + + + Create + + + + + + + + + Qt::ScrollBarAsNeeded + + + Qt::ScrollBarAlwaysOff + + + + + + + + + Remove + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Close + + + + + + + + + + + closeButton + clicked() + PlaylistChooser + close() + + + 217 + 279 + + + 129 + 124 + + + + + playlistsListWidget + currentTextChanged(QString) + playlistTextEdit + setText(QString) + + + 129 + 150 + + + 87 + 21 + + + + + diff --git a/src/playlist/playlistwidget.cpp b/src/playlist/playlistwidget.cpp index 4f9769b..91d12c8 100644 --- a/src/playlist/playlistwidget.cpp +++ b/src/playlist/playlistwidget.cpp @@ -26,6 +26,7 @@ #include "playlistshade.h" #include "playlistmenu.h" #include "FileDialog.h" +#include "playlistchooser.h" #include #include @@ -277,6 +278,8 @@ PlaylistWidget::addButtons (void) Skin::PLS_LST_DEC); b = new PlaylistMenuButton (m_lst, Skin::PLS_LST_NEW_0, Skin::PLS_LST_NEW_1); + connect (b, SIGNAL (activated ()), + this, SLOT(openPlaylistChooser ())); b = new PlaylistMenuButton (m_lst, Skin::PLS_LST_SAV_0, Skin::PLS_LST_SAV_1); b = new PlaylistMenuButton (m_lst, Skin::PLS_LST_OPN_0, @@ -505,3 +508,10 @@ PlaylistWidget::paintEvent (QPaintEvent *event) paint.end (); } +void +PlaylistWidget::openPlaylistChooser () +{ + XMMSHandler &client = XMMSHandler::getInstance (); + PlaylistChooser *tmp = new PlaylistChooser (this, client.xcollection ()); + tmp->show (); +} diff --git a/src/playlist/playlistwidget.h b/src/playlist/playlistwidget.h index 19e9efd..f2f0206 100644 --- a/src/playlist/playlistwidget.h +++ b/src/playlist/playlistwidget.h @@ -86,6 +86,9 @@ class PlaylistWidget : public QWidget { void menuAddDir (); void menuAddFile (); + protected slots: + void openPlaylistChooser (); + private: void resizeEvent (QResizeEvent *event); void paintEvent (QPaintEvent *event); diff --git a/src/src.pri b/src/src.pri index e4b8123..7882a4a 100644 --- a/src/src.pri +++ b/src/src.pri @@ -2,6 +2,7 @@ include($$PWD/widgets/widgets.pri) include($$PWD/mainwindow/mainwindow.pri) include($$PWD/playlist/playlist.pri) include($$PWD/equalizer/equalizer.pri) +include($$PWD/dialogs/dialogs.pri) HEADERS += PixWidget.h \ Skin.h \