1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-03-18 23:09:42 +01:00

Work to add setData to the model, and hook up model to some signals

This commit is contained in:
Leo Franchi 2012-02-03 17:19:04 -05:00
parent daa6b7b841
commit 34dbc50b3a
18 changed files with 543 additions and 1365 deletions

View File

@ -20,6 +20,7 @@
#include <QApplication>
#include <QPainter>
#include <QMouseEvent>
#include "accounts/AccountModel.h"
#include "accounts/Account.h"
@ -50,7 +51,7 @@ using namespace Tomahawk;
using namespace Accounts;
AccountDelegate::AccountDelegate( QObject* parent )
: ConfigDelegateBase ( parent )
: QStyledItemDelegate ( parent )
, m_widestTextWidth( 0 )
{
@ -87,12 +88,6 @@ AccountDelegate::AccountDelegate( QObject* parent )
}
}
bool
AccountDelegate::editorEvent ( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index )
{
return ConfigDelegateBase::editorEvent( event, model, option, index );
}
QSize
AccountDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
@ -125,131 +120,6 @@ AccountDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option,
paintChild( painter, opt, index );
return;
// const QRect itemRect = opt.rect;
// const int top = itemRect.top();
// const int mid = itemRect.height() / 2;
// const int quarter = mid - ( itemRect.height() / 4 );
//
// // one line bold for account name
// // space below it for online/offline status
// // checkbox, icon, name/status, features, config icon
// QFont name = opt.font;
// name.setPointSize( name.pointSize() + 2 );
// name.setBold( true );
//
// QFont smallFont = opt.font;
// smallFont.setPointSize( smallFont.pointSize() - 1 );
// QFontMetrics smallFontFM( smallFont );
//
// // draw the background
// const QWidget* w = opt.widget;
// QStyle* style = w ? w->style() : QApplication::style();
// style->drawPrimitive( QStyle::PE_PanelItemViewItem, &opt, painter, w );
/*
int iconLeftEdge = CHECK_LEFT_EDGE + WRENCH_SIZE + PADDING;
int textLeftEdge = iconLeftEdge + ICONSIZE + PADDING;
// draw checkbox first
int pos = ( mid ) - ( WRENCH_SIZE / 2 );
QRect checkRect = QRect( CHECK_LEFT_EDGE, pos + top, WRENCH_SIZE, WRENCH_SIZE );
opt.rect = checkRect;
drawCheckBox( opt, painter, w );
// draw the icon if it exists
pos = mid - ( ICONSIZE / 2 );
if( !index.data( Qt::DecorationRole ).value< QPixmap >().isNull() ) {
QRect prect = QRect( iconLeftEdge, pos + top, ICONSIZE, ICONSIZE );
painter->save();
painter->drawPixmap( prect, index.data( Qt::DecorationRole ).value< QPixmap >().scaled( prect.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation ) );
painter->restore();
}
// name
painter->save();
painter->setFont( name );
QFontMetrics namefm( name );
// pos will the top-left point of the text rect
pos = quarter - ( namefm.height() / 2 ) + top;
const QString nameStr = index.data( AccountModel::AccountName ).toString();
const int titleWidth = namefm.width( nameStr );
const QRect nameRect( textLeftEdge, pos, titleWidth, namefm.height() );
painter->drawText( nameRect, nameStr );
painter->restore();
// draw the online/offline status
const int stateY = mid + quarter - ( smallFontFM.height() / 2 ) + top;
QPixmap p;
QString statusText;
Account::ConnectionState state = static_cast< Account::ConnectionState >( index.data( AccountModel::ConnectionStateRole ).toInt() );
if ( state == Account::Connected )
{
p = m_cachedIcons[ "sipplugin-online" ];
statusText = tr( "Online" );
}
else if ( state == Account::Connecting )
{
p = m_cachedIcons[ "sipplugin-offline" ];
statusText = tr( "Connecting..." );
}
else
{
p = m_cachedIcons[ "sipplugin-offline" ];
statusText = tr( "Offline" );
}
painter->drawPixmap( textLeftEdge, stateY, STATUS_ICON_SIZE, STATUS_ICON_SIZE, p );
int width = smallFontFM.width( statusText );
int statusTextX = textLeftEdge + STATUS_ICON_SIZE + PADDING;
painter->save();
painter->setFont( smallFont );
painter->drawText( QRect( statusTextX, stateY, width, smallFontFM.height() ), statusText );
painter->restore();
// right-most edge of text on left (name, desc) is the cutoff point for the rest of the delegate
width = qMax( statusTextX + width, textLeftEdge + titleWidth );
// from the right edge--config status and online/offline
QRect confRect = QRect( itemRect.width() - WRENCH_SIZE - 2 * PADDING, mid - WRENCH_SIZE / 2 + top, WRENCH_SIZE, WRENCH_SIZE );
if( index.data( AccountModel::HasConfig ).toBool() ) {
QStyleOptionToolButton topt;
topt.rect = confRect;
topt.pos = confRect.topLeft();
drawConfigWrench( painter, opt, topt );
}
const bool hasCapability = ( static_cast< Accounts::AccountTypes >( index.data( AccountModel::AccountTypeRole ).toInt() ) != Accounts::NoType );
// draw optional capability text if it exists
if ( hasCapability )
{
QString capString;
AccountTypes types = AccountTypes( index.data( AccountModel::AccountTypeRole ).toInt() );
if ( ( types & Accounts::SipType ) && ( types & Accounts::ResolverType ) )
capString = tr( "Connects to, plays from friends" );
else if ( types & Accounts::SipType )
capString = tr( "Connects to friends" );
else if ( types & Accounts::ResolverType )
capString = tr( "Finds Music");
// checkbox for capability
// QRect capCheckRect( statusX, capY - STATUS_ICON_SIZE / 2 + top, STATUS_ICON_SIZE, STATUS_ICON_SIZE );
// opt.rect = capCheckRect;
// drawCheckBox( opt, painter, w );
// text to accompany checkbox
const int capY = mid - ( smallFontFM.height() / 2 ) + top;
const int configLeftEdge = confRect.left() - PADDING;
const int capW = configLeftEdge - width;
// Right-align text
const int capTextX = qMax( width, configLeftEdge - smallFontFM.width( capString ) );
painter->setFont( smallFont );
painter->drawText( QRect( capTextX, capY, configLeftEdge - capTextX, smallFontFM.height() ), Qt::AlignRight, capString );
}*/
}
@ -294,7 +164,8 @@ AccountDelegate::paintTopLevel( QPainter* painter, const QStyleOptionViewItemV4&
opt2.rect = checkRect;
const AccountModel::ItemState state = static_cast< AccountModel::ItemState >( index.data( AccountModel::StateRole ).toInt() );
const bool canCheck = ( state == AccountModel::Installed || state == AccountModel::ShippedWithTomahawk );
opt2.state = canCheck ? QStyle::State_On : QStyle::State_Off;
if ( !canCheck )
opt2.state &= ~QStyle::State_Enabled;
drawCheckBox( opt2, painter, opt.widget );
}
leftEdge += WRENCH_SIZE + PADDING / 2;
@ -315,62 +186,69 @@ AccountDelegate::paintTopLevel( QPainter* painter, const QStyleOptionViewItemV4&
// install / status button
const AccountModel::ItemState state = static_cast< AccountModel::ItemState >( index.data( AccountModel::StateRole ).toInt() );
QString actionText;
switch( state )
int edgeOfRightExtras = opt.rect.right();
if ( rowType == Tomahawk::Accounts::AccountModel::TopLevelFactory )
{
case AccountModel::Uninstalled:
actionText = tr( "Install" );
break;
case AccountModel::Installing:
actionText = tr( "Installing" );
break;
case AccountModel::Upgrading:
actionText = tr( "Upgrading" );
break;
case AccountModel::Failed:
actionText = tr( "Failed" );
break;
case AccountModel::Installed:
actionText = tr( "Uninstall" );
break;
case AccountModel::NeedsUpgrade:
actionText = tr( "Upgrade" );
break;
case AccountModel::ShippedWithTomahawk:
actionText = tr( "Create" );
break;
case AccountModel::UniqueFactory:
actionText = tr( "Installed" );
break;
QString actionText;
switch( state )
{
case AccountModel::Uninstalled:
actionText = tr( "Install" );
break;
case AccountModel::Installing:
actionText = tr( "Installing" );
break;
case AccountModel::Upgrading:
actionText = tr( "Upgrading" );
break;
case AccountModel::Failed:
actionText = tr( "Failed" );
break;
case AccountModel::Installed:
actionText = tr( "Uninstall" );
break;
case AccountModel::NeedsUpgrade:
actionText = tr( "Upgrade" );
break;
case AccountModel::ShippedWithTomahawk:
actionText = tr( "Create" );
break;
case AccountModel::UniqueFactory:
actionText = tr( "Installed" );
break;
}
// title and description
const int btnWidth = m_widestTextWidth + 7;
leftEdge = opt.rect.width() - PADDING - btnWidth - 3;
const QRect btnRect( leftEdge, center - ( installMetrics.height() + 4 ) / 2, btnWidth, installMetrics.height() + 4 );
m_cachedButtonRects[ index ] = btnRect;
painter->save();
painter->setPen( opt.palette.color( QPalette::Active, QPalette::AlternateBase ) );
drawRoundedButton( painter, btnRect );
painter->setFont( installFont );
painter->drawText( btnRect, Qt::AlignCenter, actionText );
painter->restore();
edgeOfRightExtras = btnRect.left();
}
// title and description
const int btnWidth = m_widestTextWidth + 7;
leftEdge = opt.rect.width() - PADDING - btnWidth - 3;
const QRect btnRect( leftEdge, center - ( installMetrics.height() + 4 ) / 2, btnWidth, installMetrics.height() + 4 );
m_cachedButtonRects[ index ] = btnRect;
const QPen saved = painter->pen();
painter->setPen( opt.palette.color( QPalette::Active, QPalette::AlternateBase ) );
drawRoundedButton( painter, btnRect );
painter->setFont( installFont );
painter->drawText( btnRect, Qt::AlignCenter, actionText );
painter->setPen( saved );
int edgeOfRightExtras = btnRect.x();
if ( rowType == AccountModel::TopLevelAccount )
{
// rating stars
const int rating = index.data( AccountModel::RatingRole ).toInt();
const int ratingWidth = 5 * ( m_ratingStarPositive.width() + PADDING_BETWEEN_STARS );
int runningEdge = ( btnRect.right() - btnRect.width() / 2 ) - ratingWidth / 2;
// int runningEdge = ( btnRect.right() - btnRect.width() / 2 ) - ratingWidth / 2;
int runningEdge = opt.rect.right() - PADDING - ratingWidth;
edgeOfRightExtras = runningEdge;
for ( int i = 1; i < 6; i++ )
{
QRect r( runningEdge, btnRect.top() - m_ratingStarPositive.height() - PADDING, m_ratingStarPositive.width(), m_ratingStarPositive.height() );
QRect r( runningEdge, opt.rect.top() + PADDING, m_ratingStarPositive.width(), m_ratingStarPositive.height() );
if ( i == 1 )
m_cachedStarRects[ index ] = r;
@ -401,19 +279,23 @@ AccountDelegate::paintTopLevel( QPainter* painter, const QStyleOptionViewItemV4&
// downloaded num times, underneath button
QString count = tr( "%1 downloads" ).arg( index.data( AccountModel::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 );
const int countW = painter->fontMetrics().width( count );
const QRect countRect( opt.rect.right() - PADDING - countW, opt.rect.bottom() - PADDING - painter->fontMetrics().height(), countW, painter->fontMetrics().height() );
painter->setFont( countFont );
painter->drawText( countRect, Qt::AlignCenter | Qt::TextWordWrap, count );
// author and version
QString author = index.data( AccountModel::AuthorRole ).toString();
painter->setFont( authorFont );
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 );
const QRect authorRect( edgeOfRightExtras - 2*PADDING - authorWidth, topTextLine, authorWidth + 6, authorMetrics.height() );
painter->drawText( authorRect, Qt::AlignCenter, author );
// Disable version for now, that space is used
@ -425,10 +307,10 @@ AccountDelegate::paintTopLevel( QPainter* painter, const QStyleOptionViewItemV4&
}
// if this is a real resolver, show config wrench, state/status, and string
edgeOfRightExtras = btnRect.x();
m_cachedConfigRects.remove( index );
if ( rowType == AccountModel::TopLevelAccount )
{
const QRect confRect = QRect( btnRect.x() - 2*PADDING - WRENCH_SIZE, center - WRENCH_SIZE / 2, WRENCH_SIZE, WRENCH_SIZE );
const QRect confRect = QRect( edgeOfRightExtras - 2*PADDING - WRENCH_SIZE, center - WRENCH_SIZE / 2, WRENCH_SIZE, WRENCH_SIZE );
if( index.data( AccountModel::HasConfig ).toBool() ) {
QStyleOptionToolButton topt;
@ -436,13 +318,17 @@ AccountDelegate::paintTopLevel( QPainter* painter, const QStyleOptionViewItemV4&
topt.pos = confRect.topLeft();
drawConfigWrench( painter, opt, topt );
m_cachedConfigRects[ index ] = confRect;
edgeOfRightExtras = confRect.left();
}
painter->save();
painter->setFont( installFont );
edgeOfRightExtras = drawStatus( painter, QPointF( edgeOfRightExtras - PADDING, center ), index );
painter->restore();
if ( state == AccountModel::Installed || state == AccountModel::ShippedWithTomahawk || state == AccountModel::NeedsUpgrade )
{
painter->save();
painter->setFont( installFont );
edgeOfRightExtras = drawStatus( painter, QPointF( edgeOfRightExtras - PADDING, center ), index );
painter->restore();
}
}
// Title and description!
@ -500,10 +386,12 @@ AccountDelegate::paintChild( QPainter* painter, const QStyleOptionViewItemV4& op
// draw remove icon, config wrench, and then status from right edge
const QRect removeRect( option.rect.right() - rightPadding - PADDING - REMOVE_ICON_SIZE, center - REMOVE_ICON_SIZE/2, REMOVE_ICON_SIZE, REMOVE_ICON_SIZE );
m_cachedButtonRects[ index ] = removeRect;
painter->drawPixmap( removeRect, m_removeIcon );
int edgeOfRightExtras = removeRect.left();
m_cachedConfigRects.remove( index );
if ( index.data( AccountModel::HasConfig ).toBool() )
{
const QRect confRect = QRect( removeRect.x() - PADDING - SMALL_WRENCH_SIZE, center - SMALL_WRENCH_SIZE / 2, SMALL_WRENCH_SIZE, SMALL_WRENCH_SIZE );
@ -514,6 +402,7 @@ AccountDelegate::paintChild( QPainter* painter, const QStyleOptionViewItemV4& op
QStyleOptionViewItemV4 opt3 = option;
drawConfigWrench( painter, opt3, topt );
m_cachedConfigRects[ index ] = confRect;
edgeOfRightExtras = confRect.left();
}
@ -527,6 +416,103 @@ AccountDelegate::paintChild( QPainter* painter, const QStyleOptionViewItemV4& op
}
bool
AccountDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index )
{
if ( event->type() != QEvent::MouseButtonPress &&
event->type() != QEvent::MouseButtonRelease &&
event->type() != QEvent::MouseButtonDblClick &&
event->type() != QEvent::MouseMove )
return false;
if ( event->type() == QEvent::MouseButtonPress )
{
// Show the config wrench as depressed on click
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if ( me->button() == Qt::LeftButton && m_cachedConfigRects.contains( index ) && m_cachedConfigRects[ index ].contains( me->pos() ) )
{
m_configPressed = index;
Account* acct = qobject_cast< Account* >( index.data( AccountModel::AccountData ).value< QObject* >() );
Q_ASSERT( acct ); // Should not be showing a config wrench if there is no account!
emit openConfig( acct );
return true;
}
} else if ( event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseButtonDblClick )
{
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if ( m_configPressed.isValid() )
emit update( m_configPressed );
m_configPressed = QModelIndex();
const AccountModel::ItemState state = static_cast< AccountModel::ItemState >( index.data( AccountModel::StateRole ).toInt() );
const bool canCheck = ( state == AccountModel::Installed || state == AccountModel::ShippedWithTomahawk );
if ( !canCheck )
return false;
// A few options. First, could be the checkbox on/off.
// second, could be the install/uninstall/create button
// third could be the config button
if ( checkRectForIndex( option, index ).contains( me->pos() ) )
{
// Check box for this row
// 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, AccountModel::CheckboxClickedRole );
}
else if ( m_cachedButtonRects.contains( index ) && m_cachedButtonRects[ index ].contains( me->pos() ) )
{
// Install/create/etc button for this row
model->setData( index, true, AccountModel::ButtonClickedRole );
}
}
if ( m_cachedStarRects.contains( index ) )
{
QRect fullStars = m_cachedStarRects[ index ];
const int starsWidth = 5 * ( m_ratingStarPositive.width() + PADDING_BETWEEN_STARS );
fullStars.setWidth( starsWidth );
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if ( fullStars.contains( me->pos() ) )
{
const int eachStar = starsWidth / 5;
const int clickOffset = me->pos().x() - fullStars.x();
const int whichStar = (clickOffset / eachStar) + 1;
if ( event->type() == QEvent::MouseButtonRelease )
{
model->setData( index, whichStar, AccountModel::RatingRole );
}
else if ( event->type() == QEvent::MouseMove )
{
// 0-indexed
m_hoveringOver = whichStar;
m_hoveringItem = index;
}
return true;
}
}
if ( m_hoveringOver > -1 )
{
emit update( m_hoveringItem );
m_hoveringOver = -1;
m_hoveringItem = QPersistentModelIndex();
}
return false;
}
void
AccountDelegate::drawRoundedButton( QPainter* painter, const QRect& btnRect ) const
{
@ -598,46 +584,62 @@ AccountDelegate::drawStatus( QPainter* painter, const QPointF& rightCenterEdge,
}
QRect
AccountDelegate::checkRectForIndex( const QStyleOptionViewItem &option, const QModelIndex &idx, int role ) const
void
AccountDelegate::drawCheckBox( QStyleOptionViewItemV4& opt, QPainter* p, const QWidget* w ) const
{
// if ( role == Qt::CheckStateRole )
// {
// // the whole resolver checkbox
// QStyleOptionViewItemV4 opt = option;
// initStyleOption( &opt, idx );
// const int mid = opt.rect.height() / 2;
// const int pos = mid - ( ICONSIZE / 2 );
// QRect checkRect( CHECK_LEFT_EDGE, pos + opt.rect.top(), ICONSIZE, ICONSIZE );
//
// return checkRect;
// } else if ( role == AccountModel::AccountTypeRole )
// {
// // The capabilities checkbox
// QStyleOptionViewItemV4 opt = option;
// initStyleOption( &opt, idx );
// const int quarter = opt.rect.height() / 4 + opt.rect.height() / 2;
// const int leftEdge = opt.rect.width() - PADDING - WRENCH_SIZE - PADDING - WRENCH_SIZE;
// QRect checkRect( leftEdge, quarter, WRENCH_SIZE, WRENCH_SIZE );
// return checkRect;
// }
QStyle* style = w ? w->style() : QApplication::style();
opt.checkState == Qt::Checked ? opt.state |= QStyle::State_On : opt.state |= QStyle::State_Off;
style->drawPrimitive( QStyle::PE_IndicatorViewItemCheck, &opt, p, w );
}
void
AccountDelegate::drawConfigWrench ( QPainter* painter, QStyleOptionViewItemV4& opt, QStyleOptionToolButton& topt ) const
{
const QWidget* w = opt.widget;
QStyle* style = w ? w->style() : QApplication::style();
// draw it the same size as the check belox
topt.font = opt.font;
topt.icon = QIcon( RESPATH "images/configure.png" );
topt.iconSize = QSize( 16, 16 );
topt.subControls = QStyle::SC_ToolButton;
topt.activeSubControls = QStyle::SC_None;
topt.features = QStyleOptionToolButton::None;
bool pressed = ( m_configPressed == opt.index );
topt.state = pressed ? QStyle::State_On : QStyle::State_Raised;
if( opt.state & QStyle::State_MouseOver || pressed )
topt.state |= QStyle::State_HasFocus;
style->drawComplexControl( QStyle::CC_ToolButton, &topt, painter, w );
}
QRect
AccountDelegate::checkRectForIndex( const QStyleOptionViewItem& option, const QModelIndex& idx ) const
{
// the checkbox for this row was hit
const AccountModel::RowType rowType = static_cast< AccountModel::RowType >( idx.data( AccountModel::RowTypeRole ).toInt() );
QStyleOptionViewItemV4 opt = option;
initStyleOption( &opt, idx );
if ( rowType == AccountModel::TopLevelAccount || rowType == AccountModel::TopLevelFactory )
{
// Top level item, return the corresponding rect
const int ypos = ( opt.rect.top() + opt.rect.height() / 2 ) - ( WRENCH_SIZE / 2 );
QRect checkRect = QRect( PADDING, ypos, WRENCH_SIZE, WRENCH_SIZE );
return checkRect;
} else if ( rowType == AccountModel::ChildAccount )
{
// Return smaller rect of individual child account
const int smallWrenchSize = opt.rect.height() - PADDING;
int ypos = ( opt.rect.center().y() ) - ( smallWrenchSize / 2 );
QRect checkRect = QRect( opt.rect.left() + PADDING, ypos, smallWrenchSize, smallWrenchSize );
return checkRect;
}
return QRect();
}
QRect
AccountDelegate::configRectForIndex( const QStyleOptionViewItem& option, const QModelIndex& idx ) const
{
QStyleOptionViewItemV4 opt = option;
initStyleOption( &opt, idx );
QRect itemRect = opt.rect;
QRect confRect = QRect( itemRect.width() - ICONSIZE - 2 * PADDING, (opt.rect.height() / 2) - ICONSIZE / 2 + opt.rect.top(), ICONSIZE, ICONSIZE );
return confRect;
}
void
AccountDelegate::askedForEdit( const QModelIndex& idx )
{
emit openConfig( qobject_cast< Account* >( idx.data( AccountModel::AccountData ).value< QObject* >() ) );
}

View File

@ -19,7 +19,7 @@
#ifndef ACCOUNTDELEGATE_H
#define ACCOUNTDELEGATE_H
#include "configdelegatebase.h"
#include <QStyledItemDelegate>
#include "accounts/AccountModel.h"
namespace Tomahawk
@ -29,21 +29,17 @@ namespace Accounts
class Account;
class AccountDelegate : public ConfigDelegateBase
class AccountDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
AccountDelegate( QObject* parent = 0);
virtual void paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
virtual bool editorEvent ( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
virtual QSize sizeHint ( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
virtual QRect checkRectForIndex( const QStyleOptionViewItem &option, const QModelIndex &idx, int role ) const;
virtual QRect configRectForIndex( const QStyleOptionViewItem& option, const QModelIndex& idx ) const;
private slots:
void askedForEdit( const QModelIndex& idx );
protected:
virtual bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
signals:
void update( const QModelIndex& idx );
@ -52,17 +48,23 @@ signals:
private:
void paintTopLevel( QPainter* painter, const QStyleOptionViewItemV4& option, const QModelIndex& index ) const;
void paintChild( QPainter* painter, const QStyleOptionViewItemV4& option, const QModelIndex& index ) const;
void drawRoundedButton( QPainter* painter, const QRect& buttonRect ) const;
// Returns new left edge
int drawStatus( QPainter* painter, const QPointF& rightCenterEdge, const QModelIndex& index ) const;
void drawCheckBox( QStyleOptionViewItemV4& opt, QPainter* p, const QWidget* w ) const;
void drawConfigWrench( QPainter* painter, QStyleOptionViewItemV4& option, QStyleOptionToolButton& topt ) const;
QRect checkRectForIndex( const QStyleOptionViewItem &option, const QModelIndex &idx ) const;
QMap< QString, QPixmap > m_cachedIcons;
QPixmap m_offlineIcon, m_onlineIcon, m_defaultCover, m_onHoverStar, m_ratingStarPositive, m_ratingStarNegative, m_removeIcon;
int m_widestTextWidth;
int m_hoveringOver;
QPersistentModelIndex m_hoveringItem;
QPersistentModelIndex m_hoveringItem, m_configPressed;
mutable QHash< QPersistentModelIndex, QRect > m_cachedButtonRects;
mutable QHash< QPersistentModelIndex, QRect > m_cachedStarRects;
mutable QHash< QPersistentModelIndex, QRect > m_cachedConfigRects;
};
}

View File

@ -74,7 +74,6 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui}
audiocontrols.cpp
settingsdialog.cpp
diagnosticsdialog.cpp
configdelegatebase.cpp
AccountDelegate.cpp
settingslistdelegate.cpp
tomahawkwindow.cpp
@ -98,13 +97,6 @@ IF(LIBLASTFM_FOUND)
)
ENDIF(LIBLASTFM_FOUND)
IF(LIBATTICA_FOUND)
SET( tomahawkSourcesGui ${tomahawkSourcesGui} GetNewStuffDialog.cpp GetNewStuffDelegate.cpp GetNewStuffModel.cpp )
SET( tomahawkHeadersGui ${tomahawkHeadersGui} GetNewStuffDialog.h GetNewStuffDelegate.h GetNewStuffModel.h )
INCLUDE_DIRECTORIES( ${LIBATTICA_INCLUDE_DIR} )
ENDIF(LIBATTICA_FOUND)
SET( tomahawkHeadersGui ${tomahawkHeadersGui}
sourcetree/sourcesmodel.h
sourcetree/sourcesproxymodel.h
@ -124,7 +116,6 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui}
audiocontrols.h
settingsdialog.h
diagnosticsdialog.h
configdelegatebase.h
AccountDelegate.h
settingslistdelegate.h
delegateconfigwrapper.h
@ -140,7 +131,6 @@ SET( tomahawkUI ${tomahawkUI}
audiocontrols.ui
GetNewStuffDialog.ui
LoadXSPFDialog.ui
)
@ -167,6 +157,7 @@ INCLUDE_DIRECTORIES(
${TAGLIB_INCLUDES}
${PHONON_INCLUDES}
${QJSON_INCLUDE_DIR}
${LIBATTICA_INCLUDE_DIR}
${LIBECHONEST_INCLUDE_DIR}
${LIBECHONEST_INCLUDE_DIR}/..
)

View File

@ -1,326 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, 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 "GetNewStuffDelegate.h"
#include "GetNewStuffModel.h"
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
#include <QtGui/QPainter>
#include <QApplication>
#include <QMouseEvent>
#include "AtticaManager.h"
#define PADDING 4
#define PADDING_BETWEEN_STARS 2
#define STAR_SIZE 12
#ifdef Q_WS_MAC
#define SIZEHINT_HEIGHT 70
#else
#define SIZEHINT_HEIGHT 60
#endif
GetNewStuffDelegate::GetNewStuffDelegate( QObject* parent )
: QStyledItemDelegate ( parent )
, m_widestTextWidth( 0 )
, m_hoveringOver( -1 )
{
m_defaultCover.load( RESPATH "images/sipplugin-online.png" );
m_ratingStarPositive.load( RESPATH "images/starred.png" );
m_ratingStarNegative.load( RESPATH "images/star-unstarred.png" );
m_onHoverStar.load( RESPATH "images/star-hover.png" );
m_ratingStarPositive = m_ratingStarPositive.scaled( STAR_SIZE, STAR_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
m_ratingStarNegative = m_ratingStarNegative.scaled( STAR_SIZE, STAR_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
m_onHoverStar = m_onHoverStar.scaled( STAR_SIZE, STAR_SIZE, 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::ItemState state = static_cast< GetNewStuffModel::ItemState >( 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::Upgrading:
actionText = tr( "Upgrading" );
break;
case GetNewStuffModel::Failed:
actionText = tr( "Failed" );
break;
case GetNewStuffModel::Installed:
actionText = tr( "Uninstall" );
break;
case GetNewStuffModel::NeedsUpgrade:
actionText = tr( "Upgrade" );
break;
case GetNewStuffModel::CanInstallMore:
actionText = tr( "Install Another" );
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<int, int>(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 ratingWidth = 5 * ( m_ratingStarPositive.width() + PADDING_BETWEEN_STARS );
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 == 1 )
m_cachedStarRects[ QPair<int, int>(index.row(), index.column()) ] = r;
const bool userHasRated = index.data( GetNewStuffModel::UserHasRatedRole ).toBool();
if ( !userHasRated && // Show on-hover animation if the user hasn't rated it yet, and is hovering over it
m_hoveringOver > -1 &&
m_hoveringItem == index )
{
if ( i <= m_hoveringOver ) // positive star
painter->drawPixmap( r, m_onHoverStar );
else
painter->drawPixmap( r, m_ratingStarNegative );
}
else
{
if ( i <= rating ) // positive or rated star
{
if ( userHasRated )
painter->drawPixmap( r, m_onHoverStar );
else
painter->drawPixmap( r, m_ratingStarPositive );
}
else
painter->drawPixmap( r, m_ratingStarNegative );
}
runningEdge += m_ratingStarPositive.width() + PADDING_BETWEEN_STARS;
}
// 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
{
Q_UNUSED( option );
Q_UNUSED( index );
return QSize( 200, SIZEHINT_HEIGHT );
}
bool
GetNewStuffDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index )
{
Q_UNUSED( option );
if ( event->type() != QEvent::MouseButtonRelease &&
event->type() != QEvent::MouseMove )
return false;
if ( event->type() == QEvent::MouseButtonRelease && m_cachedButtonRects.contains( QPair<int, int>( index.row(), index.column() ) ) )
{
QRect rect = m_cachedButtonRects[ QPair<int, int>( index.row(), index.column() ) ];
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if ( rect.contains( me->pos() ) )
{
model->setData( index, true );
return true;
}
}
if ( m_cachedStarRects.contains( QPair<int, int>( index.row(), index.column() ) ) )
{
QRect fullStars = m_cachedStarRects[ QPair<int, int>( index.row(), index.column() ) ];
const int starsWidth = 5 * ( m_ratingStarPositive.width() + PADDING_BETWEEN_STARS );
fullStars.setWidth( starsWidth );
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if ( fullStars.contains( me->pos() ) )
{
const int eachStar = starsWidth / 5;
const int clickOffset = me->pos().x() - fullStars.x();
const int whichStar = (clickOffset / eachStar) + 1;
if ( event->type() == QEvent::MouseButtonRelease )
{
model->setData( index, whichStar, GetNewStuffModel::RatingRole );
}
else if ( event->type() == QEvent::MouseMove )
{
// 0-indexed
m_hoveringOver = whichStar;
m_hoveringItem = index;
}
return true;
}
}
if ( m_hoveringOver > -1 )
{
emit update( m_hoveringItem );
m_hoveringOver = -1;
m_hoveringItem = QPersistentModelIndex();
}
return false;
}

View File

@ -1,50 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, 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 GETNEWSTUFFDELEGATE_H
#define GETNEWSTUFFDELEGATE_H
#include <QStyledItemDelegate>
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;
signals:
void update( const QModelIndex& idx );
protected:
virtual bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
private:
QPixmap m_defaultCover, m_onHoverStar, m_ratingStarPositive, m_ratingStarNegative;
int m_widestTextWidth;
int m_hoveringOver;
QPersistentModelIndex m_hoveringItem;
mutable QHash< QPair<int, int>, QRect > m_cachedButtonRects;
mutable QHash< QPair<int, int>, QRect > m_cachedStarRects;
};
#endif // GETNEWSTUFFDELEGATE_H

View File

@ -1,75 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, 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 "GetNewStuffDialog.h"
#include "ui_GetNewStuffDialog.h"
#include "GetNewStuffDelegate.h"
#include "GetNewStuffModel.h"
#include "tomahawksettings.h"
#include <QtGui/QFileDialog>
GetNewStuffDialog::GetNewStuffDialog( QWidget* parent, Qt::WindowFlags f )
: QDialog( parent, f )
, ui( new Ui::GetNewStuffDialog )
, m_model( new GetNewStuffModel( this ) )
{
ui->setupUi( this );
ui->accountsList->setModel( m_model );
GetNewStuffDelegate* del = new GetNewStuffDelegate( ui->accountsList );
connect( del, SIGNAL( update( QModelIndex ) ), ui->accountsList, SLOT( update( QModelIndex ) ) );
ui->accountsList->setItemDelegate( del );
ui->accountsList->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel );
ui->accountsList->setMouseTracking( true );
setMinimumSize( 560, 350 );
#ifdef Q_WS_MAC
setMaximumSize( 560, 350 );
setSizeGripEnabled( false );
ui->accountsList->setAttribute( Qt::WA_MacShowFocusRect, false );
#endif
connect( ui->installFromFileBtn, SIGNAL( clicked( bool ) ), this, SLOT( installFromFile() ) );
}
GetNewStuffDialog::~GetNewStuffDialog()
{
delete ui;
}
void
GetNewStuffDialog::installFromFile()
{
QString resolver = QFileDialog::getOpenFileName( this, tr( "Load script resolver file" ), TomahawkSettings::instance()->scriptDefaultPath() );
// m_resolversModel->addResolver( resolver, true );
// TODO
if( !resolver.isEmpty() )
{
QFileInfo resolverAbsoluteFilePath = resolver;
TomahawkSettings::instance()->setScriptDefaultPath( resolverAbsoluteFilePath.absolutePath() );
}
}

View File

@ -1,44 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, 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 GETNEWSTUFFDIALOG_H
#define GETNEWSTUFFDIALOG_H
#include <QDialog>
class GetNewStuffModel;
namespace Ui {
class GetNewStuffDialog;
}
class GetNewStuffDialog : public QDialog
{
Q_OBJECT
public:
explicit GetNewStuffDialog( QWidget *parent = 0, Qt::WindowFlags f = 0 );
~GetNewStuffDialog();
private slots:
void installFromFile();
private:
Ui::GetNewStuffDialog *ui;
GetNewStuffModel* m_model;
};
#endif // GETNEWSTUFFDIALOG_H

View File

@ -1,91 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GetNewStuffDialog</class>
<widget class="QDialog" name="GetNewStuffDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>449</width>
<height>327</height>
</rect>
</property>
<property name="windowTitle">
<string>Download New Resolvers</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QListView" name="accountsList"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="installFromFileBtn">
<property name="text">
<string>Install from file...</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>GetNewStuffDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>GetNewStuffDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -1,293 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, 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 "GetNewStuffModel.h"
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
#include "AtticaManager.h"
#include "accounts/AccountManager.h"
#include <QPixmap>
#include <QUrl>
using namespace Tomahawk;
using namespace Accounts;
GetNewStuffModel::GetNewStuffModel( QObject* parent )
: QAbstractListModel ( parent )
{
connect( AtticaManager::instance(), SIGNAL( resolversReloaded( Attica::Content::List ) ), this, SLOT( resolversReloaded( Attica::Content::List ) ) );
connect( AtticaManager::instance(), SIGNAL( resolverStateChanged( QString ) ), this, SLOT( resolverStateChanged( QString ) ) );
loadData();
}
GetNewStuffModel::~GetNewStuffModel()
{
}
void
GetNewStuffModel::loadData()
{
foreach ( const QVariant& content, m_contentList )
{
if ( !isAttica( content ) )
{
AccountItem* item = content.value< GetNewStuffModel::AccountItem* >();
delete item;
}
}
m_contentList.clear();
Attica::Content::List fromAttica = AtticaManager::instance()->resolvers();
foreach ( const Attica::Content& content, fromAttica )
m_contentList.append( QVariant::fromValue< Attica::Content >( content ) );
QList< AccountFactory* > factories = AccountManager::instance()->factories();
QList< Account* > allAccounts = AccountManager::instance()->accounts();
foreach ( AccountFactory* fac, factories )
{
if ( !fac->allowUserCreation() )
continue;
AccountItem* item = new AccountItem;
item->factory = fac;
foreach ( Account* acct, allAccounts )
{
if ( AccountManager::instance()->factoryForAccount( acct ) == fac )
{
item->alreadyExists = true;
break;
}
else
item->alreadyExists = false;
}
m_contentList.append( QVariant::fromValue< GetNewStuffModel::AccountItem* >( item ) );
}
}
void
GetNewStuffModel::resolversReloaded( const Attica::Content::List& resolvers )
{
beginResetModel();
loadData();
endResetModel();
}
void
GetNewStuffModel::resolverStateChanged( const QString& resolverId )
{
for ( int i = 0; i < m_contentList.count(); i++ )
{
if ( !isAttica( m_contentList.at( i ) ) )
continue;
const Attica::Content resolver = atticaFromItem( m_contentList.at( i ) );
if ( resolver.id() == resolverId )
{
QModelIndex idx = index( i, 0, QModelIndex() );
emit dataChanged( idx, idx );
}
}
}
QVariant
GetNewStuffModel::data( const QModelIndex& index, int role ) const
{
if ( !index.isValid() || !hasIndex( index.row(), index.column(), index.parent() ) )
return QVariant();
if ( isAttica( m_contentList.at( index.row() ) ) )
{
const Attica::Content resolver = atticaFromItem( m_contentList.at( index.row() ) );
switch ( role )
{
case Qt::DisplayRole:
return resolver.name();
case Qt::DecorationRole:
return QVariant::fromValue< QPixmap >( AtticaManager::instance()->iconForResolver( resolver ) );
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 AtticaType;
case AuthorRole:
return resolver.author();
case StateRole:
return (int)AtticaManager::instance()->resolverState( resolver );
case UserHasRatedRole:
return AtticaManager::instance()->userHasRated( resolver );
}
}
else
{
// Account, not from Attica
AccountItem* item = accountFromItem( m_contentList.at( index.row() ) );
Q_ASSERT( item );
switch ( role )
{
case Qt::DisplayRole:
return item->factory->prettyName();
case Qt::DecorationRole:
return QVariant::fromValue< QPixmap >( item->factory->icon() );
case RatingRole:
// TODO
return 3;
// return resolver.rating() / 20; // rating is out of 100
case DownloadCounterRole:
// TODO
return 10;
// return resolver.downloads();
case VersionRole:
return "1.0";
// return resolver.version();
case DescriptionRole:
return item->factory->description();
case TypeRole:
return AccountType;
case AuthorRole:
return "Tomahawk Developers";
case StateRole:
{
GetNewStuffModel::ItemState state = Uninstalled;
if ( item->factory->isUnique() && item->alreadyExists )
state = Installed;
else if ( !item->factory->isUnique() && item->alreadyExists )
state = CanInstallMore;
else if ( !item->alreadyExists )
state = Uninstalled;
return (int)state;
}
case UserHasRatedRole:
// TODO
return true;
// return AtticaManager::instance()->userHasRated( resolver );
}
}
return QVariant();
}
int
GetNewStuffModel::rowCount( const QModelIndex& parent ) const
{
Q_UNUSED( parent );
return m_contentList.count();
}
bool
GetNewStuffModel::setData( const QModelIndex &index, const QVariant &value, int role )
{
Q_UNUSED( value );
if ( !hasIndex( index.row(), index.column(), index.parent() ) )
return false;
if ( isAttica( m_contentList.at( index.row() ) ) )
{
Attica::Content resolver = atticaFromItem( m_contentList.at( index.row() ) );
AtticaManager::ResolverState state = AtticaManager::instance()->resolverState( resolver );
if ( role == Qt::EditRole )
{
switch( state )
{
case AtticaManager::Uninstalled:
// install
AtticaManager::instance()->installResolver( resolver );
break;
case AtticaManager::Installing:
case AtticaManager::Upgrading:
// Do nothing, busy
break;
case AtticaManager::Installed:
// Uninstall
AtticaManager::instance()->uninstallResolver( resolver );
break;
case AtticaManager::NeedsUpgrade:
AtticaManager::instance()->upgradeResolver( resolver );
break;
default:
//FIXME -- this handles e.g. Failed
break;
};
} else if ( role == RatingRole )
{
// For now only allow rating if a resolver is installed!
if ( state != AtticaManager::Installed && state != AtticaManager::NeedsUpgrade )
return false;
if ( AtticaManager::instance()->userHasRated( resolver ) )
return false;
resolver.setRating( value.toInt() * 20 );
m_contentList[ index.row() ] = QVariant::fromValue< Attica::Content >( resolver );
AtticaManager::instance()->uploadRating( resolver );
}
emit dataChanged( index, index );
}
else
{
AccountItem* item = accountFromItem( m_contentList.at( index.row() ) );
if ( role == Qt::EditRole )
{
// TODO
}
else if ( role == RatingRole )
{
// TODO
}
}
return true;
}
bool
GetNewStuffModel::isAttica( const QVariant& item ) const
{
return qstrcmp( item.typeName(),"Attica::Content" ) == 0;
}
GetNewStuffModel::AccountItem*
GetNewStuffModel::accountFromItem( const QVariant& item ) const
{
Q_ASSERT( !isAttica( item ) );
return item.value< GetNewStuffModel::AccountItem* >();
}
Attica::Content
GetNewStuffModel::atticaFromItem( const QVariant& item ) const
{
Q_ASSERT( isAttica( item ) );
return item.value< Attica::Content >();
}

View File

@ -1,91 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2011, 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 GETNEWSTUFFMODEL_H
#define GETNEWSTUFFMODEL_H
#include "accounts/Account.h"
#include <attica/content.h>
#include <QModelIndex>
#include <QPixmap>
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,
UserHasRatedRole = Qt::UserRole + 9
};
enum Types {
AtticaType = 0,
AccountType = 1
};
enum ItemState {
Uninstalled = 0,
Installing,
Installed,
NeedsUpgrade,
Upgrading,
Failed,
CanInstallMore, // accounts that are not unique
};
// plz don't use me kthxbbq
typedef struct {
Tomahawk::Accounts::AccountFactory* factory;
bool alreadyExists;
} AccountItem;
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& );
void resolverStateChanged( const QString& resolverId );
private:
void loadData();
bool isAttica( const QVariant& item ) const;
Attica::Content atticaFromItem( const QVariant& item ) const;
AccountItem* accountFromItem( const QVariant& item ) const;
QVariantList m_contentList;
};
Q_DECLARE_METATYPE( GetNewStuffModel::AccountItem* );
#endif // GETNEWSTUFFMODEL_H

View File

@ -1,113 +0,0 @@
/*
Copyright (C) 2011 Leo Franchi <leo.franchi@kdab.com>
This program 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.
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "configdelegatebase.h"
#include <QPainter>
#include <QApplication>
#include <QMouseEvent>
#include "utils/tomahawkutils.h"
#include "utils/logger.h"
#define ROW_HEIGHT 40
ConfigDelegateBase::ConfigDelegateBase ( QObject* parent )
: QStyledItemDelegate ( parent )
{
}
QSize
ConfigDelegateBase::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
int width = QStyledItemDelegate::sizeHint( option, index ).width();
return QSize( width, ROW_HEIGHT );
}
void
ConfigDelegateBase::drawCheckBox( QStyleOptionViewItemV4& opt, QPainter* p, const QWidget* w ) const
{
QStyle* style = w ? w->style() : QApplication::style();
opt.checkState == Qt::Checked ? opt.state |= QStyle::State_On : opt.state |= QStyle::State_Off;
style->drawPrimitive( QStyle::PE_IndicatorViewItemCheck, &opt, p, w );
}
void
ConfigDelegateBase::drawConfigWrench ( QPainter* painter, QStyleOptionViewItemV4& opt, QStyleOptionToolButton& topt ) const
{
const QWidget* w = opt.widget;
QStyle* style = w ? w->style() : QApplication::style();
// draw it the same size as the check belox
topt.font = opt.font;
topt.icon = QIcon( RESPATH "images/configure.png" );
topt.iconSize = QSize( 16, 16 );
topt.subControls = QStyle::SC_ToolButton;
topt.activeSubControls = QStyle::SC_None;
topt.features = QStyleOptionToolButton::None;
bool pressed = ( m_configPressed == opt.index );
topt.state = pressed ? QStyle::State_On : QStyle::State_Raised;
if( opt.state & QStyle::State_MouseOver || pressed )
topt.state |= QStyle::State_HasFocus;
style->drawComplexControl( QStyle::CC_ToolButton, &topt, painter, w );
}
bool
ConfigDelegateBase::editorEvent ( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index )
{
QStyleOptionViewItemV4 viewOpt( option );
initStyleOption( &viewOpt, index );
if( event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseButtonDblClick ) {
m_configPressed = QModelIndex();
QMouseEvent* me = static_cast< QMouseEvent* >( event );
QList<int> roles = QList<int>() << (int)Qt::CheckStateRole;
roles.append( extraCheckRoles() );
foreach ( int role, roles )
{
if( me->button() != Qt::LeftButton || !checkRectForIndex( option, index, role ).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( role ).toInt() );
Qt::CheckState newState = curState == Qt::Checked ? Qt::Unchecked : Qt::Checked;
return model->setData( index, newState, role );
}
} else if( event->type() == QEvent::MouseButtonPress ) {
QMouseEvent* me = static_cast< QMouseEvent* >( event );
if( me->button() == Qt::LeftButton && configRectForIndex( option, index ).contains( me->pos() ) ) {
m_configPressed = index;
emit configPressed( index );
return true;
}
}
return QStyledItemDelegate::editorEvent( event, model, option, index );
}

View File

@ -45,8 +45,6 @@ signals:
void configPressed( const QModelIndex& idx );
protected:
void drawCheckBox( QStyleOptionViewItemV4& opt, QPainter* p, const QWidget* w ) const;
void drawConfigWrench( QPainter* painter, QStyleOptionViewItemV4& option, QStyleOptionToolButton& topt ) const;
private:
QModelIndex m_configPressed;

View File

@ -210,6 +210,24 @@ AtticaManager::resolversList( BaseJob* j )
m_resolvers = job->itemList();
m_resolverStates = TomahawkSettingsGui::instanceGui()->atticaResolverStates();
// Sanity check. if any resolvers are installed that don't exist on the hd, remove them.
foreach ( const QString& rId, m_resolverStates.keys() )
{
if ( m_resolverStates[ rId ].state == Installed ||
m_resolverStates[ rId ].state == NeedsUpgrade )
{
// Guess location on disk
QDir dir( QString( "%1/atticaresolvers/%2" ).arg( TomahawkUtils::appDataDir().absolutePath() ).arg( rId ) );
if ( !dir.exists() )
{
// Uh oh
qWarning() << "Found attica resolver marked as installed that didn't exist on disk! Setting to uninstalled: " << rId << dir.absolutePath();
m_resolverStates[ rId ].state = Uninstalled;
TomahawkSettingsGui::instanceGui()->setAtticaResolverState( rId, Uninstalled );
}
}
}
// load icon cache from disk, and fetch any we are missing
loadPixmapsFromCache();

View File

@ -70,6 +70,10 @@ AccountModel::loadData()
}
}
connect ( AccountManager::instance(), SIGNAL( added( Tomahawk::Accounts::Account* ) ), this, SLOT( accountAdded( Tomahawk::Accounts::Account* ) ) );
connect ( AccountManager::instance(), SIGNAL( removed( Tomahawk::Accounts::Account* ) ), this, SLOT( accountRemoved( Tomahawk::Accounts::Account* ) ) );
connect ( AccountManager::instance(), SIGNAL( stateChanged( Account* ,Accounts::Account::ConnectionState ) ), this, SLOT( accountStateChanged( Account*, Accounts::Account::ConnectionState ) ) );
}
@ -82,7 +86,7 @@ AccountModel::data( const QModelIndex& index, int role ) const
if ( !hasIndex( index.row(), index.column(), index.parent() ) )
return QVariant();
AccountModelNode* node = nodeFromIndex( index );
const AccountModelNode* node = nodeFromIndex( index );
if ( node->parent == m_rootItem ) {
// This is a top-level item. 3 cases
Q_ASSERT( node->type != AccountModelNode::AccountType ); // must not be of this type, these should be children (other branch of if)
@ -255,12 +259,267 @@ AccountModel::data( const QModelIndex& index, int role ) const
return QVariant();
}
bool
AccountModel::setData( const QModelIndex& index, const QVariant& value, int role )
{
if ( !index.isValid() || !hasIndex( index.row(), index.column(), index.parent() ) )
return false;
AccountModelNode* node = nodeFromIndex( index );
if ( role == CheckboxClickedRole )
{
// All checkboxes are for turning on/off an account. So we can just do that
Q_ASSERT( node->account || node->resolverAccount || node->atticaAccount );
Q_ASSERT( node->type != AccountModelNode::FactoryType );
Account* acct = 0;
switch ( node->type )
{
case AccountModelNode::AccountType:
case AccountModelNode::UniqueFactoryType:
acct = node->account;
break;
case AccountModelNode::AtticaType:
acct = node->atticaAccount;
break;
case AccountModelNode::ManualResolverType:
acct = node->resolverAccount;
break;
default:
;
};
Q_ASSERT( acct );
Qt::CheckState state = static_cast< Qt::CheckState >( value.toInt() );
if ( state == Qt::Checked && !acct->enabled() )
AccountManager::instance()->enableAccount( acct );
else if( state == Qt::Unchecked )
AccountManager::instance()->disableAccount( acct );
acct->sync();
emit dataChanged( index, index );
return true;
}
// The install/create/remove/etc button was clicked. Handle it properly depending on this item
if ( role == ButtonClickedRole )
{
switch ( node->type )
{
case AccountModelNode::FactoryType:
case AccountModelNode::UniqueFactoryType:
{
Q_ASSERT( node->factory );
// Make a new account of this factory type
emit createAccount( node->factory );
break;
}
case AccountModelNode::AccountType:
case AccountModelNode::ManualResolverType:
{
Q_ASSERT( node->account || node->resolverAccount );
Account* acct = node->type == AccountModelNode::AccountType ? node->account : node->resolverAccount;
// This is a child account, and the remove button was just hit. Remove it!
// OR this is a manually added resolver, and
// the only thing we can do with a manual resolver is remove it completely from the list
AccountManager::instance()->removeAccount( acct );
break;
}
case AccountModelNode::AtticaType:
{
// This is an attica resolver, may be installed or not. Handle it properly
Q_ASSERT( node->atticaContent.isValid() );
Attica::Content resolver = node->atticaContent;
AtticaManager::ResolverState state = AtticaManager::instance()->resolverState( resolver );
if ( role == Qt::EditRole )
{
switch( state )
{
case AtticaManager::Uninstalled:
// install
AtticaManager::instance()->installResolver( resolver );
break;
case AtticaManager::Installing:
case AtticaManager::Upgrading:
// Do nothing, busy
break;
case AtticaManager::Installed:
// Uninstall
AtticaManager::instance()->uninstallResolver( resolver );
break;
case AtticaManager::NeedsUpgrade:
AtticaManager::instance()->upgradeResolver( resolver );
break;
default:
//FIXME -- this handles e.g. Failed
break;
};
}
emit dataChanged( index, index );
}
}
return true;
}
if ( role == RatingRole )
{
// We only support rating Attica resolvers for the moment.
Q_ASSERT( node->type == AccountModelNode::AtticaType );
AtticaManager::ResolverState state = AtticaManager::instance()->resolverState( node->atticaContent );
// For now only allow rating if a resolver is installed!
if ( state != AtticaManager::Installed && state != AtticaManager::NeedsUpgrade )
return false;
if ( AtticaManager::instance()->userHasRated( node->atticaContent ) )
return false;
node->atticaContent.setRating( value.toInt() * 20 );
AtticaManager::instance()->uploadRating( node->atticaContent );
emit dataChanged( index, index );
return true;
}
return false;
}
void
AccountModel::accountAdded( Account* account )
{
// Find the factory this belongs up, and update
AccountFactory* factory = AccountManager::instance()->factoryForAccount( account );
for ( int i = 0; i < m_rootItem->children.size(); i++ )
{
AccountModelNode* n = m_rootItem->children.at( i );
if ( n->factory == factory )
{
if ( factory->isUnique() )
{
Q_ASSERT( n->type == AccountModelNode::UniqueFactoryType );
n->account = account;
const QModelIndex idx = index( i, 0, QModelIndex() );
emit dataChanged( idx, idx );
return;
}
else
{
Q_ASSERT( n->type == AccountModelNode::FactoryType );
// This is our parent
beginInsertRows( index( i, 0, QModelIndex() ), n->children.size(), n->children.size() );
new AccountModelNode( n, account );
endInsertRows();
return;
}
}
}
// Not matched with a factory. Then just add it at the end
if ( AtticaResolverAccount* attica = qobject_cast< AtticaResolverAccount* >( account ) )
{
Attica::Content::List allAtticaContent = AtticaManager::instance()->resolvers();
foreach ( const Attica::Content& c, allAtticaContent )
{
if ( attica->atticaId() == c.id() )
{
// This is us. Create the row
// const int count = m_rootItem->children.size()
// beginInsertRows( QModelIndex(), );
// new AccountModelNode( );
}
}
}
}
void
AccountModel::accountStateChanged( Account* account , Account::ConnectionState )
{
// Find the factory this belongs up, and update
AccountFactory* factory = AccountManager::instance()->factoryForAccount( account );
for ( int i = 0; i < m_rootItem->children.size(); i++ )
{
AccountModelNode* n = m_rootItem->children.at( i );
if ( n->type != AccountModelNode::FactoryType )
{
// If this is not a non-unique factory, it has as top-level account, so find that and update it
// For each type that this node could be, check the corresponding data
if ( ( n->type == AccountModelNode::UniqueFactoryType && n->account && n->account == account ) ||
( n->type == AccountModelNode::AccountType && n->account == account ) ||
( n->type == AccountModelNode::AtticaType && n->atticaAccount && n->atticaAccount == account ) ||
( n->type == AccountModelNode::ManualResolverType && n->resolverAccount && n->resolverAccount == account ) )
{
const QModelIndex idx = index( i, 0, QModelIndex() );
emit dataChanged( idx, idx );
}
}
else
{
for ( int k = 0; k < n->children.size(); k++ )
{
AccountModelNode* childAccount = n->children.at( k );
Q_ASSERT( childAccount->type == AccountModelNode::AccountType );
if ( childAccount->account == account )
{
const QModelIndex parent = index( i, 0, QModelIndex() );
const QModelIndex idx = index( k, 0, parent );
emit dataChanged( idx, idx );
}
}
}
}
}
void
AccountModel::accountRemoved( Account* account )
{
// Find the factory this belongs up, and update
AccountFactory* factory = AccountManager::instance()->factoryForAccount( account );
for ( int i = 0; i < m_rootItem->children.size(); i++ )
{
AccountModelNode* n = m_rootItem->children.at( i );
if ( n->factory == factory )
{
if ( factory->isUnique() )
{
Q_ASSERT( n->type == AccountModelNode::UniqueFactoryType );
n->account = account;
const QModelIndex idx = index( i, 0, QModelIndex() );
emit dataChanged( idx, idx );
}
else
{
Q_ASSERT( n->type == AccountModelNode::FactoryType );
// This is our parent
beginInsertRows( index( i, 0, QModelIndex() ), n->children.size(), n->children.size() );
new AccountModelNode( n, account );
endInsertRows();
}
}
}
}
int
AccountModel::columnCount( const QModelIndex& parent ) const
{
return 1;
}
int
AccountModel::rowCount( const QModelIndex& parent ) const
{
@ -273,6 +532,7 @@ AccountModel::rowCount( const QModelIndex& parent ) const
return nodeFromIndex( parent )->children.count();
}
QModelIndex
AccountModel::parent( const QModelIndex& child ) const
{
@ -293,6 +553,7 @@ AccountModel::parent( const QModelIndex& child ) const
return createIndex( m_rootItem->children.indexOf( parent ), 0, parent );
}
QModelIndex
AccountModel::index( int row, int column, const QModelIndex& parent ) const
{
@ -309,6 +570,7 @@ AccountModel::index( int row, int column, const QModelIndex& parent ) const
return QModelIndex();
}
AccountModelNode*
AccountModel::nodeFromIndex( const QModelIndex& idx ) const
{

View File

@ -21,6 +21,8 @@
#include "dllmacro.h"
#include "Account.h"
#include <QAbstractItemModel>
@ -53,7 +55,10 @@ public:
ErrorString = Qt::UserRole + 27,
// used by individual accounts
AccountData = Qt::UserRole + 28 // raw plugin
AccountData = Qt::UserRole + 28, // raw plugin
CheckboxClickedRole = Qt::UserRole + 29, // the checkbox for this row was toggled
ButtonClickedRole = Qt::UserRole + 30, // the generic install/create/remove/etc/ button was clicked
};
enum RowType {
@ -80,6 +85,15 @@ public:
virtual int rowCount( const QModelIndex& parent = QModelIndex() ) const;
virtual QModelIndex parent( const QModelIndex& child ) const;
virtual QModelIndex index( int row, int column, const QModelIndex& parent = QModelIndex() ) const;
virtual bool setData( const QModelIndex& index, const QVariant& value, int role = Qt::EditRole );
signals:
void createAccount( Tomahawk::Accounts::AccountFactory* factory );
private slots:
void accountAdded( Tomahawk::Accounts::Account* );
void accountRemoved( Tomahawk::Accounts::Account* );
void accountStateChanged( Account*, Accounts::Account::ConnectionState );
private:
AccountModelNode* nodeFromIndex( const QModelIndex& index ) const;

View File

@ -35,7 +35,7 @@ namespace Accounts {
* Basically a union with possible types:
* 1) AccountFactory* for accounts that are not unique (jabber, google, twitter)
* 2) Account* for accounts that are associated with an AccountFactory (children of AccountFactory)
* 3) Attica::Content for AtticaResolverAccounts (with associated AtticaResolverAccount*) (all synchroton resolvers)
* 3) Attica::Content for AtticaResolverAccounts (with associated AtticaResolverAccount*) (all synchrotron resolvers)
* 4) ResolverAccount* for manually added resolvers (from file).
* 5) AccountFactory* + Account* for factories that are unique
*

View File

@ -39,7 +39,6 @@
#include "tomahawkapp.h"
#include "tomahawksettings.h"
#include "delegateconfigwrapper.h"
#include "GetNewStuffDialog.h"
#include "musicscanner.h"
#include "pipeline.h"
#include "resolver.h"
@ -102,19 +101,21 @@ SettingsDialog::SettingsDialog( QWidget *parent )
#endif
// SIP PLUGINS
AccountDelegate* sipdel = new AccountDelegate( this );
ui->accountsView->setItemDelegate( sipdel );
AccountDelegate* accountDelegate = new AccountDelegate( this );
ui->accountsView->setItemDelegate( accountDelegate );
ui->accountsView->setContextMenuPolicy( Qt::CustomContextMenu );
ui->accountsView->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel );
// connect( sipdel, SIGNAL( openConfig( Tomahawk::Accounts::Account* ) ), this, SLOT( openAccountConfig( Tomahawk::Accounts::Account* ) ) );
connect( accountDelegate, SIGNAL( openConfig( Tomahawk::Accounts::Account* ) ), this, SLOT( openAccountConfig( Tomahawk::Accounts::Account* ) ) );
connect( accountDelegate, SIGNAL( update( QModelIndex ) ), ui->accountsView, SLOT( update( QModelIndex ) ) );
connect( ui->accountsView, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( accountContextMenuRequest( QPoint ) ) );
m_accountModel = new AccountModel( this );
ui->accountsView->setModel( m_accountModel );
ui->accountsView->expandAll();
connect( ui->addNewServiceBtn, SIGNAL( clicked( bool ) ), this, SLOT( getMoreResolvers() ) );
connect( ui->removeServiceBtn, SIGNAL( clicked( bool ) ), this, SLOT( accountDeleted( bool ) ) );
connect( m_accountModel, SIGNAL( createAccount( Tomahawk::Accounts::AccountFactory* ) ), this, SLOT( createAccountFromFactory( Tomahawk::Accounts::AccountFactory* ) ) );
connect( AtticaManager::instance(), SIGNAL( resolverInstalled( QString ) ), this, SLOT( accountAdded( Tomahawk::Accounts::Account* ) ) );
connect( AtticaManager::instance(), SIGNAL( resolverUninstalled( QString ) ), this, SLOT( accountUninstalled( QString ) ) );
@ -425,22 +426,6 @@ SettingsDialog::onLastFmFinished()
}
void
SettingsDialog::getMoreResolvers()
{
#if defined(Q_WS_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();
Q_UNUSED( ret );
#endif
}
void
SettingsDialog::accountInstalled(Account* account)
{
@ -469,14 +454,6 @@ SettingsDialog::accountsSelectionChanged()
}
void
SettingsDialog::getMoreResolversFinished( int ret )
{
Q_UNUSED( ret );
sender()->deleteLater();
}
void
SettingsDialog::openAccountConfig( Account* account )
{

View File

@ -95,8 +95,6 @@ private slots:
void onAccountRowDeleted( bool );
void accountsSelectionChanged();
void getMoreResolvers();
void getMoreResolversFinished( int );
void accountInstalled( Tomahawk::Accounts::Account* account );
void accountUninstalled( const QString& acct );
@ -125,4 +123,3 @@ private:
#endif // SETTINGSDIALOG_H
struct A;