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

Refactor the resolver config UI for More Prettiness

Allow resolvers to configure themselves and whatnot
This commit is contained in:
Leo Franchi
2011-04-12 06:56:19 -04:00
parent 4b13467e4c
commit 714c306032
25 changed files with 835 additions and 143 deletions

BIN
data/images/configure.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 B

View File

@@ -90,8 +90,9 @@ public:
TomahawkWindow* mainWindow() const { return m_mainwindow; } TomahawkWindow* mainWindow() const { return m_mainwindow; }
#endif #endif
void addScriptResolver( const QString& scriptPath ); void enableScriptResolver( const QString& scriptPath );
void removeScriptResolver( const QString& scriptPath ); void disableScriptResolver( const QString& scriptPath );
Tomahawk::ExternalResolver* resolverForPath( const QString& scriptPath );
// PlatformInterface // PlatformInterface
virtual void activate(); virtual void activate();
@@ -116,7 +117,7 @@ private:
void startHTTP(); void startHTTP();
QList<Tomahawk::collection_ptr> m_collections; QList<Tomahawk::collection_ptr> m_collections;
QList<Tomahawk::ExternalResolver*> m_scriptResolvers; QHash<QString, Tomahawk::ExternalResolver*> m_scriptResolvers;
Database* m_database; Database* m_database;
ScanManager *m_scanManager; ScanManager *m_scanManager;
@@ -143,3 +144,4 @@ private:
}; };
#endif // TOMAHAWKAPP_H #endif // TOMAHAWKAPP_H

View File

@@ -74,6 +74,7 @@
<file>./data/images/back.png</file> <file>./data/images/back.png</file>
<file>./data/images/forward.png</file> <file>./data/images/forward.png</file>
<file>./data/images/music-icon.png</file> <file>./data/images/music-icon.png</file>
<file>./data/images/configure.png</file>
<file>./data/topbar-radiobuttons.css</file> <file>./data/topbar-radiobuttons.css</file>
<file>./data/icons/tomahawk-icon-16x16.png</file> <file>./data/icons/tomahawk-icon-16x16.png</file>
<file>./data/icons/tomahawk-icon-32x32.png</file> <file>./data/icons/tomahawk-icon-32x32.png</file>

View File

@@ -63,6 +63,8 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui}
tomahawktrayicon.cpp tomahawktrayicon.cpp
audiocontrols.cpp audiocontrols.cpp
settingsdialog.cpp settingsdialog.cpp
resolverconfigdelegate.cpp
resolversmodel.cpp
tomahawkwindow.cpp tomahawkwindow.cpp
) )
@@ -99,6 +101,9 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui}
tomahawktrayicon.h tomahawktrayicon.h
audiocontrols.h audiocontrols.h
settingsdialog.h settingsdialog.h
resolverconfigdelegate.h
resolversmodel.h
resolverconfigwrapper.h
tomahawkwindow.h tomahawkwindow.h
) )

View File

@@ -4,6 +4,7 @@ SET( QT_USE_QTGUI TRUE )
SET( QT_USE_QTSQL TRUE ) SET( QT_USE_QTSQL TRUE )
SET( QT_USE_QTNETWORK TRUE ) SET( QT_USE_QTNETWORK TRUE )
SET( QT_USE_QTXML TRUE ) SET( QT_USE_QTXML TRUE )
SET(QT_USE_QTUITOOLS TRUE)
include( ${QT_USE_FILE} ) include( ${QT_USE_FILE} )
@@ -21,6 +22,7 @@ set( libSources
album.cpp album.cpp
collection.cpp collection.cpp
playlist.cpp playlist.cpp
resolver.cpp
query.cpp query.cpp
result.cpp result.cpp
source.cpp source.cpp

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
@@ -22,6 +22,7 @@
#include <QObject> #include <QObject>
#include <QTimer> #include <QTimer>
#include <QDebug> #include <QDebug>
#include <QWeakPointer>
#include "boost/function.hpp" #include "boost/function.hpp"
#include "boost/bind.hpp" #include "boost/bind.hpp"
@@ -43,8 +44,9 @@ class DLLEXPORT FuncTimeout : public QObject
Q_OBJECT Q_OBJECT
public: public:
FuncTimeout( int ms, boost::function<void()> func ) FuncTimeout( int ms, boost::function<void()> func, QObject* besafe )
: m_func( func ) : m_func( func )
, m_watch( QWeakPointer< QObject >( besafe ) )
{ {
//qDebug() << Q_FUNC_INFO; //qDebug() << Q_FUNC_INFO;
QTimer::singleShot( ms, this, SLOT( exec() ) ); QTimer::singleShot( ms, this, SLOT( exec() ) );
@@ -58,12 +60,14 @@ public:
public slots: public slots:
void exec() void exec()
{ {
m_func(); if( !m_watch.isNull() )
m_func();
this->deleteLater(); this->deleteLater();
}; };
private: private:
boost::function<void()> m_func; boost::function<void()> m_func;
QWeakPointer< QObject > m_watch;
}; };
}; // ns }; // ns

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
@@ -134,7 +134,7 @@ Pipeline::resolve( const query_ptr& q, bool prioritized )
{ {
if ( q.isNull() ) if ( q.isNull() )
return; return;
QList< query_ptr > qlist; QList< query_ptr > qlist;
qlist << q; qlist << q;
resolve( qlist, prioritized ); resolve( qlist, prioritized );
@@ -292,7 +292,7 @@ Pipeline::shunt( const query_ptr& q )
{ {
incQIDState( q ); incQIDState( q );
// qDebug() << "Shunting in" << lasttimeout << "ms, q:" << q->toString(); // qDebug() << "Shunting in" << lasttimeout << "ms, q:" << q->toString();
new FuncTimeout( lasttimeout, boost::bind( &Pipeline::shunt, this, q ) ); new FuncTimeout( lasttimeout, boost::bind( &Pipeline::shunt, this, q ), this );
} }
} }
else else
@@ -311,8 +311,8 @@ Pipeline::shunt( const query_ptr& q )
bool bool
Pipeline::resolverSorter( const Resolver* left, const Resolver* right ) Pipeline::resolverSorter( const Resolver* left, const Resolver* right )
{ {
if( left->weight() == right->weight() ) if( left->weight() == right->weight() ) // TODO dispatch in parallel
return left->preference() > right->preference(); return left;
else else
return left->weight() > right->weight(); return left->weight() > right->weight();
} }

View File

