Simplify streams page

This commit is contained in:
craig.p.drummond
2013-06-28 18:24:49 +00:00
committed by craig.p.drummond
parent e7a7ac2233
commit 84dbfdb865
295 changed files with 1001 additions and 2790 deletions

View File

@@ -92,7 +92,7 @@ set(CANTATA_SRCS gui/application.cpp gui/main.cpp gui/initialsettingswizard.cpp
gui/settings.cpp gui/covers.cpp gui/filesettings.cpp gui/interfacesettings.cpp gui/playbacksettings.cpp
gui/serversettings.cpp gui/librarypage.cpp gui/albumspage.cpp gui/folderpage.cpp gui/playlistspage.cpp gui/trayitem.cpp
gui/cachesettings.cpp gui/coverdialog.cpp gui/stdactions.cpp
streams/streamspage.cpp streams/streamdialog.cpp streams/streamcategorydialog.cpp streams/streamfetcher.cpp streams/webstreams.cpp
streams/streamspage.cpp streams/streamdialog.cpp streams/streamfetcher.cpp
models/musiclibraryitemroot.cpp models/musiclibraryitemartist.cpp models/musiclibraryitemalbum.cpp models/musiclibrarymodel.cpp
models/musiclibraryproxymodel.cpp models/playlistsmodel.cpp models/playlistsproxymodel.cpp models/playqueuemodel.cpp
models/playqueueproxymodel.cpp models/dirviewmodel.cpp models/dirviewproxymodel.cpp models/dirviewitem.cpp models/dirviewitemdir.cpp
@@ -114,7 +114,7 @@ set(CANTATA_MOC_HDRS
gui/initialsettingswizard.h gui/mainwindow.h gui/settings.h gui/covers.h gui/folderpage.h gui/librarypage.h gui/albumspage.h
gui/playlistspage.h gui/playbacksettings.h gui/serversettings.h gui/preferencesdialog.h gui/filesettings.h
gui/interfacesettings.h gui/cachesettings.h gui/trayitem.h gui/coverdialog.h
streams/streamspage.h streams/streamdialog.h streams/streamcategorydialog.h streams/streamfetcher.h streams/webstreams.h
streams/streamspage.h streams/streamdialog.h streams/streamfetcher.h
models/musiclibrarymodel.h models/musiclibraryproxymodel.h models/playlistsmodel.h models/playlistsproxymodel.h models/playqueuemodel.h
models/playqueueproxymodel.h models/dirviewmodel.h models/dirviewproxymodel.h models/albumsmodel.h models/streamsmodel.h
models/actionmodel.h
@@ -402,8 +402,7 @@ endif (MSVC)
add_subdirectory(po)
add_subdirectory(support)
add_subdirectory(streams/icons)
if (ENABLE_KDE_SUPPORT)
include_directories(${KDE4_INCLUDES})
add_definitions(${KDE4_DEFINITIONS})

View File

@@ -51,56 +51,54 @@
33. Automatic accelator assignment for Qt builds.
34. Add cmake check to see if TagLib has id3version in MPEG save.
35. RTL fixes.
36. Add import/export of Streams XML files - these contians just streams,
without categories. The intention is to be able to import these into
MPDroid.
37. For Qt4 linux builds, use system QJson if found.
38. Remove amazon cover fetching - required API key that Cantata never really
36. For Qt4 linux builds, use system QJson if found.
37. Remove amazon cover fetching - required API key that Cantata never really
had.
39. Add debug logging. Please see README for details.
40. Enable MPD HTTP stream playback using QtMultiMedia for Qt5 builds. Thanks
38. Add debug logging. Please see README for details.
39. Enable MPD HTTP stream playback using QtMultiMedia for Qt5 builds. Thanks
to Marcel Bosling for the patch. Disabled by default, to enable pass
-DENABLE_HTTP_STREAM_PLAYBACK=ON to cmake.
41. Fix Qt5 segfault on exit, due to static QIcons being destructed.
42. Work-around Qt5 bug where toolbuttons (usually with menus) stay in the
40. Fix Qt5 segfault on exit, due to static QIcons being destructed.
41. Work-around Qt5 bug where toolbuttons (usually with menus) stay in the
raised state.
43. Add port number to library cache filename, to cater for scenarios where
42. Add port number to library cache filename, to cater for scenarios where
there is more than 1 server on the same host.
44. Fix retrieval of covers in albums view for multiple-artist albums when
43. Fix retrieval of covers in albums view for multiple-artist albums when
these are configured to be grouped under "Various Artists"
45. Refresh albums view when multiple-artist grouping is changed.
46. Add context menu to replygain and file organizer dialogs to remove items
44. Refresh albums view when multiple-artist grouping is changed.
45. Add context menu to replygain and file organizer dialogs to remove items
from list.
47. Also use discogs for artist images in cover dialog.
48. Fix invalid covers showing for online services.
49. For Qt builds, if shortcut is set to default then remove entry from config
46. Also use discogs for artist images in cover dialog.
47. Fix invalid covers showing for online services.
48. For Qt builds, if shortcut is set to default then remove entry from config
file.
50. Don't show page shortcuts in tooltips, as tooltip is not updated when
49. Don't show page shortcuts in tooltips, as tooltip is not updated when
shortcut is changed.
51. Check that perl is installed before attempting to start cantata-dynamic in
50. Check that perl is installed before attempting to start cantata-dynamic in
local mode.
52. If cantata-dynamic is started in server mode, then have it create any
51. If cantata-dynamic is started in server mode, then have it create any
missing folders.
53. Simpler proxy settings.
54. Delay loading of local devices at atart-up, so that we have time to add
52. Simpler proxy settings.
53. Delay loading of local devices at atart-up, so that we have time to add
device to view before try to expand it.
55. If cantata-dynamic is started in server mode, then communicate status via
54. If cantata-dynamic is started in server mode, then communicate status via
UDP multicast messages.
56. If using server mode cantata-dynamic and this is not started, then show an
55. If using server mode cantata-dynamic and this is not started, then show an
error message in dynamic page.
57. Fix keyboard shortcuts of tab pages.
58. Add support for a simple profile where MPD is started by cantata, and
56. Fix keyboard shortcuts of tab pages.
57. Add support for a simple profile where MPD is started by cantata, and
the only settings are the music folder and cover names.
59. Combine Output and Playback config pages.
60. Remove proxy config from settings, and always use system proxy.
58. Combine Output and Playback config pages.
59. Remove proxy config from settings, and always use system proxy.
To re-enable proxy settings pass -DENABLE_PROXY_CONFIG=ON to cmake.
61. Add option to draw curent album cover as backdrop to play queue.
62. Add 'Copy Songs To Device' action to playlists page.
63. Copy Qt5 Linux system proxy code for Qt4 builds.
64. Embed pre-rendered PNG versions of cantata icon, to help with Qt5 builds
60. Add option to draw curent album cover as backdrop to play queue.
61. Add 'Copy Songs To Device' action to playlists page.
62. Copy Qt5 Linux system proxy code for Qt4 builds.
63. Embed pre-rendered PNG versions of cantata icon, to help with Qt5 builds
on systems that do not have the Qt SVG icon engine installed.
65. Add support for importing Digitally Imported, Jazz Radio, and Sky.fm
streams. Only free, ad supported, streams at the moment.
64. Simplify streams page. Remove user-categories, instead have a set of
predefined top-level items; Favourites (user streams), TuneIn, IceCast,
SomaFM, Digitially Imported, Jazz Radio, and Sky.fm.
1.0.3
-----

View File

@@ -1,7 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file alias="lyrics.xml">context/ultimate_providers.xml</file>
<file alias="streams.xml">streams/providers.xml</file>
<file alias="weblinks.xml">context/weblinks.xml</file>
<file alias="repeat16.png">icons/view-media-repeat16.png</file>
<file alias="repeat22.png">icons/view-media-repeat22.png</file>
@@ -11,7 +10,6 @@
<file alias="shuffle22.png">icons/view-media-shuffle22.png</file>
<file alias="shuffle32.png">icons/view-media-shuffle32.png</file>
<file alias="shuffle48.png">icons/view-media-shuffle48.png</file>
<file alias="sidebar-albums-dark">icons/sidebar-albums-dark.svg</file>
<file alias="sidebar-artists-dark">icons/sidebar-artists-dark.svg</file>
<file alias="sidebar-devices-dark">icons/sidebar-devices-dark.svg</file>
@@ -32,5 +30,13 @@
<file alias="sidebar-playlists-light">icons/sidebar-playlists-light.svg</file>
<file alias="sidebar-playqueue-light">icons/sidebar-playqueue-light.svg</file>
<file alias="sidebar-streams-light">icons/sidebar-streams-light.svg</file>
<file alias="streams-icecast">icons/streams-icecast.svg</file>
<file alias="streams-shoutcast">icons/streams-shoutcast.png</file>
<file alias="streams-favourites">icons/streams-favourites.svg</file>
<file alias="streams-tunein">icons/streams-tunein.png</file>
<file alias="streams-digitallyimported">icons/streams-digitallyimported.png</file>
<file alias="streams-somafm">icons/streams-somafm.png</file>
<file alias="streams-skyfm">icons/streams-skyfm.png</file>
<file alias="streams-jazzradio">icons/streams-jazzradio.png</file>
</qresource>
</RCC>

View File

@@ -49,7 +49,7 @@
<item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Save list of streams in music folder:</string>
<string>Save list of favourite streams in music folder:</string>
</property>
<property name="buddy">
<cstring>storeStreamsInMpdDir</cstring>

View File

@@ -744,7 +744,7 @@
<item row="2" column="0">
<widget class="QLabel" name="storeStreamsInMpdDirLabel">
<property name="text">
<string>Save list of streams in music folder:</string>
<string>Save list of favourite streams in music folder:</string>
</property>
<property name="buddy">
<cstring>storeStreamsInMpdDir</cstring>

View File

@@ -2192,25 +2192,13 @@ void MainWindow::addToExistingStoredPlaylist(const QString &name, bool pq)
void MainWindow::addStreamToPlayQueue()
{
// Need to load streams, if not already loaded - so that we can get list of categories/genres...
if (!(loaded&TAB_STREAMS)) {
loaded|=TAB_STREAMS;
streamsPage->refresh();
}
StreamDialog dlg(streamsPage->getCategories(), streamsPage->getGenres(), this, true);
StreamDialog dlg(this, true);
if (QDialog::Accepted==dlg.exec()) {
QString url=dlg.url();
if (dlg.save()) {
QString name=dlg.name();
QString cat=dlg.category();
QString existing=StreamsModel::self()->name(cat, url);
if (existing.isEmpty()) {
StreamsModel::self()->add(cat, name, dlg.genre(), dlg.icon(), url);
}
StreamsModel::self()->addToFavourites(url, dlg.name());
}
playQueueModel.addItems(QStringList() << StreamsModel::modifyUrl(url), false, 0);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
icons/streams-jazzradio.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
icons/streams-shoutcast.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
icons/streams-skyfm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
icons/streams-somafm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
icons/streams-tunein.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -20,133 +20,123 @@
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef STREAMSMODEL_H
#define STREAMSMODEL_H
#include <QList>
#include <QUrl>
#include <QHash>
#include <QSet>
#include <QMap>
#include <QStringList>
#include "actionmodel.h"
#include <QList>
#include <QMap>
#include <QIcon>
class QTimer;
class QIODevice;
class QNetworkReply;
class QXmlStreamReader;
class QIODevice;
class QTimer;
class StreamsModel : public ActionModel
{
Q_OBJECT
public:
static const QString constPrefix;
static QString modifyUrl(const QString &u, bool addPrefix=true, const QString &name=QString());
static QString dir();
static const QLatin1String constGenreSeparator;
static QSet<QString> genreSet(const QString &str) { return str.split(constGenreSeparator, QString::SkipEmptyParts).toSet(); }
struct CategoryItem;
struct Item
{
Item(const QString &n, const QString &i) : name(n), icon(i) { name.replace("#", ""); }
virtual bool isCategory() = 0;
Item(const QString &u, const QString &n=QString(), CategoryItem *p=0) : url(u), name(n), parent(p) { }
virtual ~Item() { }
QString url;
QString name;
QString icon;
};
struct CategoryItem;
struct StreamItem : public Item
{
StreamItem(const QString &n, const QString &g, const QString &i, const QUrl &u, CategoryItem *p=0) : Item(n, i), genres(genreSet(g)), url(u), parent(p) { }
StreamItem(const QString &n, const QSet<QString> &g, const QString &i, const QUrl &u, CategoryItem *p=0) : Item(n, i), genres(g), url(u), parent(p) { }
bool isCategory() { return false; }
QString genreString() const { return QStringList(genres.toList()).join(constGenreSeparator); }
QSet<QString> genres;
QUrl url;
CategoryItem *parent;
virtual bool isCategory() const { return false; }
};
struct CategoryItem : public Item
{
CategoryItem(const QString &n, const QString &i=QString()) : Item(n, i) { }
virtual ~CategoryItem() { clearStreams(); }
bool isCategory() { return true; }
void clearStreams();
QHash<QString, StreamItem *> itemMap;
QList<StreamItem *> streams;
QSet<QString> genres;
enum State
{
Initial,
Fetching,
Fetched
};
CategoryItem(const QString &u, const QString &n=QString(), CategoryItem *p=0, const QIcon &i=QIcon())
: Item(u, n, p), state(Initial), isFavourites(false), icon(i) { }
virtual ~CategoryItem() { qDeleteAll(children); }
virtual bool isCategory() const { return true; }
State state;
bool isFavourites;
QList<Item *> children;
QIcon icon;
};
static const QString constPrefix;
static StreamsModel * self();
static QString favouritesDir();
static QString modifyUrl(const QString &u, bool addPrefix=true, const QString &name=QString());
static bool validProtocol(const QString &file);
StreamsModel();
StreamsModel(QObject *parent = 0);
~StreamsModel();
QModelIndex index(int, int, const QModelIndex & = QModelIndex()) const;
QModelIndex parent(const QModelIndex &) const;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex&) const { return 1; }
bool hasChildren(const QModelIndex &parent) const;
QModelIndex parent(const QModelIndex &index) const;
QModelIndex index(int row, int column, const QModelIndex &parent) const;
int columnCount(const QModelIndex &) const;
QVariant data(const QModelIndex &, int) const;
void reload();
void save(bool force=false);
bool save(const QString &filename, const QSet<StreamsModel::Item *> &selection=QSet<StreamsModel::Item *>(), bool streamsOnly=false);
bool import(const QString &filename) { return load(filename, false); }
bool add(const QString &cat, const QString &name, const QString &genre, const QString &icon, const QString &url);
void add(const QString &cat, const QString &icon, const QList<StreamsModel::StreamItem *> &streams);
void editCategory(const QModelIndex &index, const QString &name, const QString &icon);
void editStream(const QModelIndex &index, const QString &oldCat, const QString &newCat, const QString &name, const QString &genre, const QString &icon, const QString &url);
void remove(const QModelIndex &index);
void removeCategory(CategoryItem *cat);
void removeStream(StreamItem *stream);
void removeStream(const QString &category, const QString &name, const QString &url);
QString name(const QString &cat, const QString &url) { return name(getCategory(cat), url); }
bool entryExists(const QString &cat, const QString &name, const QUrl &url=QUrl()) { return entryExists(getCategory(cat), name, url); }
Qt::ItemFlags flags(const QModelIndex &index) const;
Qt::DropActions supportedDropActions() const;
bool validProtocol(const QString &file) const;
bool hasChildren(const QModelIndex &index) const;
bool canFetchMore(const QModelIndex &index) const;
void fetchMore(const QModelIndex &index);
void saveFavourites(bool force=false);
bool haveFavourites() const { return !favourites->children.isEmpty(); }
bool isFavoritesWritable() { return favouritesIsWriteable; }
bool checkFavouritesWritable();
void reloadFavourites();
void removeFromFavourites(const QModelIndex &index);
void addToFavourites(const QString &url, const QString &name);
QString favouritesNameForUrl(const QString &u);
bool nameExistsInFavourites(const QString &n);
void updateFavouriteStream(Item *item);
bool importXml(const QString &fileName);
bool saveXml(const QString &fileName, const QList<Item *> &items);
QStringList filenames(const QModelIndexList &indexes, bool addPrefix) const;
QMimeData * mimeData(const QModelIndexList &indexes) const;
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int col, const QModelIndex &parent);
QStringList mimeTypes() const;
void mark(const QList<int> &rows, bool f);
void updateGenres();
bool isWritable() const { return writable; }
bool checkWritable();
Action * getAction(const QModelIndex &idx, int num);
const QMap<QString, QIcon> & icons();
QIcon icon(const QString &name) const;
Q_SIGNALS:
void downloading(bool);
void updateGenres(const QSet<QString> &genres);
void error(const QString &e);
void loading();
void loaded();
void error(const QString &msg);
private Q_SLOTS:
void downloadFinished();
void jobFinished();
void persistFavourites();
private:
bool save(QIODevice *dev, const QSet<StreamsModel::Item *> &selection, bool streamsOnly, bool format);
void clearCategories();
bool load(const QString &filename, bool isInternal);
bool load(QIODevice *dev, bool isInternal);
CategoryItem * getCategory(const QString &name, bool create=false, bool signal=false);
QString name(CategoryItem *cat, const QString &url);
bool entryExists(CategoryItem *cat, const QString &name, const QUrl &url=QUrl()) { return 0!=getStream(cat, name, url); }
StreamItem * getStream(CategoryItem *cat, const QString &name, const QUrl &url);
private Q_SLOTS:
void persist();
Item * toItem(const QModelIndex &index) const { return index.isValid() ? static_cast<Item*>(index.internalPointer()) : root; }
QList<Item *> parseRadioTimeResponse(QIODevice *dev, CategoryItem *cat);
QList<Item *> parseIceCastResponse(QIODevice *dev, CategoryItem *cat);
QList<Item *> parseSomaFmResponse(QIODevice *dev, CategoryItem *cat);
QList<Item *> parseDigitallyImportedResponse(QIODevice *dev, CategoryItem *cat, const QString &origUrl);
Item * parseRadioTimeEntry(QXmlStreamReader &doc, CategoryItem *parent);
Item * parseIceCastEntry(QXmlStreamReader &doc, CategoryItem *parent);
Item * parseSomaFmEntry(QXmlStreamReader &doc, CategoryItem *parent);
void loadFavourites(const QModelIndex &index);
bool loadXml(const QString &fileName, const QModelIndex &index);
QList<Item *> loadXml(QIODevice *dev, bool isInternal);
bool saveXml(QIODevice *dev, const QList<Item *> &items, bool format) const;
private:
QList<CategoryItem *> items;
mutable QMap<QString, QIcon> iconMap;
bool writable;
bool modified;
QTimer *timer;
QNetworkReply *job;
QMap<QNetworkReply *, CategoryItem *> jobs;
CategoryItem *root;
CategoryItem *favourites;
bool favouritesIsWriteable;
bool favouritesModified;
QTimer *favouritesSaveTimer;
};
#endif

View File

@@ -33,6 +33,26 @@ StreamsProxyModel::StreamsProxyModel(QObject *parent)
sort(0);
}
bool StreamsProxyModel::filterAcceptsItem(const void *i, QStringList strings) const
{
const StreamsModel::Item *item=static_cast<const StreamsModel::Item *>(i);
strings << item->name;
if (matchesFilter(strings)) {
return true;
}
if (item->isCategory()) {
const StreamsModel::CategoryItem *cat=static_cast<const StreamsModel::CategoryItem *>(item);
foreach (const StreamsModel::Item *c, cat->children) {
if (filterAcceptsItem(c, strings)) {
return true;
}
}
}
return false;
}
bool StreamsProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
if (!filterEnabled) {
@@ -41,33 +61,58 @@ bool StreamsProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourc
if (!isChildOfRoot(sourceParent)) {
return true;
}
const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
StreamsModel::Item *item = static_cast<StreamsModel::Item *>(index.internalPointer());
QModelIndex idx=index.parent();
QStringList strings;
// Traverse back up tree, so we get parent strings...
while (idx.isValid()) {
StreamsModel::Item *i = static_cast<StreamsModel::Item *>(idx.internalPointer());
if (!i->isCategory()) {
break;
}
strings << i->name;
idx=idx.parent();
}
if (item->isCategory()) {
StreamsModel::CategoryItem *cat = static_cast<StreamsModel::CategoryItem *>(item);
if (!filterGenre.isEmpty() && !cat->genres.contains(filterGenre)) {
return false;
}
if (cat->name.contains(filterRegExp())) {
// Check *all* children...
if (filterAcceptsItem(item, strings)) {
return true;
}
foreach (StreamsModel::StreamItem *s, cat->streams) {
if (matchesFilter(QStringList() << cat->name << s->name)) {
return true;
}
}
} else {
StreamsModel::StreamItem *s = static_cast<StreamsModel::StreamItem *>(item);
if (!filterGenre.isEmpty() && !s->genres.contains(filterGenre)) {
return false;
}
return matchesFilter(QStringList() << s->name);
strings << item->name;
return matchesFilter(strings);
}
return false;
}
bool StreamsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
const StreamsModel::Item * leftItem = static_cast<const StreamsModel::Item *>(left.internalPointer());
const StreamsModel::Item * rightItem = static_cast<const StreamsModel::Item *>(right.internalPointer());
if (leftItem->isCategory() && !rightItem->isCategory()) {
return true;
}
if (!leftItem->isCategory() && rightItem->isCategory()) {
return false;
}
if (leftItem->isCategory() && rightItem->isCategory()) {
const StreamsModel::CategoryItem * leftCat = static_cast<const StreamsModel::CategoryItem *>(leftItem);
const StreamsModel::CategoryItem * rightCat = static_cast<const StreamsModel::CategoryItem *>(rightItem);
if (leftCat->isFavourites && !rightCat->isFavourites) {
return true;
}
if (!leftCat->isFavourites && rightCat->isFavourites) {
return false;
}
}
return QSortFilterProxyModel::lessThan(left, right);
}

View File

@@ -26,12 +26,15 @@
#include "proxymodel.h"
class StreamsProxyModel : public ProxyModel
{
public:
StreamsProxyModel(QObject *parent = 0);
void setFilterGenre(const QString &genre);
bool filterAcceptsItem(const void *i, QStringList strings) const;
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
};
#endif

View File

@@ -1,7 +0,0 @@
file(GLOB svg_files *.svg)
file(GLOB png_files *.png)
if (WIN32)
install(FILES ${svg_files} ${png_files} DESTINATION ${CMAKE_INSTALL_PREFIX}/streamicons/)
else (WIN32)
install(FILES ${svg_files} ${png_files} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/${CMAKE_PROJECT_NAME}/streamicons/)
endif (WIN32)

View File

@@ -1,15 +0,0 @@
<svg viewBox="0 0 41.160763 47.604721" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<linearGradient>
<stop offset="0"/>
<stop offset="1" stop-color="#fff"/>
</linearGradient>
<linearGradient x1="-1.0164395e-18" x2="1" xlink:href="#linearGradient830"/>
<radialGradient xlink:href="#linearGradient830"/>
</defs>
<g transform="translate(-80.59801,-338.389)">
<path d="m94.57371,338.62098c-8.78484.20794-15.51495,6.36209-13.33392,15.78724 .00257.0111.01334.02075.01593.03186 .25605,3.25054 2.9607,5.81468 6.27666,5.81468 3.48488,0 6.30852-2.82365 6.30852-6.30853 0-3.07137-2.1907-5.63239-5.0978-6.197-1.15848-.40989-2.89596-1.34191-2.81972-2.83565 .03514-.74343.90303-2.09188 2.29401-2.77193 1.69055-.79335 3.43378-1.22266 5.19338-.86025 2.66733.48694 9.48863,5.38493 10.02036,13.87556 .30521,6.44653-3.3159,15.15023-6.85016,19.27604-5.69761,6.50335-14.85058,10.54298-13.95522,11.26294 .80363.71997 11.61001-4.21926 17.23692-10.41862 6.86685-7.4357 10.26627-13.63373 9.9407-21.17178-.19582-7.53805-6.03171-15.6992-15.22966-15.48456z" fill-rule="evenodd" stroke="#000" stroke-width=".45574"/>
<path d="m116.85809,36.47297a9.7721,9.16135 0 1,1 -19.54421,0 9.7721,9.16135 0 1,1 19.54421,0z" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width=".894" transform="matrix(.509779,0,0,.509779,61.9591,329.3244)"/>
<path d="m116.85809,36.47297a9.7721,9.16135 0 1,1 -19.54421,0 9.7721,9.16135 0 1,1 19.54421,0z" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width=".894" transform="matrix(.509779,0,0,.509779,61.9591,342.3694)"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,6 +0,0 @@
<svg viewBox="0 0 365.62958 367.73712" xmlns="http://www.w3.org/2000/svg">
<title>Six Sided Dice</title>
<g transform="translate(-117.1457,-272.3622)">
<path d="m328.7338,272.3636c-1.0593-.0232-2.2036.2392-3.6545.7307l-160.7956,47.2156c-1.338.3127-1.2603.6733-.1462,1.5349l142.7427,113.9456c2.6283,2.1791 3.8646,2.4492 7.5282,1.3156l160.0647-55.4745c3.6722-1.3494 3.9274-1.6778.1464-4.1662l-140.4769-102.763c-2.1688-1.5284-3.6434-2.3049-5.4085-2.3387zm-18.3454,13.8138c3.2021-.0232 6.5824.3283 10.0863,1.0963 14.0157,3.073 23.9561,11.6383 22.1459,19.0764s-14.6352,10.9666-28.6507,7.8935-23.9562-11.5651-22.146-19.0032c1.3576-5.5785 8.9586-9.0156 18.5645-9.063zm-90.6303,27.5545c3.2021-.0232 6.6554.3281 10.1594,1.0964 14.0156,3.073 23.883,11.5652 22.0728,19.003s-14.6352,11.0396-28.6508,7.9667-23.883-11.638-22.0728-19.0761c1.3577-5.5785 8.8855-8.9426 18.4914-8.99zm137.3341,7.0164c3.202-.0232 6.6555.4013 10.1594,1.1695 14.0157,3.0728 23.8829,11.5651 22.0729,19.0031s-14.6352,10.9665-28.6508,7.8935-23.8831-11.5651-22.0729-19.0031c1.3577-5.5783 8.8855-9.0156 18.4915-9.063zm-202.8948,8.8438c-.2935.0748-.3883.5333-.5847,1.4619l-36.2522,181.3334c-.4224,1.8862-.3482,2.3536 1.3887,3.8739l137.6995,118.6962c3.2029,3.0612 3.8757,3.0218 4.3122-.7309l40.1259-183.8915c.8408-2.5054-.0249-3.8837-1.4618-5.0432l-143.7659-114.8226c-.74-.6243-1.1682-.9515-1.4618-.8772zm111.826,20.6841c3.202-.0232 6.6554.3281 10.1594,1.0965 14.0156,3.073 23.883,11.5651 22.0728,19.003s-14.6352,10.9666-28.6509,7.8937-23.8829-11.5652-22.0728-19.0031c1.3576-5.5787 8.8856-8.9426 18.4915-8.9901zm138.7959,6.0664c3.202-.0232 6.6554.3281 10.1594,1.0963 14.0156,3.0731 23.883,11.5651 22.0728,19.0032s-14.6352,11.0398-28.6509,7.9668-23.883-11.6383-22.0728-19.0763c1.3577-5.5783 8.8856-8.9423 18.4915-8.9899zm-241.7051,6.651c.5401-.0537 1.1314-.0294 1.681,0 6.5957.3492 13.738,6.5306 17.9068,16.4452 5.5583,13.2193 3.7052,28.0551-4.093,33.1091s-18.634-1.5446-24.1924-14.764-3.7054-28.0551 4.093-33.1091c1.4621-.9477 2.9845-1.5207 4.6045-1.6812zm150.6363,23.8271c3.202-.0231 6.6554.3282 10.1593,1.0965 14.0157,3.0728 23.8831,11.5651 22.0729,19.003s-14.6353,10.9666-28.6508,7.8936-23.883-11.5651-22.0728-19.0032c1.3576-5.5785 8.8855-8.9425 18.4914-8.99zm168.1777,5.0431c-.3073.0632-.7394.1709-1.2425.3654l-164.3771,57.0094c-3.348,1.3784-3.2476,1.9411-3.8007,4.4584l-40.0526,183.3069c-.136,2.6988-1.1302,3.9269 2.0465,2.4852l161.965-60.5177c3.1428-1.5036 3.7452-1.7677 4.093-4.8238l42.0261-180.749c.3482-1.2733.2638-1.7272-.6578-1.5349zm-26.6775,29.7472c4.6284.0748 8.2604,2.3262 9.8671,6.6513 3.2131,8.6497-2.9745,22.494-13.887,30.9165s-22.3679,8.2114-25.5811-.4385 2.9744-22.4941 13.8868-30.9166c5.4562-4.2113 11.0857-6.2873 15.7142-6.2127zm-199.2404,15.8604c6.6789.1708 13.9652,6.4487 18.1991,16.5182 5.5583,13.2194 3.7783,28.0551-4.0199,33.1091s-18.634-1.6175-24.1924-14.8369-3.7054-27.9823 4.093-33.0362c1.4622-.9477 2.9841-1.5209 4.6045-1.6812 .4389-.0453.8704-.0842 1.3156-.0726zm-58.6904,21.1958c6.6788.1708 13.9651,6.4488 18.1991,16.5181 5.5583,13.2194 3.7783,28.0551-4.0199,33.1093s-18.6341-1.6176-24.1924-14.837-3.7052-27.9822 4.093-33.0361c1.4621-.9477 2.9841-1.521 4.6045-1.6812 .4389-.0453.8705-.0842 1.3157-.0726zm-57.8133,20.9765c.5399-.0537 1.1313-.0273 1.6809,0 6.5957.3492 13.6649,6.6037 17.8338,16.5181 5.5583,13.2194 3.7784,27.9823-4.0198,33.0362s-18.6342-1.5446-24.1925-14.764-3.7053-28.0551 4.093-33.1091c1.4622-.9477 2.9845-1.5208 4.6047-1.6812zm254.0571,17.5413c4.529.1474 8.1393,2.3938 9.7208,6.6512 3.2134,8.6498-3.0476,22.4942-13.9599,30.9165s-22.3679,8.2115-25.5811-.4385 3.0476-22.4941 13.9599-30.9165c4.7742-3.6848 9.6414-5.7376 13.8869-6.1395 .6823-.0653 1.3264-.0937 1.9734-.0726zm-164.2308,58.6906c.54-.0537 1.1313-.0273 1.681,0 6.5956.3492 13.738,6.5305 17.9068,16.4449 5.5583,13.2193 3.7053,28.0554-4.093,33.1093s-18.561-1.5447-24.1193-14.7639-3.7784-28.0553 4.0198-33.1094c1.4622-.9474 2.9845-1.5206 4.6047-1.6809zm97.2813,19.0032c4.6285.0748 8.2603,2.2531 9.867,6.578 3.2132,8.6497-2.9744,22.4939-13.8869,30.9165s-22.3679,8.2843-25.5811-.3655 2.9744-22.4942 13.8869-30.9166c5.4562-4.2111 11.0856-6.287 15.7141-6.2123z" fill="#d00000"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 947 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 685 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1001 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 560 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 743 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 262 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 849 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 505 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 805 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 942 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 632 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 788 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 913 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 996 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 666 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 618 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Some files were not shown because too many files have changed in this diff Show More