mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-03-13 20:39:57 +01:00
Merge branch 'master' into accounts
Conflicts: src/libtomahawk/utils/xspfloader.cpp src/libtomahawk/utils/xspfloader.h src/tomahawkapp.cpp src/tomahawkwindow.h
This commit is contained in:
commit
f4c92793e6
@ -1,3 +1,5 @@
|
||||
Version 0.4.0:
|
||||
|
||||
Version 0.3.3:
|
||||
* Automatically load Super Collection tracks when no official release
|
||||
information is available.
|
||||
|
BIN
data/images/process-stop.png
Normal file
BIN
data/images/process-stop.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
@ -135,5 +135,6 @@
|
||||
<file>data/images/rdio.png</file>
|
||||
<file>data/images/lastfm-icon.png</file>
|
||||
<file>data/sql/dbmigrate-27_to_28.sql</file>
|
||||
<file>data/images/process-stop.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -58,4 +58,7 @@ if (APPLE)
|
||||
FILE(COPY ${CMAKE_SOURCE_DIR}/admin/mac/sparkle_pub.pem
|
||||
DESTINATION "${CMAKE_BINARY_DIR}/tomahawk.app/Contents/Resources")
|
||||
|
||||
FILE(COPY /usr/bin/SetFile DESTINATION "${CMAKE_BINARY_DIR}/tomahawk.app/Contents/MacOS")
|
||||
FILE(COPY /usr/bin/GetFileInfo DESTINATION "${CMAKE_BINARY_DIR}/tomahawk.app/Contents/MacOS")
|
||||
|
||||
endif (APPLE)
|
||||
|
@ -38,6 +38,7 @@ set( libGuiSources
|
||||
jobview/PipelineStatusItem.cpp
|
||||
jobview/TransferStatusItem.cpp
|
||||
jobview/LatchedStatusItem.cpp
|
||||
jobview/ErrorStatusMessage.cpp
|
||||
|
||||
infobar/infobar.cpp
|
||||
|
||||
@ -272,6 +273,7 @@ set( libGuiHeaders
|
||||
jobview/PipelineStatusItem.h
|
||||
jobview/TransferStatusItem.h
|
||||
jobview/LatchedStatusItem.h
|
||||
jobview/ErrorStatusMessage.h
|
||||
|
||||
thirdparty/Qocoa/qsearchfield.h
|
||||
)
|
||||
|
@ -590,10 +590,10 @@ AudioEngine::onStateChanged( Phonon::State newState, Phonon::State oldState )
|
||||
|
||||
if ( newState == Phonon::ErrorState )
|
||||
{
|
||||
stop();
|
||||
|
||||
tLog() << "Phonon Error:" << m_mediaObject->errorString() << m_mediaObject->errorType();
|
||||
emit error( UnknownError );
|
||||
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
if ( newState == Phonon::PlayingState )
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include "utils/xspfloader.h"
|
||||
#include "jobview/JobStatusView.h"
|
||||
#include "jobview/JobStatusModel.h"
|
||||
#include "jobview/ErrorStatusMessage.h"
|
||||
|
||||
#ifdef QCA2_FOUND
|
||||
#include "utils/groovesharkparser.h"
|
||||
#endif //QCA2_FOUND
|
||||
@ -699,10 +701,18 @@ DropJob::removeDuplicates()
|
||||
{
|
||||
bool contains = false;
|
||||
foreach( const Tomahawk::query_ptr &tmpItem, list )
|
||||
{
|
||||
if ( item->album() == tmpItem->album()
|
||||
&& item->artist() == tmpItem->artist()
|
||||
&& item->track() == tmpItem->track() )
|
||||
{
|
||||
if ( item->playable() && !tmpItem->playable() )
|
||||
list.replace( list.indexOf( tmpItem ), item );
|
||||
|
||||
contains = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !contains )
|
||||
list.append( item );
|
||||
}
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "query.h"
|
||||
|
||||
#include "infosystem/infosystem.h"
|
||||
#include "utils/xspfloader.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QMimeData>
|
||||
|
@ -451,8 +451,15 @@ LastFmPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSy
|
||||
QString artistName = criteria["artist"];
|
||||
QString albumName = criteria["album"];
|
||||
|
||||
QString imgurl = "http://ws.audioscrobbler.com/2.0/?method=album.imageredirect&artist=%1&album=%2&autocorrect=1&size=large&api_key=7a90f6672a04b809ee309af169f34b8b";
|
||||
QNetworkRequest req( imgurl.arg( artistName ).arg( albumName ) );
|
||||
QUrl imgurl( "http://ws.audioscrobbler.com/2.0/" );
|
||||
imgurl.addQueryItem( "method", "album.imageredirect" );
|
||||
imgurl.addQueryItem( "artist", artistName );
|
||||
imgurl.addQueryItem( "album", albumName );
|
||||
imgurl.addQueryItem( "autocorrect", QString::number( 1 ) );
|
||||
imgurl.addQueryItem( "size", "large" );
|
||||
imgurl.addQueryItem( "api_key", "7a90f6672a04b809ee309af169f34b8b" );
|
||||
|
||||
QNetworkRequest req( imgurl );
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->get( req );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
|
||||
@ -464,8 +471,14 @@ LastFmPlugin::notInCacheSlot( QHash<QString, QString> criteria, Tomahawk::InfoSy
|
||||
{
|
||||
QString artistName = criteria["artist"];
|
||||
|
||||
QString imgurl = "http://ws.audioscrobbler.com/2.0/?method=artist.imageredirect&artist=%1&autocorrect=1&size=large&api_key=7a90f6672a04b809ee309af169f34b8b";
|
||||
QNetworkRequest req( imgurl.arg( artistName ) );
|
||||
QUrl imgurl( "http://ws.audioscrobbler.com/2.0/" );
|
||||
imgurl.addQueryItem( "method", "artist.imageredirect" );
|
||||
imgurl.addQueryItem( "artist", artistName );
|
||||
imgurl.addQueryItem( "autocorrect", QString::number( 1 ) );
|
||||
imgurl.addQueryItem( "size", "large" );
|
||||
imgurl.addQueryItem( "api_key", "7a90f6672a04b809ee309af169f34b8b" );
|
||||
|
||||
QNetworkRequest req( imgurl );
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->get( req );
|
||||
reply->setProperty( "requestData", QVariant::fromValue< Tomahawk::InfoSystem::InfoRequestData >( requestData ) );
|
||||
|
||||
|
56
src/libtomahawk/jobview/ErrorStatusMessage.cpp
Normal file
56
src/libtomahawk/jobview/ErrorStatusMessage.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2012, Leo Franchi <lfranchi@kde.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 "ErrorStatusMessage.h"
|
||||
|
||||
#include "utils/tomahawkutils.h"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
QPixmap* ErrorStatusMessage::s_pixmap = 0;
|
||||
|
||||
ErrorStatusMessage::ErrorStatusMessage( const QString& message, int timeoutSecs )
|
||||
: JobStatusItem()
|
||||
, m_message( message )
|
||||
{
|
||||
m_timer = new QTimer( this );
|
||||
m_timer->setInterval( timeoutSecs * 1000 );
|
||||
m_timer->setSingleShot( true );
|
||||
|
||||
connect( m_timer, SIGNAL( timeout() ), this, SIGNAL( finished() ) );
|
||||
|
||||
if ( !s_pixmap )
|
||||
s_pixmap = new QPixmap( RESPATH "images/process-stop.png" );
|
||||
|
||||
m_timer->start();
|
||||
}
|
||||
|
||||
|
||||
QPixmap
|
||||
ErrorStatusMessage::icon() const
|
||||
{
|
||||
Q_ASSERT( s_pixmap );
|
||||
return *s_pixmap;
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
ErrorStatusMessage::mainText() const
|
||||
{
|
||||
return m_message;
|
||||
}
|
48
src/libtomahawk/jobview/ErrorStatusMessage.h
Normal file
48
src/libtomahawk/jobview/ErrorStatusMessage.h
Normal file
@ -0,0 +1,48 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2012, Leo Franchi <lfranchi@kde.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 ERRORSTATUSMESSAGE_H
|
||||
#define ERRORSTATUSMESSAGE_H
|
||||
|
||||
#include "JobStatusItem.h"
|
||||
#include "dllmacro.h"
|
||||
|
||||
class QTimer;
|
||||
class QPixmap;
|
||||
|
||||
class DLLEXPORT ErrorStatusMessage : public JobStatusItem
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ErrorStatusMessage( const QString& errorMessage, int defaultTimeoutSecs = 8 );
|
||||
|
||||
QString type() const { return "errormessage"; }
|
||||
QString rightColumnText() const { return QString(); }
|
||||
|
||||
QPixmap icon() const;
|
||||
QString mainText() const;
|
||||
|
||||
bool allowMultiLine() const { return true; }
|
||||
private:
|
||||
QString m_message;
|
||||
QTimer* m_timer;
|
||||
|
||||
static QPixmap* s_pixmap;
|
||||
};
|
||||
|
||||
#endif // ERRORSTATUSMESSAGE_H
|
@ -23,14 +23,16 @@
|
||||
|
||||
#include <QPainter>
|
||||
#include <QApplication>
|
||||
#include <QListView>
|
||||
|
||||
#define ROW_HEIGHT 20
|
||||
#define ICON_PADDING 1
|
||||
#define PADDING 2
|
||||
JobStatusDelegate::JobStatusDelegate( QObject* parent )
|
||||
: QStyledItemDelegate ( parent )
|
||||
, m_parentView( qobject_cast< QListView* >( parent ) )
|
||||
{
|
||||
|
||||
Q_ASSERT( m_parentView );
|
||||
}
|
||||
|
||||
JobStatusDelegate::~JobStatusDelegate()
|
||||
@ -45,6 +47,7 @@ JobStatusDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
QStyleOptionViewItemV4 opt = option;
|
||||
initStyleOption( &opt, index );
|
||||
QFontMetrics fm( opt.font );
|
||||
const bool allowMultiLine = index.data( JobStatusModel::AllowMultiLineRole ).toBool();
|
||||
|
||||
opt.state &= ~QStyle::State_MouseOver;
|
||||
QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget );
|
||||
@ -52,7 +55,9 @@ JobStatusDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
// painter->drawLine( opt.rect.topLeft(), opt.rect.topRight() );
|
||||
|
||||
painter->setRenderHint( QPainter::Antialiasing );
|
||||
const QRect iconRect( ICON_PADDING, ICON_PADDING + opt.rect.y(), ROW_HEIGHT - 2*ICON_PADDING, ROW_HEIGHT - 2*ICON_PADDING );
|
||||
QRect iconRect( ICON_PADDING, ICON_PADDING + opt.rect.y(), ROW_HEIGHT - 2*ICON_PADDING, ROW_HEIGHT - 2*ICON_PADDING );
|
||||
if ( allowMultiLine )
|
||||
iconRect.moveTop( opt.rect.top() + opt.rect.height() / 2 - iconRect.height() / 2);
|
||||
QPixmap p = index.data( Qt::DecorationRole ).value< QPixmap >();
|
||||
p = p.scaledToHeight( iconRect.height(), Qt::SmoothTransformation );
|
||||
painter->drawPixmap( iconRect, p );
|
||||
@ -71,15 +76,34 @@ JobStatusDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
|
||||
|
||||
const int mainW = rightEdge - 3*PADDING - iconRect.right();
|
||||
QString mainText = index.data( Qt::DisplayRole ).toString();
|
||||
mainText = fm.elidedText( mainText, Qt::ElideRight, mainW );
|
||||
painter->drawText( QRect( iconRect.right() + 2*PADDING, PADDING + opt.rect.y(), mainW, opt.rect.height() - 2*PADDING ), Qt::AlignLeft | Qt::AlignVCenter, mainText );
|
||||
QTextOption to( Qt::AlignLeft | Qt::AlignVCenter );
|
||||
if ( !allowMultiLine )
|
||||
mainText = fm.elidedText( mainText, Qt::ElideRight, mainW );
|
||||
else
|
||||
to.setWrapMode( QTextOption::WrapAtWordBoundaryOrAnywhere );
|
||||
painter->drawText( QRect( iconRect.right() + 2*PADDING, PADDING + opt.rect.y(), mainW, opt.rect.height() - 2*PADDING ), mainText, to );
|
||||
}
|
||||
|
||||
QSize
|
||||
JobStatusDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
// return QStyledItemDelegate::sizeHint( option, index );
|
||||
const int w = QStyledItemDelegate::sizeHint ( option, index ).width();
|
||||
return QSize( w, ROW_HEIGHT );
|
||||
const bool allowMultiLine = index.data( JobStatusModel::AllowMultiLineRole ).toBool();
|
||||
|
||||
if ( !allowMultiLine )
|
||||
return QSize( QStyledItemDelegate::sizeHint ( option, index ).width(), ROW_HEIGHT );
|
||||
else if ( m_cachedMultiLineHeights.contains( index ) )
|
||||
return QSize( QStyledItemDelegate::sizeHint ( option, index ).width(), m_cachedMultiLineHeights[ index ] );
|
||||
|
||||
// Don't elide, but stretch across as many rows as required
|
||||
QStyleOptionViewItemV4 opt = option;
|
||||
initStyleOption( &opt, index );
|
||||
|
||||
const QString text = index.data( Qt::DisplayRole ).toString();
|
||||
const int leftEdge = ICON_PADDING + ROW_HEIGHT + 2*PADDING;
|
||||
const QRect rect = opt.fontMetrics.boundingRect( leftEdge, opt.rect.top(), m_parentView->width() - leftEdge, 200, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, text );
|
||||
|
||||
m_cachedMultiLineHeights.insert( index, rect.height() + 4*PADDING );
|
||||
|
||||
return QSize( QStyledItemDelegate::sizeHint ( option, index ).width(), rect.height() + 4*PADDING );
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class QPainter;
|
||||
class QListView;
|
||||
|
||||
class JobStatusDelegate : public QStyledItemDelegate
|
||||
{
|
||||
@ -33,6 +34,10 @@ public:
|
||||
|
||||
virtual void paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
virtual QSize sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
|
||||
|
||||
private:
|
||||
mutable QHash< QPersistentModelIndex, int > m_cachedMultiLineHeights;
|
||||
QListView* m_parentView;
|
||||
};
|
||||
|
||||
#endif // JOBSTATUSDELEGATE_H
|
||||
|
@ -53,6 +53,7 @@ public:
|
||||
* and a count will be shown instead.
|
||||
*/
|
||||
virtual bool collapseItem() const { return false; }
|
||||
virtual bool allowMultiLine() const { return false; }
|
||||
|
||||
signals:
|
||||
/// Ask for an update
|
||||
|
@ -100,6 +100,8 @@ JobStatusModel::data( const QModelIndex& index, int role ) const
|
||||
else
|
||||
return item->rightColumnText();
|
||||
}
|
||||
case AllowMultiLineRole:
|
||||
return item->allowMultiLine();
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
|
@ -31,7 +31,8 @@ public:
|
||||
enum JobRoles {
|
||||
// DecorationRole is icon
|
||||
// DisplayRole is main col
|
||||
RightColumnRole = Qt::UserRole + 1
|
||||
RightColumnRole = Qt::UserRole + 1,
|
||||
AllowMultiLineRole = Qt::UserRole + 2
|
||||
};
|
||||
|
||||
explicit JobStatusModel( QObject* parent = 0 );
|
||||
|
@ -40,6 +40,7 @@ JobStatusView* JobStatusView::s_instance = 0;
|
||||
JobStatusView::JobStatusView( AnimatedSplitter* parent )
|
||||
: AnimatedWidget( parent )
|
||||
, m_parent( parent )
|
||||
, m_cachedHeight( -1 )
|
||||
{
|
||||
s_instance = this;
|
||||
|
||||
@ -56,9 +57,7 @@ JobStatusView::JobStatusView( AnimatedSplitter* parent )
|
||||
|
||||
m_view->setFrameShape( QFrame::NoFrame );
|
||||
m_view->setAttribute( Qt::WA_MacShowFocusRect, 0 );
|
||||
|
||||
// new QTreeWidgetItem( m_tree );
|
||||
m_view->setUniformItemSizes( true );
|
||||
m_view->setUniformItemSizes( false );
|
||||
|
||||
#ifndef Q_WS_WIN
|
||||
QFont f = font();
|
||||
@ -86,12 +85,14 @@ JobStatusView::setModel( JobStatusModel* m )
|
||||
|
||||
connect( m_view->model(), SIGNAL( rowsInserted( QModelIndex, int, int ) ), this, SLOT( checkCount() ) );
|
||||
connect( m_view->model(), SIGNAL( rowsRemoved( QModelIndex, int, int ) ), this, SLOT( checkCount() ) );
|
||||
connect( m_view->model(), SIGNAL( modelReset() ), this, SLOT( checkCount() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JobStatusView::checkCount()
|
||||
{
|
||||
m_cachedHeight = -1;
|
||||
if ( m_view->model()->rowCount() == 0 && !isHidden() )
|
||||
emit hideWidget();
|
||||
else
|
||||
@ -102,15 +103,21 @@ JobStatusView::checkCount()
|
||||
QSize
|
||||
JobStatusView::sizeHint() const
|
||||
{
|
||||
if ( m_cachedHeight >= 0 )
|
||||
return QSize( 0, m_cachedHeight );
|
||||
|
||||
unsigned int y = 0;
|
||||
// y += m_tree->header()->height();
|
||||
y += m_view->contentsMargins().top() + m_view->contentsMargins().bottom();
|
||||
|
||||
if ( m_view->model()->rowCount() )
|
||||
{
|
||||
unsigned int rowheight = m_view->sizeHintForRow( 0 );
|
||||
y += rowheight * m_view->model()->rowCount() + 2;
|
||||
for ( int i = 0; i < m_view->model()->rowCount(); i++ )
|
||||
{
|
||||
y += m_view->sizeHintForRow( i );
|
||||
}
|
||||
y += 2; // some padding
|
||||
}
|
||||
|
||||
m_cachedHeight = y;
|
||||
return QSize( 0, y );
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ private:
|
||||
QListView* m_view;
|
||||
JobStatusModel* m_model;
|
||||
AnimatedSplitter* m_parent;
|
||||
mutable int m_cachedHeight;
|
||||
|
||||
static JobStatusView* s_instance;
|
||||
};
|
||||
|
@ -181,6 +181,7 @@ Tomahawk::EchonestControl::updateWidgets()
|
||||
input->hide();
|
||||
m_match = QWeakPointer< QWidget >( match );
|
||||
m_input = QWeakPointer< QWidget >( input );
|
||||
m_data.first = m_currentType;
|
||||
} else if( selectedType() == "Artist Description" ) {
|
||||
m_currentType = Echonest::DynamicPlaylist::Description;
|
||||
|
||||
@ -199,6 +200,7 @@ Tomahawk::EchonestControl::updateWidgets()
|
||||
input->hide();
|
||||
m_match = QWeakPointer< QWidget >( match );
|
||||
m_input = QWeakPointer< QWidget >( input );
|
||||
m_data.first = m_currentType;
|
||||
} else if( selectedType() == "User Radio" ) {
|
||||
m_currentType = Echonest::DynamicPlaylist::SourceCatalog;
|
||||
|
||||
@ -246,6 +248,7 @@ Tomahawk::EchonestControl::updateWidgets()
|
||||
input->hide();
|
||||
m_match = QWeakPointer< QWidget >( match );
|
||||
m_input = QWeakPointer< QWidget >( input );
|
||||
m_data.first = m_currentType;
|
||||
} else if( selectedType() == "Variety" ) {
|
||||
m_currentType = Echonest::DynamicPlaylist::Variety;
|
||||
|
||||
@ -266,6 +269,7 @@ Tomahawk::EchonestControl::updateWidgets()
|
||||
input->hide();
|
||||
m_match = QWeakPointer< QWidget >( match );
|
||||
m_input = QWeakPointer< QWidget >( input );
|
||||
m_data.first = m_currentType;
|
||||
} else if( selectedType() == "Adventurousness" ) {
|
||||
m_currentType = Echonest::DynamicPlaylist::Adventurousness;
|
||||
|
||||
@ -287,6 +291,7 @@ Tomahawk::EchonestControl::updateWidgets()
|
||||
input->hide();
|
||||
m_match = QWeakPointer< QWidget >( match );
|
||||
m_input = QWeakPointer< QWidget >( input );
|
||||
m_data.first = m_currentType;
|
||||
} else if( selectedType() == "Tempo" ) {
|
||||
m_currentType = Echonest::DynamicPlaylist::MinTempo;
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "dropjob.h"
|
||||
#include "jobview/JobStatusView.h"
|
||||
#include "jobview/JobStatusModel.h"
|
||||
#include "jobview/ErrorStatusMessage.h"
|
||||
#include "dropjobnotifier.h"
|
||||
#include "viewmanager.h"
|
||||
|
||||
@ -198,6 +199,7 @@ GroovesharkParser::groovesharkLookupFinished()
|
||||
|
||||
} else
|
||||
{
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( tr( "Error fetching Grooveshark information from the network!" ) ) );
|
||||
tLog() << "Error in network request to grooveshark for track decoding:" << r->errorString();
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "sourcelist.h"
|
||||
#include "jobview/JobStatusView.h"
|
||||
#include "jobview/JobStatusModel.h"
|
||||
#include "jobview/ErrorStatusMessage.h"
|
||||
|
||||
#include <qjson/parser.h>
|
||||
|
||||
@ -166,6 +167,7 @@ ItunesParser::itunesResponseLookupFinished()
|
||||
|
||||
} else
|
||||
{
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( tr( "Error fetching iTunes information from the network!" ) ) );
|
||||
tLog() << "Error in network request to Itunes for track decoding:" << r->errorString();
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "dropjob.h"
|
||||
#include "jobview/JobStatusView.h"
|
||||
#include "jobview/JobStatusModel.h"
|
||||
#include "jobview/ErrorStatusMessage.h"
|
||||
#include "dropjobnotifier.h"
|
||||
#include "viewmanager.h"
|
||||
#include "sourcelist.h"
|
||||
@ -189,6 +190,7 @@ RdioParser::rdioReturned()
|
||||
|
||||
} else
|
||||
{
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( tr( "Error fetching Rdio information from the network!" ) ) );
|
||||
tLog() << "Error in network request to Rdio for track decoding:" << r->errorString();
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,9 @@
|
||||
#include "utils/logger.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "query.h"
|
||||
#include "jobview/ErrorStatusMessage.h"
|
||||
#include "jobview/JobStatusModel.h"
|
||||
#include "jobview/JobStatusView.h"
|
||||
|
||||
#include <qjson/parser.h>
|
||||
|
||||
@ -78,6 +81,9 @@ ShortenedLinkParser::lookupFinished()
|
||||
QNetworkReply* r = qobject_cast< QNetworkReply* >( sender() );
|
||||
Q_ASSERT( r );
|
||||
|
||||
if ( r->error() != QNetworkReply::NoError )
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( tr( "Network error parsing shortened link!" ) ) );
|
||||
|
||||
QVariant redir = r->attribute( QNetworkRequest::RedirectionTargetAttribute );
|
||||
if ( redir.isValid() && !redir.toUrl().isEmpty() )
|
||||
{
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "dropjob.h"
|
||||
#include "jobview/JobStatusView.h"
|
||||
#include "jobview/JobStatusModel.h"
|
||||
#include "jobview/ErrorStatusMessage.h"
|
||||
#include "dropjobnotifier.h"
|
||||
#include "viewmanager.h"
|
||||
|
||||
@ -220,6 +221,7 @@ SpotifyParser::spotifyBrowseFinished()
|
||||
|
||||
} else
|
||||
{
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( tr( "Error fetching Spotify information from the network!" ) ) );
|
||||
tLog() << "Error in network request to Spotify for track decoding:" << r->errorString();
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright 2011-2012, Leo Franchi <lfranchi@kde.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
|
||||
@ -26,6 +26,12 @@
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
#include "jobview/JobStatusView.h"
|
||||
#include "jobview/JobStatusModel.h"
|
||||
#include "jobview/ErrorStatusMessage.h"
|
||||
#endif
|
||||
|
||||
#include "sourcelist.h"
|
||||
#include "playlist.h"
|
||||
#include <XspfUpdater.h>
|
||||
@ -33,6 +39,22 @@
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
QString
|
||||
XSPFLoader::errorToString( XSPFErrorCode error )
|
||||
{
|
||||
switch ( error )
|
||||
{
|
||||
case ParseError:
|
||||
return tr( "Failed to parse contents of XSPF playlist" );
|
||||
case InvalidTrackError:
|
||||
return tr( "Some playlist entries were found without artist and track name, they will be omitted");
|
||||
case FetchError:
|
||||
return tr( "Failed to fetch the desired playlist from the network, or the desired file does not exist" );
|
||||
default:
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
XSPFLoader::XSPFLoader( bool autoCreate, bool autoUpdate, QObject *parent )
|
||||
: QObject( parent )
|
||||
, m_autoCreate( autoCreate )
|
||||
@ -98,6 +120,9 @@ void
|
||||
XSPFLoader::reportError()
|
||||
{
|
||||
emit error( FetchError );
|
||||
#ifndef ENABLE_HEADLESS
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( errorToString( FetchError) ) );
|
||||
#endif
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright 2011-2012, Leo Franchi <lfranchi@kde.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
|
||||
@ -49,6 +49,8 @@ public:
|
||||
void setOverrideTitle( const QString& newTitle );
|
||||
void setAutoResolveTracks( bool autoResolve ) { m_autoResolve = autoResolve; }
|
||||
|
||||
static QString errorToString( XSPFErrorCode error );
|
||||
|
||||
signals:
|
||||
void error( XSPFLoader::XSPFErrorCode error );
|
||||
void ok( const Tomahawk::playlist_ptr& );
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "utils/logger.h"
|
||||
#include "tomahawksettings.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QProcess>
|
||||
|
||||
static QString s_macVolumePath = "/Volumes";
|
||||
@ -31,9 +32,12 @@ CheckDirModel::CheckDirModel( QWidget* parent )
|
||||
, m_shownVolumes( false )
|
||||
{
|
||||
#ifdef Q_WS_MAC
|
||||
m_setFilePath = QString( "%1/SetFile" ) .arg( QCoreApplication::applicationDirPath() );
|
||||
m_getFileInfoPath = QString( "%1/GetFileInfo" ).arg( QCoreApplication::applicationDirPath() );
|
||||
|
||||
QProcess* checkVolumeVisible = new QProcess( this );
|
||||
connect( checkVolumeVisible, SIGNAL( readyReadStandardOutput() ), this, SLOT( getFileInfoResult() ) );
|
||||
checkVolumeVisible->start( "GetFileInfo", QStringList() << "-aV" << s_macVolumePath );
|
||||
checkVolumeVisible->start( m_getFileInfoPath, QStringList() << "-aV" << s_macVolumePath );
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -42,7 +46,7 @@ CheckDirModel::~CheckDirModel()
|
||||
#ifdef Q_WS_MAC
|
||||
// reset to previous state
|
||||
if ( m_shownVolumes )
|
||||
QProcess::startDetached( QString( "SetFile -a V %1" ).arg( s_macVolumePath ) );
|
||||
QProcess::startDetached( QString( "%1 -a V %2" ).arg( m_setFilePath).arg( s_macVolumePath ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -60,7 +64,7 @@ CheckDirModel::getFileInfoResult()
|
||||
// Remove the hidden flag for the /Volumnes folder so all mount points are visible in the default (Q)FileSystemModel
|
||||
QProcess* p = new QProcess( this );
|
||||
connect( p, SIGNAL( finished( int, QProcess::ExitStatus ) ), this, SLOT( volumeShowFinished() ) );
|
||||
p->start( QString( "SetFile -a v %1" ).arg( s_macVolumePath ) );
|
||||
p->start( QString( "%1 -a v %2" ).arg( m_setFilePath ).arg( s_macVolumePath ) );
|
||||
m_shownVolumes = true;
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,8 @@ private:
|
||||
QHash<QPersistentModelIndex, Qt::CheckState> m_checkTable;
|
||||
|
||||
bool m_shownVolumes;
|
||||
QString m_setFilePath;
|
||||
QString m_getFileInfoPath;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2012 Leo Franchi <lfranchi@kde.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
|
||||
@ -112,6 +113,20 @@ SearchWidget::changeEvent( QEvent* e )
|
||||
}
|
||||
|
||||
|
||||
Tomahawk::playlistinterface_ptr
|
||||
SearchWidget::playlistInterface() const
|
||||
{
|
||||
return ui->resultsView->playlistInterface();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SearchWidget::jumpToCurrentTrack()
|
||||
{
|
||||
return ui->resultsView->jumpToCurrentTrack();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SearchWidget::onResultsFound( const QList<Tomahawk::result_ptr>& results )
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2012 Leo Franchi <lfranchi@kde.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
|
||||
@ -46,7 +47,7 @@ public:
|
||||
~SearchWidget();
|
||||
|
||||
virtual QWidget* widget() { return this; }
|
||||
virtual Tomahawk::playlistinterface_ptr playlistInterface() const { return Tomahawk::playlistinterface_ptr(); }
|
||||
virtual Tomahawk::playlistinterface_ptr playlistInterface() const;
|
||||
virtual bool isTemporaryPage() const { return true; }
|
||||
|
||||
virtual QString title() const { return QString( tr( "Search: %1" ) ).arg( m_search ); }
|
||||
@ -55,7 +56,7 @@ public:
|
||||
|
||||
virtual bool showStatsBar() const { return false; }
|
||||
|
||||
virtual bool jumpToCurrentTrack() { return false; }
|
||||
virtual bool jumpToCurrentTrack();
|
||||
|
||||
protected:
|
||||
void changeEvent( QEvent* e );
|
||||
|
@ -319,11 +319,14 @@ TomahawkApp::~TomahawkApp()
|
||||
delete AtticaManager::instance();
|
||||
#endif
|
||||
|
||||
delete Pipeline::instance();
|
||||
|
||||
if ( !m_database.isNull() )
|
||||
delete m_database.data();
|
||||
|
||||
delete Pipeline::instance();
|
||||
|
||||
if ( !m_infoSystem.isNull() )
|
||||
delete m_infoSystem.data();
|
||||
|
||||
tLog() << "Finished shutdown.";
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,8 @@ TomahawkTrayIcon::TomahawkTrayIcon( QObject* parent )
|
||||
m_showWindowAction = m_contextMenu->addAction( tr( "Hide Tomahawk Window" ) );
|
||||
m_showWindowAction->setData( true );
|
||||
connect( m_showWindowAction, SIGNAL( triggered() ), this, SLOT( showWindow() ) );
|
||||
|
||||
connect( m_contextMenu, SIGNAL( aboutToShow() ), this, SLOT( menuAboutToShow() ) );
|
||||
#endif
|
||||
|
||||
m_contextMenu->addSeparator();
|
||||
@ -118,6 +120,16 @@ TomahawkTrayIcon::showWindow()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkTrayIcon::menuAboutToShow()
|
||||
{
|
||||
// When using Cmd-H on mac to hide a window, it is an OS-level hide that is different from QWidget::hide().
|
||||
// Qt returns isVisible() == true for windows that are hidden with Cmd-H, which is weird. isActiveWindow() returns
|
||||
// the proper information though.
|
||||
setShowHideWindow( APP->mainWindow()->isActiveWindow() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkTrayIcon::setResult( const Tomahawk::result_ptr& result )
|
||||
{
|
||||
|
@ -46,6 +46,7 @@ private slots:
|
||||
void enablePlay();
|
||||
void enablePause();
|
||||
|
||||
void menuAboutToShow();
|
||||
private:
|
||||
void refreshToolTip();
|
||||
~TomahawkTrayIcon();
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright 2010-2012, Leo Franchi <lfranchi@kde.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
|
||||
@ -58,6 +58,8 @@
|
||||
#include "tomahawksettings.h"
|
||||
#include "sourcelist.h"
|
||||
#include "jobview/JobStatusView.h"
|
||||
#include "jobview/JobStatusModel.h"
|
||||
#include "jobview/ErrorStatusMessage.h"
|
||||
#include "tomahawktrayicon.h"
|
||||
#include "scanmanager.h"
|
||||
#include "tomahawkapp.h"
|
||||
@ -80,6 +82,7 @@ TomahawkWindow::TomahawkWindow( QWidget* parent )
|
||||
, m_searchWidget( 0 )
|
||||
, m_audioControls( new AudioControls( this ) )
|
||||
, m_trayIcon( new TomahawkTrayIcon( this ) )
|
||||
, m_audioRetryCounter( 0 )
|
||||
{
|
||||
setWindowIcon( QIcon( RESPATH "icons/tomahawk-icon-128x128.png" ) );
|
||||
|
||||
@ -570,11 +573,17 @@ TomahawkWindow::onXSPFError( XSPFLoader::XSPFErrorCode error )
|
||||
void
|
||||
TomahawkWindow::onAudioEngineError( AudioEngine::AudioErrorCode /* error */ )
|
||||
{
|
||||
QString msg;
|
||||
#ifdef Q_WS_X11
|
||||
QMessageBox::warning( this, tr( "Playback Error" ), tr( "Sorry, there is a problem accessing your audio device. Make sure you have a suitable Phonon backend and required plugins installed." ), QMessageBox::Ok );
|
||||
msg = tr( "Sorry, there is a problem accessing your audio device or the desired track, current track will be skipped. Make sure you have a suitable Phonon backend and required plugins installed." );
|
||||
#else
|
||||
QMessageBox::warning( this, tr( "Playback Error" ), tr( "Sorry, there is a problem accessing your audio device." ), QMessageBox::Ok );
|
||||
msg = tr( "Sorry, there is a problem accessing your audio device or the desired track, current track will be skipped." );
|
||||
#endif
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( msg, 15 ) );
|
||||
|
||||
if ( m_audioRetryCounter < 3 )
|
||||
AudioEngine::instance()->play();
|
||||
m_audioRetryCounter++;
|
||||
}
|
||||
|
||||
|
||||
@ -654,6 +663,7 @@ TomahawkWindow::playlistCreateDialogFinished( int ret )
|
||||
void
|
||||
TomahawkWindow::audioStarted()
|
||||
{
|
||||
m_audioRetryCounter = 0;
|
||||
ui->actionPlay->setText( tr( "Pause" ) );
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright 2010-2012, Leo Franchi <lfranchi@kde.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
|
||||
@ -145,6 +145,7 @@ private:
|
||||
|
||||
Tomahawk::result_ptr m_currentTrack;
|
||||
QString m_windowTitle;
|
||||
int m_audioRetryCounter;
|
||||
};
|
||||
|
||||
#endif // TOMAHAWKWINDOW_H
|
||||
|
@ -88,11 +88,11 @@
|
||||
}
|
||||
-(void)printBacktrace;
|
||||
{
|
||||
int x;
|
||||
for(x = 3; x < frameCount; x++) {
|
||||
if(frameStrings[x] == NULL) { break; }
|
||||
printf("%s\n", frameStrings[x]);
|
||||
}
|
||||
int x;
|
||||
for(x = 3; x < frameCount; x++) {
|
||||
if(frameStrings[x] == NULL) { break; }
|
||||
printf("%s\n", frameStrings[x]);
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
|
11
thirdparty/SPMediaKeyTap/SPMediaKeyTap.h
vendored
11
thirdparty/SPMediaKeyTap/SPMediaKeyTap.h
vendored
@ -31,4 +31,13 @@
|
||||
-(void)mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event;
|
||||
@end
|
||||
|
||||
extern NSString *kMediaKeyUsingBundleIdentifiersDefaultsKey;
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern NSString *kMediaKeyUsingBundleIdentifiersDefaultsKey;
|
||||
extern NSString *kIgnoreMediaKeysDefaultsKey;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
36
thirdparty/SPMediaKeyTap/SPMediaKeyTap.m
vendored
36
thirdparty/SPMediaKeyTap/SPMediaKeyTap.m
vendored
@ -28,6 +28,9 @@ static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEv
|
||||
[self startWatchingAppSwitching];
|
||||
singleton = self;
|
||||
_mediaKeyAppList = [NSMutableArray new];
|
||||
_tapThreadRL=nil;
|
||||
_eventPort=nil;
|
||||
_eventPortSource=nil;
|
||||
return self;
|
||||
}
|
||||
-(void)dealloc;
|
||||
@ -58,6 +61,9 @@ static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEv
|
||||
}
|
||||
|
||||
-(void)startWatchingMediaKeys;{
|
||||
// Prevent having multiple mediaKeys threads
|
||||
[self stopWatchingMediaKeys];
|
||||
|
||||
[self setShouldInterceptMediaKeyEvents:YES];
|
||||
|
||||
// Add an event tap to intercept the system defined media key events
|
||||
@ -78,6 +84,22 @@ static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEv
|
||||
-(void)stopWatchingMediaKeys;
|
||||
{
|
||||
// TODO<nevyn>: Shut down thread, remove event tap port and source
|
||||
|
||||
if(_tapThreadRL){
|
||||
CFRunLoopStop(_tapThreadRL);
|
||||
_tapThreadRL=nil;
|
||||
}
|
||||
|
||||
if(_eventPort){
|
||||
CFMachPortInvalidate(_eventPort);
|
||||
CFRelease(_eventPort);
|
||||
_eventPort=nil;
|
||||
}
|
||||
|
||||
if(_eventPortSource){
|
||||
CFRelease(_eventPortSource);
|
||||
_eventPortSource=nil;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
@ -90,7 +112,9 @@ static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEv
|
||||
return NO;
|
||||
#else
|
||||
// XXX(nevyn): MediaKey event tap doesn't work on 10.4, feel free to figure out why if you have the energy.
|
||||
return floor(NSAppKitVersionNumber) >= 949/*NSAppKitVersionNumber10_5*/;
|
||||
return
|
||||
![[NSUserDefaults standardUserDefaults] boolForKey:kIgnoreMediaKeysDefaultsKey]
|
||||
&& floor(NSAppKitVersionNumber) >= 949/*NSAppKitVersionNumber10_5*/;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -108,6 +132,14 @@ static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEv
|
||||
@"com.apple.Aperture",
|
||||
@"com.plexsquared.Plex",
|
||||
@"com.soundcloud.desktop",
|
||||
@"org.niltsh.MPlayerX",
|
||||
@"com.ilabs.PandorasHelper",
|
||||
@"com.mahasoftware.pandabar",
|
||||
@"com.bitcartel.pandorajam",
|
||||
@"org.clementine-player.clementine",
|
||||
@"fm.last.Last.fm",
|
||||
@"com.beatport.BeatportPro",
|
||||
@"com.Timenut.SongKey",
|
||||
@"com.macromedia.fireworks", // the tap messes up their mouse input
|
||||
nil
|
||||
];
|
||||
@ -213,6 +245,8 @@ static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEv
|
||||
#pragma mark Task switching callbacks
|
||||
|
||||
NSString *kMediaKeyUsingBundleIdentifiersDefaultsKey = @"SPApplicationsNeedingMediaKeys";
|
||||
NSString *kIgnoreMediaKeysDefaultsKey = @"SPIgnoreMediaKeys";
|
||||
|
||||
|
||||
|
||||
-(void)mediaKeyAppListChanged;
|
||||
|
Loading…
x
Reference in New Issue
Block a user