@@ -0,0 +1,116 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "resolver.h"
#include <QWidget>
#include <QtUiTools/QUiLoader>
#include <QMetaProperty>
#include <QDebug>
#include <QBuffer>
#include <qtemporaryfile.h>
#include <QDir>
#include <QIcon>
QVariant
Tomahawk::ExternalResolver::configMsgFromWidget( QWidget* w )
{
if( !w )
return QVariant();
// generate a qvariantmap of all the widgets in the hierarchy, and for each one include the list of properties and values
QVariantMap widgetMap;
addChildProperties( w, widgetMap );
// qDebug() << "Generated widget variant:" << widgetMap;
return widgetMap;
}
void
Tomahawk::ExternalResolver::addChildProperties( QObject* widget, QVariantMap& m )
{
// recursively add all properties of this widget to the map, then repeat on all children.
// bare QWidgets are boring---so skip them! They have no input that the user can set.
if( !widget || !widget->isWidgetType() )
return;
if( qstrcmp( widget->metaObject()->className(), "QWidget" ) != 0 )
{
// qDebug() << "Adding properties for this:" << widget->metaObject()->className();
// add this widget's properties
QVariantMap props;
for( int i = widget->metaObject()->propertyOffset(); i < widget->metaObject()->propertyCount(); i++ )
{
QString prop = widget->metaObject()->property( i ).name();
QVariant val = widget->property( prop.toLatin1() );
// clean up for QJson....
if( val.canConvert< QPixmap >() || val.canConvert< QImage >() || val.canConvert< QIcon >() )
continue;
props[ prop ] = val;
// qDebug() << QString( "%1: %2" ).arg( prop ).arg( props[ prop ].toString() );
}
m[ widget->objectName() ] = props;
}
// and recurse
foreach( QObject* child, widget->children() )
addChildProperties( child, m );
}
QWidget*
Tomahawk::ExternalResolver::widgetFromData( QByteArray& data, QWidget* parent )
{
if( data.isEmpty() )
return 0;
QUiLoader l;
QBuffer b( &data );
QWidget* w = l.load( &b, parent );
return w;
}
QByteArray
Tomahawk::ExternalResolver::fixDataImagePaths( const QByteArray& data, bool compressed, const QVariantMap& images )
{
// with a list of images and image data, write each to a temp file, replace the path in the .ui file with the temp file path
QString uiFile = QString::fromUtf8( data );
foreach( const QString& filename, images.keys() )
{
if( !uiFile.contains( filename ) ) // make sure the image is used
continue;
QString fullPath = QDir::tempPath() + "/" + filename;
QFile imgF( fullPath );
if( !imgF.open( QIODevice::WriteOnly ) )
{
qWarning() << "Failed to write to temporary image in UI file:" << filename << fullPath;
continue;
}
QByteArray data = images[ filename ].toByteArray();
qDebug() << "expanding data:" << data << compressed;
data = compressed ? qUncompress( QByteArray::fromBase64( data ) ) : QByteArray::fromBase64( data );
imgF.write( data );
imgF.close();
// replace the path to the image with the real path
uiFile.replace( filename, fullPath );
}
return uiFile.toUtf8();
}

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
@@ -33,6 +33,9 @@
weighted resolver weighted resolver
*/ */
class QWidget;
namespace Tomahawk namespace Tomahawk
{ {
@@ -45,12 +48,8 @@ public:
virtual QString name() const = 0; virtual QString name() const = 0;
virtual unsigned int weight() const = 0; virtual unsigned int weight() const = 0;
virtual unsigned int preference() const { return 100; };
virtual unsigned int timeout() const = 0; virtual unsigned int timeout() const = 0;
//virtual QWidget * configUI() { return 0; };
//etc
public slots: public slots:
virtual void resolve( const Tomahawk::query_ptr& query ) = 0; virtual void resolve( const Tomahawk::query_ptr& query ) = 0;
}; };
@@ -64,10 +63,18 @@ public:
virtual QString filePath() const { return m_filePath; } virtual QString filePath() const { return m_filePath; }
virtual QWidget* configUI() const = 0;
virtual void saveConfig() = 0;
public slots: public slots:
virtual void stop() = 0; virtual void stop() = 0;
protected:
QWidget* widgetFromData( QByteArray& data, QWidget* parent = 0 );
QVariant configMsgFromWidget( QWidget* w );
QByteArray fixDataImagePaths( const QByteArray& data, bool compressed, const QVariantMap& images );
private: private:
void addChildProperties( QObject* parent, QVariantMap& m );
QString m_filePath; QString m_filePath;
}; };

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
@@ -52,7 +52,7 @@ TomahawkSettings::TomahawkSettings( QObject* parent )
qDebug() << "Config version outdated, old:" << value( "configversion" ).toUInt() qDebug() << "Config version outdated, old:" << value( "configversion" ).toUInt()
<< "new:" << VERSION << "new:" << VERSION
<< "Doing upgrade, if any..."; << "Doing upgrade, if any...";
// insert upgrade code here as required // insert upgrade code here as required
setValue( "configversion", VERSION ); setValue( "configversion", VERSION );
} }
@@ -415,7 +415,7 @@ int
TomahawkSettings::defaultPort() const TomahawkSettings::defaultPort() const
{ {
return 50210; return 50210;
} }
int int
TomahawkSettings::externalPort() const TomahawkSettings::externalPort() const
@@ -485,7 +485,7 @@ TomahawkSettings::setTwitterScreenName( const QString& screenName )
{ {
setValue( "twitter/ScreenName", screenName ); setValue( "twitter/ScreenName", screenName );
} }
QString QString
TomahawkSettings::twitterOAuthToken() const TomahawkSettings::twitterOAuthToken() const
{ {
@@ -627,20 +627,33 @@ TomahawkSettings::setXmppBotPort( const int port )
setValue( "xmppBot/port", port ); setValue( "xmppBot/port", port );
} }
void void
TomahawkSettings::addScriptResolver(const QString& resolver) TomahawkSettings::addScriptResolver(const QString& resolver)
{ {
setValue( "script/resolvers", scriptResolvers() << resolver ); setValue( "script/resolvers", allScriptResolvers() << resolver );
} }
QStringList QStringList
TomahawkSettings::scriptResolvers() const TomahawkSettings::allScriptResolvers() const
{ {
return value( "script/resolvers" ).toStringList(); return value( "script/resolvers" ).toStringList();
} }
void void
TomahawkSettings::setScriptResolvers( const QStringList& resolver ) TomahawkSettings::setAllScriptResolvers( const QStringList& resolver )
{ {
setValue( "script/resolvers", resolver ); setValue( "script/resolvers", resolver );
} }
QStringList
TomahawkSettings::enabledScriptResolvers() const
{
return value( "script/loadedresolvers" ).toStringList();
}
void
TomahawkSettings::setEnabledScriptResolvers( const QStringList& resolvers )
{
setValue( "script/loadedresolvers", resolvers );
}

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
@@ -47,14 +47,14 @@ public:
bool watchForChanges() const; bool watchForChanges() const;
void setWatchForChanges( bool watch ); void setWatchForChanges( bool watch );
bool acceptedLegalWarning() const; bool acceptedLegalWarning() const;
void setAcceptedLegalWarning( bool accept ); void setAcceptedLegalWarning( bool accept );
/// UI settings /// UI settings
QByteArray mainWindowGeometry() const; QByteArray mainWindowGeometry() const;
void setMainWindowGeometry( const QByteArray& geom ); void setMainWindowGeometry( const QByteArray& geom );
QByteArray mainWindowState() const; QByteArray mainWindowState() const;
void setMainWindowState( const QByteArray& state ); void setMainWindowState( const QByteArray& state );
@@ -71,24 +71,24 @@ public:
/// Jabber settings /// Jabber settings
bool jabberAutoConnect() const; /// true by default bool jabberAutoConnect() const; /// true by default
void setJabberAutoConnect( bool autoconnect = false ); void setJabberAutoConnect( bool autoconnect = false );
QString jabberUsername() const; QString jabberUsername() const;
void setJabberUsername( const QString& username ); void setJabberUsername( const QString& username );
QString jabberPassword() const; QString jabberPassword() const;
void setJabberPassword( const QString& pw ); void setJabberPassword( const QString& pw );
QString jabberServer() const; QString jabberServer() const;
void setJabberServer( const QString& server ); void setJabberServer( const QString& server );
unsigned int jabberPort() const; // default is 5222 unsigned int jabberPort() const; // default is 5222
void setJabberPort( int port ); void setJabberPort( int port );
/// Network settings /// Network settings
enum ExternalAddressMode { Lan, Upnp }; enum ExternalAddressMode { Lan, Upnp };
ExternalAddressMode externalAddressMode() const; ExternalAddressMode externalAddressMode() const;
void setExternalAddressMode( ExternalAddressMode externalAddressMode ); void setExternalAddressMode( ExternalAddressMode externalAddressMode );
bool preferStaticHostPort() const; bool preferStaticHostPort() const;
void setPreferStaticHostPort( bool prefer ); void setPreferStaticHostPort( bool prefer );
@@ -120,42 +120,42 @@ public:
/// ACL settings /// ACL settings
QStringList aclEntries() const; QStringList aclEntries() const;
void setAclEntries( const QStringList &entries ); void setAclEntries( const QStringList &entries );
/// Last.fm settings /// Last.fm settings
bool scrobblingEnabled() const; /// false by default bool scrobblingEnabled() const; /// false by default
void setScrobblingEnabled( bool enable ); void setScrobblingEnabled( bool enable );
QString lastFmUsername() const; QString lastFmUsername() const;
void setLastFmUsername( const QString& username ); void setLastFmUsername( const QString& username );
QString lastFmPassword() const; QString lastFmPassword() const;
void setLastFmPassword( const QString& password ); void setLastFmPassword( const QString& password );
QByteArray lastFmSessionKey() const; QByteArray lastFmSessionKey() const;
void setLastFmSessionKey( const QByteArray& key ); void setLastFmSessionKey( const QByteArray& key );
/// Twitter settings /// Twitter settings
QString twitterScreenName() const; QString twitterScreenName() const;
void setTwitterScreenName( const QString& screenName ); void setTwitterScreenName( const QString& screenName );
QString twitterOAuthToken() const; QString twitterOAuthToken() const;
void setTwitterOAuthToken( const QString& oauthtoken ); void setTwitterOAuthToken( const QString& oauthtoken );
QString twitterOAuthTokenSecret() const; QString twitterOAuthTokenSecret() const;
void setTwitterOAuthTokenSecret( const QString& oauthtokensecret ); void setTwitterOAuthTokenSecret( const QString& oauthtokensecret );
qint64 twitterCachedFriendsSinceId() const; qint64 twitterCachedFriendsSinceId() const;
void setTwitterCachedFriendsSinceId( qint64 sinceid ); void setTwitterCachedFriendsSinceId( qint64 sinceid );
qint64 twitterCachedMentionsSinceId() const; qint64 twitterCachedMentionsSinceId() const;
void setTwitterCachedMentionsSinceId( qint64 sinceid ); void setTwitterCachedMentionsSinceId( qint64 sinceid );
qint64 twitterCachedDirectMessagesSinceId() const; qint64 twitterCachedDirectMessagesSinceId() const;
void setTwitterCachedDirectMessagesSinceId( qint64 sinceid ); void setTwitterCachedDirectMessagesSinceId( qint64 sinceid );
QHash<QString, QVariant> twitterCachedPeers() const; QHash<QString, QVariant> twitterCachedPeers() const;
void setTwitterCachedPeers( const QHash<QString, QVariant> &cachedPeers ); void setTwitterCachedPeers( const QHash<QString, QVariant> &cachedPeers );
/// XMPP Component Settings /// XMPP Component Settings
QString xmppBotServer() const; QString xmppBotServer() const;
void setXmppBotServer( const QString &server ); void setXmppBotServer( const QString &server );
@@ -168,11 +168,14 @@ public:
int xmppBotPort() const; int xmppBotPort() const;
void setXmppBotPort( const int port ); void setXmppBotPort( const int port );
/// Script resolver settings /// Script resolver settings
QStringList scriptResolvers() const; QStringList allScriptResolvers() const;
void setScriptResolvers( const QStringList& resolver ); void setAllScriptResolvers( const QStringList& resolvers );
void addScriptResolver( const QString& resolver ); void addScriptResolver( const QString& resolver );
QStringList enabledScriptResolvers() const;
void setEnabledScriptResolvers( const QStringList& resolvers );
signals: signals:
void changed(); void changed();

