diff --git a/CMakeLists.txt b/CMakeLists.txt index 573baba53..c2c0a72f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,9 @@ macro_log_feature(Boost_FOUND "Boost" "Provides free peer-reviewed portable C++ macro_optional_find_package(QCA2) macro_log_feature(QCA2_FOUND "QCA2" "Provides encryption and signing functions required for Grooveshark resolver" "http://delta.affinix.com/qca/" FALSE "" "") +macro_optional_find_package(LibAttica) +macro_log_feature(LIBATTICA_FOUND "libattica" "Provides support for automatic fetching and managing of resolvers from the tomahawk website" "https://projects.kde.org/projects/kdesupport/attica" FALSE "" "") + # required #While we distribute our own liblastfm2, don't need to look for it #macro_optional_find_package(LibLastFm 0.3.3) diff --git a/CMakeModules/FindLibAttica.cmake b/CMakeModules/FindLibAttica.cmake new file mode 100644 index 000000000..bb919da77 --- /dev/null +++ b/CMakeModules/FindLibAttica.cmake @@ -0,0 +1,63 @@ +# Try to find the Attica library +# Once done this will define +# +# LIBATTICA_FOUND Indicates that Attica was found +# LIBATTICA_LIBRARIES Libraries needed to use Attica +# LIBATTICA_LIBRARY_DIRS Paths needed for linking against Attica +# LIBATTICA_INCLUDE_DIR Path needed for finding Attica include files +# +# The minimum required version of LibAttica can be specified using the +# standard syntax, e.g. find_package(LibAttica 0.20) + +# Copyright (c) 2009 Frederik Gladhorn +# +# Redistribution and use is allowed according to the terms of the BSD license. + +# Support LIBATTICA_MIN_VERSION for compatibility: +IF(NOT LibAttica_FIND_VERSION) + SET(LibAttica_FIND_VERSION "${LIBATTICA_MIN_VERSION}") +ENDIF(NOT LibAttica_FIND_VERSION) + +# the minimum version of LibAttica we require +IF(NOT LibAttica_FIND_VERSION) + SET(LibAttica_FIND_VERSION "0.1.0") +ENDIF(NOT LibAttica_FIND_VERSION) + + +IF (NOT WIN32) + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + FIND_PACKAGE(PkgConfig) + PKG_CHECK_MODULES(PC_LIBATTICA QUIET libattica) + SET(LIBATTICA_DEFINITIONS ${PC_ATTICA_CFLAGS_OTHER}) +ENDIF (NOT WIN32) + +FIND_PATH(LIBATTICA_INCLUDE_DIR attica/provider.h + HINTS + ${PC_LIBATTICA_INCLUDEDIR} + ${PC_LIBATTICA_INCLUDE_DIRS} + PATH_SUFFIXES attica + ) + +# Store the version number in the cache, so we don't have to search everytime: +IF(LIBATTICA_INCLUDE_DIR AND NOT LIBATTICA_VERSION) + FILE(READ ${LIBATTICA_INCLUDE_DIR}/attica/version.h LIBATTICA_VERSION_CONTENT) + STRING (REGEX MATCH "LIBATTICA_VERSION_STRING \".*\"\n" LIBATTICA_VERSION_MATCH "${LIBATTICA_VERSION_CONTENT}") + IF(LIBATTICA_VERSION_MATCH) + STRING(REGEX REPLACE "LIBATTICA_VERSION_STRING \"(.*)\"\n" "\\1" _LIBATTICA_VERSION ${LIBATTICA_VERSION_MATCH}) + ENDIF(LIBATTICA_VERSION_MATCH) + SET(LIBATTICA_VERSION "${_LIBATTICA_VERSION}" CACHE STRING "Version number of LibAttica" FORCE) +ENDIF(LIBATTICA_INCLUDE_DIR AND NOT LIBATTICA_VERSION) + + +FIND_LIBRARY(LIBATTICA_LIBRARIES NAMES attica libattica + HINTS + ${PC_LIBATTICA_LIBDIR} + ${PC_LIBATTICA_LIBRARY_DIRS} + ) + +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibAttica REQUIRED_VARS LIBATTICA_LIBRARIES LIBATTICA_INCLUDE_DIR + VERSION_VAR LIBATTICA_VERSION) + +MARK_AS_ADVANCED(LIBATTICA_INCLUDE_DIR LIBATTICA_LIBRARIES) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 68cbe3cee..f82f2b112 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -78,6 +78,11 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui} settingslistdelegate.cpp resolversmodel.cpp tomahawkwindow.cpp + + GetNewStuffDialog.cpp + GetNewStuffDelegate.cpp + GetNewStuffModel.cpp + AtticaManager.cpp ) SET( tomahawkHeaders ${tomahawkHeaders} @@ -126,6 +131,11 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui} resolversmodel.h delegateconfigwrapper.h tomahawkwindow.h + + GetNewStuffDialog.h + GetNewStuffDelegate.h + GetNewStuffModel.h + AtticaManager.h ) SET( tomahawkUI ${tomahawkUI} @@ -135,6 +145,8 @@ SET( tomahawkUI ${tomahawkUI} proxydialog.ui audiocontrols.ui + + GetNewStuffDialog.ui ) INCLUDE_DIRECTORIES( @@ -194,6 +206,10 @@ IF(QCA2_FOUND) INCLUDE_DIRECTORIES( ${QCA2_INCLUDE_DIR} ) ENDIF(QCA2_FOUND) +IF(LIBATTICA_FOUND) + INCLUDE_DIRECTORIES( ${LIBATTICA_INCLUDE_DIR} ) +ENDIF(LIBATTICA_FOUND) + kde4_add_app_icon( tomahawkSources "${CMAKE_SOURCE_DIR}/data/icons/tomahawk-icon-*.png" ) qt4_add_resources( RC_SRCS "../resources.qrc" ) qt4_wrap_cpp( tomahawkMoc ${tomahawkHeaders} ) @@ -238,6 +254,11 @@ IF(QCA2_FOUND) SET(LINK_LIBRARIES ${LINK_LIBRARIES} ${QCA2_LIBRARIES} ) ENDIF(QCA2_FOUND) +IF(LIBATTICA_FOUND) + SET(LINK_LIBRARIES ${LINK_LIBRARIES} ${LIBATTICA_LIBRARIES} ) +ENDIF(LIBATTICA_FOUND) + + TARGET_LINK_LIBRARIES( tomahawk ${LINK_LIBRARIES} ${TOMAHAWK_LIBRARIES} diff --git a/src/GetNewStuffDelegate.cpp b/src/GetNewStuffDelegate.cpp new file mode 100644 index 000000000..fcf596cde --- /dev/null +++ b/src/GetNewStuffDelegate.cpp @@ -0,0 +1,245 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Leo Franchi + * + * 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 . + */ + +#include "GetNewStuffDelegate.h" + +#include "GetNewStuffModel.h" +#include "utils/tomahawkutils.h" + +#include +#include +#include + +#define PADDING 4 + +#ifdef Q_WS_MAC +#define SIZEHINT_HEIGHT 70 +#else +#define SIZEHINT_HEIGHT 60 +#endif + +GetNewStuffDelegate::GetNewStuffDelegate( QObject* parent ) + : QStyledItemDelegate ( parent ) + , m_widestTextWidth( 0 ) +{ + m_defaultCover.load( RESPATH "images/sipplugin-online.png" ); + m_ratingStarPositive.load( RESPATH "images/loved.png" ); + m_ratingStarNegative.load( RESPATH "images/not-loved.png" ); + + m_ratingStarPositive = m_ratingStarPositive.scaled( 8, 8, Qt::KeepAspectRatio, Qt::SmoothTransformation ); + m_ratingStarNegative = m_ratingStarNegative.scaled( 8, 8, Qt::KeepAspectRatio, Qt::SmoothTransformation ); + const int w = SIZEHINT_HEIGHT - 2*PADDING; + m_defaultCover = m_defaultCover.scaled( w, w, Qt::KeepAspectRatio, Qt::SmoothTransformation ); + + // save the widest wifth + QFont f( QApplication::font() ); + f.setPointSize( f.pointSize() - 1 ); + QFontMetrics fm( f ); + QStringList l = QStringList() << tr( "Installed" ) << tr( "Installing" ) << tr( "Failed" ) << tr( "Uninstalling" ); + foreach ( const QString& str, l ) + { + if ( fm.width( str ) > m_widestTextWidth ) + m_widestTextWidth = fm.width( str ); + } +} + +void +GetNewStuffDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const +{ + QStyleOptionViewItemV4 opt = option; + initStyleOption( &opt, index ); + + QApplication::style()->drawPrimitive( QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget ); + + painter->setRenderHint( QPainter::Antialiasing ); + + QFont titleFont = opt.font; + titleFont.setBold( true ); + titleFont.setPointSize( titleFont.pointSize() + 2 ); + QFontMetrics titleMetrics( titleFont ); + + QFont authorFont = opt.font; + authorFont.setItalic( true ); + authorFont.setPointSize( authorFont.pointSize() - 1 ); + QFontMetrics authorMetrics( authorFont ); + + QFont descFont = authorFont; + descFont.setItalic( false ); + QFontMetrics descMetrics( descFont ); + + QFont installFont = opt.font; + installFont.setPointSize( installFont.pointSize() - 1 ); + QFontMetrics installMetrics( descFont ); + + const int height = opt.rect.height(); + const int center = height / 2 + opt.rect.top(); + + // Pixmap + QPixmap p = index.data( Qt::DecorationRole ).value< QPixmap >(); + const int pixmapWidth = height - 2*PADDING; + QRect pixmapRect( PADDING, PADDING + opt.rect.top(), pixmapWidth, pixmapWidth ); + if ( p.isNull() ) // default image... TODO + p = m_defaultCover; + else + p = p.scaled( pixmapRect.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation ); + + painter->drawPixmap( pixmapRect, p ); + + // Go from right edge now, stars, install button, and downloaded info + + // install / status button + GetNewStuffModel::States state = static_cast< GetNewStuffModel::States >( index.data( GetNewStuffModel::StateRole ).toInt() ); + QString actionText; + switch( state ) + { + case GetNewStuffModel::Uninstalled: + actionText = tr( "Install" ); + break; + case GetNewStuffModel::Installing: + actionText = tr( "Installing" ); + break; + case GetNewStuffModel::Failed: + actionText = tr( "Failed" ); + break; + case GetNewStuffModel::Installed: + actionText = tr( "Uninstall" ); + break; + } + + const int btnWidth = m_widestTextWidth + 7; + const int leftEdge = opt.rect.width() - PADDING - btnWidth - 3; + const QRect btnRect( leftEdge, center - ( installMetrics.height() + 4 ) / 2, btnWidth, installMetrics.height() + 4 ); + m_cachedButtonRects[ QPair(index.row(), index.column()) ] = btnRect; + + QPen saved = painter->pen(); + painter->setPen( opt.palette.color( QPalette::Active, QPalette::AlternateBase ) ); + + QPainterPath btnPath; + const int radius = 3; + //btnPath.addRoundedRect( btnRect, 3, 3 ); + // draw top half gradient + const int btnCenter = btnRect.bottom() - ( btnRect.height() / 2 ); + btnPath.moveTo( btnRect.left(), btnCenter ); + btnPath.lineTo( btnRect.left(), btnRect.top() + radius ); + btnPath.quadTo( QPoint( btnRect.topLeft() ), QPoint( btnRect.left() + radius, btnRect.top() ) ); + btnPath.lineTo( btnRect.right() - radius, btnRect.top() ); + btnPath.quadTo( QPoint( btnRect.topRight() ), QPoint( btnRect.right(), btnRect.top() + radius ) ); + btnPath.lineTo( btnRect.right(),btnCenter ); + btnPath.lineTo( btnRect.left(), btnCenter ); + + QLinearGradient g; + g.setColorAt( 0, QColor(54, 127, 211) ); + g.setColorAt( 0.5, QColor(43, 104, 182) ); + //painter->setPen( bg.darker() ); + painter->fillPath( btnPath, g ); + //painter->drawPath( btnPath ); + + btnPath = QPainterPath(); + btnPath.moveTo( btnRect.left(), btnCenter ); + btnPath.lineTo( btnRect.left(), btnRect.bottom() - radius ); + btnPath.quadTo( QPoint( btnRect.bottomLeft() ), QPoint( btnRect.left() + radius, btnRect.bottom() ) ); + btnPath.lineTo( btnRect.right() - radius, btnRect.bottom() ); + btnPath.quadTo( QPoint( btnRect.bottomRight() ), QPoint( btnRect.right(), btnRect.bottom() - radius ) ); + btnPath.lineTo( btnRect.right(), btnCenter ); + btnPath.lineTo( btnRect.left(), btnCenter ); + + g.setColorAt( 0, QColor(34, 85, 159) ); + g.setColorAt( 0.5, QColor(35, 79, 147) ); + painter->fillPath( btnPath, g ); + + painter->setFont( installFont ); + painter->drawText( btnRect, Qt::AlignCenter, actionText ); + + painter->setPen( saved ); + // rating stars + int rating = index.data( GetNewStuffModel::RatingRole ).toInt(); + const int paddingBetweenStars = 2; + const int ratingWidth = 5 * ( m_ratingStarPositive.width() + paddingBetweenStars ); + const int ratingY = ( btnRect.y() - ( btnRect.top() - opt.rect.y() ) / 2 ) - m_ratingStarNegative.height() / 2; + int runningEdge = ( btnRect.right() - btnRect.width() / 2 ) - ratingWidth / 2; + for ( int i = 1; i < 6; i++ ) + { + QRect r( runningEdge, btnRect.top() - m_ratingStarPositive.height() - PADDING, m_ratingStarPositive.width(), m_ratingStarPositive.height() ); + if ( i <= rating ) // positive star + painter->drawPixmap( r, m_ratingStarPositive ); + else + painter->drawPixmap( r, m_ratingStarNegative ); + runningEdge += m_ratingStarPositive.width() + paddingBetweenStars; + } + + // downloaded num times, underneath button + QString count = tr( "%1 downloads" ).arg( index.data( GetNewStuffModel::DownloadCounterRole ).toInt() ); + const QRect countRect( btnRect.left(), btnRect.bottom() + PADDING, btnRect.width(), opt.rect.bottom() - PADDING - btnRect.bottom() ); + QFont countFont = descFont; + countFont.setPointSize( countFont.pointSize() - 2 ); + countFont.setBold( true ); + painter->setFont( countFont ); + painter->drawText( countRect, Qt::AlignCenter | Qt::TextWordWrap, count ); + + // author and version + QString author = index.data( GetNewStuffModel::AuthorRole ).toString(); + const int authorWidth = authorMetrics.width( author ); + const int topTextLine = opt.rect.top() + PADDING; + const QRect authorRect( btnRect.x() - 3*PADDING - authorWidth, topTextLine, authorWidth + 6, authorMetrics.height() ); + painter->setFont( authorFont ); + painter->drawText( authorRect, Qt::AlignCenter, author ); + + const QRect versionRect = authorRect.translated( 0, authorRect.height() ); + QString version = index.data( GetNewStuffModel::VersionRole ).toString(); + painter->drawText( versionRect, Qt::AlignCenter, version ); + + // title + QString title = index.data( Qt::DisplayRole ).toString(); + const int rightTitleEdge = authorRect.left() - PADDING; + const int leftTitleEdge = pixmapRect.right() + PADDING; + const QRect textRect( leftTitleEdge, topTextLine, rightTitleEdge - leftTitleEdge, versionRect.bottom() - opt.rect.top() - PADDING ); + painter->setFont( titleFont ); + painter->drawText( textRect, Qt::AlignVCenter | Qt::AlignLeft, title ); + + // description + QString desc = index.data( GetNewStuffModel::DescriptionRole ).toString(); + const int descWidth = btnRect.left() - leftTitleEdge - PADDING; + const QRect descRect( leftTitleEdge, versionRect.bottom(), descWidth, opt.rect.bottom() - versionRect.bottom() + PADDING ); + painter->setFont( descFont ); + painter->drawText( descRect, Qt::AlignLeft | Qt::TextWordWrap, desc ); +} + + +QSize +GetNewStuffDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const +{ + return QSize( 200, SIZEHINT_HEIGHT ); +} + +bool +GetNewStuffDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index ) +{ + if ( event->type() == QEvent::MouseButtonRelease && m_cachedButtonRects.contains( QPair( index.row(), index.column() ) ) ) + { + QRect rect = m_cachedButtonRects[ QPair( index.row(), index.column() ) ]; + QMouseEvent* me = static_cast< QMouseEvent* >( event ); + + if ( rect.contains( me->pos() ) ) + { + model->setData( index, true ); + + return true; + } + } + return false; +} diff --git a/src/GetNewStuffDelegate.h b/src/GetNewStuffDelegate.h new file mode 100644 index 000000000..2677d2856 --- /dev/null +++ b/src/GetNewStuffDelegate.h @@ -0,0 +1,46 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Leo Franchi + * + * 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 . + */ + +#ifndef GETNEWSTUFFDELEGATE_H +#define GETNEWSTUFFDELEGATE_H + +#include + + +class +GetNewStuffDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + explicit GetNewStuffDelegate( 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; + +protected: + virtual bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index ); + +private: + QPixmap m_defaultCover; + QPixmap m_ratingStarPositive; + QPixmap m_ratingStarNegative; + + int m_widestTextWidth; + mutable QHash< QPair, QRect > m_cachedButtonRects; +}; + +#endif // GETNEWSTUFFDELEGATE_H diff --git a/src/GetNewStuffDialog.cpp b/src/GetNewStuffDialog.cpp new file mode 100644 index 000000000..2b4bf0c62 --- /dev/null +++ b/src/GetNewStuffDialog.cpp @@ -0,0 +1,49 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2011, Leo Franchi + * + * 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 . + */ + +#include "GetNewStuffDialog.h" + +#include "ui_GetNewStuffDialog.h" +#include "GetNewStuffDelegate.h" +#include "GetNewStuffModel.h" + +GetNewStuffDialog::GetNewStuffDialog( QWidget *parent, Qt::WindowFlags f ) + : QDialog( parent, f ) + , ui( new Ui::GetNewStuffDialog ) + , m_model( new GetNewStuffModel( this ) ) +{ + ui->setupUi( this ); + + ui->listView->setModel( m_model ); + ui->listView->setItemDelegate( new GetNewStuffDelegate( ui->listView ) ); + +#ifdef Q_WS_MAC + setMinimumSize( 510, 350 ); + setMaximumSize( 510, 350 ); + setSizeGripEnabled( false ); + + ui->listView->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel ); + ui->listView->setAttribute( Qt::WA_MacShowFocusRect, false ); +#endif + +} + +GetNewStuffDialog::~GetNewStuffDialog() +{ + delete ui; +} diff --git a/src/GetNewStuffDialog.h b/src/GetNewStuffDialog.h new file mode 100644 index 000000000..a0e195a8d --- /dev/null +++ b/src/GetNewStuffDialog.h @@ -0,0 +1,41 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2011, Leo Franchi + * + * 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 . + */ + +#ifndef GETNEWSTUFFDIALOG_H +#define GETNEWSTUFFDIALOG_H + +#include + +class GetNewStuffModel; +namespace Ui { + class GetNewStuffDialog; +} + +class GetNewStuffDialog : public QDialog +{ + Q_OBJECT +public: + explicit GetNewStuffDialog( QWidget *parent = 0, Qt::WindowFlags f = 0 ); + ~GetNewStuffDialog(); + +private: + Ui::GetNewStuffDialog *ui; + GetNewStuffModel* m_model; +}; + +#endif // GETNEWSTUFFDIALOG_H diff --git a/src/GetNewStuffDialog.ui b/src/GetNewStuffDialog.ui new file mode 100644 index 000000000..af7c4a2ac --- /dev/null +++ b/src/GetNewStuffDialog.ui @@ -0,0 +1,67 @@ + + + GetNewStuffDialog + + + + 0 + 0 + 389 + 270 + + + + Dialog + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + GetNewStuffDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + GetNewStuffDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/GetNewStuffModel.cpp b/src/GetNewStuffModel.cpp new file mode 100644 index 000000000..f4e935fbf --- /dev/null +++ b/src/GetNewStuffModel.cpp @@ -0,0 +1,102 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Leo Franchi + * + * 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 . + */ + +#include "GetNewStuffModel.h" + +#include "utils/tomahawkutils.h" +#include "utils/logger.h" + +#include +#include +#include "AtticaManager.h" + +GetNewStuffModel::GetNewStuffModel( QObject* parent ) + : QAbstractListModel ( parent ) +{ + m_clicked = false; + + if ( AtticaManager::instance()->resolversLoaded() ) + m_contentList = AtticaManager::instance()->resolvers(); + + connect( AtticaManager::instance(), SIGNAL( resolversReloaded( Attica::Content::List ) ), this, SLOT( resolversReloaded( Attica::Content::List ) ) ); + +} + +GetNewStuffModel::~GetNewStuffModel() +{ +} + +void +GetNewStuffModel::resolversReloaded( const Attica::Content::List& resolvers ) +{ + beginResetModel(); + m_contentList = resolvers; + endResetModel(); +} + + +QVariant +GetNewStuffModel::data( const QModelIndex& index, int role ) const +{ + if ( !index.isValid() || !hasIndex( index.row(), index.column(), index.parent() ) ) + return QVariant(); + + Attica::Content resolver = m_contentList[ index.row() ]; + // TODO use attica + switch ( role ) + { + case Qt::DisplayRole: + return resolver.name(); + case Qt::DecorationRole: + return QVariant::fromValue< QPixmap >( QPixmap( RESPATH "images/delegate-add.png" ) ); + case DownloadUrlRole: + // TODO + return QUrl(); + case RatingRole: + return resolver.rating() / 20; // rating is out of 100 + case DownloadCounterRole: + return resolver.downloads(); + case VersionRole: + return resolver.version(); + case DescriptionRole: + return resolver.description(); + case TypeRole: + return ResolverType; + case AuthorRole: + return resolver.author(); + case StateRole: + return m_clicked ? Installed : Uninstalled; + } + return QVariant(); +} + +int +GetNewStuffModel::rowCount( const QModelIndex& parent ) const +{ + return m_contentList.count(); +} + +bool +GetNewStuffModel::setData( const QModelIndex &index, const QVariant &value, int role ) +{ + // the install/uninstall button was clicked + m_clicked = !m_clicked; + emit dataChanged( index, index ); + + return true; +} diff --git a/src/GetNewStuffModel.h b/src/GetNewStuffModel.h new file mode 100644 index 000000000..b7f4d6401 --- /dev/null +++ b/src/GetNewStuffModel.h @@ -0,0 +1,70 @@ +/* === This file is part of Tomahawk Player - === + * + * Copyright 2010-2011, Leo Franchi + * + * 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 . + */ + +#ifndef GETNEWSTUFFMODEL_H +#define GETNEWSTUFFMODEL_H + +#include + +#include + +class GetNewStuffModel: public QAbstractListModel +{ + Q_OBJECT +public: + enum NewStuffRoles { + // DisplayRole is title + // DecorationRole is qicon for item + DownloadUrlRole = Qt::UserRole + 1, + RatingRole = Qt::UserRole + 2, + DownloadCounterRole = Qt::UserRole + 3, + VersionRole = Qt::UserRole + 4, + DescriptionRole = Qt::UserRole + 5, + TypeRole = Qt::UserRole + 6, // Category in attica-speak. What sort of item this is (resolver, etc). + AuthorRole = Qt::UserRole + 7, + StateRole = Qt::UserRole + 8 + }; + + enum Types { + ResolverType = 0, + }; + + enum States { + Uninstalled = 0, + Installing = 1, + Failed = 2, + Installed = 3 + }; + + explicit GetNewStuffModel( QObject* parent = 0 ); + virtual ~GetNewStuffModel(); + + virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const; + virtual int rowCount( const QModelIndex& parent = QModelIndex() ) const; + virtual bool setData( const QModelIndex &index, const QVariant &value, int role ); + +private slots: + void resolversReloaded( const Attica::Content::List& ); + +private: + bool m_clicked; + + Attica::Content::List m_contentList; +}; + +#endif // GETNEWSTUFFMODEL_H diff --git a/src/libtomahawk/tomahawksettings.cpp b/src/libtomahawk/tomahawksettings.cpp index 302c0068f..4d58964b7 100644 --- a/src/libtomahawk/tomahawksettings.cpp +++ b/src/libtomahawk/tomahawksettings.cpp @@ -848,6 +848,28 @@ TomahawkSettings::setEnabledScriptResolvers( const QStringList& resolvers ) setValue( "script/loadedresolvers", resolvers ); } +void +TomahawkSettings::addAtticaInstalledResolver ( const QString& resolver ) +{ + QStringList resolvers = value( "script/atticainstalled", QStringList() ); + resolvers << resolver; + setValue( "script/atticainstalled", resolvers ); +} + +QStringList +TomahawkSettings::atticaInstalledResolvers ( const QStringList& resolvers ) const +{ + return value( "script/atticainstalled", QString() ); +} + +void +TomahawkSettings::removeAtticaInstalledResolver( const QString& resolver ) +{ + QStringList resolvers = value( "script/atticainstalled", QStringList() ); + resolvers.removeAll( resolver ); + setValue( "script/atticainstalled", resolvers ); +} + QString TomahawkSettings::scriptDefaultPath() const diff --git a/src/libtomahawk/tomahawksettings.h b/src/libtomahawk/tomahawksettings.h index bdf3ee806..f294fab00 100644 --- a/src/libtomahawk/tomahawksettings.h +++ b/src/libtomahawk/tomahawksettings.h @@ -184,7 +184,10 @@ public: QStringList enabledScriptResolvers() const; void setEnabledScriptResolvers( const QStringList& resolvers ); - // Default paths + QStringList atticaInstalledResolvers( const QStringList& resolvers ) const; + void addAtticaInstalledResolver( const QString& resolver ); + void removeAtticaInstalledResolver( const QString& resolver ); + QString scriptDefaultPath() const; void setScriptDefaultPath( const QString& path ); QString playlistDefaultPath() const; diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp index 1fb34a068..519667392 100644 --- a/src/settingsdialog.cpp +++ b/src/settingsdialog.cpp @@ -52,6 +52,7 @@ #include "ui_proxydialog.h" #include "ui_stackedsettingsdialog.h" #include +#include "GetNewStuffDialog.h" static QString md5( const QByteArray& src ) @@ -189,6 +190,7 @@ SettingsDialog::SettingsDialog( QWidget *parent ) m_resolversModel = new ResolversModel( s->allScriptResolvers(), s->enabledScriptResolvers(), this ); ui->scriptList->setModel( m_resolversModel ); + connect( ui->getMoreResolvers, SIGNAL( clicked() ), this, SLOT( getMoreResolvers() ) ); connect( ui->scriptList->selectionModel(), SIGNAL( selectionChanged( QItemSelection,QItemSelection ) ), this, SLOT( scriptSelectionChanged() ) ); connect( ui->addScript, SIGNAL( clicked( bool ) ), this, SLOT( addScriptResolver() ) ); connect( ui->removeScript, SIGNAL( clicked( bool ) ), this, SLOT( removeScriptResolver() ) ); @@ -538,6 +540,21 @@ SettingsDialog::removeScriptResolver() } } +void +SettingsDialog::getMoreResolvers() +{ +#ifdef Q_OS_MAC + GetNewStuffDialog* diag = new GetNewStuffDialog( this, Qt::Sheet ); + connect( diag, SIGNAL( finished( int ) ), this, SLOT( getMoreResolversFinished(int))); + + diag->show(); +#else + GetNewStuffDialog diag( this ); + int ret = diag.exec(); +#endif + +} + void SettingsDialog::scriptSelectionChanged() @@ -552,6 +569,12 @@ SettingsDialog::scriptSelectionChanged() } } +void +SettingsDialog::getMoreResolversFinished( int ret ) +{ + +} + void SettingsDialog::openResolverConfig( const QString& resolver ) diff --git a/src/settingsdialog.h b/src/settingsdialog.h index fea8f5592..6a990079b 100644 --- a/src/settingsdialog.h +++ b/src/settingsdialog.h @@ -84,6 +84,9 @@ private slots: void addScriptResolver(); void scriptSelectionChanged(); void removeScriptResolver(); + void getMoreResolvers(); + void getMoreResolversFinished( int ); + void openResolverConfig( const QString& ); void sipItemClicked ( const QModelIndex& ); void openSipConfig( SipPlugin* ); diff --git a/src/stackedsettingsdialog.ui b/src/stackedsettingsdialog.ui index 961b3d6b1..4f4feffb4 100644 --- a/src/stackedsettingsdialog.ui +++ b/src/stackedsettingsdialog.ui @@ -7,7 +7,7 @@ 0 0 641 - 393 + 399 @@ -100,7 +100,7 @@ - 1 + 3 @@ -508,6 +508,13 @@ + + + + Get more resolvers... + + + diff --git a/src/tomahawkapp.cpp b/src/tomahawkapp.cpp index 8dce6460a..5ce3f2e49 100644 --- a/src/tomahawkapp.cpp +++ b/src/tomahawkapp.cpp @@ -53,6 +53,7 @@ #include "globalactionmanager.h" #include "database/localcollection.h" #include "musicscanner.h" +#include "AtticaManager.h" #include "audio/audioengine.h" #include "utils/xspfloader.h" @@ -231,6 +232,9 @@ TomahawkApp::init() tDebug() << "Init Pipeline."; initPipeline(); + // load remote list of resolvers able to be installed + AtticaManager::instance(); + if ( arguments().contains( "--http" ) || TomahawkSettings::instance()->value( "network/http", true ).toBool() ) { initHTTP(); @@ -275,6 +279,8 @@ TomahawkApp::~TomahawkApp() delete m_mainwindow; #endif + delete AtticaManager::instance(); + if ( !m_audioEngine.isNull() ) delete m_audioEngine.data();