1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-04-20 16:02:07 +02:00

Found a better place to do bundle loading, and also load metadata.

This commit is contained in:
Teo Mrnjavac 2013-03-11 22:53:58 +01:00
parent 70baca7711
commit 118b0a1cbf
6 changed files with 121 additions and 47 deletions

View File

@ -451,48 +451,18 @@ SettingsDialog::openAccountConfig( Account* account, bool showDelete )
void
SettingsDialog::installFromFile()
{
QString resolver = QFileDialog::getOpenFileName( 0, tr( "Install resolver from file" ),
TomahawkSettings::instance()->scriptDefaultPath(),
tr( "Tomahawk Resolvers (*.axe *.js);;"
"All files (*)" ),
0,
QFileDialog::ReadOnly );
const QString resolver = QFileDialog::getOpenFileName( 0, tr( "Install resolver from file" ),
TomahawkSettings::instance()->scriptDefaultPath(),
tr( "Tomahawk Resolvers (*.axe *.js);;"
"All files (*)" ),
0,
QFileDialog::ReadOnly );
if( !resolver.isEmpty() )
{
//I'm still a little proof of concept, refactor me into a proper class
QFileInfo resolverAbsoluteFilePath( resolver );
const QFileInfo resolverAbsoluteFilePath( resolver );
TomahawkSettings::instance()->setScriptDefaultPath( resolverAbsoluteFilePath.absolutePath() );
if ( resolverAbsoluteFilePath.suffix() == "axe" )
{
QDir dir( TomahawkUtils::extractScriptPayload( resolverAbsoluteFilePath.filePath(),
resolverAbsoluteFilePath.baseName(),
"manualresolvers" ) );
dir.cd( "content" );
QFile desktopFile( dir.absoluteFilePath( "metadata.desktop" ) );
if ( desktopFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
{
QTextStream desktopFileStream( &desktopFile );
while ( !desktopFileStream.atEnd() )
{
QString line = desktopFileStream.readLine().trimmed();
//TODO: correct baseName
if ( line.startsWith( "X-Synchrotron-MainScript" ) )
{
line.remove( QRegExp( "^X-Synchrotron-MainScript\\s*=\\s*" ) );
resolver = dir.absoluteFilePath( line ); //this is our path to the JS
}
}
}
}
resolverAbsoluteFilePath = QFileInfo( resolver );
//TODO: if the new path has a metadata file in the dir structure, read it, check the config
// and act accordingly for multi-account resolvers
if ( resolverAbsoluteFilePath.baseName() == "spotify_tomahawkresolver" )
{
// HACK if this is a spotify resolver, we treat it specially.

View File

@ -88,6 +88,8 @@ public:
virtual QWidget* aclWidget() = 0;
virtual QPixmap icon() const = 0;
#endif
virtual QString description() const { return QString(); }
virtual QString author() const { return QString(); }
virtual void saveConfig() {} // called when the widget has been edited. save values from config widget, call sync() to write to disk account generic settings

View File

@ -278,11 +278,16 @@ AccountDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option,
// Draw the title and description
// title
QString title = index.data( Qt::DisplayRole ).toString();
QString author = index.data( AccountModel::AuthorRole ).toString();
QString desc = index.data( AccountModel::DescriptionRole ).toString();
const int rightTitleEdge = rightEdge - PADDING;
const int leftTitleEdge = pixmapRect.right() + PADDING;
painter->setFont( titleFont );
QRect textRect;
const bool canRate = index.data( AccountModel::CanRateRole ).toBool();
const bool canRate = index.data( AccountModel::CanRateRole ).toBool()
|| !author.isEmpty()
|| !desc.isEmpty(); // if it's Attica, or it has non-empty at least author or description
if ( canRate )
{
textRect = QRect( leftTitleEdge, opt.rect.top() + PADDING, rightTitleEdge - leftTitleEdge, painter->fontMetrics().height() );
@ -294,7 +299,6 @@ AccountDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option,
painter->drawText( textRect, Qt::AlignVCenter | Qt::AlignLeft, title );
// author
QString author = index.data( AccountModel::AuthorRole ).toString();
int runningBottom = textRect.bottom();
if ( !author.isEmpty() && canRate )
{
@ -310,7 +314,6 @@ AccountDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option,
}
// description
QString desc = index.data( AccountModel::DescriptionRole ).toString();
const int descWidth = rightEdge - leftTitleEdge - PADDING;
painter->setFont( descFont );
const QRect descRect( leftTitleEdge, runningBottom + PADDING, descWidth, painter->fontMetrics().height() );

View File

@ -337,7 +337,11 @@ AccountModel::data( const QModelIndex& index, int role ) const
case Qt::DecorationRole:
return acct->icon();
case DescriptionRole:
return node->factory ? node->factory->description() : QString();
return node->factory ?
( !node->factory->description().isEmpty() ? node->factory->description() : acct->description() )
: acct->description();
case AuthorRole:
return acct->author();
case Qt::CheckStateRole:
return acct->enabled() ? Qt::Checked : Qt::Unchecked;
case AccountData:

View File

@ -66,8 +66,84 @@ ResolverAccountFactory::createFromPath( const QString& path, const QString& fact
QFileInfo info( path );
return new AtticaResolverAccount( generateId( factory ), path, info.baseName() );
}
else
return new ResolverAccount( generateId( factory ), path );
else //on filesystem, but it could be a bundle or a legacy resolver file
{
QString realPath( path );
const QFileInfo pathInfo( path );
QVariantHash configuration;
if ( pathInfo.suffix() == "axe" )
{
QDir dir( TomahawkUtils::extractScriptPayload( pathInfo.filePath(),
pathInfo.baseName(),
"manualresolvers" ) );
if ( !( dir.exists() && dir.isReadable() ) ) //decompression fubar
return 0;
if ( !dir.cd( "content" ) ) //more fubar
return 0;
QString desktopFilePath = dir.absoluteFilePath( "metadata.desktop" );
configuration = metadataFromDesktopFile( desktopFilePath );
realPath = configuration[ "path" ].toString();
if ( realPath.isEmpty() )
return 0;
}
else //either legacy resolver or uncompressed bundle, so we look for a metadata file
{
QDir dir = pathInfo.absoluteDir();//assume we are in the code directory of a bundle
if ( dir.cdUp() && dir.cdUp() ) //go up twice to the content dir, if any
{
QString desktopFilePath = dir.absoluteFilePath( "metadata.desktop" );
configuration = metadataFromDesktopFile( desktopFilePath );
configuration[ "path" ] = realPath; //our initial path still overrides whatever the desktop file says
}
//else we just have empty metadata (legacy resolver without desktop file)
}
//TODO: handle multi-account resolvers
return new ResolverAccount( generateId( factory ), realPath, configuration );
}
}
QVariantHash
ResolverAccountFactory::metadataFromDesktopFile( const QString& path )
{
QVariantHash result;
QFile desktopFile( path );
if ( desktopFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
{
QTextStream desktopFileStream( &desktopFile );
while ( !desktopFileStream.atEnd() )
{
QString line = desktopFileStream.readLine().trimmed();
if ( line.contains( QRegExp( "^X-Synchrotron-MainScript\\s*=\\s*" ) ) )
{
line.remove( QRegExp( "^X-Synchrotron-MainScript\\s*=\\s*" ) );
QFileInfo fi( path );
result[ "path" ] = fi.absoluteDir().absoluteFilePath( line ); //this is our path to the JS
}
else if ( line.contains( QRegExp( "^X-KDE-PluginInfo-Author\\s*=\\s*" ) ) )
{
line.remove( QRegExp( "^X-KDE-PluginInfo-Author\\s*=\\s*" ) );
result[ "author" ] = line;
}
else if ( line.contains( QRegExp( "^Comment\\s*=\\s*" ) ) )
{
line.remove( QRegExp( "^Comment\\s*=\\s*" ) );
result[ "description" ] = line;
}
//TODO: correct baseName and rename directory maybe?
}
}
return result;
}
@ -84,10 +160,10 @@ ResolverAccount::ResolverAccount( const QString& accountId )
}
ResolverAccount::ResolverAccount( const QString& accountId, const QString& path )
ResolverAccount::ResolverAccount( const QString& accountId, const QString& path, const QVariantHash& initialConfiguration )
: Account( accountId )
{
QVariantHash configuration;
QVariantHash configuration( initialConfiguration );
configuration[ "path" ] = path;
setConfiguration( configuration );
@ -242,6 +318,21 @@ ResolverAccount::icon() const
return m_resolver.data()->icon();
}
QString
ResolverAccount::description() const
{
return configuration().value( "description" ).toString();
}
QString
ResolverAccount::author() const
{
return configuration().value( "author" ).toString();
}
/// AtticaResolverAccount
AtticaResolverAccount::AtticaResolverAccount( const QString& accountId )

View File

@ -51,6 +51,9 @@ public:
// Internal use
static Account* createFromPath( const QString& path, const QString& factoryId, bool isAttica );
private:
static QVariantHash metadataFromDesktopFile( const QString& path );
};
/**
@ -80,6 +83,8 @@ public:
QString path() const;
virtual QPixmap icon() const;
virtual QString description() const;
virtual QString author() const;
// Not relevant
virtual SipPlugin* sipPlugin() { return 0; }
@ -91,8 +96,7 @@ private slots:
protected:
// Created by factory, when user installs a new resolver
ResolverAccount( const QString& accountId, const QString& path );
ResolverAccount( const QString& accountId, const QString& path, const QVariantHash& initialConfiguration = QVariantHash() );
void hookupResolver();
QPointer<ExternalResolverGui> m_resolver;