View File

@@ -0,0 +1,176 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "resolverconfigdelegate.h"
#include "resolversmodel.h"
#include "tomahawk/tomahawkapp.h"
#include <QApplication>
#include <QPainter>
#include <QMouseEvent>
#define PADDING 4
ResolverConfigDelegate::ResolverConfigDelegate( QObject* parent )
: QStyledItemDelegate( parent )
, m_configPressed( false )
{
}
void
ResolverConfigDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
QStyleOptionViewItemV4 opt = option;
initStyleOption( &opt, index );
QRect itemRect = opt.rect;
int top = itemRect.top();
QFont name = opt.font;
name.setPointSize( name.pointSize() + 2 );
name.setBold( true );
QFont path = opt.font;
path.setItalic( true );
path.setPointSize( path.pointSize() - 1 );
QFontMetrics bfm( name );
QFontMetrics sfm( path );
// draw the background
const QWidget* w = opt.widget;
QStyle* style = w ? w->style() : QApplication::style();
style->drawPrimitive( QStyle::PE_PanelItemViewItem, &opt, painter, w );
int rightSplit = itemRect.width();
int rectW = opt.rect.height() - 4 * PADDING;
QRect confRect = QRect( rightSplit - rectW - 2 * PADDING, 2 * PADDING + top, rectW, rectW );
// if the resolver has a config widget, paint it first (right-aligned)
if( index.data( ResolversModel::HasConfig ).toBool() ) {
// draw it the same size as the check belox
QStyleOptionToolButton topt;
topt.font = opt.font;
topt.icon = QIcon( RESPATH "images/configure.png" );
topt.iconSize = QSize( 16, 16 );
topt.rect = confRect;
topt.subControls = QStyle::SC_ToolButton;
topt.activeSubControls = QStyle::SC_None;
topt.features = QStyleOptionToolButton::None;
topt.pos = confRect.topLeft();
topt.state = m_configPressed ? QStyle::State_On : QStyle::State_Raised;
if( opt.state & QStyle::State_MouseOver || m_configPressed )
topt.state |= QStyle::State_HasFocus;
style->drawComplexControl( QStyle::CC_ToolButton, &topt, painter, w );
}
// draw check
confRect.moveTo( 2 * PADDING, 2 * PADDING + top );
opt.rect = confRect;
opt.checkState == Qt::Checked ? opt.state |= QStyle::State_On : opt.state |= QStyle::State_Off;
style->drawPrimitive( QStyle::PE_IndicatorViewItemCheck, &opt, painter, w );
itemRect.setX( opt.rect.topRight().x() + PADDING );
QString nameStr = bfm.elidedText( index.data( ResolversModel::ResolverName ).toString(),Qt::ElideRight, rightSplit );
painter->save();
painter->setFont( name );
QRect textRect = itemRect.adjusted( PADDING, PADDING, -PADDING, -PADDING );
textRect.setBottom( itemRect.height() / 2 + top );
painter->drawText( textRect, nameStr );
painter->restore();
QString pathStr = sfm.elidedText( index.data( ResolversModel::ResolverPath ).toString(),Qt::ElideMiddle, rightSplit );
painter->save();
painter->setFont( path );
painter->setBrush( Qt::gray );
textRect.moveTop( itemRect.height() / 2 + top );
painter->drawText( textRect, pathStr );
painter->restore();
}
QSize
ResolverConfigDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
int width = QStyledItemDelegate::sizeHint( option, index ).width();
QStyleOptionViewItemV4 opt = option;
initStyleOption( &opt, index );
QFont name = opt.font;
name.setPointSize( name.pointSize() + 2 );
name.setBold( true );
QFont path = opt.font;
path.setItalic( true );
path.setPointSize( path.pointSize() - 1 );
QFontMetrics bfm( name );
QFontMetrics sfm( path );
return QSize( width, 3 * PADDING + bfm.height() + sfm.height() );
}
bool
ResolverConfigDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{
// qDebug() << "EDITOR EVENT!" << ( event->type() == QEvent::MouseButtonRelease );
QStyleOptionViewItemV4 viewOpt( option );
initStyleOption( &viewOpt, index );
const QWidget* w = viewOpt.widget;
QStyle* style = w ? w->style() : QApplication::style();
int top = viewOpt.rect.top();
if( event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseButtonDblClick ) {
m_configPressed = false;
int rectW = option.rect.height() - 4 * PADDING;
QRect checkRect = QRect( 2 * PADDING, 2 * PADDING + top, rectW, rectW );
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if( me->button() != Qt::LeftButton || !checkRect.contains( me->pos() ) )
return false;
// eat the double click events inside the check rect
if( event->type() == QEvent::MouseButtonDblClick ) {
return true;
}
Qt::CheckState curState = static_cast< Qt::CheckState >( index.data( Qt::CheckStateRole ).toInt() );
Qt::CheckState newState = curState == Qt::Checked ? Qt::Unchecked : Qt::Checked;
return model->setData( index, newState, Qt::CheckStateRole );
} else if( event->type() == QEvent::MouseButtonPress ) {
int rightSplit = viewOpt.rect.width();
int rectW = viewOpt.rect.height() - 4 * PADDING;
QRect confRect = QRect( rightSplit - rectW - 2 * PADDING, 2 * PADDING + top, rectW, rectW );
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if( me->button() == Qt::LeftButton && confRect.contains( me->pos() ) ) {
m_configPressed = true;
emit openConfig( index.data( ResolversModel::ResolverPath ).toString() );
return true;
}
}
return QStyledItemDelegate::editorEvent( event, model, option, index );
}

