mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-03-20 07:49:42 +01:00
Merge branch 'master' into playlistinterface_ptr
Conflicts: src/libtomahawk/playlistinterface.h
This commit is contained in:
commit
44cbcd434e
README
data
src
CMakeLists.txttomahawkapp.cpp
libtomahawk
sourcetree
items
categoryitems.cppcategoryitems.hgroupitem.cppgroupitem.hhistoryitem.cpphistoryitem.hplaylistitems.cppsourceitem.cppsourceitem.hsourcetreeitem.cppsourcetreeitem.h
sourcedelegate.cppsourcedelegate.hsourcesmodel.cppsourcesmodel.hsourcesproxymodel.cppsourcesproxymodel.hsourcetreeview.cppsourcetreeview.h
2
README
2
README
@ -39,7 +39,7 @@ Dependencies
|
||||
The following dependencies are optional, but recommended:
|
||||
|
||||
Attica 0.2.0 - ftp://ftp.kde.org/pub/kde/stable/attica/
|
||||
jreen (Git) - https://github.com/euroelessar/jreen
|
||||
Jreen 1.0.1 - https://github.com/euroelessar/jreen
|
||||
QTweetLib 0.3.0 - https://github.com/minimoog/QTweetLib
|
||||
|
||||
Third party libraries that we ship with our source:
|
||||
|
Binary file not shown.
Before ![]() (image error) Size: 2.5 KiB After ![]() (image error) Size: 10 KiB ![]() ![]() |
@ -2,7 +2,7 @@
|
||||
// if run in phantomjs add fake Tomahawk environment
|
||||
if(window.Tomahawk === undefined)
|
||||
{
|
||||
alert("PHANTOMJS ENVIRONMENT");
|
||||
// alert("PHANTOMJS ENVIRONMENT");
|
||||
var Tomahawk = {
|
||||
fakeEnv: function()
|
||||
{
|
||||
|
@ -60,11 +60,13 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui}
|
||||
sourcetree/sourcedelegate.cpp
|
||||
sourcetree/animationhelper.cpp
|
||||
sourcetree/items/sourcetreeitem.cpp
|
||||
sourcetree/items/collectionitem.cpp
|
||||
sourcetree/items/sourceitem.cpp
|
||||
sourcetree/items/playlistitems.cpp
|
||||
sourcetree/items/categoryitems.cpp
|
||||
sourcetree/items/genericpageitems.cpp
|
||||
sourcetree/items/temporarypageitem.cpp
|
||||
sourcetree/items/groupitem.cpp
|
||||
sourcetree/items/historyitem.cpp
|
||||
|
||||
breakpad/BreakPad.cpp
|
||||
|
||||
@ -112,11 +114,13 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui}
|
||||
sourcetree/sourcedelegate.h
|
||||
sourcetree/animationhelper.h
|
||||
sourcetree/items/sourcetreeitem.h
|
||||
sourcetree/items/collectionitem.h
|
||||
sourcetree/items/sourceitem.h
|
||||
sourcetree/items/playlistitems.h
|
||||
sourcetree/items/categoryitems.h
|
||||
sourcetree/items/genericpageitems.h
|
||||
sourcetree/items/temporarypageitem.h
|
||||
sourcetree/items/groupitem.h
|
||||
sourcetree/items/historyitem.h
|
||||
|
||||
tomahawktrayicon.h
|
||||
audiocontrols.h
|
||||
|
@ -76,9 +76,9 @@ DatabaseCommand_Resolve::resolve( DatabaseImpl* lib )
|
||||
typedef QPair<int, float> scorepair_t;
|
||||
|
||||
// STEP 1
|
||||
QList< QPair<int, float> > artists = lib->searchTable( "artist", m_query->artist(), 10 );
|
||||
QList< QPair<int, float> > tracks = lib->searchTable( "track", m_query->track(), 10 );
|
||||
QList< QPair<int, float> > albums = lib->searchTable( "album", m_query->album(), 10 );
|
||||
QList< QPair<int, float> > artists = lib->searchTable( "artist", m_query->artist() );
|
||||
QList< QPair<int, float> > tracks = lib->searchTable( "track", m_query->track() );
|
||||
QList< QPair<int, float> > albums = lib->searchTable( "album", m_query->album() );
|
||||
|
||||
if ( artists.length() == 0 || tracks.length() == 0 )
|
||||
{
|
||||
|
@ -385,7 +385,7 @@ DatabaseImpl::searchTable( const QString& table, const QString& name, uint limit
|
||||
return resultslist;
|
||||
|
||||
QList< QPair<int, float> > resultscapped;
|
||||
for ( unsigned int i = 0; i < limit && i < resultsmap.count(); i++ )
|
||||
for ( int i = 0; i < (int)limit && i < resultsmap.count(); i++ )
|
||||
{
|
||||
resultscapped << resultslist.at( i );
|
||||
}
|
||||
|
@ -378,7 +378,7 @@ Servent::readyRead()
|
||||
}
|
||||
|
||||
// they connected to us and want something we are offering
|
||||
if( conntype == "accept-offer" || "push-offer" )
|
||||
if ( conntype == "accept-offer" || conntype == "push-offer" )
|
||||
{
|
||||
sock->_msg.clear();
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << key << nodeid << "socket peer address = " << sock->peerAddress() << "socket peer name = " << sock->peerName();
|
||||
|
@ -53,6 +53,7 @@ public:
|
||||
Q_INVOKABLE void addCustomUrlHandler( const QString& protocol, const QString& callbackFuncName );
|
||||
|
||||
QSharedPointer<QIODevice> customIODeviceFactory( const Tomahawk::result_ptr& result );
|
||||
|
||||
public slots:
|
||||
QByteArray readRaw( const QString& fileName );
|
||||
QString readBase64( const QString& fileName );
|
||||
@ -66,7 +67,6 @@ public slots:
|
||||
|
||||
void addTrackResults( const QVariantMap& results );
|
||||
|
||||
|
||||
private:
|
||||
QString m_scriptPath, m_urlCallback;
|
||||
QVariantMap m_resolverConfig;
|
||||
|
@ -77,8 +77,6 @@ private slots:
|
||||
void resolvingFinished( bool hasResults );
|
||||
|
||||
private:
|
||||
SourcePlaylistInterface();
|
||||
|
||||
Tomahawk::source_ptr m_source;
|
||||
Tomahawk::result_ptr m_currentItem;
|
||||
bool m_gotNextItem;
|
||||
|
@ -34,14 +34,12 @@ ProxyStyle::drawPrimitive( PrimitiveElement pe, const QStyleOption* opt, QPainte
|
||||
{
|
||||
if ( pe == PE_IndicatorBranch )
|
||||
{
|
||||
if ( opt->state & QStyle::State_Children )
|
||||
if ( opt->state & QStyle::State_Children && !w->property( "flattenBranches" ).toBool() )
|
||||
{
|
||||
QRect r = opt->rect;
|
||||
|
||||
int hd = ( opt->rect.height() - ARROW_HEIGHT ) / 2;
|
||||
int wd = ( opt->rect.width() - ARROW_WIDTH ) / 2;
|
||||
r.adjust( wd, hd, 0, 0 );
|
||||
|
||||
QRect r = opt->rect.adjusted( wd, hd, 0, 0 );
|
||||
QPointF pointsOpened[3] = { QPointF( r.x(), r.y() ), QPointF( r.x() + ARROW_WIDTH, r.y() ), QPointF( r.x() + ARROW_WIDTH / 2, r.y() + ARROW_HEIGHT ) };
|
||||
QPointF pointsClosed[3] = { QPointF( r.x(), r.y() ), QPointF( r.x() + ARROW_WIDTH, r.y() + ARROW_HEIGHT / 2 ), QPointF( r.x(), r.y() + ARROW_HEIGHT ) };
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "sourcelist.h"
|
||||
#include "tomahawksettings.h"
|
||||
|
||||
#include "customplaylistview.h"
|
||||
#include "dynamic/widgets/DynamicWidget.h"
|
||||
|
||||
#include "widgets/welcomewidget.h"
|
||||
@ -71,6 +72,7 @@ ViewManager::ViewManager( QObject* parent )
|
||||
, m_widget( new QWidget() )
|
||||
, m_welcomeWidget( new WelcomeWidget() )
|
||||
, m_whatsHotWidget( new WhatsHotWidget() )
|
||||
, m_topLovedWidget( 0 )
|
||||
, m_currentMode( PlaylistInterface::Tree )
|
||||
{
|
||||
s_instance = this;
|
||||
@ -418,6 +420,15 @@ ViewManager::showWhatsHotPage()
|
||||
}
|
||||
|
||||
|
||||
Tomahawk::ViewPage*
|
||||
ViewManager::showTopLovedPage()
|
||||
{
|
||||
if ( !m_topLovedWidget )
|
||||
m_topLovedWidget = new CustomPlaylistView( CustomPlaylistView::AllLovedTracks, source_ptr(), m_widget );
|
||||
|
||||
return show( m_topLovedWidget );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ViewManager::setTableMode()
|
||||
|
@ -90,6 +90,7 @@ public:
|
||||
|
||||
Tomahawk::ViewPage* welcomeWidget() const { return m_welcomeWidget; }
|
||||
Tomahawk::ViewPage* whatsHotWidget() const { return m_whatsHotWidget; }
|
||||
Tomahawk::ViewPage* topLovedWidget() const { return m_topLovedWidget; }
|
||||
ArtistView* superCollectionView() const { return m_superCollectionView; }
|
||||
|
||||
/// Get the view page for the given item. Not pretty...
|
||||
@ -133,6 +134,7 @@ public slots:
|
||||
Tomahawk::ViewPage* showSuperCollection();
|
||||
Tomahawk::ViewPage* showWelcomePage();
|
||||
Tomahawk::ViewPage* showWhatsHotPage();
|
||||
Tomahawk::ViewPage* showTopLovedPage();
|
||||
void showCurrentTrack();
|
||||
|
||||
// Returns the shown viewpage
|
||||
@ -194,6 +196,7 @@ private:
|
||||
QueueView* m_queue;
|
||||
WelcomeWidget* m_welcomeWidget;
|
||||
WhatsHotWidget* m_whatsHotWidget;
|
||||
Tomahawk::ViewPage* m_topLovedWidget;
|
||||
|
||||
QList< Tomahawk::collection_ptr > m_superCollections;
|
||||
|
||||
|
@ -144,7 +144,7 @@ CheckDirModel::getCheck( const QModelIndex& index )
|
||||
CheckDirTree::CheckDirTree( QWidget* parent )
|
||||
: QTreeView( parent )
|
||||
{
|
||||
m_dirModel.setFilter( QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks );
|
||||
m_dirModel.setFilter( QDir::Dirs | QDir::NoDotAndDotDot );
|
||||
m_dirModel.setRootPath( "/" );
|
||||
|
||||
m_dirModel.setNameFilters( QStringList() << "[^\\.]*" );
|
||||
|
@ -365,6 +365,8 @@ CategoryItem::CategoryItem( SourcesModel* model, SourceTreeItem* parent, Sources
|
||||
m_addItem = new CategoryAddItem( model, this, m_category );
|
||||
}
|
||||
// endRowsAdded();
|
||||
|
||||
connect( this, SIGNAL( toggleExpandRequest( SourceTreeItem* ) ), model, SLOT( itemToggleExpandRequest( SourceTreeItem* ) ) );
|
||||
}
|
||||
|
||||
|
||||
@ -405,8 +407,5 @@ CategoryItem::peerSortValue() const
|
||||
void
|
||||
CategoryItem::activate()
|
||||
{
|
||||
if( m_category == SourcesModel::StationsCategory ) {
|
||||
// TODO activate stations page
|
||||
}
|
||||
|
||||
emit toggleExpandRequest( this );
|
||||
}
|
||||
|
@ -75,6 +75,9 @@ public:
|
||||
|
||||
SourcesModel::CategoryType categoryType() { return m_category; }
|
||||
|
||||
signals:
|
||||
void toggleExpandRequest( SourceTreeItem* );
|
||||
|
||||
private:
|
||||
SourcesModel::CategoryType m_category;
|
||||
CategoryAddItem* m_addItem;
|
||||
|
55
src/sourcetree/items/groupitem.cpp
Normal file
55
src/sourcetree/items/groupitem.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "groupitem.h"
|
||||
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
#include "viewmanager.h"
|
||||
#include "audio/audioengine.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
GroupItem::GroupItem( SourcesModel* model, SourceTreeItem* parent, const QString& text, int peerSortValue )
|
||||
: SourceTreeItem( model, parent, SourcesModel::Group )
|
||||
, m_text( text )
|
||||
, m_peerSortValue( peerSortValue )
|
||||
{
|
||||
connect( this, SIGNAL( toggleExpandRequest( SourceTreeItem* ) ), model, SLOT( itemToggleExpandRequest( SourceTreeItem* ) ) );
|
||||
}
|
||||
|
||||
|
||||
GroupItem::~GroupItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GroupItem::activate()
|
||||
{
|
||||
emit toggleExpandRequest( this );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
GroupItem::text() const
|
||||
{
|
||||
return m_text;
|
||||
}
|
53
src/sourcetree/items/groupitem.h
Normal file
53
src/sourcetree/items/groupitem.h
Normal file
@ -0,0 +1,53 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GROUP_ITEM_H
|
||||
#define GROUP_ITEM_H
|
||||
|
||||
#include "sourcetreeitem.h"
|
||||
|
||||
#include "boost/function.hpp"
|
||||
#include "boost/bind.hpp"
|
||||
|
||||
// generic item that has some name, some text, and calls a certain slot when activated. badabing!
|
||||
class GroupItem : public SourceTreeItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
// takes 2 function pointers: show: called when wanting to show the desired view page. get: called to get the view page from ViewManager if it exists
|
||||
GroupItem( SourcesModel* model, SourceTreeItem* parent, const QString& text, int peerSortValue = 0 );
|
||||
virtual ~GroupItem();
|
||||
|
||||
virtual QString text() const;
|
||||
virtual void activate();
|
||||
virtual bool willAcceptDrag( const QMimeData* data ) const { Q_UNUSED( data ); return false; }
|
||||
virtual QIcon icon() const { return QIcon(); }
|
||||
virtual int peerSortValue() const { return m_peerSortValue; }
|
||||
virtual bool isBeingPlayed() const { return false; }
|
||||
|
||||
signals:
|
||||
void activated();
|
||||
void toggleExpandRequest( SourceTreeItem* );
|
||||
|
||||
private:
|
||||
QString m_text;
|
||||
int m_peerSortValue;
|
||||
};
|
||||
|
||||
#endif
|
96
src/sourcetree/items/historyitem.cpp
Normal file
96
src/sourcetree/items/historyitem.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "historyitem.h"
|
||||
|
||||
#include "viewmanager.h"
|
||||
#include "genericpageitems.h"
|
||||
#include "utils/tomahawkutilsgui.h"
|
||||
#include "utils/logger.h"
|
||||
#include "playlist/customplaylistview.h"
|
||||
#include "temporarypageitem.h"
|
||||
#include "sourcelist.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
HistoryItem::HistoryItem( SourcesModel* model, SourceTreeItem* parent, const QString& text, int peerSortValue )
|
||||
: GroupItem( model, parent, text, peerSortValue )
|
||||
{
|
||||
connect( this, SIGNAL( toggleExpandRequest( SourceTreeItem* ) ), model, SLOT( itemToggleExpandRequest( SourceTreeItem* ) ) );
|
||||
connect( ViewManager::instance(), SIGNAL( tempPageActivated( Tomahawk::ViewPage* ) ), SLOT( tempPageActivated( Tomahawk::ViewPage* ) ) );
|
||||
}
|
||||
|
||||
|
||||
HistoryItem::~HistoryItem()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HistoryItem::activate()
|
||||
{
|
||||
emit toggleExpandRequest( this );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HistoryItem::tempPageActivated( Tomahawk::ViewPage* v )
|
||||
{
|
||||
const int idx = children().count();
|
||||
int latest = idx;
|
||||
if ( idx )
|
||||
{
|
||||
latest = children().last()->IDValue();
|
||||
|
||||
foreach ( TemporaryPageItem* page, m_tempItems )
|
||||
{
|
||||
if ( page->page() == v )
|
||||
{
|
||||
emit selectRequest( page );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only keep 5 temporary pages at once
|
||||
while ( m_tempItems.size() > 4 )
|
||||
{
|
||||
TemporaryPageItem* item = m_tempItems.takeFirst();
|
||||
QTimer::singleShot( 0, item, SLOT( removeFromList() ) );
|
||||
}
|
||||
|
||||
emit beginRowsAdded( idx, idx );
|
||||
|
||||
TemporaryPageItem* tempPage = new TemporaryPageItem( model(), this, v, latest + 1 );
|
||||
connect( tempPage, SIGNAL( removed() ), this, SLOT( temporaryPageDestroyed() ) );
|
||||
m_tempItems << tempPage;
|
||||
endRowsAdded();
|
||||
|
||||
emit selectRequest( tempPage );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HistoryItem::temporaryPageDestroyed()
|
||||
{
|
||||
TemporaryPageItem* tempPage = qobject_cast< TemporaryPageItem* >( sender() );
|
||||
Q_ASSERT( tempPage );
|
||||
m_tempItems.removeAll( tempPage );
|
||||
}
|
57
src/sourcetree/items/historyitem.h
Normal file
57
src/sourcetree/items/historyitem.h
Normal file
@ -0,0 +1,57 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef HISTORY_ITEM_H
|
||||
#define HISTORY_ITEM_H
|
||||
|
||||
#include "groupitem.h"
|
||||
|
||||
class TemporaryPageItem;
|
||||
class GenericPageItem;
|
||||
class CategoryItem;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
class ViewPage;
|
||||
}
|
||||
|
||||
class HistoryItem : public GroupItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
HistoryItem( SourcesModel* model, SourceTreeItem* parent, const QString& text, int peerSortValue = 0 );
|
||||
virtual ~HistoryItem();
|
||||
|
||||
virtual void activate();
|
||||
|
||||
signals:
|
||||
void activated();
|
||||
void toggleExpandRequest( SourceTreeItem* );
|
||||
|
||||
private slots:
|
||||
void tempPageActivated( Tomahawk::ViewPage* );
|
||||
void temporaryPageDestroyed();
|
||||
|
||||
private:
|
||||
QList< TemporaryPageItem* > m_tempItems;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
@ -25,7 +25,7 @@
|
||||
#include "viewmanager.h"
|
||||
#include "playlist/dynamic/GeneratorInterface.h"
|
||||
#include "categoryitems.h"
|
||||
#include "collectionitem.h"
|
||||
#include "sourceitem.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
#include "dropjob.h"
|
||||
@ -337,7 +337,7 @@ DynamicPlaylistItem::checkReparentHackNeeded( const DynamicPlaylistRevision& rev
|
||||
CategoryItem* from = cat;
|
||||
CategoryItem* to = 0;
|
||||
if( cat->categoryType() == SourcesModel::PlaylistsCategory && revision.mode == OnDemand ) { // WRONG
|
||||
CollectionItem* col = qobject_cast< CollectionItem* >( cat->parent() );
|
||||
SourceItem* col = qobject_cast< SourceItem* >( cat->parent() );
|
||||
to = col->stationsCategory();
|
||||
if( !to ) { // you have got to be fucking kidding me
|
||||
int fme = col->children().count();
|
||||
@ -348,7 +348,7 @@ DynamicPlaylistItem::checkReparentHackNeeded( const DynamicPlaylistRevision& rev
|
||||
col->setStationsCategory( to );
|
||||
}
|
||||
} else if( cat->categoryType() == SourcesModel::StationsCategory && revision.mode == Static ) { // WRONG
|
||||
CollectionItem* col = qobject_cast< CollectionItem* >( cat->parent() );
|
||||
SourceItem* col = qobject_cast< SourceItem* >( cat->parent() );
|
||||
to = col->playlistsCategory();
|
||||
// qDebug() << "TRYING TO HACK TO:" << to;
|
||||
if( !to ) { // you have got to be fucking kidding me
|
||||
|
@ -16,7 +16,7 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "collectionitem.h"
|
||||
#include "sourceitem.h"
|
||||
|
||||
#include "categoryitems.h"
|
||||
#include "playlistitems.h"
|
||||
@ -28,14 +28,13 @@
|
||||
#include "widgets/SocialPlaylistWidget.h"
|
||||
#include "playlist/customplaylistview.h"
|
||||
#include "source.h"
|
||||
#include "temporarypageitem.h"
|
||||
#include <sourcelist.h>
|
||||
#include "sourcelist.h"
|
||||
|
||||
/// CollectionItem
|
||||
/// SourceItem
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, const Tomahawk::source_ptr& source )
|
||||
SourceItem::SourceItem( SourcesModel* mdl, SourceTreeItem* parent, const Tomahawk::source_ptr& source )
|
||||
: SourceTreeItem( mdl, parent, SourcesModel::Collection )
|
||||
, m_source( source )
|
||||
, m_playlists( 0 )
|
||||
@ -43,51 +42,31 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons
|
||||
, m_latchedOn( false )
|
||||
, m_sourceInfoItem( 0 )
|
||||
, m_coolPlaylistsItem( 0 )
|
||||
, m_lovedTracksItem()
|
||||
, m_collectionPage( 0 )
|
||||
, m_sourceInfoPage( 0 )
|
||||
, m_coolPlaylistsPage( 0 )
|
||||
, m_lovedTracksPage( 0 )
|
||||
, m_whatsHotPage( 0 )
|
||||
{
|
||||
m_lovedTracksItem = new GenericPageItem( model(), this, ( m_source.isNull() ? tr( "Top Loved Tracks" ) : tr( "Loved Tracks" ) ), QIcon( RESPATH "images/loved_playlist.png" ),
|
||||
boost::bind( &CollectionItem::lovedTracksClicked, this ),
|
||||
boost::bind( &CollectionItem::getLovedTracksPage, this ) );
|
||||
m_lovedTracksItem->setSortValue( -250 );
|
||||
|
||||
if ( m_source.isNull() )
|
||||
{
|
||||
// super collection
|
||||
connect( ViewManager::instance(), SIGNAL( tempPageActivated( Tomahawk::ViewPage*) ), this, SLOT( tempPageActivated( Tomahawk::ViewPage* ) ) );
|
||||
|
||||
// add misc children of root node
|
||||
GenericPageItem* recent = new GenericPageItem( model(), this, tr( "Dashboard" ), QIcon( RESPATH "images/dashboard.png" ),
|
||||
boost::bind( &ViewManager::showWelcomePage, ViewManager::instance() ),
|
||||
boost::bind( &ViewManager::welcomeWidget, ViewManager::instance() )
|
||||
);
|
||||
recent->setSortValue( -300 );
|
||||
|
||||
GenericPageItem* hot = new GenericPageItem( model(), this, tr( "Charts" ), QIcon( RESPATH "images/charts.png" ),
|
||||
boost::bind( &ViewManager::showWhatsHotPage, ViewManager::instance() ),
|
||||
boost::bind( &ViewManager::whatsHotWidget, ViewManager::instance() )
|
||||
);
|
||||
hot->setSortValue( -300 );
|
||||
|
||||
|
||||
// TODO finish implementing and making pretty
|
||||
// m_coolPlaylistsItem = new GenericPageItem( model(), this, tr( "Cool Stuff" ), QIcon( RESPATH "images/new-additions.png" ),
|
||||
// boost::bind( &CollectionItem::coolPlaylistsClicked, this ),
|
||||
// boost::bind( &CollectionItem::getCoolPlaylistsPage, this )
|
||||
// );
|
||||
// m_coolPlaylistsItem->setSortValue( 200 );
|
||||
|
||||
m_superCol = TomahawkUtils::createAvatarFrame( QPixmap( RESPATH "images/supercollection.png" ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_lovedTracksItem = new GenericPageItem( model(), this, tr( "Loved Tracks" ), QIcon( RESPATH "images/loved_playlist.png" ),
|
||||
boost::bind( &SourceItem::lovedTracksClicked, this ),
|
||||
boost::bind( &SourceItem::getLovedTracksPage, this ) );
|
||||
m_lovedTracksItem->setSortValue( -250 );
|
||||
|
||||
m_collectionItem = new GenericPageItem( model(), this, tr( "Collection" ), QIcon( RESPATH "images/drop-song.png" ), //FIXME different icon
|
||||
boost::bind( &SourceItem::collectionClicked, this ),
|
||||
boost::bind( &SourceItem::getCollectionPage, this ) );
|
||||
m_collectionItem->setSortValue( -350 );
|
||||
|
||||
m_sourceInfoItem = new GenericPageItem( model(), this, tr( "New Additions" ), QIcon( RESPATH "images/new-additions.png" ),
|
||||
boost::bind( &CollectionItem::sourceInfoClicked, this ),
|
||||
boost::bind( &CollectionItem::getSourceInfoPage, this ) );
|
||||
boost::bind( &SourceItem::sourceInfoClicked, this ),
|
||||
boost::bind( &SourceItem::getSourceInfoPage, this ) );
|
||||
m_sourceInfoItem->setSortValue( -300 );
|
||||
|
||||
// create category items if there are playlists to show, or stations to show
|
||||
@ -114,14 +93,14 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons
|
||||
|
||||
// load auto playlists and stations!
|
||||
|
||||
connect( source.data(), SIGNAL( stats( QVariantMap ) ), this, SIGNAL( updated() ) );
|
||||
connect( source.data(), SIGNAL( syncedWithDatabase() ), this, SIGNAL( updated() ) );
|
||||
connect( source.data(), SIGNAL( playbackStarted( Tomahawk::query_ptr ) ), this, SIGNAL( updated() ) );
|
||||
connect( source.data(), SIGNAL( stateChanged() ), this, SIGNAL( updated() ) );
|
||||
connect( source.data(), SIGNAL( offline() ), this, SIGNAL( updated() ) );
|
||||
connect( source.data(), SIGNAL( online() ), this, SIGNAL( updated() ) );
|
||||
connect( SourceList::instance(), SIGNAL( sourceLatchedOn( Tomahawk::source_ptr, Tomahawk::source_ptr ) ), this, SLOT( latchedOn( Tomahawk::source_ptr, Tomahawk::source_ptr ) ) );
|
||||
connect( SourceList::instance(), SIGNAL( sourceLatchedOff( Tomahawk::source_ptr, Tomahawk::source_ptr ) ), this, SLOT( latchedOff( Tomahawk::source_ptr, Tomahawk::source_ptr ) ) );
|
||||
connect( source.data(), SIGNAL( stats( QVariantMap ) ), SIGNAL( updated() ) );
|
||||
connect( source.data(), SIGNAL( syncedWithDatabase() ), SIGNAL( updated() ) );
|
||||
connect( source.data(), SIGNAL( playbackStarted( Tomahawk::query_ptr ) ), SIGNAL( updated() ) );
|
||||
connect( source.data(), SIGNAL( stateChanged() ), SIGNAL( updated() ) );
|
||||
connect( source.data(), SIGNAL( offline() ), SIGNAL( updated() ) );
|
||||
connect( source.data(), SIGNAL( online() ), SIGNAL( updated() ) );
|
||||
connect( SourceList::instance(), SIGNAL( sourceLatchedOn( Tomahawk::source_ptr, Tomahawk::source_ptr ) ), SLOT( latchedOn( Tomahawk::source_ptr, Tomahawk::source_ptr ) ) );
|
||||
connect( SourceList::instance(), SIGNAL( sourceLatchedOff( Tomahawk::source_ptr, Tomahawk::source_ptr ) ), SLOT( latchedOff( Tomahawk::source_ptr, Tomahawk::source_ptr ) ) );
|
||||
|
||||
connect( source->collection().data(), SIGNAL( playlistsAdded( QList<Tomahawk::playlist_ptr> ) ),
|
||||
SLOT( onPlaylistsAdded( QList<Tomahawk::playlist_ptr> ) ), Qt::QueuedConnection );
|
||||
@ -131,30 +110,30 @@ CollectionItem::CollectionItem( SourcesModel* mdl, SourceTreeItem* parent, cons
|
||||
SLOT( onStationsAdded( QList<Tomahawk::dynplaylist_ptr> ) ), Qt::QueuedConnection );
|
||||
|
||||
if ( m_source->isLocal() )
|
||||
QTimer::singleShot(0, this, SLOT(requestExpanding()));
|
||||
QTimer::singleShot( 0, this, SLOT( requestExpanding() ) );
|
||||
}
|
||||
|
||||
|
||||
Tomahawk::source_ptr
|
||||
CollectionItem::source() const
|
||||
SourceItem::source() const
|
||||
{
|
||||
return m_source;
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
CollectionItem::text() const
|
||||
SourceItem::text() const
|
||||
{
|
||||
return m_source.isNull() ? tr( "Super Collection" ) : m_source->friendlyName();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
CollectionItem::IDValue() const
|
||||
SourceItem::IDValue() const
|
||||
{
|
||||
if( m_source.isNull() )
|
||||
if ( m_source.isNull() )
|
||||
return -1;
|
||||
if( m_source->isLocal() )
|
||||
if ( m_source->isLocal() )
|
||||
return 0;
|
||||
|
||||
return m_source->id();
|
||||
@ -162,46 +141,46 @@ CollectionItem::IDValue() const
|
||||
|
||||
|
||||
int
|
||||
CollectionItem::peerSortValue() const
|
||||
SourceItem::peerSortValue() const
|
||||
{
|
||||
if( m_source.isNull() )
|
||||
if ( m_source.isNull() || m_source->isLocal() )
|
||||
return -1;
|
||||
if( m_source->isLocal() )
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CollectionItem::activate()
|
||||
SourceItem::activate()
|
||||
{
|
||||
ViewPage* p = 0;
|
||||
if ( source().isNull() )
|
||||
p = ViewManager::instance()->showSuperCollection();
|
||||
else
|
||||
p = ViewManager::instance()->show( source()->collection() );
|
||||
emit toggleExpandRequest( this );
|
||||
// p = ViewManager::instance()->show( source()->collection() );
|
||||
|
||||
model()->linkSourceItemToPage( this, p );
|
||||
}
|
||||
|
||||
|
||||
QIcon
|
||||
CollectionItem::icon() const
|
||||
SourceItem::icon() const
|
||||
{
|
||||
if ( m_source.isNull() )
|
||||
return m_superCol;
|
||||
else
|
||||
{
|
||||
if( m_source->avatar().isNull() )
|
||||
if ( m_source->avatar().isNull() )
|
||||
return m_defaultAvatar;
|
||||
else
|
||||
return m_source->avatar( Source::FancyStyle );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
CollectionItem::localLatchedOn() const
|
||||
SourceItem::localLatchedOn() const
|
||||
{
|
||||
// Don't show a listen icon if this is the local collection and we are latched on to someone who went offline
|
||||
// we are technically still latched on (if they come back online we'll be still listening along) but it's not visible
|
||||
@ -216,7 +195,7 @@ CollectionItem::localLatchedOn() const
|
||||
|
||||
|
||||
void
|
||||
CollectionItem::latchedOff( const source_ptr& from, const source_ptr& to )
|
||||
SourceItem::latchedOff( const source_ptr& from, const source_ptr& to )
|
||||
{
|
||||
if ( from->isLocal() && ( m_source == to || m_source == from ) )
|
||||
{
|
||||
@ -226,8 +205,9 @@ CollectionItem::latchedOff( const source_ptr& from, const source_ptr& to )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CollectionItem::latchedOn( const source_ptr& from, const source_ptr& to )
|
||||
SourceItem::latchedOn( const source_ptr& from, const source_ptr& to )
|
||||
{
|
||||
if ( from->isLocal() && ( m_source == to || m_source == from ) )
|
||||
{
|
||||
@ -239,29 +219,32 @@ CollectionItem::latchedOn( const source_ptr& from, const source_ptr& to )
|
||||
|
||||
|
||||
void
|
||||
CollectionItem::playlistsAddedInternal( SourceTreeItem* parent, const QList< dynplaylist_ptr >& playlists )
|
||||
SourceItem::playlistsAddedInternal( SourceTreeItem* parent, const QList< dynplaylist_ptr >& playlists )
|
||||
{
|
||||
QList< SourceTreeItem* > items;
|
||||
int addOffset = playlists.first()->author()->isLocal() ? 1 : 0;
|
||||
|
||||
int from = parent->children().count() - addOffset;
|
||||
parent->beginRowsAdded( from, from + playlists.count() - 1 );
|
||||
foreach( const dynplaylist_ptr& p, playlists )
|
||||
foreach ( const dynplaylist_ptr& p, playlists )
|
||||
{
|
||||
DynamicPlaylistItem* plItem = new DynamicPlaylistItem( model(), parent, p, parent->children().count() - addOffset );
|
||||
// qDebug() << "Dynamic Playlist added:" << p->title() << p->creator() << p->info();
|
||||
p->loadRevision();
|
||||
items << plItem;
|
||||
|
||||
if( p->mode() == Static ) {
|
||||
if( m_source->isLocal() )
|
||||
if ( p->mode() == Static )
|
||||
{
|
||||
if ( m_source->isLocal() )
|
||||
connect( p.data(), SIGNAL( aboutToBeDeleted( Tomahawk::dynplaylist_ptr ) ),
|
||||
SLOT( onAutoPlaylistDeleted( Tomahawk::dynplaylist_ptr ) ), Qt::QueuedConnection );
|
||||
else
|
||||
connect( p.data(), SIGNAL( deleted( Tomahawk::dynplaylist_ptr ) ),
|
||||
SLOT( onAutoPlaylistDeleted( Tomahawk::dynplaylist_ptr ) ), Qt::QueuedConnection );
|
||||
} else {
|
||||
if( m_source->isLocal() )
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_source->isLocal() )
|
||||
connect( p.data(), SIGNAL( aboutToBeDeleted( Tomahawk::dynplaylist_ptr ) ),
|
||||
SLOT( onStationDeleted( Tomahawk::dynplaylist_ptr ) ), Qt::QueuedConnection );
|
||||
else
|
||||
@ -275,7 +258,7 @@ CollectionItem::playlistsAddedInternal( SourceTreeItem* parent, const QList< dyn
|
||||
|
||||
template< typename T >
|
||||
void
|
||||
CollectionItem::playlistDeletedInternal( SourceTreeItem* parent, const T& p )
|
||||
SourceItem::playlistDeletedInternal( SourceTreeItem* parent, const T& p )
|
||||
{
|
||||
Q_ASSERT( parent ); // How can we delete playlists if we have none?
|
||||
int curCount = parent->children().count();
|
||||
@ -314,7 +297,7 @@ CollectionItem::playlistDeletedInternal( SourceTreeItem* parent, const T& p )
|
||||
|
||||
|
||||
void
|
||||
CollectionItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists )
|
||||
SourceItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists )
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO << m_source->friendlyName() << playlists.count();
|
||||
|
||||
@ -355,14 +338,14 @@ CollectionItem::onPlaylistsAdded( const QList< playlist_ptr >& playlists )
|
||||
|
||||
|
||||
void
|
||||
CollectionItem::onPlaylistDeleted( const playlist_ptr& playlist )
|
||||
SourceItem::onPlaylistDeleted( const playlist_ptr& playlist )
|
||||
{
|
||||
playlistDeletedInternal( m_playlists, playlist );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CollectionItem::onAutoPlaylistsAdded( const QList< dynplaylist_ptr >& playlists )
|
||||
SourceItem::onAutoPlaylistsAdded( const QList< dynplaylist_ptr >& playlists )
|
||||
{
|
||||
if( playlists.isEmpty() )
|
||||
return;
|
||||
@ -381,7 +364,7 @@ CollectionItem::onAutoPlaylistsAdded( const QList< dynplaylist_ptr >& playlists
|
||||
|
||||
|
||||
void
|
||||
CollectionItem::onAutoPlaylistDeleted( const dynplaylist_ptr& playlist )
|
||||
SourceItem::onAutoPlaylistDeleted( const dynplaylist_ptr& playlist )
|
||||
{
|
||||
if( !m_playlists )
|
||||
qDebug() << "NO playlist category item for a deleting playlist..";
|
||||
@ -391,7 +374,7 @@ CollectionItem::onAutoPlaylistDeleted( const dynplaylist_ptr& playlist )
|
||||
|
||||
|
||||
void
|
||||
CollectionItem::onStationsAdded( const QList< dynplaylist_ptr >& stations )
|
||||
SourceItem::onStationsAdded( const QList< dynplaylist_ptr >& stations )
|
||||
{
|
||||
if( stations.isEmpty() )
|
||||
return;
|
||||
@ -410,59 +393,21 @@ CollectionItem::onStationsAdded( const QList< dynplaylist_ptr >& stations )
|
||||
|
||||
|
||||
void
|
||||
CollectionItem::onStationDeleted( const dynplaylist_ptr& station )
|
||||
SourceItem::onStationDeleted( const dynplaylist_ptr& station )
|
||||
{
|
||||
playlistDeletedInternal( m_stations, station );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CollectionItem::requestExpanding()
|
||||
SourceItem::requestExpanding()
|
||||
{
|
||||
emit expandRequest(this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CollectionItem::tempPageActivated( Tomahawk::ViewPage* v )
|
||||
{
|
||||
const int idx = children().count();
|
||||
const int latest = children().last()->IDValue();
|
||||
|
||||
foreach ( TemporaryPageItem* page, m_tempItems )
|
||||
{
|
||||
if ( page->page() == v )
|
||||
{
|
||||
emit selectRequest( page );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Only keep 5 temporary pages at once
|
||||
while ( m_tempItems.size() > 4 )
|
||||
{
|
||||
TemporaryPageItem* item = m_tempItems.takeFirst();
|
||||
QTimer::singleShot( 0, item, SLOT( removeFromList() ) );
|
||||
}
|
||||
emit beginRowsAdded( idx, idx );
|
||||
TemporaryPageItem* tempPage = new TemporaryPageItem( model(), this, v, latest + 1 );
|
||||
connect( tempPage, SIGNAL( removed() ), this, SLOT( temporaryPageDestroyed() ) );
|
||||
m_tempItems << tempPage;
|
||||
endRowsAdded();
|
||||
emit selectRequest( tempPage );
|
||||
}
|
||||
|
||||
void
|
||||
CollectionItem::temporaryPageDestroyed()
|
||||
{
|
||||
TemporaryPageItem* tempPage = qobject_cast< TemporaryPageItem* >( sender() );
|
||||
Q_ASSERT( tempPage );
|
||||
m_tempItems.removeAll( tempPage );
|
||||
emit expandRequest( this );
|
||||
}
|
||||
|
||||
|
||||
ViewPage*
|
||||
CollectionItem::sourceInfoClicked()
|
||||
SourceItem::sourceInfoClicked()
|
||||
{
|
||||
if( m_source.isNull() )
|
||||
return 0;
|
||||
@ -473,19 +418,37 @@ CollectionItem::sourceInfoClicked()
|
||||
|
||||
|
||||
ViewPage*
|
||||
CollectionItem::getSourceInfoPage() const
|
||||
SourceItem::getSourceInfoPage() const
|
||||
{
|
||||
return m_sourceInfoPage;
|
||||
}
|
||||
|
||||
|
||||
ViewPage*
|
||||
CollectionItem::coolPlaylistsClicked()
|
||||
SourceItem::collectionClicked()
|
||||
{
|
||||
if( !m_source.isNull() )
|
||||
if( m_source.isNull() )
|
||||
return 0;
|
||||
|
||||
if( !m_coolPlaylistsPage )
|
||||
m_collectionPage = ViewManager::instance()->show( m_source->collection() );
|
||||
return m_collectionPage;
|
||||
}
|
||||
|
||||
|
||||
ViewPage*
|
||||
SourceItem::getCollectionPage() const
|
||||
{
|
||||
return m_collectionPage;;
|
||||
}
|
||||
|
||||
|
||||
ViewPage*
|
||||
SourceItem::coolPlaylistsClicked()
|
||||
{
|
||||
if ( !m_source.isNull() )
|
||||
return 0;
|
||||
|
||||
if ( !m_coolPlaylistsPage )
|
||||
m_coolPlaylistsPage = new SocialPlaylistWidget( ViewManager::instance()->widget() );
|
||||
|
||||
ViewManager::instance()->show( m_coolPlaylistsPage );
|
||||
@ -494,16 +457,16 @@ CollectionItem::coolPlaylistsClicked()
|
||||
|
||||
|
||||
ViewPage*
|
||||
CollectionItem::getCoolPlaylistsPage() const
|
||||
SourceItem::getCoolPlaylistsPage() const
|
||||
{
|
||||
return m_coolPlaylistsPage;
|
||||
}
|
||||
|
||||
|
||||
ViewPage*
|
||||
CollectionItem::lovedTracksClicked()
|
||||
SourceItem::lovedTracksClicked()
|
||||
{
|
||||
if( !m_lovedTracksPage )
|
||||
if ( !m_lovedTracksPage )
|
||||
m_lovedTracksPage = new CustomPlaylistView( m_source.isNull() ? CustomPlaylistView::AllLovedTracks : CustomPlaylistView::SourceLovedTracks, m_source, ViewManager::instance()->widget() );
|
||||
|
||||
ViewManager::instance()->show( m_lovedTracksPage );
|
||||
@ -512,7 +475,7 @@ CollectionItem::lovedTracksClicked()
|
||||
|
||||
|
||||
ViewPage*
|
||||
CollectionItem::getLovedTracksPage() const
|
||||
SourceItem::getLovedTracksPage() const
|
||||
{
|
||||
return m_lovedTracksPage;
|
||||
}
|
@ -16,8 +16,8 @@
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef COLLECTION_ITEM_H
|
||||
#define COLLECTION_ITEM_H
|
||||
#ifndef SOURCE_ITEM_H
|
||||
#define SOURCE_ITEM_H
|
||||
|
||||
#include "sourcetreeitem.h"
|
||||
|
||||
@ -30,11 +30,11 @@ namespace Tomahawk
|
||||
class ViewPage;
|
||||
}
|
||||
|
||||
class CollectionItem : public SourceTreeItem
|
||||
class SourceItem : public SourceTreeItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CollectionItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::source_ptr& source );
|
||||
SourceItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::source_ptr& source );
|
||||
|
||||
virtual QString text() const;
|
||||
virtual void activate();
|
||||
@ -64,12 +64,12 @@ private slots:
|
||||
|
||||
void requestExpanding();
|
||||
|
||||
void tempPageActivated( Tomahawk::ViewPage* );
|
||||
void temporaryPageDestroyed();
|
||||
|
||||
Tomahawk::ViewPage* sourceInfoClicked();
|
||||
Tomahawk::ViewPage* getSourceInfoPage() const;
|
||||
|
||||
Tomahawk::ViewPage* collectionClicked();
|
||||
Tomahawk::ViewPage* getCollectionPage() const;
|
||||
|
||||
Tomahawk::ViewPage* coolPlaylistsClicked();
|
||||
Tomahawk::ViewPage* getCoolPlaylistsPage() const;
|
||||
|
||||
@ -89,11 +89,12 @@ private:
|
||||
bool m_latchedOn;
|
||||
Tomahawk::source_ptr m_latchedOnTo;
|
||||
|
||||
QList< TemporaryPageItem* > m_tempItems;
|
||||
GenericPageItem* m_collectionItem;
|
||||
GenericPageItem* m_sourceInfoItem;
|
||||
GenericPageItem* m_coolPlaylistsItem;
|
||||
GenericPageItem* m_lovedTracksItem;
|
||||
|
||||
Tomahawk::ViewPage* m_collectionPage;
|
||||
Tomahawk::ViewPage* m_sourceInfoPage;
|
||||
Tomahawk::ViewPage* m_coolPlaylistsPage;
|
||||
Tomahawk::ViewPage* m_lovedTracksPage;
|
@ -29,18 +29,20 @@ SourceTreeItem::SourceTreeItem( SourcesModel* model, SourceTreeItem* parent, Sou
|
||||
, m_parent( parent )
|
||||
, m_model( model )
|
||||
{
|
||||
connect( this, SIGNAL( beginChildRowsAdded( int,int ) ), m_model, SLOT( onItemRowsAddedBegin( int,int ) ) );
|
||||
connect( this, SIGNAL( beginChildRowsRemoved( int,int ) ), m_model, SLOT( onItemRowsRemovedBegin( int,int ) ) );
|
||||
connect( this, SIGNAL( beginChildRowsAdded( int, int ) ), m_model, SLOT( onItemRowsAddedBegin( int, int ) ) );
|
||||
connect( this, SIGNAL( beginChildRowsRemoved( int, int ) ), m_model, SLOT( onItemRowsRemovedBegin( int, int ) ) );
|
||||
connect( this, SIGNAL( childRowsAdded() ), m_model, SLOT( onItemRowsAddedDone() ) );
|
||||
connect( this, SIGNAL( childRowsRemoved() ), m_model, SLOT( onItemRowsRemovedDone() ) );
|
||||
connect( this, SIGNAL( updated() ), m_model, SLOT( itemUpdated() ) );
|
||||
connect( this, SIGNAL( selectRequest( SourceTreeItem* ) ), m_model, SLOT( itemSelectRequest( SourceTreeItem* ) ) );
|
||||
connect( this, SIGNAL( expandRequest( SourceTreeItem* ) ), m_model, SLOT( itemExpandRequest( SourceTreeItem* ) ) );
|
||||
if( !m_parent )
|
||||
connect( this, SIGNAL( toggleExpandRequest( SourceTreeItem* ) ), m_model, SLOT( itemToggleExpandRequest( SourceTreeItem* ) ) );
|
||||
|
||||
if ( !m_parent )
|
||||
return;
|
||||
|
||||
// caller must call begin/endInsertRows
|
||||
if( index < 0 )
|
||||
if ( index < 0 )
|
||||
m_parent->appendChild( this );
|
||||
else
|
||||
m_parent->insertChild( index, this );
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "sourcesmodel.h"
|
||||
|
||||
class QMimeData;
|
||||
|
||||
class SourceTreeItem : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -80,6 +81,7 @@ signals:
|
||||
void updated();
|
||||
void selectRequest( SourceTreeItem* );
|
||||
void expandRequest( SourceTreeItem* );
|
||||
void toggleExpandRequest( SourceTreeItem* );
|
||||
|
||||
void beginChildRowsAdded( int fromRow, int toRow );
|
||||
void childRowsAdded();
|
||||
@ -90,6 +92,7 @@ signals:
|
||||
protected:
|
||||
void setRowType( SourcesModel::RowType t ) { m_type = t; }
|
||||
void setParentItem( SourceTreeItem* item ) { m_parent = item; }
|
||||
|
||||
private:
|
||||
SourcesModel::RowType m_type;
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "sourcedelegate.h"
|
||||
|
||||
#include "items/sourcetreeitem.h"
|
||||
#include "items/collectionitem.h"
|
||||
#include "items/sourceitem.h"
|
||||
#include "items/playlistitems.h"
|
||||
#include "items/categoryitems.h"
|
||||
#include "items/temporarypageitem.h"
|
||||
@ -37,7 +37,7 @@
|
||||
#include <audio/audioengine.h>
|
||||
#include <actioncollection.h>
|
||||
|
||||
#define TREEVIEW_INDENT_ADD -7
|
||||
#define TREEVIEW_INDENT_ADD 12
|
||||
|
||||
|
||||
SourceDelegate::SourceDelegate( QAbstractItemView* parent )
|
||||
@ -81,17 +81,21 @@ QSize
|
||||
SourceDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
SourceTreeItem *item = index.data( SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >();
|
||||
SourcesModel::RowType type = static_cast< SourcesModel::RowType >( index.data( SourcesModel::SourceTreeItemTypeRole ).toInt() );
|
||||
|
||||
if ( index.data( SourcesModel::SourceTreeItemTypeRole ).toInt() == SourcesModel::Collection )
|
||||
if ( type == SourcesModel::Collection )
|
||||
{
|
||||
return QSize( option.rect.width(), 44 );
|
||||
return QSize( option.rect.width(), 40 );
|
||||
}
|
||||
else if ( type == SourcesModel::Divider )
|
||||
{
|
||||
return QSize( option.rect.width(), 6 );
|
||||
}
|
||||
else if ( m_expandedMap.contains( index ) )
|
||||
{
|
||||
if ( !m_expandedMap.value( index )->initialized() )
|
||||
{
|
||||
int dropTypes = dropTypeCount( item );
|
||||
qDebug() << "droptypecount is " << dropTypes;
|
||||
QSize originalSize = QStyledItemDelegate::sizeHint( option, index );
|
||||
QSize targetSize = originalSize + QSize( 0, dropTypes == 0 ? 0 : 56 );
|
||||
m_expandedMap.value( index )->initialize( originalSize, targetSize, 300 );
|
||||
@ -105,166 +109,286 @@ SourceDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex&
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceDelegate::paintDecorations( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
SourcesModel::RowType type = static_cast< SourcesModel::RowType >( index.data( SourcesModel::SourceTreeItemTypeRole ).toInt() );
|
||||
SourceTreeItem* item = index.data( SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >();
|
||||
|
||||
// Paint the speaker icon next to the currently-playing playlist
|
||||
const bool playable = ( type == SourcesModel::StaticPlaylist ||
|
||||
type == SourcesModel::AutomaticPlaylist ||
|
||||
type == SourcesModel::Station ||
|
||||
type == SourcesModel::TemporaryPage ||
|
||||
type == SourcesModel::GenericPage );
|
||||
const bool playing = ( AudioEngine::instance()->isPlaying() || AudioEngine::instance()->isPaused() );
|
||||
|
||||
if ( playable && playing && item->isBeingPlayed() )
|
||||
{
|
||||
const int iconW = option.rect.height() - 4;
|
||||
QRect iconRect = QRect( option.rect.x() - iconW - 4, option.rect.y() + 2, iconW, iconW );
|
||||
QPixmap speaker = option.state & QStyle::State_Selected ? m_nowPlayingSpeaker : m_nowPlayingSpeakerDark;
|
||||
speaker = speaker.scaledToHeight( iconW, Qt::SmoothTransformation );
|
||||
painter->drawPixmap( iconRect, speaker );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceDelegate::paintCollection( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
QFont normal = painter->font();
|
||||
QFont bold = painter->font();
|
||||
bold.setBold( true );
|
||||
|
||||
SourceTreeItem* item = index.data( SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >();
|
||||
SourceItem* colItem = qobject_cast< SourceItem* >( item );
|
||||
Q_ASSERT( colItem );
|
||||
bool status = !( !colItem || colItem->source().isNull() || !colItem->source()->isOnline() );
|
||||
|
||||
QString tracks;
|
||||
QString name = index.data().toString();
|
||||
int figWidth = 0;
|
||||
|
||||
if ( status && colItem && !colItem->source().isNull() )
|
||||
{
|
||||
tracks = QString::number( colItem->source()->trackCount() );
|
||||
figWidth = painter->fontMetrics().width( tracks );
|
||||
name = colItem->source()->friendlyName();
|
||||
}
|
||||
|
||||
QRect iconRect = option.rect.adjusted( 4, 6, -option.rect.width() + option.rect.height() - 12 + 4, -6 );
|
||||
|
||||
QPixmap avatar = colItem->icon().pixmap( iconRect.size() );
|
||||
painter->drawPixmap( iconRect, avatar.scaledToHeight( iconRect.height(), Qt::SmoothTransformation ) );
|
||||
|
||||
if ( ( option.state & QStyle::State_Selected ) == QStyle::State_Selected )
|
||||
{
|
||||
painter->setPen( option.palette.color( QPalette::HighlightedText ) );
|
||||
}
|
||||
|
||||
QRect textRect = option.rect.adjusted( iconRect.width() + 8, 6, -figWidth - 24, 0 );
|
||||
if ( status || colItem->source().isNull() )
|
||||
painter->setFont( bold );
|
||||
QString text = painter->fontMetrics().elidedText( name, Qt::ElideRight, textRect.width() );
|
||||
painter->drawText( textRect, text );
|
||||
|
||||
bool isPlaying = false;
|
||||
QString desc = status ? colItem->source()->textStatus() : tr( "Offline" );
|
||||
if ( colItem->source().isNull() )
|
||||
desc = tr( "All available tracks" );
|
||||
if ( status && desc.isEmpty() && !colItem->source()->currentTrack().isNull() )
|
||||
{
|
||||
desc = colItem->source()->currentTrack()->artist() + " - " + colItem->source()->currentTrack()->track();
|
||||
isPlaying = true;
|
||||
}
|
||||
if ( desc.isEmpty() )
|
||||
desc = tr( "Online" );
|
||||
|
||||
textRect = option.rect.adjusted( iconRect.width() + 8, painter->fontMetrics().height() + 9, -figWidth - 24, -6 );
|
||||
painter->setFont( normal );
|
||||
bool privacyOn = TomahawkSettings::instance()->privateListeningMode() == TomahawkSettings::FullyPrivate;
|
||||
if ( !colItem->source().isNull() && colItem->source()->isLocal() && privacyOn )
|
||||
{
|
||||
QRect pmRect = textRect;
|
||||
pmRect.setTop( pmRect.bottom() - painter->fontMetrics().height() + 3 );
|
||||
pmRect.setRight( pmRect.left() + pmRect.height() );
|
||||
ActionCollection::instance()->getAction( "togglePrivacy" )->icon().paint( painter, pmRect );
|
||||
textRect.adjust( pmRect.width() + 3, 0, 0, 0 );
|
||||
}
|
||||
if ( isPlaying || ( !colItem->source().isNull() && colItem->source()->isLocal() ) )
|
||||
{
|
||||
// Show a listen icon
|
||||
QPixmap pm;
|
||||
if ( index.data( SourcesModel::LatchedOnRole ).toBool() )
|
||||
{
|
||||
// Currently listening along
|
||||
pm = m_headphonesOn;
|
||||
}
|
||||
else if ( !colItem->source()->isLocal() )
|
||||
{
|
||||
pm = m_headphonesOff;
|
||||
}
|
||||
|
||||
if ( !pm.isNull() )
|
||||
{
|
||||
QRect pmRect = textRect;
|
||||
pmRect.setTop( pmRect.bottom() - painter->fontMetrics().height() + 3 );
|
||||
pmRect.setRight( pmRect.left() + pmRect.height() );
|
||||
painter->drawPixmap( pmRect, pm.scaledToHeight( pmRect.height(), Qt::SmoothTransformation ) );
|
||||
textRect.adjust( pmRect.width() + 3, 0, 0, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
text = painter->fontMetrics().elidedText( desc, Qt::ElideRight, textRect.width() );
|
||||
QTextOption to( Qt::AlignBottom );
|
||||
painter->drawText( textRect, text, to );
|
||||
|
||||
if ( status )
|
||||
{
|
||||
painter->setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
QRect figRect = option.rect.adjusted( option.rect.width() - figWidth - 8, 0, -13, -option.rect.height() + 16 );
|
||||
int hd = ( option.rect.height() - figRect.height() ) / 2;
|
||||
figRect.adjust( 0, hd, 0, hd );
|
||||
#ifdef Q_WS_WIN
|
||||
figRect.adjust( -3, 0, 3, 0 );
|
||||
#endif
|
||||
painter->setFont( bold );
|
||||
|
||||
QColor figColor( 167, 183, 211 );
|
||||
painter->setPen( figColor );
|
||||
painter->setBrush( figColor );
|
||||
|
||||
TomahawkUtils::drawBackgroundAndNumbers( painter, tracks, figRect );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceDelegate::paintCategory( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
QTextOption to( Qt::AlignVCenter );
|
||||
|
||||
painter->setPen( option.palette.color( QPalette::Base ) );
|
||||
painter->setBrush( option.palette.color( QPalette::Base ) );
|
||||
painter->drawRect( option.rect );
|
||||
painter->setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
painter->setPen( Qt::white );
|
||||
painter->drawText( option.rect.translated( 4, 1 ), index.data().toString().toUpper(), to );
|
||||
painter->setPen( QColor( 99, 113, 128 ) );
|
||||
painter->drawText( option.rect.translated( 4, 0 ), index.data().toString().toUpper(), to );
|
||||
|
||||
if ( option.state & QStyle::State_MouseOver )
|
||||
{
|
||||
QString text = tr( "Show" );
|
||||
if ( option.state & QStyle::State_Open )
|
||||
text = tr( "Hide" );
|
||||
|
||||
QFont font = painter->font();
|
||||
font.setPixelSize( 11 );
|
||||
font.setBold( true );
|
||||
painter->setFont( font );
|
||||
QTextOption to( Qt::AlignVCenter | Qt::AlignRight );
|
||||
|
||||
// draw close icon
|
||||
painter->setPen( Qt::white );
|
||||
painter->drawText( option.rect.translated( -4, 1 ), text, to );
|
||||
painter->setPen( QColor( 99, 113, 128 ) );
|
||||
painter->drawText( option.rect.translated( -4, 0 ), text, to );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceDelegate::paintGroup( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
QFont font = painter->font();
|
||||
font.setPixelSize( 12 );
|
||||
font.setBold( true );
|
||||
painter->setFont( font );
|
||||
|
||||
QTextOption to( Qt::AlignVCenter );
|
||||
|
||||
painter->setPen( option.palette.color( QPalette::Base ) );
|
||||
painter->setBrush( option.palette.color( QPalette::Base ) );
|
||||
painter->drawRect( option.rect );
|
||||
painter->setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
painter->setPen( Qt::white );
|
||||
painter->drawText( option.rect.translated( 4, 1 ), index.data().toString().toUpper(), to );
|
||||
painter->setPen( QColor( 99, 113, 128 ) );
|
||||
painter->drawText( option.rect.translated( 4, 0 ), index.data().toString().toUpper(), to );
|
||||
|
||||
if ( option.state & QStyle::State_MouseOver )
|
||||
{
|
||||
QString text = tr( "Show" );
|
||||
if ( option.state & QStyle::State_Open )
|
||||
text = tr( "Hide" );
|
||||
|
||||
font.setPixelSize( font.pixelSize() - 1 );
|
||||
painter->setFont( font );
|
||||
QTextOption to( Qt::AlignVCenter | Qt::AlignRight );
|
||||
|
||||
// draw close icon
|
||||
painter->setPen( Qt::white );
|
||||
painter->drawText( option.rect.translated( -4, 1 ), text, to );
|
||||
painter->setPen( QColor( 99, 113, 128 ) );
|
||||
painter->drawText( option.rect.translated( -4, 0 ), text, to );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
QStyleOptionViewItem o = option;
|
||||
QStyleOptionViewItemV4 o3 = option;
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
QFont savedFont = painter->font();
|
||||
QFont smaller = savedFont;
|
||||
smaller.setPointSize( smaller.pointSize() - 2 );
|
||||
painter->setFont( smaller );
|
||||
o.font = smaller;
|
||||
#endif
|
||||
painter->save();
|
||||
|
||||
QFont font = painter->font();
|
||||
font.setPixelSize( 11 );
|
||||
painter->setFont( font );
|
||||
o.font = font;
|
||||
o3.font = font;
|
||||
|
||||
SourcesModel::RowType type = static_cast< SourcesModel::RowType >( index.data( SourcesModel::SourceTreeItemTypeRole ).toInt() );
|
||||
SourceTreeItem* item = index.data( SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >();
|
||||
Q_ASSERT( item );
|
||||
|
||||
if ( ( option.state & QStyle::State_Enabled ) == QStyle::State_Enabled )
|
||||
{
|
||||
o.state = QStyle::State_Enabled;
|
||||
|
||||
if ( ( option.state & QStyle::State_MouseOver ) == QStyle::State_MouseOver )
|
||||
{
|
||||
o.state |= QStyle::State_MouseOver;
|
||||
o3.state |= QStyle::State_MouseOver;
|
||||
}
|
||||
|
||||
if ( ( option.state & QStyle::State_Open ) == QStyle::State_Open )
|
||||
{
|
||||
o.state |= QStyle::State_Open;
|
||||
}
|
||||
|
||||
if ( ( option.state & QStyle::State_Selected ) == QStyle::State_Selected )
|
||||
{
|
||||
o3.state |= QStyle::State_Selected;
|
||||
if ( type != SourcesModel::Collection )
|
||||
o3.state |= QStyle::State_Selected;
|
||||
else
|
||||
o3.state &= ~QStyle::State_Selected;
|
||||
|
||||
o.palette.setColor( QPalette::Base, QColor( 0, 0, 0, 0 ) );
|
||||
o.palette.setColor( QPalette::Text, o.palette.color( QPalette::HighlightedText ) );
|
||||
o3.palette.setColor( QPalette::Text, o.palette.color( QPalette::HighlightedText ) );
|
||||
}
|
||||
}
|
||||
|
||||
SourcesModel::RowType type = static_cast< SourcesModel::RowType >( index.data( SourcesModel::SourceTreeItemTypeRole ).toInt() );
|
||||
SourceTreeItem* item = index.data( SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >();
|
||||
Q_ASSERT( item );
|
||||
|
||||
if ( type != SourcesModel::Collection && type != SourcesModel::Category )
|
||||
o3.rect.setX( 0 );
|
||||
|
||||
QApplication::style()->drawControl( QStyle::CE_ItemViewItem, &o3, painter );
|
||||
|
||||
// Paint the speaker icon next to the currently-playing playlist
|
||||
const bool playable = ( type == SourcesModel::StaticPlaylist ||
|
||||
type == SourcesModel::AutomaticPlaylist ||
|
||||
type == SourcesModel::Station ||
|
||||
type == SourcesModel::TemporaryPage ||
|
||||
type == SourcesModel::GenericPage );
|
||||
const bool playing = ( AudioEngine::instance()->isPlaying() || AudioEngine::instance()->isPaused() );
|
||||
if ( playable && playing && item->isBeingPlayed() )
|
||||
// shrink the indentations
|
||||
{
|
||||
const int iconW = o3.rect.height() - 4;
|
||||
QRect iconRect = QRect( option.rect.x() - iconW - 4, option.rect.y() + 2, iconW, iconW );
|
||||
QPixmap speaker = o3.state & QStyle::State_Selected ? m_nowPlayingSpeaker : m_nowPlayingSpeakerDark;
|
||||
speaker = speaker.scaledToHeight( iconW, Qt::SmoothTransformation );
|
||||
painter->drawPixmap( iconRect, speaker );
|
||||
int indentMult = 0;
|
||||
QModelIndex counter = index;
|
||||
while ( counter.parent().isValid() )
|
||||
{
|
||||
indentMult++;
|
||||
counter = counter.parent();
|
||||
}
|
||||
|
||||
int indentDelta = o.rect.x() - m_parent->viewport()->x();
|
||||
o.rect.setX( o.rect.x() - indentDelta + indentMult * TREEVIEW_INDENT_ADD );
|
||||
o3.rect.setX( 0 );
|
||||
}
|
||||
|
||||
if ( type != SourcesModel::Group && type != SourcesModel::Category && type != SourcesModel::Divider )
|
||||
QApplication::style()->drawControl( QStyle::CE_ItemViewItem, &o3, painter );
|
||||
|
||||
paintDecorations( painter, o3, index );
|
||||
|
||||
if ( type == SourcesModel::Collection )
|
||||
{
|
||||
painter->save();
|
||||
|
||||
QFont normal = painter->font();
|
||||
QFont bold = painter->font();
|
||||
bold.setBold( true );
|
||||
|
||||
CollectionItem* colItem = qobject_cast< CollectionItem* >( item );
|
||||
Q_ASSERT( colItem );
|
||||
bool status = !( !colItem || colItem->source().isNull() || !colItem->source()->isOnline() );
|
||||
|
||||
QString tracks;
|
||||
QString name = index.data().toString();
|
||||
int figWidth = 0;
|
||||
|
||||
if ( status && colItem && !colItem->source().isNull() )
|
||||
{
|
||||
tracks = QString::number( colItem->source()->trackCount() );
|
||||
figWidth = painter->fontMetrics().width( tracks );
|
||||
name = colItem->source()->friendlyName();
|
||||
}
|
||||
|
||||
QRect iconRect = option.rect.adjusted( 4, 6, -option.rect.width() + option.rect.height() - 12 + 4, -6 );
|
||||
|
||||
QPixmap avatar = colItem->icon().pixmap( iconRect.size() );
|
||||
painter->drawPixmap( iconRect, avatar.scaledToHeight( iconRect.height(), Qt::SmoothTransformation ) );
|
||||
|
||||
if ( ( option.state & QStyle::State_Selected ) == QStyle::State_Selected )
|
||||
{
|
||||
painter->setPen( o.palette.color( QPalette::HighlightedText ) );
|
||||
}
|
||||
|
||||
QRect textRect = option.rect.adjusted( iconRect.width() + 8, 6, -figWidth - 24, 0 );
|
||||
if ( status || colItem->source().isNull() )
|
||||
painter->setFont( bold );
|
||||
QString text = painter->fontMetrics().elidedText( name, Qt::ElideRight, textRect.width() );
|
||||
painter->drawText( textRect, text );
|
||||
|
||||
bool isPlaying = false;
|
||||
QString desc = status ? colItem->source()->textStatus() : tr( "Offline" );
|
||||
if ( colItem->source().isNull() )
|
||||
desc = tr( "All available tracks" );
|
||||
if ( status && desc.isEmpty() && !colItem->source()->currentTrack().isNull() )
|
||||
{
|
||||
desc = colItem->source()->currentTrack()->artist() + " - " + colItem->source()->currentTrack()->track();
|
||||
isPlaying = true;
|
||||
}
|
||||
if ( desc.isEmpty() )
|
||||
desc = tr( "Online" );
|
||||
|
||||
textRect = option.rect.adjusted( iconRect.width() + 8, painter->fontMetrics().height() + 6, -figWidth - 24, -4 );
|
||||
painter->setFont( normal );
|
||||
bool privacyOn = TomahawkSettings::instance()->privateListeningMode() == TomahawkSettings::FullyPrivate;
|
||||
if ( !colItem->source().isNull() && colItem->source()->isLocal() && privacyOn )
|
||||
{
|
||||
QRect pmRect = textRect;
|
||||
pmRect.setTop( pmRect.bottom() - painter->fontMetrics().height() + 3 );
|
||||
pmRect.setRight( pmRect.left() + pmRect.height() );
|
||||
ActionCollection::instance()->getAction( "togglePrivacy" )->icon().paint( painter, pmRect );
|
||||
textRect.adjust( pmRect.width() + 3, 0, 0, 0 );
|
||||
}
|
||||
if ( isPlaying || ( !colItem->source().isNull() && colItem->source()->isLocal() ) )
|
||||
{
|
||||
// Show a listen icon
|
||||
QPixmap pm;
|
||||
if ( index.data( SourcesModel::LatchedOnRole ).toBool() )
|
||||
{
|
||||
// Currently listening along
|
||||
pm = m_headphonesOn;
|
||||
} else if ( !colItem->source()->isLocal() ) {
|
||||
pm = m_headphonesOff;
|
||||
}
|
||||
|
||||
if ( !pm.isNull() )
|
||||
{
|
||||
QRect pmRect = textRect;
|
||||
pmRect.setTop( pmRect.bottom() - painter->fontMetrics().height() + 3 );
|
||||
pmRect.setRight( pmRect.left() + pmRect.height() );
|
||||
// tDebug() << "DOING HEADPHONES RECT:" << pmRect;
|
||||
painter->drawPixmap( pmRect, pm.scaledToHeight( pmRect.height(), Qt::SmoothTransformation ) );
|
||||
textRect.adjust( pmRect.width() + 3, 0, 0, 0 );
|
||||
}
|
||||
}
|
||||
text = painter->fontMetrics().elidedText( desc, Qt::ElideRight, textRect.width() );
|
||||
QTextOption to( Qt::AlignBottom );
|
||||
painter->drawText( textRect, text, to );
|
||||
|
||||
if ( status )
|
||||
{
|
||||
painter->setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
QRect figRect = o.rect.adjusted( o.rect.width() - figWidth - 8, 0, -13, -o.rect.height() + 16 );
|
||||
int hd = ( option.rect.height() - figRect.height() ) / 2;
|
||||
figRect.adjust( 0, hd, 0, hd );
|
||||
#ifdef Q_WS_WIN
|
||||
figRect.adjust( -3, 0, 3, 0 );
|
||||
#endif
|
||||
painter->setFont( bold );
|
||||
|
||||
QColor figColor( 167, 183, 211 );
|
||||
painter->setPen( figColor );
|
||||
painter->setBrush( figColor );
|
||||
|
||||
TomahawkUtils::drawBackgroundAndNumbers( painter, tracks, figRect );
|
||||
}
|
||||
|
||||
painter->restore();
|
||||
paintCollection( painter, o, index );
|
||||
}
|
||||
else if ( ( type == SourcesModel::StaticPlaylist || type == SourcesModel::CategoryAdd ) &&
|
||||
m_expandedMap.contains( index ) && m_expandedMap.value( index )->partlyExpanded() && dropTypeCount( item ) > 0 )
|
||||
@ -275,8 +399,6 @@ SourceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, co
|
||||
o.rect.adjust( 0, 0, 0, - option.rect.height() + m_expandedMap.value( index )->originalSize().height() );
|
||||
QStyledItemDelegate::paint( painter, o, index );
|
||||
|
||||
painter->save();
|
||||
|
||||
// Get whole rect for the menu
|
||||
QRect itemsRect = option.rect.adjusted( -option.rect.x(), m_expandedMap.value( index )->originalSize().height(), 0, 0 );
|
||||
QPoint cursorPos = m_parent->mapFromGlobal( QCursor::pos() );
|
||||
@ -287,9 +409,6 @@ SourceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, co
|
||||
{
|
||||
m_gradient = QLinearGradient( itemsRect.topLeft(), itemsRect.bottomLeft() );
|
||||
m_gradient.setColorAt( 0.0, Qt::white );
|
||||
// m_gradient.setColorAt( 0.8, QColor( 0xd6, 0xd6, 0xd6 ) ); // light grey
|
||||
// m_gradient.setColorAt( 1.0, QColor( 0xf4, 0x17, 0x05 ) ); // dark red
|
||||
// m_gradient.setColorAt( 1.0, QColor( 0xb1, 0xb1, 0xb1 ) ); // not so light but still not dark grey
|
||||
m_gradient.setColorAt( 0.9, QColor( 0x88, 0x88, 0x88 ) );
|
||||
m_gradient.setColorAt( 1.0, QColor( 0x99, 0x99, 0x99 ) ); // dark grey
|
||||
}
|
||||
@ -352,11 +471,30 @@ SourceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, co
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
else if ( type == SourcesModel::Group )
|
||||
{
|
||||
paintGroup( painter, o3, index );
|
||||
}
|
||||
else if ( type == SourcesModel::Category )
|
||||
{
|
||||
paintCategory( painter, o, index );
|
||||
}
|
||||
else if ( type == SourcesModel::Divider )
|
||||
{
|
||||
QRect middle = o.rect.adjusted( 0, 2, 0, -2 );
|
||||
painter->setRenderHint( QPainter::Antialiasing, false );
|
||||
|
||||
painter->restore();
|
||||
QColor bgcolor = o3.palette.color( QPalette::Base );
|
||||
|
||||
painter->setPen( bgcolor.darker( 120 ) );
|
||||
painter->drawLine( middle.topLeft(), middle.topRight() );
|
||||
painter->setPen( bgcolor.lighter( 120 ) );
|
||||
painter->drawLine( middle.bottomLeft(), middle.bottomRight() );
|
||||
}
|
||||
else
|
||||
{
|
||||
o.state &= ~QStyle::State_MouseOver;
|
||||
QStyledItemDelegate::paint( painter, o, index );
|
||||
|
||||
if ( type == SourcesModel::TemporaryPage )
|
||||
@ -376,29 +514,9 @@ SourceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, co
|
||||
painter->drawPixmap( r, p );
|
||||
}
|
||||
}
|
||||
|
||||
/*QStyleOptionViewItemV4 opt = o;
|
||||
initStyleOption( &opt, index );
|
||||
|
||||
// shrink the indentations. count how indented this item is and remove it
|
||||
int indentMult = 0;
|
||||
QModelIndex counter = index;
|
||||
while ( counter.parent().isValid() )
|
||||
{
|
||||
indentMult++;
|
||||
counter = counter.parent();
|
||||
}
|
||||
int realX = opt.rect.x() + indentMult * TREEVIEW_INDENT_ADD;
|
||||
|
||||
opt.rect.setX( realX );
|
||||
const QWidget *widget = opt.widget;
|
||||
QStyle *style = widget ? widget->style() : QApplication::style();
|
||||
style->drawControl( QStyle::CE_ItemViewItem, &opt, painter, widget ); */
|
||||
}
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
painter->setFont( savedFont );
|
||||
#endif
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
|
||||
@ -415,7 +533,7 @@ SourceDelegate::updateEditorGeometry( QWidget* editor, const QStyleOptionViewIte
|
||||
|
||||
|
||||
bool
|
||||
SourceDelegate::editorEvent ( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index )
|
||||
SourceDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index )
|
||||
{
|
||||
if ( event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseButtonPress )
|
||||
{
|
||||
@ -447,7 +565,7 @@ SourceDelegate::editorEvent ( QEvent* event, QAbstractItemModel* model, const QS
|
||||
}
|
||||
else if ( type == SourcesModel::Collection )
|
||||
{
|
||||
CollectionItem* colItem = qobject_cast< CollectionItem* >( index.data( SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >() );
|
||||
SourceItem* colItem = qobject_cast< SourceItem* >( index.data( SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >() );
|
||||
Q_ASSERT( colItem );
|
||||
|
||||
if ( !colItem->source().isNull() && !colItem->source()->currentTrack().isNull() && !colItem->source()->isLocal() )
|
||||
@ -460,7 +578,6 @@ SourceDelegate::editorEvent ( QEvent* event, QAbstractItemModel* model, const QS
|
||||
const int height = fm.height() + 3;
|
||||
|
||||
QRect headphonesRect( option.rect.height() + 10, o.rect.bottom() - height, height, height );
|
||||
// tDebug() << "CHECKING CLICK RECT:" << headphonesRect;
|
||||
if ( headphonesRect.contains( ev->pos() ) )
|
||||
{
|
||||
if ( event->type() == QEvent::MouseButtonRelease )
|
||||
|
@ -56,6 +56,12 @@ private slots:
|
||||
void animationFinished( const QModelIndex& );
|
||||
|
||||
private:
|
||||
void paintDecorations( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
|
||||
void paintCollection( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
void paintCategory( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
void paintGroup( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
|
||||
QAbstractItemView* m_parent;
|
||||
mutable int m_iconHeight;
|
||||
QModelIndex m_dropHoverIndex;
|
||||
|
@ -25,8 +25,10 @@
|
||||
#include <QSize>
|
||||
|
||||
#include "sourcetree/items/sourcetreeitem.h"
|
||||
#include "sourcetree/items/collectionitem.h"
|
||||
#include "sourcetree/items/sourceitem.h"
|
||||
#include "sourcetree/items/groupitem.h"
|
||||
#include "sourcetree/items/genericpageitems.h"
|
||||
#include "sourcetree/items/historyitem.h"
|
||||
#include "sourcelist.h"
|
||||
#include "playlist.h"
|
||||
#include "collection.h"
|
||||
@ -50,6 +52,7 @@ SourcesModel::SourcesModel( QObject* parent )
|
||||
{
|
||||
m_rootItem = new SourceTreeItem( this, 0, Invalid );
|
||||
|
||||
appendGroups();
|
||||
appendItem( source_ptr() );
|
||||
|
||||
onSourcesAdded( SourceList::instance()->sources() );
|
||||
@ -71,6 +74,9 @@ SourcesModel::rowTypeToString( RowType type )
|
||||
{
|
||||
switch ( type )
|
||||
{
|
||||
case Group:
|
||||
return tr( "Group" );
|
||||
|
||||
case Collection:
|
||||
return tr( "Collection" );
|
||||
|
||||
@ -92,35 +98,35 @@ SourcesModel::rowTypeToString( RowType type )
|
||||
QVariant
|
||||
SourcesModel::data( const QModelIndex& index, int role ) const
|
||||
{
|
||||
if( !index.isValid() )
|
||||
if ( !index.isValid() )
|
||||
return QVariant();
|
||||
|
||||
switch( role )
|
||||
switch ( role )
|
||||
{
|
||||
case Qt::SizeHintRole:
|
||||
return QSize( 0, 18 );
|
||||
case SourceTreeItemRole:
|
||||
return QVariant::fromValue< SourceTreeItem* >( itemFromIndex( index ) );
|
||||
case SourceTreeItemTypeRole:
|
||||
return itemFromIndex( index )->type();
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
return itemFromIndex( index )->text();
|
||||
case Qt::DecorationRole:
|
||||
return itemFromIndex( index )->icon();
|
||||
case SourcesModel::SortRole:
|
||||
return itemFromIndex( index )->peerSortValue();
|
||||
case SourcesModel::IDRole:
|
||||
return itemFromIndex( index )->IDValue();
|
||||
case SourcesModel::LatchedOnRole:
|
||||
{
|
||||
if ( itemFromIndex( index )->type() == Collection )
|
||||
case Qt::SizeHintRole:
|
||||
return QSize( 0, 18 );
|
||||
case SourceTreeItemRole:
|
||||
return QVariant::fromValue< SourceTreeItem* >( itemFromIndex( index ) );
|
||||
case SourceTreeItemTypeRole:
|
||||
return itemFromIndex( index )->type();
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
return itemFromIndex( index )->text();
|
||||
case Qt::DecorationRole:
|
||||
return itemFromIndex( index )->icon();
|
||||
case SourcesModel::SortRole:
|
||||
return itemFromIndex( index )->peerSortValue();
|
||||
case SourcesModel::IDRole:
|
||||
return itemFromIndex( index )->IDValue();
|
||||
case SourcesModel::LatchedOnRole:
|
||||
{
|
||||
CollectionItem* cItem = qobject_cast< CollectionItem* >( itemFromIndex( index ) );
|
||||
return cItem->localLatchedOn();
|
||||
if ( itemFromIndex( index )->type() == Collection )
|
||||
{
|
||||
SourceItem* cItem = qobject_cast< SourceItem* >( itemFromIndex( index ) );
|
||||
return cItem->localLatchedOn();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
@ -236,21 +242,63 @@ SourcesModel::supportedDropActions() const
|
||||
Qt::ItemFlags
|
||||
SourcesModel::flags( const QModelIndex& index ) const
|
||||
{
|
||||
if ( index.isValid() ) {
|
||||
if ( index.isValid() )
|
||||
{
|
||||
return itemFromIndex( index )->flags();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourcesModel::appendGroups()
|
||||
{
|
||||
beginInsertRows( QModelIndex(), rowCount(), rowCount() + 2 );
|
||||
|
||||
SourceTreeItem* divider = new SourceTreeItem( this, m_rootItem, SourcesModel::Divider, 0 );
|
||||
HistoryItem* history = new HistoryItem( this, m_rootItem, tr( "History" ), 5 );
|
||||
GroupItem* browse = new GroupItem( this, m_rootItem, tr( "Browse" ), 10 );
|
||||
|
||||
// super collection
|
||||
GenericPageItem* loved = new GenericPageItem( this, browse, tr( "Top Loved Tracks" ), QIcon( RESPATH "images/loved_playlist.png" ),
|
||||
boost::bind( &ViewManager::showTopLovedPage, ViewManager::instance() ),
|
||||
boost::bind( &ViewManager::topLovedWidget, ViewManager::instance() ) );
|
||||
loved->setSortValue( -250 );
|
||||
|
||||
// add misc children of root node
|
||||
GenericPageItem* recent = new GenericPageItem( this, browse, tr( "Dashboard" ), QIcon( RESPATH "images/dashboard.png" ),
|
||||
boost::bind( &ViewManager::showWelcomePage, ViewManager::instance() ),
|
||||
boost::bind( &ViewManager::welcomeWidget, ViewManager::instance() ) );
|
||||
recent->setSortValue( -300 );
|
||||
|
||||
GenericPageItem* hot = new GenericPageItem( this, browse, tr( "Charts" ), QIcon( RESPATH "images/charts.png" ),
|
||||
boost::bind( &ViewManager::showWhatsHotPage, ViewManager::instance() ),
|
||||
boost::bind( &ViewManager::whatsHotWidget, ViewManager::instance() ) );
|
||||
hot->setSortValue( -300 );
|
||||
|
||||
m_collectionsGroup = new GroupItem( this, m_rootItem, tr( "Friends" ), 15 );
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourcesModel::appendItem( const Tomahawk::source_ptr& source )
|
||||
{
|
||||
beginInsertRows( QModelIndex(), rowCount(), rowCount() );
|
||||
// append to end
|
||||
new CollectionItem( this, m_rootItem, source );
|
||||
SourceTreeItem* parent;
|
||||
if ( !source.isNull() && source->isLocal() )
|
||||
{
|
||||
parent = m_rootItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent = m_collectionsGroup;
|
||||
}
|
||||
|
||||
QModelIndex idx = indexFromItem( parent );
|
||||
beginInsertRows( idx, rowCount( idx ), rowCount( idx ) );
|
||||
new SourceItem( this, parent, source );
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
@ -265,7 +313,7 @@ SourcesModel::removeItem( const Tomahawk::source_ptr& source )
|
||||
for ( int row = 0; row < rows; row++ )
|
||||
{
|
||||
QModelIndex idx = index( row, 0, QModelIndex() );
|
||||
CollectionItem* item = static_cast< CollectionItem* >( idx.internalPointer() );
|
||||
SourceItem* item = static_cast< SourceItem* >( idx.internalPointer() );
|
||||
if ( item && item->source() == source )
|
||||
{
|
||||
// qDebug() << "Found removed source item:" << item->source()->userName();
|
||||
@ -348,12 +396,12 @@ SourcesModel::viewPageActivated( Tomahawk::ViewPage* page )
|
||||
m_sourcesWithViewPageItems[ s ] = collectionOfPlaylist;
|
||||
tDebug() << "Emitting dataChanged for offline source:" << idx << idx.isValid() << collectionOfPlaylist << collectionOfPlaylist->text();
|
||||
emit dataChanged( idx, idx );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SourceTreeItem*
|
||||
SourcesModel::activatePlaylistPage( ViewPage* p, SourceTreeItem* i )
|
||||
{
|
||||
@ -425,7 +473,6 @@ SourcesModel::itemUpdated()
|
||||
void
|
||||
SourcesModel::onItemRowsAddedBegin( int first, int last )
|
||||
{
|
||||
|
||||
Q_ASSERT( qobject_cast< SourceTreeItem* >( sender() ) );
|
||||
SourceTreeItem* item = qobject_cast< SourceTreeItem* >( sender() );
|
||||
|
||||
@ -486,6 +533,7 @@ SourcesModel::linkSourceItemToPage( SourceTreeItem* item, ViewPage* p )
|
||||
m_viewPageDelayedCacheItem = 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourcesModel::onWidgetDestroyed( QWidget* w )
|
||||
{
|
||||
@ -576,9 +624,17 @@ SourcesModel::itemSelectRequest( SourceTreeItem* item )
|
||||
emit selectRequest( QPersistentModelIndex( indexFromItem( item ) ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourcesModel::itemExpandRequest( SourceTreeItem *item )
|
||||
{
|
||||
qDebug() << "expanding source" << indexFromItem( item ) << item;
|
||||
emit expandRequest( QPersistentModelIndex( indexFromItem( item ) ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourcesModel::itemToggleExpandRequest( SourceTreeItem *item )
|
||||
{
|
||||
emit toggleExpandRequest( QPersistentModelIndex( indexFromItem( item ) ) );
|
||||
}
|
||||
|
@ -1,19 +1,21 @@
|
||||
|
||||
/*
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SOURCESMODEL_H
|
||||
@ -28,6 +30,7 @@
|
||||
class QMimeData;
|
||||
|
||||
class SourceTreeItem;
|
||||
class GroupItem;
|
||||
|
||||
namespace Tomahawk {
|
||||
class Source;
|
||||
@ -41,8 +44,10 @@ class SourcesModel : public QAbstractItemModel
|
||||
public:
|
||||
enum RowType {
|
||||
Invalid = -1,
|
||||
Divider = 9,
|
||||
|
||||
Collection = 0,
|
||||
Group = 8,
|
||||
|
||||
Category = 1,
|
||||
CategoryAdd = 2,
|
||||
@ -65,7 +70,7 @@ public:
|
||||
SourceTreeItemTypeRole = Qt::UserRole + 11,
|
||||
SortRole = Qt::UserRole + 12,
|
||||
IDRole = Qt::UserRole + 13,
|
||||
LatchedOnRole = Qt::UserRole + 14
|
||||
LatchedOnRole = Qt::UserRole + 14
|
||||
};
|
||||
|
||||
SourcesModel( QObject* parent = 0 );
|
||||
@ -87,6 +92,8 @@ public:
|
||||
virtual Qt::DropActions supportedDropActions() const;
|
||||
virtual Qt::ItemFlags flags(const QModelIndex& index) const;
|
||||
|
||||
void appendGroups();
|
||||
|
||||
void appendItem( const Tomahawk::source_ptr& source );
|
||||
bool removeItem( const Tomahawk::source_ptr& source );
|
||||
|
||||
@ -110,10 +117,12 @@ public slots:
|
||||
|
||||
void itemSelectRequest( SourceTreeItem* item );
|
||||
void itemExpandRequest( SourceTreeItem* item );
|
||||
void itemToggleExpandRequest( SourceTreeItem* item );
|
||||
|
||||
signals:
|
||||
void selectRequest( const QPersistentModelIndex& idx );
|
||||
void expandRequest( const QPersistentModelIndex& idx );
|
||||
void toggleExpandRequest( const QPersistentModelIndex& idx );
|
||||
|
||||
private slots:
|
||||
void onSourcesAdded( const QList<Tomahawk::source_ptr>& sources );
|
||||
@ -121,12 +130,14 @@ private slots:
|
||||
void onSourceRemoved( const Tomahawk::source_ptr& source );
|
||||
|
||||
void onWidgetDestroyed( QWidget* w );
|
||||
|
||||
private:
|
||||
SourceTreeItem* itemFromIndex( const QModelIndex& idx ) const;
|
||||
int rowForItem( SourceTreeItem* item ) const;
|
||||
SourceTreeItem* activatePlaylistPage( Tomahawk::ViewPage* p, SourceTreeItem* i );
|
||||
|
||||
SourceTreeItem* m_rootItem;
|
||||
GroupItem* m_collectionsGroup;
|
||||
|
||||
QList< Tomahawk::source_ptr > m_sourcesWithViewPage;
|
||||
QHash< Tomahawk::source_ptr, SourceTreeItem* > m_sourcesWithViewPageItems;
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -22,7 +23,7 @@
|
||||
|
||||
#include "sourcelist.h"
|
||||
#include "sourcesmodel.h"
|
||||
#include "sourcetree/items/collectionitem.h"
|
||||
#include "sourcetree/items/sourceitem.h"
|
||||
|
||||
#include "utils/logger.h"
|
||||
|
||||
@ -37,6 +38,11 @@ SourcesProxyModel::SourcesProxyModel( SourcesModel* model, QObject* parent )
|
||||
|
||||
setSourceModel( model );
|
||||
|
||||
connect( model, SIGNAL( rowsInserted( QModelIndex, int, int ) ), SLOT( onModelChanged() ) );
|
||||
connect( model, SIGNAL( rowsRemoved( QModelIndex, int, int ) ), SLOT( onModelChanged() ) );
|
||||
|
||||
if ( model && model->metaObject()->indexOfSignal( "toggleExpandRequest(QPersistentModelIndex)" ) > -1 )
|
||||
connect( model, SIGNAL( toggleExpandRequest( QPersistentModelIndex ) ), this, SLOT( toggleExpandRequested( QPersistentModelIndex ) ), Qt::QueuedConnection );
|
||||
if ( model && model->metaObject()->indexOfSignal( "expandRequest(QPersistentModelIndex)" ) > -1 )
|
||||
connect( model, SIGNAL( expandRequest( QPersistentModelIndex ) ), this, SLOT( expandRequested( QPersistentModelIndex ) ), Qt::QueuedConnection );
|
||||
if ( model && model->metaObject()->indexOfSignal( "selectRequest(QPersistentModelIndex)" ) > -1 )
|
||||
@ -55,10 +61,16 @@ SourcesProxyModel::showOfflineSources( bool offlineSourcesShown )
|
||||
bool
|
||||
SourcesProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const
|
||||
{
|
||||
// always filter empty top-level groups
|
||||
SourceTreeItem* item = m_model->data( sourceModel()->index( sourceRow, 0, sourceParent ), SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >();
|
||||
|
||||
if ( item && item->type() != SourcesModel::Divider && item->parent()->parent() == 0 && !item->children().count() )
|
||||
return false;
|
||||
|
||||
if ( !m_filtered )
|
||||
return true;
|
||||
|
||||
CollectionItem* sti = qobject_cast< CollectionItem* >( m_model->data( sourceModel()->index( sourceRow, 0, sourceParent ), SourcesModel::SourceTreeItemRole ).value< SourceTreeItem* >() );
|
||||
SourceItem* sti = qobject_cast< SourceItem* >( item );
|
||||
if ( sti )
|
||||
{
|
||||
if ( sti->source().isNull() || sti->source()->isOnline() )
|
||||
@ -68,6 +80,7 @@ SourcesProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourcePar
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// accept rows that aren't sources
|
||||
return true;
|
||||
}
|
||||
@ -76,7 +89,6 @@ SourcesProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourcePar
|
||||
void
|
||||
SourcesProxyModel::selectRequested( const QPersistentModelIndex& idx )
|
||||
{
|
||||
qDebug() << "selectRequested for idx" << idx << idx.data(Qt::DisplayRole).toString() << mapFromSource( idx ) << mapFromSource( idx ).data(Qt::DisplayRole).toString();
|
||||
emit selectRequest( QPersistentModelIndex( mapFromSource( idx ) ) );
|
||||
}
|
||||
|
||||
@ -84,11 +96,17 @@ SourcesProxyModel::selectRequested( const QPersistentModelIndex& idx )
|
||||
void
|
||||
SourcesProxyModel::expandRequested( const QPersistentModelIndex& idx )
|
||||
{
|
||||
qDebug() << "emitting expand for idx" << idx << idx.data(Qt::DisplayRole).toString() << mapFromSource( idx ) << mapFromSource( idx ).data(Qt::DisplayRole).toString();
|
||||
emit expandRequest( QPersistentModelIndex( mapFromSource( idx ) ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourcesProxyModel::toggleExpandRequested( const QPersistentModelIndex& idx )
|
||||
{
|
||||
emit toggleExpandRequest( QPersistentModelIndex( mapFromSource( idx ) ) );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SourcesProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right ) const
|
||||
{
|
||||
@ -103,3 +121,10 @@ SourcesProxyModel::lessThan( const QModelIndex& left, const QModelIndex& right )
|
||||
else
|
||||
return QString::localeAwareCompare( lefts, rights ) < 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourcesProxyModel::onModelChanged()
|
||||
{
|
||||
invalidateFilter();
|
||||
}
|
||||
|
@ -35,15 +35,20 @@ public slots:
|
||||
|
||||
void selectRequested( const QPersistentModelIndex& );
|
||||
void expandRequested( const QPersistentModelIndex& );
|
||||
void toggleExpandRequested( const QPersistentModelIndex& );
|
||||
|
||||
signals:
|
||||
void selectRequest( const QPersistentModelIndex& idx );
|
||||
void expandRequest( const QPersistentModelIndex& idx );
|
||||
void toggleExpandRequest( const QPersistentModelIndex& idx );
|
||||
|
||||
protected:
|
||||
bool filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const;
|
||||
bool lessThan( const QModelIndex& left, const QModelIndex& right ) const;
|
||||
|
||||
private slots:
|
||||
void onModelChanged();
|
||||
|
||||
private:
|
||||
SourcesModel* m_model;
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include "sourcelist.h"
|
||||
#include "sourcedelegate.h"
|
||||
#include "sourcetree/items/playlistitems.h"
|
||||
#include "sourcetree/items/collectionitem.h"
|
||||
#include "sourcetree/items/sourceitem.h"
|
||||
#include "audio/audioengine.h"
|
||||
#include "sourceplaylistinterface.h"
|
||||
#include "tomahawksettings.h"
|
||||
@ -56,6 +56,8 @@ SourceTreeView::SourceTreeView( QWidget* parent )
|
||||
, m_latchManager( new LatchManager( this ) )
|
||||
, m_dragging( false )
|
||||
{
|
||||
setProperty( "flattenBranches", QVariant( true ) );
|
||||
|
||||
setFrameShape( QFrame::NoFrame );
|
||||
setAttribute( Qt::WA_MacShowFocusRect, 0 );
|
||||
setContentsMargins( 0, 0, 0, 0 );
|
||||
@ -71,11 +73,12 @@ SourceTreeView::SourceTreeView( QWidget* parent )
|
||||
setDropIndicatorShown( false );
|
||||
setAllColumnsShowFocus( true );
|
||||
setUniformRowHeights( false );
|
||||
setIndentation( 14 );
|
||||
setIndentation( 0 );
|
||||
setSortingEnabled( true );
|
||||
sortByColumn( 0, Qt::AscendingOrder );
|
||||
setVerticalScrollMode( QTreeView::ScrollPerPixel );
|
||||
setMouseTracking( true );
|
||||
|
||||
// TODO animation conflicts with the expanding-playlists-when-collection-is-null
|
||||
// so investigate
|
||||
// setAnimated( true );
|
||||
@ -93,6 +96,7 @@ SourceTreeView::SourceTreeView( QWidget* parent )
|
||||
m_proxyModel = new SourcesProxyModel( m_model, this );
|
||||
connect( m_proxyModel, SIGNAL( selectRequest( QPersistentModelIndex ) ), this, SLOT( selectRequest( QPersistentModelIndex ) ) );
|
||||
connect( m_proxyModel, SIGNAL( expandRequest( QPersistentModelIndex ) ), this, SLOT( expandRequest( QPersistentModelIndex ) ) );
|
||||
connect( m_proxyModel, SIGNAL( toggleExpandRequest( QPersistentModelIndex ) ), this, SLOT( toggleExpandRequest( QPersistentModelIndex ) ) );
|
||||
|
||||
setModel( m_proxyModel );
|
||||
|
||||
@ -152,7 +156,7 @@ SourceTreeView::setupMenus()
|
||||
|
||||
if ( type == SourcesModel::Collection )
|
||||
{
|
||||
CollectionItem* item = itemFromIndex< CollectionItem >( m_contextMenuIndex );
|
||||
SourceItem* item = itemFromIndex< SourceItem >( m_contextMenuIndex );
|
||||
source_ptr source = item->source();
|
||||
if ( !source.isNull() )
|
||||
{
|
||||
@ -198,7 +202,7 @@ SourceTreeView::setupMenus()
|
||||
connect( deletePlaylistAction, SIGNAL( triggered() ), SLOT( deletePlaylist() ) );
|
||||
connect( copyPlaylistAction, SIGNAL( triggered() ), SLOT( copyPlaylistLink() ) );
|
||||
connect( addToLocalAction, SIGNAL( triggered() ), SLOT( addToLocal() ) );
|
||||
connect( latchOnAction, SIGNAL( triggered() ), SLOT( latchOnOrCatchUp() ), Qt::QueuedConnection );
|
||||
connect( latchOnAction, SIGNAL( triggered() ), SLOT( latchOnOrCatchUp() ), Qt::QueuedConnection );
|
||||
}
|
||||
|
||||
|
||||
@ -235,7 +239,6 @@ SourceTreeView::onItemExpanded( const QModelIndex& idx )
|
||||
void
|
||||
SourceTreeView::selectRequest( const QPersistentModelIndex& idx )
|
||||
{
|
||||
qDebug() << "Select request for:" << idx << idx.data().toString() << selectionModel()->selectedIndexes().contains( idx );
|
||||
if ( !selectionModel()->selectedIndexes().contains( idx ) )
|
||||
{
|
||||
scrollTo( idx, QTreeView::EnsureVisible );
|
||||
@ -247,11 +250,20 @@ SourceTreeView::selectRequest( const QPersistentModelIndex& idx )
|
||||
void
|
||||
SourceTreeView::expandRequest( const QPersistentModelIndex &idx )
|
||||
{
|
||||
qDebug() << "Expanding idx" << idx << idx.data( Qt::DisplayRole ).toString();
|
||||
expand( idx );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceTreeView::toggleExpandRequest( const QPersistentModelIndex &idx )
|
||||
{
|
||||
if ( isExpanded( idx ) )
|
||||
collapse( idx );
|
||||
else
|
||||
expand( idx );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceTreeView::loadPlaylist()
|
||||
{
|
||||
@ -359,7 +371,7 @@ SourceTreeView::latchOnOrCatchUp()
|
||||
if( type != SourcesModel::Collection )
|
||||
return;
|
||||
|
||||
CollectionItem* item = itemFromIndex< CollectionItem >( m_contextMenuIndex );
|
||||
SourceItem* item = itemFromIndex< SourceItem >( m_contextMenuIndex );
|
||||
source_ptr source = item->source();
|
||||
|
||||
latchOnOrCatchUp( source );
|
||||
@ -378,7 +390,7 @@ SourceTreeView::latchOff()
|
||||
if( type != SourcesModel::Collection )
|
||||
return;
|
||||
|
||||
const CollectionItem* item = itemFromIndex< CollectionItem >( m_contextMenuIndex );
|
||||
const SourceItem* item = itemFromIndex< SourceItem >( m_contextMenuIndex );
|
||||
const source_ptr source = item->source();
|
||||
|
||||
latchOff( source );
|
||||
@ -436,7 +448,7 @@ SourceTreeView::onCustomContextMenu( const QPoint& pos )
|
||||
}
|
||||
else if ( model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::Collection )
|
||||
{
|
||||
CollectionItem* item = itemFromIndex< CollectionItem >( m_contextMenuIndex );
|
||||
SourceItem* item = itemFromIndex< SourceItem >( m_contextMenuIndex );
|
||||
if ( !item->source().isNull() && !item->source()->isLocal() )
|
||||
m_latchMenu.exec( mapToGlobal( pos ) );
|
||||
else if ( !item->source().isNull() )
|
||||
|
@ -64,6 +64,7 @@ private slots:
|
||||
void onItemActivated( const QModelIndex& index );
|
||||
void selectRequest( const QPersistentModelIndex& idx );
|
||||
void expandRequest( const QPersistentModelIndex& idx );
|
||||
void toggleExpandRequest( const QPersistentModelIndex& idx );
|
||||
|
||||
void loadPlaylist();
|
||||
void deletePlaylist( const QModelIndex& = QModelIndex() );
|
||||
@ -74,7 +75,7 @@ private slots:
|
||||
void latchOff();
|
||||
void latchOnOrCatchUp( const Tomahawk::source_ptr& source );
|
||||
void latchOff( const Tomahawk::source_ptr& source );
|
||||
|
||||
|
||||
void onCustomContextMenu( const QPoint& pos );
|
||||
|
||||
protected:
|
||||
|
@ -226,7 +226,6 @@ TomahawkApp::init()
|
||||
#ifndef ENABLE_HEADLESS
|
||||
EchonestGenerator::setupCatalogs();
|
||||
|
||||
|
||||
if ( !m_headless )
|
||||
{
|
||||
tDebug() << "Init MainWindow.";
|
||||
@ -282,7 +281,7 @@ TomahawkApp::init()
|
||||
GlobalActionManager::instance();
|
||||
|
||||
// check if our spotify playlist api server is up and running, and enable spotify playlist drops if so
|
||||
QNetworkReply* r = TomahawkUtils::nam()->get( QNetworkRequest( QUrl( SPOTIFY_PLAYLIST_API_URL "/playlist/test" ) ) );
|
||||
QNetworkReply* r = TomahawkUtils::nam()->get( QNetworkRequest( QUrl( SPOTIFY_PLAYLIST_API_URL "/pong" ) ) );
|
||||
connect( r, SIGNAL( finished() ), this, SLOT( spotifyApiCheckFinished() ) );
|
||||
#endif
|
||||
|
||||
@ -541,10 +540,10 @@ TomahawkApp::spotifyApiCheckFinished()
|
||||
QNetworkReply* reply = qobject_cast< QNetworkReply* >( sender() );
|
||||
Q_ASSERT( reply );
|
||||
|
||||
if ( reply->error() == QNetworkReply::ContentNotFoundError )
|
||||
DropJob::setCanParseSpotifyPlaylists( true );
|
||||
else
|
||||
if ( reply->error() )
|
||||
DropJob::setCanParseSpotifyPlaylists( false );
|
||||
else
|
||||
DropJob::setCanParseSpotifyPlaylists( true );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user