1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-06 14:16:32 +02:00

Add completion for artists with echonest artist/suggest path

This commit is contained in:
Leo Franchi
2011-05-23 23:11:10 -04:00
parent 9b4c826e10
commit 597e459db1
2 changed files with 102 additions and 17 deletions

View File

@@ -26,6 +26,8 @@
#include <QLineEdit> #include <QLineEdit>
#include <QLabel> #include <QLabel>
#include "EchonestGenerator.h" #include "EchonestGenerator.h"
#include <qcompleter.h>
#include <qstringlistmodel.h>
Tomahawk::EchonestControl::EchonestControl( const QString& selectedType, const QStringList& typeSelectors, QObject* parent ) Tomahawk::EchonestControl::EchonestControl( const QString& selectedType, const QStringList& typeSelectors, QObject* parent )
@@ -146,6 +148,8 @@ Tomahawk::EchonestControl::updateWidgets()
input->setPlaceholderText( "Artist name" ); input->setPlaceholderText( "Artist name" );
input->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed ); input->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Fixed );
input->setCompleter( new QCompleter( QStringList(), input ) );
input->completer()->setCaseSensitivity( Qt::CaseInsensitive );
connect( match, SIGNAL( currentIndexChanged(int) ), this, SLOT( updateData() ) ); connect( match, SIGNAL( currentIndexChanged(int) ), this, SLOT( updateData() ) );
connect( match, SIGNAL( currentIndexChanged(int) ), this, SIGNAL( changed() ) ); connect( match, SIGNAL( currentIndexChanged(int) ), this, SIGNAL( changed() ) );
@@ -153,6 +157,7 @@ Tomahawk::EchonestControl::updateWidgets()
connect( input, SIGNAL( editingFinished() ), this, SLOT( editingFinished() ) ); connect( input, SIGNAL( editingFinished() ), this, SLOT( editingFinished() ) );
connect( input, SIGNAL( textEdited( QString ) ), &m_editingTimer, SLOT( stop() ) ); connect( input, SIGNAL( textEdited( QString ) ), &m_editingTimer, SLOT( stop() ) );
connect( input, SIGNAL( textEdited( QString ) ), &m_delayedEditTimer, SLOT( start() ) ); connect( input, SIGNAL( textEdited( QString ) ), &m_delayedEditTimer, SLOT( start() ) );
connect( input, SIGNAL( textEdited( QString ) ), this, SLOT( artistTextEdited( QString ) ) );
match->hide(); match->hide();
input->hide(); input->hide();
@@ -552,6 +557,78 @@ Tomahawk::EchonestControl::editTimerFired()
m_cacheData = m_data.second; m_cacheData = m_data.second;
} }
void
Tomahawk::EchonestControl::artistTextEdited( const QString& text )
{
// if the user is editing an artist field, try to help him out and suggest from echonest
QLineEdit* l = qobject_cast<QLineEdit*>( m_input.data() );
Q_ASSERT( l );
// l->setCompleter( new QCompleter( this ) ); // clear
foreach( QNetworkReply* r, m_suggestWorkers ) {
r->abort();
r->deleteLater();
}
m_suggestWorkers.clear();
if( !text.isEmpty() ) {
if( m_suggestCache.contains( text ) ) {
addArtistSuggestions( m_suggestCache[ text ] );
} else { // gotta look it up
QNetworkReply* r = Echonest::Artist::suggest( text );
qDebug() << "Asking echonest for suggestions to help our completion..." << r->url().toString();
r->setProperty( "curtext", text );
m_suggestWorkers.insert( r );
connect( r, SIGNAL( finished() ), this, SLOT( suggestFinished() ) );
}
}
}
void
Tomahawk::EchonestControl::suggestFinished()
{
qDebug() << Q_FUNC_INFO;
QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() );
Q_ASSERT( r );
QLineEdit* l = qobject_cast<QLineEdit*>( m_input.data() );
Q_ASSERT( l );
m_suggestWorkers.remove( r );
if( r->error() != QNetworkReply::NoError )
return;
QString origText = r->property( "curtext" ).toString();
if( origText != l->text() ) { // user might have kept on typing, then ignore
qDebug() << "Text changed meanwhile, stopping suggestion parsing";
return;
}
QStringList suggestions;
try {
Echonest::Artists artists = Echonest::Artist::parseSuggest( r );
foreach( const Echonest::Artist& artist, artists )
suggestions << artist.name();
} catch( Echonest::ParseError& e ) {
qWarning() << "libechonest failed to parse this artist/suggest call..." << e.errorType() << e.what();
return;
}
m_suggestCache[ origText ] = suggestions;
addArtistSuggestions( suggestions );
}
void
Tomahawk::EchonestControl::addArtistSuggestions( const QStringList& suggestions )
{
// if the user is editing an artist field, try to help him out and suggest from echonest
QLineEdit* l = qobject_cast<QLineEdit*>( m_input.data() );
Q_ASSERT( l );
l->completer()->setModel( new QStringListModel( suggestions, l->completer() ) );
l->completer()->complete();
}
void void
Tomahawk::EchonestControl::calculateSummary() Tomahawk::EchonestControl::calculateSummary()