View File

@@ -0,0 +1,42 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef RESOLVERCONFIGDELEGATE_H
#define RESOLVERCONFIGDELEGATE_H
#include <QStyledItemDelegate>
class ResolverConfigDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
explicit ResolverConfigDelegate(QObject* parent = 0);
virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;
virtual bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
signals:
void openConfig( const QString& resolverPath );
private:
bool m_configPressed;
};
#endif // RESOLVERCONFIGDELEGATE_H

View File

View File

@@ -0,0 +1,68 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef RESOLVER_CONFIG_WRAPPER
#define RESOLVER_CONFIG_WRAPPER
#include <QDialog>
#include <QDialogButtonBox>
#include <QVBoxLayout>
class ResolverConfigWrapper : public QDialog
{
Q_OBJECT
public:
ResolverConfigWrapper( QWidget* conf, const QString& title, QWidget* parent ) : QDialog( parent ), m_widget( conf )
{
setWindowTitle( title );
QVBoxLayout* v = new QVBoxLayout( this );
v->addWidget( m_widget );
QDialogButtonBox* buttons = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this );
connect( buttons, SIGNAL( clicked( QAbstractButton*) ), this, SLOT( closed( QAbstractButton* ) ) );
connect( this, SIGNAL( rejected() ), this, SLOT( rejected() ) );
v->addWidget( buttons );
setLayout( v );
}
public slots:
void closed( QAbstractButton* b )
{
// let the config widget live to see another day
layout()->removeWidget( m_widget );
m_widget->setParent( 0 );
QDialogButtonBox* buttons = qobject_cast< QDialogButtonBox* >( sender() );
if( buttons->standardButton( b ) == QDialogButtonBox::Ok )
done( QDialog::Accepted );
else
done( QDialog::Rejected );
}
// we get a rejected() signal emitted if the user presses escape (and no clicked() signal )
void rejected()
{
layout()->removeWidget( m_widget );
m_widget->setParent( 0 );
}
private:
QWidget* m_widget;
};
#endif

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
@@ -49,9 +49,8 @@ QtScriptResolver::QtScriptResolver( const QString& scriptPath )
m_name = m.value( "name" ).toString(); m_name = m.value( "name" ).toString();
m_weight = m.value( "weight", 0 ).toUInt(); m_weight = m.value( "weight", 0 ).toUInt();
m_timeout = m.value( "timeout", 25 ).toUInt() * 1000; m_timeout = m.value( "timeout", 25 ).toUInt() * 1000;
m_preference = m.value( "preference", 0 ).toUInt();
qDebug() << Q_FUNC_INFO << m_name << m_weight << m_timeout << m_preference; qDebug() << Q_FUNC_INFO << m_name << m_weight << m_timeout;
m_ready = true; m_ready = true;
Tomahawk::Pipeline::instance()->addResolver( this ); Tomahawk::Pipeline::instance()->addResolver( this );

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
@@ -68,9 +68,10 @@ public:
virtual QString name() const { return m_name; } virtual QString name() const { return m_name; }
virtual unsigned int weight() const { return m_weight; } virtual unsigned int weight() const { return m_weight; }
virtual unsigned int preference() const { return m_preference; }
virtual unsigned int timeout() const { return m_timeout; } virtual unsigned int timeout() const { return m_timeout; }
virtual QWidget* configUI() const { return 0; } // TODO support properly for qtscript resolvers too!
virtual void saveConfig() {}
public slots: public slots:
virtual void resolve( const Tomahawk::query_ptr& query ); virtual void resolve( const Tomahawk::query_ptr& query );
virtual void stop(); virtual void stop();
@@ -82,7 +83,7 @@ private:
ScriptEngine* m_engine; ScriptEngine* m_engine;
QString m_name; QString m_name;
unsigned int m_weight, m_preference, m_timeout; unsigned int m_weight, m_timeout;
bool m_ready, m_stopped; bool m_ready, m_stopped;
}; };

