mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-07-31 19:30:21 +02:00
Merge remote branch 'origin/master'
Conflicts: src/playlist/trackview.cpp
This commit is contained in:
16
README
16
README
@@ -30,12 +30,21 @@ QJson (Qt JSON library)
|
||||
$ ./configure && make
|
||||
$ sudo make install
|
||||
|
||||
libEchonest 0.1
|
||||
---------------
|
||||
See: http://projects.kde.org/projects/playground/libs/libechonest/
|
||||
|
||||
$ git clone git://git.kde.org/libechonest.git
|
||||
$ cd libechonest
|
||||
$ mkdir build && cd build
|
||||
$ cmake ..
|
||||
$ make
|
||||
$ sudo make install
|
||||
|
||||
Now compile Tomahawk
|
||||
-------------------
|
||||
$ sudo ldconfig -v | grep -Ei 'qjson|gloox'
|
||||
$ mkdir build
|
||||
$ cd build
|
||||
$ mkdir build && cd build
|
||||
$ cmake ..
|
||||
$ make
|
||||
$ ./tomahawk
|
||||
@@ -57,7 +66,8 @@ Dependencies
|
||||
libmad 0.15.1b http://www.underbit.com/products/mad/
|
||||
libvorbis 1.2.3 http://xiph.org/vorbis/
|
||||
libogg 1.1.4 http://xiph.org/ogg/
|
||||
liblastfm 0.3.0 http://github.com/mxcl/liblastfm/
|
||||
liblastfm 0.3.3 http://github.com/mxcl/liblastfm/
|
||||
libechonest 0.1.2 http://projects.kde.org/projects/playground/libs/libechonest/
|
||||
|
||||
Third party libraries that we ship with our source:
|
||||
|
||||
|
148
include/tomahawk/infosystem.h
Normal file
148
include/tomahawk/infosystem.h
Normal file
@@ -0,0 +1,148 @@
|
||||
#ifndef TOMAHAWK_INFOSYSTEM_H
|
||||
#define TOMAHAWK_INFOSYSTEM_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QtDebug>
|
||||
#include <QtCore/qmap.h>
|
||||
#include <QtCore/qsharedpointer.h>
|
||||
#include <QtCore/qset.h>
|
||||
#include <QtCore/qlinkedlist.h>
|
||||
#include <QtCore/qvariant.h>
|
||||
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
namespace InfoSystem {
|
||||
|
||||
enum InfoType {
|
||||
InfoTrackID,
|
||||
InfoTrackArtist,
|
||||
InfoTrackAlbum,
|
||||
InfoTrackGenre,
|
||||
InfoTrackComposer,
|
||||
InfoTrackDate,
|
||||
InfoTrackNumber,
|
||||
InfoTrackDiscNumber,
|
||||
InfoTrackBitRate,
|
||||
InfoTrackLength,
|
||||
InfoTrackSampleRate,
|
||||
InfoTrackFileSize,
|
||||
InfoTrackBPM,
|
||||
InfoTrackReplayGain,
|
||||
InfoTrackReplayPeakGain,
|
||||
InfoTrackLyrics,
|
||||
InfoTrackLocation,
|
||||
InfoTrackProfile,
|
||||
InfoTrackEnergy,
|
||||
InfoTrackDanceability,
|
||||
InfoTrackTempo,
|
||||
InfoTrackLoudness,
|
||||
|
||||
InfoArtistID,
|
||||
InfoArtistName,
|
||||
InfoArtistBiography,
|
||||
InfoArtistBlog,
|
||||
InfoArtistFamiliarity,
|
||||
InfoArtistHotttness,
|
||||
InfoArtistImages,
|
||||
InfoArtistNews,
|
||||
InfoArtistProfile,
|
||||
InfoArtistReviews,
|
||||
InfoArtistSongs,
|
||||
InfoArtistSimilars,
|
||||
InfoArtistTerms,
|
||||
InfoArtistLinks,
|
||||
InfoArtistVideos,
|
||||
|
||||
InfoAlbumID,
|
||||
InfoAlbumName,
|
||||
InfoAlbumArtist,
|
||||
InfoAlbumDate,
|
||||
InfoAlbumGenre,
|
||||
InfoAlbumComposer,
|
||||
InfoMiscTopHotttness,
|
||||
InfoMiscTopTerms,
|
||||
|
||||
InfoNoInfo
|
||||
};
|
||||
|
||||
typedef QMap< InfoType, QVariant > InfoMap;
|
||||
typedef QMap< QString, QMap< QString, QString > > InfoGenericMap;
|
||||
typedef QHash<QString, QVariant> InfoCustomDataHash;
|
||||
typedef QHash<QString, QString> MusixMatchHash;
|
||||
|
||||
class InfoPlugin : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InfoPlugin(QObject *parent)
|
||||
:QObject(parent)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
~InfoPlugin()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
virtual void getInfo(const QString &caller, const InfoType type, const QVariant &data, Tomahawk::InfoSystem::InfoCustomDataHash customData) = 0;
|
||||
|
||||
signals:
|
||||
void info(QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomDataHash customData);
|
||||
void finished(QString, Tomahawk::InfoSystem::InfoType);
|
||||
|
||||
protected:
|
||||
InfoType m_type;
|
||||
};
|
||||
|
||||
typedef QWeakPointer< InfoPlugin > InfoPluginPtr;
|
||||
|
||||
class InfoSystem : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
|
||||
InfoSystem(QObject *parent);
|
||||
~InfoSystem()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
void registerInfoTypes(const InfoPluginPtr &plugin, const QSet< InfoType > &types);
|
||||
|
||||
void getInfo(const QString &caller, const InfoType type, const QVariant &data, InfoCustomDataHash customData);
|
||||
void getInfo(const QString &caller, const InfoMap &input, InfoCustomDataHash customData);
|
||||
|
||||
signals:
|
||||
void info(QString caller, Tomahawk::InfoSystem::InfoType, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomDataHash customData);
|
||||
void finished(QString target);
|
||||
|
||||
public slots:
|
||||
void infoSlot(QString target, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomDataHash customData);
|
||||
void finishedSlot(QString target,Tomahawk::InfoSystem::InfoType type);
|
||||
|
||||
private:
|
||||
|
||||
QLinkedList< InfoPluginPtr > determineOrderedMatches(const InfoType type) const;
|
||||
|
||||
QMap< InfoType, QLinkedList<InfoPluginPtr> > m_infoMap;
|
||||
|
||||
// For now, statically instantiate plugins; this is just somewhere to keep them
|
||||
QLinkedList<InfoPluginPtr> m_plugins;
|
||||
|
||||
QHash< QString, QHash< Tomahawk::InfoSystem::InfoType, int > > m_dataTracker;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(Tomahawk::InfoSystem::InfoGenericMap)
|
||||
Q_DECLARE_METATYPE(Tomahawk::InfoSystem::InfoCustomDataHash);
|
||||
Q_DECLARE_METATYPE(Tomahawk::InfoSystem::MusixMatchHash)
|
||||
|
||||
#endif // TOMAHAWK_INFOSYSTEM_H
|
@@ -51,13 +51,13 @@ public:
|
||||
|
||||
signals:
|
||||
void resultsAdded( const QList<Tomahawk::result_ptr>& );
|
||||
void resultsRemoved( Tomahawk::result_ptr );
|
||||
void resultsRemoved( const Tomahawk::result_ptr& );
|
||||
void solvedStateChanged( bool state );
|
||||
|
||||
public slots:
|
||||
/// (indirectly) called by resolver plugins when results are found
|
||||
void addResults( const QList< Tomahawk::result_ptr >& );
|
||||
void removeResult( Tomahawk::result_ptr );
|
||||
void removeResult( const Tomahawk::result_ptr& );
|
||||
|
||||
private slots:
|
||||
void resultUnavailable();
|
||||
|
@@ -29,9 +29,18 @@
|
||||
|
||||
class Database;
|
||||
class Jabber;
|
||||
class XMPPBot;
|
||||
class TomahawkZeroconf;
|
||||
class TomahawkSettings;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
namespace InfoSystem
|
||||
{
|
||||
class InfoSystem;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef TOMAHAWK_HEADLESS
|
||||
class AudioEngine;
|
||||
class TomahawkWindow;
|
||||
@@ -64,6 +73,9 @@ public:
|
||||
SourceList& sourcelist() { return m_sources; }
|
||||
Servent& servent() { return m_servent; }
|
||||
QNetworkAccessManager* nam() { return m_nam; }
|
||||
QNetworkProxy* proxy() { return m_proxy; }
|
||||
Tomahawk::InfoSystem::InfoSystem* infoSystem() { return m_infoSystem; }
|
||||
XMPPBot* xmppBot() { return m_xmppBot; }
|
||||
const QString& nodeID() const;
|
||||
|
||||
#ifndef TOMAHAWK_HEADLESS
|
||||
@@ -114,6 +126,7 @@ private:
|
||||
SourceList m_sources;
|
||||
TomahawkZeroconf* m_zeroconf;
|
||||
QSharedPointer<Jabber> m_jabber;
|
||||
XMPPBot* m_xmppBot;
|
||||
|
||||
#ifndef TOMAHAWK_HEADLESS
|
||||
TomahawkWindow* m_mainwindow;
|
||||
@@ -129,6 +142,9 @@ private:
|
||||
TomahawkSettings* m_settings;
|
||||
|
||||
QNetworkAccessManager* m_nam;
|
||||
QNetworkProxy* m_proxy;
|
||||
|
||||
Tomahawk::InfoSystem::InfoSystem* m_infoSystem;
|
||||
|
||||
QxtHttpServerConnector m_connector;
|
||||
QxtHttpSessionManager m_session;
|
||||
|
@@ -36,6 +36,10 @@ SET( tomahawkSources ${tomahawkSources}
|
||||
utils/tomahawkutils.cpp
|
||||
jabber/jabber_p.cpp
|
||||
|
||||
infosystem/infosystem.cpp
|
||||
infosystem/infoplugins/echonestplugin.cpp
|
||||
infosystem/infoplugins/musixmatchplugin.cpp
|
||||
|
||||
bufferiodevice.cpp
|
||||
connection.cpp
|
||||
msgprocessor.cpp
|
||||
@@ -73,6 +77,8 @@ SET( tomahawkSources ${tomahawkSources}
|
||||
database/databasecommand_updatesearchindex.cpp
|
||||
database/databasecollection.cpp
|
||||
|
||||
xmppbot/xmppbot.cpp
|
||||
|
||||
web/api_v1.cpp
|
||||
|
||||
tomahawksettings.cpp
|
||||
@@ -139,6 +145,8 @@ SET( tomahawkHeaders ${tomahawkHeaders}
|
||||
"${TOMAHAWK_INC_DIR}/tomahawk/track.h"
|
||||
"${TOMAHAWK_INC_DIR}/tomahawk/playlist.h"
|
||||
|
||||
"${TOMAHAWK_INC_DIR}/tomahawk/infosystem.h"
|
||||
|
||||
"${TOMAHAWK_INC_DIR}/tomahawk/functimeout.h"
|
||||
# "${TOMAHAWK_INC_DIR}/tomahawk/tomahawkplugin.h"
|
||||
|
||||
@@ -170,6 +178,9 @@ SET( tomahawkHeaders ${tomahawkHeaders}
|
||||
jabber/jabber.h
|
||||
jabber/jabber_p.h
|
||||
|
||||
infosystem/infoplugins/echonestplugin.h
|
||||
infosystem/infoplugins/musixmatchplugin.h
|
||||
|
||||
bufferiodevice.h
|
||||
connection.h
|
||||
msgprocessor.h
|
||||
@@ -183,6 +194,8 @@ SET( tomahawkHeaders ${tomahawkHeaders}
|
||||
scriptresolver.h
|
||||
tomahawksettings.h
|
||||
|
||||
xmppbot/xmppbot.h
|
||||
|
||||
web/api_v1.h
|
||||
)
|
||||
|
||||
@@ -231,12 +244,13 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui}
|
||||
)
|
||||
|
||||
SET( tomahawkUI ${tomahawkUI}
|
||||
tomahawkwindow.ui
|
||||
settingsdialog.ui
|
||||
tomahawkwindow.ui
|
||||
settingsdialog.ui
|
||||
proxydialog.ui
|
||||
|
||||
audiocontrols.ui
|
||||
sourcetree/sourcetreeitemwidget.ui
|
||||
topbar/topbar.ui
|
||||
audiocontrols.ui
|
||||
sourcetree/sourcetreeitemwidget.ui
|
||||
topbar/topbar.ui
|
||||
)
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
@@ -258,6 +272,8 @@ INCLUDE_DIRECTORIES(
|
||||
|
||||
/usr/include/taglib
|
||||
/usr/local/include/taglib
|
||||
/usr/include/echonest
|
||||
/usr/local/include/echonest
|
||||
/usr/local/include
|
||||
)
|
||||
|
||||
@@ -304,6 +320,7 @@ TARGET_LINK_LIBRARIES( tomahawk
|
||||
${QT_LIBRARIES}
|
||||
${MAC_EXTRA_LIBS}
|
||||
${OS_SPECIFIC_LINK_LIBRARIES}
|
||||
echonest
|
||||
portfwd
|
||||
)
|
||||
|
||||
|
@@ -25,4 +25,4 @@ ELSE()
|
||||
|
||||
SET( tomahawkSourcesGui ${tomahawkSourcesGui} audio/vorbistranscode.cpp scrobbler.cpp )
|
||||
SET( tomahawkHeadersGui ${tomahawkHeadersGui} audio/vorbistranscode.h scrobbler.h )
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
|
@@ -13,8 +13,8 @@ SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "rj@tomahawk.org")
|
||||
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/../README")
|
||||
SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/../LICENSE.txt")
|
||||
SET(CPACK_PACKAGE_VERSION_MAJOR "0")
|
||||
SET(CPACK_PACKAGE_VERSION_MINOR "1")
|
||||
SET(CPACK_PACKAGE_VERSION_PATCH "3")
|
||||
SET(CPACK_PACKAGE_VERSION_MINOR "0")
|
||||
SET(CPACK_PACKAGE_VERSION_PATCH "1")
|
||||
SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
|
||||
|
||||
#SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "i386") # Default: Output of dpkg --print-architecture or i386
|
||||
@@ -51,7 +51,7 @@ ENDIF(WIN32 AND NOT UNIX)
|
||||
# Nsis only? SET(CPACK_PACKAGE_EXECUTABLES "tomahawk" "tomahawk")
|
||||
|
||||
#gnutls is in here because gloox needs it, and we link statically to gloox:
|
||||
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libqtgui4 (>=4:4.6.2-0ubuntu5), libtag1c2a (>=1.6.2-0ubuntu1), liblastfm-dev (>=0.4.0~git20090710-1), libqt4-sql-sqlite (>=4:4.6.2-0ubuntu5), libvorbis0a (>=1.2.3-3ubuntu1), libmad0 (>=0.15.1b-4ubuntu1), libasound2 (>=1.0.22-0ubuntu7), zlib1g (>=1:1.2.3.3.dfsg-15ubuntu1), libqjson-dev (>=0.7.1-1), libgnutls26 (>= 2.7.14-0)")
|
||||
SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libqtgui4 (>=4:4.7.0-0ubuntu1), libtag1c2a (>=1.6.2-0ubuntu1), liblastfm-dev (>=0.4.0~really0.3.3-0ubuntu1), libqt4-sql-sqlite (>=4:4.7.0-0ubuntu1), libvorbis0a (>=1.2.3-3ubuntu1), libmad0 (>=0.15.1b-4ubuntu1), libasound2 (>=1.0.22-0ubuntu7), zlib1g (>=1:1.2.3.3.dfsg-15ubuntu1), libqjson-dev (>=0.7.1-1), libgnutls26 (>= 2.7.14-0), libgloox8 (>=1.0-1)")
|
||||
|
||||
#SET(CPACK_DEBIAN_PACKAGE_SECTION "music")
|
||||
|
||||
|
@@ -91,6 +91,7 @@ DatabaseCommand_LoadPlaylistEntries::exec( DatabaseImpl* dbi )
|
||||
|
||||
if( !query_entries_old.next() )
|
||||
{
|
||||
return;
|
||||
Q_ASSERT( false );
|
||||
}
|
||||
|
||||
|
260
src/infosystem/infoplugins/echonestplugin.cpp
Normal file
260
src/infosystem/infoplugins/echonestplugin.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
#include "tomahawk/infosystem.h"
|
||||
#include "tomahawk/tomahawkapp.h"
|
||||
#include "echonestplugin.h"
|
||||
#include <echonest/Artist.h>
|
||||
#include <echonest/ArtistTypes.h>
|
||||
|
||||
using namespace Tomahawk::InfoSystem;
|
||||
using namespace Echonest;
|
||||
|
||||
// for internal neatness
|
||||
|
||||
EchoNestPlugin::EchoNestPlugin(QObject *parent)
|
||||
: InfoPlugin(parent)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
Config::instance()->setAPIKey("JGJCRKWLXLBZIFAZB");
|
||||
QSet< InfoType > supportedTypes;
|
||||
supportedTypes << Tomahawk::InfoSystem::InfoArtistBiography << Tomahawk::InfoSystem::InfoArtistFamiliarity << Tomahawk::InfoSystem::InfoArtistHotttness << Tomahawk::InfoSystem::InfoArtistTerms << Tomahawk::InfoSystem::InfoMiscTopTerms;
|
||||
qobject_cast< InfoSystem* >(parent)->registerInfoTypes(this, supportedTypes);
|
||||
}
|
||||
|
||||
EchoNestPlugin::~EchoNestPlugin()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
void EchoNestPlugin::getInfo(const QString &caller, const InfoType type, const QVariant& data, InfoCustomDataHash customData)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Tomahawk::InfoSystem::InfoArtistBiography:
|
||||
return getArtistBiography(caller, data, customData);
|
||||
case Tomahawk::InfoSystem::InfoArtistFamiliarity:
|
||||
return getArtistFamiliarity(caller, data, customData);
|
||||
case Tomahawk::InfoSystem::InfoArtistHotttness:
|
||||
return getArtistHotttnesss(caller, data, customData);
|
||||
case Tomahawk::InfoSystem::InfoArtistTerms:
|
||||
return getArtistTerms(caller, data, customData);
|
||||
case Tomahawk::InfoSystem::InfoTrackEnergy:
|
||||
return getSongProfile(caller, data, customData, "energy");
|
||||
case Tomahawk::InfoSystem::InfoMiscTopTerms:
|
||||
return getMiscTopTerms(caller, data, customData);
|
||||
default:
|
||||
{
|
||||
emit info(caller, Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariant(), customData);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EchoNestPlugin::getSongProfile(const QString &caller, const QVariant& data, InfoCustomDataHash &customData, const QString &item)
|
||||
{
|
||||
//WARNING: Totally not implemented yet
|
||||
|
||||
if( !isValidTrackData( caller, data, customData ) )
|
||||
return;
|
||||
|
||||
// Track track( data.toString() );
|
||||
// Artist artist( customData.data()->property("artistName").toString() );
|
||||
// reply->setProperty("artist", QVariant::fromValue<Artist>(artist));
|
||||
// reply->setProperty( "data", data );
|
||||
// m_replyMap[reply] = customData;
|
||||
// connect(reply, SIGNAL(finished()), SLOT(getArtistBiographySlot()));
|
||||
}
|
||||
|
||||
void EchoNestPlugin::getArtistBiography(const QString &caller, const QVariant& data, InfoCustomDataHash &customData)
|
||||
{
|
||||
if( !isValidArtistData( caller, data, customData ) )
|
||||
return;
|
||||
|
||||
Artist artist( data.toString() );
|
||||
QNetworkReply *reply = artist.fetchBiographies();
|
||||
reply->setProperty("artist", QVariant::fromValue<Artist>(artist));
|
||||
reply->setProperty( "data", data );
|
||||
m_replyMap[reply] = customData;
|
||||
m_callerMap[reply] = caller;
|
||||
connect(reply, SIGNAL(finished()), SLOT(getArtistBiographySlot()));
|
||||
}
|
||||
|
||||
void EchoNestPlugin::getArtistFamiliarity(const QString &caller, const QVariant& data, InfoCustomDataHash &customData)
|
||||
{
|
||||
if( !isValidArtistData( caller, data, customData ) )
|
||||
return;
|
||||
|
||||
qDebug() << "Fetching artist familiarity!" << data;
|
||||
Artist artist( data.toString() );
|
||||
QNetworkReply* reply = artist.fetchFamiliarity();
|
||||
reply->setProperty( "artist", QVariant::fromValue<Artist>(artist));
|
||||
reply->setProperty( "data", data );
|
||||
m_replyMap[reply] = customData;
|
||||
m_callerMap[reply] = caller;
|
||||
connect(reply, SIGNAL(finished()), SLOT(getArtistFamiliaritySlot()));
|
||||
}
|
||||
|
||||
void EchoNestPlugin::getArtistHotttnesss(const QString &caller, const QVariant& data, InfoCustomDataHash &customData)
|
||||
{
|
||||
if( !isValidArtistData( caller, data, customData ) )
|
||||
return;
|
||||
|
||||
Artist artist( data.toString() );
|
||||
QNetworkReply* reply = artist.fetchHotttnesss();
|
||||
reply->setProperty( "artist", QVariant::fromValue<Artist>(artist));
|
||||
reply->setProperty( "data", data );
|
||||
m_replyMap[reply] = customData;
|
||||
m_callerMap[reply] = caller;
|
||||
connect(reply, SIGNAL(finished()), SLOT(getArtistHotttnesssSlot()));
|
||||
}
|
||||
|
||||
void EchoNestPlugin::getArtistTerms(const QString &caller, const QVariant& data, InfoCustomDataHash &customData)
|
||||
{
|
||||
if( !isValidArtistData( caller, data, customData ) )
|
||||
return;
|
||||
|
||||
Artist artist( data.toString() );
|
||||
QNetworkReply* reply = artist.fetchTerms( Echonest::Artist::Weight );
|
||||
reply->setProperty( "artist", QVariant::fromValue<Artist>(artist));
|
||||
reply->setProperty( "data", data );
|
||||
m_replyMap[reply] = customData;
|
||||
m_callerMap[reply] = caller;
|
||||
connect(reply, SIGNAL(finished()), SLOT(getArtistTermsSlot()));
|
||||
}
|
||||
|
||||
void EchoNestPlugin::getMiscTopTerms(const QString &caller, const QVariant& data, InfoCustomDataHash& customData)
|
||||
{
|
||||
QNetworkReply* reply = Artist::topTerms( 20 );
|
||||
m_replyMap[reply] = customData;
|
||||
m_callerMap[reply] = caller;
|
||||
connect( reply,SIGNAL(finished()), SLOT( getMiscTopSlot()));
|
||||
}
|
||||
|
||||
|
||||
void EchoNestPlugin::getArtistBiographySlot()
|
||||
{
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
Artist artist = artistFromReply( reply );
|
||||
BiographyList biographies = artist.biographies();
|
||||
InfoGenericMap biographyMap;
|
||||
Q_FOREACH(const Biography& biography, biographies)
|
||||
{
|
||||
biographyMap[biography.site()]["site"] = biography.site();
|
||||
biographyMap[biography.site()]["url"] = biography.url().toString();
|
||||
biographyMap[biography.site()]["text"] = biography.text();
|
||||
biographyMap[biography.site()]["attribution"] = biography.license().attribution;
|
||||
biographyMap[biography.site()]["licensetype"] = biography.license().type;
|
||||
biographyMap[biography.site()]["attribution"] = biography.license().url.toString();
|
||||
|
||||
}
|
||||
emit info( m_callerMap[reply], Tomahawk::InfoSystem::InfoArtistBiography, reply->property( "data" ), QVariant::fromValue<Tomahawk::InfoSystem::InfoGenericMap>(biographyMap), m_replyMap[reply] );
|
||||
emit finished( m_callerMap[reply], Tomahawk::InfoSystem::InfoArtistBiography);
|
||||
m_replyMap.remove(reply);
|
||||
m_callerMap.remove(reply);
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void EchoNestPlugin::getArtistFamiliaritySlot()
|
||||
{
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
Artist artist = artistFromReply( reply );
|
||||
qreal familiarity = artist.familiarity();
|
||||
emit info( m_callerMap[reply], Tomahawk::InfoSystem::InfoArtistFamiliarity, reply->property( "data" ), familiarity, m_replyMap[reply] );
|
||||
emit finished( m_callerMap[reply], Tomahawk::InfoSystem::InfoArtistFamiliarity);
|
||||
m_replyMap.remove(reply);
|
||||
m_callerMap.remove(reply);
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void EchoNestPlugin::getArtistHotttnesssSlot()
|
||||
{
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
Artist artist = artistFromReply( reply );
|
||||
qreal hotttnesss = artist.hotttnesss();
|
||||
emit info( m_callerMap[reply], Tomahawk::InfoSystem::InfoArtistHotttness, reply->property( "data" ), hotttnesss, m_replyMap[reply] );
|
||||
emit finished( m_callerMap[reply], Tomahawk::InfoSystem::InfoArtistHotttness);
|
||||
m_replyMap.remove(reply);
|
||||
m_callerMap.remove(reply);
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void EchoNestPlugin::getArtistTermsSlot()
|
||||
{
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
Artist artist = artistFromReply( reply );
|
||||
TermList terms = artist.terms();
|
||||
InfoGenericMap termsMap;
|
||||
Q_FOREACH( const Echonest::Term& term, terms ) {
|
||||
QMap< QString, QString > termMap;
|
||||
termMap[ "weight" ] = QString::number(term.weight());
|
||||
termMap[ "frequency" ] = QString::number(term.frequency());
|
||||
termsMap[ term.name() ] = termMap;
|
||||
}
|
||||
emit info( m_callerMap[reply], Tomahawk::InfoSystem::InfoArtistTerms, reply->property( "data" ), QVariant::fromValue<Tomahawk::InfoSystem::InfoGenericMap>(termsMap), m_replyMap[reply] );
|
||||
emit finished( m_callerMap[reply], Tomahawk::InfoSystem::InfoArtistTerms);
|
||||
m_replyMap.remove(reply);
|
||||
m_callerMap.remove(reply);
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void EchoNestPlugin::getMiscTopSlot()
|
||||
{
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
TermList terms = Artist::parseTopTerms( reply );
|
||||
InfoGenericMap termsMap;
|
||||
Q_FOREACH( const Echonest::Term& term, terms ) {
|
||||
QMap< QString, QString > termMap;
|
||||
termMap[ "weight" ] = QString::number( term.weight() );
|
||||
termMap[ "frequency" ] = QString::number( term.frequency() );
|
||||
termsMap[ term.name().toLower() ] = termMap;
|
||||
}
|
||||
emit info( m_callerMap[reply], Tomahawk::InfoSystem::InfoMiscTopTerms, QVariant(), QVariant::fromValue<Tomahawk::InfoSystem::InfoGenericMap>(termsMap), m_replyMap[reply] );
|
||||
emit finished( m_callerMap[reply], Tomahawk::InfoSystem::InfoMiscTopTerms);
|
||||
m_replyMap.remove(reply);
|
||||
m_callerMap.remove(reply);
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
bool EchoNestPlugin::isValidArtistData(const QString &caller, const QVariant& data, InfoCustomDataHash &customData)
|
||||
{
|
||||
if (data.isNull() || !data.isValid() || !data.canConvert<QString>())
|
||||
{
|
||||
emit info(caller, Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariant(), customData);
|
||||
return false;
|
||||
}
|
||||
QString artistName = data.toString();
|
||||
if (artistName.isEmpty() )
|
||||
{
|
||||
emit info(caller, Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariant(), customData);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EchoNestPlugin::isValidTrackData(const QString &caller, const QVariant& data, InfoCustomDataHash &customData)
|
||||
{
|
||||
if (data.isNull() || !data.isValid() || !data.canConvert<QString>())
|
||||
{
|
||||
emit info(caller, Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariant(), customData);
|
||||
return false;
|
||||
}
|
||||
QString trackName = data.toString();
|
||||
if (trackName.isEmpty() )
|
||||
{
|
||||
emit info(caller, Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariant(), customData);
|
||||
return false;
|
||||
}
|
||||
if (!customData.contains("artistName") ||
|
||||
customData["artistName"].toString().isEmpty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Artist EchoNestPlugin::artistFromReply(QNetworkReply* reply)
|
||||
{
|
||||
Artist artist = reply->property("artist").value<Artist>();
|
||||
try {
|
||||
artist.parseProfile(reply);
|
||||
} catch( const Echonest::ParseError& e ) {
|
||||
qWarning() << "Caught parser error from echonest!" << e.what();
|
||||
}
|
||||
return artist;
|
||||
}
|
54
src/infosystem/infoplugins/echonestplugin.h
Normal file
54
src/infosystem/infoplugins/echonestplugin.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef ECHONESTPLUGIN_H
|
||||
#define ECHONESTPLUGIN_H
|
||||
#include "tomahawk/infosystem.h"
|
||||
|
||||
class QNetworkReply;
|
||||
namespace Echonest {
|
||||
class Artist;
|
||||
}
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
|
||||
class EchoNestPlugin : public InfoPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EchoNestPlugin(QObject *parent);
|
||||
virtual ~EchoNestPlugin();
|
||||
|
||||
void getInfo( const QString &caller, const InfoType type, const QVariant &data, InfoCustomDataHash customData );
|
||||
|
||||
private:
|
||||
void getSongProfile( const QString &caller, const QVariant &data, InfoCustomDataHash &customData, const QString &item = QString() );
|
||||
void getArtistBiography ( const QString &caller, const QVariant &data, InfoCustomDataHash &customData );
|
||||
void getArtistFamiliarity( const QString &caller, const QVariant &data, InfoCustomDataHash &customData );
|
||||
void getArtistHotttnesss( const QString &caller, const QVariant &data, InfoCustomDataHash &customData );
|
||||
void getArtistTerms( const QString &caller, const QVariant &data, InfoCustomDataHash &customData );
|
||||
void getMiscTopTerms( const QString &caller, const QVariant &data, InfoCustomDataHash &customData );
|
||||
|
||||
bool isValidArtistData( const QString &caller, const QVariant& data, InfoCustomDataHash& customData );
|
||||
bool isValidTrackData( const QString &caller, const QVariant& data, InfoCustomDataHash& customData );
|
||||
Echonest::Artist artistFromReply( QNetworkReply* );
|
||||
|
||||
private slots:
|
||||
void getArtistBiographySlot();
|
||||
void getArtistFamiliaritySlot();
|
||||
void getArtistHotttnesssSlot();
|
||||
void getArtistTermsSlot();
|
||||
void getMiscTopSlot();
|
||||
|
||||
private:
|
||||
QHash< QNetworkReply*, InfoCustomDataHash > m_replyMap;
|
||||
QHash< QNetworkReply*, QString > m_callerMap;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // ECHONESTPLUGIN_H
|
134
src/infosystem/infoplugins/musixmatchplugin.cpp
Normal file
134
src/infosystem/infoplugins/musixmatchplugin.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
#include "tomahawk/infosystem.h"
|
||||
#include "tomahawk/tomahawkapp.h"
|
||||
#include "musixmatchplugin.h"
|
||||
#include <QNetworkReply>
|
||||
|
||||
using namespace Tomahawk::InfoSystem;
|
||||
|
||||
// for internal neatness
|
||||
|
||||
MusixMatchPlugin::MusixMatchPlugin(QObject *parent)
|
||||
: InfoPlugin(parent)
|
||||
, m_apiKey("61be4ea5aea7dd942d52b2f1311dd9fe")
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QSet< InfoType > supportedTypes;
|
||||
supportedTypes << Tomahawk::InfoSystem::InfoTrackLyrics;
|
||||
qobject_cast< InfoSystem* >(parent)->registerInfoTypes(this, supportedTypes);
|
||||
}
|
||||
|
||||
MusixMatchPlugin::~MusixMatchPlugin()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
void MusixMatchPlugin::getInfo(const QString &caller, const InfoType type, const QVariant& data, Tomahawk::InfoSystem::InfoCustomDataHash customData)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if( !isValidTrackData(caller, data, customData) || !data.canConvert<Tomahawk::InfoSystem::MusixMatchHash>())
|
||||
return;
|
||||
Tomahawk::InfoSystem::MusixMatchHash hash = data.value<Tomahawk::InfoSystem::MusixMatchHash>();
|
||||
QString artist = hash["artistName"];
|
||||
QString track = hash["trackName"];
|
||||
if( artist.isEmpty() || track.isEmpty() )
|
||||
{
|
||||
emit info(caller, Tomahawk::InfoSystem::InfoTrackLyrics, data, QVariant(), customData);
|
||||
emit finished(caller, Tomahawk::InfoSystem::InfoTrackLyrics);
|
||||
return;
|
||||
}
|
||||
qDebug() << "artist is " << artist << ", track is " << track;
|
||||
QString requestString("http://api.musixmatch.com/ws/1.1/track.search?format=xml&page_size=1&f_has_lyrics=1");
|
||||
QUrl url(requestString);
|
||||
url.addQueryItem("apikey", m_apiKey);
|
||||
url.addQueryItem("q_artist", artist);
|
||||
url.addQueryItem("q_track", track);
|
||||
QNetworkReply* reply = TomahawkApp::instance()->nam()->get(QNetworkRequest(url));
|
||||
reply->setProperty("customData", QVariant::fromValue<Tomahawk::InfoSystem::InfoCustomDataHash>(customData));
|
||||
reply->setProperty("origData", data);
|
||||
reply->setProperty("caller", caller);
|
||||
|
||||
connect(reply, SIGNAL(finished()), SLOT(trackSearchSlot()));
|
||||
}
|
||||
|
||||
bool MusixMatchPlugin::isValidTrackData(const QString &caller, const QVariant& data, Tomahawk::InfoSystem::InfoCustomDataHash &customData)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if (data.isNull() || !data.isValid() || !data.canConvert<Tomahawk::InfoSystem::MusixMatchHash>())
|
||||
{
|
||||
emit info(caller, Tomahawk::InfoSystem::InfoTrackLyrics, data, QVariant(), customData);
|
||||
emit finished(caller, Tomahawk::InfoSystem::InfoTrackLyrics);
|
||||
qDebug() << "MusixMatchPlugin::isValidTrackData: Data null, invalid, or can't convert";
|
||||
return false;
|
||||
}
|
||||
MusixMatchHash hash = data.value<Tomahawk::InfoSystem::MusixMatchHash>();
|
||||
if (hash["trackName"].isEmpty() )
|
||||
{
|
||||
emit info(caller, Tomahawk::InfoSystem::InfoTrackLyrics, data, QVariant(), customData);
|
||||
emit finished(caller, Tomahawk::InfoSystem::InfoTrackLyrics);
|
||||
qDebug() << "MusixMatchPlugin::isValidTrackData: Track name is empty";
|
||||
return false;
|
||||
}
|
||||
if (hash["artistName"].isEmpty() )
|
||||
{
|
||||
emit info(caller, Tomahawk::InfoSystem::InfoTrackLyrics, data, QVariant(), customData);
|
||||
emit finished(caller, Tomahawk::InfoSystem::InfoTrackLyrics);
|
||||
qDebug() << "MusixMatchPlugin::isValidTrackData: No artist name found";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MusixMatchPlugin::trackSearchSlot()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QNetworkReply* oldReply = qobject_cast<QNetworkReply*>( sender() );
|
||||
if (!oldReply)
|
||||
{
|
||||
emit info(QString(), Tomahawk::InfoSystem::InfoTrackLyrics, QVariant(), QVariant(), Tomahawk::InfoSystem::InfoCustomDataHash());
|
||||
return;
|
||||
}
|
||||
QDomDocument doc;
|
||||
doc.setContent(oldReply->readAll());
|
||||
qDebug() << doc.toString();
|
||||
QDomNodeList domNodeList = doc.elementsByTagName("track_id");
|
||||
if (domNodeList.isEmpty())
|
||||
{
|
||||
emit info(oldReply->property("caller").toString(), Tomahawk::InfoSystem::InfoTrackLyrics, oldReply->property("origData"), QVariant(), oldReply->property("customData").value<Tomahawk::InfoSystem::InfoCustomDataHash>());
|
||||
emit finished(oldReply->property("caller").toString(), Tomahawk::InfoSystem::InfoTrackLyrics);
|
||||
return;
|
||||
}
|
||||
QString track_id = domNodeList.at(0).toElement().text();
|
||||
QString requestString("http://api.musixmatch.com/ws/1.1/track.lyrics.get?track_id=%1&format=xml&apikey=%2");
|
||||
QUrl url(requestString);
|
||||
url.addQueryItem("apikey", m_apiKey);
|
||||
url.addQueryItem("track_id", track_id);
|
||||
QNetworkReply* newReply = TomahawkApp::instance()->nam()->get(QNetworkRequest(url));
|
||||
newReply->setProperty("origData", oldReply->property("origData"));
|
||||
newReply->setProperty("customData", oldReply->property("customData"));
|
||||
newReply->setProperty("caller", oldReply->property("caller"));
|
||||
connect(newReply, SIGNAL(finished()), SLOT(trackLyricsSlot()));
|
||||
}
|
||||
|
||||
void MusixMatchPlugin::trackLyricsSlot()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
|
||||
if (!reply)
|
||||
{
|
||||
emit info(QString(), Tomahawk::InfoSystem::InfoTrackLyrics, QVariant(), QVariant(), Tomahawk::InfoSystem::InfoCustomDataHash());
|
||||
return;
|
||||
}
|
||||
QDomDocument doc;
|
||||
doc.setContent(reply->readAll());
|
||||
QDomNodeList domNodeList = doc.elementsByTagName("lyrics_body");
|
||||
if (domNodeList.isEmpty())
|
||||
{
|
||||
emit info(reply->property("caller").toString(), Tomahawk::InfoSystem::InfoTrackLyrics, reply->property("origData"), QVariant(), reply->property("customData").value<Tomahawk::InfoSystem::InfoCustomDataHash>());
|
||||
emit finished(reply->property("caller").toString(), Tomahawk::InfoSystem::InfoTrackLyrics);
|
||||
return;
|
||||
}
|
||||
QString lyrics = domNodeList.at(0).toElement().text();
|
||||
qDebug() << "Emitting lyrics: " << lyrics;
|
||||
emit info(reply->property("caller").toString(), Tomahawk::InfoSystem::InfoTrackLyrics, reply->property("origData"), QVariant(lyrics), reply->property("customData").value<Tomahawk::InfoSystem::InfoCustomDataHash>());
|
||||
emit finished(reply->property("caller").toString(), Tomahawk::InfoSystem::InfoTrackLyrics);
|
||||
}
|
38
src/infosystem/infoplugins/musixmatchplugin.h
Normal file
38
src/infosystem/infoplugins/musixmatchplugin.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef MUSIXMATCHPLUGIN_H
|
||||
#define MUSIXMATCHPLUGIN_H
|
||||
#include "tomahawk/infosystem.h"
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
|
||||
class MusixMatchPlugin : public InfoPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MusixMatchPlugin(QObject *parent);
|
||||
virtual ~MusixMatchPlugin();
|
||||
|
||||
void getInfo(const QString &caller, const InfoType type, const QVariant &data, InfoCustomDataHash customData);
|
||||
|
||||
private:
|
||||
bool isValidTrackData( const QString &caller, const QVariant& data, InfoCustomDataHash &customData );
|
||||
|
||||
public slots:
|
||||
void trackSearchSlot();
|
||||
void trackLyricsSlot();
|
||||
|
||||
private:
|
||||
QString m_apiKey;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // MUSIXMATCHPLUGIN_H
|
96
src/infosystem/infosystem.cpp
Normal file
96
src/infosystem/infosystem.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
#include "tomahawk/infosystem.h"
|
||||
#include "infoplugins/echonestplugin.h"
|
||||
#include "infoplugins/musixmatchplugin.h"
|
||||
|
||||
using namespace Tomahawk::InfoSystem;
|
||||
|
||||
InfoSystem::InfoSystem(QObject *parent)
|
||||
: QObject( parent )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
qRegisterMetaType<QMap< QString, QMap< QString, QString > > >("Tomahawk::InfoSystem::InfoGenericMap");
|
||||
qRegisterMetaType<QHash<QString, QVariant > >("Tomahawk::InfoSystem::InfoCustomDataHash");
|
||||
qRegisterMetaType<QHash<QString, QString > >("Tomahawk::InfoSystem::MusixMatchHash");
|
||||
InfoPluginPtr enptr(new EchoNestPlugin(this));
|
||||
m_plugins.append(enptr);
|
||||
InfoPluginPtr mmptr(new MusixMatchPlugin(this));
|
||||
m_plugins.append(mmptr);
|
||||
}
|
||||
|
||||
void InfoSystem::registerInfoTypes(const InfoPluginPtr &plugin, const QSet< InfoType >& types)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
Q_FOREACH(InfoType type, types)
|
||||
m_infoMap[type].append(plugin);
|
||||
}
|
||||
|
||||
QLinkedList< InfoPluginPtr > InfoSystem::determineOrderedMatches(const InfoType type) const
|
||||
{
|
||||
//Dummy function for now that returns the various items in the QSet; at some point this will
|
||||
//probably need to support ordering based on the data source
|
||||
QLinkedList< InfoPluginPtr > providers;
|
||||
Q_FOREACH(InfoPluginPtr ptr, m_infoMap[type])
|
||||
providers << ptr;
|
||||
return providers;
|
||||
}
|
||||
|
||||
void InfoSystem::getInfo(const QString &caller, const InfoType type, const QVariant& data, InfoCustomDataHash customData)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QLinkedList< InfoPluginPtr > providers = determineOrderedMatches(type);
|
||||
if (providers.isEmpty())
|
||||
{
|
||||
emit info(QString(), Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariant(), customData);
|
||||
return;
|
||||
}
|
||||
|
||||
InfoPluginPtr ptr = providers.first();
|
||||
if (!ptr)
|
||||
{
|
||||
emit info(QString(), Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariant(), customData);
|
||||
return;
|
||||
}
|
||||
|
||||
m_dataTracker[caller][type] = m_dataTracker[caller][type] + 1;
|
||||
qDebug() << "current count in dataTracker for type" << type << "is" << m_dataTracker[caller][type];
|
||||
connect(ptr.data(), SIGNAL(info(QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomDataHash)),
|
||||
this, SLOT(infoSlot(QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomDataHash)), Qt::UniqueConnection);
|
||||
connect(ptr.data(), SIGNAL(finished(QString, Tomahawk::InfoSystem::InfoType)),
|
||||
this, SLOT(finishedSlot(QString, Tomahawk::InfoSystem::InfoType)), Qt::UniqueConnection);
|
||||
ptr.data()->getInfo(caller, type, data, customData);
|
||||
}
|
||||
|
||||
void InfoSystem::getInfo(const QString &caller, const InfoMap &input, InfoCustomDataHash customData)
|
||||
{
|
||||
Q_FOREACH( InfoType type, input.keys() )
|
||||
getInfo(caller, type, input[type], customData);
|
||||
}
|
||||
|
||||
void InfoSystem::infoSlot(QString target, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomDataHash customData)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
qDebug() << "current count in dataTracker is " << m_dataTracker[target][type];
|
||||
if (m_dataTracker[target][type] == 0)
|
||||
{
|
||||
qDebug() << "Caller was not waiting for that type of data!";
|
||||
return;
|
||||
}
|
||||
emit info(target, type, input, output, customData);
|
||||
}
|
||||
|
||||
void InfoSystem::finishedSlot(QString target, Tomahawk::InfoSystem::InfoType type)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
m_dataTracker[target][type] = m_dataTracker[target][type] - 1;
|
||||
qDebug() << "current count in dataTracker is " << m_dataTracker[target][type];
|
||||
Q_FOREACH(Tomahawk::InfoSystem::InfoType testtype, m_dataTracker[target].keys())
|
||||
{
|
||||
if (m_dataTracker[target][testtype] != 0)
|
||||
{
|
||||
qDebug() << "found outstanding request of type" << testtype;
|
||||
return;
|
||||
}
|
||||
}
|
||||
qDebug() << "emitting finished with target" << target;
|
||||
emit finished(target);
|
||||
}
|
@@ -11,11 +11,8 @@ class Jabber : public QObject
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
Jabber(const QString &jid,
|
||||
const QString password,
|
||||
const QString server = "",
|
||||
const int port=-1)
|
||||
: p( jid, password, server, port )
|
||||
Jabber( const QString &jid, const QString password, const QString server = "", const int port=-1 )
|
||||
: p( jid, password, server, port )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -24,6 +21,11 @@ public:
|
||||
// p.disconnect();
|
||||
}
|
||||
|
||||
void setProxy( QNetworkProxy* proxy )
|
||||
{
|
||||
p.setProxy( proxy );
|
||||
}
|
||||
|
||||
public slots:
|
||||
|
||||
void start()
|
||||
|
@@ -2,6 +2,8 @@
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTime>
|
||||
#include <QString>
|
||||
#include <QRegExp>
|
||||
|
||||
using namespace gloox;
|
||||
using namespace std;
|
||||
@@ -62,6 +64,40 @@ Jabber_p::~Jabber_p()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Jabber_p::setProxy( QNetworkProxy* proxy )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if( !m_client || !proxy )
|
||||
{
|
||||
qDebug() << "No client or no proxy";
|
||||
return;
|
||||
}
|
||||
|
||||
QNetworkProxy appProx = QNetworkProxy::applicationProxy();
|
||||
QNetworkProxy* prox = proxy->type() == QNetworkProxy::DefaultProxy ? &appProx : proxy;
|
||||
|
||||
if( prox->type() == QNetworkProxy::NoProxy )
|
||||
{
|
||||
qDebug() << "Setting proxy to none";
|
||||
m_client->setConnectionImpl( new gloox::ConnectionTCPClient( m_client.data(), m_client->logInstance(), m_client->server(), m_client->port() ) );
|
||||
}
|
||||
else if( proxy->type() == QNetworkProxy::Socks5Proxy )
|
||||
{
|
||||
qDebug() << "Setting proxy to SOCKS5";
|
||||
m_client->setConnectionImpl( new gloox::ConnectionSOCKS5Proxy( m_client.data(),
|
||||
new gloox::ConnectionTCPClient( m_client->logInstance(), proxy->hostName().toStdString(), proxy->port() ),
|
||||
m_client->logInstance(), m_client->server(), m_client->port() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "Proxy type unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Jabber_p::go()
|
||||
{
|
||||
@@ -79,8 +115,10 @@ Jabber_p::go()
|
||||
|
||||
m_client->setPresence( Presence::Available, 1, "Tomahawk available" );
|
||||
|
||||
// m_client->connect();
|
||||
// return;
|
||||
// m_client->connect();
|
||||
// return;
|
||||
|
||||
// Handle proxy
|
||||
|
||||
if( m_client->connect( false ) )
|
||||
{
|
||||
@@ -108,7 +146,7 @@ Jabber_p::doJabberRecv()
|
||||
void
|
||||
Jabber_p::disconnect()
|
||||
{
|
||||
if(m_client)
|
||||
if ( m_client )
|
||||
{
|
||||
m_client->disconnect();
|
||||
}
|
||||
@@ -400,14 +438,21 @@ Jabber_p::handleRosterPresence( const RosterItem& item, const std::string& resou
|
||||
return;
|
||||
|
||||
// ignore anyone not running tomahawk:
|
||||
if( jid.full().find( "/tomahawk" ) == string::npos )
|
||||
// convert to QString to get proper regex support
|
||||
QString res( jid.resource().c_str() );
|
||||
QRegExp regex( "tomahawk\\d+" );
|
||||
if( res != "tomahawk-tomahawk" && !res.contains( regex ) )
|
||||
{
|
||||
qDebug() << "not considering resource of " << res;
|
||||
// Disco them to check if they are tomahawk-capable
|
||||
|
||||
//qDebug() << "No tomahawk resource, DISCOing... " << jid.full().c_str();
|
||||
//m_client->disco()->getDiscoInfo( jid, "", this, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "handling presence for resource of " << res;
|
||||
|
||||
//qDebug() << Q_FUNC_INFO << "jid: " << QString::fromStdString(item.jid())
|
||||
// << " resource: " << QString::fromStdString(resource)
|
||||
// << " presencetype " << presence;
|
||||
@@ -425,7 +470,7 @@ Jabber_p::handleRosterPresence( const RosterItem& item, const std::string& resou
|
||||
return;
|
||||
}
|
||||
|
||||
// "coming online " event
|
||||
// "coming online" event
|
||||
if( presenceMeansOnline( presence ) &&
|
||||
( !m_peers.contains( fulljid ) ||
|
||||
!presenceMeansOnline( m_peers.value( fulljid ) )
|
||||
@@ -478,6 +523,20 @@ Jabber_p::handleNonrosterPresence( const Presence& presence )
|
||||
/// END ROSTER STUFF
|
||||
|
||||
|
||||
void
|
||||
Jabber_p::handleVCard( const JID& jid, const VCard* vcard )
|
||||
{
|
||||
qDebug() << "VCARD RECEIVED!" << jid.bare().c_str();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Jabber_p::handleVCardResult( VCardContext context, const JID& jid, StanzaError se )
|
||||
{
|
||||
qDebug() << "VCARD RESULT RECEIVED!" << jid.bare().c_str();
|
||||
}
|
||||
|
||||
|
||||
/// DISCO STUFF
|
||||
void
|
||||
Jabber_p::handleDiscoInfo( const JID& from, const Disco::Info& info, int context)
|
||||
@@ -525,8 +584,3 @@ bool Jabber_p::presenceMeansOnline( Presence::PresenceType p )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
#include <QMap>
|
||||
#include <QNetworkProxy>
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
@@ -41,6 +42,9 @@
|
||||
#include <gloox/error.h>
|
||||
#include <gloox/presence.h>
|
||||
#include <gloox/rosteritem.h>
|
||||
#include <gloox/vcard.h>
|
||||
#include <gloox/vcardhandler.h>
|
||||
#include <gloox/vcardmanager.h>
|
||||
|
||||
#if defined( WIN32 ) || defined( _WIN32 )
|
||||
# include <windows.h>
|
||||
@@ -51,6 +55,7 @@ class Jabber_p :
|
||||
public gloox::ConnectionListener,
|
||||
public gloox::RosterListener,
|
||||
public gloox::MessageHandler,
|
||||
public gloox::VCardHandler,
|
||||
gloox::LogHandler
|
||||
//public gloox::DiscoHandler,
|
||||
{
|
||||
@@ -60,6 +65,8 @@ public:
|
||||
explicit Jabber_p( const QString& jid, const QString& password, const QString& server = "", const int port = -1 );
|
||||
virtual ~Jabber_p();
|
||||
|
||||
void setProxy( QNetworkProxy* proxy );
|
||||
|
||||
void disconnect();
|
||||
|
||||
/// GLOOX IMPLEMENTATION STUFF FOLLOWS
|
||||
@@ -91,6 +98,9 @@ public:
|
||||
virtual void handleNonrosterPresence( const gloox::Presence& presence );
|
||||
/// END ROSTER STUFF
|
||||
|
||||
virtual void handleVCard( const gloox::JID& jid, const gloox::VCard* vcard );
|
||||
virtual void handleVCardResult( gloox::VCardHandler::VCardContext context, const gloox::JID& jid, gloox::StanzaError se );
|
||||
|
||||
/// DISCO STUFF
|
||||
virtual void handleDiscoInfo( const gloox::JID& from, const gloox::Disco::Info& info, int context);
|
||||
virtual void handleDiscoItems( const gloox::JID& /*iq*/, const gloox::Disco::Items&, int /*context*/ );
|
||||
@@ -115,7 +125,6 @@ public slots:
|
||||
void broadcastMsg( const QString &msg );
|
||||
|
||||
private slots:
|
||||
|
||||
void doJabberRecv();
|
||||
|
||||
private:
|
||||
@@ -125,6 +134,7 @@ private:
|
||||
gloox::JID m_jid;
|
||||
QMap<gloox::Presence::PresenceType, QString> m_presences;
|
||||
QMap<QString, gloox::Presence::PresenceType> m_peers;
|
||||
QSharedPointer<gloox::VCardManager> m_vcardManager;
|
||||
QTimer m_timer; // for recv()
|
||||
};
|
||||
|
||||
|
@@ -17,6 +17,7 @@ Pipeline::Pipeline( QObject* parent )
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Pipeline::databaseReady()
|
||||
{
|
||||
@@ -24,6 +25,7 @@ Pipeline::databaseReady()
|
||||
APP->database()->loadIndex();
|
||||
}
|
||||
|
||||
|
||||
void Pipeline::indexReady()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "shuting this many pending queries:" << m_queries_pending.size();
|
||||
@@ -36,12 +38,14 @@ void Pipeline::indexReady()
|
||||
m_queries_pending.clear();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Pipeline::removeResolver( Resolver* r )
|
||||
{
|
||||
m_resolvers.removeAll( r );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Pipeline::addResolver( Resolver* r, bool sort )
|
||||
{
|
||||
|
@@ -299,8 +299,6 @@ Playlist::setRevision( const QString& rev,
|
||||
m_currentrevision = rev;
|
||||
pr.applied = applied;
|
||||
|
||||
|
||||
|
||||
emit revisionLoaded( pr );
|
||||
}
|
||||
|
||||
|
@@ -12,6 +12,8 @@ CollectionFlatModel::CollectionFlatModel( QObject* parent )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
m_rootItem = new PlItem( 0, this );
|
||||
|
||||
connect( &APP->sourcelist(), SIGNAL( sourceRemoved( Tomahawk::source_ptr ) ), SLOT( onSourceOffline( Tomahawk::source_ptr ) ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +67,7 @@ CollectionFlatModel::removeCollection( const collection_ptr& collection )
|
||||
disconnect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ),
|
||||
this, SLOT( onTracksAddingFinished( Tomahawk::collection_ptr ) ) );
|
||||
|
||||
QList<PlItem*> plitems = m_collectionIndex.values( collection );
|
||||
// QList<PlItem*> plitems = m_collectionIndex.values( collection );
|
||||
QList< QPair< int, int > > rows;
|
||||
QList< QPair< int, int > > sortrows;
|
||||
QPair< int, int > row;
|
||||
@@ -111,11 +113,15 @@ CollectionFlatModel::removeCollection( const collection_ptr& collection )
|
||||
|
||||
qDebug() << "Removing rows:" << row.first << row.second;
|
||||
emit beginRemoveRows( QModelIndex(), row.first, row.second );
|
||||
for ( int i = row.second; i >= row.first; i-- )
|
||||
{
|
||||
PlItem* item = itemFromIndex( index( i, 0, QModelIndex() ) );
|
||||
delete item;
|
||||
}
|
||||
emit endRemoveRows();
|
||||
}
|
||||
|
||||
qDeleteAll( plitems );
|
||||
m_collectionIndex.remove( collection );
|
||||
// m_collectionIndex.remove( collection );
|
||||
}
|
||||
|
||||
|
||||
@@ -148,7 +154,7 @@ CollectionFlatModel::onTracksAdded( const QList<QVariant>& tracks, const collect
|
||||
|
||||
connect( plitem, SIGNAL( dataChanged() ), SLOT( onDataChanged() ) );
|
||||
|
||||
m_collectionIndex.insertMulti( collection, plitem );
|
||||
// m_collectionIndex.insertMulti( collection, plitem );
|
||||
}
|
||||
|
||||
m_collectionRows.insertMulti( collection, crows );
|
||||
@@ -174,3 +180,15 @@ CollectionFlatModel::onDataChanged()
|
||||
// emit itemSizeChanged( p->index );
|
||||
emit dataChanged( p->index, p->index.sibling( p->index.row(), columnCount() - 1 ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CollectionFlatModel::onSourceOffline( const Tomahawk::source_ptr& src )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if ( m_collectionRows.contains( src->collection() ) )
|
||||
{
|
||||
removeCollection( src->collection() );
|
||||
}
|
||||
}
|
||||
|
@@ -47,8 +47,9 @@ private slots:
|
||||
void onTracksAdded( const QList<QVariant>& tracks, const Tomahawk::collection_ptr& collection );
|
||||
void onTracksAddingFinished( const Tomahawk::collection_ptr& collection );
|
||||
|
||||
void onSourceOffline( const Tomahawk::source_ptr& src );
|
||||
|
||||
private:
|
||||
QMap< Tomahawk::collection_ptr, PlItem* > m_collectionIndex;
|
||||
QMap< Tomahawk::collection_ptr, QPair< int, int > > m_collectionRows;
|
||||
};
|
||||
|
||||
|
@@ -11,6 +11,8 @@ CollectionModel::CollectionModel( QObject* parent )
|
||||
: QAbstractItemModel( parent )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
connect( &APP->sourcelist(), SIGNAL( sourceRemoved( Tomahawk::source_ptr ) ), SLOT( onSourceOffline( Tomahawk::source_ptr ) ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -242,3 +244,15 @@ CollectionModel::onTracksAddingFinished( const Tomahawk::collection_ptr& /* coll
|
||||
qDebug() << "Finished loading tracks";
|
||||
emit loadingFinished();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CollectionModel::onSourceOffline( Tomahawk::source_ptr src )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if ( m_collectionIndex.contains( src->collection() ) )
|
||||
{
|
||||
removeCollection( src->collection() );
|
||||
}
|
||||
}
|
||||
|
@@ -63,6 +63,8 @@ private slots:
|
||||
void onTracksAdded( const QList<QVariant>& tracks, const Tomahawk::collection_ptr& collection );
|
||||
void onTracksAddingFinished( const Tomahawk::collection_ptr& collection );
|
||||
|
||||
void onSourceOffline( Tomahawk::source_ptr src );
|
||||
|
||||
private:
|
||||
QMap< Tomahawk::collection_ptr, PlItem* > m_collectionIndex;
|
||||
};
|
||||
|
@@ -38,6 +38,9 @@ void
|
||||
PlaylistItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
PlItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
|
||||
if ( !item )
|
||||
return;
|
||||
|
||||
if ( item->query()->results().count() )
|
||||
painter->setOpacity( item->query()->results().at( 0 )->score() );
|
||||
else
|
||||
|
@@ -21,6 +21,8 @@ PlaylistManager::PlaylistManager( QObject* parent )
|
||||
, m_currentMode( 0 )
|
||||
, m_superCollectionVisible( true )
|
||||
{
|
||||
m_widget->setMinimumWidth( 620 );
|
||||
|
||||
m_superCollectionViews << new CollectionView();
|
||||
m_superCollectionViews.first()->setModel( m_superCollectionFlatModel );
|
||||
m_widget->addWidget( m_superCollectionViews.first() );
|
||||
|
@@ -9,6 +9,7 @@ using namespace Tomahawk;
|
||||
|
||||
PlaylistModel::PlaylistModel( QObject* parent )
|
||||
: TrackModel( parent )
|
||||
, m_waitForUpdate( false )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
m_rootItem = new PlItem( 0, this );
|
||||
@@ -51,13 +52,15 @@ PlaylistModel::loadPlaylist( const Tomahawk::playlist_ptr& playlist )
|
||||
{
|
||||
emit beginRemoveRows( QModelIndex(), 0, rowCount( QModelIndex() ) - 1 );
|
||||
delete m_rootItem;
|
||||
m_rootItem = new PlItem( 0, this );
|
||||
emit endRemoveRows();
|
||||
m_rootItem = new PlItem( 0, this );
|
||||
}
|
||||
|
||||
m_playlist = playlist;
|
||||
connect( playlist.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), SLOT( onRevisionLoaded( Tomahawk::PlaylistRevision ) ) );
|
||||
|
||||
setReadOnly( !m_playlist->author()->isLocal() );
|
||||
|
||||
PlItem* plitem;
|
||||
QList<plentry_ptr> entries = playlist->entries();
|
||||
int c = rowCount( QModelIndex() );
|
||||
@@ -68,6 +71,7 @@ PlaylistModel::loadPlaylist( const Tomahawk::playlist_ptr& playlist )
|
||||
|
||||
foreach( const plentry_ptr& entry, entries )
|
||||
{
|
||||
qDebug() << entry->query()->toString();
|
||||
plitem = new PlItem( entry, m_rootItem );
|
||||
plitem->index = createIndex( m_rootItem->children.count() - 1, 0, plitem );
|
||||
|
||||
@@ -95,5 +99,124 @@ PlaylistModel::onRevisionLoaded( Tomahawk::PlaylistRevision revision )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
loadPlaylist( m_playlist );
|
||||
if ( m_waitForUpdate )
|
||||
{
|
||||
qDebug() << m_playlist->currentrevision() << revision.revisionguid;
|
||||
m_waitForUpdate = false;
|
||||
}
|
||||
else
|
||||
loadPlaylist( m_playlist );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PlaylistModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent )
|
||||
{
|
||||
if ( action == Qt::IgnoreAction || isReadOnly() )
|
||||
return true;
|
||||
|
||||
if ( !data->hasFormat( "application/tomahawk.query.list" ) && !data->hasFormat( "application/tomahawk.plentry.list" ) )
|
||||
return false;
|
||||
|
||||
int beginRow;
|
||||
if ( row != -1 )
|
||||
beginRow = row;
|
||||
else if ( parent.isValid() )
|
||||
beginRow = parent.row();
|
||||
else
|
||||
beginRow = rowCount( QModelIndex() );
|
||||
|
||||
qDebug() << data->formats();
|
||||
|
||||
if ( data->hasFormat( "application/tomahawk.query.list" ) )
|
||||
{
|
||||
QByteArray itemData = data->data( "application/tomahawk.query.list" );
|
||||
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||
QList<Tomahawk::query_ptr> queries;
|
||||
|
||||
while ( !stream.atEnd() )
|
||||
{
|
||||
qlonglong qptr;
|
||||
stream >> qptr;
|
||||
|
||||
Tomahawk::query_ptr* query = reinterpret_cast<Tomahawk::query_ptr*>(qptr);
|
||||
if ( query && !query->isNull() )
|
||||
{
|
||||
qDebug() << "Dropped query item:" << query->data()->artist() << "-" << query->data()->track();
|
||||
queries << *query;
|
||||
}
|
||||
}
|
||||
|
||||
emit beginInsertRows( QModelIndex(), beginRow, beginRow + queries.count() - 1 );
|
||||
foreach( const Tomahawk::query_ptr& query, queries )
|
||||
{
|
||||
plentry_ptr e( new PlaylistEntry() );
|
||||
e->setGuid( uuid() );
|
||||
|
||||
if ( query->results().count() )
|
||||
e->setDuration( query->results().at( 0 )->duration() );
|
||||
else
|
||||
e->setDuration( 0 );
|
||||
|
||||
e->setLastmodified( 0 );
|
||||
e->setAnnotation( "" ); // FIXME
|
||||
e->setQuery( query );
|
||||
|
||||
PlItem* plitem = new PlItem( e, m_rootItem, beginRow );
|
||||
plitem->index = createIndex( beginRow++, 0, plitem );
|
||||
|
||||
connect( plitem, SIGNAL( dataChanged() ), SLOT( onDataChanged() ) );
|
||||
}
|
||||
emit endInsertRows();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::onPlaylistChanged()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
QList<plentry_ptr> l = playlistEntries();
|
||||
foreach( const plentry_ptr& ple, l )
|
||||
{
|
||||
qDebug() << "updateinternal:" << ple->query()->toString();
|
||||
}
|
||||
|
||||
QString newrev = uuid();
|
||||
m_playlist->createNewRevision( newrev, m_playlist->currentrevision(), l );
|
||||
}
|
||||
|
||||
|
||||
QList<Tomahawk::plentry_ptr>
|
||||
PlaylistModel::playlistEntries() const
|
||||
{
|
||||
QList<plentry_ptr> l;
|
||||
for ( int i = 0; i < rowCount( QModelIndex() ); i++ )
|
||||
{
|
||||
QModelIndex idx = index( i, 0, QModelIndex() );
|
||||
if ( !idx.isValid() )
|
||||
continue;
|
||||
|
||||
PlItem* item = itemFromIndex( idx );
|
||||
if ( item )
|
||||
l << item->entry();
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistModel::removeIndex( const QModelIndex& index )
|
||||
{
|
||||
if ( isReadOnly() )
|
||||
return;
|
||||
|
||||
TrackModel::removeIndex( index );
|
||||
|
||||
m_waitForUpdate = true;
|
||||
onPlaylistChanged();
|
||||
}
|
||||
|
@@ -28,8 +28,12 @@ public:
|
||||
QVariant data( const QModelIndex& index, int role ) const;
|
||||
QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
|
||||
|
||||
virtual bool dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent );
|
||||
|
||||
void loadPlaylist( const Tomahawk::playlist_ptr& playlist );
|
||||
|
||||
virtual void removeIndex( const QModelIndex& index );
|
||||
|
||||
signals:
|
||||
void repeatModeChanged( PlaylistInterface::RepeatMode mode );
|
||||
void shuffleModeChanged( bool enabled );
|
||||
@@ -43,9 +47,13 @@ private slots:
|
||||
void onDataChanged();
|
||||
|
||||
void onRevisionLoaded( Tomahawk::PlaylistRevision revision );
|
||||
void onPlaylistChanged();
|
||||
|
||||
private:
|
||||
QList<Tomahawk::plentry_ptr> playlistEntries() const;
|
||||
|
||||
Tomahawk::playlist_ptr m_playlist;
|
||||
bool m_waitForUpdate;
|
||||
};
|
||||
|
||||
#endif // PLAYLISTMODEL_H
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#include "playlistview.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "playlist/playlistproxymodel.h"
|
||||
|
||||
@@ -11,6 +12,9 @@ PlaylistView::PlaylistView( QWidget* parent )
|
||||
: TrackView( parent )
|
||||
{
|
||||
setProxyModel( new PlaylistProxyModel( this ) );
|
||||
|
||||
setContextMenuPolicy( Qt::CustomContextMenu );
|
||||
connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( onCustomContextMenu( const QPoint& ) ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -18,3 +22,77 @@ PlaylistView::~PlaylistView()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistView::setupMenus()
|
||||
{
|
||||
m_itemMenu.clear();
|
||||
|
||||
m_playItemAction = m_itemMenu.addAction( tr( "&Play" ) );
|
||||
m_itemMenu.addSeparator();
|
||||
m_addItemsToPlaylistAction = m_itemMenu.addAction( tr( "&Add to Playlist" ) );
|
||||
m_itemMenu.addSeparator();
|
||||
m_deleteItemAction = m_itemMenu.addAction( tr( "&Delete Item" ) );
|
||||
|
||||
if ( model() )
|
||||
m_deleteItemAction->setEnabled( !model()->isReadOnly() );
|
||||
|
||||
connect( m_playItemAction, SIGNAL( triggered() ), SLOT( playItem() ) );
|
||||
connect( m_addItemsToPlaylistAction, SIGNAL( triggered() ), SLOT( addItemsToPlaylist() ) );
|
||||
connect( m_deleteItemAction, SIGNAL( triggered() ), SLOT( deleteItem() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistView::onCustomContextMenu( const QPoint& pos )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
setupMenus();
|
||||
|
||||
QModelIndex idx = indexAt( pos );
|
||||
idx = idx.sibling( idx.row(), 0 );
|
||||
m_contextMenuIndex = idx;
|
||||
|
||||
if ( !idx.isValid() )
|
||||
return;
|
||||
|
||||
m_itemMenu.exec( mapToGlobal( pos ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistView::keyPressEvent( QKeyEvent* event )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QTreeView::keyPressEvent( event );
|
||||
|
||||
if ( !model() )
|
||||
return;
|
||||
|
||||
if ( event->key() == Qt::Key_Delete )
|
||||
{
|
||||
qDebug() << "Removing selected items";
|
||||
proxyModel()->removeIndexes( selectedIndexes() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistView::playItem()
|
||||
{
|
||||
onItemActivated( m_contextMenuIndex );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistView::addItemsToPlaylist()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlaylistView::deleteItem()
|
||||
{
|
||||
proxyModel()->removeIndex( m_contextMenuIndex );
|
||||
}
|
||||
|
@@ -1,6 +1,8 @@
|
||||
#ifndef PLAYLISTVIEW_H
|
||||
#define PLAYLISTVIEW_H
|
||||
|
||||
#include <QMenu>
|
||||
|
||||
#include "tomahawk/tomahawkapp.h"
|
||||
#include "trackview.h"
|
||||
|
||||
@@ -11,6 +13,26 @@ Q_OBJECT
|
||||
public:
|
||||
explicit PlaylistView( QWidget* parent = 0 );
|
||||
~PlaylistView();
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent( QKeyEvent* event );
|
||||
|
||||
private slots:
|
||||
void onCustomContextMenu( const QPoint& pos );
|
||||
|
||||
void playItem();
|
||||
void addItemsToPlaylist();
|
||||
void deleteItem();
|
||||
|
||||
private:
|
||||
void setupMenus();
|
||||
|
||||
QModelIndex m_contextMenuIndex;
|
||||
|
||||
QMenu m_itemMenu;
|
||||
QAction* m_playItemAction;
|
||||
QAction* m_addItemsToPlaylistAction;
|
||||
QAction* m_deleteItemAction;
|
||||
};
|
||||
|
||||
#endif // PLAYLISTVIEW_H
|
||||
|
@@ -9,12 +9,16 @@ using namespace Tomahawk;
|
||||
|
||||
PlItem::~PlItem()
|
||||
{
|
||||
qDeleteAll( children );
|
||||
// Don't use qDeleteAll here! The children will remove themselves
|
||||
// from the list when they get deleted and the qDeleteAll iterator
|
||||
// will fail badly!
|
||||
for ( int i = children.count() - 1; i >= 0; i-- )
|
||||
delete children.at( i );
|
||||
|
||||
// Q_ASSERT( parent->children.at( m_parentPos ) == this );
|
||||
|
||||
if ( parent )
|
||||
parent->children.removeAt( m_parentPos );
|
||||
if ( parent && index.isValid() )
|
||||
{
|
||||
parent->children.removeAt( index.row() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +32,6 @@ PlItem::PlItem( PlItem* parent, QAbstractItemModel* model )
|
||||
if ( parent )
|
||||
{
|
||||
parent->children.append( this );
|
||||
m_parentPos = parent->children.count() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,38 +48,42 @@ PlItem::PlItem( const QString& caption, PlItem* parent )
|
||||
if ( parent )
|
||||
{
|
||||
parent->children.append( this );
|
||||
m_parentPos = parent->children.count() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PlItem::PlItem( const Tomahawk::query_ptr& query, PlItem* parent )
|
||||
PlItem::PlItem( const Tomahawk::query_ptr& query, PlItem* parent, int row )
|
||||
: QObject( parent )
|
||||
{
|
||||
setupItem( query, parent );
|
||||
setupItem( query, parent, row );
|
||||
}
|
||||
|
||||
|
||||
PlItem::PlItem( const Tomahawk::plentry_ptr& entry, PlItem* parent )
|
||||
PlItem::PlItem( const Tomahawk::plentry_ptr& entry, PlItem* parent, int row )
|
||||
: QObject( parent )
|
||||
, m_entry( entry )
|
||||
{
|
||||
setupItem( entry->query(), parent );
|
||||
setupItem( entry->query(), parent, row );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlItem::setupItem( const Tomahawk::query_ptr& query, PlItem* parent )
|
||||
PlItem::setupItem( const Tomahawk::query_ptr& query, PlItem* parent, int row )
|
||||
{
|
||||
this->parent = parent;
|
||||
if ( parent )
|
||||
{
|
||||
parent->children.append( this );
|
||||
m_parentPos = parent->children.count() - 1;
|
||||
this->model = parent->model;
|
||||
if ( row < 0 )
|
||||
{
|
||||
parent->children.append( this );
|
||||
row = parent->children.count() - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
parent->children.insert( row, this );
|
||||
}
|
||||
|
||||
connect( model, SIGNAL( rowsRemoved( QModelIndex, int, int ) ),
|
||||
SLOT( onModelRowsRemoved( QModelIndex, int, int ) ) );
|
||||
this->model = parent->model;
|
||||
}
|
||||
|
||||
m_isPlaying = false;
|
||||
@@ -85,8 +92,11 @@ PlItem::setupItem( const Tomahawk::query_ptr& query, PlItem* parent )
|
||||
if ( query->numResults() )
|
||||
onResultsAdded( query->results() );
|
||||
|
||||
connect( query.data(), SIGNAL( resultsAdded( const QList<Tomahawk::result_ptr>& ) ),
|
||||
SLOT( onResultsAdded( const QList<Tomahawk::result_ptr>& ) ), Qt::DirectConnection );
|
||||
connect( query.data(), SIGNAL( resultsAdded( QList<Tomahawk::result_ptr> ) ),
|
||||
SLOT( onResultsAdded( QList<Tomahawk::result_ptr> ) ), Qt::DirectConnection );
|
||||
|
||||
connect( query.data(), SIGNAL( resultsRemoved( Tomahawk::result_ptr ) ),
|
||||
SLOT( onResultsRemoved( Tomahawk::result_ptr ) ), Qt::DirectConnection );
|
||||
}
|
||||
|
||||
|
||||
@@ -99,18 +109,7 @@ PlItem::onResultsAdded( const QList<Tomahawk::result_ptr>& results )
|
||||
|
||||
|
||||
void
|
||||
PlItem::onModelRowsRemoved( const QModelIndex& index, int start, int end )
|
||||
PlItem::onResultsRemoved( const Tomahawk::result_ptr& result )
|
||||
{
|
||||
if ( !toberemoved && this->parent->index == index )
|
||||
{
|
||||
if ( ( start <= m_parentPos ) && ( m_parentPos <= end ) )
|
||||
toberemoved = true;
|
||||
else
|
||||
{
|
||||
if ( start < m_parentPos )
|
||||
{
|
||||
m_parentPos -= ( end - start ) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
emit dataChanged();
|
||||
}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
#define PLITEM_H
|
||||
|
||||
#include <QHash>
|
||||
#include <QModelIndex>
|
||||
#include <QPersistentModelIndex>
|
||||
#include <QAbstractItemModel>
|
||||
|
||||
#include "tomahawk/query.h"
|
||||
@@ -17,8 +17,8 @@ public:
|
||||
|
||||
explicit PlItem( PlItem* parent = 0, QAbstractItemModel* model = 0 );
|
||||
explicit PlItem( const QString& caption, PlItem* parent = 0 );
|
||||
explicit PlItem( const Tomahawk::query_ptr& query, PlItem* parent = 0 );
|
||||
explicit PlItem( const Tomahawk::plentry_ptr& entry, PlItem* parent = 0 );
|
||||
explicit PlItem( const Tomahawk::query_ptr& query, PlItem* parent = 0, int row = -1 );
|
||||
explicit PlItem( const Tomahawk::plentry_ptr& entry, PlItem* parent = 0, int row = -1 );
|
||||
|
||||
const Tomahawk::plentry_ptr& entry() const { return m_entry; };
|
||||
const Tomahawk::query_ptr& query() const { return m_query; };
|
||||
@@ -31,7 +31,7 @@ public:
|
||||
QHash<QString, PlItem*> hash;
|
||||
QString caption;
|
||||
int childCount;
|
||||
QModelIndex index;
|
||||
QPersistentModelIndex index;
|
||||
QAbstractItemModel* model;
|
||||
bool toberemoved;
|
||||
|
||||
@@ -40,15 +40,14 @@ signals:
|
||||
|
||||
private slots:
|
||||
void onResultsAdded( const QList<Tomahawk::result_ptr>& result );
|
||||
void onModelRowsRemoved( const QModelIndex& index, int start, int end );
|
||||
void onResultsRemoved( const Tomahawk::result_ptr& result );
|
||||
|
||||
private:
|
||||
void setupItem( const Tomahawk::query_ptr& query, PlItem* parent );
|
||||
void setupItem( const Tomahawk::query_ptr& query, PlItem* parent, int row = -1 );
|
||||
|
||||
Tomahawk::plentry_ptr m_entry;
|
||||
Tomahawk::query_ptr m_query;
|
||||
bool m_isPlaying;
|
||||
int m_parentPos;
|
||||
};
|
||||
|
||||
#endif // PLITEM_H
|
||||
|
@@ -11,6 +11,7 @@ using namespace Tomahawk;
|
||||
|
||||
TrackModel::TrackModel( QObject* parent )
|
||||
: QAbstractItemModel( parent )
|
||||
, m_readOnly( true )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
@@ -260,3 +261,31 @@ TrackModel::mimeData( const QModelIndexList &indexes ) const
|
||||
|
||||
return mimeData;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackModel::removeIndex( const QModelIndex& index )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if ( index.column() > 0 )
|
||||
return;
|
||||
|
||||
PlItem* item = itemFromIndex( index );
|
||||
if ( item )
|
||||
{
|
||||
emit beginRemoveRows( index.parent(), index.row(), index.row() );
|
||||
delete item;
|
||||
emit endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackModel::removeIndexes( const QList<QModelIndex>& indexes )
|
||||
{
|
||||
foreach( const QModelIndex& idx, indexes )
|
||||
{
|
||||
removeIndex( idx );
|
||||
}
|
||||
}
|
||||
|
@@ -18,6 +18,8 @@ public:
|
||||
virtual QModelIndex index( int row, int column, const QModelIndex& parent ) const;
|
||||
virtual QModelIndex parent( const QModelIndex& child ) const;
|
||||
|
||||
virtual bool isReadOnly() const { return m_readOnly; }
|
||||
|
||||
virtual int trackCount() const { return rowCount( QModelIndex() ); }
|
||||
|
||||
virtual int rowCount( const QModelIndex& parent ) const;
|
||||
@@ -26,6 +28,9 @@ public:
|
||||
virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const;
|
||||
virtual QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
|
||||
|
||||
virtual void removeIndex( const QModelIndex& index );
|
||||
virtual void removeIndexes( const QList<QModelIndex>& indexes );
|
||||
|
||||
virtual PlItem* previousItem() { return 0; }
|
||||
virtual PlItem* nextItem() { return 0; }
|
||||
virtual PlItem* siblingItem( int direction ) { return 0; }
|
||||
@@ -49,8 +54,12 @@ public slots:
|
||||
virtual void setRepeatMode( PlaylistInterface::RepeatMode mode ) {}
|
||||
virtual void setShuffled( bool shuffled ) {}
|
||||
|
||||
protected:
|
||||
virtual void setReadOnly( bool b ) { m_readOnly = b; }
|
||||
|
||||
private:
|
||||
QPersistentModelIndex m_currentIndex;
|
||||
bool m_readOnly;
|
||||
};
|
||||
|
||||
#endif // TRACKMODEL_H
|
||||
|
@@ -168,3 +168,30 @@ TrackProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParen
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackProxyModel::removeIndex( const QModelIndex& index )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if ( !sourceModel() )
|
||||
return;
|
||||
if ( index.column() > 0 )
|
||||
return;
|
||||
|
||||
sourceModel()->removeIndex( mapToSource( index ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackProxyModel::removeIndexes( const QList<QModelIndex>& indexes )
|
||||
{
|
||||
if ( !sourceModel() )
|
||||
return;
|
||||
|
||||
foreach( const QModelIndex& idx, indexes )
|
||||
{
|
||||
removeIndex( idx );
|
||||
}
|
||||
}
|
||||
|
@@ -21,6 +21,9 @@ public:
|
||||
|
||||
virtual int trackCount() const { return rowCount( QModelIndex() ); }
|
||||
|
||||
virtual void removeIndex( const QModelIndex& index );
|
||||
virtual void removeIndexes( const QList<QModelIndex>& indexes );
|
||||
|
||||
virtual PlItem* previousItem();
|
||||
virtual PlItem* nextItem();
|
||||
virtual PlItem* siblingItem( int itemsAway );
|
||||
|
@@ -29,7 +29,7 @@ TrackView::TrackView( QWidget* parent )
|
||||
setDragEnabled( true );
|
||||
setDropIndicatorShown( false );
|
||||
setDragDropMode( QAbstractItemView::InternalMove );
|
||||
setDragDropOverwriteMode ( false );
|
||||
setDragDropOverwriteMode( false );
|
||||
setAllColumnsShowFocus( true );
|
||||
|
||||
header()->setMinimumSectionSize( 60 );
|
||||
@@ -186,39 +186,6 @@ TrackView::resizeColumns()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackView::keyPressEvent( QKeyEvent* event )
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO;
|
||||
QTreeView::keyPressEvent( event );
|
||||
|
||||
if ( !m_model )
|
||||
return;
|
||||
|
||||
if ( event->key() == Qt::Key_Delete )
|
||||
{
|
||||
/* if ( m_model->isPlaylistBacked() && selectedIndexes().count() )
|
||||
{
|
||||
qDebug() << "Removing selected items";
|
||||
QList<PlaylistItem*> items;
|
||||
|
||||
QModelIndexList sidxs = selectedIndexes();
|
||||
foreach( const QModelIndex& idx, sidxs )
|
||||
{
|
||||
if ( idx.column() > 0 )
|
||||
continue;
|
||||
|
||||
PlaylistItem* item = PlaylistModel::indexToPlaylistItem( idx );
|
||||
if ( item )
|
||||
items << item;
|
||||
}
|
||||
|
||||
m_model->removeItems( items );
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TrackView::dragEnterEvent( QDragEnterEvent* event )
|
||||
{
|
||||
@@ -241,6 +208,12 @@ TrackView::dragMoveEvent( QDragMoveEvent* event )
|
||||
{
|
||||
QTreeView::dragMoveEvent( event );
|
||||
|
||||
if ( model()->isReadOnly() )
|
||||
{
|
||||
event->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( event->mimeData()->hasFormat( "application/tomahawk.query.list" ) || event->mimeData()->hasFormat( "application/tomahawk.plentry.list" ) )
|
||||
{
|
||||
setDirtyRegion( m_dropRect );
|
||||
@@ -329,24 +302,25 @@ TrackView::onFilterChanged( const QString& )
|
||||
void
|
||||
TrackView::startDrag( Qt::DropActions supportedActions )
|
||||
{
|
||||
QList<QPersistentModelIndex> pindexes;
|
||||
QModelIndexList indexes = selectedIndexes();
|
||||
qDebug() << "Dragging" << indexes.count() << "indexes";
|
||||
for( int i = indexes.count() - 1 ; i >= 0; --i )
|
||||
{
|
||||
if( !( m_proxyModel->flags( indexes.at( i ) ) & Qt::ItemIsDragEnabled ) )
|
||||
if ( !( m_proxyModel->flags( indexes.at( i ) ) & Qt::ItemIsDragEnabled ) )
|
||||
indexes.removeAt( i );
|
||||
else
|
||||
pindexes << indexes.at( i );
|
||||
}
|
||||
|
||||
if( indexes.count() == 0 )
|
||||
if ( indexes.count() == 0 )
|
||||
return;
|
||||
|
||||
qDebug() << "Dragging" << indexes.count() << "indexes";
|
||||
|
||||
QMimeData *data = m_proxyModel->mimeData( indexes );
|
||||
QMimeData* data = m_proxyModel->mimeData( indexes );
|
||||
if ( !data )
|
||||
return;
|
||||
|
||||
QDrag *drag = new QDrag( this );
|
||||
QDrag* drag = new QDrag( this );
|
||||
drag->setMimeData( data );
|
||||
const QPixmap p = createDragPixmap( indexes.count() );
|
||||
drag->setPixmap( p );
|
||||
@@ -355,7 +329,15 @@ TrackView::startDrag( Qt::DropActions supportedActions )
|
||||
// NOTE: if we support moving items in the model
|
||||
// in the future, if exec() returns Qt::MoveAction
|
||||
// we need to clean up ourselves.
|
||||
drag->exec( supportedActions, Qt::CopyAction );
|
||||
Qt::DropAction action = drag->exec( supportedActions, Qt::CopyAction );
|
||||
|
||||
if ( action == Qt::MoveAction )
|
||||
{
|
||||
foreach ( const QPersistentModelIndex& idx, pindexes )
|
||||
{
|
||||
m_proxyModel->removeIndex( idx );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -396,22 +378,22 @@ TrackView::createDragPixmap( int itemCount ) const
|
||||
QPixmap dragPixmap( xCount * size + xCount - 1, yCount * size + yCount - 1 );
|
||||
dragPixmap.fill( Qt::transparent );
|
||||
|
||||
QPainter painter(&dragPixmap);
|
||||
QPainter painter( &dragPixmap );
|
||||
painter.setRenderHint( QPainter::Antialiasing );
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
for( int i = 0; i < itemCount; ++i )
|
||||
{
|
||||
const QPixmap pixmap = QPixmap( QString( RESPATH "icons/audio-x-generic-%2.png" ).arg( size ) );
|
||||
painter.drawPixmap(x, y, pixmap);
|
||||
const QPixmap pixmap = QPixmap( QString( ":/data/icons/audio-x-generic-%2.png" ).arg( size ) );
|
||||
painter.drawPixmap( x, y, pixmap );
|
||||
|
||||
x += size + 1;
|
||||
if (x >= dragPixmap.width())
|
||||
if ( x >= dragPixmap.width() )
|
||||
{
|
||||
x = 0;
|
||||
y += size + 1;
|
||||
}
|
||||
if (y >= dragPixmap.height())
|
||||
if ( y >= dragPixmap.height() )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
@@ -26,9 +26,11 @@ public:
|
||||
|
||||
void setModel( TrackModel* model );
|
||||
|
||||
public slots:
|
||||
void onItemActivated( const QModelIndex& index );
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent( QResizeEvent* event );
|
||||
virtual void keyPressEvent( QKeyEvent* event );
|
||||
|
||||
virtual void startDrag( Qt::DropActions supportedActions );
|
||||
virtual void dragEnterEvent( QDragEnterEvent* event );
|
||||
@@ -39,7 +41,6 @@ protected:
|
||||
void paintEvent( QPaintEvent* event );
|
||||
|
||||
private slots:
|
||||
void onItemActivated( const QModelIndex& index );
|
||||
void onItemResized( const QModelIndex& index );
|
||||
|
||||
void resizeColumns();
|
||||
|
174
src/proxydialog.ui
Normal file
174
src/proxydialog.ui
Normal file
@@ -0,0 +1,174 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ProxyDialog</class>
|
||||
<widget class="QDialog" name="ProxyDialog">
|
||||
<property name="windowModality">
|
||||
<enum>Qt::WindowModal</enum>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>200</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Proxy Settings</string>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
<y>160</y>
|
||||
<width>341</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="gridLayoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>381</width>
|
||||
<height>141</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="horizontalSpacing">
|
||||
<number>16</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="typeBox"/>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="hostLineEdit">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="hostLabel">
|
||||
<property name="text">
|
||||
<string>Host</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="portLabel">
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="portLineEdit"/>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLineEdit" name="userLineEdit"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="userLabel">
|
||||
<property name="text">
|
||||
<string>User</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="passwordLable">
|
||||
<property name="text">
|
||||
<string>Password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="passwordLineEdit">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="typeLabel">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ProxyDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ProxyDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@@ -50,31 +50,34 @@ Query::resultUnavailable()
|
||||
Result* result = (Result*) sender();
|
||||
Q_ASSERT( result );
|
||||
|
||||
for(int i = 0; i < m_results.length(); ++i )
|
||||
for ( int i = 0; i < m_results.length(); ++i )
|
||||
{
|
||||
if( m_results.value( i ).data() == result )
|
||||
if ( m_results.value( i ).data() == result )
|
||||
{
|
||||
result_ptr r = m_results.value( i );
|
||||
m_results.removeAt( i );
|
||||
|
||||
emit resultsRemoved( r );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_results.isEmpty() ) // FIXME proper score checking
|
||||
emit solvedStateChanged( false );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Query::removeResult( Tomahawk::result_ptr result )
|
||||
Query::removeResult( const Tomahawk::result_ptr& result )
|
||||
{
|
||||
bool becameUnsolved = false;
|
||||
{
|
||||
QMutexLocker lock( &m_mut );
|
||||
m_results.removeAll( result );
|
||||
|
||||
if ( m_results.isEmpty() ) // FIXME proper score checking
|
||||
becameUnsolved = true;
|
||||
|
||||
}
|
||||
emit resultsRemoved( result );
|
||||
if( becameUnsolved ) emit solvedStateChanged( false );
|
||||
|
||||
if ( m_results.isEmpty() ) // FIXME proper score checking
|
||||
emit solvedStateChanged( false );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
#include "settingsdialog.h"
|
||||
#include "ui_settingsdialog.h"
|
||||
#include "ui_proxydialog.h"
|
||||
|
||||
#include <QCryptographicHash>
|
||||
#include <QDebug>
|
||||
@@ -17,7 +18,8 @@
|
||||
#include <QDesktopServices>
|
||||
|
||||
|
||||
static QString md5( const QByteArray& src )
|
||||
static QString
|
||||
md5( const QByteArray& src )
|
||||
{
|
||||
QByteArray const digest = QCryptographicHash::hash( src, QCryptographicHash::Md5 );
|
||||
return QString::fromLatin1( digest.toHex() ).rightJustified( 32, '0' );
|
||||
@@ -27,6 +29,7 @@ static QString md5( const QByteArray& src )
|
||||
SettingsDialog::SettingsDialog( QWidget *parent )
|
||||
: QDialog( parent )
|
||||
, ui( new Ui::SettingsDialog )
|
||||
, m_proxySettings( this )
|
||||
, m_rejected( false )
|
||||
, m_testLastFmQuery( 0 )
|
||||
{
|
||||
@@ -39,9 +42,10 @@ SettingsDialog::SettingsDialog( QWidget *parent )
|
||||
// JABBER
|
||||
ui->checkBoxJabberAutoConnect->setChecked( s->jabberAutoConnect() );
|
||||
ui->jabberUsername->setText( s->jabberUsername() );
|
||||
ui->jabberPassword->setText(s->jabberPassword() );
|
||||
ui->jabberServer->setText( s->jabberServer() );
|
||||
ui->jabberPassword->setText( s->jabberPassword() );
|
||||
ui->jabberServer->setText( s->jabberServer() );
|
||||
ui->jabberPort->setValue( s->jabberPort() );
|
||||
ui->proxyButton->setVisible( false );
|
||||
|
||||
if ( ui->jabberPort->text().toInt() != 5222 || !ui->jabberServer->text().isEmpty() )
|
||||
{
|
||||
@@ -67,6 +71,7 @@ SettingsDialog::SettingsDialog( QWidget *parent )
|
||||
connect( ui->pushButtonTestLastfmLogin, SIGNAL( clicked( bool) ), this, SLOT( testLastFmLogin() ) );
|
||||
|
||||
connect( ui->buttonBrowse, SIGNAL( clicked() ), SLOT( showPathSelector() ) );
|
||||
connect( ui->proxyButton, SIGNAL( clicked() ), SLOT( showProxySettings() ) );
|
||||
connect( this, SIGNAL( rejected() ), SLOT( onRejected() ) );
|
||||
}
|
||||
|
||||
@@ -117,7 +122,6 @@ SettingsDialog::~SettingsDialog()
|
||||
{
|
||||
APP->reconnectJabber();
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
qDebug() << "Settings dialog cancelled, NOT saving prefs.";
|
||||
@@ -126,7 +130,8 @@ SettingsDialog::~SettingsDialog()
|
||||
}
|
||||
|
||||
|
||||
void SettingsDialog::showPathSelector()
|
||||
void
|
||||
SettingsDialog::showPathSelector()
|
||||
{
|
||||
QString path = QFileDialog::getExistingDirectory(
|
||||
this,
|
||||
@@ -141,7 +146,8 @@ void SettingsDialog::showPathSelector()
|
||||
}
|
||||
|
||||
|
||||
void SettingsDialog::doScan()
|
||||
void
|
||||
SettingsDialog::doScan()
|
||||
{
|
||||
// TODO this doesnt really belong here..
|
||||
QString path = ui->lineEditMusicPath->text();
|
||||
@@ -155,13 +161,15 @@ void SettingsDialog::doScan()
|
||||
}
|
||||
|
||||
|
||||
void SettingsDialog::onRejected()
|
||||
void
|
||||
SettingsDialog::onRejected()
|
||||
{
|
||||
m_rejected = true;
|
||||
}
|
||||
|
||||
|
||||
void SettingsDialog::changeEvent( QEvent *e )
|
||||
void
|
||||
SettingsDialog::changeEvent( QEvent *e )
|
||||
{
|
||||
QDialog::changeEvent( e );
|
||||
switch ( e->type() )
|
||||
@@ -176,7 +184,17 @@ void SettingsDialog::changeEvent( QEvent *e )
|
||||
}
|
||||
|
||||
|
||||
void SettingsDialog::testLastFmLogin()
|
||||
void
|
||||
SettingsDialog::showProxySettings()
|
||||
{
|
||||
m_proxySettings.exec();
|
||||
if ( m_proxySettings.result() == QDialog::Accepted )
|
||||
m_proxySettings.saveSettings();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsDialog::testLastFmLogin()
|
||||
{
|
||||
#ifndef NO_LIBLASTFM
|
||||
ui->pushButtonTestLastfmLogin->setEnabled( false );
|
||||
@@ -196,7 +214,8 @@ void SettingsDialog::testLastFmLogin()
|
||||
}
|
||||
|
||||
|
||||
void SettingsDialog::onLastFmFinished()
|
||||
void
|
||||
SettingsDialog::onLastFmFinished()
|
||||
{
|
||||
#ifndef NO_LIBLASTFM
|
||||
lastfm::XmlQuery lfm = lastfm::XmlQuery( m_testLastFmQuery->readAll() );
|
||||
@@ -233,3 +252,61 @@ void SettingsDialog::onLastFmFinished()
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
ProxyDialog::ProxyDialog( QWidget *parent )
|
||||
: QDialog( parent )
|
||||
, ui( new Ui::ProxyDialog )
|
||||
{
|
||||
ui->setupUi( this );
|
||||
|
||||
// ugly, I know, but...
|
||||
QHash<int,int> enumMap;
|
||||
int i = 0;
|
||||
ui->typeBox->insertItem( i, "No Proxy", QNetworkProxy::NoProxy );
|
||||
enumMap[QNetworkProxy::NoProxy] = i++;
|
||||
ui->typeBox->insertItem( i, "SOCKS 5", QNetworkProxy::Socks5Proxy );
|
||||
enumMap[QNetworkProxy::Socks5Proxy] = i++;
|
||||
|
||||
TomahawkSettings* s = TomahawkApp::instance()->settings();
|
||||
|
||||
ui->typeBox->setCurrentIndex( enumMap[s->proxyType()] );
|
||||
ui->hostLineEdit->setText( s->proxyHost() );
|
||||
ui->portLineEdit->setText( QString::number( s->proxyPort() ) );
|
||||
ui->userLineEdit->setText( s->proxyUsername() );
|
||||
ui->passwordLineEdit->setText( s->proxyPassword() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ProxyDialog::saveSettings()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
//First set settings
|
||||
TomahawkSettings* s = TomahawkApp::instance()->settings();
|
||||
s->setProxyHost( ui->hostLineEdit->text() );
|
||||
|
||||
bool ok;
|
||||
qulonglong port = ui->portLineEdit->text().toULongLong( &ok );
|
||||
if( ok )
|
||||
s->setProxyPort( port );
|
||||
|
||||
s->setProxyUsername( ui->userLineEdit->text() );
|
||||
s->setProxyPassword( ui->passwordLineEdit->text() );
|
||||
s->setProxyType( ui->typeBox->itemData( ui->typeBox->currentIndex() ).toInt() );
|
||||
|
||||
// Now, if a proxy is defined, set QNAM
|
||||
if( s->proxyType() == QNetworkProxy::NoProxy || s->proxyHost().isEmpty() )
|
||||
return;
|
||||
|
||||
QNetworkProxy proxy( static_cast<QNetworkProxy::ProxyType>(s->proxyType()), s->proxyHost(), s->proxyPort(), s->proxyUsername(), s->proxyPassword() );
|
||||
QNetworkAccessManager* nam = TomahawkApp::instance()->nam();
|
||||
nam->setProxy( proxy );
|
||||
QNetworkProxy* globalProxy = TomahawkApp::instance()->proxy();
|
||||
QNetworkProxy* oldProxy = globalProxy;
|
||||
globalProxy = new QNetworkProxy( proxy );
|
||||
if( oldProxy )
|
||||
delete oldProxy;
|
||||
|
||||
QNetworkProxy::setApplicationProxy( proxy );
|
||||
}
|
||||
|
@@ -8,8 +8,23 @@ class QNetworkReply;
|
||||
namespace Ui
|
||||
{
|
||||
class SettingsDialog;
|
||||
class ProxyDialog;
|
||||
}
|
||||
|
||||
class ProxyDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProxyDialog( QWidget *parent = 0 );
|
||||
~ProxyDialog() {};
|
||||
|
||||
void saveSettings();
|
||||
|
||||
private:
|
||||
Ui::ProxyDialog *ui;
|
||||
};
|
||||
|
||||
class SettingsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -31,12 +46,15 @@ private slots:
|
||||
void showPathSelector();
|
||||
void doScan();
|
||||
|
||||
void showProxySettings();
|
||||
|
||||
void testLastFmLogin();
|
||||
void onLastFmFinished();
|
||||
|
||||
private:
|
||||
Ui::SettingsDialog *ui;
|
||||
|
||||
ProxyDialog m_proxySettings;
|
||||
bool m_rejected;
|
||||
QNetworkReply* m_testLastFmQuery;
|
||||
};
|
||||
|
@@ -224,6 +224,43 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="proxyButton">
|
||||
<property name="text">
|
||||
<string>Proxy Settings...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@@ -234,7 +271,7 @@
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>146</height>
|
||||
<height>73</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@@ -531,5 +568,21 @@
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>checkBoxJabberAdvanced</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>proxyButton</receiver>
|
||||
<slot>setVisible(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>310</x>
|
||||
<y>110</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>368</x>
|
||||
<y>194</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
|
@@ -76,7 +76,9 @@ void
|
||||
Source::remove()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_cc = 0;
|
||||
emit offline();
|
||||
APP->sourcelist().remove( this );
|
||||
m_collections.clear();
|
||||
}
|
||||
|
@@ -31,7 +31,8 @@ SourceTreeView::SourceTreeView( QWidget* parent )
|
||||
setDropIndicatorShown( false );
|
||||
setAllColumnsShowFocus( false );
|
||||
|
||||
setupMenus();
|
||||
setContextMenuPolicy( Qt::CustomContextMenu );
|
||||
connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( onCustomContextMenu( const QPoint& ) ) );
|
||||
|
||||
m_model = new SourcesModel( this );
|
||||
setModel( m_model );
|
||||
@@ -50,15 +51,30 @@ SourceTreeView::SourceTreeView( QWidget* parent )
|
||||
void
|
||||
SourceTreeView::setupMenus()
|
||||
{
|
||||
m_playlistMenu.clear();
|
||||
|
||||
m_loadPlaylistAction = m_playlistMenu.addAction( tr( "&Load Playlist" ) );
|
||||
m_playlistMenu.addSeparator();
|
||||
m_deletePlaylistAction = m_playlistMenu.addAction( tr( "&Delete Playlist" ) );
|
||||
|
||||
bool readonly = true;
|
||||
int type = SourcesModel::indexType( m_contextMenuIndex );
|
||||
if ( type == 1 )
|
||||
{
|
||||
playlist_ptr playlist = SourcesModel::indexToPlaylist( m_contextMenuIndex );
|
||||
if ( !playlist.isNull() )
|
||||
{
|
||||
readonly = !playlist->author()->isLocal();
|
||||
}
|
||||
}
|
||||
|
||||
if ( readonly )
|
||||
{
|
||||
m_deletePlaylistAction->setEnabled( !readonly );
|
||||
}
|
||||
|
||||
connect( m_loadPlaylistAction, SIGNAL( triggered() ), SLOT( loadPlaylist() ) );
|
||||
connect( m_deletePlaylistAction, SIGNAL( triggered() ), SLOT( deletePlaylist() ) );
|
||||
|
||||
setContextMenuPolicy( Qt::CustomContextMenu );
|
||||
connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( onCustomContextMenu( const QPoint& ) ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -66,18 +82,9 @@ void
|
||||
SourceTreeView::onSourceOffline( Tomahawk::source_ptr src )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if ( APP->playlistManager()->superCollections().contains( src->collection() ) )
|
||||
{
|
||||
qDebug() << "Removing source from active view";
|
||||
APP->playlistManager()->show( src->collection() );
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "not removing source from active view (not active)";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceTreeView::onItemActivated( const QModelIndex& index )
|
||||
{
|
||||
@@ -171,6 +178,8 @@ SourceTreeView::onCustomContextMenu( const QPoint& pos )
|
||||
if ( !idx.isValid() )
|
||||
return;
|
||||
|
||||
setupMenus();
|
||||
|
||||
if ( SourcesModel::indexType( idx ) )
|
||||
{
|
||||
m_playlistMenu.exec( mapToGlobal( pos ) );
|
||||
|
@@ -7,12 +7,14 @@
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include "tomahawk/collection.h"
|
||||
#include "tomahawk/infosystem.h"
|
||||
#include "database/database.h"
|
||||
#include "database/databasecollection.h"
|
||||
#include "database/databasecommand_collectionstats.h"
|
||||
#include "database/databaseresolver.h"
|
||||
#include "jabber/jabber.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "xmppbot/xmppbot.h"
|
||||
#include "web/api_v1.h"
|
||||
#include "scriptresolver.h"
|
||||
|
||||
@@ -101,6 +103,8 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
|
||||
, m_zeroconf( 0 )
|
||||
, m_settings( 0 )
|
||||
, m_nam( 0 )
|
||||
, m_proxy( 0 )
|
||||
, m_infoSystem( 0 )
|
||||
{
|
||||
qsrand( QTime( 0, 0, 0 ).secsTo( QTime::currentTime() ) );
|
||||
|
||||
@@ -157,6 +161,24 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set up proxy
|
||||
if( m_settings->proxyType() != QNetworkProxy::NoProxy && !m_settings->proxyHost().isEmpty() )
|
||||
{
|
||||
qDebug() << "Setting proxy to saved values";
|
||||
m_proxy = new QNetworkProxy( static_cast<QNetworkProxy::ProxyType>(m_settings->proxyType()), m_settings->proxyHost(), m_settings->proxyPort(), m_settings->proxyUsername(), m_settings->proxyPassword() );
|
||||
qDebug() << "Proxy type = " << QString::number( static_cast<int>(m_proxy->type()) );
|
||||
qDebug() << "Proxy host = " << m_proxy->hostName();
|
||||
QNetworkAccessManager* nam = TomahawkApp::instance()->nam();
|
||||
nam->setProxy( *m_proxy );
|
||||
}
|
||||
else
|
||||
m_proxy = new QNetworkProxy( QNetworkProxy::NoProxy );
|
||||
|
||||
QNetworkProxy::setApplicationProxy( *m_proxy );
|
||||
|
||||
m_infoSystem = new Tomahawk::InfoSystem::InfoSystem( this );
|
||||
m_xmppBot = new XMPPBot( this );
|
||||
|
||||
boost::function<QSharedPointer<QIODevice>(result_ptr)> fac =
|
||||
boost::bind( &TomahawkApp::httpIODeviceFactory, this, _1 );
|
||||
this->registerIODeviceFactory( "http", fac );
|
||||
@@ -449,6 +471,7 @@ TomahawkApp::setupJabber() //const QString& jid, const QString& pass, const QStr
|
||||
connect( m_jabber.data(), SIGNAL( connected() ), SLOT( jabberConnected() ) );
|
||||
connect( m_jabber.data(), SIGNAL( authError(int, const QString&) ), SLOT( jabberAuthError(int,const QString&) ) );
|
||||
|
||||
m_jabber->setProxy( m_proxy );
|
||||
m_jabber->start();
|
||||
}
|
||||
|
||||
@@ -663,7 +686,6 @@ TomahawkApp::httpIODeviceFactory( const Tomahawk::result_ptr& result )
|
||||
}
|
||||
|
||||
|
||||
|
||||
const QString&
|
||||
TomahawkApp::nodeID() const
|
||||
{
|
||||
|
@@ -21,8 +21,8 @@ TomahawkSettings::TomahawkSettings( QObject* parent )
|
||||
else if( value( "configversion" ).toUInt() != SettingsDialog::VERSION )
|
||||
{
|
||||
qDebug() << "Config version outdated, old:" << value( "configversion" ).toUInt()
|
||||
<< "new:" << SettingsDialog::VERSION
|
||||
<< "Doing upgrade, if any...";
|
||||
<< "new:" << SettingsDialog::VERSION
|
||||
<< "Doing upgrade, if any...";
|
||||
|
||||
// insert upgrade code here as required
|
||||
setValue( "configversion", SettingsDialog::VERSION );
|
||||
@@ -36,7 +36,8 @@ TomahawkSettings::~TomahawkSettings()
|
||||
}
|
||||
|
||||
|
||||
QString TomahawkSettings::scannerPath() const
|
||||
QString
|
||||
TomahawkSettings::scannerPath() const
|
||||
{
|
||||
#ifndef TOMAHAWK_HEADLESS
|
||||
return value( "scannerpath", QDesktopServices::storageLocation( QDesktopServices::MusicLocation ) ).toString();
|
||||
@@ -46,181 +47,337 @@ QString TomahawkSettings::scannerPath() const
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setScannerPath(const QString& path)
|
||||
void
|
||||
TomahawkSettings::setScannerPath( const QString& path )
|
||||
{
|
||||
setValue( "scannerpath", path );
|
||||
}
|
||||
|
||||
|
||||
bool TomahawkSettings::hasScannerPath() const
|
||||
bool
|
||||
TomahawkSettings::hasScannerPath() const
|
||||
{
|
||||
return contains( "scannerpath" );
|
||||
}
|
||||
|
||||
|
||||
bool TomahawkSettings::httpEnabled() const
|
||||
bool
|
||||
TomahawkSettings::httpEnabled() const
|
||||
{
|
||||
return value( "network/http", true ).toBool();
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setHttpEnabled(bool enable)
|
||||
void
|
||||
TomahawkSettings::setHttpEnabled( bool enable )
|
||||
{
|
||||
setValue( "network/http", enable );
|
||||
}
|
||||
|
||||
|
||||
QByteArray TomahawkSettings::mainWindowGeometry() const
|
||||
QString
|
||||
TomahawkSettings::proxyHost() const
|
||||
{
|
||||
return value( "network/proxy/host", QString() ).toString();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkSettings::setProxyHost( const QString& host )
|
||||
{
|
||||
setValue( "network/proxy/host", host );
|
||||
}
|
||||
|
||||
|
||||
qulonglong
|
||||
TomahawkSettings::proxyPort() const
|
||||
{
|
||||
return value( "network/proxy/port", 1080 ).toULongLong();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkSettings::setProxyPort( const qulonglong port )
|
||||
{
|
||||
setValue( "network/proxy/port", port );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
TomahawkSettings::proxyUsername() const
|
||||
{
|
||||
return value( "network/proxy/username", QString() ).toString();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkSettings::setProxyUsername( const QString& username )
|
||||
{
|
||||
setValue( "network/proxy/username", username );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
TomahawkSettings::proxyPassword() const
|
||||
{
|
||||
return value( "network/proxy/password", QString() ).toString();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkSettings::setProxyPassword( const QString& password )
|
||||
{
|
||||
setValue( "network/proxy/password", password );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
TomahawkSettings::proxyType() const
|
||||
{
|
||||
return value( "network/proxy/type", 0 ).toInt();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkSettings::setProxyType( const int type )
|
||||
{
|
||||
setValue( "network/proxy/type", type );
|
||||
}
|
||||
|
||||
|
||||
QByteArray
|
||||
TomahawkSettings::mainWindowGeometry() const
|
||||
{
|
||||
return value( "ui/mainwindow/geometry" ).toByteArray();
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setMainWindowGeometry(const QByteArray& geom)
|
||||
void
|
||||
TomahawkSettings::setMainWindowGeometry( const QByteArray& geom )
|
||||
{
|
||||
setValue( "ui/mainwindow/geometry", geom );
|
||||
}
|
||||
|
||||
|
||||
QByteArray TomahawkSettings::mainWindowState() const
|
||||
QByteArray
|
||||
TomahawkSettings::mainWindowState() const
|
||||
{
|
||||
return value( "ui/mainwindow/state" ).toByteArray();
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setMainWindowState(const QByteArray& state)
|
||||
void
|
||||
TomahawkSettings::setMainWindowState( const QByteArray& state )
|
||||
{
|
||||
setValue( "ui/mainwindow/state", state );
|
||||
}
|
||||
|
||||
|
||||
QList<QVariant> TomahawkSettings::playlistColumnSizes() const
|
||||
QList<QVariant>
|
||||
TomahawkSettings::playlistColumnSizes() const
|
||||
{
|
||||
return value( "ui/playlist/columnSize" ).toList();
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setPlaylistColumnSizes(const QList<QVariant>& cols)
|
||||
void
|
||||
TomahawkSettings::setPlaylistColumnSizes( const QList<QVariant>& cols )
|
||||
{
|
||||
setValue( "ui/playlist/geometry", cols );
|
||||
}
|
||||
|
||||
|
||||
bool TomahawkSettings::jabberAutoConnect() const
|
||||
bool
|
||||
TomahawkSettings::jabberAutoConnect() const
|
||||
{
|
||||
return value( "jabber/autoconnect", true ).toBool();
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setJabberAutoConnect(bool autoconnect)
|
||||
void
|
||||
TomahawkSettings::setJabberAutoConnect( bool autoconnect )
|
||||
{
|
||||
setValue( "jabber/autoconnect", autoconnect );
|
||||
}
|
||||
|
||||
|
||||
int TomahawkSettings::jabberPort() const
|
||||
int
|
||||
TomahawkSettings::jabberPort() const
|
||||
{
|
||||
return value( "jabber/port", 5222 ).toInt();
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setJabberPort(int port)
|
||||
void
|
||||
TomahawkSettings::setJabberPort( int port )
|
||||
{
|
||||
setValue( "jabber/port", port );
|
||||
}
|
||||
|
||||
|
||||
QString TomahawkSettings::jabberServer() const
|
||||
QString
|
||||
TomahawkSettings::jabberServer() const
|
||||
{
|
||||
return value( "jabber/server" ).toString();
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setJabberServer(const QString& server)
|
||||
void
|
||||
TomahawkSettings::setJabberServer( const QString& server )
|
||||
{
|
||||
setValue( "jabber/server", server );
|
||||
}
|
||||
|
||||
|
||||
QString TomahawkSettings::jabberUsername() const
|
||||
QString
|
||||
TomahawkSettings::jabberUsername() const
|
||||
{
|
||||
return value( "jabber/username" ).toString();
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setJabberUsername(const QString& username)
|
||||
void
|
||||
TomahawkSettings::setJabberUsername( const QString& username )
|
||||
{
|
||||
setValue( "jabber/username", username );
|
||||
}
|
||||
|
||||
|
||||
QString TomahawkSettings::jabberPassword() const
|
||||
QString
|
||||
TomahawkSettings::jabberPassword() const
|
||||
{
|
||||
return value( "jabber/password" ).toString();
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setJabberPassword(const QString& pw)
|
||||
void
|
||||
TomahawkSettings::setJabberPassword( const QString& pw )
|
||||
{
|
||||
setValue( "jabber/password", pw );
|
||||
}
|
||||
|
||||
|
||||
bool TomahawkSettings::upnpEnabled() const
|
||||
bool
|
||||
TomahawkSettings::upnpEnabled() const
|
||||
{
|
||||
return value( "network/upnp", true ).toBool();
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setUPnPEnabled(bool enable)
|
||||
void
|
||||
TomahawkSettings::setUPnPEnabled( bool enable )
|
||||
{
|
||||
setValue( "network/upnp", enable );
|
||||
}
|
||||
|
||||
|
||||
QString TomahawkSettings::lastFmPassword() const
|
||||
QString
|
||||
TomahawkSettings::lastFmPassword() const
|
||||
{
|
||||
return value( "lastfm/password" ).toString();
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setLastFmPassword(const QString& password)
|
||||
void
|
||||
TomahawkSettings::setLastFmPassword( const QString& password )
|
||||
{
|
||||
setValue( "lastfm/password", password );
|
||||
}
|
||||
|
||||
|
||||
QByteArray TomahawkSettings::lastFmSessionKey() const
|
||||
QByteArray
|
||||
TomahawkSettings::lastFmSessionKey() const
|
||||
{
|
||||
return value( "lastfm/sessionkey" ).toByteArray();
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setLastFmSessionKey(const QByteArray& key)
|
||||
void
|
||||
TomahawkSettings::setLastFmSessionKey( const QByteArray& key )
|
||||
{
|
||||
setValue( "lastfm/sessionkey", key );
|
||||
}
|
||||
|
||||
|
||||
QString TomahawkSettings::lastFmUsername() const
|
||||
QString
|
||||
TomahawkSettings::lastFmUsername() const
|
||||
{
|
||||
return value( "lastfm/username" ).toString();
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setLastFmUsername(const QString& username )
|
||||
void
|
||||
TomahawkSettings::setLastFmUsername( const QString& username )
|
||||
{
|
||||
setValue( "lastfm/username", username );
|
||||
}
|
||||
|
||||
|
||||
bool TomahawkSettings::scrobblingEnabled() const
|
||||
bool
|
||||
TomahawkSettings::scrobblingEnabled() const
|
||||
{
|
||||
return value( "lastfm/enablescrobbling", false ).toBool();
|
||||
}
|
||||
|
||||
|
||||
void TomahawkSettings::setScrobblingEnabled(bool enable)
|
||||
void
|
||||
TomahawkSettings::setScrobblingEnabled( bool enable )
|
||||
{
|
||||
setValue( "lastfm/enablescrobbling", enable );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
TomahawkSettings::xmppBotServer() const
|
||||
{
|
||||
return value( "xmppBot/server", QString() ).toString();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkSettings::setXmppBotServer( const QString& server )
|
||||
{
|
||||
setValue( "xmppBot/server", server );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
TomahawkSettings::xmppBotJid() const
|
||||
{
|
||||
return value( "xmppBot/jid", QString() ).toString();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkSettings::setXmppBotJid( const QString& component )
|
||||
{
|
||||
setValue( "xmppBot/jid", component );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
TomahawkSettings::xmppBotPassword() const
|
||||
{
|
||||
return value( "xmppBot/password", QString() ).toString();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkSettings::setXmppBotPassword( const QString& password )
|
||||
{
|
||||
setValue( "xmppBot/password", password );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
TomahawkSettings::xmppBotPort() const
|
||||
{
|
||||
return value( "xmppBot/port", -1 ).toInt();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkSettings::setXmppBotPort( const int port )
|
||||
{
|
||||
setValue( "xmppBot/port", -1 );
|
||||
}
|
||||
|
@@ -50,7 +50,22 @@ public:
|
||||
|
||||
bool upnpEnabled() const; /// true by default
|
||||
void setUPnPEnabled( bool enable );
|
||||
|
||||
|
||||
QString proxyHost() const;
|
||||
void setProxyHost( const QString &host );
|
||||
|
||||
qulonglong proxyPort() const;
|
||||
void setProxyPort( const qulonglong port );
|
||||
|
||||
QString proxyUsername() const;
|
||||
void setProxyUsername( const QString &username );
|
||||
|
||||
QString proxyPassword() const;
|
||||
void setProxyPassword( const QString &password );
|
||||
|
||||
int proxyType() const;
|
||||
void setProxyType( const int type );
|
||||
|
||||
/// Last.fm settings
|
||||
bool scrobblingEnabled() const; /// false by default
|
||||
void setScrobblingEnabled( bool enable );
|
||||
@@ -63,6 +78,19 @@ public:
|
||||
|
||||
QByteArray lastFmSessionKey() const;
|
||||
void setLastFmSessionKey( const QByteArray& key );
|
||||
|
||||
/// XMPP Component Settings
|
||||
QString xmppBotServer() const;
|
||||
void setXmppBotServer( const QString &server );
|
||||
|
||||
QString xmppBotJid() const;
|
||||
void setXmppBotJid( const QString &component );
|
||||
|
||||
QString xmppBotPassword() const;
|
||||
void setXmppBotPassword( const QString &password );
|
||||
|
||||
int xmppBotPort() const;
|
||||
void setXmppBotPort( const int port );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -49,8 +49,6 @@ TomahawkWindow::TomahawkWindow( QWidget* parent )
|
||||
#endif
|
||||
|
||||
ui->setupUi( this );
|
||||
// ui->playlistView->connectProgressBar( ui->actionProgress );
|
||||
// ui->playlistView->setFocus();
|
||||
|
||||
#ifndef Q_WS_MAC
|
||||
ui->centralWidget->layout()->setContentsMargins( 4, 4, 4, 2 );
|
||||
@@ -60,7 +58,10 @@ TomahawkWindow::TomahawkWindow( QWidget* parent )
|
||||
ui->sourceTreeView->setAttribute( Qt::WA_MacShowFocusRect, 0 );
|
||||
#endif
|
||||
|
||||
ui->mainLayout->addWidget( m_playlistManager->widget() );
|
||||
delete ui->playlistWidget;
|
||||
ui->splitter->addWidget( m_playlistManager->widget() );
|
||||
ui->splitter->setStretchFactor( 0, 1 );
|
||||
ui->splitter->setStretchFactor( 1, 3 );
|
||||
|
||||
QToolBar* toolbar = addToolBar( "TomahawkToolbar" );
|
||||
toolbar->setObjectName( "TomahawkToolbar" );
|
||||
|
@@ -11,42 +11,25 @@
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>EchoChamber</string>
|
||||
<string>Tomahawk</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="SourceTreeView" name="sourceTreeView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="mainLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="SourceTreeView" name="sourceTreeView">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="playlistWidget" native="true"/>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
396
src/xmppbot/xmppbot.cpp
Normal file
396
src/xmppbot/xmppbot.cpp
Normal file
@@ -0,0 +1,396 @@
|
||||
#include "xmppbot.h"
|
||||
|
||||
#include "tomahawk/tomahawkapp.h"
|
||||
#include "tomahawk/infosystem.h"
|
||||
#include <tomahawksettings.h>
|
||||
#include <audio/audioengine.h>
|
||||
|
||||
#include <gloox/client.h>
|
||||
#include <gloox/rostermanager.h>
|
||||
#include <gloox/message.h>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
using namespace gloox;
|
||||
using namespace Tomahawk::InfoSystem;
|
||||
|
||||
static QString s_infoIdentifier = QString("XMPPBot");
|
||||
|
||||
XMPPBot::XMPPBot(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_currReturnMessage("\n")
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
TomahawkSettings *settings = TomahawkApp::instance()->settings();
|
||||
QString server = settings->xmppBotServer();
|
||||
QString jidstring = settings->xmppBotJid();
|
||||
QString password = settings->xmppBotPassword();
|
||||
int port = settings->xmppBotPort();
|
||||
if (jidstring.isEmpty() || password.isEmpty())
|
||||
return;
|
||||
|
||||
JID jid(jidstring.toStdString());
|
||||
|
||||
m_client = new XMPPBotClient(this, jid, password.toStdString(), port);
|
||||
if (!server.isEmpty())
|
||||
m_client.data()->setServer(server.toStdString());
|
||||
|
||||
m_client.data()->registerConnectionListener(this);
|
||||
m_client.data()->registerSubscriptionHandler(this);
|
||||
m_client.data()->registerMessageHandler(this);
|
||||
|
||||
connect(TomahawkApp::instance()->audioEngine(), SIGNAL(started(const Tomahawk::result_ptr &)),
|
||||
SLOT(newTrackSlot(const Tomahawk::result_ptr &)));
|
||||
|
||||
connect(TomahawkApp::instance()->infoSystem(),
|
||||
SIGNAL(info(QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomDataHash)),
|
||||
SLOT(infoReturnedSlot(QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomDataHash)));
|
||||
|
||||
connect(TomahawkApp::instance()->infoSystem(), SIGNAL(finished(QString)), SLOT(infoFinishedSlot(QString)));
|
||||
|
||||
bool success = m_client.data()->gloox::Client::connect(false);
|
||||
if (success)
|
||||
m_client.data()->run();
|
||||
else
|
||||
qDebug() << "XMPPBot failed to connect with Client";
|
||||
}
|
||||
|
||||
XMPPBot::~XMPPBot()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if (!m_client.isNull())
|
||||
m_client.data()->gloox::Client::disconnect();
|
||||
}
|
||||
|
||||
void XMPPBot::newTrackSlot(const Tomahawk::result_ptr &track)
|
||||
{
|
||||
m_currTrack = track;
|
||||
if (!track)
|
||||
return;
|
||||
QString status = QString("%1 - %2 (%3)")
|
||||
.arg(track->artist())
|
||||
.arg(track->track())
|
||||
.arg(track->album());
|
||||
m_client.data()->setPresence(Presence::Chat, 1, status.toStdString());
|
||||
}
|
||||
|
||||
void XMPPBot::onConnect()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
qDebug() << "XMPPBot Connected";
|
||||
}
|
||||
|
||||
void XMPPBot::onDisconnect(ConnectionError e)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
qDebug() << "XMPPBot Disconnected";
|
||||
if (e != gloox::ConnNoError && e != gloox::ConnUserDisconnected)
|
||||
qDebug() << "ERROR: in XMPPBot, disconnected";
|
||||
}
|
||||
|
||||
bool XMPPBot::onTLSConnect(const gloox::CertInfo& info)
|
||||
{
|
||||
//WARNING: Blindly accepts all certificates, at the moment
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
return true;
|
||||
}
|
||||
|
||||
void XMPPBot::handleSubscription(const gloox::Subscription& subscription)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if (subscription.subtype() == Subscription::Subscribed)
|
||||
{
|
||||
qDebug() << "XMPPBot is now subscribed to " << subscription.from().bare().c_str();
|
||||
return;
|
||||
}
|
||||
else if(subscription.subtype() == Subscription::Unsubscribed)
|
||||
{
|
||||
qDebug() << "XMPPBot is now unsubscribed from " << subscription.from().bare().c_str();
|
||||
return;
|
||||
}
|
||||
else if(subscription.subtype() == Subscription::Subscribe)
|
||||
{
|
||||
m_client.data()->rosterManager()->ackSubscriptionRequest(subscription.from().bareJID(), true);
|
||||
m_client.data()->rosterManager()->subscribe(subscription.from().bareJID(), EmptyString, StringList(), "Let me in?");
|
||||
}
|
||||
else if(subscription.subtype() == Subscription::Unsubscribe)
|
||||
{
|
||||
m_client.data()->rosterManager()->ackSubscriptionRequest(subscription.from().bareJID(), true);
|
||||
m_client.data()->rosterManager()->unsubscribe(subscription.from().bareJID(), "Sorry to see you go.");
|
||||
}
|
||||
}
|
||||
|
||||
void XMPPBot::handleMessage(const Message& msg, MessageSession* session)
|
||||
{
|
||||
//TODO: implement "properly" with MessageSessions, if the bot is to be multi-user
|
||||
if (msg.subtype() != Message::Chat || msg.from().full().empty() || msg.to().full().empty())
|
||||
return;
|
||||
|
||||
qDebug() << "jid from: " << QString::fromStdString(msg.from().full()) << ", jid to: " << QString::fromStdString(msg.to().full());
|
||||
|
||||
QString body = QString::fromStdString(msg.body());
|
||||
QString originatingJid = QString::fromStdString(msg.from().full());
|
||||
QStringList tokens(body.split(QString(" and "), QString::SkipEmptyParts));
|
||||
|
||||
qDebug() << "Operating on tokens: " << tokens;
|
||||
|
||||
if (m_currTrack.isNull() || m_currTrack->artist().isEmpty() || m_currTrack->track().isEmpty())
|
||||
{
|
||||
qDebug() << "XMPPBot can't figure out track";
|
||||
QString m_currReturnMessage("\n\nSorry, I can't figure out what track is playing.\n\n");
|
||||
Message retMsg(Message::Chat, JID(originatingJid.toStdString()), m_currReturnMessage.toStdString());
|
||||
m_client.data()->send(retMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
InfoMap infoMap;
|
||||
Q_FOREACH(QString token, tokens)
|
||||
{
|
||||
if (token == "biography")
|
||||
infoMap[InfoArtistBiography] = m_currTrack.data()->artist();
|
||||
if (token == "terms")
|
||||
infoMap[InfoArtistTerms] = m_currTrack.data()->artist();
|
||||
if (token == "hotttness")
|
||||
infoMap[InfoArtistHotttness] = m_currTrack.data()->artist();
|
||||
if (token == "familiarity")
|
||||
infoMap[InfoArtistFamiliarity] = m_currTrack.data()->artist();
|
||||
if (token == "lyrics")
|
||||
{
|
||||
MusixMatchHash myhash;
|
||||
myhash["trackName"] = m_currTrack.data()->track();
|
||||
myhash["artistName"] = m_currTrack.data()->artist();
|
||||
infoMap[InfoTrackLyrics] = QVariant::fromValue<Tomahawk::InfoSystem::MusixMatchHash>(myhash);
|
||||
}
|
||||
}
|
||||
|
||||
if (infoMap.isEmpty())
|
||||
{
|
||||
qDebug() << "XMPPBot can't figure out track";
|
||||
QString m_currReturnMessage("\n\nSorry, I couldn't recognize any commands.\n\n");
|
||||
Message retMsg(Message::Chat, JID(originatingJid.toStdString()), m_currReturnMessage.toStdString());
|
||||
m_client.data()->send(retMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
m_currInfoMap.unite(infoMap);
|
||||
QString waitMsg("Please wait...");
|
||||
Message retMsg(Message::Chat, JID(originatingJid.toStdString()), waitMsg.toStdString());
|
||||
m_client.data()->send(retMsg);
|
||||
Tomahawk::InfoSystem::InfoCustomDataHash hash;
|
||||
hash["XMPPBotSendToJID"] = originatingJid;
|
||||
TomahawkApp::instance()->infoSystem()->getInfo(s_infoIdentifier, infoMap, hash);
|
||||
}
|
||||
|
||||
void XMPPBot::infoReturnedSlot(QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomDataHash customData)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if (caller != s_infoIdentifier ||
|
||||
input.isNull() || !input.isValid() ||
|
||||
!customData.contains("XMPPBotSendToJID")
|
||||
)
|
||||
{
|
||||
qDebug() << "Not the right object, custom data is null, or don't have a set JID";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_currInfoMap.contains(type))
|
||||
{
|
||||
qDebug() << "not in currInfoMap";
|
||||
return;
|
||||
}
|
||||
else
|
||||
m_currInfoMap.remove(type);
|
||||
|
||||
QString jid = customData["XMPPBotSendToJID"].toString();
|
||||
if (!m_currReturnJid.isEmpty() && m_currReturnJid != jid && !m_currReturnMessage.isEmpty())
|
||||
{
|
||||
gloox::Message msg(Message::Chat, JID(jid.toStdString()), m_currReturnMessage.toStdString());
|
||||
m_client.data()->send(msg);
|
||||
m_currReturnMessage = QString("\n");
|
||||
}
|
||||
m_currReturnJid = jid;
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case InfoArtistBiography:
|
||||
{
|
||||
qDebug() << "Artist bio requested";
|
||||
if (!output.canConvert<Tomahawk::InfoSystem::InfoGenericMap>() ||
|
||||
!input.canConvert<QString>()
|
||||
)
|
||||
{
|
||||
qDebug() << "Variants failed to be valid";
|
||||
break;
|
||||
}
|
||||
InfoGenericMap bmap = output.value<Tomahawk::InfoSystem::InfoGenericMap>();
|
||||
QString artist = input.toString();
|
||||
m_currReturnMessage += QString("\nBiographies for %1\n").arg(artist);
|
||||
Q_FOREACH(QString source, bmap.keys())
|
||||
{
|
||||
m_currReturnMessage += (bmap[source]["attribution"].isEmpty() ?
|
||||
QString("From %1:\n").arg(bmap[source]["site"]) :
|
||||
QString("From %1 at %2:\n").arg(bmap[source]["attribution"]).arg(bmap[source]["site"]));
|
||||
m_currReturnMessage += bmap[source]["text"] + QString("\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case InfoArtistTerms:
|
||||
{
|
||||
qDebug() << "Artist terms requested";
|
||||
if (!output.canConvert<Tomahawk::InfoSystem::InfoGenericMap>() ||
|
||||
!input.canConvert<QString>()
|
||||
)
|
||||
{
|
||||
qDebug() << "Variants failed to be valid";
|
||||
break;
|
||||
}
|
||||
InfoGenericMap tmap = output.value<Tomahawk::InfoSystem::InfoGenericMap>();
|
||||
QString artist = input.toString();
|
||||
m_currReturnMessage += QString("\nTerms for %1:\n").arg(artist);
|
||||
if (tmap.isEmpty())
|
||||
m_currReturnMessage += QString("No terms found, sorry.");
|
||||
else
|
||||
{
|
||||
bool first = true;
|
||||
Q_FOREACH(QString term, tmap.keys())
|
||||
{
|
||||
if (first)
|
||||
m_currReturnMessage += (first ?
|
||||
QString("%1 (weight %2, frequency %3)")
|
||||
.arg(term).arg(tmap[term]["weight"]).arg(tmap[term]["frequency"])
|
||||
:
|
||||
QString("\n%1 (weight %2, frequency %3)")
|
||||
.arg(term).arg(tmap[term]["weight"]).arg(tmap[term]["frequency"])
|
||||
);
|
||||
first = false;
|
||||
}
|
||||
m_currReturnMessage += QString("\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case InfoArtistHotttness:
|
||||
{
|
||||
qDebug() << "Artist hotttness requested";
|
||||
if (!output.canConvert<qreal>() ||
|
||||
!input.canConvert<QString>()
|
||||
)
|
||||
{
|
||||
qDebug() << "Variants failed to be valid";
|
||||
break;
|
||||
}
|
||||
QString artist = input.toString();
|
||||
qreal retVal = output.toReal();
|
||||
QString retValString = (retVal == 0.0 ? "(none)" : QString::number(retVal));
|
||||
m_currReturnMessage += QString("\nHotttness for %1: %2\n").arg(artist).arg(retValString);
|
||||
break;
|
||||
}
|
||||
case InfoArtistFamiliarity:
|
||||
{
|
||||
qDebug() << "Artist familiarity requested";
|
||||
if (!output.canConvert<qreal>() ||
|
||||
!input.canConvert<QString>()
|
||||
)
|
||||
{
|
||||
qDebug() << "Variants failed to be valid";
|
||||
break;
|
||||
}
|
||||
QString artist = input.toString();
|
||||
qreal retVal = output.toReal();
|
||||
QString retValString = (retVal == 0.0 ? "(none)" : QString::number(retVal));
|
||||
m_currReturnMessage += QString("\nFamiliartiy for %1: %2\n").arg(artist).arg(retValString);
|
||||
break;
|
||||
}
|
||||
case InfoTrackLyrics:
|
||||
{
|
||||
qDebug() << "Lyrics requested";
|
||||
if (!output.canConvert<QString>() ||
|
||||
!input.canConvert<Tomahawk::InfoSystem::MusixMatchHash>()
|
||||
)
|
||||
{
|
||||
qDebug() << "Variants failed to be valid";
|
||||
break;
|
||||
}
|
||||
MusixMatchHash inHash = input.value<MusixMatchHash>();
|
||||
QString artist = inHash["artistName"];
|
||||
QString track = inHash["trackName"];
|
||||
QString lyrics = output.toString();
|
||||
qDebug() << "lyrics = " << lyrics;
|
||||
m_currReturnMessage += QString("\nLyrics for \"%1\" by %2:\n\n%3\n").arg(track).arg(artist).arg(lyrics);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_currReturnMessage.isEmpty())
|
||||
{
|
||||
qDebug() << "Empty message, not sending anything back";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Going to send message: " << m_currReturnMessage << " to " << jid;
|
||||
|
||||
//gloox::Message msg(Message::Chat, JID(jid.toStdString()), m_currReturnMessage.toStdString());
|
||||
//m_client.data()->send(msg);
|
||||
}
|
||||
|
||||
void XMPPBot::infoFinishedSlot(QString caller)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
qDebug() << "current return message is" << m_currReturnMessage;
|
||||
qDebug() << "id is" << caller << "and our id is" << s_infoIdentifier;
|
||||
if (m_currReturnMessage.isEmpty() || caller != s_infoIdentifier)
|
||||
return;
|
||||
|
||||
qDebug() << "Sending message to JID" << m_currReturnJid;
|
||||
gloox::Message msg(Message::Chat, JID(m_currReturnJid.toStdString()), m_currReturnMessage.toStdString());
|
||||
m_client.data()->send(msg);
|
||||
m_currReturnMessage = QString("\n");
|
||||
m_currReturnJid.clear();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
XMPPBotClient::XMPPBotClient(QObject *parent, JID &jid, std::string password, int port)
|
||||
: QObject(parent)
|
||||
, Client(jid, password, port)
|
||||
, m_timer(this)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
setResource(QString( "tomahawkbot%1" ).arg( qrand() ).toStdString() );
|
||||
|
||||
// the google hack, because they filter disco features they don't know.
|
||||
if( server().find( "googlemail." ) != std::string::npos
|
||||
|| server().find( "gmail." ) != std::string::npos
|
||||
|| server().find( "gtalk." ) != std::string::npos )
|
||||
{
|
||||
if( resource().find( "tomahawkbot" ) == std::string::npos )
|
||||
{
|
||||
qDebug() << "Forcing your /resource to contain 'tomahawk' (the google workaround)";
|
||||
setResource( "tomahawkbot-tomahawkbot" );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
XMPPBotClient::~XMPPBotClient()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
void XMPPBotClient::run()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
setPresence(Presence::Chat, 1, "Hi!");
|
||||
QObject::connect(&m_timer, SIGNAL(timeout()), SLOT(recvSlot()));
|
||||
m_timer.start(200);
|
||||
qDebug() << "XMPPBot running";
|
||||
}
|
||||
|
||||
void XMPPBotClient::recvSlot()
|
||||
{
|
||||
gloox::ConnectionError error = recv(100);
|
||||
if (error != gloox::ConnNoError)
|
||||
qDebug() << "ERROR: in XMPPBotClient::recvSlot";
|
||||
}
|
||||
|
74
src/xmppbot/xmppbot.h
Normal file
74
src/xmppbot/xmppbot.h
Normal file
@@ -0,0 +1,74 @@
|
||||
#ifndef XMPPBOT_H
|
||||
#define XMPPBOT_H
|
||||
|
||||
#include <tomahawk/result.h>
|
||||
#include <tomahawk/infosystem.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/qsharedpointer.h>
|
||||
#include <QTimer>
|
||||
|
||||
#include <gloox/messagehandler.h>
|
||||
#include <gloox/messagesessionhandler.h>
|
||||
#include <gloox/client.h>
|
||||
#include <gloox/connectionlistener.h>
|
||||
#include <gloox/subscriptionhandler.h>
|
||||
#include <gloox/messagehandler.h>
|
||||
|
||||
class XMPPBotClient
|
||||
: public QObject
|
||||
, public gloox::Client
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
XMPPBotClient(QObject* parent, gloox::JID &jid, std::string password, int port);
|
||||
virtual ~XMPPBotClient();
|
||||
|
||||
void run();
|
||||
|
||||
private slots:
|
||||
void recvSlot();
|
||||
|
||||
private:
|
||||
QTimer m_timer;
|
||||
};
|
||||
|
||||
class XMPPBot
|
||||
: public QObject
|
||||
, public gloox::ConnectionListener
|
||||
, public gloox::SubscriptionHandler
|
||||
, public gloox::MessageHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
XMPPBot(QObject *parent);
|
||||
virtual ~XMPPBot();
|
||||
|
||||
public slots:
|
||||
virtual void newTrackSlot(const Tomahawk::result_ptr &track);
|
||||
virtual void infoReturnedSlot(QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomDataHash customData);
|
||||
virtual void infoFinishedSlot(QString caller);
|
||||
|
||||
protected:
|
||||
// ConnectionListener
|
||||
virtual void onConnect();
|
||||
virtual void onDisconnect(gloox::ConnectionError e);
|
||||
virtual bool onTLSConnect(const gloox::CertInfo &info);
|
||||
|
||||
// SubscriptionHandler
|
||||
virtual void handleSubscription(const gloox::Subscription &subscription);
|
||||
|
||||
// MessageHandler
|
||||
virtual void handleMessage(const gloox::Message &msg, gloox::MessageSession *session = 0);
|
||||
|
||||
private:
|
||||
QWeakPointer<XMPPBotClient> m_client;
|
||||
Tomahawk::result_ptr m_currTrack;
|
||||
Tomahawk::InfoSystem::InfoMap m_currInfoMap;
|
||||
QString m_currReturnMessage;
|
||||
QString m_currReturnJid;
|
||||
};
|
||||
|
||||
#endif // XMPPBOT_H
|
Reference in New Issue
Block a user