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:
parent
70baca7711
commit
118b0a1cbf
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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() );
|
||||
|
@ -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:
|
||||
|
@ -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 )
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user