View File

@@ -49,6 +49,9 @@ ScriptResolver::~ScriptResolver()
stop(); stop();
Tomahawk::Pipeline::instance()->removeResolver( this ); Tomahawk::Pipeline::instance()->removeResolver( this );
if( !m_configWidget.isNull() )
delete m_configWidget.data();
} }
@@ -94,8 +97,6 @@ ScriptResolver::sendMsg( const QByteArray& msg )
{ {
qDebug() << Q_FUNC_INFO << m_ready << msg << msg.length(); qDebug() << Q_FUNC_INFO << m_ready << msg << msg.length();
if( !m_ready ) return;
quint32 len; quint32 len;
qToBigEndian( msg.length(), (uchar*) &len ); qToBigEndian( msg.length(), (uchar*) &len );
m_proc.write( (const char*) &len, 4 ); m_proc.write( (const char*) &len, 4 );
@@ -121,6 +122,9 @@ ScriptResolver::handleMsg( const QByteArray& msg )
{ {
doSetup( m ); doSetup( m );
return; return;
} else if( msgtype == "confwidget" ) {
setupConfWidget( m );
return;
} }
if( msgtype == "results" ) if( msgtype == "results" )
@@ -212,7 +216,7 @@ ScriptResolver::resolve( const Tomahawk::query_ptr& query )
sendMsg( msg ); sendMsg( msg );
m_queryState.insert( query->id(), 1 ); m_queryState.insert( query->id(), 1 );
new Tomahawk::FuncTimeout( m_timeout, boost::bind( &ScriptResolver::onTimeout, this, query ) ); new Tomahawk::FuncTimeout( m_timeout, boost::bind( &ScriptResolver::onTimeout, this, query ), this );
} }
@@ -223,17 +227,54 @@ ScriptResolver::doSetup( const QVariantMap& m )
m_name = m.value( "name" ).toString(); m_name = m.value( "name" ).toString();
m_weight = m.value( "weight", 0 ).toUInt(); m_weight = m.value( "weight", 0 ).toUInt();
m_timeout = m.value( "timeout", 25 ).toUInt() * 1000; m_timeout = m.value( "timeout", 25 ).toUInt() * 1000;
m_preference = m.value( "preference", 0 ).toUInt();
qDebug() << "SCRIPT" << filePath() << "READY," << endl qDebug() << "SCRIPT" << filePath() << "READY," << endl
<< "name" << m_name << endl << "name" << m_name << endl
<< "weight" << m_weight << endl << "weight" << m_weight << endl
<< "timeout" << m_timeout << endl << "timeout" << m_timeout;
<< "preference" << m_preference;
m_ready = true; m_ready = true;
Tomahawk::Pipeline::instance()->addResolver( this ); Tomahawk::Pipeline::instance()->addResolver( this );
} }
void
ScriptResolver::setupConfWidget( const QVariantMap& m )
{
bool compressed = m.value( "compressed", "false" ).toString() == "true";
qDebug() << "Resolver has a preferences widget! compressed?" << compressed << m;
QByteArray uiData = m[ "widget" ].toByteArray();
if( compressed )
uiData = qUncompress( QByteArray::fromBase64( uiData ) );
else
uiData = QByteArray::fromBase64( uiData );
if( m.contains( "images" ) )
uiData = fixDataImagePaths( uiData, compressed, m[ "images" ].toMap() );
m_configWidget = QWeakPointer< QWidget >( widgetFromData( uiData, 0 ) );
}
void
ScriptResolver::saveConfig()
{
Q_ASSERT( !m_configWidget.isNull() );
QVariantMap m;
m.insert( "_msgtype", "setpref" );
QVariant widgets = configMsgFromWidget( m_configWidget.data() );
m.insert( "widgets", widgets );
QByteArray data = m_serializer.serialize( m );
sendMsg( data );
}
QWidget* ScriptResolver::configUI() const
{
if( m_configWidget.isNull() )
return 0;
else
return m_configWidget.data();
}
void void
ScriptResolver::stop() ScriptResolver::stop()

View File

