From 1deef1baecf73f1e42e9ce626e9cee1274995c8a Mon Sep 17 00:00:00 2001 From: craig Date: Wed, 14 Dec 2011 19:38:56 +0000 Subject: [PATCH] Add option to set stream as favourite --- TODO | 1 - gui/streamdialog.cpp | 28 ++++++++++------ gui/streamdialog.h | 12 ++++--- gui/streamspage.cpp | 63 ++++++++++++++++++++++++++++++------ gui/streamspage.h | 7 +++- models/streamsmodel.cpp | 50 +++++++++++++++++++++------- models/streamsmodel.h | 9 ++++-- models/streamsproxymodel.cpp | 10 ++++++ models/streamsproxymodel.h | 1 + 9 files changed, 143 insertions(+), 38 deletions(-) diff --git a/TODO b/TODO index d352f4ea6..be395d9e5 100644 --- a/TODO +++ b/TODO @@ -7,7 +7,6 @@ - Handle xspf/spiff playlists - Handle more than 1st entry?? Not sure - Check that MPD can handle protocols before adding - - Add option to makr stream as 'favourite'. If so, place at top of list and show KDE favourite icon * Library browser - Have artist icons ? diff --git a/gui/streamdialog.cpp b/gui/streamdialog.cpp index ef6ca6366..80ef041cf 100644 --- a/gui/streamdialog.cpp +++ b/gui/streamdialog.cpp @@ -42,10 +42,11 @@ StreamDialog::StreamDialog(QWidget *parent) #endif { QWidget *wid = new QWidget(this); - QFormLayout *layout=new QFormLayout(wid); + QFormLayout *layout = new QFormLayout(wid); - nameEntry=new LineEdit(wid); - urlEntry=new LineEdit(wid); + nameEntry = new LineEdit(wid); + urlEntry = new LineEdit(wid); + fav = new QCheckBox(wid); #ifdef ENABLE_KDE_SUPPORT layout->setWidget(0, QFormLayout::LabelRole, new QLabel(i18n("Name:"), wid)); #else @@ -59,7 +60,12 @@ StreamDialog::StreamDialog(QWidget *parent) #endif layout->setWidget(1, QFormLayout::FieldRole, urlEntry); urlEntry->setMinimumWidth(300); - +#ifdef ENABLE_KDE_SUPPORT + layout->setWidget(2, QFormLayout::LabelRole, new QLabel(i18n("Favorite:"), wid)); +#else + layout->setWidget(2, QFormLayout::LabelRole, new QLabel(tr("Favorite:"), wid)); +#endif + layout->setWidget(2, QFormLayout::FieldRole, fav); #ifdef ENABLE_KDE_SUPPORT setMainWidget(wid); setButtons(KDialog::Ok|KDialog::Cancel); @@ -75,11 +81,13 @@ StreamDialog::StreamDialog(QWidget *parent) connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); #endif - connect(nameEntry, SIGNAL(textChanged(const QString &)), SLOT(textChanged())); - connect(urlEntry, SIGNAL(textChanged(const QString &)), SLOT(textChanged())); + connect(nameEntry, SIGNAL(textChanged(const QString &)), SLOT(changed())); + connect(urlEntry, SIGNAL(textChanged(const QString &)), SLOT(changed())); + connect(fav, SIGNAL(toggled(bool)), SLOT(changed())); + prevFav=false; } -void StreamDialog::setEdit(const QString &editName, const QString &editUrl) +void StreamDialog::setEdit(const QString &editName, const QString &editUrl, bool f) { #ifdef ENABLE_KDE_SUPPORT setCaption(i18n("Edit Stream")); @@ -90,15 +98,17 @@ void StreamDialog::setEdit(const QString &editName, const QString &editUrl) #endif prevName=editName; prevUrl=editUrl; + prevFav=f; nameEntry->setText(editName); urlEntry->setText(editUrl); + fav->setChecked(f); } -void StreamDialog::textChanged() +void StreamDialog::changed() { QString n=name(); QString u=url(); - bool enableOk=!n.isEmpty() && !u.isEmpty() && (n!=prevName || u!=prevUrl); + bool enableOk=!n.isEmpty() && !u.isEmpty() && (n!=prevName || u!=prevUrl || fav->isChecked()!=prevFav); #ifdef ENABLE_KDE_SUPPORT enableButton(KDialog::Ok, enableOk); #else diff --git a/gui/streamdialog.h b/gui/streamdialog.h index 5feeea33a..4853b8c0d 100644 --- a/gui/streamdialog.h +++ b/gui/streamdialog.h @@ -31,6 +31,7 @@ class QDialogButtonBox; #endif #include "lineedit.h" +#include #ifdef ENABLE_KDE_SUPPORT class StreamDialog : public KDialog @@ -43,22 +44,25 @@ class StreamDialog : public QDialog public: StreamDialog(QWidget *parent); - void setEdit(const QString &editName, const QString &editUrl); + void setEdit(const QString &editName, const QString &editUrl, bool f); - QString name() { return nameEntry->text().trimmed(); } - QString url() { return urlEntry->text().trimmed(); } + QString name() const { return nameEntry->text().trimmed(); } + QString url() const { return urlEntry->text().trimmed(); } + bool favorite() const { return fav->isChecked(); } private Q_SLOTS: - void textChanged(); + void changed(); private: QString prevName; QString prevUrl; + bool prevFav; #ifndef ENABLE_KDE_SUPPORT QDialogButtonBox *buttonBox; #endif LineEdit *nameEntry; LineEdit *urlEntry; + QCheckBox *fav; }; #endif diff --git a/gui/streamspage.cpp b/gui/streamspage.cpp index cdd41c090..9f02233f3 100644 --- a/gui/streamspage.cpp +++ b/gui/streamspage.cpp @@ -54,18 +54,27 @@ StreamsPage::StreamsPage(MainWindow *p) removeAction->setText(i18n("Remove Stream")); editAction = p->actionCollection()->addAction("editstream"); editAction->setText(i18n("Edit Stream")); + editAction = p->actionCollection()->addAction("editstream"); + editAction->setText(i18n("Edit Stream")); + markAsFavAction = p->actionCollection()->addAction("markasfav"); + markAsFavAction->setText(i18n("Set As Favorite")); + unMarkAsFavAction = p->actionCollection()->addAction("unmarkasfav"); + unMarkAsFavAction->setText(i18n("Unset As Favorite")); #else importAction = new QAction(tr("Import Streams"), this); exportAction = new QAction(tr("Export Streams"), this); addAction = new QAction(tr("Add Stream"), this); removeAction = new QAction(tr("Remove Stream"), this); editAction = new QAction(tr("Rename Stream"), this); + markAsFavAction = new QAction(tr("Set As Favorite"), this); + unMarkAsFavAction = new QAction(tr("Unset As Favorite"), this); #endif importAction->setIcon(QIcon::fromTheme("document-import")); exportAction->setIcon(QIcon::fromTheme("document-export")); addAction->setIcon(QIcon::fromTheme("list-add")); removeAction->setIcon(QIcon::fromTheme("list-remove")); editAction->setIcon(QIcon::fromTheme("document-edit")); + markAsFavAction->setIcon(QIcon::fromTheme("emblem-favorite")); importStreams->setDefaultAction(importAction); exportStreams->setDefaultAction(exportAction); addStream->setDefaultAction(addAction); @@ -84,7 +93,9 @@ StreamsPage::StreamsPage(MainWindow *p) connect(editAction, SIGNAL(triggered(bool)), this, SLOT(edit())); connect(importAction, SIGNAL(triggered(bool)), this, SLOT(importXml())); connect(exportAction, SIGNAL(triggered(bool)), this, SLOT(exportXml())); - connect(view, SIGNAL(itemsSelected(bool)), SLOT(controlEdit())); + connect(markAsFavAction, SIGNAL(triggered(bool)), this, SLOT(markAsFav())); + connect(unMarkAsFavAction, SIGNAL(triggered(bool)), this, SLOT(unMarkAsFav())); + connect(view, SIGNAL(itemsSelected(bool)), SLOT(controlActions())); importStreams->setAutoRaise(true); exportStreams->setAutoRaise(true); addStream->setAutoRaise(true); @@ -109,6 +120,8 @@ StreamsPage::StreamsPage(MainWindow *p) view->addAction(editAction); view->addAction(removeAction); view->addAction(exportAction); + view->addAction(markAsFavAction); + view->addAction(unMarkAsFavAction); proxy.setSourceModel(&model); view->setModel(&proxy); } @@ -212,7 +225,7 @@ void StreamsPage::add() return; } - if (!model.add(name, url)) { + if (!model.add(name, url, dlg.favorite())) { #ifdef ENABLE_KDE_SUPPORT KMessageBox::error(this, i18n("A stream named %1 already exists!", name)); #else @@ -268,17 +281,19 @@ void StreamsPage::edit() StreamDialog dlg(this); QModelIndex index=proxy.mapToSource(selected.first()); - QString name=model.data(index, Qt::DisplayRole).toString(); - QString url=model.data(index, Qt::ToolTipRole).toString(); + StreamsModel::Stream *stream=static_cast(index.internalPointer()); + QString name=stream->name; + QString url=stream->url.toString(); + bool fav=stream->favorite; - dlg.setEdit(name, url); + dlg.setEdit(name, url, fav); if (QDialog::Accepted==dlg.exec()) { QString newName=dlg.name(); QString newUrl=dlg.url(); QString existingNameForUrl=newUrl!=url ? model.name(newUrl) : QString(); - +// if (!existingNameForUrl.isEmpty()) { #ifdef ENABLE_KDE_SUPPORT KMessageBox::error(this, i18n("Stream already exists!
%1", existingNameForUrl)); @@ -292,17 +307,47 @@ void StreamsPage::edit() QMessageBox::critical(this, tr("Error"), tr("A stream named %1 already exists!").arg(newName)); #endif } else { - model.edit(index, newName, newUrl); + model.edit(index, newName, newUrl, dlg.favorite()); } } } -void StreamsPage::controlEdit() +void StreamsPage::controlActions() { - editAction->setEnabled(1==view->selectionModel()->selectedIndexes().size()); + QModelIndexList selected=view->selectionModel()->selectedIndexes(); + editAction->setEnabled(1==selected.size()); + bool doneMark=false, doneUnMark=false; + markAsFavAction->setEnabled(false); + unMarkAsFavAction->setEnabled(false); + foreach (const QModelIndex &idx, selected) { + QModelIndex index=proxy.mapToSource(idx); + StreamsModel::Stream *stream=static_cast(index.internalPointer()); + if (stream->favorite) { + unMarkAsFavAction->setEnabled(true); + doneUnMark=true; + } else { + markAsFavAction->setEnabled(true); + doneMark=true; + } + if (doneUnMark && doneMark) { + break; + } + } } void StreamsPage::searchItems() { proxy.setFilterRegExp(search->text()); } + +void StreamsPage::mark(bool f) +{ + QModelIndexList selected=view->selectionModel()->selectedIndexes(); + QList rows; + foreach (const QModelIndex &idx, selected) { + QModelIndex index=proxy.mapToSource(idx); + rows << index.row(); + } + model.mark(rows, f); +} + diff --git a/gui/streamspage.h b/gui/streamspage.h index 611d72158..5a0643f1b 100644 --- a/gui/streamspage.h +++ b/gui/streamspage.h @@ -50,8 +50,11 @@ private Q_SLOTS: void add(); void remove(); void edit(); - void controlEdit(); + void controlActions(); void searchItems(); + void markAsFav() { mark(true); } + void unMarkAsFav() { mark(false); } + void mark(bool f); private: Action *importAction; @@ -59,6 +62,8 @@ private: Action *addAction; Action *removeAction; Action *editAction; + Action *markAsFavAction; + Action *unMarkAsFavAction; StreamsModel model; StreamsProxyModel proxy; }; diff --git a/models/streamsmodel.cpp b/models/streamsmodel.cpp index 1cb85a4b6..fb050f685 100644 --- a/models/streamsmodel.cpp +++ b/models/streamsmodel.cpp @@ -31,11 +31,11 @@ #include #include #include +#include #include "streamsmodel.h" #include "settings.h" #include "playlisttablemodel.h" #include "config.h" -#include static QString configDir() { @@ -70,6 +70,16 @@ int StreamsModel::rowCount(const QModelIndex &) const return items.size(); } +QModelIndex StreamsModel::index(int row, int column, const QModelIndex &parent) const +{ + Q_UNUSED(parent) + + if(row &rows, bool f) +{ + beginResetModel(); + foreach (int r, rows) { + items[r].favorite=f; + } + endResetModel(); +} diff --git a/models/streamsmodel.h b/models/streamsmodel.h index e924390e1..84df10b3a 100644 --- a/models/streamsmodel.h +++ b/models/streamsmodel.h @@ -37,27 +37,30 @@ class StreamsModel : public QAbstractListModel public: struct Stream { - Stream(const QString &n, const QUrl &u) : name(n), url(u) { } + Stream(const QString &n, const QUrl &u, bool fav) : name(n), url(u), favorite(fav) { } QString name; QUrl url; + bool favorite; }; StreamsModel(); ~StreamsModel(); QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; int rowCount(const QModelIndex &parent = QModelIndex()) const; + QModelIndex index(int row, int column, const QModelIndex &parent) const; QVariant data(const QModelIndex &, int) const; void reload(); void save(bool force=false); bool save(const QString &filename); bool import(const QString &filename) { return load(filename, false); } - bool add(const QString &name, const QString &url); - void edit(const QModelIndex &index, const QString &name, const QString &url); + bool add(const QString &name, const QString &url, bool fav); + void edit(const QModelIndex &index, const QString &name, const QString &url, bool fav); void remove(const QModelIndex &index); QString name(const QString &url); bool entryExists(const QString &name, const QUrl &url=QUrl()); Qt::ItemFlags flags(const QModelIndex &index) const; QMimeData * mimeData(const QModelIndexList &indexes) const; + void mark(const QList &rows, bool f); private: bool load(const QString &filename, bool isInternal); diff --git a/models/streamsproxymodel.cpp b/models/streamsproxymodel.cpp index d69b887cb..b30e5c0d2 100644 --- a/models/streamsproxymodel.cpp +++ b/models/streamsproxymodel.cpp @@ -21,6 +21,7 @@ * Boston, MA 02110-1301, USA. */ #include "streamsproxymodel.h" +#include "streamsmodel.h" StreamsProxyModel::StreamsProxyModel(QObject *parent) : QSortFilterProxyModel(parent) { @@ -30,3 +31,12 @@ StreamsProxyModel::StreamsProxyModel(QObject *parent) : QSortFilterProxyModel(pa setSortLocaleAware(true); sort(0); } + +bool StreamsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const +{ + StreamsModel::Stream *l=static_cast(left.internalPointer()); + StreamsModel::Stream *r=static_cast(right.internalPointer()); + + return l->favorite > r->favorite + || (l->favorite==r->favorite && l->name.localeAwareCompare(r->name)<0); +} \ No newline at end of file diff --git a/models/streamsproxymodel.h b/models/streamsproxymodel.h index 865f7716f..2f505cad8 100644 --- a/models/streamsproxymodel.h +++ b/models/streamsproxymodel.h @@ -30,6 +30,7 @@ class StreamsProxyModel : public QSortFilterProxyModel { public: StreamsProxyModel(QObject *parent = 0); + bool lessThan(const QModelIndex &left, const QModelIndex &right) const; }; #endif