From fbfb08165cfe60087d4d70cc036b91cee1fd5efe Mon Sep 17 00:00:00 2001 From: "craig.p.drummond" Date: Mon, 19 Aug 2013 20:44:02 +0000 Subject: [PATCH] - Add support for user-installable stream providers. Need to copy name.xml.gz, and name.svg/name.png to ~/.config/cantata/streams - or PREFIX/share/cantata/streams - Use thi snew mechanism to install 1.fm provider --- CMakeLists.txt | 1 + ChangeLog | 3 ++ models/streamsmodel.cpp | 62 ++++++++++++++++++++++++++++++- models/streamsmodel.h | 10 ++++- streams/providers/1.fm.png | Bin 0 -> 8473 bytes streams/providers/1.fm.xml.gz | Bin 0 -> 680 bytes streams/providers/CMakeLists.txt | 6 +++ 7 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 streams/providers/1.fm.png create mode 100644 streams/providers/1.fm.xml.gz create mode 100644 streams/providers/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 53e0bb6dc..9704854c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -354,6 +354,7 @@ endif (MSVC) add_subdirectory(po) add_subdirectory(support) add_subdirectory(streams/icons) +add_subdirectory(streams/providers) if (ENABLE_PROXY_CONFIG) set(CANTATA_SRCS ${CANTATA_SRCS} network/proxysettings.cpp) diff --git a/ChangeLog b/ChangeLog index d1c046c89..6768045ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,9 @@ ----- 1. Add support for opus audio format - AudioCD encoding, transcoding, HTTP server, etc. +2. Add support for user-installable stream providers. Need to copy + name.xml.gz, and name.svg/name.png to ~/.config/cantata/streams - or + PREFIX/share/cantata/streams 1.1.1 ----- diff --git a/models/streamsmodel.cpp b/models/streamsmodel.cpp index 8fc799176..90f54e110 100644 --- a/models/streamsmodel.cpp +++ b/models/streamsmodel.cpp @@ -38,12 +38,14 @@ #include "digitallyimported.h" #include "qjson/parser.h" #include "qtiocompressor/qtiocompressor.h" +#include "utils.h" #include #include #include #include #include #include +#include #include #include #include @@ -54,6 +56,9 @@ #include K_GLOBAL_STATIC(StreamsModel, instance) #endif +#if defined Q_OS_WIN +#include +#endif StreamsModel * StreamsModel::self() { @@ -116,6 +121,25 @@ static QIcon getIcon(const QString &name) return icon.isNull() ? Icons::self()->streamCategoryIcon : icon; } +static QIcon getExternalIcon(const QString &xmlFile) +{ + QIcon icon; + QString iconFile=xmlFile; + iconFile.replace(".xml.gz", ".svg"); + + if (QFile::exists(iconFile)) { + icon.addFile(iconFile); + } else { + iconFile=xmlFile; + iconFile.replace(".xml.gz", ".png"); + if (QFile::exists(iconFile)) { + icon.addFile(iconFile); + } + } + + return icon; +} + static QString categoryCacheName(const QString &name, bool createDir=false) { return Utils::cacheDir(StreamsModel::constCacheDir, createDir)+name+StreamsModel::constCacheExt; @@ -264,7 +288,16 @@ QList StreamsModel::CategoryItem::loadCache() } } - return newItems; + return QList(); +} + +QList StreamsModel::XmlCategoryItem::loadCache() +{ + if (QFile::exists(cacheName)) { + return loadXml(cacheName); + } + + return QList(); } bool StreamsModel::CategoryItem::saveXml(const QString &fileName, bool format) const @@ -460,6 +493,7 @@ StreamsModel::StreamsModel(QObject *parent) favourites=new FavouritesCategoryItem(constFavouritesUrl, i18n("Favorites"), root, getIcon("favourites")); root->children.append(favourites); buildListenLive(); + buildXml(); addBookmarkAction = ActionCollection::get()->createAction("bookmarkcategory", i18n("Bookmark Category"), Icon("bookmark-new")); addToFavouritesAction = ActionCollection::get()->createAction("addtofavourites", i18n("Add Stream To Favorites"), favouritesIcon()); configureAction = ActionCollection::get()->createAction("configurestreams", i18n("Configure Streams"), Icons::self()->configureIcon); @@ -1668,3 +1702,29 @@ void StreamsModel::buildListenLive() } } } + +void StreamsModel::buildXml() +{ + #ifdef Q_OS_WIN + QStringList dirs=QStringList() << QCoreApplication::applicationDirPath()+"/streams/"; + #else + QStringList dirs=QStringList() << INSTALL_PREFIX "/share/cantata/streams/" + << Utils::configDir("streams"); + #endif + QSet added; + + foreach (const QString &dir, dirs) { + if (dir.isEmpty()) { + continue; + } + QDir d(dir); + QStringList files=d.entryList(QStringList() << "*.xml.gz", QDir::Files|QDir::Readable); + foreach (const QString &file, files) { + if (!added.contains(file)) { + CategoryItem *cat=new XmlCategoryItem(Utils::getFile(file).remove(".xml.gz"), root, getExternalIcon(dir+file), dir+file); + added.insert(file); + root->children.append(cat); + } + } + } +} diff --git a/models/streamsmodel.h b/models/streamsmodel.h index 8f329f515..f641566dc 100644 --- a/models/streamsmodel.h +++ b/models/streamsmodel.h @@ -79,7 +79,7 @@ public: CategoryItem * getBookmarksCategory(); CategoryItem * createBookmarksCategory(); void saveCache() const; - QList loadCache(); + virtual QList loadCache(); bool saveXml(const QString &fileName, bool format=false) const; bool saveXml(QIODevice *dev, bool format=false) const; QList loadXml(const QString &fileName, bool importing=false); @@ -119,6 +119,13 @@ public: bool canConfigure() const { return true; } }; + struct XmlCategoryItem : public CategoryItem + { + XmlCategoryItem(const QString &n, CategoryItem *p, const QIcon &i, const QString &cn) + : CategoryItem("-", n, p, i, cn) { } + QList loadCache(); + }; + static const QString constPrefix; static const QString constCacheDir; static const QString constCacheExt; @@ -198,6 +205,7 @@ private: Item * toItem(const QModelIndex &index) const { return index.isValid() ? static_cast(index.internalPointer()) : root; } bool loadFavourites(const QString &fileName, const QModelIndex &index, bool importing=false); void buildListenLive(); + void buildXml(); private: QMap jobs; diff --git a/streams/providers/1.fm.png b/streams/providers/1.fm.png new file mode 100644 index 0000000000000000000000000000000000000000..4b37ecf42c6468052da9ed7fa3d8a394f83bf5a3 GIT binary patch literal 8473 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 literal 0 HcmV?d00001 diff --git a/streams/providers/1.fm.xml.gz b/streams/providers/1.fm.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..f3eefd22de56ad4a97c94823bd2fff31ae028e19 GIT binary patch literal 680 zcmb2|=HRHW5DH>oHq=YY)vL(OVd$Oa>;Kq5pzZyiu0TF+nFVjVo@Q&Vcg^{DM%k{w~>m+t)$Lai-Dc zx=#jsZ&~`B^E3CGvt5Y$`~FY&%MBt<)EQ~anQq4YKDgV>W5;2iK&Giz|Ehf7XY;P4 zYPY}Z@&zH8Hy!i8e~&Bkemm)0__dvz76r+vg{A6bv~`EaxI~Kk8YC+}Zdo(!Nb|)| zE?Ye=!H~Tg$rG$DO`UGAROs6-nKQvVulF8mdmKGuM{E8mnf4_iQ}p7dpPw-8_}0?M z$Xj`xC%1*YT;z55=kx;CZ=$)!QfKHs4ZO3&NU8nyDb0fmPen=jf7aY#H1);9An%8| zlBx!Lljkqe_{0?}cZ*?Je@updot*xRk~qmPjU_zaCo>)|O0`*}*d_jf#cukC#k*fV zkQRIDe}lij@Il@6kIyWYpQ_m1F!7VFhKP6M6!UNMoFbgJd|5u}ba8IsyP#w42ICCuYO@!*!2sSd-vZ+dQrE7i-7?Ew{lGz literal 0 HcmV?d00001 diff --git a/streams/providers/CMakeLists.txt b/streams/providers/CMakeLists.txt new file mode 100644 index 000000000..f169279b5 --- /dev/null +++ b/streams/providers/CMakeLists.txt @@ -0,0 +1,6 @@ +file(GLOB provider_files *.xml.gz *.png *.svg) +if (WIN32) + install(FILES ${provider_files} DESTINATION ${CMAKE_INSTALL_PREFIX}/streams/) +else (WIN32) + install(FILES ${provider_files} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/${CMAKE_PROJECT_NAME}/streams/) +endif (WIN32)