@@ -29,6 +29,7 @@
#include "query.h" #include "query.h"
#include "result.h" #include "result.h"
class QWidget;
class ScriptResolver : public Tomahawk::ExternalResolver class ScriptResolver : public Tomahawk::ExternalResolver
{ {
Q_OBJECT Q_OBJECT
@@ -42,6 +43,9 @@ public:
virtual unsigned int preference() const { return m_preference; } virtual unsigned int preference() const { return m_preference; }
virtual unsigned int timeout() const { return m_timeout; } virtual unsigned int timeout() const { return m_timeout; }
virtual QWidget* configUI() const;
virtual void saveConfig();
signals: signals:
void finished(); void finished();
@@ -60,10 +64,12 @@ private:
void handleMsg( const QByteArray& msg ); void handleMsg( const QByteArray& msg );
void sendMsg( const QByteArray& msg ); void sendMsg( const QByteArray& msg );
void doSetup( const QVariantMap& m ); void doSetup( const QVariantMap& m );
void setupConfWidget( const QVariantMap& m );
QProcess m_proc; QProcess m_proc;
QString m_name; QString m_name;
unsigned int m_weight, m_preference, m_timeout, m_num_restarts; unsigned int m_weight, m_preference, m_timeout, m_num_restarts;
QWeakPointer< QWidget > m_configWidget;
quint32 m_msgsize; quint32 m_msgsize;
QByteArray m_msg; QByteArray m_msg;

154
src/resolversmodel.cpp Normal file
View File

@@ -0,0 +1,154 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "resolversmodel.h"
#include <QFileInfo>
#include <tomahawksettings.h>
#include <tomahawk/tomahawkapp.h>
ResolversModel::ResolversModel( const QStringList& allResolvers, const QStringList& enabledResolvers, QObject* parent )
: QAbstractListModel( parent )
, m_allResolvers( allResolvers )
, m_enabledResolvers( enabledResolvers )
{
// do some sanity checking just in case
bool changed = false;
foreach( const QString& l, m_enabledResolvers ) {
if( !m_allResolvers.contains( l ) ) {
m_enabledResolvers.removeAll( l );
changed = true;
}
}
if( changed )
TomahawkSettings::instance()->setEnabledScriptResolvers( m_enabledResolvers );
}
ResolversModel::~ResolversModel()
{
}
QVariant
ResolversModel::data( const QModelIndex& index, int role ) const
{
if( !index.isValid() )
return QVariant();
switch( role )
{
case Qt::DisplayRole:
case ResolversModel::ResolverName:
{
QFileInfo info( m_allResolvers.at( index.row() ) );
return info.baseName();
}
case ResolversModel::ResolverPath:
return m_allResolvers.at( index.row() );
case ResolversModel::HasConfig:
if( Tomahawk::ExternalResolver* r = TomahawkApp::instance()->resolverForPath( m_allResolvers.at( index.row() ) ) ) // if we have one, it means we are loaded too!
return r->configUI() != 0;
return false;
case Qt::CheckStateRole:
return m_enabledResolvers.contains( m_allResolvers.at( index.row() ) ) ? Qt::Checked : Qt::Unchecked;
default:
return QVariant();
}
}
bool
ResolversModel::setData( const QModelIndex& index, const QVariant& value, int role )
{
if( role == Qt::CheckStateRole ) {
Qt::CheckState state = static_cast< Qt::CheckState >( value.toInt() );
QString resolver = m_allResolvers.at( index.row() );
if( state == Qt::Checked && !m_enabledResolvers.contains( resolver ) ) {
m_enabledResolvers.append( resolver );
TomahawkApp::instance()->enableScriptResolver( resolver );
} else if( state == Qt::Unchecked ) {
m_enabledResolvers.removeAll( resolver );
TomahawkApp::instance()->disableScriptResolver( resolver );
}
dataChanged( index, index );
return true;
}
return false;
}
int
ResolversModel::rowCount( const QModelIndex& parent ) const
{
return m_allResolvers.size();
}
int
ResolversModel::columnCount(const QModelIndex& parent) const
{
return 1;
}
Qt::ItemFlags
ResolversModel::flags( const QModelIndex& index ) const
{
return QAbstractItemModel::flags(index) | Qt::ItemIsUserCheckable;
}
void
ResolversModel::addResolver( const QString& resolver, bool enable )
{
beginInsertRows( QModelIndex(), m_allResolvers.count(), m_allResolvers.count() );
m_allResolvers << resolver;
if( enable )
m_enabledResolvers << resolver;
endInsertRows();
}
void
ResolversModel::removeResolver( const QString& resolver )
{
for( int i = 0; i < m_allResolvers.count(); i++ ) {
if( m_allResolvers.at( i ) == resolver ) {
beginRemoveRows( QModelIndex(), i, i );
m_allResolvers.takeAt( i );
endRemoveRows();
}
}
m_enabledResolvers.removeAll( resolver );
}
QStringList
ResolversModel::allResolvers() const
{
return m_allResolvers;
}
QStringList
ResolversModel::enabledResolvers() const
{
return m_enabledResolvers;
}

55
src/resolversmodel.h Normal file
View File

@@ -0,0 +1,55 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef RESOLVERSMODEL_H
#define RESOLVERSMODEL_H
#include <QModelIndex>
#include <QStringList>
class ResolversModel : public QAbstractListModel
{
public:
enum Roles {
ResolverName = Qt::UserRole + 15,
ResolverPath = Qt::UserRole + 16,
HasConfig = Qt::UserRole + 17
};
explicit ResolversModel( const QStringList& allResolvers, const QStringList& enabledResolvers, QObject* parent = 0 );
virtual ~ResolversModel();
virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const;
virtual int rowCount( const QModelIndex& parent = QModelIndex() ) const;
virtual int columnCount( const QModelIndex& parent ) const;
virtual Qt::ItemFlags flags(const QModelIndex& index) const;
virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
void addResolver( const QString& resolver, bool enable = false );
void removeResolver( const QString& resolver );
QStringList allResolvers() const;
QStringList enabledResolvers() const;
private:
QStringList m_allResolvers;
QStringList m_enabledResolvers;
};
#endif // RESOLVERSMODEL_H

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
@@ -24,6 +24,7 @@
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox> #include <QMessageBox>
#include <QNetworkProxy> #include <QNetworkProxy>
#include <QVBoxLayout>
#ifdef LIBLASTFM_FOUND #ifdef LIBLASTFM_FOUND
#include <lastfm/ws.h> #include <lastfm/ws.h>
@@ -39,6 +40,9 @@
#include "sip/SipHandler.h" #include "sip/SipHandler.h"
#include <database/database.h> #include <database/database.h>
#include "scanmanager.h" #include "scanmanager.h"
#include "resolverconfigdelegate.h"
#include "resolversmodel.h"
#include "resolverconfigwrapper.h"
static QString static QString
md5( const QByteArray& src ) md5( const QByteArray& src )
@@ -47,7 +51,6 @@ md5( const QByteArray& src )
return QString::fromLatin1( digest.toHex() ).rightJustified( 32, '0' ); return QString::fromLatin1( digest.toHex() ).rightJustified( 32, '0' );
} }
SettingsDialog::SettingsDialog( QWidget *parent ) SettingsDialog::SettingsDialog( QWidget *parent )
: QDialog( parent ) : QDialog( parent )
, ui( new Ui::SettingsDialog ) , ui( new Ui::SettingsDialog )
@@ -96,18 +99,19 @@ SettingsDialog::SettingsDialog( QWidget *parent )
ui->lineEditLastfmUsername->setText( s->lastFmUsername() ); ui->lineEditLastfmUsername->setText( s->lastFmUsername() );
ui->lineEditLastfmPassword->setText(s->lastFmPassword() ); ui->lineEditLastfmPassword->setText(s->lastFmPassword() );
connect( ui->pushButtonTestLastfmLogin, SIGNAL( clicked( bool) ), this, SLOT( testLastFmLogin() ) ); connect( ui->pushButtonTestLastfmLogin, SIGNAL( clicked( bool) ), this, SLOT( testLastFmLogin() ) );
// SCRIPT RESOLVER // SCRIPT RESOLVER
ui->removeScript->setEnabled( false ); ui->removeScript->setEnabled( false );
foreach( const QString& resolver, s->scriptResolvers() ) { ResolverConfigDelegate* del = new ResolverConfigDelegate( this );
QFileInfo info( resolver ); connect( del, SIGNAL( openConfig( QString ) ), this, SLOT( openResolverConfig( QString ) ) );
ui->scriptList->addTopLevelItem( new QTreeWidgetItem( QStringList() << info.baseName() << resolver ) ); ui->scriptList->setItemDelegate( del );
m_resolversModel = new ResolversModel( s->allScriptResolvers(), s->enabledScriptResolvers(), this );
} ui->scriptList->setModel( m_resolversModel );
connect( ui->scriptList, SIGNAL( itemClicked( QTreeWidgetItem*, int ) ), this, SLOT( scriptSelectionChanged() ) );
connect( ui->scriptList->selectionModel(), SIGNAL( selectionChanged( QItemSelection,QItemSelection ) ), this, SLOT( scriptSelectionChanged() ) );
connect( ui->addScript, SIGNAL( clicked( bool ) ), this, SLOT( addScriptResolver() ) ); connect( ui->addScript, SIGNAL( clicked( bool ) ), this, SLOT( addScriptResolver() ) );
connect( ui->removeScript, SIGNAL( clicked( bool ) ), this, SLOT( removeScriptResolver() ) ); connect( ui->removeScript, SIGNAL( clicked( bool ) ), this, SLOT( removeScriptResolver() ) );
connect( ui->buttonBrowse, SIGNAL( clicked() ), SLOT( showPathSelector() ) ); connect( ui->buttonBrowse, SIGNAL( clicked() ), SLOT( showPathSelector() ) );
connect( ui->proxyButton, SIGNAL( clicked() ), SLOT( showProxySettings() ) ); connect( ui->proxyButton, SIGNAL( clicked() ), SLOT( showProxySettings() ) );
connect( ui->checkBoxStaticPreferred, SIGNAL( toggled(bool) ), SLOT( toggleUpnp(bool) ) ); connect( ui->checkBoxStaticPreferred, SIGNAL( toggled(bool) ), SLOT( toggleUpnp(bool) ) );
@@ -132,23 +136,19 @@ SettingsDialog::~SettingsDialog()
s->setJabberPassword( ui->jabberPassword->text() ); s->setJabberPassword( ui->jabberPassword->text() );
s->setJabberServer( ui->jabberServer->text() ); s->setJabberServer( ui->jabberServer->text() );
s->setJabberPort( ui->jabberPort->value() ); s->setJabberPort( ui->jabberPort->value() );
s->setExternalHostname( ui->staticHostName->text() ); s->setExternalHostname( ui->staticHostName->text() );
s->setExternalPort( ui->staticPort->value() ); s->setExternalPort( ui->staticPort->value() );
s->setScannerPaths( QStringList( ui->lineEditMusicPath->text() ) ); s->setScannerPaths( QStringList( ui->lineEditMusicPath->text() ) );
s->setWatchForChanges( ui->checkBoxWatchForChanges->isChecked() ); s->setWatchForChanges( ui->checkBoxWatchForChanges->isChecked() );
s->setScrobblingEnabled( ui->checkBoxEnableLastfm->isChecked() ); s->setScrobblingEnabled( ui->checkBoxEnableLastfm->isChecked() );
s->setLastFmUsername( ui->lineEditLastfmUsername->text() ); s->setLastFmUsername( ui->lineEditLastfmUsername->text() );
s->setLastFmPassword( ui->lineEditLastfmPassword->text() ); s->setLastFmPassword( ui->lineEditLastfmPassword->text() );
QStringList resolvers; s->setAllScriptResolvers( m_resolversModel->allResolvers() );
for( int i = 0; i < ui->scriptList->topLevelItemCount(); i++ ) s->setEnabledScriptResolvers( m_resolversModel->enabledResolvers() );
{
resolvers << ui->scriptList->topLevelItem( i )->data( 1, Qt::DisplayRole ).toString();
}
s->setScriptResolvers( resolvers );
s->applyChanges(); s->applyChanges();
} }
@@ -260,13 +260,13 @@ SettingsDialog::onLastFmFinished()
ui->pushButtonTestLastfmLogin->setEnabled( false ); ui->pushButtonTestLastfmLogin->setEnabled( false );
} }
break; break;
case QNetworkReply::ContentOperationNotPermittedError: case QNetworkReply::ContentOperationNotPermittedError:
case QNetworkReply::AuthenticationRequiredError: case QNetworkReply::AuthenticationRequiredError:
ui->pushButtonTestLastfmLogin->setText( tr( "Failed" ) ); ui->pushButtonTestLastfmLogin->setText( tr( "Failed" ) );
ui->pushButtonTestLastfmLogin->setEnabled( true ); ui->pushButtonTestLastfmLogin->setEnabled( true );
break; break;
default: default:
qDebug() << "Couldn't get last.fm auth result"; qDebug() << "Couldn't get last.fm auth result";
ui->pushButtonTestLastfmLogin->setText( tr( "Could not contact server" ) ); ui->pushButtonTestLastfmLogin->setText( tr( "Could not contact server" ) );
@@ -336,38 +336,50 @@ ProxyDialog::saveSettings()
} }
void void
SettingsDialog::addScriptResolver() SettingsDialog::addScriptResolver()
{ {
QString resolver = QFileDialog::getOpenFileName( this, tr( "Load script resolver file" ), qApp->applicationDirPath() ); QString resolver = QFileDialog::getOpenFileName( this, tr( "Load script resolver file" ), qApp->applicationDirPath() );
if( !resolver.isEmpty() ) { if( !resolver.isEmpty() ) {
QFileInfo info( resolver ); m_resolversModel->addResolver( resolver, true );
ui->scriptList->addTopLevelItem( new QTreeWidgetItem( QStringList() << info.baseName() << resolver ) ); TomahawkApp::instance()->enableScriptResolver( resolver );
TomahawkApp::instance()->addScriptResolver( resolver );
} }
} }
void void
SettingsDialog::removeScriptResolver() SettingsDialog::removeScriptResolver()
{ {
// only one selection // only one selection
if( !ui->scriptList->selectedItems().isEmpty() ) { if( !ui->scriptList->selectionModel()->selectedIndexes().isEmpty() ) {
QString resolver = ui->scriptList->selectedItems().first()->data( 1, Qt::DisplayRole ).toString(); QString resolver = ui->scriptList->selectionModel()->selectedIndexes().first().data( ResolversModel::ResolverPath ).toString();
delete ui->scriptList->takeTopLevelItem( ui->scriptList->indexOfTopLevelItem( ui->scriptList->selectedItems().first() ) ); m_resolversModel->removeResolver( resolver );
TomahawkApp::instance()->removeScriptResolver( resolver ); TomahawkApp::instance()->disableScriptResolver( resolver );
} }
} }
void
void
SettingsDialog::scriptSelectionChanged() SettingsDialog::scriptSelectionChanged()
{ {
if( !ui->scriptList->selectedItems().isEmpty() ) { if( !ui->scriptList->selectionModel()->selectedIndexes().isEmpty() ) {
ui->removeScript->setEnabled( true ); ui->removeScript->setEnabled( true );
} else { } else {
ui->removeScript->setEnabled( false ); ui->removeScript->setEnabled( false );
} }
} }
void
SettingsDialog::openResolverConfig( const QString& resolver )
{
Tomahawk::ExternalResolver* r = TomahawkApp::instance()->resolverForPath( resolver );
if( r && r->configUI() ) {
ResolverConfigWrapper dialog( r->configUI(), "Resolver Config", this );
QWeakPointer< ResolverConfigWrapper > watcher( &dialog );
int ret = dialog.exec();
if( !watcher.isNull() && ret == QDialog::Accepted ) {
// send changed config to resolver
r->saveConfig();
}
}
}

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
@@ -21,6 +21,7 @@
#include <QDialog> #include <QDialog>
class ResolversModel;
class QNetworkReply; class QNetworkReply;
namespace Ui namespace Ui
@@ -53,7 +54,7 @@ public:
signals: signals:
void settingsChanged(); void settingsChanged();
protected: protected:
void changeEvent( QEvent* e ); void changeEvent( QEvent* e );
@@ -71,13 +72,15 @@ private slots:
void addScriptResolver(); void addScriptResolver();
void scriptSelectionChanged(); void scriptSelectionChanged();
void removeScriptResolver(); void removeScriptResolver();
void openResolverConfig( const QString& );
private: private:
Ui::SettingsDialog* ui; Ui::SettingsDialog* ui;
ProxyDialog m_proxySettings; ProxyDialog m_proxySettings;
bool m_rejected; bool m_rejected;
QNetworkReply* m_testLastFmQuery; QNetworkReply* m_testLastFmQuery;
ResolversModel* m_resolversModel;
}; };
#endif // SETTINGSDIALOG_H #endif // SETTINGSDIALOG_H

