diff --git a/src/libtomahawk/Query.cpp b/src/libtomahawk/Query.cpp
index e38cfd0ab..1049103b0 100644
--- a/src/libtomahawk/Query.cpp
+++ b/src/libtomahawk/Query.cpp
@@ -736,6 +736,7 @@ Query::socialActionDescription( const QString& action, DescriptionMode mode ) co
}
}
+ QDateTime earliestTimestamp = QDateTime::currentDateTime();
actionSources.clear();
int loveCounter = 0;
foreach ( const Tomahawk::SocialAction& sa, socialActions )
@@ -765,6 +766,10 @@ Query::socialActionDescription( const QString& action, DescriptionMode mode ) co
}
else
desc += "" + sa.source->friendlyName() + "";
+
+ QDateTime saTimestamp = QDateTime::fromTime_t( sa.timestamp.toInt() );
+ if ( saTimestamp < earliestTimestamp && saTimestamp.toTime_t() > 0 )
+ earliestTimestamp = saTimestamp;
}
}
if ( loveCounter > 0 )
@@ -775,7 +780,12 @@ Query::socialActionDescription( const QString& action, DescriptionMode mode ) co
if ( mode == Short )
desc = "" + tr( "%n people", "", loveCounter ) + "";
- desc += " " + tr( "loved this track" ); //FIXME: more action descs required
+ //FIXME: more action descs required
+ if ( action == "Love" )
+ desc += " " + tr( "loved this track" );
+ else if ( action == "Inbox" )
+ desc += " " + tr( "sent you this track %1" )
+ .arg( TomahawkUtils::ageToString( earliestTimestamp, true ) );
}
return desc;
diff --git a/src/libtomahawk/ViewManager.cpp b/src/libtomahawk/ViewManager.cpp
index ee2eb3fcb..a616da83e 100644
--- a/src/libtomahawk/ViewManager.cpp
+++ b/src/libtomahawk/ViewManager.cpp
@@ -443,7 +443,7 @@ ViewManager::showInboxPage()
TrackView* inboxView = new TrackView( m_widget );
PlaylistLargeItemDelegate* delegate =
- new PlaylistLargeItemDelegate( PlaylistLargeItemDelegate::/*Inbox*/LovedTracks,
+ new PlaylistLargeItemDelegate( PlaylistLargeItemDelegate::Inbox,
inboxView,
inboxView->proxyModel() );
connect( delegate, SIGNAL( updateIndex( QModelIndex ) ),
diff --git a/src/libtomahawk/database/DatabaseCommand_ShareTrack.cpp b/src/libtomahawk/database/DatabaseCommand_ShareTrack.cpp
index 90d48806f..291558a7d 100644
--- a/src/libtomahawk/database/DatabaseCommand_ShareTrack.cpp
+++ b/src/libtomahawk/database/DatabaseCommand_ShareTrack.cpp
@@ -90,6 +90,16 @@ DatabaseCommand_ShareTrack::postCommitHook()
if ( m_query.isNull() )
return;
+ Tomahawk::SocialAction action;
+ action.action = "Inbox";
+ action.source = source();
+ action.value = true; //unlistened
+ action.timestamp = timestamp();
+
+ QList< Tomahawk::SocialAction > actions;
+ actions << action;
+ m_query->setAllSocialActions( actions );
+
QMetaObject::invokeMethod( ViewManager::instance()->inboxModel(),
"insertQuery",
Qt::QueuedConnection,
diff --git a/src/libtomahawk/playlist/InboxModel.cpp b/src/libtomahawk/playlist/InboxModel.cpp
index 17f1af1a5..b236186cb 100644
--- a/src/libtomahawk/playlist/InboxModel.cpp
+++ b/src/libtomahawk/playlist/InboxModel.cpp
@@ -20,12 +20,19 @@
#include "database/Database.h"
#include "database/DatabaseCommand_GenericSelect.h"
+#include "SourceList.h"
+#include "utils/Logger.h"
+#include "utils/Closure.h"
InboxModel::InboxModel( QObject* parent )
: PlaylistModel( parent )
{
- loadTracks();
+ if ( SourceList::instance()->isReady() )
+ loadTracks();
+ else
+ NewClosure( SourceList::instance(), SIGNAL( ready() ),
+ this, SLOT( loadTracks() ) );
}
@@ -33,6 +40,92 @@ InboxModel::~InboxModel()
{}
+QList
+InboxModel::mergeSocialActions( QList first, QList second)
+{
+ foreach ( Tomahawk::SocialAction sa, second )
+ {
+ if ( sa.action != "Inbox" )
+ {
+ first.append( sa );
+ continue;
+ }
+
+ bool contains = false;
+ for ( int i = 0; i < first.count(); ++i )
+ {
+ Tomahawk::SocialAction &sb = first[ i ];
+ if ( sa.source == sb.source )
+ {
+ sb.timestamp = qMax( sa.timestamp.toInt(), sb.timestamp.toInt() );
+ sb.value = sa.value.toBool() && sb.value.toBool();
+ contains = true;
+ break;
+ }
+ }
+ if ( !contains )
+ first.append( sa );
+ }
+ return first;
+}
+
+
+void
+InboxModel::insertEntries( const QList< Tomahawk::plentry_ptr >& entries, int row )
+{
+ QList< Tomahawk::plentry_ptr > toInsert;
+ for ( QList< Tomahawk::plentry_ptr >::const_iterator it = entries.constBegin();
+ it != entries.constEnd(); ++it )
+ {
+ Tomahawk::plentry_ptr entry = *it;
+ bool gotDupe = false;
+ for ( QList< Tomahawk::plentry_ptr >::iterator jt = toInsert.begin();
+ jt != toInsert.end(); ++jt )
+ {
+ Tomahawk::plentry_ptr existingEntry = *jt;
+ if ( entry->query()->equals( existingEntry->query(), true /*ignoreCase*/) )
+ {
+ //We got a dupe, let's merge the social actions
+ existingEntry->query()->setAllSocialActions( mergeSocialActions( existingEntry->query()->allSocialActions(),
+ entry->query()->allSocialActions() ) );
+ gotDupe = true;
+ break;
+ }
+ }
+ if ( !gotDupe )
+ toInsert.append( entry );
+ }
+
+ foreach ( Tomahawk::plentry_ptr plEntry, playlistEntries() )
+ {
+ for ( int i = 0; i < toInsert.count(); )
+ {
+ if ( plEntry->query()->equals( toInsert.at( i )->query(), true ) )
+ {
+ plEntry->query()->setAllSocialActions( mergeSocialActions( plEntry->query()->allSocialActions(),
+ toInsert.at( i )->query()->allSocialActions() ) );
+ toInsert.removeAt( i );
+
+ dataChanged( index( playlistEntries().indexOf( plEntry ), 0, QModelIndex() ),
+ index( playlistEntries().indexOf( plEntry ), columnCount() -1, QModelIndex() ) );
+ }
+ else
+ ++i;
+ }
+ }
+ changed();
+
+ PlaylistModel::insertEntries( toInsert, row );
+}
+
+
+void
+InboxModel::clear()
+{
+ PlaylistModel::clear();
+}
+
+
void
InboxModel::loadTracks()
{
@@ -60,6 +153,23 @@ InboxModel::tracksLoaded( QList< Tomahawk::query_ptr > newTracks )
foreach ( const Tomahawk::plentry_ptr ple, playlistEntries() )
tracks << ple->query();
+ foreach ( Tomahawk::query_ptr newQuery, newTracks )
+ {
+ QVariantList extraData = newQuery->property( "data" ).toList();
+
+ Tomahawk::SocialAction action;
+ action.action = "Inbox";
+ action.source = SourceList::instance()->get( extraData.at( 0 ).toInt() );
+ action.value = extraData.at( 1 ).toBool(); //unlistened
+ action.timestamp = extraData.at( 2 ).toUInt();
+
+ QList< Tomahawk::SocialAction > actions;
+ actions << action;
+ newQuery->setAllSocialActions( actions );
+
+ newQuery->setProperty( "data", QVariant() ); //clear
+ }
+
bool changed = false;
QList< Tomahawk::query_ptr > mergedTracks = TomahawkUtils::mergePlaylistChanges( tracks, newTracks, changed );
@@ -71,3 +181,4 @@ InboxModel::tracksLoaded( QList< Tomahawk::query_ptr > newTracks )
appendEntries( el );
}
}
+
diff --git a/src/libtomahawk/playlist/InboxModel.h b/src/libtomahawk/playlist/InboxModel.h
index a44275787..4ae757725 100644
--- a/src/libtomahawk/playlist/InboxModel.h
+++ b/src/libtomahawk/playlist/InboxModel.h
@@ -23,6 +23,7 @@
#include "Typedefs.h"
#include "DllMacro.h"
+
class DLLEXPORT InboxModel : public PlaylistModel
{
Q_OBJECT
@@ -30,13 +31,24 @@ public:
explicit InboxModel( QObject* parent = 0 );
virtual ~InboxModel();
+public slots:
+ /**
+ * Reimplemented from PlaylistModel, all track insertions/appends go through this method.
+ * On top of PlaylistModel functionality, adds deduplication/grouping of equivalent tracks
+ * sent from different sources.
+ */
+ virtual void insertEntries( const QList< Tomahawk::plentry_ptr >& entries, int row = 0 );
+
+ virtual void clear();
+
private slots:
void loadTracks();
void tracksLoaded( QList< Tomahawk::query_ptr > );
private:
- QTimer* m_smoothingTimer;
+ static QList< Tomahawk::SocialAction > mergeSocialActions( QList< Tomahawk::SocialAction > first,
+ QList< Tomahawk::SocialAction > second );
};
#endif // INBOXMODEL_H
diff --git a/src/libtomahawk/playlist/PlaylistLargeItemDelegate.cpp b/src/libtomahawk/playlist/PlaylistLargeItemDelegate.cpp
index 30d248fcf..a627c00ab 100644
--- a/src/libtomahawk/playlist/PlaylistLargeItemDelegate.cpp
+++ b/src/libtomahawk/playlist/PlaylistLargeItemDelegate.cpp
@@ -144,6 +144,8 @@ PlaylistLargeItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem&
if ( m_mode == LovedTracks )
lowerText = item->query()->socialActionDescription( "Love", Query::Detailed );
+ if ( m_mode == Inbox )
+ lowerText = item->query()->socialActionDescription( "Inbox", Query::Detailed );
painter->save();
{