[vlc-devel] [PATCH 06/10][RFC][WIP] qt: add cloudstorage integration and improved sidebar sub-trees logic
Diogo Silva
dbtdsilva at gmail.com
Thu Aug 17 03:08:14 CEST 2017
This patches includes some modification in order for the cloudstorage
to be user-friendly and also improves the logic behind the sub-trees
in the sidebar (e.g. Podcasts)
---
modules/gui/qt/components/playlist/selector.cpp | 287 +++++++++++++++------
modules/gui/qt/components/playlist/selector.hpp | 51 +++-
.../qt/pixmaps/playlist/sidebar-icons/cloud.png | Bin 0 -> 252 bytes
.../qt/pixmaps/playlist/sidebar-icons/cloud.svgz | Bin 0 -> 448 bytes
modules/gui/qt/vlc.qrc | 1 +
5 files changed, 252 insertions(+), 87 deletions(-)
create mode 100644 modules/gui/qt/pixmaps/playlist/sidebar-icons/cloud.png
create mode 100644 modules/gui/qt/pixmaps/playlist/sidebar-icons/cloud.svgz
diff --git a/modules/gui/qt/components/playlist/selector.cpp b/modules/gui/qt/components/playlist/selector.cpp
index 1d41f7f6af..d6c72ba0ca 100644
--- a/modules/gui/qt/components/playlist/selector.cpp
+++ b/modules/gui/qt/components/playlist/selector.cpp
@@ -62,7 +62,7 @@ void SelectorActionButton::paintEvent( QPaintEvent *event )
}
PLSelItem::PLSelItem ( QTreeWidgetItem *i, const QString& text )
- : qitem(i), lblAction( NULL)
+ : qitem(i), lblAction( NULL), pInnerTree( NULL )
{
layout = new QHBoxLayout( this );
layout->setContentsMargins(0,0,0,0);
@@ -75,6 +75,29 @@ PLSelItem::PLSelItem ( QTreeWidgetItem *i, const QString& text )
setMinimumHeight( height );
}
+PLSelItem::~PLSelItem()
+{
+ if ( pInnerTree != NULL )
+ delete pInnerTree;
+}
+
+void PLSelItem::createInnerTree( const char* slot_add, const char* slot_remove,
+ const char* slot_activate )
+{
+ QTreeWidgetItem* parent = this->treeItem();
+ pInnerTree = new PLSelItemTree(parent, slot_add, slot_remove,
+ slot_activate);
+ parent->setChildIndicatorPolicy(
+ QTreeWidgetItem::ChildIndicatorPolicy::ShowIndicator);
+}
+
+void PLSelItem::mouseReleaseEvent( QMouseEvent* event )
+{
+ // Emit an internal signal and re-invoke the original callback
+ emit subTreeActivated( this );
+ QWidget::mouseReleaseEvent( event );
+}
+
void PLSelItem::addAction( ItemAction act, const QString& tooltip )
{
if( lblAction ) return; //might change later
@@ -130,10 +153,6 @@ PLSelector::PLSelector( QWidget *p, intf_thread_t *_p_intf )
#endif
setMinimumHeight( 120 );
- /* Podcasts */
- podcastsParent = NULL;
- podcastsParentId = -1;
-
/* Podcast connects */
CONNECT( THEMIM, playlistItemAppended( int, int ),
this, plItemAdded( int, int ) );
@@ -160,20 +179,29 @@ PLSelector::PLSelector( QWidget *p, intf_thread_t *_p_intf )
this, setSource( QTreeWidgetItem *) );
CONNECT( this, itemClicked( QTreeWidgetItem *, int ),
this, setSource( QTreeWidgetItem *) );
+ CONNECT( this, itemExpanded( QTreeWidgetItem * ),
+ this, setSource( QTreeWidgetItem *) );
}
PLSelector::~PLSelector()
{
- if( podcastsParent )
+ for ( auto& lItem : listItems )
{
- int c = podcastsParent->childCount();
+ if (lItem->innerTree() == NULL)
+ continue;
+
+ int c = lItem->treeItem()->childCount();
for( int i = 0; i < c; i++ )
{
- QTreeWidgetItem *item = podcastsParent->child(i);
+ QTreeWidgetItem *item = lItem->treeItem()->child(i);
input_item_t *p_input = item->data( 0, IN_ITEM_ROLE ).value<input_item_t*>();
input_item_Release( p_input );
}
}
+
+ for (std::vector<PLSelItem*>::iterator it = listItems.begin();
+ it != listItems.end(); ++it)
+ delete *it;
}
PLSelItem * putSDData( PLSelItem* item, const char* name, const char* longname )
@@ -279,12 +307,18 @@ void PLSelector::createItems()
selItem = addItem( SD_TYPE, *ppsz_longname, false, false, internet );
if( name.startsWith( "podcast" ) )
{
- selItem->treeItem()->setData( 0, SPECIAL_ROLE, QVariant( IS_PODCAST ) );
- selItem->addAction( ADD_ACTION, qtr( "Subscribe to a podcast" ) );
- CONNECT( selItem, action( PLSelItem* ), this, podcastAdd( PLSelItem* ) );
- podcastsParent = selItem->treeItem();
+ selItem->createInnerTree(SLOT(podcastAdd(PLSelItem*)),
+ SLOT(podcastRemove(PLSelItem*)),
+ nullptr);
icon = QIcon( ":/sidebar/podcast" );
}
+ else if ( name.startsWith( "cloudstorage" ))
+ {
+ selItem->createInnerTree(SLOT(cloudProviderAdd(PLSelItem*)),
+ SLOT(cloudProviderRemove(PLSelItem*)),
+ SLOT(cloudProviderActivated(PLSelItem*)));
+ icon = QIcon( ":/sidebar/cloud" );
+ }
else if ( name.startsWith( "lua{" ) )
{
int i_head = name.indexOf( "sd='" ) + 4;
@@ -330,6 +364,14 @@ void PLSelector::createItems()
selItem = addItem( SD_TYPE, *ppsz_longname );
}
+ if (selItem->innerTree() != NULL &&
+ selItem->innerTree()->slotAddFunct() != NULL)
+ {
+ selItem->addAction( ADD_ACTION, qtr( "Add a new item" ) );
+ connect( selItem, SIGNAL(action( PLSelItem* )),
+ this, selItem->innerTree()->slotAddFunct() );
+ }
+
selItem->treeItem()->setData( 0, SD_CATEGORY_ROLE, *p_category );
putSDData( selItem, *ppsz_name, *ppsz_longname );
if ( ! icon.isNull() )
@@ -337,6 +379,8 @@ void PLSelector::createItems()
free( *ppsz_name );
free( *ppsz_longname );
+
+ listItems.push_back( selItem );
}
free( ppsz_names );
free( ppsz_longnames );
@@ -359,6 +403,7 @@ void PLSelector::setSource( QTreeWidgetItem *item )
return;
bool sd_loaded;
+ playlist_item_t *pl_item = NULL;
if( i_type == SD_TYPE )
{
QString qs = item->data( 0, NAME_ROLE ).toString();
@@ -376,41 +421,33 @@ void PLSelector::setSource( QTreeWidgetItem *item )
item->setData( 0, CAP_SEARCH_ROLE, (test.i_capabilities & SD_CAP_SEARCH) );
}
}
- }
-
- curItem = item;
-
- /* */
- playlist_Lock( THEPL );
- playlist_item_t *pl_item = NULL;
- /* Special case for podcast */
- // FIXME: simplify
- if( i_type == SD_TYPE )
- {
+ playlist_Lock( THEPL );
/* Find the right item for the SD */
/* FIXME: searching by name - what could possibly go wrong? */
pl_item = playlist_ChildSearchName( &(THEPL->root),
vlc_gettext(qtu(item->data(0, LONGNAME_ROLE).toString())) );
- /* Podcasts */
- if( item->data( 0, SPECIAL_ROLE ).toInt() == IS_PODCAST )
+ PLSelItem* sel_item = itemWidget( item );
+ if (sel_item != NULL && sel_item->innerTree() != NULL)
{
- if( pl_item && !sd_loaded )
+ if ( pl_item && !sd_loaded )
{
- podcastsParentId = pl_item->i_id;
- for( int i=0; i < pl_item->i_children; i++ )
- addPodcastItem( pl_item->pp_children[i] );
+ sel_item->innerTree()->setParentId( pl_item->i_id );
+ for ( int i = 0; i < pl_item->i_children; i++ )
+ addItemOnTree( pl_item->pp_children[i], sel_item );
}
- pl_item = NULL; //to prevent activating it
+ pl_item = NULL; // prevent sidebar item activation
}
+ playlist_Unlock( THEPL );
}
else
+ {
pl_item = item->data( 0, PL_ITEM_ROLE ).value<playlist_item_t*>();
+ }
- playlist_Unlock( THEPL );
+ curItem = item;
- /* */
if( pl_item )
{
emit categoryActivated( pl_item, false );
@@ -436,19 +473,31 @@ PLSelItem * PLSelector::addItem (
return selItem;
}
-PLSelItem *PLSelector::addPodcastItem( playlist_item_t *p_item )
+PLSelItem *PLSelector::addItemOnTree( playlist_item_t *p_item, PLSelItem* sel_item )
{
input_item_Hold( p_item->p_input );
char *psz_name = input_item_GetName( p_item->p_input );
- PLSelItem *item = addItem( PL_ITEM_TYPE, psz_name, false, false, podcastsParent );
+ QTreeWidgetItem* parent = sel_item->innerTree()->parent();
+ PLSelItem *item = addItem( PL_ITEM_TYPE, psz_name, false, false, parent );
free( psz_name );
- item->addAction( RM_ACTION, qtr( "Remove this podcast subscription" ) );
item->treeItem()->setData( 0, PL_ITEM_ROLE, QVariant::fromValue( p_item ) );
item->treeItem()->setData( 0, PL_ITEM_ID_ROLE, QVariant(p_item->i_id) );
item->treeItem()->setData( 0, IN_ITEM_ROLE, QVariant::fromValue( p_item->p_input ) );
- CONNECT( item, action( PLSelItem* ), this, podcastRemove( PLSelItem* ) );
+
+ if (sel_item->innerTree()->slotActivatedFunct() != nullptr)
+ {
+ connect( item, SIGNAL(subTreeActivated( PLSelItem* )),
+ this, sel_item->innerTree()->slotActivatedFunct() );
+ }
+
+ if (sel_item->innerTree()->slotRemoveFunct() != NULL)
+ {
+ item->addAction( RM_ACTION, qtr( "Remove item" ) );
+ connect( item, SIGNAL(action( PLSelItem* )),
+ this, sel_item->innerTree()->slotRemoveFunct() );
+ }
return item;
}
@@ -503,52 +552,73 @@ void PLSelector::dragMoveEvent ( QDragMoveEvent * event )
void PLSelector::plItemAdded( int item, int parent )
{
updateTotalDuration(playlistItem, "Playlist");
- if( parent != podcastsParentId || podcastsParent == NULL ) return;
playlist_Lock( THEPL );
playlist_item_t *p_item = playlist_ItemGetById( THEPL, item );
- if( !p_item ) {
+ if( !p_item )
+ {
playlist_Unlock( THEPL );
return;
}
- int c = podcastsParent->childCount();
- for( int i = 0; i < c; i++ )
+ PLSelItem* sel_item = NULL;
+
+ for (std::vector<PLSelItem*>::iterator it = listItems.begin();
+ it != listItems.end(); ++it)
+ {
+ PLSelItem* lItem = *it;
+ if (lItem->innerTree() == NULL || lItem->innerTree()->parentId()
+ != parent)
+ continue;
+ sel_item = lItem;
+ }
+
+ if ( sel_item != NULL )
{
- QTreeWidgetItem *podItem = podcastsParent->child(i);
- if( podItem->data( 0, PL_ITEM_ID_ROLE ).toInt() == item )
+ // Check if the item already exists on the tree
+ int childsCounter = sel_item->treeItem()->childCount();
+ for( int i = 0; i < childsCounter; i++ )
{
- //msg_Dbg( p_intf, "Podcast already in: (%d) %s", item, p_item->p_input->psz_uri);
- playlist_Unlock( THEPL );
- return;
+ QTreeWidgetItem *widgetItem = sel_item->treeItem()->child(i);
+ if( widgetItem->data( 0, PL_ITEM_ID_ROLE ).toInt() == item )
+ {
+ // Item already exists
+ playlist_Unlock( THEPL );
+ return;
+ }
}
+ // The items does not exists yet
+ addItemOnTree( p_item, sel_item );
+ sel_item->treeItem()->setExpanded( true );
}
- //msg_Dbg( p_intf, "Adding podcast: (%d) %s", item, p_item->p_input->psz_uri );
- addPodcastItem( p_item );
-
playlist_Unlock( THEPL );
-
- podcastsParent->setExpanded( true );
}
void PLSelector::plItemRemoved( int id )
{
updateTotalDuration(playlistItem, "Playlist");
- if( !podcastsParent ) return;
- int c = podcastsParent->childCount();
- for( int i = 0; i < c; i++ )
+ for (std::vector<PLSelItem*>::iterator it = listItems.begin();
+ it != listItems.end(); ++it)
{
- QTreeWidgetItem *item = podcastsParent->child(i);
- if( item->data( 0, PL_ITEM_ID_ROLE ).toInt() == id )
+ PLSelItem* lItem = *it;
+ if (lItem->innerTree() == NULL)
+ continue;
+
+ int c = lItem->treeItem()->childCount();
+ for( int i = 0; i < c; i++ )
{
- input_item_t *p_input = item->data( 0, IN_ITEM_ROLE ).value<input_item_t*>();
- //msg_Dbg( p_intf, "Removing podcast: (%d) %s", id, p_input->psz_uri );
- input_item_Release( p_input );
- delete item;
- return;
+ QTreeWidgetItem *item = lItem->treeItem()->child(i);
+ if( item->data( 0, PL_ITEM_ID_ROLE ).toInt() == id )
+ {
+ input_item_t *p_input = item->data( 0, IN_ITEM_ROLE ).value<input_item_t*>();
+ //msg_Dbg( p_intf, "Removing podcast: (%d) %s", id, p_input->psz_uri );
+ input_item_Release( p_input );
+ delete item;
+ return;
+ }
}
}
}
@@ -557,28 +627,33 @@ void PLSelector::inputItemUpdate( input_item_t *arg )
{
updateTotalDuration(playlistItem, "Playlist");
- if( podcastsParent == NULL )
- return;
-
- int c = podcastsParent->childCount();
- for( int i = 0; i < c; i++ )
+ for (std::vector<PLSelItem*>::iterator it = listItems.begin();
+ it != listItems.end(); ++it)
{
- QTreeWidgetItem *item = podcastsParent->child(i);
- input_item_t *p_input = item->data( 0, IN_ITEM_ROLE ).value<input_item_t*>();
- if( p_input == arg )
+ PLSelItem* lItem = *it;
+ if (lItem->innerTree() == NULL)
+ continue;
+
+ int c = lItem->treeItem()->childCount();
+ for( int i = 0; i < c; i++ )
{
- PLSelItem *si = itemWidget( item );
- char *psz_name = input_item_GetName( p_input );
- si->setText( qfu( psz_name ) );
- free( psz_name );
- return;
+ QTreeWidgetItem *item = lItem->treeItem()->child(i);
+ input_item_t *p_input = item->data( 0, IN_ITEM_ROLE ).value<input_item_t*>();
+ if( p_input == arg )
+ {
+ PLSelItem *si = itemWidget( item );
+ char *psz_name = input_item_GetName( p_input );
+ si->setText( qfu( psz_name ) );
+ free( psz_name );
+ return;
+ }
}
}
}
-void PLSelector::podcastAdd( PLSelItem * )
+void PLSelector::podcastAdd( PLSelItem * item)
{
- assert( podcastsParent );
+ //assert( podcastsParent );
bool ok;
QString url = QInputDialog::getText( this, qtr( "Subscribe" ),
@@ -586,7 +661,8 @@ void PLSelector::podcastAdd( PLSelItem * )
QLineEdit::Normal, QString(), &ok );
if( !ok || url.isEmpty() ) return;
- setSource( podcastsParent ); //to load the SD in case it's not loaded
+ //to load the SD in case it's not loaded
+ setSource( item->innerTree()->parent() );
QString request("ADD:");
request += url.trimmed();
@@ -613,6 +689,56 @@ void PLSelector::podcastRemove( PLSelItem* item )
free( psz_uri );
}
+void PLSelector::cloudProviderAdd( PLSelItem * item )
+{
+ QStringList items;
+ items << "google" << "onedrive" << "dropbox" << "amazon" << "box";
+ items << "youtube" << "yandex" << "amazons3" << "owncloud" << "mega";
+
+ bool ok;
+ QString provider = QInputDialog::getItem( this,
+ qtr( "Cloud Storage Provider" ),
+ qtr( "Select the provider to authenticate" ),
+ items, 0, false, &ok);
+ if( !ok || provider.isEmpty() ) return;
+
+ //to load the SD in case it's not loaded
+ setSource( item->innerTree()->parent() );
+
+ QString request("ADD:" + provider);
+ var_SetString( THEPL, "cloudstorage-request", qtu( request ) );
+}
+
+void PLSelector::cloudProviderRemove( PLSelItem* item )
+{
+ QString question ( qtr( "Do you really want to remove the service %1?" ) );
+ question = question.arg( item->text() );
+ QMessageBox::StandardButton res =
+ QMessageBox::question( this, qtr( "Logout" ), question,
+ QMessageBox::Yes | QMessageBox::No,
+ QMessageBox::No );
+ if( res == QMessageBox::No ) return;
+
+ input_item_t *input = item->treeItem()->data( 0, IN_ITEM_ROLE ).
+ value<input_item_t*>();
+ if( !input ) return;
+
+ QString request("RM:");
+ request += qfu( input->psz_name );
+ var_SetString( THEPL, "cloudstorage-request", qtu( request ) );
+}
+
+void PLSelector::cloudProviderActivated( PLSelItem* item )
+{
+ input_item_t *input = item->treeItem()->data( 0, IN_ITEM_ROLE ).
+ value<input_item_t*>();
+ if( !input ) return;
+
+ QString request("ACT:");
+ request += qfu( input->psz_name );
+ var_SetString( THEPL, "cloudstorage-request", qtu( request ) );
+}
+
PLSelItem * PLSelector::itemWidget( QTreeWidgetItem *item )
{
return ( static_cast<PLSelItem*>( QTreeWidget::itemWidget( item, 0 ) ) );
@@ -652,3 +778,12 @@ void PLSelector::wheelEvent( QWheelEvent *e )
// Accept this event in order to prevent unwanted volume up/down changes
e->accept();
}
+
+PLSelItemTree::PLSelItemTree(QTreeWidgetItem* parent,
+ const char* slot_add_funct, const char* slot_remove_funct,
+ const char* slot_activate_funct) :
+ parent_ptr(parent), parent_id(-1), slot_add_funct(slot_add_funct),
+ slot_remove_funct(slot_remove_funct),
+ slot_activate_funct(slot_activate_funct)
+{
+}
diff --git a/modules/gui/qt/components/playlist/selector.hpp b/modules/gui/qt/components/playlist/selector.hpp
index b7d629af91..51f1572291 100644
--- a/modules/gui/qt/components/playlist/selector.hpp
+++ b/modules/gui/qt/components/playlist/selector.hpp
@@ -47,8 +47,7 @@ enum SelectorItemType {
};
enum SpecialData {
- IS_PODCAST = 1,
- IS_PL,
+ IS_PL = 1,
IS_ML
};
@@ -76,11 +75,31 @@ protected:
void paintEvent( QPaintEvent * ) Q_DECL_OVERRIDE;
};
+class PLSelItemTree
+{
+public:
+ PLSelItemTree(QTreeWidgetItem*, const char* = nullptr,
+ const char* = nullptr, const char * = nullptr);
+ void setParentId(int id) { parent_id = id; }
+ int parentId() const { return parent_id; }
+ QTreeWidgetItem* parent() const { return parent_ptr; }
+ const char* slotAddFunct() const { return slot_add_funct; }
+ const char* slotRemoveFunct() const { return slot_remove_funct; }
+ const char* slotActivatedFunct() const { return slot_activate_funct; }
+private:
+ QTreeWidgetItem* parent_ptr;
+ int parent_id;
+ const char* slot_add_funct;
+ const char* slot_remove_funct;
+ const char* slot_activate_funct;
+};
+
class PLSelItem : public QWidget
{
Q_OBJECT
public:
PLSelItem( QTreeWidgetItem*, const QString& );
+ virtual ~PLSelItem();
void setText( const QString& text ) { lbl->setText( text ); }
QString text() const { return lbl->text(); }
@@ -88,6 +107,12 @@ public:
void addAction( ItemAction, const QString& toolTip = 0 );
QTreeWidgetItem *treeItem() { return qitem; }
+ void createInnerTree( const char* = nullptr, const char* = nullptr,
+ const char* = nullptr );
+ PLSelItemTree* innerTree() const { return pInnerTree; }
+protected:
+ void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
+
public slots:
void showAction() { if( lblAction ) lblAction->show(); }
void hideAction() { if( lblAction ) lblAction->hide(); }
@@ -96,16 +121,18 @@ private slots:
void triggerAction() { emit action( this ); }
signals:
+ void subTreeActivated( PLSelItem* );
void action( PLSelItem* );
private:
inline void enterEvent( QEvent* ){ showAction(); }
inline void leaveEvent( QEvent* ){ hideAction(); }
- QTreeWidgetItem* qitem;
- QFramelessButton* lblAction;
- QLabel* lbl;
- QHBoxLayout* layout;
+ QTreeWidgetItem * qitem;
+ QFramelessButton * lblAction;
+ QLabel* lbl;
+ QHBoxLayout* layout;
+ PLSelItemTree* pInnerTree;
};
#include <vlc_input_item.h>
@@ -133,7 +160,7 @@ private:
void createItems();
PLSelItem * addItem ( SelectorItemType type, const char* str,
bool drop = false, bool bold = false, QTreeWidgetItem* parentItem = 0 );
- PLSelItem * addPodcastItem( playlist_item_t *p_item );
+ PLSelItem * addItemOnTree( playlist_item_t *p_item, PLSelItem* sel_item );
PLSelItem* playlistItem;
@@ -141,10 +168,9 @@ private:
inline PLSelItem * itemWidget( QTreeWidgetItem * );
- intf_thread_t *p_intf;
- QTreeWidgetItem *podcastsParent;
- int podcastsParentId;
- QTreeWidgetItem *curItem;
+ intf_thread_t * p_intf;
+ QTreeWidgetItem * curItem;
+ std::vector<PLSelItem *> listItems;
private slots:
void setSource( QTreeWidgetItem *item );
@@ -153,6 +179,9 @@ private slots:
void inputItemUpdate( input_item_t * );
void podcastAdd( PLSelItem* );
void podcastRemove( PLSelItem* );
+ void cloudProviderAdd( PLSelItem* );
+ void cloudProviderRemove( PLSelItem* );
+ void cloudProviderActivated( PLSelItem* );
signals:
void categoryActivated( playlist_item_t *, bool );
diff --git a/modules/gui/qt/pixmaps/playlist/sidebar-icons/cloud.png b/modules/gui/qt/pixmaps/playlist/sidebar-icons/cloud.png
new file mode 100644
index 0000000000000000000000000000000000000000..f68cb091452b5a315ee2d411ac7a836545c6142a
GIT binary patch
literal 252
zcmeAS at N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf<Z~8yL>4nJ
za0`PlBg3pY5<tOuo-U3d7QI(58uBqZN*w(t&&9b^_(I1EnFG8naZ~uVs886 at 9-ukL
zY4L at VULq<QGg3C4Of!%EI4S&$&%gK8#)t2(4lJ-c#-u!F!ZhA>iLK#Jq|;m<2ykAL
zw6Jhh=g)gIhxypN;{g at Ta%C^3?TC}lmHEIkd$!Qz&3=!rRJS&8U)j%iT<GfNUB|jJ
uTgANX{>z#iU|HLAl0RqT`U}6rzp^R)a6cNT-Mkj)QU*^~KbLh*2~7a8Qd>X(
literal 0
HcmV?d00001
diff --git a/modules/gui/qt/pixmaps/playlist/sidebar-icons/cloud.svgz b/modules/gui/qt/pixmaps/playlist/sidebar-icons/cloud.svgz
new file mode 100644
index 0000000000000000000000000000000000000000..4258dd1fce7fe73b0ec7a3860a6e28144023a4c5
GIT binary patch
literal 448
zcmV;x0YCm9iwFpKToPCS17mD&b!0Acc4q)>P+f1FFcADJu3zp2ufG9bfk?TFqDpBS
zscEY|RRpX9g>ne!amlamnncw}tt_usyEC)1&aTeCI&$*k)E at hsN)VJ>71_J}=iS4P
z`x`Qy4usr)y}tXfBOAu~cfI3$|F9=tzTFZDlJlES8$veCJP%vWmt}!P!*M+D+p!#)
zwwgF1c|anIqnwmb&-JFrf^_5CLo?^pN;RA*Y3rQcmCt_sDJhxe=g#NU_vK^f*<)Ef
z9meDDzTWnJAp#GQ!hKIK{Uh<z`sMm~&glh+lBKQZ=I<ojdOHneg#(7sPkuc4wb)NN
z{dX57gb3c>Alq}-_D}x<O6MG3yR^uLa&8E2^ijJMWTdnPRS70RMFJF4VAfYdjMdmO
zD<Nf4CJ<w^ki6y<GcmFSOR*HG1PqhHfR5s%VyMduUIZ!@gJmj44NM5Bm~vo|XH6I`
z!7-ac8d(8$XA=}q+M*S$A{9G?V4{VqL_ny>2rM}PE=q%plZ{GZNIDUT${>#gP%6=-
qPO!gbsRl#H&ZGi;3Wy_P^g1WRi%)o=yvV|T7JmRtZbsyP0ssJ2!P9R5
literal 0
HcmV?d00001
diff --git a/modules/gui/qt/vlc.qrc b/modules/gui/qt/vlc.qrc
index 59055fb6bb..3883111699 100644
--- a/modules/gui/qt/vlc.qrc
+++ b/modules/gui/qt/vlc.qrc
@@ -133,6 +133,7 @@
<file alias="library">pixmaps/playlist/sidebar-icons/library.png</file>
<file alias="capture">pixmaps/playlist/sidebar-icons/capture.png</file>
<file alias="lan">pixmaps/playlist/sidebar-icons/lan.png</file>
+ <file alias="cloud">pixmaps/playlist/sidebar-icons/cloud.png</file>
</qresource>
<qresource prefix="/sidebar/sd">
<file alias="icecast">pixmaps/playlist/sidebar-icons/sd/icecast.png</file>
--
2.14.1
More information about the vlc-devel
mailing list