View File

@@ -23,7 +23,7 @@
<item> <item>
<widget class="QTabWidget" name="tabWidget"> <widget class="QTabWidget" name="tabWidget">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>4</number>
</property> </property>
<widget class="QWidget" name="tabJabber"> <widget class="QWidget" name="tabJabber">
<attribute name="title"> <attribute name="title">
@@ -590,7 +590,7 @@
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_4"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<item> <item>
<widget class="QTreeWidget" name="scriptList"> <widget class="QTreeView" name="scriptList">
<property name="alternatingRowColors"> <property name="alternatingRowColors">
<bool>true</bool> <bool>true</bool>
</property> </property>
@@ -600,40 +600,18 @@
<property name="rootIsDecorated"> <property name="rootIsDecorated">
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="uniformRowHeights">
<bool>true</bool>
</property>
<property name="itemsExpandable"> <property name="itemsExpandable">
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="animated"> <property name="animated">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="columnCount"> <property name="headerHidden">
<number>2</number> <bool>true</bool>
</property> </property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
<attribute name="headerCascadingSectionResizes">
<bool>true</bool>
</attribute>
<attribute name="headerDefaultSectionSize">
<number>150</number>
</attribute>
<attribute name="headerHighlightSections">
<bool>true</bool>
</attribute>
<attribute name="headerStretchLastSection">
<bool>true</bool>
</attribute>
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
<column>
<property name="text">
<string notr="true">2</string>
</property>
</column>
</widget> </widget>
</item> </item>
<item> <item>