View File

@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> === /* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
* *
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org> * Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* *
* Tomahawk is free software: you can redistribute it and/or modify * Tomahawk is free software: you can redistribute it and/or modify
@@ -26,65 +26,73 @@
namespace Tomahawk namespace Tomahawk
{ {
class EchonestControl : public DynamicControl class EchonestControl : public DynamicControl
{ {
Q_OBJECT Q_OBJECT
public: public:
virtual QWidget* inputField(); virtual QWidget* inputField();
virtual QWidget* matchSelector(); virtual QWidget* matchSelector();
/// Converts this to an echonest suitable parameter /// Converts this to an echonest suitable parameter
Echonest::DynamicPlaylist::PlaylistParamData toENParam() const; Echonest::DynamicPlaylist::PlaylistParamData toENParam() const;
virtual QString input() const; virtual QString input() const;
virtual QString match() const; virtual QString match() const;
virtual QString matchString() const; virtual QString matchString() const;
virtual QString summary() const; virtual QString summary() const;
virtual void setInput(const QString& input); virtual void setInput(const QString& input);
virtual void setMatch(const QString& match); virtual void setMatch(const QString& match);
/// DO NOT USE IF YOU ARE NOT A DBCMD /// DO NOT USE IF YOU ARE NOT A DBCMD
EchonestControl( const QString& type, const QStringList& typeSelectors, QObject* parent = 0 ); EchonestControl( const QString& type, const QStringList& typeSelectors, QObject* parent = 0 );
public slots: public slots:
virtual void setSelectedType ( const QString& type ); virtual void setSelectedType ( const QString& type );
private slots: private slots:
void updateData(); void updateData();
void editingFinished(); void editingFinished();
void editTimerFired(); void editTimerFired();
void artistTextEdited( const QString& );
void suggestFinished();
private: private:
void updateWidgets(); void updateWidgets();
void updateWidgetsFromData(); void updateWidgetsFromData();
// utility // utility
void setupMinMaxWidgets( Echonest::DynamicPlaylist::PlaylistParam min, Echonest::DynamicPlaylist::PlaylistParam max, const QString& leftL, const QString& rightL, int maxRange ); void setupMinMaxWidgets( Echonest::DynamicPlaylist::PlaylistParam min, Echonest::DynamicPlaylist::PlaylistParam max, const QString& leftL, const QString& rightL, int maxRange );
void updateFromComboAndSlider( bool smooth = false ); void updateFromComboAndSlider( bool smooth = false );
void updateFromLabelAndCombo(); void updateFromLabelAndCombo();
void updateToComboAndSlider( bool smooth = false ); void updateToComboAndSlider( bool smooth = false );
void updateToLabelAndCombo(); void updateToLabelAndCombo();
void addArtistSuggestions( const QStringList& suggestions );
void calculateSummary(); void calculateSummary();
Echonest::DynamicPlaylist::PlaylistParam m_currentType; Echonest::DynamicPlaylist::PlaylistParam m_currentType;
int m_overrideType; int m_overrideType;
QWeakPointer< QWidget > m_input; QWeakPointer< QWidget > m_input;
QWeakPointer< QWidget > m_match; QWeakPointer< QWidget > m_match;
QString m_matchData; QString m_matchData;
QString m_matchString; QString m_matchString;
QString m_summary; QString m_summary;
QTimer m_editingTimer; QTimer m_editingTimer;
QTimer m_delayedEditTimer; QTimer m_delayedEditTimer;
Echonest::DynamicPlaylist::PlaylistParamData m_data; Echonest::DynamicPlaylist::PlaylistParamData m_data;
QVariant m_cacheData; QVariant m_cacheData;
QSet< QNetworkReply* > m_suggestWorkers;
QHash< QString, QStringList > m_suggestCache;
friend class EchonestGenerator; friend class EchonestGenerator;
}; };