Bookmark tuneIn categories
BUG:252
This commit is contained in:
committed by
craig.p.drummond
parent
cdb9a7e9e8
commit
bb69a08634
@@ -131,6 +131,11 @@ static QString categoryCacheName(const QString &name, bool createDir=false)
|
||||
return Utils::cacheDir(StreamsModel::constCacheDir, createDir)+name+StreamsModel::constCacheExt;
|
||||
}
|
||||
|
||||
static QString categoryBookmarksName(const QString &name, bool createDir=false)
|
||||
{
|
||||
return Utils::configDir(QLatin1String("bookmarks"), createDir)+name+StreamsModel::constCacheExt;
|
||||
}
|
||||
|
||||
void StreamsModel::CategoryItem::removeCache()
|
||||
{
|
||||
if (childrenHaveCache) {
|
||||
@@ -147,6 +152,97 @@ void StreamsModel::CategoryItem::removeCache()
|
||||
}
|
||||
}
|
||||
|
||||
void StreamsModel::CategoryItem::removeBookmarks()
|
||||
{
|
||||
if (bookmarksName.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
QString fileName=categoryBookmarksName(bookmarksName);
|
||||
if (QFile::exists(fileName)) {
|
||||
QFile::remove(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
void StreamsModel::CategoryItem::saveBookmarks()
|
||||
{
|
||||
if (bookmarksName.isEmpty() || !supportsBookmarks) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (Item *child, children) {
|
||||
if (child->isCategory()) {
|
||||
CategoryItem *cat=static_cast<CategoryItem *>(child);
|
||||
if (cat->isBookmarks) {
|
||||
if (cat->children.count()) {
|
||||
QFile file(categoryBookmarksName(bookmarksName, true));
|
||||
QtIOCompressor compressor(&file);
|
||||
compressor.setStreamFormat(QtIOCompressor::GzipFormat);
|
||||
if (compressor.open(QIODevice::WriteOnly)) {
|
||||
QXmlStreamWriter doc(&compressor);
|
||||
doc.writeStartDocument();
|
||||
doc.writeStartElement("bookmarks");
|
||||
doc.writeAttribute("version", "1.0");
|
||||
doc.setAutoFormatting(false);
|
||||
foreach (Item *i, cat->children) {
|
||||
doc.writeStartElement("bookmark");
|
||||
doc.writeAttribute("name", i->name);
|
||||
doc.writeAttribute("url", i->url);
|
||||
doc.writeEndElement();
|
||||
}
|
||||
doc.writeEndElement();
|
||||
doc.writeEndElement();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QList<StreamsModel::Item *> StreamsModel::CategoryItem::loadBookmarks()
|
||||
{
|
||||
QList<Item *> newItems;
|
||||
if (bookmarksName.isEmpty() || !supportsBookmarks) {
|
||||
return newItems;
|
||||
}
|
||||
|
||||
QString fileName=categoryBookmarksName(bookmarksName);
|
||||
if (!QFile::exists(fileName)) {
|
||||
return newItems;
|
||||
}
|
||||
|
||||
QFile file(fileName);
|
||||
QtIOCompressor compressor(&file);
|
||||
compressor.setStreamFormat(QtIOCompressor::GzipFormat);
|
||||
if (compressor.open(QIODevice::ReadOnly)) {
|
||||
QXmlStreamReader doc(&compressor);
|
||||
while (!doc.atEnd()) {
|
||||
doc.readNext();
|
||||
|
||||
if (doc.isStartElement() && QLatin1String("bookmark")==doc.name()) {
|
||||
QString name=doc.attributes().value("name").toString();
|
||||
QString url=doc.attributes().value("url").toString();
|
||||
if (!name.isEmpty() && !url.isEmpty()) {
|
||||
newItems.append(new CategoryItem(url, name, this));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return newItems;
|
||||
}
|
||||
|
||||
StreamsModel::CategoryItem * StreamsModel::CategoryItem::createBookmarksCategory()
|
||||
{
|
||||
Icon icon=Icon("bookmarks");
|
||||
if (icon.isNull()) {
|
||||
icon=Icon("user-bookmarks");
|
||||
}
|
||||
CategoryItem *bookmarkCat = new CategoryItem(QString(), i18n("Bookmarks"), this, icon);
|
||||
bookmarkCat->state=CategoryItem::Fetched;
|
||||
bookmarkCat->isBookmarks=true;
|
||||
return bookmarkCat;
|
||||
}
|
||||
|
||||
StreamsModel::StreamsModel(QObject *parent)
|
||||
: ActionModel(parent)
|
||||
, root(new CategoryItem(QString(), "root"))
|
||||
@@ -155,7 +251,9 @@ StreamsModel::StreamsModel(QObject *parent)
|
||||
, favouritesModified(false)
|
||||
, favouritesSaveTimer(0)
|
||||
{
|
||||
root->children.append(new CategoryItem(constRadioTimeUrl+QLatin1String("?locale=")+QLocale::system().name(), i18n("TuneIn"), root, getIcon("tunein")));
|
||||
CategoryItem *tuneIn=new CategoryItem(constRadioTimeUrl+QLatin1String("?locale=")+QLocale::system().name(), i18n("TuneIn"), root, getIcon("tunein"), QString(), "tunein");
|
||||
tuneIn->supportsBookmarks=true;
|
||||
root->children.append(tuneIn);
|
||||
root->children.append(new CategoryItem(constIceCastUrl, i18n("IceCast"), root, getIcon("icecast"), "icecast"));
|
||||
root->children.append(new CategoryItem(constShoutCastUrl, i18n("ShoutCast"), root, getIcon("shoutcast")));
|
||||
root->children.append(new CategoryItem(constSomaFMUrl, i18n("SomaFM"), root, getIcon("somafm"), "somafm"));
|
||||
@@ -469,6 +567,92 @@ void StreamsModel::updateFavouriteStream(Item *item)
|
||||
emit dataChanged(index, index);
|
||||
}
|
||||
|
||||
void StreamsModel::addBookmark(const QModelIndex &index)
|
||||
{
|
||||
Item *item=toItem(index);
|
||||
|
||||
if (item!=root && item->isCategory() && !item->url.isEmpty() && !root->children.contains(item) && static_cast<CategoryItem *>(item)->canBookmark) {
|
||||
CategoryItem *cat=item->parent;
|
||||
CategoryItem *bookmarkParentCat=0;
|
||||
while (cat && !bookmarkParentCat) {
|
||||
if (cat->supportsBookmarks) {
|
||||
bookmarkParentCat=cat;
|
||||
}
|
||||
cat=cat->parent;
|
||||
}
|
||||
|
||||
if (bookmarkParentCat) {
|
||||
CategoryItem *bookmarkCat=0;
|
||||
foreach (Item *i, bookmarkParentCat->children) {
|
||||
if (i->isCategory() && static_cast<CategoryItem *>(i)->isBookmarks) {
|
||||
bookmarkCat=static_cast<CategoryItem *>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bookmarkCat) {
|
||||
QModelIndex index=createIndex(bookmarkParentCat->parent->children.indexOf(bookmarkParentCat), 0, (void *)bookmarkParentCat);
|
||||
beginInsertRows(index, bookmarkParentCat->children.count(), bookmarkParentCat->children.count());
|
||||
bookmarkCat=bookmarkParentCat->createBookmarksCategory();
|
||||
bookmarkParentCat->children.append(bookmarkCat);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
foreach (Item *i, bookmarkCat->children) {
|
||||
if (i->url==item->url) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex index=createIndex(bookmarkCat->parent->children.indexOf(bookmarkCat), 0, (void *)bookmarkCat);
|
||||
beginInsertRows(index, bookmarkCat->children.count(), bookmarkCat->children.count());
|
||||
bookmarkCat->children.append(new CategoryItem(item->url, item->name, bookmarkCat));
|
||||
endInsertRows();
|
||||
bookmarkParentCat->saveBookmarks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StreamsModel::removeBookmark(const QModelIndex &index)
|
||||
{
|
||||
Item *item=toItem(index);
|
||||
|
||||
if (item->isCategory() && item->parent && item->parent->isBookmarks) {
|
||||
CategoryItem *bookmarkCat=item->parent; // 'Bookmarks'
|
||||
CategoryItem *cat=bookmarkCat->parent; // e.g. 'TuneIn'
|
||||
if (1==bookmarkCat->children.count()) { // Only 1 bookark, so remove 'Bookmarks' folder...
|
||||
int pos=cat->children.indexOf(bookmarkCat);
|
||||
QModelIndex index=createIndex(cat->parent->children.indexOf(cat), 0, (void *)cat);
|
||||
beginRemoveRows(index, pos, pos);
|
||||
delete cat->children.takeAt(pos);
|
||||
endRemoveRows();
|
||||
cat->removeBookmarks();
|
||||
} else if (!bookmarkCat->children.isEmpty()) { // More than 1 bookmark...
|
||||
int pos=bookmarkCat->children.indexOf(item);
|
||||
QModelIndex index=createIndex(bookmarkCat->parent->children.indexOf(bookmarkCat), 0, (void *)bookmarkCat);
|
||||
beginRemoveRows(index, pos, pos);
|
||||
delete bookmarkCat->children.takeAt(pos);
|
||||
endRemoveRows();
|
||||
cat->saveBookmarks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StreamsModel::removeAllBookmarks(const QModelIndex &index)
|
||||
{
|
||||
Item *item=toItem(index);
|
||||
|
||||
if (item->isCategory() && static_cast<CategoryItem *>(item)->isBookmarks) {
|
||||
CategoryItem *cat=item->parent; // e.g. 'TuneIn'
|
||||
int pos=cat->children.indexOf(item);
|
||||
QModelIndex index=createIndex(cat->parent->children.indexOf(cat), 0, (void *)cat);
|
||||
beginRemoveRows(index, pos, pos);
|
||||
delete cat->children.takeAt(pos);
|
||||
endRemoveRows();
|
||||
cat->removeBookmarks();
|
||||
}
|
||||
}
|
||||
|
||||
bool StreamsModel::importXml(const QString &fileName)
|
||||
{
|
||||
return loadXml(fileName, createIndex(root->children.indexOf(favourites), 0, favourites));
|
||||
@@ -611,6 +795,18 @@ void StreamsModel::jobFinished()
|
||||
saveCache(cat, newItems);
|
||||
}
|
||||
|
||||
if (cat && cat->parent==root && cat->supportsBookmarks) {
|
||||
QList<Item *> bookmarks=cat->loadBookmarks();
|
||||
if (bookmarks.count()) {
|
||||
CategoryItem *bookmarksCat=cat->createBookmarksCategory();
|
||||
foreach (Item *i, bookmarks) {
|
||||
i->parent=bookmarksCat;
|
||||
}
|
||||
bookmarksCat->children=bookmarks;
|
||||
newItems.append(bookmarksCat);
|
||||
}
|
||||
}
|
||||
|
||||
if (!newItems.isEmpty()) {
|
||||
beginInsertRows(index, cat->children.count(), (cat->children.count()+newItems.count())-1);
|
||||
cat->children+=newItems;
|
||||
@@ -657,6 +853,7 @@ QList<StreamsModel::Item *> StreamsModel::parseRadioTimeResponse(QIODevice *dev,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newItems;
|
||||
}
|
||||
|
||||
@@ -1137,7 +1334,9 @@ StreamsModel::Item * StreamsModel::parseRadioTimeEntry(QXmlStreamReader &doc, Ca
|
||||
if (isStation) {
|
||||
item=new Item(url, text, parent);
|
||||
} else {
|
||||
item=cat=new CategoryItem(url, text, parent);
|
||||
cat=new CategoryItem(url, text, parent);
|
||||
cat->canBookmark=!url.isEmpty();
|
||||
item=cat;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1316,6 +1515,9 @@ static void saveStream(QXmlStreamWriter &doc, const StreamsModel::Item *item)
|
||||
|
||||
static void saveCategory(QXmlStreamWriter &doc, const StreamsModel::CategoryItem *cat)
|
||||
{
|
||||
if (cat->isBookmarks) {
|
||||
return;
|
||||
}
|
||||
doc.writeStartElement("category");
|
||||
doc.writeAttribute("name", cat->name);
|
||||
if (cat->isAll) {
|
||||
|
||||
@@ -60,18 +60,28 @@ public:
|
||||
Fetched
|
||||
};
|
||||
|
||||
CategoryItem(const QString &u, const QString &n=QString(), CategoryItem *p=0, const QIcon &i=QIcon(), const QString &cn=QString())
|
||||
: Item(u, n, p), state(Initial), isFavourites(false), isAll(false), childrenHaveCache(false), icon(i), cacheName(cn) { }
|
||||
CategoryItem(const QString &u, const QString &n=QString(), CategoryItem *p=0, const QIcon &i=QIcon(),
|
||||
const QString &cn=QString(), const QString &bn=QString())
|
||||
: Item(u, n, p), state(Initial), isFavourites(false), isAll(false), isBookmarks(false),
|
||||
childrenHaveCache(false), supportsBookmarks(false), canBookmark(false), icon(i), cacheName(cn), bookmarksName(bn) { }
|
||||
virtual ~CategoryItem() { qDeleteAll(children); }
|
||||
virtual bool isCategory() const { return true; }
|
||||
void removeCache();
|
||||
void removeBookmarks();
|
||||
void saveBookmarks();
|
||||
QList<Item *> loadBookmarks();
|
||||
CategoryItem *createBookmarksCategory();
|
||||
State state;
|
||||
bool isFavourites : 1;
|
||||
bool isAll : 1;
|
||||
bool childrenHaveCache : 1;
|
||||
bool isBookmarks : 1; // 'Virtual' bookmarks category...
|
||||
bool childrenHaveCache : 1; // Only used for ListenLive - as each sub-category can have the cache
|
||||
bool supportsBookmarks : 1; // Intended for top-level items, indicates if bookmarks can be added
|
||||
bool canBookmark : 1; // Can this category be bookmark'ed in top-level parent?
|
||||
QList<Item *> children;
|
||||
QIcon icon;
|
||||
QString cacheName;
|
||||
QString bookmarksName;
|
||||
};
|
||||
|
||||
static const QString constPrefix;
|
||||
@@ -108,6 +118,10 @@ public:
|
||||
bool nameExistsInFavourites(const QString &n);
|
||||
void updateFavouriteStream(Item *item);
|
||||
|
||||
void addBookmark(const QModelIndex &index);
|
||||
void removeBookmark(const QModelIndex &index);
|
||||
void removeAllBookmarks(const QModelIndex &index);
|
||||
|
||||
bool importXml(const QString &fileName);
|
||||
bool saveXml(const QString &fileName, const QList<Item *> &items, bool format=true);
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ StreamsPage::StreamsPage(QWidget *p)
|
||||
addToFavouritesAction = ActionCollection::get()->createAction("addtofavourites", i18n("Add Stream To Favourites"), Icons::self()->addRadioStreamIcon);
|
||||
reloadAction = ActionCollection::get()->createAction("reloadstreams", i18n("Reload"), Icon("view-refresh"));
|
||||
editAction = ActionCollection::get()->createAction("editstream", i18n("Edit"), Icons::self()->editIcon);
|
||||
addBookmarkAction = ActionCollection::get()->createAction("bookmarkcategory", i18n("Bookmark Category"), Icon("bookmark-new"));
|
||||
Action *settingsAct = new Action(i18n("Digitally Imported Settings"), this);
|
||||
replacePlayQueue->setDefaultAction(StdActions::self()->replacePlayQueueAction);
|
||||
Action *searchAction = ActionCollection::get()->createAction("searchtunein", i18n("Search for Radio Stations via TuneIn"), Icons::self()->searchIcon);
|
||||
@@ -67,6 +68,7 @@ StreamsPage::StreamsPage(QWidget *p)
|
||||
connect(view, SIGNAL(searchItems()), this, SLOT(searchItems()));
|
||||
connect(view, SIGNAL(itemsSelected(bool)), SLOT(controlActions()));
|
||||
connect(addAction, SIGNAL(triggered(bool)), this, SLOT(add()));
|
||||
connect(addBookmarkAction, SIGNAL(triggered(bool)), this, SLOT(addBookmark()));
|
||||
connect(addToFavouritesAction, SIGNAL(triggered(bool)), this, SLOT(addToFavourites()));
|
||||
connect(reloadAction, SIGNAL(triggered(bool)), this, SLOT(reload()));
|
||||
connect(editAction, SIGNAL(triggered(bool)), this, SLOT(edit()));
|
||||
@@ -102,6 +104,7 @@ StreamsPage::StreamsPage(QWidget *p)
|
||||
view->addAction(editAction);
|
||||
view->addAction(StdActions::self()->removeAction);
|
||||
view->addAction(addToFavouritesAction);
|
||||
view->addAction(addBookmarkAction);
|
||||
view->addAction(reloadAction);
|
||||
proxy.setSourceModel(StreamsModel::self());
|
||||
view->setModel(&proxy);
|
||||
@@ -271,6 +274,17 @@ void StreamsPage::add()
|
||||
exportAction->setEnabled(StreamsModel::self()->haveFavourites());
|
||||
}
|
||||
|
||||
void StreamsPage::addBookmark()
|
||||
{
|
||||
QModelIndexList selected = view->selectedIndexes();
|
||||
|
||||
if (1!=selected.count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
StreamsModel::self()->addBookmark(proxy.mapToSource(selected.first()));
|
||||
}
|
||||
|
||||
void StreamsPage::addToFavourites()
|
||||
{
|
||||
if (!StreamsModel::self()->isFavoritesWritable()) {
|
||||
@@ -316,11 +330,32 @@ void StreamsPage::reload()
|
||||
|
||||
void StreamsPage::removeItems()
|
||||
{
|
||||
QModelIndexList selected = view->selectedIndexes();
|
||||
|
||||
if (1==selected.count()) {
|
||||
QModelIndex mapped=proxy.mapToSource(selected.first());
|
||||
const StreamsModel::Item *item=static_cast<const StreamsModel::Item *>(mapped.internalPointer());
|
||||
if (item->isCategory() && item->parent) {
|
||||
if (item->parent->isBookmarks) {
|
||||
if (MessageBox::No==MessageBox::warningYesNo(this, i18n("Are you sure you wish to remove bookmark to <b>%1</b>?").arg(item->name))) {
|
||||
return;
|
||||
}
|
||||
StreamsModel::self()->removeBookmark(mapped);
|
||||
return;
|
||||
} else if (static_cast<const StreamsModel::CategoryItem *>(item)->isBookmarks) {
|
||||
if (MessageBox::No==MessageBox::warningYesNo(this, i18n("Are you sure you wish to remove all <b>%1</b> bookmarks?").arg(item->parent->name))) {
|
||||
return;
|
||||
}
|
||||
StreamsModel::self()->removeAllBookmarks(mapped);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!StreamsModel::self()->isFavoritesWritable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndexList selected = view->selectedIndexes();
|
||||
QModelIndexList useable;
|
||||
|
||||
foreach (const QModelIndex &i, selected) {
|
||||
@@ -334,6 +369,7 @@ void StreamsPage::removeItems()
|
||||
if (useable.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (useable.size()>1) {
|
||||
if (MessageBox::No==MessageBox::warningYesNo(this, i18n("Are you sure you wish to remove the %1 selected streams?").arg(useable.size()))) {
|
||||
return;
|
||||
@@ -407,14 +443,8 @@ void StreamsPage::controlActions()
|
||||
QModelIndexList selected=view->selectedIndexes();
|
||||
editAction->setEnabled(false);
|
||||
addToFavouritesAction->setEnabled(false);
|
||||
addBookmarkAction->setEnabled(false);
|
||||
reloadAction->setEnabled(false);
|
||||
if (1==selected.size()) {
|
||||
const StreamsModel::Item *item=static_cast<const StreamsModel::Item *>(proxy.mapToSource(selected.first()).internalPointer());
|
||||
if (StreamsModel::self()->isFavoritesWritable() && !item->isCategory() && item->parent && item->parent->isFavourites) {
|
||||
editAction->setEnabled(true);
|
||||
}
|
||||
reloadAction->setEnabled(item->isCategory() && StreamsModel::self()->isTopLevel(static_cast<const StreamsModel::CategoryItem *>(item)));
|
||||
}
|
||||
StdActions::self()->removeAction->setEnabled(false);
|
||||
if (!selected.isEmpty() && StreamsModel::self()->isFavoritesWritable()) {
|
||||
bool enableRemove=true;
|
||||
@@ -436,6 +466,19 @@ void StreamsPage::controlActions()
|
||||
StdActions::self()->removeAction->setEnabled(enableRemove);
|
||||
addToFavouritesAction->setEnabled(enableAddToFav);
|
||||
}
|
||||
if (1==selected.size()) {
|
||||
const StreamsModel::Item *item=static_cast<const StreamsModel::Item *>(proxy.mapToSource(selected.first()).internalPointer());
|
||||
if (StreamsModel::self()->isFavoritesWritable() && !item->isCategory() && item->parent && item->parent->isFavourites) {
|
||||
editAction->setEnabled(true);
|
||||
}
|
||||
reloadAction->setEnabled(item->isCategory() && StreamsModel::self()->isTopLevel(static_cast<const StreamsModel::CategoryItem *>(item)));
|
||||
addBookmarkAction->setEnabled(item->isCategory() && static_cast<const StreamsModel::CategoryItem *>(item)->canBookmark);
|
||||
if (!StdActions::self()->removeAction->isEnabled()) {
|
||||
StdActions::self()->removeAction->setEnabled(item->isCategory() && item->parent &&
|
||||
(item->parent->isBookmarks || (static_cast<const StreamsModel::CategoryItem *>(item)->isBookmarks)));
|
||||
}
|
||||
}
|
||||
|
||||
addAction->setEnabled(StreamsModel::self()->isFavoritesWritable());
|
||||
exportAction->setEnabled(StreamsModel::self()->haveFavourites());
|
||||
importAction->setEnabled(StreamsModel::self()->isFavoritesWritable());
|
||||
|
||||
@@ -64,6 +64,7 @@ private Q_SLOTS:
|
||||
void importXml();
|
||||
void exportXml();
|
||||
void add();
|
||||
void addBookmark();
|
||||
void addToFavourites();
|
||||
void reload();
|
||||
void edit();
|
||||
@@ -84,6 +85,7 @@ private:
|
||||
Action *editAction;
|
||||
Action *addToFavouritesAction;
|
||||
Action *reloadAction;
|
||||
Action *addBookmarkAction;
|
||||
StreamsProxyModel proxy;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user