View File

@@ -289,7 +289,7 @@ TomahawkApp::~TomahawkApp()
qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO;
// stop script resolvers // stop script resolvers
foreach( Tomahawk::ExternalResolver* r, m_scriptResolvers ) foreach( Tomahawk::ExternalResolver* r, m_scriptResolvers.values() )
{ {
delete r; delete r;
} }
@@ -415,37 +415,41 @@ TomahawkApp::setupPipeline()
Pipeline::instance()->addResolver( new DatabaseResolver( 100 ) ); Pipeline::instance()->addResolver( new DatabaseResolver( 100 ) );
// load script resolvers // load script resolvers
foreach( QString resolver, TomahawkSettings::instance()->scriptResolvers() ) foreach( QString resolver, TomahawkSettings::instance()->enabledScriptResolvers() )
addScriptResolver( resolver ); enableScriptResolver( resolver );
} }
void void
TomahawkApp::addScriptResolver( const QString& path ) TomahawkApp::enableScriptResolver( const QString& path )
{ {
const QFileInfo fi( path ); const QFileInfo fi( path );
if ( fi.suffix() == "js" || fi.suffix() == "script" ) if ( fi.suffix() == "js" || fi.suffix() == "script" )
m_scriptResolvers << new QtScriptResolver( path ); m_scriptResolvers.insert( path, new QtScriptResolver( path ) );
else else
m_scriptResolvers << new ScriptResolver( path ); m_scriptResolvers.insert( path, new ScriptResolver( path ) );
} }
void void
TomahawkApp::removeScriptResolver( const QString& path ) TomahawkApp::disableScriptResolver( const QString& path )
{ {
foreach( Tomahawk::ExternalResolver* r, m_scriptResolvers ) if( m_scriptResolvers.contains( path ) )
{ {
if( r->filePath() == path ) Tomahawk::ExternalResolver* r = m_scriptResolvers.take( path );
{
m_scriptResolvers.removeAll( r ); connect( r, SIGNAL( finished() ), r, SLOT( deleteLater() ) );
connect( r, SIGNAL( finished() ), r, SLOT( deleteLater() ) ); r->stop();
r->stop(); return;
return;
}
} }
} }
Tomahawk::ExternalResolver*
TomahawkApp::resolverForPath( const QString& scriptPath )
{
return m_scriptResolvers.value( scriptPath, 0 );
}
void void
TomahawkApp::initLocalCollection() TomahawkApp::initLocalCollection()