Services
Merge branch 'accounts' Conflicts: resources.qrc src/accounts/zeroconf/zeroconf.cpp
@@ -111,10 +111,10 @@ 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 "" "")
|
||||
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" TRUE "" "")
|
||||
|
||||
macro_optional_find_package(QuaZip)
|
||||
macro_log_feature(QuaZip_FOUND "QuaZip" "Provides support for extracting downloaded resolvers automatically." "http://quazip.sourceforge.net/" FALSE "" "")
|
||||
macro_log_feature(QuaZip_FOUND "QuaZip" "Provides support for extracting downloaded resolvers automatically." "http://quazip.sourceforge.net/" TRUE "" "")
|
||||
|
||||
macro_optional_find_package(Jreen)
|
||||
macro_log_feature(LIBJREEN_FOUND "Jreen" "Qt XMPP Library" "https://github.com/euroelessar/jreen" FALSE "" "Jreen is needed for the Jabber SIP plugin.\n")
|
||||
|
@@ -280,7 +280,7 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
|
||||
File "${INSTALL_PATH}\bin\libtomahawk_portfwd.dll"
|
||||
File "${INSTALL_PATH}\bin\libtomahawk_lastfm2.dll"
|
||||
File "${INSTALL_PATH}\bin\libtomahawklib.dll"
|
||||
File "${INSTALL_PATH}\lib\libtomahawk_sip*.dll"
|
||||
File "${INSTALL_PATH}\lib\libtomahawk_account_*.dll"
|
||||
!endif
|
||||
!ifndef INSTALL_PATH
|
||||
;Main executable.
|
||||
@@ -293,7 +293,7 @@ Section "Tomahawk Player" SEC_TOMAHAWK_PLAYER
|
||||
File "${BUILD_PATH}\libqxtweb-standalone.dll"
|
||||
File "${BUILD_PATH}\libtomahawk_portfwd.dll"
|
||||
File "${BUILD_PATH}\libtomahawk_lastfm2.dll"
|
||||
File "${BUILD_PATH}\libtomahawk_sip*.dll"
|
||||
File "${BUILD_PATH}\libtomahawk_account_*.dll"
|
||||
!endif
|
||||
|
||||
;License & release notes.
|
||||
|
BIN
data/images/lastfm-icon.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
@@ -134,6 +134,7 @@
|
||||
<file>data/images/no-album-no-case.png</file>
|
||||
<file>data/images/rdio.png</file>
|
||||
<file>data/images/grooveshark.png</file>
|
||||
<file>data/images/lastfm-icon.png</file>
|
||||
<file>data/sql/dbmigrate-27_to_28.sql</file>
|
||||
<file>data/images/process-stop.png</file>
|
||||
</qresource>
|
||||
|
650
src/AccountDelegate.cpp
Normal file
@@ -0,0 +1,650 @@
|
||||
/*
|
||||
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 "AccountDelegate.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include "accounts/AccountModel.h"
|
||||
#include "accounts/Account.h"
|
||||
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
|
||||
#define CHILD_ACCOUNT_HEIGHT 24
|
||||
|
||||
#define PADDING 4
|
||||
#define PADDING_BETWEEN_STARS 2
|
||||
#define STAR_SIZE 12
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
#define TOPLEVEL_ACCOUNT_HEIGHT 72
|
||||
#else
|
||||
#define TOPLEVEL_ACCOUNT_HEIGHT 68
|
||||
#endif
|
||||
|
||||
#define ICONSIZE 40
|
||||
#define WRENCH_SIZE 24
|
||||
#define SMALL_WRENCH_SIZE 16
|
||||
#define STATUS_ICON_SIZE 13
|
||||
#define CHECK_LEFT_EDGE 8
|
||||
#define REMOVE_ICON_SIZE 12
|
||||
|
||||
using namespace Tomahawk;
|
||||
using namespace Accounts;
|
||||
|
||||
AccountDelegate::AccountDelegate( QObject* parent )
|
||||
: QStyledItemDelegate ( parent )
|
||||
{
|
||||
|
||||
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_onlineIcon.load( RESPATH "images/sipplugin-online.png" );
|
||||
m_offlineIcon.load( RESPATH "images/sipplugin-offline.png" );
|
||||
m_removeIcon.load( RESPATH "images/list-remove.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_onlineIcon = m_onlineIcon.scaled( STATUS_ICON_SIZE, STATUS_ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
|
||||
m_offlineIcon = m_offlineIcon.scaled( STATUS_ICON_SIZE, STATUS_ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
|
||||
m_onHoverStar = m_onHoverStar.scaled( STAR_SIZE, STAR_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
|
||||
m_removeIcon = m_removeIcon.scaled( REMOVE_ICON_SIZE, REMOVE_ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
|
||||
|
||||
m_defaultCover = m_defaultCover.scaled( ICONSIZE, ICONSIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
|
||||
|
||||
}
|
||||
|
||||
|
||||
QSize
|
||||
AccountDelegate::sizeHint( const QStyleOptionViewItem&, const QModelIndex& index ) const
|
||||
{
|
||||
AccountModel::RowType rowType = static_cast< AccountModel::RowType >( index.data( AccountModel::RowTypeRole ).toInt() );
|
||||
if ( rowType == AccountModel::TopLevelAccount || rowType == AccountModel::UniqueFactory || rowType == AccountModel::CustomAccount )
|
||||
return QSize( 200, TOPLEVEL_ACCOUNT_HEIGHT );
|
||||
else if ( rowType == AccountModel::TopLevelFactory )
|
||||
{
|
||||
// Make more space for each account we have to show.
|
||||
AccountFactory* fac = qobject_cast< AccountFactory* >( index.data( AccountModel::AccountData ).value< QObject* >() );
|
||||
if ( fac->isUnique() )
|
||||
return QSize( 200, TOPLEVEL_ACCOUNT_HEIGHT );
|
||||
|
||||
const QList< Account* > accts = index.data( AccountModel::ChildrenOfFactoryRole ).value< QList< Tomahawk::Accounts::Account* > >();
|
||||
const QSize s = QSize( 200, TOPLEVEL_ACCOUNT_HEIGHT + 12 * accts.size()-1 );
|
||||
|
||||
if ( s != m_sizeHints[ index ] )
|
||||
const_cast< AccountDelegate* >( this )->sizeHintChanged( index ); // FU KTHBBQ
|
||||
|
||||
m_sizeHints[ index ] = s;
|
||||
return s;
|
||||
}
|
||||
|
||||
return QSize();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
QStyleOptionViewItemV4 opt = option;
|
||||
initStyleOption( &opt, index );
|
||||
|
||||
// draw the background
|
||||
const QWidget* w = opt.widget;
|
||||
QStyle* style = w ? w->style() : QApplication::style();
|
||||
style->drawPrimitive( QStyle::PE_PanelItemViewItem, &opt, painter, w );
|
||||
|
||||
painter->setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
QFont titleFont = opt.font;
|
||||
titleFont.setBold( true );
|
||||
titleFont.setPointSize( titleFont.pointSize() + 2 );
|
||||
const QFontMetrics titleMetrics( titleFont );
|
||||
|
||||
QFont authorFont = opt.font;
|
||||
authorFont.setItalic( true );
|
||||
authorFont.setPointSize( authorFont.pointSize() - 1 );
|
||||
#ifdef Q_OS_MAC
|
||||
authorFont.setPointSize( authorFont.pointSize() - 1 );
|
||||
#endif
|
||||
const QFontMetrics authorMetrics( authorFont );
|
||||
|
||||
QFont descFont = authorFont;
|
||||
descFont.setItalic( false );
|
||||
const QFontMetrics descMetrics( descFont );
|
||||
|
||||
QFont installFont = opt.font;
|
||||
installFont.setPointSize( installFont.pointSize() - 1 );
|
||||
const QFontMetrics installMetrics( descFont );
|
||||
|
||||
const int height = opt.rect.height();
|
||||
const int center = height / 2 + opt.rect.top();
|
||||
|
||||
// Left account enable/disable checkbox
|
||||
const AccountModel::RowType rowType = static_cast< AccountModel::RowType >( index.data( AccountModel::RowTypeRole ).toInt() );
|
||||
int leftEdge = PADDING;
|
||||
// draw checkbox first
|
||||
const int checkboxYPos = ( center ) - ( WRENCH_SIZE / 2 );
|
||||
QRect checkRect = QRect( leftEdge, checkboxYPos, WRENCH_SIZE, WRENCH_SIZE );
|
||||
QStyleOptionViewItemV4 opt2 = opt;
|
||||
opt2.rect = checkRect;
|
||||
drawCheckBox( opt2, painter, opt.widget );
|
||||
leftEdge += WRENCH_SIZE + PADDING / 2;
|
||||
|
||||
// Pixmap
|
||||
QPixmap p = index.data( Qt::DecorationRole ).value< QPixmap >();
|
||||
QRect pixmapRect( leftEdge + PADDING, center - ICONSIZE/2, ICONSIZE, ICONSIZE );
|
||||
if ( p.isNull() ) // default image... TODO
|
||||
p = m_defaultCover;
|
||||
else
|
||||
p = p.scaled( pixmapRect.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation );
|
||||
|
||||
painter->drawPixmap( pixmapRect, p );
|
||||
|
||||
// Draw config wrench if there is one
|
||||
const bool hasConfigWrench = index.data( AccountModel::HasConfig ).toBool();
|
||||
int rightEdge = opt.rect.right();
|
||||
m_cachedConfigRects[ index ] = QRect();
|
||||
if ( hasConfigWrench )
|
||||
{
|
||||
const QRect confRect = QRect( rightEdge - 2*PADDING - WRENCH_SIZE, center - WRENCH_SIZE / 2, WRENCH_SIZE, WRENCH_SIZE );
|
||||
QStyleOptionToolButton topt;
|
||||
topt.rect = confRect;
|
||||
topt.pos = confRect.topLeft();
|
||||
|
||||
drawConfigWrench( painter, opt, topt );
|
||||
m_cachedConfigRects[ index ] = confRect;
|
||||
rightEdge = confRect.left();
|
||||
|
||||
}
|
||||
|
||||
// Draw individual accounts and add account button for factories
|
||||
m_cachedButtonRects[ index ] = QRect();
|
||||
|
||||
bool canDelete = index.data( AccountModel::CanDeleteRole ) .toBool();
|
||||
if ( rowType == Tomahawk::Accounts::AccountModel::TopLevelFactory )
|
||||
{
|
||||
const QList< Account* > accts = index.data( AccountModel::ChildrenOfFactoryRole ).value< QList< Tomahawk::Accounts::Account* > >();
|
||||
|
||||
QRect btnRect;
|
||||
const QString btnText = tr( "Add Account" );
|
||||
const int btnWidth = installMetrics.width( btnText ) + 2*PADDING;
|
||||
|
||||
if ( accts.isEmpty() )
|
||||
{
|
||||
Q_ASSERT( !hasConfigWrench );
|
||||
|
||||
// Draw button in center of row
|
||||
btnRect= QRect( opt.rect.right() - PADDING - btnWidth, center - ( installMetrics.height() + 4 ) / 2, btnWidth, installMetrics.height() + 2*PADDING );
|
||||
rightEdge = btnRect.left();
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->save();
|
||||
painter->setFont( installFont );
|
||||
int oldRightEdge = rightEdge;
|
||||
rightEdge = drawAccountList( painter, opt, accts, rightEdge );
|
||||
painter->restore();
|
||||
|
||||
btnRect = QRect( opt.rect.right() - PADDING - btnWidth, opt.rect.bottom() - installMetrics.height() - 3*PADDING, btnWidth, installMetrics.height() + 2*PADDING );
|
||||
#ifdef Q_WS_MAC
|
||||
btnRect.adjust( -4, 0, 4, 0 );
|
||||
#endif
|
||||
}
|
||||
|
||||
leftEdge = btnRect.left();
|
||||
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, btnText );
|
||||
painter->restore();
|
||||
}
|
||||
else if ( rowType == AccountModel::UniqueFactory )
|
||||
{
|
||||
// Display as usual, except if it has an account, show the status.
|
||||
const QList< Account* > accts = index.data( AccountModel::ChildrenOfFactoryRole ).value< QList< Tomahawk::Accounts::Account* > >();
|
||||
if ( !accts.isEmpty() )
|
||||
{
|
||||
Q_ASSERT( accts.size() == 1 );
|
||||
|
||||
rightEdge = drawStatus( painter, QPointF( rightEdge, center - painter->fontMetrics().height()/2 ), accts.first(), true );
|
||||
}
|
||||
|
||||
}
|
||||
else if ( canDelete )
|
||||
{
|
||||
const QString btnText = tr( "Remove Account" );
|
||||
const int btnWidth = installMetrics.width( btnText ) + 2*PADDING;
|
||||
QRect btnRect;
|
||||
|
||||
if ( hasConfigWrench )
|
||||
btnRect = QRect( opt.rect.right() - PADDING - btnWidth, opt.rect.bottom() - installMetrics.height() - 3*PADDING, btnWidth, installMetrics.height() + 2*PADDING );
|
||||
else
|
||||
btnRect = QRect( opt.rect.right() - PADDING - btnWidth, center - ( installMetrics.height() + 4 ) / 2, btnWidth, installMetrics.height() + 2*PADDING );
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
btnRect.adjust( -4, 2, 4, -2 );
|
||||
#endif
|
||||
leftEdge = btnRect.left();
|
||||
m_cachedButtonRects[ index ] = btnRect;
|
||||
|
||||
painter->save();
|
||||
painter->setPen( opt.palette.color( QPalette::Active, QPalette::AlternateBase ) );
|
||||
|
||||
drawRoundedButton( painter, btnRect, true );
|
||||
|
||||
painter->setFont( installFont );
|
||||
painter->drawText( btnRect, Qt::AlignCenter, btnText );
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
// Draw the title and description
|
||||
// title
|
||||
QString title = index.data( Qt::DisplayRole ).toString();
|
||||
const int rightTitleEdge = rightEdge - PADDING;
|
||||
const int leftTitleEdge = pixmapRect.right() + PADDING;
|
||||
painter->setFont( titleFont );
|
||||
QRect textRect;
|
||||
const bool canRate = index.data( AccountModel::CanRateRole ).toBool();
|
||||
if ( canRate )
|
||||
{
|
||||
textRect = QRect( leftTitleEdge, opt.rect.top() + PADDING, rightTitleEdge - leftTitleEdge, painter->fontMetrics().height() );
|
||||
}
|
||||
else
|
||||
{
|
||||
textRect = QRect( leftTitleEdge, opt.rect.top() + PADDING, rightTitleEdge - leftTitleEdge, center - opt.rect.top() - PADDING );
|
||||
}
|
||||
painter->drawText( textRect, Qt::AlignVCenter | Qt::AlignLeft, title );
|
||||
|
||||
// author
|
||||
QString author = index.data( AccountModel::AuthorRole ).toString();
|
||||
int runningBottom = textRect.bottom();
|
||||
if ( !author.isEmpty() && canRate )
|
||||
{
|
||||
painter->save();
|
||||
painter->setFont( authorFont );
|
||||
painter->setPen( QColor( Qt::gray ).darker( 150 ) );
|
||||
const int authorWidth = authorMetrics.width( author );
|
||||
const QRect authorRect( textRect.left(), textRect.bottom() + PADDING/2, authorWidth + 6, authorMetrics.height() );
|
||||
painter->drawText( authorRect, Qt::AlignLeft | Qt::AlignVCenter, author );
|
||||
painter->restore();
|
||||
|
||||
runningBottom = authorRect.bottom();
|
||||
}
|
||||
|
||||
// description
|
||||
QString desc = index.data( AccountModel::DescriptionRole ).toString();
|
||||
const int descWidth = rightEdge - leftTitleEdge - PADDING;
|
||||
painter->setFont( descFont );
|
||||
const QRect descRect( leftTitleEdge, runningBottom + PADDING, descWidth, painter->fontMetrics().height() );
|
||||
desc = painter->fontMetrics().elidedText( desc, Qt::ElideRight, descWidth );
|
||||
painter->drawText( descRect, Qt::AlignLeft | Qt::TextWordWrap | Qt::AlignTop, desc );
|
||||
runningBottom = descRect.bottom();
|
||||
|
||||
if ( index.data( AccountModel::CanRateRole ).toBool() )
|
||||
{
|
||||
// rating stars
|
||||
const int rating = index.data( AccountModel::RatingRole ).toInt();
|
||||
|
||||
// int runningEdge = opt.rect.right() - 2*PADDING - ratingWidth;
|
||||
int runningEdge = textRect.left();
|
||||
// int starsTop = opt.rect.bottom() - 3*PADDING - m_ratingStarNegative.height();
|
||||
int starsTop = runningBottom + PADDING;
|
||||
for ( int i = 1; i < 6; i++ )
|
||||
{
|
||||
QRect r( runningEdge, starsTop, 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;
|
||||
|
||||
const bool userHasRated = index.data( AccountModel::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
|
||||
QString count = tr( "%1 downloads" ).arg( index.data( AccountModel::DownloadCounterRole ).toInt() );
|
||||
painter->setFont( descFont );
|
||||
const int countW = painter->fontMetrics().width( count );
|
||||
const QRect countRect( runningEdge + 50, starsTop, countW, painter->fontMetrics().height() );
|
||||
count = painter->fontMetrics().elidedText( count, Qt::ElideRight, rightEdge - PADDING - countRect.left() );
|
||||
painter->drawText( countRect, Qt::AlignLeft | Qt::TextWordWrap, count );
|
||||
// runningEdge = authorRect.x();
|
||||
}
|
||||
|
||||
// Title and description!
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
AccountDelegate::drawAccountList( QPainter* painter, QStyleOptionViewItemV4& opt, const QList< Account* > accts, int rightEdge ) const
|
||||
{
|
||||
// list each account name, and show the online, offline icon
|
||||
const int textHeight = painter->fontMetrics().height() + 1;
|
||||
const int mid = opt.rect.bottom() - opt.rect.height() / 2;
|
||||
int runningRightEdge = rightEdge;
|
||||
int current = 0;
|
||||
|
||||
int leftOfAccounts = rightEdge;
|
||||
|
||||
if ( accts.size() % 2 == 1 )
|
||||
{
|
||||
// If there's an odd number, the center one is centered
|
||||
current = mid - ((textHeight + PADDING/2) * (accts.size()/2) ) - textHeight / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Even number, center between the middle ones
|
||||
current = mid - ((textHeight + PADDING/2) * (accts.size()/2) );
|
||||
}
|
||||
|
||||
for ( int i = 0; i < accts.size(); i++ )
|
||||
{
|
||||
// draw lightbulb and text
|
||||
runningRightEdge = drawStatus( painter, QPointF( rightEdge - PADDING, current), accts.at( i ) );
|
||||
|
||||
const QString label = accts.at( i )->accountFriendlyName();
|
||||
const QPoint textTopLeft( runningRightEdge - PADDING - painter->fontMetrics().width( label ), current);
|
||||
painter->drawText( QRect( textTopLeft, QSize( painter->fontMetrics().width( label ) + 1, textHeight ) ), label );
|
||||
|
||||
current += textHeight + PADDING/2;
|
||||
|
||||
leftOfAccounts = qMin( leftOfAccounts, textTopLeft.x() );
|
||||
}
|
||||
|
||||
return leftOfAccounts;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
const AccountModel::RowType rowType = static_cast< AccountModel::RowType >( index.data( AccountModel::RowTypeRole ).toInt() );
|
||||
if ( rowType == AccountModel::TopLevelAccount ||
|
||||
rowType == AccountModel::CustomAccount )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
else if ( rowType == AccountModel::TopLevelFactory )
|
||||
{
|
||||
AccountFactory* fac = qobject_cast< AccountFactory* >( index.data( AccountModel::AccountData ).value< QObject* >() );
|
||||
Q_ASSERT( fac ); // Should not be showing a config wrench if there is no account!
|
||||
emit openConfig( fac );
|
||||
}
|
||||
else if ( rowType == AccountModel::UniqueFactory )
|
||||
{
|
||||
const QList< Account* > accts = index.data( AccountModel::ChildrenOfFactoryRole ).value< QList< Tomahawk::Accounts::Account* > >();
|
||||
|
||||
Q_ASSERT( !accts.isEmpty() ); // If there's no account, why is there a config widget for this factory?
|
||||
Q_ASSERT( accts.size() == 1 );
|
||||
emit openConfig( accts.first() );
|
||||
}
|
||||
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();
|
||||
|
||||
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::CustomButtonRole );
|
||||
}
|
||||
}
|
||||
|
||||
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, bool red ) const
|
||||
{
|
||||
QPainterPath btnPath;
|
||||
const int radius = 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;
|
||||
if ( !red )
|
||||
{
|
||||
g.setColorAt( 0, QColor(54, 127, 211) );
|
||||
g.setColorAt( 0.5, QColor(43, 104, 182) );
|
||||
}
|
||||
else
|
||||
{
|
||||
g.setColorAt( 0, QColor(206, 63, 63) );
|
||||
g.setColorAt( 0.5, QColor(170, 52, 52) );
|
||||
}
|
||||
//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 );
|
||||
|
||||
if ( !red )
|
||||
{
|
||||
g.setColorAt( 0, QColor(34, 85, 159) );
|
||||
g.setColorAt( 0.5, QColor(35, 79, 147) );
|
||||
}
|
||||
else
|
||||
{
|
||||
g.setColorAt( 0, QColor(150, 50, 50) );
|
||||
g.setColorAt( 0.5, QColor(130, 40, 40) );
|
||||
}
|
||||
painter->fillPath( btnPath, g );
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
AccountDelegate::drawStatus( QPainter* painter, const QPointF& rightTopEdge, Account* acct, bool drawText ) const
|
||||
{
|
||||
QPixmap p;
|
||||
QString statusText;
|
||||
Account::ConnectionState state = acct->connectionState();
|
||||
if ( state == Account::Connected )
|
||||
{
|
||||
p = m_onlineIcon;
|
||||
statusText = tr( "Online" );
|
||||
}
|
||||
else if ( state == Account::Connecting )
|
||||
{
|
||||
p = m_offlineIcon;
|
||||
statusText = tr( "Connecting..." );
|
||||
}
|
||||
else
|
||||
{
|
||||
p = m_offlineIcon;
|
||||
statusText = tr( "Offline" );
|
||||
}
|
||||
|
||||
const int yPos = rightTopEdge.y();
|
||||
const QRect connectIconRect( rightTopEdge.x() - STATUS_ICON_SIZE, yPos, STATUS_ICON_SIZE, STATUS_ICON_SIZE );
|
||||
painter->drawPixmap( connectIconRect, p );
|
||||
|
||||
int leftEdge = connectIconRect.x();
|
||||
if ( drawText )
|
||||
{
|
||||
int width = painter->fontMetrics().width( statusText );
|
||||
int statusTextX = connectIconRect.x() - PADDING - width;
|
||||
painter->drawText( QRect( statusTextX, yPos, width, painter->fontMetrics().height() ), statusText );
|
||||
|
||||
leftEdge = statusTextX;
|
||||
}
|
||||
|
||||
return leftEdge;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountDelegate::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
|
||||
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( 14, 14 );
|
||||
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
|
||||
{
|
||||
QStyleOptionViewItemV4 opt = option;
|
||||
initStyleOption( &opt, idx );
|
||||
|
||||
// Top level item, return the corresponding rect
|
||||
const int ypos = ( opt.rect.top() + opt.rect.height() / 2 ) - ( WRENCH_SIZE / 2 );
|
||||
const QRect checkRect = QRect( PADDING, ypos, WRENCH_SIZE, WRENCH_SIZE );
|
||||
|
||||
return checkRect;
|
||||
|
||||
}
|
||||
|
||||
|
72
src/AccountDelegate.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ACCOUNTDELEGATE_H
|
||||
#define ACCOUNTDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
#include "accounts/AccountModel.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
class Account;
|
||||
|
||||
class AccountDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AccountDelegate( 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 );
|
||||
|
||||
signals:
|
||||
void update( const QModelIndex& idx );
|
||||
void openConfig( Tomahawk::Accounts::Account* );
|
||||
void openConfig( Tomahawk::Accounts::AccountFactory* );
|
||||
|
||||
private:
|
||||
void drawRoundedButton( QPainter* painter, const QRect& buttonRect, bool red = false ) const;
|
||||
// Returns new left edge
|
||||
int drawStatus( QPainter* painter, const QPointF& rightTopEdge, Account* acct, bool drawText = false ) const;
|
||||
void drawCheckBox( QStyleOptionViewItemV4& opt, QPainter* p, const QWidget* w ) const;
|
||||
void drawConfigWrench( QPainter* painter, QStyleOptionViewItemV4& option, QStyleOptionToolButton& topt ) const;
|
||||
// returns new left edge
|
||||
int drawAccountList( QPainter* painter, QStyleOptionViewItemV4& option, const QList< Account* > accounts, int rightEdge ) const;
|
||||
|
||||
QRect checkRectForIndex( const QStyleOptionViewItem &option, const QModelIndex &idx ) const;
|
||||
|
||||
QPixmap m_offlineIcon, m_onlineIcon, m_defaultCover, m_onHoverStar, m_ratingStarPositive, m_ratingStarNegative, m_removeIcon;
|
||||
int m_hoveringOver;
|
||||
QPersistentModelIndex m_hoveringItem, m_configPressed;
|
||||
mutable QHash< QPersistentModelIndex, QRect > m_cachedButtonRects;
|
||||
mutable QHash< QPersistentModelIndex, QRect > m_cachedStarRects;
|
||||
mutable QHash< QPersistentModelIndex, QRect > m_cachedConfigRects;
|
||||
mutable QHash< QPersistentModelIndex, QSize > m_sizeHints;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ACCOUNTDELEGATE_H
|
149
src/AccountFactoryWrapper.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
/* === 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 "AccountFactoryWrapper.h"
|
||||
|
||||
#include "accounts/Account.h"
|
||||
#include <accounts/AccountManager.h>
|
||||
#include "AccountFactoryWrapperDelegate.h"
|
||||
#include "delegateconfigwrapper.h"
|
||||
#include "ui_AccountFactoryWrapper.h"
|
||||
|
||||
using namespace Tomahawk::Accounts;
|
||||
AccountFactoryWrapper::AccountFactoryWrapper( AccountFactory* factory, QWidget* parent )
|
||||
: QDialog( parent, Qt::Sheet )
|
||||
, m_factory( factory )
|
||||
, m_ui( new Ui_AccountFactoryWrapper )
|
||||
, m_createAccount( false )
|
||||
{
|
||||
m_ui->setupUi( this );
|
||||
|
||||
setWindowTitle( factory->prettyName() );
|
||||
|
||||
m_ui->factoryIcon->setPixmap( factory->icon() );
|
||||
m_ui->factoryDescription->setText( factory->description() );
|
||||
|
||||
m_addButton = m_ui->buttonBox->addButton( tr( "Add Account" ), QDialogButtonBox::ActionRole );
|
||||
|
||||
AccountFactoryWrapperDelegate* del = new AccountFactoryWrapperDelegate( m_ui->accountsList );
|
||||
m_ui->accountsList->setItemDelegate( del );
|
||||
|
||||
connect( del, SIGNAL( openConfig( Tomahawk::Accounts::Account* ) ), this, SLOT( openAccountConfig( Tomahawk::Accounts::Account* ) ) );
|
||||
connect( del, SIGNAL( removeAccount( Tomahawk::Accounts::Account* ) ), this, SLOT( removeAccount( Tomahawk::Accounts::Account* ) ) );
|
||||
|
||||
load();
|
||||
|
||||
connect( m_ui->buttonBox, SIGNAL( rejected() ), this, SLOT( reject() ) );
|
||||
connect( m_ui->buttonBox, SIGNAL( accepted() ), this, SLOT( accept() ) );
|
||||
connect( m_ui->buttonBox, SIGNAL( clicked( QAbstractButton*) ), this, SLOT( buttonClicked( QAbstractButton* ) ) );
|
||||
|
||||
|
||||
connect ( AccountManager::instance(), SIGNAL( added( Tomahawk::Accounts::Account* ) ), this, SLOT( load() ) );
|
||||
connect ( AccountManager::instance(), SIGNAL( removed( Tomahawk::Accounts::Account* ) ), this, SLOT( load() ) );
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
setContentsMargins( 0, 0, 0, 0 );
|
||||
m_ui->verticalLayout->setSpacing( 6 );
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
AccountFactoryWrapper::load()
|
||||
{
|
||||
m_ui->accountsList->clear();
|
||||
foreach ( Account* acc, AccountManager::instance()->accounts() )
|
||||
{
|
||||
if ( AccountManager::instance()->factoryForAccount( acc ) == m_factory )
|
||||
{
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem( m_ui->accountsList );
|
||||
item->setData( 0, AccountRole, QVariant::fromValue< QObject *>( acc ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_ui->accountsList->model()->rowCount() == 0 )
|
||||
accept();
|
||||
|
||||
#ifndef Q_OS_MAC
|
||||
const int padding = 7;
|
||||
#else
|
||||
const int padding = 8;
|
||||
#endif
|
||||
const int height = m_ui->accountsList->model()->rowCount( QModelIndex() ) * ACCOUNT_ROW_HEIGHT + padding;
|
||||
|
||||
m_ui->accountsList->setFixedHeight( height );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountFactoryWrapper::openAccountConfig( Account* account )
|
||||
{
|
||||
if( account->configurationWidget() )
|
||||
{
|
||||
#ifndef Q_WS_MAC
|
||||
DelegateConfigWrapper dialog( account->configurationWidget(), QString("%1 Configuration" ).arg( account->accountFriendlyName() ), this );
|
||||
QWeakPointer< DelegateConfigWrapper > watcher( &dialog );
|
||||
int ret = dialog.exec();
|
||||
if( !watcher.isNull() && ret == QDialog::Accepted )
|
||||
{
|
||||
// send changed config to resolver
|
||||
account->saveConfig();
|
||||
}
|
||||
#else
|
||||
// on osx a sheet needs to be non-modal
|
||||
DelegateConfigWrapper* dialog = new DelegateConfigWrapper( account->configurationWidget(), QString("%1 Configuration" ).arg( account->accountFriendlyName() ), this, Qt::Sheet );
|
||||
dialog->setProperty( "accountplugin", QVariant::fromValue< QObject* >( account ) );
|
||||
connect( dialog, SIGNAL( finished( int ) ), this, SLOT( accountConfigClosed( int ) ) );
|
||||
|
||||
dialog->show();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountFactoryWrapper::accountConfigClosed( int value )
|
||||
{
|
||||
if( value == QDialog::Accepted )
|
||||
{
|
||||
DelegateConfigWrapper* dialog = qobject_cast< DelegateConfigWrapper* >( sender() );
|
||||
Account* account = qobject_cast< Account* >( dialog->property( "accountplugin" ).value< QObject* >() );
|
||||
account->saveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AccountFactoryWrapper::removeAccount( Tomahawk::Accounts::Account* acct )
|
||||
{
|
||||
AccountManager::instance()->removeAccount( acct );
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
void
|
||||
AccountFactoryWrapper::buttonClicked( QAbstractButton* button )
|
||||
{
|
||||
if ( button == m_addButton )
|
||||
{
|
||||
m_createAccount = true;
|
||||
emit createAccount( m_factory );
|
||||
return;
|
||||
}
|
||||
else
|
||||
reject();
|
||||
}
|
||||
|
66
src/AccountFactoryWrapper.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/* === 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 ACCOUNTFACTORYWRAPPER_H
|
||||
#define ACCOUNTFACTORYWRAPPER_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
class QAbstractButton;
|
||||
namespace Tomahawk {
|
||||
namespace Accounts {
|
||||
class AccountFactory;
|
||||
class Account;
|
||||
}
|
||||
}
|
||||
|
||||
class Ui_AccountFactoryWrapper;
|
||||
|
||||
// class AccountFactoryWrapper_
|
||||
class AccountFactoryWrapper : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum ExtraRoles {
|
||||
AccountRole = Qt::UserRole + 140
|
||||
};
|
||||
|
||||
explicit AccountFactoryWrapper( Tomahawk::Accounts::AccountFactory* factory, QWidget* parent = 0 );
|
||||
|
||||
bool doCreateAccount() const { return m_createAccount; }
|
||||
|
||||
signals:
|
||||
void createAccount( Tomahawk::Accounts::AccountFactory* factory );
|
||||
|
||||
public slots:
|
||||
void openAccountConfig( Tomahawk::Accounts::Account* );
|
||||
void accountConfigClosed( int value );
|
||||
void removeAccount( Tomahawk::Accounts::Account* );
|
||||
|
||||
private slots:
|
||||
void buttonClicked( QAbstractButton* );
|
||||
void load();
|
||||
|
||||
private:
|
||||
Tomahawk::Accounts::AccountFactory* m_factory;
|
||||
Ui_AccountFactoryWrapper* m_ui;
|
||||
QPushButton* m_addButton;
|
||||
bool m_createAccount;
|
||||
};
|
||||
|
||||
#endif // ACCOUNTFACTORYWRAPPER_H
|
110
src/AccountFactoryWrapper.ui
Normal file
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AccountFactoryWrapper</class>
|
||||
<widget class="QDialog" name="AccountFactoryWrapper">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>507</width>
|
||||
<height>150</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="factoryIcon">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="factoryDescription">
|
||||
<property name="text">
|
||||
<string>Description goes here</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="accountsList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="autoScroll">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="verticalScrollMode">
|
||||
<enum>QAbstractItemView::ScrollPerItem</enum>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="headerHidden">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
166
src/AccountFactoryWrapperDelegate.cpp
Normal file
@@ -0,0 +1,166 @@
|
||||
/* === 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 "AccountFactoryWrapperDelegate.h"
|
||||
#include "accounts/Account.h"
|
||||
#include "AccountFactoryWrapper.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
|
||||
using namespace Tomahawk::Accounts;
|
||||
|
||||
#define ICON_SIZE 15
|
||||
#define CONFIG_WRENCH_SIZE 20
|
||||
#define PADDING 4
|
||||
|
||||
AccountFactoryWrapperDelegate::AccountFactoryWrapperDelegate( QObject* parent )
|
||||
: QStyledItemDelegate( parent )
|
||||
{
|
||||
m_removePixmap.load( RESPATH "images/list-remove.png" );
|
||||
m_onlineIcon.load( RESPATH "images/sipplugin-online.png" );
|
||||
m_offlineIcon.load( RESPATH "images/sipplugin-offline.png" );
|
||||
|
||||
m_removePixmap = m_removePixmap.scaled( ICON_SIZE, ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
|
||||
m_onlineIcon = m_onlineIcon.scaled( ICON_SIZE, ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
|
||||
m_offlineIcon = m_offlineIcon.scaled( ICON_SIZE, ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation );
|
||||
|
||||
m_configIcon.addFile( RESPATH "images/configure.png", QSize( CONFIG_WRENCH_SIZE - 8, CONFIG_WRENCH_SIZE - 8 ) );
|
||||
}
|
||||
|
||||
void
|
||||
AccountFactoryWrapperDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
QStyleOptionViewItemV4 opt = option;
|
||||
initStyleOption( &opt, index );
|
||||
|
||||
const int center = opt.rect.height() / 2 + opt.rect.top();
|
||||
const int topIcon = center - ICON_SIZE/2;
|
||||
|
||||
// draw the background
|
||||
const QWidget* w = opt.widget;
|
||||
QStyle* style = w ? w->style() : QApplication::style();
|
||||
style->drawPrimitive( QStyle::PE_PanelItemViewItem, &opt, painter, w );
|
||||
|
||||
Account* acc = qobject_cast< Account* >( index.data( AccountFactoryWrapper::AccountRole ).value< QObject* >() );
|
||||
Q_ASSERT( acc );
|
||||
|
||||
// name on left
|
||||
painter->drawText( opt.rect.adjusted( PADDING, PADDING, -PADDING, -PADDING ), Qt::AlignLeft | Qt::AlignVCenter, acc->accountFriendlyName() );
|
||||
|
||||
// remove, config, status on right
|
||||
const QRect pmRect( opt.rect.right() - PADDING - m_removePixmap.width(), topIcon, ICON_SIZE, ICON_SIZE );
|
||||
painter->drawPixmap( pmRect, m_removePixmap );
|
||||
m_cachedButtonRects[ index ] = pmRect;
|
||||
|
||||
const QRect confRect( pmRect.left() - PADDING - CONFIG_WRENCH_SIZE, center - CONFIG_WRENCH_SIZE/2, CONFIG_WRENCH_SIZE, CONFIG_WRENCH_SIZE );
|
||||
|
||||
QStyleOptionToolButton topt;
|
||||
topt.rect = confRect;
|
||||
topt.pos = confRect.topLeft();
|
||||
topt.font = opt.font;
|
||||
topt.icon = m_configIcon;
|
||||
topt.iconSize = QSize( CONFIG_WRENCH_SIZE - 8, CONFIG_WRENCH_SIZE - 8 );
|
||||
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 );
|
||||
m_cachedConfigRects[ index ] = confRect;
|
||||
|
||||
QPixmap p;
|
||||
QString statusText;
|
||||
Account::ConnectionState state = acc->connectionState();
|
||||
if ( state == Account::Connected )
|
||||
{
|
||||
p = m_onlineIcon;
|
||||
statusText = tr( "Online" );
|
||||
}
|
||||
else if ( state == Account::Connecting )
|
||||
{
|
||||
p = m_offlineIcon;
|
||||
statusText = tr( "Connecting..." );
|
||||
}
|
||||
else
|
||||
{
|
||||
p = m_offlineIcon;
|
||||
statusText = tr( "Offline" );
|
||||
}
|
||||
|
||||
const QRect connectIconRect( confRect.left() - PADDING - ICON_SIZE, topIcon, ICON_SIZE, ICON_SIZE );
|
||||
painter->drawPixmap( connectIconRect, p );
|
||||
|
||||
int width = painter->fontMetrics().width( statusText );
|
||||
painter->drawText( QRect( connectIconRect.left() - PADDING - width, center - painter->fontMetrics().height()/2, width, painter->fontMetrics().height() ), statusText );
|
||||
|
||||
}
|
||||
|
||||
QSize
|
||||
AccountFactoryWrapperDelegate::sizeHint(const QStyleOptionViewItem&, const QModelIndex&) const
|
||||
{
|
||||
return QSize( 200, ACCOUNT_ROW_HEIGHT );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AccountFactoryWrapperDelegate::editorEvent( QEvent* event, QAbstractItemModel*, const QStyleOptionViewItem&, 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( AccountFactoryWrapper::AccountRole ).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();
|
||||
|
||||
if ( m_cachedButtonRects.contains( index ) && m_cachedButtonRects[ index ].contains( me->pos() ) )
|
||||
{
|
||||
Account* acct = qobject_cast< Account* >( index.data( AccountFactoryWrapper::AccountRole ).value< QObject* >() );
|
||||
emit removeAccount( acct );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright 2010-2012, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,35 +16,43 @@
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GETNEWSTUFFDELEGATE_H
|
||||
#define GETNEWSTUFFDELEGATE_H
|
||||
#ifndef ACCOUNTFACTORYWRAPPERDELEGATE_H
|
||||
#define ACCOUNTFACTORYWRAPPERDELEGATE_H
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
#define ACCOUNT_ROW_HEIGHT 20
|
||||
|
||||
class
|
||||
GetNewStuffDelegate : public QStyledItemDelegate
|
||||
namespace Tomahawk {
|
||||
namespace Accounts {
|
||||
class Account;
|
||||
}
|
||||
}
|
||||
|
||||
class AccountFactoryWrapperDelegate : public QStyledItemDelegate
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit GetNewStuffDelegate( QObject* parent = 0 );
|
||||
explicit AccountFactoryWrapperDelegate( 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;
|
||||
virtual bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index);
|
||||
|
||||
signals:
|
||||
void update( const QModelIndex& idx );
|
||||
void update( const QModelIndex& );
|
||||
|
||||
protected:
|
||||
virtual bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
|
||||
void openConfig( Tomahawk::Accounts::Account* );
|
||||
void removeAccount( Tomahawk::Accounts::Account* );
|
||||
|
||||
private:
|
||||
QPixmap m_defaultCover, m_onHoverStar, m_ratingStarPositive, m_ratingStarNegative;
|
||||
QPixmap m_removePixmap, m_offlineIcon, m_onlineIcon;
|
||||
QIcon m_configIcon;
|
||||
QModelIndex m_configPressed;
|
||||
|
||||
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;
|
||||
mutable QHash< QPersistentModelIndex, QRect > m_cachedButtonRects;
|
||||
mutable QHash< QPersistentModelIndex, QRect > m_cachedConfigRects;
|
||||
};
|
||||
|
||||
#endif // GETNEWSTUFFDELEGATE_H
|
||||
#endif // ACCOUNTFACTORYWRAPPERDELEGATE_H
|
@@ -74,13 +74,12 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui}
|
||||
audiocontrols.cpp
|
||||
settingsdialog.cpp
|
||||
diagnosticsdialog.cpp
|
||||
configdelegatebase.cpp
|
||||
sipconfigdelegate.cpp
|
||||
resolverconfigdelegate.cpp
|
||||
AccountDelegate.cpp
|
||||
settingslistdelegate.cpp
|
||||
resolversmodel.cpp
|
||||
tomahawkwindow.cpp
|
||||
LoadXSPFDialog.cpp
|
||||
AccountFactoryWrapper.cpp
|
||||
AccountFactoryWrapperDelegate.cpp
|
||||
)
|
||||
|
||||
SET( tomahawkHeaders ${tomahawkHeaders}
|
||||
@@ -100,13 +99,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
|
||||
@@ -126,14 +118,13 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui}
|
||||
audiocontrols.h
|
||||
settingsdialog.h
|
||||
diagnosticsdialog.h
|
||||
configdelegatebase.h
|
||||
resolverconfigdelegate.h
|
||||
sipconfigdelegate.h
|
||||
AccountDelegate.h
|
||||
settingslistdelegate.h
|
||||
resolversmodel.h
|
||||
delegateconfigwrapper.h
|
||||
tomahawkwindow.h
|
||||
LoadXSPFDialog.h
|
||||
AccountFactoryWrapper.h
|
||||
AccountFactoryWrapperDelegate.h
|
||||
)
|
||||
|
||||
SET( tomahawkUI ${tomahawkUI}
|
||||
@@ -144,8 +135,9 @@ SET( tomahawkUI ${tomahawkUI}
|
||||
|
||||
audiocontrols.ui
|
||||
|
||||
GetNewStuffDialog.ui
|
||||
LoadXSPFDialog.ui
|
||||
|
||||
AccountFactoryWrapper.ui
|
||||
)
|
||||
|
||||
INCLUDE_DIRECTORIES(
|
||||
@@ -171,6 +163,7 @@ INCLUDE_DIRECTORIES(
|
||||
${TAGLIB_INCLUDES}
|
||||
${PHONON_INCLUDES}
|
||||
${QJSON_INCLUDE_DIR}
|
||||
${LIBATTICA_INCLUDE_DIR}
|
||||
${LIBECHONEST_INCLUDE_DIR}
|
||||
${LIBECHONEST_INCLUDE_DIR}/..
|
||||
)
|
||||
@@ -200,7 +193,8 @@ IF(GLOOX_FOUND)
|
||||
SET( tomahawkHeaders ${tomahawkHeaders} xmppbot/xmppbot.h )
|
||||
SET( tomahawkSources ${tomahawkSources} xmppbot/xmppbot.cpp )
|
||||
ENDIF(GLOOX_FOUND)
|
||||
ADD_SUBDIRECTORY( sip )
|
||||
|
||||
ADD_SUBDIRECTORY( accounts )
|
||||
|
||||
IF(QCA2_FOUND)
|
||||
INCLUDE_DIRECTORIES( ${QCA2_INCLUDE_DIR} )
|
||||
|
@@ -1,323 +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
|
||||
AtticaManager::ResolverState state = static_cast< AtticaManager::ResolverState >( index.data( GetNewStuffModel::StateRole ).toInt() );
|
||||
QString actionText;
|
||||
switch( state )
|
||||
{
|
||||
case AtticaManager::Uninstalled:
|
||||
actionText = tr( "Install" );
|
||||
break;
|
||||
case AtticaManager::Installing:
|
||||
actionText = tr( "Installing" );
|
||||
break;
|
||||
case AtticaManager::Upgrading:
|
||||
actionText = tr( "Upgrading" );
|
||||
break;
|
||||
case AtticaManager::Failed:
|
||||
actionText = tr( "Failed" );
|
||||
break;
|
||||
case AtticaManager::Installed:
|
||||
actionText = tr( "Uninstall" );
|
||||
break;
|
||||
case AtticaManager::NeedsUpgrade:
|
||||
actionText = tr( "Upgrade" );
|
||||
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;
|
||||
}
|
@@ -1,54 +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"
|
||||
|
||||
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 );
|
||||
GetNewStuffDelegate* del = new GetNewStuffDelegate( ui->listView );
|
||||
connect( del, SIGNAL( update( QModelIndex ) ), ui->listView, SLOT( update( QModelIndex ) ) );
|
||||
ui->listView->setItemDelegate( del );
|
||||
ui->listView->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel );
|
||||
|
||||
ui->listView->setMouseTracking( true );
|
||||
|
||||
setMinimumSize( 560, 350 );
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
setMaximumSize( 560, 350 );
|
||||
setSizeGripEnabled( false );
|
||||
|
||||
ui->listView->setAttribute( Qt::WA_MacShowFocusRect, false );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
GetNewStuffDialog::~GetNewStuffDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
@@ -1,67 +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>282</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Download New Resolvers</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QListView" name="listView"/>
|
||||
</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>
|
||||
</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>
|
@@ -1,156 +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 <QPixmap>
|
||||
#include <QUrl>
|
||||
#include "AtticaManager.h"
|
||||
|
||||
GetNewStuffModel::GetNewStuffModel( QObject* parent )
|
||||
: QAbstractListModel ( parent )
|
||||
{
|
||||
|
||||
if ( AtticaManager::instance()->resolversLoaded() )
|
||||
m_contentList = AtticaManager::instance()->resolvers();
|
||||
|
||||
connect( AtticaManager::instance(), SIGNAL( resolversReloaded( Attica::Content::List ) ), this, SLOT( resolversReloaded( Attica::Content::List ) ) );
|
||||
connect( AtticaManager::instance(), SIGNAL( resolverStateChanged( QString ) ), this, SLOT( resolverStateChanged( QString ) ) );
|
||||
|
||||
}
|
||||
|
||||
GetNewStuffModel::~GetNewStuffModel()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
GetNewStuffModel::resolversReloaded( const Attica::Content::List& resolvers )
|
||||
{
|
||||
beginResetModel();
|
||||
m_contentList = resolvers;
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void
|
||||
GetNewStuffModel::resolverStateChanged( const QString& resolverId )
|
||||
{
|
||||
for ( int i = 0; i < m_contentList.count(); i++ )
|
||||
{
|
||||
const Attica::Content resolver = m_contentList[ 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();
|
||||
|
||||
Attica::Content resolver = m_contentList[ 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 ResolverType;
|
||||
case AuthorRole:
|
||||
return resolver.author();
|
||||
case StateRole:
|
||||
return (int)AtticaManager::instance()->resolverState( resolver );
|
||||
case UserHasRatedRole:
|
||||
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;
|
||||
|
||||
|
||||
Attica::Content resolver = m_contentList[ 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;
|
||||
m_contentList[ index.row() ].setRating( value.toInt() * 20 );
|
||||
AtticaManager::instance()->uploadRating( m_contentList[ index.row() ] );
|
||||
}
|
||||
emit dataChanged( index, index );
|
||||
|
||||
return true;
|
||||
}
|
@@ -1,64 +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 <QModelIndex>
|
||||
|
||||
#include <attica/content.h>
|
||||
#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 {
|
||||
ResolverType = 0,
|
||||
};
|
||||
|
||||
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:
|
||||
Attica::Content::List m_contentList;
|
||||
};
|
||||
|
||||
#endif // GETNEWSTUFFMODEL_H
|
@@ -1,9 +1,10 @@
|
||||
|
||||
IF( LIBJREEN_FOUND )
|
||||
ADD_SUBDIRECTORY( jabber )
|
||||
ENDIF( LIBJREEN_FOUND )
|
||||
add_subdirectory( xmpp )
|
||||
ENDIF()
|
||||
|
||||
IF( QTWEETLIB_FOUND AND BUILD_GUI )
|
||||
ADD_SUBDIRECTORY( twitter )
|
||||
ENDIF()
|
||||
|
||||
ADD_SUBDIRECTORY( zeroconf )
|
||||
ADD_SUBDIRECTORY( zeroconf )
|
@@ -1,6 +1,6 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.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
|
||||
@@ -16,26 +16,17 @@
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GETNEWSTUFFDIALOG_H
|
||||
#define GETNEWSTUFFDIALOG_H
|
||||
#ifndef ACCOUNTDLLMACRO_H
|
||||
#define ACCOUNTDLLMACRO_H
|
||||
|
||||
#include <QDialog>
|
||||
#ifdef Q_WS_WIN
|
||||
#ifdef ACCOUNTDLLEXPORT_PRO
|
||||
#define ACCOUNTDLLEXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define ACCOUNTDLLEXPORT __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define ACCOUNTDLLEXPORT
|
||||
#endif
|
||||
|
||||
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
|
||||
#endif
|
@@ -4,21 +4,23 @@ include( ${QT_USE_FILE} )
|
||||
add_definitions( ${QT_DEFINITIONS} )
|
||||
add_definitions( -DQT_PLUGIN )
|
||||
add_definitions( -DQT_SHARED )
|
||||
add_definitions( -DSIPDLLEXPORT_PRO )
|
||||
add_definitions( -DACCOUNTDLLEXPORT_PRO )
|
||||
|
||||
set( twitterSources
|
||||
twitter.cpp
|
||||
set( twitterAccountSources
|
||||
twitteraccount.cpp
|
||||
twitterconfigwidget.cpp
|
||||
tomahawkoauthtwitter.cpp
|
||||
sip/twittersip.cpp
|
||||
)
|
||||
|
||||
set( twitterHeaders
|
||||
twitter.h
|
||||
set( twitterAccountHeaders
|
||||
twitteraccount.h
|
||||
twitterconfigwidget.h
|
||||
tomahawkoauthtwitter.h
|
||||
sip/twittersip.h
|
||||
)
|
||||
|
||||
set( twitterUI
|
||||
set( twitterAccountUI
|
||||
twitterconfigwidget.ui
|
||||
)
|
||||
|
||||
@@ -27,10 +29,10 @@ include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ..
|
||||
${QTWEETLIB_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
qt4_wrap_cpp( twitterAccountMoc ${twitterAccountHeaders} )
|
||||
qt4_wrap_ui( twitterAccountUI_H ${twitterAccountUI} )
|
||||
qt4_add_resources( RC_SRCS "resources.qrc" )
|
||||
qt4_wrap_cpp( twitterMoc ${twitterHeaders} )
|
||||
qt4_wrap_ui( twitterUI_H ${twitterUI} )
|
||||
add_library( tomahawk_siptwitter SHARED ${twitterUI_H} ${twitterSources} ${twitterMoc} ${RC_SRCS} )
|
||||
add_library( tomahawk_account_twitter MODULE ${twitterAccountUI_H} ${twitterAccountSources} ${twitterAccountMoc} ${RC_SRCS} )
|
||||
|
||||
IF( WIN32 )
|
||||
SET( OS_SPECIFIC_LINK_LIBRARIES
|
||||
@@ -40,7 +42,7 @@ SET( OS_SPECIFIC_LINK_LIBRARIES
|
||||
)
|
||||
ENDIF( WIN32 )
|
||||
|
||||
target_link_libraries( tomahawk_siptwitter
|
||||
target_link_libraries( tomahawk_account_twitter
|
||||
${TOMAHAWK_LIBRARIES}
|
||||
${QTWEETLIB_LIBRARIES}
|
||||
${QT_LIBRARIES}
|
||||
@@ -51,4 +53,4 @@ IF( APPLE )
|
||||
# SET( CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} "-undefined dynamic_lookup" )
|
||||
ENDIF( APPLE )
|
||||
|
||||
install( TARGETS tomahawk_siptwitter DESTINATION ${CMAKE_INSTALL_LIBDIR} )
|
||||
install( TARGETS tomahawk_account_twitter DESTINATION ${CMAKE_INSTALL_LIBDIR} )
|
714
src/accounts/twitter/sip/twittersip.cpp
Normal file
@@ -0,0 +1,714 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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 "twittersip.h"
|
||||
|
||||
#include <QtPlugin>
|
||||
#include <QDateTime>
|
||||
#include <QRegExp>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QStringList>
|
||||
|
||||
#include <QTweetLib/qtweetaccountverifycredentials.h>
|
||||
#include <QTweetLib/qtweetuser.h>
|
||||
#include <QTweetLib/qtweetstatus.h>
|
||||
#include <QTweetLib/qtweetusershow.h>
|
||||
|
||||
#include <utils/tomahawkutils.h>
|
||||
#include <tomahawksettings.h>
|
||||
#include <database/database.h>
|
||||
#include <network/servent.h>
|
||||
|
||||
#include "utils/logger.h"
|
||||
#include "accounts/twitter/tomahawkoauthtwitter.h"
|
||||
#include <accounts/twitter/twitteraccount.h>
|
||||
|
||||
static QString s_gotTomahawkRegex = QString( "^(@[a-zA-Z0-9]+ )?(Got Tomahawk\\?) (\\{[a-fA-F0-9\\-]+\\}) (.*)$" );
|
||||
|
||||
TwitterSipPlugin::TwitterSipPlugin( Tomahawk::Accounts::Account* account )
|
||||
: SipPlugin( account )
|
||||
, m_checkTimer( this )
|
||||
, m_connectTimer( this )
|
||||
, m_dmPollTimer( this )
|
||||
, m_cachedFriendsSinceId( 0 )
|
||||
, m_cachedMentionsSinceId( 0 )
|
||||
, m_cachedDirectMessagesSinceId( 0 )
|
||||
, m_cachedPeers()
|
||||
, m_keyCache()
|
||||
, m_state( Tomahawk::Accounts::Account::Disconnected )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
connect( account, SIGNAL( nowAuthenticated( const QWeakPointer< TomahawkOAuthTwitter > &, const QTweetUser & ) ), SLOT( accountAuthenticated( const QWeakPointer< TomahawkOAuthTwitter > &, const QTweetUser & ) ) );
|
||||
|
||||
m_configuration = account->configuration();
|
||||
qDebug() << "SIP configuration:" << m_configuration << m_configuration[ "cachedpeers" ];
|
||||
if ( Database::instance()->dbid() != m_account->configuration()[ "saveddbid" ].toString() )
|
||||
{
|
||||
m_configuration[ "cachedpeers" ] = QVariantHash();
|
||||
m_configuration[ "saveddbid" ] = Database::instance()->dbid();
|
||||
syncConfig();
|
||||
}
|
||||
|
||||
m_checkTimer.setInterval( 180000 );
|
||||
m_checkTimer.setSingleShot( false );
|
||||
connect( &m_checkTimer, SIGNAL( timeout() ), SLOT( checkTimerFired() ) );
|
||||
|
||||
m_dmPollTimer.setInterval( 60000 );
|
||||
m_dmPollTimer.setSingleShot( false );
|
||||
connect( &m_dmPollTimer, SIGNAL( timeout() ), SLOT( pollDirectMessages() ) );
|
||||
|
||||
m_connectTimer.setInterval( 180000 );
|
||||
m_connectTimer.setSingleShot( false );
|
||||
connect( &m_connectTimer, SIGNAL( timeout() ), SLOT( connectTimerFired() ) );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TwitterSipPlugin::isValid() const
|
||||
{
|
||||
return m_account->enabled() && m_account->isAuthenticated() && !m_cachedTwitterAuth.isNull();
|
||||
}
|
||||
|
||||
|
||||
Tomahawk::Accounts::Account::ConnectionState
|
||||
TwitterSipPlugin::connectionState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TwitterSipPlugin::checkSettings()
|
||||
{
|
||||
configurationChanged();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TwitterSipPlugin::connectPlugin()
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
if ( !m_account->enabled() )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << "account isn't enabled";
|
||||
return;
|
||||
}
|
||||
|
||||
m_cachedPeers = m_configuration[ "cachedpeers" ].toHash();
|
||||
QStringList peerList = m_cachedPeers.keys();
|
||||
qStableSort( peerList.begin(), peerList.end() );
|
||||
|
||||
if ( !m_account->isAuthenticated() )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << "account isn't authenticated, attempting";
|
||||
m_account->authenticate();
|
||||
}
|
||||
|
||||
m_state = Tomahawk::Accounts::Account::Connecting;
|
||||
emit stateChanged( m_state );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TwitterSipPlugin::disconnectPlugin()
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
m_checkTimer.stop();
|
||||
m_connectTimer.stop();
|
||||
m_dmPollTimer.stop();
|
||||
if( !m_friendsTimeline.isNull() )
|
||||
delete m_friendsTimeline.data();
|
||||
if( !m_mentions.isNull() )
|
||||
delete m_mentions.data();
|
||||
if( !m_directMessages.isNull() )
|
||||
delete m_directMessages.data();
|
||||
if( !m_directMessageNew.isNull() )
|
||||
delete m_directMessageNew.data();
|
||||
if( !m_directMessageDestroy.isNull() )
|
||||
delete m_directMessageDestroy.data();
|
||||
|
||||
m_cachedTwitterAuth.clear();
|
||||
|
||||
m_configuration[ "cachedpeers" ] = m_cachedPeers;
|
||||
syncConfig();
|
||||
m_cachedPeers.empty();
|
||||
m_state = Tomahawk::Accounts::Account::Disconnected;
|
||||
emit stateChanged( m_state );
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::accountAuthenticated( const QWeakPointer< TomahawkOAuthTwitter > &twitterAuth, const QTweetUser &user )
|
||||
{
|
||||
Q_UNUSED( user );
|
||||
|
||||
if ( !m_account->enabled() || !m_account->isAuthenticated() )
|
||||
return;
|
||||
|
||||
m_cachedTwitterAuth = twitterAuth;
|
||||
|
||||
m_friendsTimeline = QWeakPointer<QTweetFriendsTimeline>( new QTweetFriendsTimeline( m_cachedTwitterAuth.data(), this ) );
|
||||
m_mentions = QWeakPointer<QTweetMentions>( new QTweetMentions( m_cachedTwitterAuth.data(), this ) );
|
||||
m_directMessages = QWeakPointer<QTweetDirectMessages>( new QTweetDirectMessages( m_cachedTwitterAuth.data(), this ) );
|
||||
m_directMessageNew = QWeakPointer<QTweetDirectMessageNew>( new QTweetDirectMessageNew( m_cachedTwitterAuth.data(), this ) );
|
||||
m_directMessageDestroy = QWeakPointer<QTweetDirectMessageDestroy>( new QTweetDirectMessageDestroy( m_cachedTwitterAuth.data(), this ) );
|
||||
connect( m_friendsTimeline.data(), SIGNAL( parsedStatuses(const QList< QTweetStatus > &) ), SLOT( friendsTimelineStatuses(const QList<QTweetStatus> &) ) );
|
||||
connect( m_mentions.data(), SIGNAL( parsedStatuses(const QList< QTweetStatus > &) ), SLOT( mentionsStatuses(const QList<QTweetStatus> &) ) );
|
||||
connect( m_directMessages.data(), SIGNAL( parsedDirectMessages(const QList<QTweetDMStatus> &)), SLOT( directMessages(const QList<QTweetDMStatus> &) ) );
|
||||
connect( m_directMessageNew.data(), SIGNAL( parsedDirectMessage(const QTweetDMStatus &)), SLOT( directMessagePosted(const QTweetDMStatus &) ) );
|
||||
connect( m_directMessageNew.data(), SIGNAL( error(QTweetNetBase::ErrorCode, const QString &) ), SLOT( directMessagePostError(QTweetNetBase::ErrorCode, const QString &) ) );
|
||||
connect( m_directMessageDestroy.data(), SIGNAL( parsedDirectMessage(const QTweetDMStatus &) ), SLOT( directMessageDestroyed(const QTweetDMStatus &) ) );
|
||||
m_state = Tomahawk::Accounts::Account::Connected;
|
||||
emit stateChanged( m_state );
|
||||
QStringList peerList = m_cachedPeers.keys();
|
||||
qStableSort( peerList.begin(), peerList.end() );
|
||||
registerOffers( peerList );
|
||||
m_connectTimer.start();
|
||||
m_checkTimer.start();
|
||||
m_dmPollTimer.start();
|
||||
|
||||
QMetaObject::invokeMethod( this, "checkTimerFired", Qt::AutoConnection );
|
||||
QTimer::singleShot( 20000, this, SLOT( connectTimerFired() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TwitterSipPlugin::checkTimerFired()
|
||||
{
|
||||
if ( !isValid() )
|
||||
return;
|
||||
|
||||
if ( m_cachedFriendsSinceId == 0 )
|
||||
m_cachedFriendsSinceId = m_configuration[ "cachedfriendssinceid" ].toLongLong();
|
||||
|
||||
qDebug() << "TwitterSipPlugin looking at friends timeline since id " << m_cachedFriendsSinceId;
|
||||
|
||||
if ( !m_friendsTimeline.isNull() )
|
||||
m_friendsTimeline.data()->fetch( m_cachedFriendsSinceId, 0, 800 );
|
||||
|
||||
if ( m_cachedMentionsSinceId == 0 )
|
||||
m_cachedMentionsSinceId = m_configuration[ "cachedmentionssinceid" ].toLongLong();
|
||||
|
||||
qDebug() << "TwitterSipPlugin looking at mentions timeline since id " << m_cachedMentionsSinceId;
|
||||
|
||||
if ( !m_mentions.isNull() )
|
||||
m_mentions.data()->fetch( m_cachedMentionsSinceId, 0, 800 );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TwitterSipPlugin::registerOffers( const QStringList &peerList )
|
||||
{
|
||||
if ( !isValid() )
|
||||
return;
|
||||
|
||||
foreach( QString screenName, peerList )
|
||||
{
|
||||
QVariantHash peerData = m_cachedPeers[screenName].toHash();
|
||||
|
||||
if ( peerData.contains( "onod" ) && peerData["onod"] != Database::instance()->dbid() )
|
||||
{
|
||||
m_cachedPeers.remove( screenName );
|
||||
m_configuration[ "cachedpeers" ] = m_cachedPeers;
|
||||
syncConfig();
|
||||
}
|
||||
|
||||
if ( Servent::instance()->connectedToSession( peerData["node"].toString() ) )
|
||||
{
|
||||
peerData["lastseen"] = QDateTime::currentMSecsSinceEpoch();
|
||||
m_cachedPeers[screenName] = peerData;
|
||||
m_configuration[ "cachedpeers" ] = m_cachedPeers;
|
||||
syncConfig();
|
||||
qDebug() << Q_FUNC_INFO << " already connected";
|
||||
continue;
|
||||
}
|
||||
else if ( QDateTime::currentMSecsSinceEpoch() - peerData["lastseen"].toLongLong() > 1209600000 ) // 2 weeks
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << " aging peer " << screenName << " out of cache";
|
||||
m_cachedPeers.remove( screenName );
|
||||
m_configuration[ "cachedpeers" ] = m_cachedPeers;
|
||||
syncConfig();
|
||||
m_cachedAvatars.remove( screenName );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !peerData.contains( "host" ) || !peerData.contains( "port" ) || !peerData.contains( "pkey" ) )
|
||||
{
|
||||
qDebug() << "TwitterSipPlugin does not have host, port and/or pkey values for " << screenName << " (this is usually *not* a bug or problem but a normal part of the process)";
|
||||
continue;
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod( this, "registerOffer", Q_ARG( QString, screenName ), Q_ARG( QVariantHash, peerData ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TwitterSipPlugin::connectTimerFired()
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << " beginning";
|
||||
if ( !isValid() || m_cachedPeers.isEmpty() )
|
||||
{
|
||||
if ( !isValid() )
|
||||
tDebug() << Q_FUNC_INFO << " is not valid";
|
||||
if ( m_cachedPeers.isEmpty() )
|
||||
tDebug() << Q_FUNC_INFO << " has empty cached peers";
|
||||
return;
|
||||
}
|
||||
|
||||
tDebug() << Q_FUNC_INFO << " continuing";
|
||||
QString myScreenName = m_configuration[ "screenname" ].toString();
|
||||
QStringList peerList = m_cachedPeers.keys();
|
||||
qStableSort( peerList.begin(), peerList.end() );
|
||||
registerOffers( peerList );
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::parseGotTomahawk( const QRegExp ®ex, const QString &screenName, const QString &text )
|
||||
{
|
||||
QString myScreenName = m_configuration[ "screenname" ].toString();
|
||||
qDebug() << "TwitterSipPlugin found an exact matching Got Tomahawk? mention or direct message from user " << screenName << ", now parsing";
|
||||
regex.exactMatch( text );
|
||||
if ( text.startsWith( '@' ) && regex.captureCount() >= 2 && regex.cap( 1 ) != QString( '@' + myScreenName ) )
|
||||
{
|
||||
qDebug() << "TwitterSipPlugin skipping mention because it's directed @someone that isn't us";
|
||||
return;
|
||||
}
|
||||
|
||||
QString node;
|
||||
for ( int i = 0; i < regex.captureCount(); ++i )
|
||||
{
|
||||
if ( regex.cap( i ) == QString( "Got Tomahawk?" ) )
|
||||
{
|
||||
QString nodeCap = regex.cap( i + 1 );
|
||||
nodeCap.chop( 1 );
|
||||
node = nodeCap.mid( 1 );
|
||||
}
|
||||
}
|
||||
if ( node.isEmpty() )
|
||||
{
|
||||
qDebug() << "TwitterSipPlugin could not parse node out of the tweet";
|
||||
return;
|
||||
}
|
||||
else
|
||||
qDebug() << "TwitterSipPlugin parsed node " << node << " out of the tweet";
|
||||
|
||||
if ( node == Database::instance()->dbid() )
|
||||
{
|
||||
qDebug() << "My dbid found; ignoring";
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantHash peerData;
|
||||
if( m_cachedPeers.contains( screenName ) )
|
||||
{
|
||||
peerData = m_cachedPeers[screenName].toHash();
|
||||
//force a re-send of info but no need to re-register
|
||||
peerData["resend"] = QVariant::fromValue< bool >( true );
|
||||
if ( peerData["node"].toString() != node )
|
||||
peerData["rekey"] = QVariant::fromValue< bool >( true );
|
||||
}
|
||||
peerData["node"] = QVariant::fromValue< QString >( node );
|
||||
QMetaObject::invokeMethod( this, "registerOffer", Q_ARG( QString, screenName ), Q_ARG( QVariantHash, peerData ) );
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::friendsTimelineStatuses( const QList< QTweetStatus > &statuses )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
QRegExp regex( s_gotTomahawkRegex, Qt::CaseSensitive, QRegExp::RegExp2 );
|
||||
|
||||
QHash< QString, QTweetStatus > latestHash;
|
||||
foreach ( QTweetStatus status, statuses )
|
||||
{
|
||||
if ( !regex.exactMatch( status.text() ) )
|
||||
continue;
|
||||
|
||||
if ( !latestHash.contains( status.user().screenName() ) )
|
||||
latestHash[status.user().screenName()] = status;
|
||||
else
|
||||
{
|
||||
if ( status.id() > latestHash[status.user().screenName()].id() )
|
||||
latestHash[status.user().screenName()] = status;
|
||||
}
|
||||
}
|
||||
|
||||
foreach( QTweetStatus status, latestHash.values() )
|
||||
{
|
||||
if ( status.id() > m_cachedFriendsSinceId )
|
||||
m_cachedFriendsSinceId = status.id();
|
||||
|
||||
tDebug() << "TwitterSipPlugin checking mention from " << status.user().screenName() << " with content " << status.text();
|
||||
parseGotTomahawk( regex, status.user().screenName(), status.text() );
|
||||
}
|
||||
|
||||
m_configuration[ "cachedfriendssinceid" ] = m_cachedFriendsSinceId;
|
||||
syncConfig();
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::mentionsStatuses( const QList< QTweetStatus > &statuses )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
QRegExp regex( s_gotTomahawkRegex, Qt::CaseSensitive, QRegExp::RegExp2 );
|
||||
|
||||
QHash< QString, QTweetStatus > latestHash;
|
||||
foreach ( QTweetStatus status, statuses )
|
||||
{
|
||||
if ( !regex.exactMatch( status.text() ) )
|
||||
continue;
|
||||
|
||||
if ( !latestHash.contains( status.user().screenName() ) )
|
||||
latestHash[status.user().screenName()] = status;
|
||||
else
|
||||
{
|
||||
if ( status.id() > latestHash[status.user().screenName()].id() )
|
||||
latestHash[status.user().screenName()] = status;
|
||||
}
|
||||
}
|
||||
|
||||
foreach( QTweetStatus status, latestHash.values() )
|
||||
{
|
||||
if ( status.id() > m_cachedMentionsSinceId )
|
||||
m_cachedMentionsSinceId = status.id();
|
||||
|
||||
tDebug() << "TwitterSipPlugin checking mention from " << status.user().screenName() << " with content " << status.text();
|
||||
parseGotTomahawk( regex, status.user().screenName(), status.text() );
|
||||
}
|
||||
|
||||
m_configuration[ "cachedmentionssinceid" ] = m_cachedMentionsSinceId;
|
||||
syncConfig();
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::pollDirectMessages()
|
||||
{
|
||||
if ( !isValid() )
|
||||
return;
|
||||
|
||||
if ( m_cachedDirectMessagesSinceId == 0 )
|
||||
m_cachedDirectMessagesSinceId = m_configuration[ "cacheddirectmessagessinceid" ].toLongLong();
|
||||
|
||||
tDebug() << "TwitterSipPlugin looking for direct messages since id " << m_cachedDirectMessagesSinceId;
|
||||
|
||||
if ( !m_directMessages.isNull() )
|
||||
m_directMessages.data()->fetch( m_cachedDirectMessagesSinceId, 0, 800 );
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::directMessages( const QList< QTweetDMStatus > &messages )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
|
||||
QRegExp regex( s_gotTomahawkRegex, Qt::CaseSensitive, QRegExp::RegExp2 );
|
||||
QString myScreenName = m_configuration[ "screenname" ].toString();
|
||||
|
||||
QHash< QString, QTweetDMStatus > latestHash;
|
||||
foreach ( QTweetDMStatus status, messages )
|
||||
{
|
||||
if ( !regex.exactMatch( status.text() ) )
|
||||
{
|
||||
QStringList splitList = status.text().split(':');
|
||||
if ( splitList.length() != 5 )
|
||||
continue;
|
||||
if ( splitList[0] != "TOMAHAWKPEER" )
|
||||
continue;
|
||||
if ( !splitList[1].startsWith( "Host=" ) || !splitList[2].startsWith( "Port=" ) || !splitList[3].startsWith( "Node=" ) || !splitList[4].startsWith( "PKey=" ) )
|
||||
continue;
|
||||
int port = splitList[2].mid( 5 ).toInt();
|
||||
if ( port == 0 )
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !latestHash.contains( status.senderScreenName() ) )
|
||||
latestHash[status.senderScreenName()] = status;
|
||||
else
|
||||
{
|
||||
if ( status.id() > latestHash[status.senderScreenName()].id() )
|
||||
latestHash[status.senderScreenName()] = status;
|
||||
}
|
||||
}
|
||||
|
||||
foreach( QTweetDMStatus status, latestHash.values() )
|
||||
{
|
||||
qDebug() << "TwitterSipPlugin checking direct message from " << status.senderScreenName() << " with content " << status.text();
|
||||
if ( status.id() > m_cachedDirectMessagesSinceId )
|
||||
m_cachedDirectMessagesSinceId = status.id();
|
||||
|
||||
if ( regex.exactMatch( status.text() ) )
|
||||
parseGotTomahawk( regex, status.sender().screenName(), status.text() );
|
||||
else
|
||||
{
|
||||
QStringList splitList = status.text().split(':');
|
||||
qDebug() << "TwitterSipPlugin found " << splitList.length() << " parts to the message; the parts are:";
|
||||
foreach( QString part, splitList )
|
||||
qDebug() << part;
|
||||
//validity is checked above
|
||||
int port = splitList[2].mid( 5 ).toInt();
|
||||
QString host = splitList[1].mid( 5 );
|
||||
QString node = splitList[3].mid( 5 );
|
||||
QString pkey = splitList[4].mid( 5 );
|
||||
QStringList splitNode = node.split('*');
|
||||
if ( splitNode.length() != 2 )
|
||||
{
|
||||
qDebug() << "Old-style node info found, ignoring";
|
||||
continue;
|
||||
}
|
||||
qDebug() << "TwitterSipPlugin found a peerstart message from " << status.senderScreenName() << " with host " << host << " and port " << port << " and pkey " << pkey << " and node " << splitNode[0] << " destined for node " << splitNode[1];
|
||||
|
||||
|
||||
QVariantHash peerData = ( m_cachedPeers.contains( status.senderScreenName() ) ) ?
|
||||
m_cachedPeers[status.senderScreenName()].toHash() :
|
||||
QVariantHash();
|
||||
|
||||
peerData["host"] = QVariant::fromValue< QString >( host );
|
||||
peerData["port"] = QVariant::fromValue< int >( port );
|
||||
peerData["pkey"] = QVariant::fromValue< QString >( pkey );
|
||||
peerData["node"] = QVariant::fromValue< QString >( splitNode[0] );
|
||||
peerData["dirty"] = QVariant::fromValue< bool >( true );
|
||||
|
||||
QMetaObject::invokeMethod( this, "registerOffer", Q_ARG( QString, status.senderScreenName() ), Q_ARG( QVariantHash, peerData ) );
|
||||
|
||||
if ( Database::instance()->dbid().startsWith( splitNode[1] ) )
|
||||
{
|
||||
qDebug() << "TwitterSipPlugin found message destined for this node; destroying it";
|
||||
if ( !m_directMessageDestroy.isNull() )
|
||||
m_directMessageDestroy.data()->destroyMessage( status.id() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_configuration[ "cacheddirectmessagessinceid" ] = m_cachedDirectMessagesSinceId;
|
||||
syncConfig();
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::registerOffer( const QString &screenName, const QVariantHash &peerData )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
bool peersChanged = false;
|
||||
bool needToSend = false;
|
||||
bool needToAddToCache = false;
|
||||
|
||||
QString friendlyName = QString( '@' + screenName );
|
||||
|
||||
if ( !m_cachedAvatars.contains( screenName ) )
|
||||
QMetaObject::invokeMethod( this, "fetchAvatar", Q_ARG( QString, screenName ) );
|
||||
|
||||
QVariantHash _peerData( peerData );
|
||||
|
||||
if ( _peerData.contains( "dirty" ) )
|
||||
{
|
||||
peersChanged = true;
|
||||
_peerData.remove( "dirty" );
|
||||
}
|
||||
|
||||
if ( _peerData.contains( "resend" ) )
|
||||
{
|
||||
needToSend = true;
|
||||
peersChanged = true;
|
||||
_peerData.remove( "resend" );
|
||||
}
|
||||
|
||||
if ( !_peerData.contains( "okey" ) ||
|
||||
!_peerData.contains( "onod" ) ||
|
||||
( _peerData.contains( "onod" ) && _peerData["onod"] != Database::instance()->dbid() ) )
|
||||
{
|
||||
QString okey = QUuid::createUuid().toString().split( '-' ).last();
|
||||
okey.chop( 1 );
|
||||
_peerData["okey"] = QVariant::fromValue< QString >( okey );
|
||||
_peerData["onod"] = QVariant::fromValue< QString >( Database::instance()->dbid() );
|
||||
peersChanged = true;
|
||||
needToAddToCache = true;
|
||||
needToSend = true;
|
||||
}
|
||||
|
||||
if ( _peerData.contains( "rekey" ) || !m_keyCache.contains( _peerData["okey"].toString() ) )
|
||||
{
|
||||
_peerData.remove( "rekey" );
|
||||
needToAddToCache = true;
|
||||
}
|
||||
|
||||
if ( !_peerData.contains( "ohst" ) || !_peerData.contains( "oprt" ) ||
|
||||
_peerData["ohst"].toString() != Servent::instance()->externalAddress() ||
|
||||
_peerData["oprt"].toInt() != Servent::instance()->externalPort()
|
||||
)
|
||||
needToSend = true;
|
||||
|
||||
if( needToAddToCache && _peerData.contains( "node" ) )
|
||||
{
|
||||
qDebug() << "TwitterSipPlugin registering offer to " << friendlyName << " with node " << _peerData["node"].toString() << " and offeredkey " << _peerData["okey"].toString();
|
||||
m_keyCache << Servent::instance()->createConnectionKey( friendlyName, _peerData["node"].toString(), _peerData["okey"].toString(), false );
|
||||
}
|
||||
|
||||
if( needToSend && _peerData.contains( "node") )
|
||||
{
|
||||
qDebug() << "TwitterSipPlugin needs to send and has node";
|
||||
_peerData["ohst"] = QVariant::fromValue< QString >( Servent::instance()->externalAddress() );
|
||||
_peerData["oprt"] = QVariant::fromValue< int >( Servent::instance()->externalPort() );
|
||||
peersChanged = true;
|
||||
if( !Servent::instance()->externalAddress().isEmpty() && !Servent::instance()->externalPort() == 0 )
|
||||
QMetaObject::invokeMethod( this, "sendOffer", Q_ARG( QString, screenName ), Q_ARG( QVariantHash, _peerData ) );
|
||||
else
|
||||
qDebug() << "TwitterSipPlugin did not send offer because external address is " << Servent::instance()->externalAddress() << " and external port is " << Servent::instance()->externalPort();
|
||||
}
|
||||
|
||||
if ( peersChanged )
|
||||
{
|
||||
_peerData["lastseen"] = QString::number( QDateTime::currentMSecsSinceEpoch() );
|
||||
m_cachedPeers[screenName] = QVariant::fromValue< QVariantHash >( _peerData );
|
||||
m_configuration[ "cachedpeers" ] = m_cachedPeers;
|
||||
syncConfig();
|
||||
}
|
||||
|
||||
if ( m_state == Tomahawk::Accounts::Account::Connected && _peerData.contains( "host" ) && _peerData.contains( "port" ) && _peerData.contains( "pkey" ) )
|
||||
QMetaObject::invokeMethod( this, "makeConnection", Q_ARG( QString, screenName ), Q_ARG( QVariantHash, _peerData ) );
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::sendOffer( const QString &screenName, const QVariantHash &peerData )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QString offerString = QString( "TOMAHAWKPEER:Host=%1:Port=%2:Node=%3*%4:PKey=%5" ).arg( peerData["ohst"].toString() )
|
||||
.arg( peerData["oprt"].toString() )
|
||||
.arg( Database::instance()->dbid() )
|
||||
.arg( peerData["node"].toString().left( 8 ) )
|
||||
.arg( peerData["okey"].toString() );
|
||||
qDebug() << "TwitterSipPlugin sending message to " << screenName << ": " << offerString;
|
||||
if( !m_directMessageNew.isNull() )
|
||||
m_directMessageNew.data()->post( screenName, offerString );
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::makeConnection( const QString &screenName, const QVariantHash &peerData )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if ( !peerData.contains( "host" ) || !peerData.contains( "port" ) || !peerData.contains( "pkey" ) || !peerData.contains( "node" ) ||
|
||||
peerData["host"].toString().isEmpty() || peerData["port"].toString().isEmpty() || peerData["pkey"].toString().isEmpty() || peerData["node"].toString().isEmpty() )
|
||||
{
|
||||
qDebug() << "TwitterSipPlugin could not find host and/or port and/or pkey and/or node for peer " << screenName;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( peerData["host"].toString() == Servent::instance()->externalAddress() &&
|
||||
peerData["port"].toInt() == Servent::instance()->externalPort() )
|
||||
{
|
||||
qDebug() << "TwitterSipPlugin asked to make connection to our own host and port, ignoring " << screenName;
|
||||
return;
|
||||
}
|
||||
|
||||
QString friendlyName = QString( '@' + screenName );
|
||||
if ( !Servent::instance()->connectedToSession( peerData["node"].toString() ) )
|
||||
Servent::instance()->connectToPeer( peerData["host"].toString(),
|
||||
peerData["port"].toString().toInt(),
|
||||
peerData["pkey"].toString(),
|
||||
friendlyName,
|
||||
peerData["node"].toString() );
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::directMessagePosted( const QTweetDMStatus& message )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
qDebug() << "TwitterSipPlugin sent message to " << message.recipientScreenName() << " containing: " << message.text();
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::directMessagePostError( QTweetNetBase::ErrorCode errorCode, const QString &message )
|
||||
{
|
||||
Q_UNUSED( errorCode );
|
||||
Q_UNUSED( message );
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
qDebug() << "TwitterSipPlugin received an error posting direct message: " << m_directMessageNew.data()->lastErrorMessage();
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::directMessageDestroyed( const QTweetDMStatus& message )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
qDebug() << "TwitterSipPlugin destroyed message " << message.text();
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::fetchAvatar( const QString& screenName )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if ( !isValid() )
|
||||
return;
|
||||
|
||||
QTweetUserShow *userShowFetch = new QTweetUserShow( m_cachedTwitterAuth.data(), this );
|
||||
connect( userShowFetch, SIGNAL( parsedUserInfo( QTweetUser ) ), SLOT( avatarUserDataSlot( QTweetUser ) ) );
|
||||
userShowFetch->fetch( screenName );
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::avatarUserDataSlot( const QTweetUser &user )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
if ( !isValid() || user.profileImageUrl().isEmpty())
|
||||
return;
|
||||
|
||||
QNetworkRequest request( user.profileImageUrl() );
|
||||
QNetworkReply *reply = m_cachedTwitterAuth.data()->networkAccessManager()->get( request );
|
||||
reply->setProperty( "screenname", user.screenName() );
|
||||
connect( reply, SIGNAL( finished() ), this, SLOT( profilePicReply() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TwitterSipPlugin::profilePicReply()
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
QNetworkReply *reply = qobject_cast< QNetworkReply* >( sender() );
|
||||
if ( !reply || reply->error() != QNetworkReply::NoError || !reply->property( "screenname" ).isValid() )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << " reply not valid or came back with error";
|
||||
return;
|
||||
}
|
||||
QString screenName = reply->property( "screenname" ).toString();
|
||||
QString friendlyName = '@' + screenName;
|
||||
QByteArray rawData = reply->readAll();
|
||||
QImage image;
|
||||
image.loadFromData( rawData, "PNG" );
|
||||
QPixmap pixmap = QPixmap::fromImage( image );
|
||||
m_cachedAvatars[screenName] = pixmap;
|
||||
emit avatarReceived( friendlyName, QPixmap::fromImage( image ) );
|
||||
}
|
||||
|
||||
void
|
||||
TwitterSipPlugin::configurationChanged()
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
if ( m_state != Tomahawk::Accounts::Account::Disconnected )
|
||||
m_account->deauthenticate();
|
||||
connectPlugin();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TwitterSipPlugin::syncConfig()
|
||||
{
|
||||
m_account->setConfiguration( m_configuration );
|
||||
m_account->sync();
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 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
|
||||
@@ -19,8 +20,6 @@
|
||||
#ifndef TWITTER_H
|
||||
#define TWITTER_H
|
||||
|
||||
#include "twitterconfigwidget.h"
|
||||
|
||||
#include <QTimer>
|
||||
#include <QWeakPointer>
|
||||
#include <QSet>
|
||||
@@ -34,50 +33,30 @@
|
||||
#include <QTweetLib/qtweetmentions.h>
|
||||
#include <QTweetLib/qtweetdmstatus.h>
|
||||
|
||||
#include "../sipdllmacro.h"
|
||||
#include "accounts/accountdllmacro.h"
|
||||
#include "sip/SipPlugin.h"
|
||||
#include "tomahawkoauthtwitter.h"
|
||||
#include "accounts/Account.h"
|
||||
#include "accounts/twitter/tomahawkoauthtwitter.h"
|
||||
|
||||
#define MYNAME "SIPTWITTER"
|
||||
|
||||
class SIPDLLEXPORT TwitterFactory : public SipPluginFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES( SipPluginFactory )
|
||||
|
||||
public:
|
||||
TwitterFactory() {}
|
||||
virtual ~TwitterFactory() {}
|
||||
|
||||
virtual QString prettyName() const { return "Twitter"; }
|
||||
virtual QString factoryId() const { return "siptwitter"; }
|
||||
virtual QIcon icon() const;
|
||||
virtual SipPlugin* createPlugin( const QString& pluginId = QString() );
|
||||
};
|
||||
|
||||
class SIPDLLEXPORT TwitterPlugin : public SipPlugin
|
||||
class ACCOUNTDLLEXPORT TwitterSipPlugin : public SipPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TwitterPlugin( const QString& pluginId );
|
||||
TwitterSipPlugin( Tomahawk::Accounts::Account *account );
|
||||
|
||||
virtual ~TwitterPlugin() {}
|
||||
virtual ~TwitterSipPlugin() {}
|
||||
|
||||
virtual bool isValid() const;
|
||||
virtual const QString name() const;
|
||||
virtual const QString accountName() const;
|
||||
virtual const QString friendlyName() const;
|
||||
virtual ConnectionState connectionState() const;
|
||||
virtual QIcon icon() const;
|
||||
virtual QWidget* configWidget();
|
||||
virtual Tomahawk::Accounts::Account::ConnectionState connectionState() const;
|
||||
|
||||
signals:
|
||||
void stateChanged( Tomahawk::Accounts::Account::ConnectionState );
|
||||
|
||||
public slots:
|
||||
virtual bool connectPlugin( bool startup );
|
||||
virtual void connectPlugin();
|
||||
void disconnectPlugin();
|
||||
void checkSettings();
|
||||
void refreshProxy();
|
||||
void deletePlugin();
|
||||
void configurationChanged();
|
||||
|
||||
void sendMsg( const QString& to, const QString& msg )
|
||||
{
|
||||
@@ -96,9 +75,10 @@ public slots:
|
||||
Q_UNUSED( msg );
|
||||
}
|
||||
|
||||
void checkSettings();
|
||||
|
||||
private slots:
|
||||
void configDialogAuthedSignalSlot( bool authed );
|
||||
void connectAuthVerifyReply( const QTweetUser &user );
|
||||
void accountAuthenticated( const QWeakPointer< TomahawkOAuthTwitter > &twitterAuth, const QTweetUser &user );
|
||||
void checkTimerFired();
|
||||
void connectTimerFired();
|
||||
void friendsTimelineStatuses( const QList< QTweetStatus > &statuses );
|
||||
@@ -117,35 +97,20 @@ private slots:
|
||||
void profilePicReply();
|
||||
|
||||
private:
|
||||
inline void syncConfig() { setTwitterCachedPeers( m_cachedPeers ); }
|
||||
void syncConfig();
|
||||
bool refreshTwitterAuth();
|
||||
void parseGotTomahawk( const QRegExp ®ex, const QString &screenName, const QString &text );
|
||||
// handle per-plugin config
|
||||
QString twitterSavedDbid() const;
|
||||
void setTwitterSavedDbid( const QString& dbid );
|
||||
QString twitterScreenName() const;
|
||||
void setTwitterScreenName( const QString& screenName );
|
||||
QString twitterOAuthToken() const;
|
||||
void setTwitterOAuthToken( const QString& oauthtoken );
|
||||
QString twitterOAuthTokenSecret() const;
|
||||
void setTwitterOAuthTokenSecret( const QString& oauthtokensecret );
|
||||
qint64 twitterCachedFriendsSinceId() const;
|
||||
void setTwitterCachedFriendsSinceId( qint64 sinceid );
|
||||
qint64 twitterCachedMentionsSinceId() const;
|
||||
void setTwitterCachedMentionsSinceId( qint64 sinceid );
|
||||
qint64 twitterCachedDirectMessagesSinceId() const;
|
||||
void setTwitterCachedDirectMessagesSinceId( qint64 sinceid );
|
||||
QVariantHash twitterCachedPeers() const;
|
||||
void setTwitterCachedPeers( const QVariantHash &cachedPeers );
|
||||
|
||||
QWeakPointer< TomahawkOAuthTwitter > m_twitterAuth;
|
||||
QWeakPointer< TomahawkOAuthTwitter > m_cachedTwitterAuth;
|
||||
|
||||
QWeakPointer< QTweetFriendsTimeline > m_friendsTimeline;
|
||||
QWeakPointer< QTweetMentions > m_mentions;
|
||||
QWeakPointer< QTweetDirectMessages > m_directMessages;
|
||||
QWeakPointer< QTweetDirectMessageNew > m_directMessageNew;
|
||||
QWeakPointer< QTweetDirectMessageDestroy > m_directMessageDestroy;
|
||||
|
||||
bool m_isAuthed;
|
||||
QVariantHash m_configuration;
|
||||
|
||||
QTimer m_checkTimer;
|
||||
QTimer m_connectTimer;
|
||||
QTimer m_dmPollTimer;
|
||||
@@ -155,12 +120,7 @@ private:
|
||||
QVariantHash m_cachedPeers;
|
||||
QHash< QString, QPixmap > m_cachedAvatars;
|
||||
QSet<QString> m_keyCache;
|
||||
ConnectionState m_state;
|
||||
|
||||
QWeakPointer<TwitterConfigWidget > m_configWidget;
|
||||
|
||||
// for settings access
|
||||
friend class TwitterConfigWidget;
|
||||
Tomahawk::Accounts::Account::ConnectionState m_state;
|
||||
};
|
||||
|
||||
#endif
|
@@ -1,6 +1,6 @@
|
||||
#include "tomahawkoauthtwitter.h"
|
||||
|
||||
#include <QInputDialog>
|
||||
#include <QtGui/QInputDialog>
|
||||
|
||||
#include "utils/logger.h"
|
||||
|
26
src/accounts/twitter/tomahawkoauthtwitter.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef TOMAHAWKOAUTHTWITTERACCOUNT
|
||||
#define TOMAHAWKOAUTHTWITTERACCOUNT
|
||||
|
||||
#include "accounts/accountdllmacro.h"
|
||||
#include <utils/tomahawkutils.h>
|
||||
|
||||
#include <QTweetLib/qtweetlib_global.h>
|
||||
#include <QTweetLib/oauthtwitter.h>
|
||||
|
||||
class ACCOUNTDLLEXPORT TomahawkOAuthTwitter : public OAuthTwitter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TomahawkOAuthTwitter( QNetworkAccessManager *nam = TomahawkUtils::nam() , QObject *parent = 0 );
|
||||
|
||||
~TomahawkOAuthTwitter() {}
|
||||
|
||||
protected:
|
||||
virtual int authorizationWidget();
|
||||
|
||||
private slots:
|
||||
void error();
|
||||
};
|
||||
|
||||
#endif
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
186
src/accounts/twitter/twitteraccount.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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 "twitteraccount.h"
|
||||
#include "twitterconfigwidget.h"
|
||||
#include "accounts/twitter/tomahawkoauthtwitter.h"
|
||||
|
||||
#include "sip/SipPlugin.h"
|
||||
|
||||
#include <QTweetLib/qtweetaccountverifycredentials.h>
|
||||
#include <QTweetLib/qtweetuser.h>
|
||||
#include <QTweetLib/qtweetstatus.h>
|
||||
#include <QTweetLib/qtweetusershow.h>
|
||||
|
||||
#include <QtCore/QtPlugin>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
Account*
|
||||
TwitterAccountFactory::createAccount( const QString& accountId )
|
||||
{
|
||||
return new TwitterAccount( accountId.isEmpty() ? Tomahawk::Accounts::generateId( factoryId() ) : accountId );
|
||||
}
|
||||
|
||||
|
||||
TwitterAccount::TwitterAccount( const QString &accountId )
|
||||
: Account( accountId )
|
||||
, m_isAuthenticated( false )
|
||||
{
|
||||
setAccountServiceName( "Twitter" );
|
||||
setTypes( AccountTypes( InfoType | SipType ) );
|
||||
|
||||
qDebug() << "Got cached peers:" << configuration() << configuration()[ "cachedpeers" ];
|
||||
|
||||
m_configWidget = QWeakPointer< TwitterConfigWidget >( new TwitterConfigWidget( this, 0 ) );
|
||||
connect( m_configWidget.data(), SIGNAL( twitterAuthed( bool ) ), SLOT( configDialogAuthedSignalSlot( bool ) ) );
|
||||
|
||||
m_twitterAuth = QWeakPointer< TomahawkOAuthTwitter >( new TomahawkOAuthTwitter( TomahawkUtils::nam(), this ) );
|
||||
}
|
||||
|
||||
|
||||
TwitterAccount::~TwitterAccount()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TwitterAccount::configDialogAuthedSignalSlot( bool authed )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
m_isAuthenticated = authed;
|
||||
if ( !credentials()[ "username" ].toString().isEmpty() )
|
||||
setAccountFriendlyName( QString( "@%1" ).arg( credentials()[ "username" ].toString() ) );
|
||||
syncConfig();
|
||||
emit configurationChanged();
|
||||
}
|
||||
|
||||
|
||||
Account::ConnectionState
|
||||
TwitterAccount::connectionState() const
|
||||
{
|
||||
return m_twitterSipPlugin.data()->connectionState();
|
||||
}
|
||||
|
||||
SipPlugin*
|
||||
TwitterAccount::sipPlugin()
|
||||
{
|
||||
if ( m_twitterSipPlugin.isNull() )
|
||||
{
|
||||
qDebug() << "CHECKING:" << configuration() << configuration()[ "cachedpeers" ];
|
||||
m_twitterSipPlugin = QWeakPointer< TwitterSipPlugin >( new TwitterSipPlugin( this ) );
|
||||
|
||||
connect( m_twitterSipPlugin.data(), SIGNAL( stateChanged( Tomahawk::Accounts::Account::ConnectionState ) ), this, SIGNAL( connectionStateChanged( Tomahawk::Accounts::Account::ConnectionState ) ) );
|
||||
return m_twitterSipPlugin.data();
|
||||
}
|
||||
return m_twitterSipPlugin.data();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TwitterAccount::authenticate()
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << "credentials: " << credentials().keys();
|
||||
|
||||
if ( credentials()[ "oauthtoken" ].toString().isEmpty() || credentials()[ "oauthtokensecret" ].toString().isEmpty() )
|
||||
{
|
||||
qDebug() << "TwitterSipPlugin has empty Twitter credentials; not connecting";
|
||||
return;
|
||||
}
|
||||
|
||||
if ( refreshTwitterAuth() )
|
||||
{
|
||||
QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( m_twitterAuth.data(), this );
|
||||
connect( credVerifier, SIGNAL( parsedUser( const QTweetUser & ) ), SLOT( connectAuthVerifyReply( const QTweetUser & ) ) );
|
||||
credVerifier->verify();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TwitterAccount::deauthenticate()
|
||||
{
|
||||
if ( sipPlugin() )
|
||||
sipPlugin()->disconnectPlugin();
|
||||
|
||||
m_isAuthenticated = false;
|
||||
emit nowDeauthenticated();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
TwitterAccount::refreshTwitterAuth()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << " begin";
|
||||
if( !m_twitterAuth.isNull() )
|
||||
delete m_twitterAuth.data();
|
||||
|
||||
Q_ASSERT( TomahawkUtils::nam() != 0 );
|
||||
qDebug() << Q_FUNC_INFO << " with nam " << TomahawkUtils::nam();
|
||||
m_twitterAuth = QWeakPointer< TomahawkOAuthTwitter >( new TomahawkOAuthTwitter( TomahawkUtils::nam(), this ) );
|
||||
|
||||
if( m_twitterAuth.isNull() )
|
||||
return false;
|
||||
|
||||
m_twitterAuth.data()->setOAuthToken( credentials()[ "oauthtoken" ].toString().toLatin1() );
|
||||
m_twitterAuth.data()->setOAuthTokenSecret( credentials()[ "oauthtokensecret" ].toString().toLatin1() );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TwitterAccount::connectAuthVerifyReply( const QTweetUser &user )
|
||||
{
|
||||
if ( user.id() == 0 )
|
||||
{
|
||||
qDebug() << "TwitterAccount could not authenticate to Twitter";
|
||||
deauthenticate();
|
||||
}
|
||||
else
|
||||
{
|
||||
tDebug() << "TwitterAccount successfully authenticated to Twitter as user " << user.screenName();
|
||||
QVariantHash config = configuration();
|
||||
config[ "screenname" ] = user.screenName();
|
||||
setConfiguration( config );
|
||||
sync();
|
||||
|
||||
sipPlugin()->connectPlugin();
|
||||
|
||||
m_isAuthenticated = true;
|
||||
emit nowAuthenticated( m_twitterAuth, user );
|
||||
}
|
||||
}
|
||||
QPixmap
|
||||
TwitterAccount::icon() const {
|
||||
return QPixmap( ":/twitter-icon.png" );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Q_EXPORT_PLUGIN2( Tomahawk::Accounts::AccountFactory, Tomahawk::Accounts::TwitterAccountFactory )
|
103
src/accounts/twitter/twitteraccount.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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 TWITTERACCOUNT_H
|
||||
#define TWITTERACCOUNT_H
|
||||
|
||||
#include "twitterconfigwidget.h"
|
||||
#include "tomahawkoauthtwitter.h"
|
||||
|
||||
#include "sip/twittersip.h"
|
||||
#include "accounts/accountdllmacro.h"
|
||||
#include "accounts/Account.h"
|
||||
|
||||
#define MYNAME "ACCOUNTTWITTER"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
class ACCOUNTDLLEXPORT TwitterAccountFactory : public AccountFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES( Tomahawk::Accounts::AccountFactory )
|
||||
|
||||
public:
|
||||
TwitterAccountFactory() {}
|
||||
virtual ~TwitterAccountFactory() {}
|
||||
|
||||
QString prettyName() const { return "Twitter"; }
|
||||
QString factoryId() const { return "twitteraccount"; }
|
||||
QString description() const { return tr( "Connect to your Twitter followers." ); }
|
||||
QPixmap icon() const { return QPixmap( ":/twitter-icon.png" ); }
|
||||
AccountTypes types() const { return AccountTypes( SipType ); };
|
||||
Account* createAccount( const QString& pluginId = QString() );
|
||||
};
|
||||
|
||||
class ACCOUNTDLLEXPORT TwitterAccount : public Account
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TwitterAccount( const QString &accountId );
|
||||
virtual ~TwitterAccount();
|
||||
|
||||
QPixmap icon() const;
|
||||
|
||||
void authenticate();
|
||||
void deauthenticate();
|
||||
bool isAuthenticated() const { return m_isAuthenticated; }
|
||||
|
||||
ConnectionState connectionState() const;
|
||||
|
||||
Tomahawk::InfoSystem::InfoPlugin* infoPlugin() { return 0; }
|
||||
SipPlugin* sipPlugin();
|
||||
|
||||
QWidget* configurationWidget() { return m_configWidget.data(); }
|
||||
QWidget* aclWidget() { return 0; }
|
||||
|
||||
bool refreshTwitterAuth();
|
||||
TomahawkOAuthTwitter* twitterAuth() const { return m_twitterAuth.data(); }
|
||||
|
||||
signals:
|
||||
void nowAuthenticated( const QWeakPointer< TomahawkOAuthTwitter >&, const QTweetUser &user );
|
||||
void nowDeauthenticated();
|
||||
|
||||
private slots:
|
||||
void configDialogAuthedSignalSlot( bool authed );
|
||||
void connectAuthVerifyReply( const QTweetUser &user );
|
||||
|
||||
private:
|
||||
QIcon m_icon;
|
||||
bool m_isAuthenticated;
|
||||
QWeakPointer< TomahawkOAuthTwitter > m_twitterAuth;
|
||||
QWeakPointer< TwitterConfigWidget > m_configWidget;
|
||||
QWeakPointer< TwitterSipPlugin > m_twitterSipPlugin;
|
||||
|
||||
// for settings access
|
||||
friend class TwitterConfigWidget;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
|
||||
#include "twitterconfigwidget.h"
|
||||
#include "twitter.h"
|
||||
#include "twitteraccount.h"
|
||||
#include "ui_twitterconfigwidget.h"
|
||||
|
||||
#include "tomahawksettings.h"
|
||||
@@ -33,38 +33,47 @@
|
||||
|
||||
#include "utils/logger.h"
|
||||
|
||||
|
||||
TwitterConfigWidget::TwitterConfigWidget( TwitterPlugin* plugin, QWidget *parent ) :
|
||||
QWidget( parent ),
|
||||
ui( new Ui::TwitterConfigWidget ),
|
||||
m_plugin( plugin )
|
||||
namespace Tomahawk
|
||||
{
|
||||
ui->setupUi( this );
|
||||
|
||||
connect( ui->twitterAuthenticateButton, SIGNAL( pressed() ),
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
TwitterConfigWidget::TwitterConfigWidget( TwitterAccount* account, QWidget *parent ) :
|
||||
QWidget( parent ),
|
||||
m_ui( new Ui::TwitterConfigWidget ),
|
||||
m_account( account )
|
||||
{
|
||||
m_ui->setupUi( this );
|
||||
|
||||
connect( m_ui->twitterAuthenticateButton, SIGNAL( pressed() ),
|
||||
this, SLOT( authDeauthTwitter() ) );
|
||||
connect( ui->twitterTweetGotTomahawkButton, SIGNAL( pressed() ),
|
||||
connect( m_ui->twitterTweetGotTomahawkButton, SIGNAL( pressed() ),
|
||||
this, SLOT( startPostGotTomahawkStatus() ) );
|
||||
connect( ui->twitterTweetComboBox, SIGNAL( currentIndexChanged( int ) ),
|
||||
connect( m_ui->twitterTweetComboBox, SIGNAL( currentIndexChanged( int ) ),
|
||||
this, SLOT( tweetComboBoxIndexChanged( int ) ) );
|
||||
|
||||
ui->twitterTweetComboBox->setCurrentIndex( 0 );
|
||||
ui->twitterTweetGotTomahawkButton->setText( tr( "Tweet!" ) );
|
||||
m_ui->twitterTweetComboBox->setCurrentIndex( 0 );
|
||||
m_ui->twitterTweetGotTomahawkButton->setText( tr( "Tweet!" ) );
|
||||
|
||||
if ( m_plugin->twitterOAuthToken().isEmpty() || m_plugin->twitterOAuthTokenSecret().isEmpty() || m_plugin->twitterScreenName().isEmpty() )
|
||||
QVariantHash credentials = m_account->credentials();
|
||||
|
||||
if ( credentials[ "oauthtoken" ].toString().isEmpty() ||
|
||||
credentials[ "oauthtokensecret" ].toString().isEmpty() ||
|
||||
credentials[ "username" ].toString().isEmpty() )
|
||||
{
|
||||
ui->twitterStatusLabel->setText( tr( "Status: No saved credentials" ) );
|
||||
ui->twitterAuthenticateButton->setText( tr( "Authenticate" ) );
|
||||
ui->twitterSyncGroupBox->setVisible( false );
|
||||
m_ui->twitterStatusLabel->setText( tr( "Status: No saved credentials" ) );
|
||||
m_ui->twitterAuthenticateButton->setText( tr( "Authenticate" ) );
|
||||
m_ui->twitterSyncGroupBox->setVisible( false );
|
||||
|
||||
emit twitterAuthed( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->twitterStatusLabel->setText( tr( "Status: Credentials saved for %1" ).arg( m_plugin->twitterScreenName() ) );
|
||||
ui->twitterAuthenticateButton->setText( tr( "De-authenticate" ) );
|
||||
ui->twitterSyncGroupBox->setVisible( true );
|
||||
ui->twitterUserTweetLineEdit->setVisible( false );
|
||||
m_ui->twitterStatusLabel->setText( tr( "Status: Credentials saved for %1" ).arg( m_account->credentials()[ "username" ].toString() ) );
|
||||
m_ui->twitterAuthenticateButton->setText( tr( "De-authenticate" ) );
|
||||
m_ui->twitterSyncGroupBox->setVisible( true );
|
||||
m_ui->twitterUserTweetLineEdit->setVisible( false );
|
||||
|
||||
emit twitterAuthed( true );
|
||||
}
|
||||
@@ -73,13 +82,13 @@ TwitterConfigWidget::TwitterConfigWidget( TwitterPlugin* plugin, QWidget *parent
|
||||
|
||||
TwitterConfigWidget::~TwitterConfigWidget()
|
||||
{
|
||||
delete ui;
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void
|
||||
TwitterConfigWidget::authDeauthTwitter()
|
||||
{
|
||||
if ( ui->twitterAuthenticateButton->text() == tr( "Authenticate" ) ) //FIXME: don't rely on UI strings here!
|
||||
if ( m_ui->twitterAuthenticateButton->text() == tr( "Authenticate" ) ) //FIXME: don't rely on UI strings here!
|
||||
authenticateTwitter();
|
||||
else
|
||||
deauthenticateTwitter();
|
||||
@@ -92,8 +101,10 @@ TwitterConfigWidget::authenticateTwitter()
|
||||
TomahawkOAuthTwitter *twitAuth = new TomahawkOAuthTwitter( TomahawkUtils::nam(), this );
|
||||
twitAuth->authorizePin();
|
||||
|
||||
m_plugin->setTwitterOAuthToken( twitAuth->oauthToken() );
|
||||
m_plugin->setTwitterOAuthTokenSecret( twitAuth->oauthTokenSecret() );
|
||||
QVariantHash credentials = m_account->credentials();
|
||||
credentials[ "oauthtoken" ] = twitAuth->oauthToken();
|
||||
credentials[ "oauthtokensecret" ] = twitAuth->oauthTokenSecret();
|
||||
m_account->setCredentials( credentials );
|
||||
|
||||
QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( twitAuth, this );
|
||||
connect( credVerifier, SIGNAL( parsedUser( const QTweetUser & ) ), SLOT( authenticateVerifyReply( const QTweetUser & ) ) );
|
||||
@@ -112,18 +123,21 @@ TwitterConfigWidget::authenticateVerifyReply( const QTweetUser &user )
|
||||
return;
|
||||
}
|
||||
|
||||
m_plugin->setTwitterScreenName( user.screenName() );
|
||||
m_plugin->setTwitterCachedFriendsSinceId( 0 );
|
||||
m_plugin->setTwitterCachedMentionsSinceId( 0 );
|
||||
QVariantHash credentials = m_account->credentials();
|
||||
credentials[ "username" ] = user.screenName();
|
||||
m_account->setCredentials( credentials );
|
||||
|
||||
ui->twitterStatusLabel->setText( tr( "Status: Credentials saved for %1" ).arg( m_plugin->twitterScreenName() ) );
|
||||
ui->twitterAuthenticateButton->setText( tr( "De-authenticate" ) );
|
||||
ui->twitterSyncGroupBox->setVisible( true );
|
||||
ui->twitterTweetComboBox->setCurrentIndex( 0 );
|
||||
ui->twitterUserTweetLineEdit->setVisible( false );
|
||||
ui->twitterTweetGotTomahawkButton->setText( tr( "Tweet!" ) );
|
||||
QVariantHash configuration = m_account->configuration();
|
||||
configuration[ "sipcachedfriendssinceid" ] = 0;
|
||||
configuration[ "sipcachedmentionssinceid" ] = 0;
|
||||
m_account->setConfiguration( configuration );
|
||||
|
||||
m_plugin->connectPlugin( false );
|
||||
m_ui->twitterStatusLabel->setText( tr( "Status: Credentials saved for %1" ).arg( user.screenName() ) );
|
||||
m_ui->twitterAuthenticateButton->setText( tr( "De-authenticate" ) );
|
||||
m_ui->twitterSyncGroupBox->setVisible( true );
|
||||
m_ui->twitterTweetComboBox->setCurrentIndex( 0 );
|
||||
m_ui->twitterUserTweetLineEdit->setVisible( false );
|
||||
m_ui->twitterTweetGotTomahawkButton->setText( tr( "Tweet!" ) );
|
||||
|
||||
emit twitterAuthed( true );
|
||||
emit sizeHintChanged();
|
||||
@@ -134,7 +148,7 @@ TwitterConfigWidget::authenticateVerifyError( QTweetNetBase::ErrorCode code, con
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
qDebug() << "Error validating credentials, error code is " << code << ", error message is " << errorMsg;
|
||||
ui->twitterStatusLabel->setText(tr("Status: Error validating credentials"));
|
||||
m_ui->twitterStatusLabel->setText(tr("Status: Error validating credentials"));
|
||||
emit twitterAuthed( false );
|
||||
return;
|
||||
}
|
||||
@@ -143,13 +157,15 @@ void
|
||||
TwitterConfigWidget::deauthenticateTwitter()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
m_plugin->setTwitterOAuthToken( QString() );
|
||||
m_plugin->setTwitterOAuthTokenSecret( QString() );
|
||||
m_plugin->setTwitterScreenName( QString() );
|
||||
QVariantHash credentials = m_account->credentials();
|
||||
credentials[ "oauthtoken" ] = QString();
|
||||
credentials[ "oauthtokensecret" ] = QString();
|
||||
credentials[ "username" ] = QString();
|
||||
m_account->setCredentials( credentials );
|
||||
|
||||
ui->twitterStatusLabel->setText(tr("Status: No saved credentials"));
|
||||
ui->twitterAuthenticateButton->setText( tr( "Authenticate" ) );
|
||||
ui->twitterSyncGroupBox->setVisible( false );
|
||||
m_ui->twitterStatusLabel->setText(tr("Status: No saved credentials"));
|
||||
m_ui->twitterAuthenticateButton->setText( tr( "Authenticate" ) );
|
||||
m_ui->twitterSyncGroupBox->setVisible( false );
|
||||
|
||||
emit twitterAuthed( false );
|
||||
emit sizeHintChanged();
|
||||
@@ -159,41 +175,45 @@ void
|
||||
TwitterConfigWidget::tweetComboBoxIndexChanged( int index )
|
||||
{
|
||||
Q_UNUSED( index );
|
||||
if ( ui->twitterTweetComboBox->currentText() == tr( "Global Tweet" ) ) //FIXME: use data!
|
||||
ui->twitterUserTweetLineEdit->setVisible( false );
|
||||
if ( m_ui->twitterTweetComboBox->currentText() == tr( "Global Tweet" ) ) //FIXME: use data!
|
||||
m_ui->twitterUserTweetLineEdit->setVisible( false );
|
||||
else
|
||||
ui->twitterUserTweetLineEdit->setVisible( true );
|
||||
m_ui->twitterUserTweetLineEdit->setVisible( true );
|
||||
|
||||
if ( ui->twitterTweetComboBox->currentText() == tr( "Direct Message" ) ) //FIXME: use data!
|
||||
ui->twitterTweetGotTomahawkButton->setText( tr( "Send Message!" ) );
|
||||
else if ( ui->twitterTweetComboBox->currentText() == tr( "@Mention" ) )
|
||||
ui->twitterTweetGotTomahawkButton->setText( tr( "Send Mention!" ) );
|
||||
if ( m_ui->twitterTweetComboBox->currentText() == tr( "Direct Message" ) ) //FIXME: use data!
|
||||
m_ui->twitterTweetGotTomahawkButton->setText( tr( "Send Message!" ) );
|
||||
else if ( m_ui->twitterTweetComboBox->currentText() == tr( "@Mention" ) )
|
||||
m_ui->twitterTweetGotTomahawkButton->setText( tr( "Send Mention!" ) );
|
||||
else
|
||||
ui->twitterTweetGotTomahawkButton->setText( tr( "Tweet!" ) );
|
||||
m_ui->twitterTweetGotTomahawkButton->setText( tr( "Tweet!" ) );
|
||||
}
|
||||
|
||||
void
|
||||
TwitterConfigWidget::startPostGotTomahawkStatus()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
m_postGTtype = ui->twitterTweetComboBox->currentText();
|
||||
m_postGTtype = m_ui->twitterTweetComboBox->currentText();
|
||||
|
||||
if ( m_postGTtype != "Global Tweet" && ( ui->twitterUserTweetLineEdit->text().isEmpty() || ui->twitterUserTweetLineEdit->text() == "@" ) )
|
||||
if ( m_postGTtype != "Global Tweet" && ( m_ui->twitterUserTweetLineEdit->text().isEmpty() || m_ui->twitterUserTweetLineEdit->text() == "@" ) )
|
||||
{
|
||||
QMessageBox::critical( this, tr("Tweetin' Error"), tr("You must enter a user name for this type of tweet.") );
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Posting Got Tomahawk status";
|
||||
if ( m_plugin->twitterOAuthToken().isEmpty() || m_plugin->twitterOAuthTokenSecret().isEmpty() || m_plugin->twitterScreenName().isEmpty() )
|
||||
QVariantHash credentials = m_account->credentials();
|
||||
|
||||
if ( credentials[ "oauthtoken" ].toString().isEmpty() ||
|
||||
credentials[ "oauthtokensecret" ].toString().isEmpty() ||
|
||||
credentials[ "username" ].toString().isEmpty() )
|
||||
{
|
||||
QMessageBox::critical( this, tr("Tweetin' Error"), tr("Your saved credentials could not be loaded.\nYou may wish to try re-authenticating.") );
|
||||
emit twitterAuthed( false );
|
||||
return;
|
||||
}
|
||||
TomahawkOAuthTwitter *twitAuth = new TomahawkOAuthTwitter( TomahawkUtils::nam(), this );
|
||||
twitAuth->setOAuthToken( m_plugin->twitterOAuthToken().toLatin1() );
|
||||
twitAuth->setOAuthTokenSecret( m_plugin->twitterOAuthTokenSecret().toLatin1() );
|
||||
twitAuth->setOAuthToken( credentials[ "oauthtoken" ].toString().toLatin1() );
|
||||
twitAuth->setOAuthTokenSecret( credentials[ "oauthtokensecret" ].toString().toLatin1() );
|
||||
QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( twitAuth, this );
|
||||
connect( credVerifier, SIGNAL( parsedUser(const QTweetUser &) ), SLOT( postGotTomahawkStatusAuthVerifyReply(const QTweetUser &) ) );
|
||||
credVerifier->verify();
|
||||
@@ -209,10 +229,10 @@ TwitterConfigWidget::postGotTomahawkStatusAuthVerifyReply( const QTweetUser &use
|
||||
emit twitterAuthed( false );
|
||||
return;
|
||||
}
|
||||
m_plugin->setTwitterScreenName( user.screenName() );
|
||||
TomahawkOAuthTwitter *twitAuth = new TomahawkOAuthTwitter( TomahawkUtils::nam(), this );
|
||||
twitAuth->setOAuthToken( m_plugin->twitterOAuthToken().toLatin1() );
|
||||
twitAuth->setOAuthTokenSecret( m_plugin->twitterOAuthTokenSecret().toLatin1() );
|
||||
QVariantHash credentials = m_account->credentials();
|
||||
twitAuth->setOAuthToken( credentials[ "oauthtoken" ].toString().toLatin1() );
|
||||
twitAuth->setOAuthTokenSecret( credentials[ "oauthtokensecret" ].toString().toLatin1() );
|
||||
if ( m_postGTtype != "Direct Message" )
|
||||
{
|
||||
QTweetStatusUpdate *statUpdate = new QTweetStatusUpdate( twitAuth, this );
|
||||
@@ -222,7 +242,7 @@ TwitterConfigWidget::postGotTomahawkStatusAuthVerifyReply( const QTweetUser &use
|
||||
QString message = QString( "Got Tomahawk? {" ) + Database::instance()->dbid() + QString( "} (" ) + uuid.mid( 1, 8 ) + QString( ")" ) + QString( " http://gettomahawk.com" );
|
||||
if ( m_postGTtype == "@Mention" )
|
||||
{
|
||||
QString user = ui->twitterUserTweetLineEdit->text();
|
||||
QString user = m_ui->twitterUserTweetLineEdit->text();
|
||||
if ( user.startsWith( "@" ) )
|
||||
user.remove( 0, 1 );
|
||||
message = QString( "@" ) + user + QString( " " ) + message;
|
||||
@@ -236,7 +256,7 @@ TwitterConfigWidget::postGotTomahawkStatusAuthVerifyReply( const QTweetUser &use
|
||||
connect( statUpdate, SIGNAL( error(QTweetNetBase::ErrorCode, const QString&) ), SLOT( postGotTomahawkStatusUpdateError(QTweetNetBase::ErrorCode, const QString &) ) );
|
||||
QString uuid = QUuid::createUuid();
|
||||
QString message = QString( "Got Tomahawk? {" ) + Database::instance()->dbid() + QString( "} (" ) + uuid.mid( 1, 8 ) + QString( ")" ) + QString( " http://gettomahawk.com" );
|
||||
QString user = ui->twitterUserTweetLineEdit->text();
|
||||
QString user = m_ui->twitterUserTweetLineEdit->text();
|
||||
if ( user.startsWith( "@" ) )
|
||||
user.remove( 0, 1 );
|
||||
statUpdate->post( user, message );
|
||||
@@ -268,3 +288,7 @@ TwitterConfigWidget::postGotTomahawkStatusUpdateError( QTweetNetBase::ErrorCode
|
||||
qDebug() << "Error posting Got Tomahawk message, error code is " << code << ", error message is " << errorMsg;
|
||||
QMessageBox::critical( this, tr("Tweetin' Error"), tr("There was an error posting your status -- sorry!") );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -16,10 +16,10 @@
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TWITTERCONFIGWIDGET_H
|
||||
#define TWITTERCONFIGWIDGET_H
|
||||
#ifndef TWITTERACCOUNTCONFIGWIDGET_H
|
||||
#define TWITTERACCOUNTCONFIGWIDGET_H
|
||||
|
||||
#include "sip/SipPlugin.h"
|
||||
#include "accounts/accountdllmacro.h"
|
||||
|
||||
#include <QTweetLib/qtweetstatus.h>
|
||||
#include <QTweetLib/qtweetdmstatus.h>
|
||||
@@ -28,24 +28,33 @@
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class TwitterPlugin;
|
||||
|
||||
namespace Ui {
|
||||
namespace Ui
|
||||
{
|
||||
class TwitterConfigWidget;
|
||||
}
|
||||
|
||||
class TwitterConfigWidget : public QWidget
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
class TwitterAccount;
|
||||
|
||||
|
||||
class ACCOUNTDLLEXPORT TwitterConfigWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TwitterConfigWidget( TwitterPlugin* plugin = 0, QWidget *parent = 0 );
|
||||
~TwitterConfigWidget();
|
||||
explicit TwitterConfigWidget( TwitterAccount* account = 0, QWidget *parent = 0 );
|
||||
virtual ~TwitterConfigWidget();
|
||||
|
||||
signals:
|
||||
void twitterAuthed( bool authed );
|
||||
|
||||
void sizeHintChanged();
|
||||
|
||||
private slots:
|
||||
void authDeauthTwitter();
|
||||
void startPostGotTomahawkStatus();
|
||||
@@ -61,9 +70,13 @@ private:
|
||||
void authenticateTwitter();
|
||||
void deauthenticateTwitter();
|
||||
|
||||
Ui::TwitterConfigWidget *ui;
|
||||
TwitterPlugin *m_plugin;
|
||||
Ui::TwitterConfigWidget *m_ui;
|
||||
TwitterAccount *m_account;
|
||||
QString m_postGTtype;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // TWITTERCONFIGWIDGET_H
|
64
src/accounts/xmpp/CMakeLists.txt
Normal file
@@ -0,0 +1,64 @@
|
||||
project( tomahawk )
|
||||
|
||||
include( ${QT_USE_FILE} )
|
||||
add_definitions( ${QT_DEFINITIONS} )
|
||||
add_definitions( -DQT_PLUGIN )
|
||||
add_definitions( -DQT_SHARED )
|
||||
add_definitions( -DACCOUNTDLLEXPORT_PRO )
|
||||
|
||||
set( xmppAccountSources
|
||||
xmppaccount.cpp
|
||||
xmppconfigwidget.cpp
|
||||
sip/xmppsip.cpp
|
||||
sip/tomahawkxmppmessage.cpp
|
||||
sip/tomahawkxmppmessagefactory.cpp
|
||||
sip/avatarmanager.cpp
|
||||
sip/xmlconsole.cpp
|
||||
)
|
||||
|
||||
set( xmppAccountHeaders
|
||||
xmppaccount.h
|
||||
xmppconfigwidget.h
|
||||
sip/xmppsip.h
|
||||
sip/avatarmanager.h
|
||||
sip/xmlconsole.h
|
||||
)
|
||||
|
||||
set( xmppAccountUI
|
||||
xmppconfigwidget.ui
|
||||
sip/xmlconsole.ui
|
||||
)
|
||||
|
||||
include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ..
|
||||
${QT_INCLUDE_DIR}
|
||||
${LIBJREEN_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
qt4_wrap_cpp( xmppAccountMoc ${xmppAccountHeaders} )
|
||||
qt4_wrap_ui( xmppAccountUI_H ${xmppAccountUI} )
|
||||
qt4_add_resources( RC_SRCS "resources.qrc" )
|
||||
add_library( tomahawk_account_xmpp MODULE ${xmppAccountUI_H} ${xmppAccountSources} ${xmppAccountMoc} ${RC_SRCS} )
|
||||
|
||||
IF( WIN32 )
|
||||
SET( OS_SPECIFIC_LINK_LIBRARIES
|
||||
${OS_SPECIFIC_LINK_LIBRARIES}
|
||||
"winmm.dll"
|
||||
"iphlpapi.a"
|
||||
)
|
||||
ENDIF( WIN32 )
|
||||
|
||||
target_link_libraries( tomahawk_account_xmpp
|
||||
${TOMAHAWK_LIBRARIES}
|
||||
${LIBJREEN_LIBRARY}
|
||||
${QT_LIBRARIES}
|
||||
${OS_SPECIFIC_LINK_LIBRARIES}
|
||||
)
|
||||
|
||||
IF( APPLE )
|
||||
# SET( CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} "-undefined dynamic_lookup" )
|
||||
ENDIF( APPLE )
|
||||
|
||||
install( TARGETS tomahawk_account_xmpp DESTINATION ${CMAKE_INSTALL_LIBDIR} )
|
||||
|
||||
add_subdirectory(googlewrapper)
|
||||
|
37
src/accounts/xmpp/googlewrapper/CMakeLists.txt
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
# fake google plugin
|
||||
|
||||
set( googleHeaders
|
||||
../xmppaccount.h
|
||||
../xmppconfigwidget.h
|
||||
../sip/xmppsip.h
|
||||
../sip/avatarmanager.h
|
||||
../sip/xmlconsole.h
|
||||
googlewrapper.h )
|
||||
|
||||
set( googleSources
|
||||
../xmppaccount.cpp
|
||||
../xmppconfigwidget.cpp
|
||||
../sip/xmppsip.cpp
|
||||
../sip/tomahawkxmppmessage.cpp
|
||||
../sip/tomahawkxmppmessagefactory.cpp
|
||||
../sip/avatarmanager.cpp
|
||||
../sip/xmlconsole.cpp
|
||||
|
||||
googlewrapper.cpp )
|
||||
|
||||
add_definitions(-DGOOGLE_WRAPPER)
|
||||
|
||||
qt4_add_resources( RCX_SRCS "resources.qrc" )
|
||||
|
||||
qt4_wrap_cpp( googleMoc ${googleHeaders} )
|
||||
add_library( tomahawk_account_google MODULE ${googleSources} ${googleMoc} ${googleMoc} ${RCX_SRCS} )
|
||||
|
||||
target_link_libraries( tomahawk_account_google
|
||||
${QT_LIBRARIES}
|
||||
${LIBJREEN_LIBRARY}
|
||||
${OS_SPECIFIC_LINK_LIBRARIES}
|
||||
tomahawklib
|
||||
)
|
||||
|
||||
install( TARGETS tomahawk_account_google DESTINATION ${CMAKE_INSTALL_LIBDIR} )
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
122
src/accounts/xmpp/googlewrapper/googlewrapper.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
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 "googlewrapper.h"
|
||||
#include "xmppconfigwidget.h"
|
||||
#include "ui_xmppconfigwidget.h"
|
||||
|
||||
#include "utils/tomahawkutilsgui.h"
|
||||
|
||||
#include <QtPlugin>
|
||||
#include <QInputDialog>
|
||||
|
||||
using namespace Tomahawk;
|
||||
using namespace Accounts;
|
||||
|
||||
Account*
|
||||
GoogleWrapperFactory::createAccount( const QString& pluginId )
|
||||
{
|
||||
return new GoogleWrapper( pluginId.isEmpty() ? generateId( factoryId() ) : pluginId );
|
||||
}
|
||||
|
||||
|
||||
QPixmap
|
||||
GoogleWrapperFactory::icon() const
|
||||
{
|
||||
return QPixmap( ":/gmail-logo.png" );
|
||||
}
|
||||
|
||||
GoogleWrapperSip::GoogleWrapperSip( Account* account )
|
||||
: XmppSipPlugin( account )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
GoogleWrapperSip::~GoogleWrapperSip()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
GoogleWrapperSip::showAddFriendDialog()
|
||||
{
|
||||
bool ok;
|
||||
QString id = QInputDialog::getText( TomahawkUtils::tomahawkWindow(), tr( "Add Friend" ),
|
||||
tr( "Enter Google Address:" ), QLineEdit::Normal, "", &ok );
|
||||
if ( !ok )
|
||||
return;
|
||||
|
||||
qDebug() << "Attempting to add google contact to roster:" << id;
|
||||
addContact( id );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
GoogleWrapperSip::defaultSuffix() const
|
||||
{
|
||||
return "@gmail.com";
|
||||
}
|
||||
|
||||
|
||||
GoogleWrapper::GoogleWrapper ( const QString& pluginID )
|
||||
: XmppAccount ( pluginID )
|
||||
{
|
||||
XmppConfigWidget* config = static_cast< XmppConfigWidget* >( m_configWidget.data() );
|
||||
config->m_ui->headerLabel->setText( tr( "Configure this Google Account" ) );
|
||||
config->m_ui->emailLabel->setText( tr( "Google Address" ) );
|
||||
config->m_ui->xmppBlurb->setText( tr( "Enter your Google login to connect with your friends using Tomahawk!" ) );
|
||||
config->m_ui->xmppUsername->setPlaceholderText( tr( "username@gmail.com" ) );
|
||||
config->m_ui->logoLabel->setPixmap( QPixmap( ":/gmail-logo.png" ) );
|
||||
config->m_ui->xmppServer->setText( "talk.google.com" );
|
||||
config->m_ui->xmppPort->setValue( 5222 );
|
||||
config->m_ui->groupBoxXmppAdvanced->hide();
|
||||
}
|
||||
|
||||
GoogleWrapper::~GoogleWrapper()
|
||||
{
|
||||
delete m_sipPlugin.data();
|
||||
}
|
||||
|
||||
|
||||
QPixmap
|
||||
GoogleWrapper::icon() const
|
||||
{
|
||||
return QPixmap( ":/gmail-logo.png" );
|
||||
}
|
||||
|
||||
|
||||
SipPlugin*
|
||||
GoogleWrapper::sipPlugin()
|
||||
{
|
||||
if ( m_xmppSipPlugin.isNull() )
|
||||
{
|
||||
m_xmppSipPlugin = QWeakPointer< XmppSipPlugin >( new GoogleWrapperSip( const_cast< GoogleWrapper* >( this ) ) );
|
||||
|
||||
connect( m_xmppSipPlugin.data(), SIGNAL( stateChanged( Tomahawk::Accounts::Account::ConnectionState ) ), this, SIGNAL( connectionStateChanged( Tomahawk::Accounts::Account::ConnectionState ) ) );
|
||||
connect( m_xmppSipPlugin.data(), SIGNAL( error( int, QString ) ), this, SIGNAL( error( int, QString ) ) );
|
||||
|
||||
return m_xmppSipPlugin.data();
|
||||
}
|
||||
return m_xmppSipPlugin.data();
|
||||
}
|
||||
|
||||
|
||||
#ifdef GOOGLE_WRAPPER
|
||||
Q_EXPORT_PLUGIN2( Tomahawk::Accounts::AccountFactory, Tomahawk::Accounts::GoogleWrapperFactory )
|
||||
#endif
|
@@ -19,39 +19,63 @@
|
||||
#ifndef GOOGLEWRAPPER_H
|
||||
#define GOOGLEWRAPPER_H
|
||||
|
||||
#include "sip/jabber/jabber.h"
|
||||
#include "xmppaccount.h"
|
||||
|
||||
class SIPDLLEXPORT GoogleWrapperFactory : public SipPluginFactory
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
class ACCOUNTDLLEXPORT GoogleWrapperFactory : public XmppAccountFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES( SipPluginFactory )
|
||||
Q_INTERFACES( Tomahawk::Accounts::AccountFactory )
|
||||
|
||||
public:
|
||||
GoogleWrapperFactory() {}
|
||||
virtual ~GoogleWrapperFactory() {}
|
||||
|
||||
virtual QString prettyName() const { return "Google"; }
|
||||
virtual QString factoryId() const { return "sipgoogle"; }
|
||||
virtual QIcon icon() const;
|
||||
virtual SipPlugin* createPlugin( const QString& pluginId );
|
||||
virtual QString factoryId() const { return "googleaccount"; }
|
||||
QString description() const { return tr( "Connect to GChat to find your friends" ); }
|
||||
virtual QPixmap icon() const;
|
||||
virtual Account* createAccount( const QString& pluginId );
|
||||
};
|
||||
|
||||
class SIPDLLEXPORT GoogleWrapper : public JabberPlugin
|
||||
class ACCOUNTDLLEXPORT GoogleWrapperSip : public XmppSipPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GoogleWrapper( const QString& pluginID );
|
||||
virtual ~GoogleWrapper() {}
|
||||
|
||||
virtual const QString name() const { return QString( "Google" ); }
|
||||
virtual const QString friendlyName() const { return "Google"; }
|
||||
virtual QIcon icon() const;
|
||||
|
||||
protected:
|
||||
QString defaultSuffix() const;
|
||||
GoogleWrapperSip( Tomahawk::Accounts::Account* account );
|
||||
virtual ~GoogleWrapperSip();
|
||||
|
||||
public slots:
|
||||
void showAddFriendDialog();
|
||||
|
||||
protected:
|
||||
QString defaultSuffix() const;
|
||||
};
|
||||
|
||||
class ACCOUNTDLLEXPORT GoogleWrapper : public XmppAccount
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GoogleWrapper( const QString& pluginID );
|
||||
virtual ~GoogleWrapper();
|
||||
|
||||
virtual const QString name() const { return QString( "Google" ); }
|
||||
virtual const QString friendlyName() const { return "Google"; }
|
||||
virtual QPixmap icon() const;
|
||||
|
||||
virtual SipPlugin* sipPlugin();
|
||||
|
||||
private:
|
||||
QWeakPointer< GoogleWrapperSip > m_sipPlugin;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // GOOGLEWRAPPER_H
|
@@ -1,5 +1,5 @@
|
||||
<!DOCTYPE RCC><RCC version="1.0">
|
||||
<qresource>
|
||||
<file>jabber-icon.png</file>
|
||||
<file>xmpp-icon.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
@@ -21,12 +21,12 @@
|
||||
|
||||
#include <jreen/client.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QDir>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QDir>
|
||||
|
||||
#include "../sipdllmacro.h"
|
||||
#include "accounts/accountdllmacro.h"
|
||||
|
||||
class SIPDLLEXPORT AvatarManager : public QObject
|
||||
class ACCOUNTDLLEXPORT AvatarManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@@ -16,12 +16,12 @@
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tomahawksipmessage.h"
|
||||
#include "tomahawkxmppmessage.h"
|
||||
|
||||
#include "utils/logger.h"
|
||||
|
||||
|
||||
class TomahawkSipMessagePrivate
|
||||
class TomahawkXmppMessagePrivate
|
||||
{
|
||||
public:
|
||||
QString ip;
|
||||
@@ -31,9 +31,9 @@ public:
|
||||
bool visible;
|
||||
};
|
||||
|
||||
TomahawkSipMessage::TomahawkSipMessage(const QString &ip, unsigned int port, const QString &uniqname, const QString &key) : d_ptr(new TomahawkSipMessagePrivate)
|
||||
TomahawkXmppMessage::TomahawkXmppMessage(const QString &ip, unsigned int port, const QString &uniqname, const QString &key) : d_ptr(new TomahawkXmppMessagePrivate)
|
||||
{
|
||||
Q_D(TomahawkSipMessage);
|
||||
Q_D(TomahawkXmppMessage);
|
||||
d->ip = ip;
|
||||
d->port = port;
|
||||
d->uniqname = uniqname;
|
||||
@@ -41,39 +41,39 @@ TomahawkSipMessage::TomahawkSipMessage(const QString &ip, unsigned int port, con
|
||||
d->visible = true;
|
||||
}
|
||||
|
||||
TomahawkSipMessage::TomahawkSipMessage() : d_ptr(new TomahawkSipMessagePrivate)
|
||||
TomahawkXmppMessage::TomahawkXmppMessage() : d_ptr(new TomahawkXmppMessagePrivate)
|
||||
{
|
||||
Q_D(TomahawkSipMessage);
|
||||
Q_D(TomahawkXmppMessage);
|
||||
d->visible = false;
|
||||
d->port = -1;
|
||||
}
|
||||
|
||||
|
||||
TomahawkSipMessage::~TomahawkSipMessage()
|
||||
TomahawkXmppMessage::~TomahawkXmppMessage()
|
||||
{
|
||||
}
|
||||
|
||||
const QString TomahawkSipMessage::ip() const
|
||||
const QString TomahawkXmppMessage::ip() const
|
||||
{
|
||||
return d_func()->ip;
|
||||
}
|
||||
|
||||
unsigned int TomahawkSipMessage::port() const
|
||||
unsigned int TomahawkXmppMessage::port() const
|
||||
{
|
||||
return d_func()->port;
|
||||
}
|
||||
|
||||
const QString TomahawkSipMessage::uniqname() const
|
||||
const QString TomahawkXmppMessage::uniqname() const
|
||||
{
|
||||
return d_func()->uniqname;
|
||||
}
|
||||
|
||||
const QString TomahawkSipMessage::key() const
|
||||
const QString TomahawkXmppMessage::key() const
|
||||
{
|
||||
return d_func()->key;
|
||||
}
|
||||
|
||||
bool TomahawkSipMessage::visible() const
|
||||
bool TomahawkXmppMessage::visible() const
|
||||
{
|
||||
return d_func()->visible;
|
||||
}
|
@@ -23,20 +23,20 @@
|
||||
|
||||
#define TOMAHAWK_SIP_MESSAGE_NS QLatin1String("http://www.tomhawk-player.org/sip/transports")
|
||||
|
||||
#include "../sipdllmacro.h"
|
||||
#include "accounts/accountdllmacro.h"
|
||||
|
||||
class TomahawkSipMessagePrivate;
|
||||
class SIPDLLEXPORT TomahawkSipMessage : public Jreen::Payload
|
||||
class TomahawkXmppMessagePrivate;
|
||||
class ACCOUNTDLLEXPORT TomahawkXmppMessage : public Jreen::Payload
|
||||
{
|
||||
J_PAYLOAD(TomahawkSipMessage)
|
||||
Q_DECLARE_PRIVATE(TomahawkSipMessage)
|
||||
J_PAYLOAD(TomahawkXmppMessage)
|
||||
Q_DECLARE_PRIVATE(TomahawkXmppMessage)
|
||||
public:
|
||||
// sets visible to true
|
||||
TomahawkSipMessage(const QString &ip, unsigned int port, const QString &uniqname, const QString &key);
|
||||
TomahawkXmppMessage(const QString &ip, unsigned int port, const QString &uniqname, const QString &key);
|
||||
|
||||
// sets visible to false as we dont have any extra information
|
||||
TomahawkSipMessage();
|
||||
~TomahawkSipMessage();
|
||||
TomahawkXmppMessage();
|
||||
~TomahawkXmppMessage();
|
||||
|
||||
const QString ip() const;
|
||||
unsigned int port() const;
|
||||
@@ -44,7 +44,7 @@ class SIPDLLEXPORT TomahawkSipMessage : public Jreen::Payload
|
||||
const QString key() const;
|
||||
bool visible() const;
|
||||
private:
|
||||
QScopedPointer<TomahawkSipMessagePrivate> d_ptr;
|
||||
QScopedPointer<TomahawkXmppMessagePrivate> d_ptr;
|
||||
};
|
||||
|
||||
#endif // ENTITYTIME_H
|
@@ -16,7 +16,7 @@
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "tomahawksipmessagefactory.h"
|
||||
#include "tomahawkxmppmessagefactory.h"
|
||||
|
||||
#include <QStringList>
|
||||
#include <QXmlStreamWriter>
|
||||
@@ -26,29 +26,29 @@
|
||||
|
||||
using namespace Jreen;
|
||||
|
||||
TomahawkSipMessageFactory::TomahawkSipMessageFactory()
|
||||
TomahawkXmppMessageFactory::TomahawkXmppMessageFactory()
|
||||
{
|
||||
m_depth = 0;
|
||||
m_state = AtNowhere;
|
||||
}
|
||||
|
||||
TomahawkSipMessageFactory::~TomahawkSipMessageFactory()
|
||||
TomahawkXmppMessageFactory::~TomahawkXmppMessageFactory()
|
||||
{
|
||||
}
|
||||
|
||||
QStringList TomahawkSipMessageFactory::features() const
|
||||
QStringList TomahawkXmppMessageFactory::features() const
|
||||
{
|
||||
return QStringList(TOMAHAWK_SIP_MESSAGE_NS);
|
||||
}
|
||||
|
||||
bool TomahawkSipMessageFactory::canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
|
||||
bool TomahawkXmppMessageFactory::canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes)
|
||||
{
|
||||
Q_UNUSED(uri);
|
||||
Q_UNUSED(attributes);
|
||||
return name == QLatin1String("tomahawk") && uri == TOMAHAWK_SIP_MESSAGE_NS;
|
||||
}
|
||||
|
||||
void TomahawkSipMessageFactory::handleStartElement(const QStringRef &name, const QStringRef &uri,
|
||||
void TomahawkXmppMessageFactory::handleStartElement(const QStringRef &name, const QStringRef &uri,
|
||||
const QXmlStreamAttributes &attributes)
|
||||
{
|
||||
m_depth++;
|
||||
@@ -83,7 +83,7 @@ void TomahawkSipMessageFactory::handleStartElement(const QStringRef &name, const
|
||||
Q_UNUSED(attributes);
|
||||
}
|
||||
|
||||
void TomahawkSipMessageFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
|
||||
void TomahawkXmppMessageFactory::handleEndElement(const QStringRef &name, const QStringRef &uri)
|
||||
{
|
||||
if (m_depth == 3)
|
||||
m_state = AtNowhere;
|
||||
@@ -92,7 +92,7 @@ void TomahawkSipMessageFactory::handleEndElement(const QStringRef &name, const Q
|
||||
m_depth--;
|
||||
}
|
||||
|
||||
void TomahawkSipMessageFactory::handleCharacterData(const QStringRef &text)
|
||||
void TomahawkXmppMessageFactory::handleCharacterData(const QStringRef &text)
|
||||
{
|
||||
/*if (m_state == AtUtc) {
|
||||
//m_utc = Util::fromStamp(text.toString());
|
||||
@@ -105,9 +105,9 @@ void TomahawkSipMessageFactory::handleCharacterData(const QStringRef &text)
|
||||
Q_UNUSED(text);
|
||||
}
|
||||
|
||||
void TomahawkSipMessageFactory::serialize(Payload *extension, QXmlStreamWriter *writer)
|
||||
void TomahawkXmppMessageFactory::serialize(Payload *extension, QXmlStreamWriter *writer)
|
||||
{
|
||||
TomahawkSipMessage *sipMessage = se_cast<TomahawkSipMessage*>(extension);
|
||||
TomahawkXmppMessage *sipMessage = se_cast<TomahawkXmppMessage*>(extension);
|
||||
|
||||
writer->writeStartElement(QLatin1String("tomahawk"));
|
||||
writer->writeDefaultNamespace(TOMAHAWK_SIP_MESSAGE_NS);
|
||||
@@ -137,10 +137,10 @@ void TomahawkSipMessageFactory::serialize(Payload *extension, QXmlStreamWriter *
|
||||
writer->writeEndElement();
|
||||
}
|
||||
|
||||
Payload::Ptr TomahawkSipMessageFactory::createPayload()
|
||||
Payload::Ptr TomahawkXmppMessageFactory::createPayload()
|
||||
{
|
||||
if(m_visible)
|
||||
return Payload::Ptr(new TomahawkSipMessage(m_ip, m_port, m_uniqname, m_key));
|
||||
return Payload::Ptr(new TomahawkXmppMessage(m_ip, m_port, m_uniqname, m_key));
|
||||
else
|
||||
return Payload::Ptr(new TomahawkSipMessage());
|
||||
return Payload::Ptr(new TomahawkXmppMessage());
|
||||
}
|
@@ -19,17 +19,17 @@
|
||||
#ifndef ENTITYTIMEFACTORY_P_H
|
||||
#define ENTITYTIMEFACTORY_P_H
|
||||
|
||||
#include "tomahawksipmessage.h"
|
||||
#include "tomahawkxmppmessage.h"
|
||||
|
||||
#include <jreen/stanzaextension.h>
|
||||
|
||||
#include "../sipdllmacro.h"
|
||||
#include "accounts/accountdllmacro.h"
|
||||
|
||||
class SIPDLLEXPORT TomahawkSipMessageFactory : public Jreen::PayloadFactory<TomahawkSipMessage>
|
||||
class ACCOUNTDLLEXPORT TomahawkXmppMessageFactory : public Jreen::PayloadFactory<TomahawkXmppMessage>
|
||||
{
|
||||
public:
|
||||
TomahawkSipMessageFactory();
|
||||
virtual ~TomahawkSipMessageFactory();
|
||||
TomahawkXmppMessageFactory();
|
||||
virtual ~TomahawkXmppMessageFactory();
|
||||
QStringList features() const;
|
||||
bool canParse(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
|
||||
void handleStartElement(const QStringRef &name, const QStringRef &uri, const QXmlStreamAttributes &attributes);
|
@@ -23,18 +23,18 @@
|
||||
#include <jreen/client.h>
|
||||
#include <jreen/jid.h>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QXmlStreamReader>
|
||||
#include <QDateTime>
|
||||
#include <QTextBlock>
|
||||
#include <QtGui/QWidget>
|
||||
#include <QtXml/QXmlStreamReader>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtGui/QTextBlock>
|
||||
|
||||
namespace Ui {
|
||||
class XmlConsole;
|
||||
}
|
||||
|
||||
#include "../sipdllmacro.h"
|
||||
#include "accounts/accountdllmacro.h"
|
||||
|
||||
class SIPDLLEXPORT XmlConsole : public QWidget, public Jreen::XmlStreamHandler
|
||||
class ACCOUNTDLLEXPORT XmlConsole : public QWidget, public Jreen::XmlStreamHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@@ -2,6 +2,7 @@
|
||||
*
|
||||
* Copyright 2010-2011, Dominik Schmidt <dev@dominik-schmidt.de>
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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
|
||||
@@ -17,14 +18,12 @@
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "jabber.h"
|
||||
#include "ui_configwidget.h"
|
||||
#include "xmppsip.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "tomahawksettings.h"
|
||||
#include "tomahawksipmessage.h"
|
||||
#include "tomahawksipmessagefactory.h"
|
||||
#include "tomahawkxmppmessage.h"
|
||||
#include "tomahawkxmppmessagefactory.h"
|
||||
|
||||
#include <jreen/jid.h>
|
||||
#include <jreen/capabilities.h>
|
||||
@@ -43,6 +42,10 @@
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#include <utils/tomahawkutils.h>
|
||||
#include <utils/logger.h>
|
||||
#include <accounts/AccountManager.h>
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
#include <QtGui/QInputDialog>
|
||||
#include <QtGui/QLineEdit>
|
||||
@@ -52,59 +55,33 @@
|
||||
#include <utils/tomahawkutilsgui.h>
|
||||
#include "utils/logger.h"
|
||||
|
||||
using namespace Jreen;
|
||||
using namespace Tomahawk;
|
||||
using namespace Accounts;
|
||||
|
||||
SipPlugin*
|
||||
JabberFactory::createPlugin( const QString& pluginId )
|
||||
{
|
||||
return new JabberPlugin( pluginId.isEmpty() ? generateId() : pluginId );
|
||||
}
|
||||
|
||||
|
||||
QIcon
|
||||
JabberFactory::icon() const
|
||||
{
|
||||
return QIcon( ":/jabber-icon.png" );
|
||||
}
|
||||
|
||||
|
||||
JabberPlugin::JabberPlugin( const QString& pluginId )
|
||||
: SipPlugin( pluginId )
|
||||
, m_state( Disconnected )
|
||||
XmppSipPlugin::XmppSipPlugin( Account *account )
|
||||
: SipPlugin( account )
|
||||
#ifndef ENABLE_HEADLESS
|
||||
, m_menu( 0 )
|
||||
, m_xmlConsole( 0 )
|
||||
#endif
|
||||
, m_state( Account::Disconnected )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_currentUsername = accountName();
|
||||
m_currentUsername = readUsername();
|
||||
|
||||
m_currentServer = readServer();
|
||||
m_currentPassword = readPassword();
|
||||
m_currentPort = readPort();
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
m_configWidget = QWeakPointer< QWidget >( new QWidget );
|
||||
m_ui = new Ui_JabberConfig;
|
||||
m_ui->setupUi( m_configWidget.data() );
|
||||
m_configWidget.data()->setVisible( false );
|
||||
|
||||
m_ui->jabberUsername->setText( m_currentUsername );
|
||||
m_ui->jabberPassword->setText( m_currentPassword );
|
||||
m_ui->jabberServer->setText( m_currentServer );
|
||||
m_ui->jabberPort->setValue( m_currentPort );
|
||||
m_ui->jidExistsLabel->hide();
|
||||
connect( m_ui->jabberUsername, SIGNAL( textChanged( QString ) ), SLOT( onCheckJidExists( QString ) ) );
|
||||
#endif
|
||||
|
||||
// setup JID object
|
||||
Jreen::JID jid = Jreen::JID( accountName() );
|
||||
Jreen::JID jid = Jreen::JID( readUsername() );
|
||||
|
||||
// general client setup
|
||||
m_client = new Jreen::Client( jid, m_currentPassword );
|
||||
setupClientHelper();
|
||||
|
||||
m_client->registerPayload(new TomahawkSipMessageFactory);
|
||||
m_client->registerPayload( new TomahawkXmppMessageFactory );
|
||||
m_currentResource = QString::fromAscii( "tomahawk%1" ).arg( QString::number( qrand() % 10000 ) );
|
||||
m_client->setResource( m_currentResource );
|
||||
|
||||
@@ -158,8 +135,7 @@ JabberPlugin::JabberPlugin( const QString& pluginId )
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
JabberPlugin::~JabberPlugin()
|
||||
XmppSipPlugin::~XmppSipPlugin()
|
||||
{
|
||||
delete m_avatarManager;
|
||||
delete m_roster;
|
||||
@@ -167,67 +143,29 @@ JabberPlugin::~JabberPlugin()
|
||||
delete m_xmlConsole;
|
||||
#endif
|
||||
delete m_client;
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
|
||||
const QString
|
||||
JabberPlugin::name() const
|
||||
{
|
||||
return QString( MYNAME );
|
||||
}
|
||||
|
||||
|
||||
const QString
|
||||
JabberPlugin::friendlyName() const
|
||||
{
|
||||
return QString( "Jabber" );
|
||||
}
|
||||
|
||||
|
||||
const QString
|
||||
JabberPlugin::accountName() const
|
||||
{
|
||||
return TomahawkSettings::instance()->value( pluginId() + "/username" ).toString();
|
||||
}
|
||||
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
QMenu*
|
||||
JabberPlugin::menu()
|
||||
XmppSipPlugin::menu()
|
||||
{
|
||||
return m_menu;
|
||||
}
|
||||
|
||||
|
||||
QWidget*
|
||||
JabberPlugin::configWidget()
|
||||
{
|
||||
return m_configWidget.data();
|
||||
}
|
||||
|
||||
|
||||
QIcon
|
||||
JabberPlugin::icon() const
|
||||
{
|
||||
return QIcon( ":/jabber-icon.png" );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
bool
|
||||
JabberPlugin::connectPlugin( bool startup )
|
||||
void
|
||||
XmppSipPlugin::connectPlugin()
|
||||
{
|
||||
Q_UNUSED( startup );
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if(m_client->isConnected())
|
||||
if( m_client->isConnected() )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "Already connected to server, not connecting again...";
|
||||
return true; //FIXME: should i return false here?!
|
||||
return; //FIXME: should i return false here?!
|
||||
}
|
||||
|
||||
qDebug() << "Connecting to the XMPP server..." << m_client->jid().full();
|
||||
qDebug() << "Connecting to the Xmpp server..." << m_client->jid().full();
|
||||
|
||||
//FIXME: we're badly workarounding some missing reconnection api here, to be fixed soon
|
||||
QTimer::singleShot( 1000, m_client, SLOT( connectToServer() ) );
|
||||
@@ -235,21 +173,21 @@ JabberPlugin::connectPlugin( bool startup )
|
||||
if ( m_client->connection() )
|
||||
connect(m_client->connection(), SIGNAL(error(SocketError)), SLOT(onError(SocketError)));
|
||||
|
||||
m_state = Connecting;
|
||||
m_state = Account::Connecting;
|
||||
emit stateChanged( m_state );
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JabberPlugin::disconnectPlugin()
|
||||
XmppSipPlugin::disconnectPlugin()
|
||||
{
|
||||
if (!m_client->isConnected())
|
||||
{
|
||||
if ( m_state != Disconnected ) // might be Connecting
|
||||
if ( m_state != Account::Disconnected ) // might be Connecting
|
||||
{
|
||||
m_state = Disconnected;
|
||||
emit stateChanged( m_state );
|
||||
m_state = Account::Disconnected;
|
||||
emit stateChanged( m_state );
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -262,13 +200,13 @@ JabberPlugin::disconnectPlugin()
|
||||
m_peers.clear();
|
||||
|
||||
m_client->disconnectFromServer( true );
|
||||
m_state = Disconnecting;
|
||||
m_state = Account::Disconnecting;
|
||||
emit stateChanged( m_state );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JabberPlugin::onConnect()
|
||||
XmppSipPlugin::onConnect()
|
||||
{
|
||||
// qDebug() << Q_FUNC_INFO;
|
||||
|
||||
@@ -280,7 +218,7 @@ JabberPlugin::onConnect()
|
||||
emit jidChanged( m_client->jid().full() );
|
||||
}
|
||||
|
||||
qDebug() << "Connected to jabber as:" << m_client->jid().full();
|
||||
qDebug() << "Connected to xmpp as:" << m_client->jid().full();
|
||||
|
||||
// set presence to least valid value
|
||||
m_client->setPresence(Jreen::Presence::XA, "Got Tomahawk? http://gettomahawk.com", -127);
|
||||
@@ -303,7 +241,7 @@ JabberPlugin::onConnect()
|
||||
//connect( m_room, SIGNAL( messageReceived( Jreen::Message, bool ) ), this, SLOT( onNewMessage( Jreen::Message ) ) );
|
||||
//connect( m_room, SIGNAL( presenceReceived( Jreen::Presence, const Jreen::MUCRoom::Participant* ) ), this, SLOT( onNewPresence( Jreen::Presence ) ) );
|
||||
|
||||
m_state = Connected;
|
||||
m_state = Account::Connected;
|
||||
emit stateChanged( m_state );
|
||||
|
||||
addMenuHelper();
|
||||
@@ -311,7 +249,7 @@ JabberPlugin::onConnect()
|
||||
|
||||
|
||||
void
|
||||
JabberPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
|
||||
XmppSipPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
@@ -321,7 +259,7 @@ JabberPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
|
||||
break;
|
||||
|
||||
case Jreen::Client::AuthorizationError:
|
||||
emit error( SipPlugin::AuthError, errorMessage( reason ) );
|
||||
emit error( Account::AuthError, errorMessage( reason ) );
|
||||
break;
|
||||
|
||||
case Jreen::Client::HostUnknown:
|
||||
@@ -332,7 +270,7 @@ JabberPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
|
||||
case Jreen::Client::SystemShutdown:
|
||||
case Jreen::Client::Conflict:
|
||||
case Jreen::Client::Unknown:
|
||||
emit error( SipPlugin::ConnectionError, errorMessage( reason ) );
|
||||
emit error( Account::ConnectionError, errorMessage( reason ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -340,7 +278,7 @@ JabberPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
m_state = Disconnected;
|
||||
m_state = Account::Disconnected;
|
||||
emit stateChanged( m_state );
|
||||
|
||||
removeMenuHelper();
|
||||
@@ -353,14 +291,14 @@ JabberPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
|
||||
|
||||
|
||||
void
|
||||
JabberPlugin::onError( const Jreen::Connection::SocketError& e )
|
||||
XmppSipPlugin::onError( const Jreen::Connection::SocketError& e )
|
||||
{
|
||||
tDebug() << "JABBER error:" << e;
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
JabberPlugin::errorMessage( Jreen::Client::DisconnectReason reason )
|
||||
XmppSipPlugin::errorMessage( Jreen::Client::DisconnectReason reason )
|
||||
{
|
||||
switch( reason )
|
||||
{
|
||||
@@ -402,7 +340,7 @@ JabberPlugin::errorMessage( Jreen::Client::DisconnectReason reason )
|
||||
break;
|
||||
}
|
||||
|
||||
m_state = Disconnected;
|
||||
m_state = Account::Disconnected;
|
||||
emit stateChanged( m_state );
|
||||
|
||||
return QString();
|
||||
@@ -410,7 +348,7 @@ JabberPlugin::errorMessage( Jreen::Client::DisconnectReason reason )
|
||||
|
||||
|
||||
void
|
||||
JabberPlugin::sendMsg( const QString& to, const QString& msg )
|
||||
XmppSipPlugin::sendMsg( const QString& to, const QString& msg )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << to << msg;
|
||||
|
||||
@@ -426,16 +364,16 @@ JabberPlugin::sendMsg( const QString& to, const QString& msg )
|
||||
QVariant v = parser.parse( msg.toAscii(), &ok );
|
||||
if ( !ok || v.type() != QVariant::Map )
|
||||
{
|
||||
qDebug() << "Invalid JSON in XMPP msg";
|
||||
qDebug() << "Invalid JSON in Xmpp msg";
|
||||
return;
|
||||
}
|
||||
QVariantMap m = v.toMap();
|
||||
/*******************************************************/
|
||||
|
||||
TomahawkSipMessage *sipMessage;
|
||||
TomahawkXmppMessage *sipMessage;
|
||||
if(m["visible"].toBool())
|
||||
{
|
||||
sipMessage = new TomahawkSipMessage( m["ip"].toString(),
|
||||
sipMessage = new TomahawkXmppMessage( m["ip"].toString(),
|
||||
m["port"].toInt(),
|
||||
m["uniqname"].toString(),
|
||||
m["key"].toString()
|
||||
@@ -443,7 +381,7 @@ JabberPlugin::sendMsg( const QString& to, const QString& msg )
|
||||
}
|
||||
else
|
||||
{
|
||||
sipMessage = new TomahawkSipMessage();
|
||||
sipMessage = new TomahawkXmppMessage();
|
||||
}
|
||||
|
||||
qDebug() << "Send sip messsage to " << to;
|
||||
@@ -456,7 +394,7 @@ JabberPlugin::sendMsg( const QString& to, const QString& msg )
|
||||
|
||||
|
||||
void
|
||||
JabberPlugin::broadcastMsg( const QString& msg )
|
||||
XmppSipPlugin::broadcastMsg( const QString& msg )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
@@ -471,7 +409,7 @@ JabberPlugin::broadcastMsg( const QString& msg )
|
||||
|
||||
|
||||
void
|
||||
JabberPlugin::addContact( const QString& jid, const QString& msg )
|
||||
XmppSipPlugin::addContact( const QString& jid, const QString& msg )
|
||||
{
|
||||
// Add contact to the Tomahawk group on the roster
|
||||
|
||||
@@ -486,30 +424,31 @@ JabberPlugin::addContact( const QString& jid, const QString& msg )
|
||||
|
||||
|
||||
void
|
||||
JabberPlugin::showAddFriendDialog()
|
||||
XmppSipPlugin::showAddFriendDialog()
|
||||
{
|
||||
#ifndef ENABLE_HEADLESS
|
||||
bool ok;
|
||||
QString id = QInputDialog::getText( TomahawkUtils::tomahawkWindow(), tr( "Add Friend" ),
|
||||
tr( "Enter Jabber ID:" ), QLineEdit::Normal, "", &ok ).trimmed();
|
||||
tr( "Enter Xmpp ID:" ), QLineEdit::Normal, "", &ok ).trimmed();
|
||||
|
||||
if ( !ok )
|
||||
return;
|
||||
|
||||
qDebug() << "Attempting to add jabber contact to roster:" << id;
|
||||
qDebug() << "Attempting to add xmpp contact to roster:" << id;
|
||||
addContact( id );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
JabberPlugin::defaultSuffix() const
|
||||
XmppSipPlugin::defaultSuffix() const
|
||||
{
|
||||
return "@jabber.org";
|
||||
return "@xmpp.org";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JabberPlugin::showXmlConsole()
|
||||
XmppSipPlugin::showXmlConsole()
|
||||
{
|
||||
#ifndef ENABLE_HEADLESS
|
||||
m_xmlConsole->show();
|
||||
@@ -518,14 +457,21 @@ JabberPlugin::showXmlConsole()
|
||||
|
||||
|
||||
void
|
||||
JabberPlugin::checkSettings()
|
||||
XmppSipPlugin::checkSettings()
|
||||
{
|
||||
configurationChanged();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmppSipPlugin::configurationChanged()
|
||||
{
|
||||
bool reconnect = false;
|
||||
|
||||
QString username, password, server;
|
||||
int port;
|
||||
|
||||
username = accountName();
|
||||
username = readUsername();
|
||||
password = readPassword();
|
||||
server = readServer();
|
||||
port = readPort();
|
||||
@@ -554,7 +500,10 @@ JabberPlugin::checkSettings()
|
||||
if ( !m_currentUsername.contains( '@' ) )
|
||||
{
|
||||
m_currentUsername += defaultSuffix();
|
||||
TomahawkSettings::instance()->setValue( pluginId() + "/username", m_currentUsername );
|
||||
QVariantHash credentials = m_account->credentials();
|
||||
credentials[ "username" ] = m_currentUsername;
|
||||
m_account->setCredentials( credentials );
|
||||
m_account->sync();
|
||||
}
|
||||
|
||||
if ( reconnect )
|
||||
@@ -565,12 +514,11 @@ JabberPlugin::checkSettings()
|
||||
setupClientHelper();
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "Updated settings";
|
||||
connectPlugin( false );
|
||||
connectPlugin();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void JabberPlugin::setupClientHelper()
|
||||
void XmppSipPlugin::setupClientHelper()
|
||||
{
|
||||
Jreen::JID jid = Jreen::JID( m_currentUsername );
|
||||
m_client->setJID( jid );
|
||||
@@ -590,13 +538,12 @@ void JabberPlugin::setupClientHelper()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void JabberPlugin::addMenuHelper()
|
||||
void XmppSipPlugin::addMenuHelper()
|
||||
{
|
||||
#ifndef ENABLE_HEADLESS
|
||||
if( !m_menu )
|
||||
{
|
||||
m_menu = new QMenu( QString( "%1 (" ).arg( friendlyName() ).append( accountName() ).append(")" ) );
|
||||
m_menu = new QMenu( QString( "%1 (" ).arg( friendlyName() ).append( readUsername() ).append(")" ) );
|
||||
|
||||
QAction* addFriendAction = m_menu->addAction( tr( "Add Friend..." ) );
|
||||
connect( addFriendAction, SIGNAL( triggered() ), this, SLOT( showAddFriendDialog() ) );
|
||||
@@ -612,8 +559,7 @@ void JabberPlugin::addMenuHelper()
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void JabberPlugin::removeMenuHelper()
|
||||
void XmppSipPlugin::removeMenuHelper()
|
||||
{
|
||||
#ifndef ENABLE_HEADLESS
|
||||
if( m_menu )
|
||||
@@ -627,9 +573,9 @@ void JabberPlugin::removeMenuHelper()
|
||||
}
|
||||
|
||||
|
||||
void JabberPlugin::onNewMessage( const Jreen::Message& message )
|
||||
void XmppSipPlugin::onNewMessage( const Jreen::Message& message )
|
||||
{
|
||||
if ( m_state != Connected )
|
||||
if ( m_state != Account::Connected )
|
||||
return;
|
||||
|
||||
// qDebug() << Q_FUNC_INFO << "message type" << message.subtype();
|
||||
@@ -668,10 +614,10 @@ void JabberPlugin::onNewMessage( const Jreen::Message& message )
|
||||
}
|
||||
|
||||
|
||||
void JabberPlugin::onPresenceReceived( const Jreen::RosterItem::Ptr &item, const Jreen::Presence& presence )
|
||||
void XmppSipPlugin::onPresenceReceived( const Jreen::RosterItem::Ptr &item, const Jreen::Presence& presence )
|
||||
{
|
||||
Q_UNUSED(item);
|
||||
if ( m_state != Connected )
|
||||
if ( m_state != Account::Connected )
|
||||
return;
|
||||
|
||||
Jreen::JID jid = presence.from();
|
||||
@@ -712,9 +658,9 @@ void JabberPlugin::onPresenceReceived( const Jreen::RosterItem::Ptr &item, const
|
||||
}
|
||||
|
||||
|
||||
void JabberPlugin::onSubscriptionReceived( const Jreen::RosterItem::Ptr& item, const Jreen::Presence& presence )
|
||||
void XmppSipPlugin::onSubscriptionReceived( const Jreen::RosterItem::Ptr& item, const Jreen::Presence& presence )
|
||||
{
|
||||
if ( m_state != Connected )
|
||||
if ( m_state != Account::Connected )
|
||||
return;
|
||||
|
||||
// qDebug() << Q_FUNC_INFO << "presence type:" << presence.subtype();
|
||||
@@ -766,7 +712,7 @@ void JabberPlugin::onSubscriptionReceived( const Jreen::RosterItem::Ptr& item, c
|
||||
|
||||
|
||||
void
|
||||
JabberPlugin::onSubscriptionRequestConfirmed( int result )
|
||||
XmppSipPlugin::onSubscriptionRequestConfirmed( int result )
|
||||
{
|
||||
#ifndef ENABLE_HEADLESS
|
||||
qDebug() << Q_FUNC_INFO << result;
|
||||
@@ -803,9 +749,9 @@ JabberPlugin::onSubscriptionRequestConfirmed( int result )
|
||||
}
|
||||
|
||||
|
||||
void JabberPlugin::onNewIq( const Jreen::IQ& iq )
|
||||
void XmppSipPlugin::onNewIq( const Jreen::IQ& iq )
|
||||
{
|
||||
if ( m_state != Connected )
|
||||
if ( m_state != Account::Connected )
|
||||
return;
|
||||
|
||||
Jreen::IQReply *reply = qobject_cast< Jreen::IQReply* >( sender() );
|
||||
@@ -855,7 +801,7 @@ void JabberPlugin::onNewIq( const Jreen::IQ& iq )
|
||||
}*/
|
||||
else
|
||||
{
|
||||
TomahawkSipMessage::Ptr sipMessage = iq.payload< TomahawkSipMessage >();
|
||||
TomahawkXmppMessage::Ptr sipMessage = iq.payload< TomahawkXmppMessage >();
|
||||
if(sipMessage)
|
||||
{
|
||||
iq.accept();
|
||||
@@ -885,7 +831,7 @@ void JabberPlugin::onNewIq( const Jreen::IQ& iq )
|
||||
}
|
||||
|
||||
|
||||
bool JabberPlugin::presenceMeansOnline( Jreen::Presence::Type p )
|
||||
bool XmppSipPlugin::presenceMeansOnline( Jreen::Presence::Type p )
|
||||
{
|
||||
switch( p )
|
||||
{
|
||||
@@ -900,7 +846,7 @@ bool JabberPlugin::presenceMeansOnline( Jreen::Presence::Type p )
|
||||
}
|
||||
|
||||
|
||||
void JabberPlugin::handlePeerStatus( const Jreen::JID& jid, Jreen::Presence::Type presenceType )
|
||||
void XmppSipPlugin::handlePeerStatus( const Jreen::JID& jid, Jreen::Presence::Type presenceType )
|
||||
{
|
||||
QString fulljid = jid.full();
|
||||
|
||||
@@ -950,11 +896,11 @@ void JabberPlugin::handlePeerStatus( const Jreen::JID& jid, Jreen::Presence::Typ
|
||||
}
|
||||
|
||||
|
||||
void JabberPlugin::onNewAvatar( const QString& jid )
|
||||
void XmppSipPlugin::onNewAvatar( const QString& jid )
|
||||
{
|
||||
#ifndef ENABLE_HEADLESS
|
||||
// qDebug() << Q_FUNC_INFO << jid;
|
||||
if ( m_state != Connected )
|
||||
if ( m_state != Account::Connected )
|
||||
return;
|
||||
|
||||
Q_ASSERT( !m_avatarManager->avatar( jid ).isNull() );
|
||||
@@ -980,84 +926,46 @@ void JabberPlugin::onNewAvatar( const QString& jid )
|
||||
|
||||
|
||||
bool
|
||||
JabberPlugin::readXmlConsoleEnabled()
|
||||
XmppSipPlugin::readXmlConsoleEnabled()
|
||||
{
|
||||
return TomahawkSettings::instance()->value( pluginId() + "/xmlconsole", QVariant( false ) ).toBool();
|
||||
QVariantHash configuration = m_account->configuration();
|
||||
return configuration.contains( "xmlconsole" ) && configuration[ "xmlconsole" ].toBool();
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
JabberPlugin::readPassword()
|
||||
XmppSipPlugin::readUsername()
|
||||
{
|
||||
return TomahawkSettings::instance()->value( pluginId() + "/password" ).toString();
|
||||
QVariantHash credentials = m_account->credentials();
|
||||
return credentials.contains( "username" ) ? credentials[ "username" ].toString() : QString();
|
||||
}
|
||||
|
||||
QString
|
||||
XmppSipPlugin::readPassword()
|
||||
{
|
||||
QVariantHash credentials = m_account->credentials();
|
||||
return credentials.contains( "password" ) ? credentials[ "password" ].toString() : QString();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
JabberPlugin::readPort()
|
||||
XmppSipPlugin::readPort()
|
||||
{
|
||||
return TomahawkSettings::instance()->value( pluginId() + "/port", 5222 ).toInt();
|
||||
QVariantHash configuration = m_account->configuration();
|
||||
return configuration.contains( "port" ) ? configuration[ "port" ].toInt() : 5222;
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
JabberPlugin::readServer()
|
||||
XmppSipPlugin::readServer()
|
||||
{
|
||||
return TomahawkSettings::instance()->value( pluginId() + "/server" ).toString();
|
||||
QVariantHash configuration = m_account->configuration();
|
||||
return configuration.contains( "server" ) ? configuration[ "server" ].toString() : QString();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JabberPlugin::onCheckJidExists( QString jid )
|
||||
{
|
||||
for ( int i=0; i<TomahawkSettings::instance()->sipPlugins().count(); i++ )
|
||||
{
|
||||
QString savedUsername = TomahawkSettings::instance()->value(
|
||||
TomahawkSettings::instance()->sipPlugins().at( i ) + "/username" ).toString();
|
||||
QStringList splitUserName = TomahawkSettings::instance()->value(
|
||||
TomahawkSettings::instance()->sipPlugins().at( i ) + "/username" ).toString().split("@");
|
||||
QString server = TomahawkSettings::instance()->value(
|
||||
TomahawkSettings::instance()->sipPlugins().at( i ) + "/server" ).toString();
|
||||
|
||||
if ( ( savedUsername == jid || splitUserName.contains( jid ) ) &&
|
||||
server == m_ui->jabberServer->text() && !jid.trimmed().isEmpty() )
|
||||
{
|
||||
m_ui->jidExistsLabel->show();
|
||||
// the already jid exists
|
||||
emit dataError( true );
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_ui->jidExistsLabel->hide();
|
||||
emit dataError( false );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JabberPlugin::saveConfig()
|
||||
{
|
||||
TomahawkSettings::instance()->setValue( pluginId() + "/username", m_ui->jabberUsername->text() );
|
||||
TomahawkSettings::instance()->setValue( pluginId() + "/password", m_ui->jabberPassword->text() );
|
||||
TomahawkSettings::instance()->setValue( pluginId() + "/port", m_ui->jabberPort->value() );
|
||||
TomahawkSettings::instance()->setValue( pluginId() + "/server", m_ui->jabberServer->text() );
|
||||
|
||||
checkSettings();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JabberPlugin::deletePlugin()
|
||||
{
|
||||
TomahawkSettings::instance()->remove( pluginId() );
|
||||
}
|
||||
|
||||
|
||||
SipPlugin::ConnectionState
|
||||
JabberPlugin::connectionState() const
|
||||
Account::ConnectionState
|
||||
XmppSipPlugin::connectionState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
#ifndef GOOGLE_WRAPPER
|
||||
Q_EXPORT_PLUGIN2( sipfactory, JabberFactory )
|
||||
#endif
|
@@ -2,6 +2,7 @@
|
||||
*
|
||||
* Copyright 2010-2011, Dominik Schmidt <dev@dominik-schmidt.de>
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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
|
||||
@@ -17,8 +18,8 @@
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef JABBER_H
|
||||
#define JABBER_H
|
||||
#ifndef XMPPSIP_H
|
||||
#define XMPPSIP_H
|
||||
|
||||
#include "sip/SipPlugin.h"
|
||||
|
||||
@@ -45,70 +46,49 @@
|
||||
#include <QtGui/QMessageBox>
|
||||
#endif
|
||||
|
||||
#define MYNAME "SIPJREEN"
|
||||
#define TOMAHAWK_FEATURE QLatin1String( "tomahawk:sip:v1" )
|
||||
#define TOMAHAWK_CAP_NODE_NAME QLatin1String( "http://tomahawk-player.org/" )
|
||||
|
||||
#include "../sipdllmacro.h"
|
||||
#include "accounts/accountdllmacro.h"
|
||||
|
||||
class Ui_JabberConfig;
|
||||
|
||||
class SIPDLLEXPORT JabberFactory : public SipPluginFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES( SipPluginFactory )
|
||||
|
||||
public:
|
||||
JabberFactory() {}
|
||||
virtual ~JabberFactory() {}
|
||||
|
||||
virtual QString prettyName() const { return "Jabber"; }
|
||||
virtual QString factoryId() const { return "sipjabber"; }
|
||||
virtual QIcon icon() const;
|
||||
virtual SipPlugin* createPlugin( const QString& pluginId );
|
||||
};
|
||||
|
||||
class SIPDLLEXPORT JabberPlugin : public SipPlugin
|
||||
class ACCOUNTDLLEXPORT XmppSipPlugin : public SipPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
JabberPlugin( const QString& pluginId );
|
||||
virtual ~JabberPlugin();
|
||||
XmppSipPlugin( Tomahawk::Accounts::Account* account );
|
||||
virtual ~XmppSipPlugin();
|
||||
|
||||
//FIXME: Make this more correct
|
||||
virtual bool isValid() const { return true; }
|
||||
virtual const QString name() const;
|
||||
virtual const QString friendlyName() const;
|
||||
virtual const QString accountName() const;
|
||||
virtual ConnectionState connectionState() const;
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
virtual QMenu* menu();
|
||||
virtual QIcon icon() const;
|
||||
virtual QWidget* configWidget();
|
||||
#endif
|
||||
virtual void saveConfig();
|
||||
virtual void deletePlugin();
|
||||
|
||||
// used by XmppAccount to expose connection state and controls
|
||||
Tomahawk::Accounts::Account::ConnectionState connectionState() const;
|
||||
|
||||
signals:
|
||||
void dataError( bool exists );
|
||||
void jidChanged( const QString& );
|
||||
|
||||
// Used by XmppAccount
|
||||
void stateChanged( Tomahawk::Accounts::Account::ConnectionState state );
|
||||
void error( int errorId, const QString& errorStr );
|
||||
|
||||
public slots:
|
||||
virtual bool connectPlugin( bool startup );
|
||||
void disconnectPlugin();
|
||||
void checkSettings();
|
||||
void sendMsg( const QString& to, const QString& msg );
|
||||
virtual void connectPlugin();
|
||||
virtual void disconnectPlugin();
|
||||
virtual void checkSettings();
|
||||
virtual void configurationChanged();
|
||||
virtual void sendMsg( const QString& to, const QString& msg );
|
||||
void broadcastMsg( const QString &msg );
|
||||
void addContact( const QString &jid, const QString& msg = QString() );
|
||||
virtual void addContact( const QString &jid, const QString& msg = QString() );
|
||||
void showAddFriendDialog();
|
||||
|
||||
protected:
|
||||
virtual QString defaultSuffix() const;
|
||||
|
||||
Ui_JabberConfig* m_ui; // so the google wrapper can change the config dialog a bit
|
||||
|
||||
private slots:
|
||||
void showXmlConsole();
|
||||
void onConnect();
|
||||
@@ -122,10 +102,10 @@ private slots:
|
||||
void onError( const Jreen::Connection::SocketError& e );
|
||||
void onNewIq( const Jreen::IQ &iq );
|
||||
void onNewAvatar( const QString &jid );
|
||||
void onCheckJidExists( QString jid );
|
||||
|
||||
private:
|
||||
bool readXmlConsoleEnabled();
|
||||
QString readUsername();
|
||||
QString readPassword();
|
||||
QString readServer();
|
||||
int readPort();
|
||||
@@ -138,15 +118,11 @@ private:
|
||||
bool presenceMeansOnline( Jreen::Presence::Type p );
|
||||
void handlePeerStatus( const Jreen::JID &jid, Jreen::Presence::Type presenceType );
|
||||
|
||||
using SipPlugin::errorMessage;
|
||||
|
||||
QString m_currentUsername;
|
||||
QString m_currentPassword;
|
||||
QString m_currentServer;
|
||||
int m_currentPort;
|
||||
ConnectionState m_state;
|
||||
|
||||
QWeakPointer< QWidget > m_configWidget;
|
||||
Tomahawk::Accounts::Account::ConnectionState m_state;
|
||||
|
||||
QString m_currentResource;
|
||||
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
114
src/accounts/xmpp/xmppaccount.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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 "xmppaccount.h"
|
||||
#include "xmppconfigwidget.h"
|
||||
#include "sip/SipPlugin.h"
|
||||
#include "ui_xmppconfigwidget.h"
|
||||
|
||||
#include <QtCore/QtPlugin>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
Account*
|
||||
XmppAccountFactory::createAccount( const QString& accountId )
|
||||
{
|
||||
return new XmppAccount( accountId.isEmpty() ? Tomahawk::Accounts::generateId( factoryId() ) : accountId );
|
||||
}
|
||||
|
||||
|
||||
XmppAccount::XmppAccount( const QString &accountId )
|
||||
: Account( accountId )
|
||||
{
|
||||
setAccountServiceName( "XMPP (Jabber)" );
|
||||
setTypes( SipType );
|
||||
|
||||
m_configWidget = QWeakPointer< QWidget >( new XmppConfigWidget( this, 0 ) );
|
||||
}
|
||||
|
||||
|
||||
XmppAccount::~XmppAccount()
|
||||
{
|
||||
delete m_xmppSipPlugin.data();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmppAccount::authenticate()
|
||||
{
|
||||
if ( connectionState() != Account::Connected )
|
||||
sipPlugin()->connectPlugin();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmppAccount::deauthenticate()
|
||||
{
|
||||
if ( connectionState() != Account::Disconnected )
|
||||
sipPlugin()->disconnectPlugin();
|
||||
}
|
||||
|
||||
bool
|
||||
XmppAccount::isAuthenticated() const
|
||||
{
|
||||
return m_xmppSipPlugin.data()->connectionState() == Account::Connected;
|
||||
}
|
||||
|
||||
|
||||
Account::ConnectionState
|
||||
XmppAccount::connectionState() const
|
||||
{
|
||||
return m_xmppSipPlugin.data()->connectionState();
|
||||
}
|
||||
|
||||
void
|
||||
XmppAccount::saveConfig()
|
||||
{
|
||||
if ( !m_configWidget.isNull() )
|
||||
static_cast< XmppConfigWidget* >( m_configWidget.data() )->saveConfig();
|
||||
}
|
||||
|
||||
|
||||
SipPlugin*
|
||||
XmppAccount::sipPlugin()
|
||||
{
|
||||
if ( m_xmppSipPlugin.isNull() )
|
||||
{
|
||||
m_xmppSipPlugin = QWeakPointer< XmppSipPlugin >( new XmppSipPlugin( this ) );
|
||||
|
||||
connect( m_xmppSipPlugin.data(), SIGNAL( stateChanged( Tomahawk::Accounts::Account::ConnectionState ) ), this, SIGNAL( connectionStateChanged( Tomahawk::Accounts::Account::ConnectionState ) ) );
|
||||
connect( m_xmppSipPlugin.data(), SIGNAL( error( int, QString ) ), this, SIGNAL( error( int, QString ) ) );
|
||||
|
||||
return m_xmppSipPlugin.data();
|
||||
}
|
||||
return m_xmppSipPlugin.data();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifndef GOOGLE_WRAPPER
|
||||
Q_EXPORT_PLUGIN2( Tomahawk::Accounts::AccountFactory, Tomahawk::Accounts::XmppAccountFactory )
|
||||
#endif
|
89
src/accounts/xmpp/xmppaccount.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Dominik Schmidt <dev@dominik-schmidt.de>
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@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 XMPPACCOUNT_H
|
||||
#define XMPPACCOUNT_H
|
||||
|
||||
#include "sip/xmppsip.h"
|
||||
#include "accounts/accountdllmacro.h"
|
||||
#include "accounts/Account.h"
|
||||
|
||||
#define MYNAME "ACCOUNTJABBER"
|
||||
|
||||
class Ui_XmppConfigWidget;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
class ACCOUNTDLLEXPORT XmppAccountFactory : public AccountFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES( Tomahawk::Accounts::AccountFactory )
|
||||
|
||||
// for settings access
|
||||
friend class XmppConfigWidget;
|
||||
public:
|
||||
XmppAccountFactory() {}
|
||||
virtual ~XmppAccountFactory() {}
|
||||
|
||||
QString prettyName() const { return "XMPP (Jabber)"; }
|
||||
QString description() const { return tr( "Log on to your Jabber/XMPP account to connect to your friends" ); }
|
||||
QString factoryId() const { return "xmppaccount"; }
|
||||
QPixmap icon() const { return QPixmap( ":/xmpp-icon.png" ); }
|
||||
AccountTypes types() const { return AccountTypes( SipType ); };
|
||||
Account* createAccount( const QString& pluginId = QString() );
|
||||
};
|
||||
|
||||
class ACCOUNTDLLEXPORT XmppAccount : public Account
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
XmppAccount( const QString &accountId );
|
||||
virtual ~XmppAccount();
|
||||
|
||||
QPixmap icon() const { return QPixmap( ":/xmpp-icon.png" ); }
|
||||
|
||||
void authenticate();
|
||||
void deauthenticate();
|
||||
bool isAuthenticated() const;
|
||||
|
||||
Tomahawk::InfoSystem::InfoPlugin* infoPlugin() { return 0; }
|
||||
SipPlugin* sipPlugin();
|
||||
|
||||
QWidget* configurationWidget() { return m_configWidget.data(); }
|
||||
QWidget* aclWidget() { return 0; }
|
||||
void saveConfig();
|
||||
|
||||
virtual Tomahawk::Accounts::Account::ConnectionState connectionState() const;
|
||||
|
||||
protected:
|
||||
QWeakPointer< QWidget > m_configWidget; // so the google wrapper can change the config dialog a bit
|
||||
QWeakPointer< XmppSipPlugin > m_xmppSipPlugin;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
108
src/accounts/xmpp/xmppconfigwidget.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.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 "xmppaccount.h"
|
||||
#include "xmppconfigwidget.h"
|
||||
#include "ui_xmppconfigwidget.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <accounts/AccountManager.h>
|
||||
#include <utils/logger.h>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
XmppConfigWidget::XmppConfigWidget( XmppAccount* account, QWidget *parent ) :
|
||||
QWidget( parent ),
|
||||
m_ui( new Ui::XmppConfigWidget ),
|
||||
m_account( account )
|
||||
{
|
||||
m_ui->setupUi( this );
|
||||
|
||||
m_ui->xmppUsername->setText( account->credentials().contains( "username" ) ? account->credentials()[ "username" ].toString() : QString() );
|
||||
m_ui->xmppPassword->setText( account->credentials().contains( "password" ) ? account->credentials()[ "password" ].toString() : QString() );
|
||||
m_ui->xmppServer->setText( account->configuration().contains( "server" ) ? account->configuration()[ "server" ].toString() : QString() );
|
||||
m_ui->xmppPort->setValue( account->configuration().contains( "port" ) ? account->configuration()[ "port" ].toInt() : 5222 );
|
||||
m_ui->jidExistsLabel->hide();
|
||||
|
||||
connect( m_ui->xmppUsername, SIGNAL( textChanged( QString ) ), SLOT( onCheckJidExists( QString ) ) );
|
||||
}
|
||||
|
||||
|
||||
XmppConfigWidget::~XmppConfigWidget()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
void
|
||||
XmppConfigWidget::saveConfig()
|
||||
{
|
||||
QVariantHash credentials = m_account->credentials();
|
||||
credentials[ "username" ] = m_ui->xmppUsername->text().trimmed();
|
||||
credentials[ "password" ] = m_ui->xmppPassword->text().trimmed();
|
||||
|
||||
QVariantHash configuration = m_account->configuration();
|
||||
configuration[ "server" ] = m_ui->xmppServer->text().trimmed();
|
||||
configuration[ "port" ] = m_ui->xmppPort->text().trimmed();
|
||||
|
||||
m_account->setAccountFriendlyName( m_ui->xmppUsername->text() );
|
||||
m_account->setCredentials( credentials );
|
||||
m_account->setConfiguration( configuration);
|
||||
m_account->sync();
|
||||
|
||||
static_cast< XmppSipPlugin* >( m_account->sipPlugin() )->checkSettings();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XmppConfigWidget::onCheckJidExists( QString jid )
|
||||
{
|
||||
QList< Tomahawk::Accounts::Account* > accounts = Tomahawk::Accounts::AccountManager::instance()->accounts( Tomahawk::Accounts::SipType );
|
||||
foreach( Tomahawk::Accounts::Account* account, accounts )
|
||||
{
|
||||
if ( account->accountId() == m_account->accountId() )
|
||||
continue;
|
||||
|
||||
QString savedUsername = account->credentials()[ "username" ].toString();
|
||||
QStringList savedSplitUsername = account->credentials()[ "username" ].toString().split("@");
|
||||
QString savedServer = account->configuration()[ "server" ].toString();
|
||||
int savedPort = account->configuration()[ "port" ].toInt();
|
||||
|
||||
if ( ( savedUsername == jid || savedSplitUsername.contains( jid ) ) &&
|
||||
savedServer == m_ui->xmppServer->text() &&
|
||||
savedPort == m_ui->xmppPort->value() &&
|
||||
!jid.trimmed().isEmpty() )
|
||||
{
|
||||
m_ui->jidExistsLabel->show();
|
||||
// the already jid exists
|
||||
emit dataError( true );
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_ui->jidExistsLabel->hide();
|
||||
emit dataError( false );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
68
src/accounts/xmpp/xmppconfigwidget.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.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 JABBERACCOUNTCONFIGWIDGET_H
|
||||
#define JABBERACCOUNTCONFIGWIDGET_H
|
||||
|
||||
#include "accounts/accountdllmacro.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class XmppConfigWidget;
|
||||
}
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
class XmppAccount;
|
||||
class GoogleWrapper;
|
||||
|
||||
|
||||
class ACCOUNTDLLEXPORT XmppConfigWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit XmppConfigWidget( XmppAccount* account = 0, QWidget *parent = 0 );
|
||||
virtual ~XmppConfigWidget();
|
||||
|
||||
void saveConfig();
|
||||
|
||||
signals:
|
||||
void dataError( bool exists );
|
||||
|
||||
private slots:
|
||||
void onCheckJidExists( QString jid );
|
||||
|
||||
private:
|
||||
Ui::XmppConfigWidget *m_ui;
|
||||
XmppAccount *m_account;
|
||||
|
||||
friend class GoogleWrapper; // So google wrapper can modify the labels and text
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // TWITTERCONFIGWIDGET_H
|
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>JabberConfig</class>
|
||||
<widget class="QWidget" name="JabberConfig">
|
||||
<class>XmppConfigWidget</class>
|
||||
<widget class="QWidget" name="XmppConfig">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
@@ -11,7 +11,7 @@
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Jabber Configuration</string>
|
||||
<string>Xmpp Configuration</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
@@ -35,7 +35,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="resources.qrc">:/jabber-icon.png</pixmap>
|
||||
<pixmap resource="resources.qrc">:/xmpp-icon.png</pixmap>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -49,7 +49,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Configure this Jabber account</string>
|
||||
<string>Configure this Xmpp account</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -84,9 +84,9 @@
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="jabberBlurb">
|
||||
<widget class="QLabel" name="xmppBlurb">
|
||||
<property name="text">
|
||||
<string>Enter your Jabber login to connect with your friends using Tomahawk!</string>
|
||||
<string>Enter your Xmpp login to connect with your friends using Tomahawk!</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -128,15 +128,15 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Jabber ID:</string>
|
||||
<string>Xmpp ID:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>jabberUsername</cstring>
|
||||
<cstring>xmppUsername</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="jabberUsername">
|
||||
<widget class="QLineEdit" name="xmppUsername">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -160,12 +160,12 @@
|
||||
<string>Password:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>jabberPassword</cstring>
|
||||
<cstring>xmppPassword</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="jabberPassword">
|
||||
<widget class="QLineEdit" name="xmppPassword">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -196,7 +196,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxJabberAdvanced">
|
||||
<widget class="QGroupBox" name="groupBoxXmppAdvanced">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
@@ -207,13 +207,13 @@
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Advanced Jabber Settings</string>
|
||||
<string>Advanced Xmpp Settings</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelJabberServer">
|
||||
<widget class="QLabel" name="labelXmppServer">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -233,12 +233,12 @@
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>jabberServer</cstring>
|
||||
<cstring>xmppServer</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="jabberServer">
|
||||
<widget class="QLineEdit" name="xmppServer">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
@@ -248,7 +248,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelJabberPort">
|
||||
<widget class="QLabel" name="labelXmppPort">
|
||||
<property name="text">
|
||||
<string>Port:</string>
|
||||
</property>
|
||||
@@ -258,7 +258,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="jabberPort">
|
||||
<widget class="QSpinBox" name="xmppPort">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
@@ -4,15 +4,17 @@ include( ${QT_USE_FILE} )
|
||||
add_definitions( ${QT_DEFINITIONS} )
|
||||
add_definitions( -DQT_PLUGIN )
|
||||
add_definitions( -DQT_SHARED )
|
||||
add_definitions( -DSIPDLLEXPORT_PRO )
|
||||
add_definitions( -DACCOUNTDLLEXPORT_PRO )
|
||||
|
||||
set( zeroconfSources
|
||||
zeroconf.cpp
|
||||
zeroconfaccount.cpp
|
||||
)
|
||||
|
||||
set( zeroconfHeaders
|
||||
zeroconf.h
|
||||
tomahawkzeroconf.h
|
||||
zeroconfaccount.h
|
||||
)
|
||||
|
||||
include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ..
|
||||
@@ -22,7 +24,7 @@ include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ..
|
||||
qt4_wrap_ui( UI_SRCS configwidget.ui )
|
||||
qt4_add_resources( RC_SRCS "resources.qrc" )
|
||||
qt4_wrap_cpp( zeroconfMoc ${zeroconfHeaders} )
|
||||
add_library( tomahawk_sipzeroconf SHARED ${zeroconfSources} ${zeroconfMoc} ${RC_SRCS} ${UI_SRCS} )
|
||||
add_library( tomahawk_account_zeroconf MODULE ${zeroconfSources} ${zeroconfMoc} ${RC_SRCS} ${UI_SRCS} )
|
||||
|
||||
IF( WIN32 )
|
||||
SET( OS_SPECIFIC_LINK_LIBRARIES
|
||||
@@ -32,7 +34,7 @@ SET( OS_SPECIFIC_LINK_LIBRARIES
|
||||
)
|
||||
ENDIF( WIN32 )
|
||||
|
||||
target_link_libraries( tomahawk_sipzeroconf
|
||||
target_link_libraries( tomahawk_account_zeroconf
|
||||
${QT_LIBRARIES}
|
||||
${OS_SPECIFIC_LINK_LIBRARIES}
|
||||
${TOMAHAWK_LIBRARIES}
|
||||
@@ -42,4 +44,4 @@ IF( APPLE )
|
||||
# SET( CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} "-undefined dynamic_lookup" )
|
||||
ENDIF( APPLE )
|
||||
|
||||
install( TARGETS tomahawk_sipzeroconf DESTINATION ${CMAKE_INSTALL_LIBDIR} )
|
||||
install( TARGETS tomahawk_account_zeroconf DESTINATION ${CMAKE_INSTALL_LIBDIR} )
|
@@ -30,10 +30,9 @@
|
||||
|
||||
#include "database/database.h"
|
||||
#include "network/servent.h"
|
||||
#include "accounts/accountdllmacro.h"
|
||||
|
||||
#include "../sipdllmacro.h"
|
||||
|
||||
class SIPDLLEXPORT Node : public QObject
|
||||
class Node : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -61,7 +60,7 @@ public slots:
|
||||
emit tomahawkHostFound( ip, port, "Unknown", nid );
|
||||
this->deleteLater();
|
||||
}
|
||||
|
||||
|
||||
void resolve()
|
||||
{
|
||||
QHostInfo::lookupHost( ip, this, SLOT( resolved( QHostInfo ) ) );
|
||||
@@ -74,7 +73,7 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class SIPDLLEXPORT TomahawkZeroconf : public QObject
|
||||
class ACCOUNTDLLEXPORT TomahawkZeroconf : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
@@ -1,6 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 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
|
||||
@@ -24,20 +25,15 @@
|
||||
|
||||
#include "tomahawksettings.h"
|
||||
#include "utils/logger.h"
|
||||
#include "zeroconfaccount.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
using namespace Accounts;
|
||||
|
||||
SipPlugin*
|
||||
ZeroconfFactory::createPlugin( const QString& pluginId )
|
||||
{
|
||||
return new ZeroconfPlugin( pluginId.isEmpty() ? generateId() : pluginId );
|
||||
}
|
||||
|
||||
ZeroconfPlugin::ZeroconfPlugin() : SipPlugin( "" ) {}
|
||||
|
||||
ZeroconfPlugin::ZeroconfPlugin ( const QString& pluginId )
|
||||
: SipPlugin( pluginId )
|
||||
ZeroconfPlugin::ZeroconfPlugin ( ZeroconfAccount* parent )
|
||||
: SipPlugin( parent )
|
||||
, m_zeroconf( 0 )
|
||||
, m_state( Disconnected )
|
||||
, m_state( Account::Disconnected )
|
||||
, m_cachedNodes()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
@@ -66,22 +62,15 @@ ZeroconfPlugin::friendlyName() const
|
||||
return QString( MYNAME );
|
||||
}
|
||||
|
||||
SipPlugin::ConnectionState
|
||||
Account::ConnectionState
|
||||
ZeroconfPlugin::connectionState() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
#ifndef ENABLE_HEADLESS
|
||||
QIcon
|
||||
ZeroconfFactory::icon() const
|
||||
{
|
||||
return QIcon( ":/zeroconf-icon.png" );
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
ZeroconfPlugin::connectPlugin( bool /*startup*/ )
|
||||
void
|
||||
ZeroconfPlugin::connectPlugin()
|
||||
{
|
||||
delete m_zeroconf;
|
||||
m_zeroconf = new TomahawkZeroconf( Servent::instance()->port(), this );
|
||||
@@ -89,7 +78,7 @@ ZeroconfPlugin::connectPlugin( bool /*startup*/ )
|
||||
SLOT( lanHostFound( QString, int, QString, QString ) ) );
|
||||
|
||||
advertise();
|
||||
m_state = Connected;
|
||||
m_state = Account::Connected;
|
||||
|
||||
foreach( const QStringList& nodeSet, m_cachedNodes )
|
||||
{
|
||||
@@ -99,15 +88,13 @@ ZeroconfPlugin::connectPlugin( bool /*startup*/ )
|
||||
m_cachedNodes.clear();
|
||||
|
||||
m_advertisementTimer.start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ZeroconfPlugin::disconnectPlugin()
|
||||
{
|
||||
m_advertisementTimer.stop();
|
||||
m_state = Disconnected;
|
||||
m_state = Account::Disconnected;
|
||||
|
||||
delete m_zeroconf;
|
||||
m_zeroconf = 0;
|
||||
@@ -118,7 +105,7 @@ ZeroconfPlugin::disconnectPlugin()
|
||||
QIcon
|
||||
ZeroconfPlugin::icon() const
|
||||
{
|
||||
return QIcon( ":/zeroconf-icon.png" );
|
||||
return account()->icon();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -138,7 +125,7 @@ ZeroconfPlugin::lanHostFound( const QString& host, int port, const QString& name
|
||||
|
||||
qDebug() << "Found LAN host:" << host << port << nodeid;
|
||||
|
||||
if ( m_state != Connected )
|
||||
if ( m_state != Account::Connected )
|
||||
{
|
||||
qDebug() << "Not online, so not connecting.";
|
||||
QStringList nodeSet;
|
||||
@@ -153,5 +140,3 @@ ZeroconfPlugin::lanHostFound( const QString& host, int port, const QString& name
|
||||
qDebug() << "Already connected to" << host;
|
||||
}
|
||||
|
||||
|
||||
Q_EXPORT_PLUGIN2( sipfactory, ZeroconfFactory )
|
@@ -1,6 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 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
|
||||
@@ -20,55 +21,45 @@
|
||||
#define ZEROCONF_H
|
||||
|
||||
#include "sip/SipPlugin.h"
|
||||
#include "accounts/Account.h"
|
||||
#include "tomahawkzeroconf.h"
|
||||
|
||||
#include "../sipdllmacro.h"
|
||||
#include "../accountdllmacro.h"
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#define MYNAME "Local Network"
|
||||
|
||||
class SIPDLLEXPORT ZeroconfFactory : public SipPluginFactory
|
||||
namespace Tomahawk
|
||||
{
|
||||
namespace Accounts
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES( SipPluginFactory )
|
||||
public:
|
||||
ZeroconfFactory() {}
|
||||
virtual ~ZeroconfFactory() {}
|
||||
|
||||
virtual QString factoryId() const { return "sipzeroconf"; }
|
||||
virtual QString prettyName() const { return "Local Network"; }
|
||||
virtual bool isUnique() const { return true; }
|
||||
#ifndef ENABLE_HEADLESS
|
||||
virtual QIcon icon() const;
|
||||
#endif
|
||||
class ZeroconfAccount;
|
||||
|
||||
|
||||
virtual SipPlugin* createPlugin ( const QString& pluginId = QString() );
|
||||
};
|
||||
|
||||
class SIPDLLEXPORT ZeroconfPlugin : public SipPlugin
|
||||
class ACCOUNTDLLEXPORT ZeroconfPlugin : public SipPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ZeroconfPlugin();
|
||||
ZeroconfPlugin( const QString& pluginId );
|
||||
ZeroconfPlugin( ZeroconfAccount* acc );
|
||||
|
||||
virtual ~ZeroconfPlugin();
|
||||
|
||||
virtual const QString name() const;
|
||||
virtual const QString friendlyName() const;
|
||||
virtual const QString accountName() const;
|
||||
virtual ConnectionState connectionState() const;
|
||||
virtual Account::ConnectionState connectionState() const;
|
||||
virtual bool isValid() const { return true; }
|
||||
#ifndef ENABLE_HEADLESS
|
||||
virtual QIcon icon() const;
|
||||
#endif
|
||||
virtual void checkSettings() {}
|
||||
virtual void configurationChanged() {}
|
||||
|
||||
public slots:
|
||||
virtual bool connectPlugin( bool startup );
|
||||
void connectPlugin();
|
||||
void disconnectPlugin();
|
||||
|
||||
void advertise();
|
||||
@@ -82,9 +73,12 @@ private slots:
|
||||
|
||||
private:
|
||||
TomahawkZeroconf* m_zeroconf;
|
||||
ConnectionState m_state;
|
||||
Account::ConnectionState m_state;
|
||||
QVector<QStringList> m_cachedNodes;
|
||||
QTimer m_advertisementTimer;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
128
src/accounts/zeroconf/zeroconfaccount.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/* === 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 "zeroconfaccount.h"
|
||||
|
||||
#include "sip/SipPlugin.h"
|
||||
#include "zeroconf.h"
|
||||
|
||||
#include <QtCore/QtPlugin>
|
||||
|
||||
using namespace Tomahawk;
|
||||
using namespace Accounts;
|
||||
|
||||
QPixmap* s_icon = 0;
|
||||
|
||||
ZeroconfFactory::ZeroconfFactory()
|
||||
{
|
||||
#ifndef ENABLE_HEADLESS
|
||||
if ( s_icon == 0 )
|
||||
s_icon = new QPixmap( ":/zeroconf-icon.png" );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
ZeroconfFactory::~ZeroconfFactory()
|
||||
{
|
||||
if ( s_icon )
|
||||
{
|
||||
delete s_icon;
|
||||
s_icon = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Account*
|
||||
ZeroconfFactory::createAccount( const QString& pluginId )
|
||||
{
|
||||
return new ZeroconfAccount( pluginId.isEmpty() ? generateId( factoryId() ) : pluginId );
|
||||
}
|
||||
|
||||
QPixmap
|
||||
ZeroconfFactory::icon() const
|
||||
{
|
||||
return *s_icon;
|
||||
}
|
||||
|
||||
|
||||
ZeroconfAccount::ZeroconfAccount( const QString& accountId )
|
||||
: Account( accountId )
|
||||
{
|
||||
setAccountServiceName( "Local Network" );
|
||||
setAccountFriendlyName( "Local Network" );
|
||||
|
||||
setTypes( SipType );
|
||||
}
|
||||
|
||||
ZeroconfAccount::~ZeroconfAccount()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QPixmap
|
||||
ZeroconfAccount::icon() const
|
||||
{
|
||||
return *s_icon;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ZeroconfAccount::authenticate()
|
||||
{
|
||||
if ( !isAuthenticated() )
|
||||
static_cast< ZeroconfPlugin* >( m_sipPlugin.data() )->connectPlugin();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ZeroconfAccount::deauthenticate()
|
||||
{
|
||||
if ( isAuthenticated() )
|
||||
static_cast< ZeroconfPlugin* >( m_sipPlugin.data() )->disconnectPlugin();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ZeroconfAccount::isAuthenticated() const
|
||||
{
|
||||
return connectionState() == Connected;
|
||||
}
|
||||
|
||||
|
||||
Account::ConnectionState
|
||||
ZeroconfAccount::connectionState() const
|
||||
{
|
||||
if ( m_sipPlugin.isNull() )
|
||||
return Disconnected;
|
||||
|
||||
// TODO can we get called before sipPlugin()?
|
||||
return static_cast< ZeroconfPlugin* >( m_sipPlugin.data() )->connectionState();
|
||||
}
|
||||
|
||||
|
||||
SipPlugin*
|
||||
ZeroconfAccount::sipPlugin()
|
||||
{
|
||||
if ( m_sipPlugin.isNull() )
|
||||
m_sipPlugin = QWeakPointer< SipPlugin >( new ZeroconfPlugin( this ) );
|
||||
|
||||
return m_sipPlugin.data();
|
||||
}
|
||||
|
||||
|
||||
Q_EXPORT_PLUGIN2( Tomahawk::Accounts::AccountFactory, Tomahawk::Accounts::ZeroconfFactory )
|
80
src/accounts/zeroconf/zeroconfaccount.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* === 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 ZEROCONF_ACCOUNTS_H
|
||||
#define ZEROCONF_ACCOUNTS_H
|
||||
|
||||
#include "accounts/Account.h"
|
||||
#include "../accountdllmacro.h"
|
||||
|
||||
class SipPlugin;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
class ACCOUNTDLLEXPORT ZeroconfFactory : public AccountFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_INTERFACES( Tomahawk::Accounts::AccountFactory )
|
||||
public:
|
||||
ZeroconfFactory();
|
||||
virtual ~ZeroconfFactory();
|
||||
|
||||
virtual QString factoryId() const { return "zeroconfaccount"; }
|
||||
virtual QString prettyName() const { return "Local Network"; }
|
||||
QString description() const { return tr( "Automatically connect to Tomahawks on the local network" ); }
|
||||
virtual bool isUnique() const { return true; }
|
||||
AccountTypes types() const { return AccountTypes( SipType ); };
|
||||
#ifndef ENABLE_HEADLESS
|
||||
virtual QPixmap icon() const;
|
||||
#endif
|
||||
|
||||
|
||||
virtual Account* createAccount ( const QString& pluginId = QString() );
|
||||
};
|
||||
|
||||
class ACCOUNTDLLEXPORT ZeroconfAccount : public Account
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ZeroconfAccount( const QString &accountId );
|
||||
virtual ~ZeroconfAccount();
|
||||
|
||||
QPixmap icon() const;
|
||||
|
||||
void authenticate();
|
||||
void deauthenticate();
|
||||
bool isAuthenticated() const;
|
||||
ConnectionState connectionState() const;
|
||||
|
||||
Tomahawk::InfoSystem::InfoPlugin* infoPlugin() { return 0; }
|
||||
SipPlugin* sipPlugin();
|
||||
|
||||
QWidget* configurationWidget() { return 0; }
|
||||
QWidget* aclWidget() { return 0; }
|
||||
|
||||
private:
|
||||
QWeakPointer< SipPlugin > m_sipPlugin;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -20,6 +20,5 @@
|
||||
#cmakedefine LIBLASTFM_FOUND
|
||||
#cmakedefine GLOOX_FOUND
|
||||
#cmakedefine QCA2_FOUND
|
||||
#cmakedefine LIBATTICA_FOUND
|
||||
|
||||
#endif // CONFIG_H_IN
|
||||
|
@@ -1,120 +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"
|
||||
|
||||
ConfigDelegateBase::ConfigDelegateBase ( QObject* parent )
|
||||
: QStyledItemDelegate ( parent )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
QSize
|
||||
ConfigDelegateBase::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
|
||||
{
|
||||
int width = QStyledItemDelegate::sizeHint( option, index ).width();
|
||||
|
||||
QStyleOptionViewItemV4 opt = option;
|
||||
initStyleOption( &opt, index );
|
||||
|
||||
|
||||
QFont name = opt.font;
|
||||
name.setPointSize( name.pointSize() + 2 );
|
||||
name.setBold( true );
|
||||
|
||||
QFont path = opt.font;
|
||||
path.setItalic( true );
|
||||
path.setPointSize( path.pointSize() - 1 );
|
||||
|
||||
|
||||
QFontMetrics bfm( name );
|
||||
QFontMetrics sfm( path );
|
||||
return QSize( width, 2 * PADDING + bfm.height() + sfm.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 );
|
||||
if( me->button() != Qt::LeftButton || !checkRectForIndex( option, index ).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( Qt::CheckStateRole ).toInt() );
|
||||
Qt::CheckState newState = curState == Qt::Checked ? Qt::Unchecked : Qt::Checked;
|
||||
return model->setData( index, newState, Qt::CheckStateRole );
|
||||
|
||||
} 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 );
|
||||
}
|
@@ -36,16 +36,15 @@ public:
|
||||
virtual bool editorEvent ( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
|
||||
|
||||
// if you want to use a checkbox, you need to have this say where to paint it
|
||||
virtual QRect checkRectForIndex( const QStyleOptionViewItem& option, const QModelIndex& idx ) const = 0;
|
||||
virtual QRect checkRectForIndex( const QStyleOptionViewItem& option, const QModelIndex& idx, int role ) const = 0;
|
||||
// if you want to use a config wrench, you need to have this say where to paint it
|
||||
virtual QRect configRectForIndex( const QStyleOptionViewItem& option, const QModelIndex& idx ) const = 0;
|
||||
|
||||
virtual QList<int> extraCheckRoles() const { return QList<int>(); }
|
||||
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;
|
||||
|
@@ -22,28 +22,28 @@
|
||||
#include <QDialogButtonBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QDebug>
|
||||
|
||||
class DelegateConfigWrapper : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DelegateConfigWrapper( QWidget* conf, const QString& title, QWidget* parent, Qt::WindowFlags flags = 0 ) : QDialog( parent, flags ), m_widget( conf )
|
||||
DelegateConfigWrapper( QWidget* conf, const QString& title, QWidget* parent, Qt::WindowFlags flags = 0 ) : QDialog( parent, flags ), m_widget( conf ), m_deleted( false )
|
||||
{
|
||||
m_widget->setWindowFlags( Qt::Sheet );
|
||||
#ifdef Q_WS_MAC
|
||||
m_widget->setVisible( true );
|
||||
#endif
|
||||
|
||||
setWindowTitle( title );
|
||||
QVBoxLayout* v = new QVBoxLayout( this );
|
||||
v->setContentsMargins( 0, 0, 0, 0 );
|
||||
v->addWidget( m_widget );
|
||||
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this );
|
||||
m_okButton = buttons->button( QDialogButtonBox::Ok );
|
||||
connect( buttons, SIGNAL( clicked( QAbstractButton*) ), this, SLOT( closed( QAbstractButton* ) ) );
|
||||
m_buttons = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this );
|
||||
m_okButton = m_buttons->button( QDialogButtonBox::Ok );
|
||||
connect( m_buttons, SIGNAL( clicked( QAbstractButton*) ), this, SLOT( closed( QAbstractButton* ) ) );
|
||||
connect( this, SIGNAL( rejected() ), this, SLOT( rejected() ) );
|
||||
v->addWidget( buttons );
|
||||
v->addWidget( m_buttons );
|
||||
|
||||
setLayout( v );
|
||||
|
||||
@@ -59,6 +59,17 @@ public:
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
~DelegateConfigWrapper() {}
|
||||
|
||||
void setShowDelete( bool del )
|
||||
{
|
||||
if ( del )
|
||||
m_deleteButton = m_buttons->addButton( tr( "Delete Account" ), QDialogButtonBox::DestructiveRole );
|
||||
}
|
||||
|
||||
bool deleted() const { return m_deleted; }
|
||||
|
||||
public slots:
|
||||
void toggleOkButton( bool dataError )
|
||||
{
|
||||
@@ -75,6 +86,12 @@ public slots:
|
||||
QDialogButtonBox* buttons = qobject_cast< QDialogButtonBox* >( sender() );
|
||||
if( buttons->standardButton( b ) == QDialogButtonBox::Ok )
|
||||
done( QDialog::Accepted );
|
||||
else if ( b == m_deleteButton )
|
||||
{
|
||||
m_deleted = true;
|
||||
emit closedWithDelete();
|
||||
reject();
|
||||
}
|
||||
else
|
||||
done( QDialog::Rejected );
|
||||
}
|
||||
@@ -97,9 +114,14 @@ public slots:
|
||||
show();
|
||||
}
|
||||
|
||||
signals:
|
||||
void closedWithDelete();
|
||||
|
||||
private:
|
||||
QDialogButtonBox* m_buttons;
|
||||
QWidget* m_widget;
|
||||
QPushButton* m_okButton;
|
||||
QPushButton *m_okButton, *m_deleteButton;
|
||||
bool m_deleted;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -90,81 +90,81 @@ void DiagnosticsDialog::updateLogView()
|
||||
log.append("\n\n");
|
||||
|
||||
|
||||
// Peers
|
||||
log.append("SIP PLUGINS:\n");
|
||||
QList< Tomahawk::source_ptr > sources = SourceList::instance()->sources( true );
|
||||
Q_FOREACH(SipPlugin *sip, SipHandler::instance()->allPlugins())
|
||||
{
|
||||
Q_ASSERT(sip);
|
||||
QString stateString;
|
||||
switch( sip->connectionState() )
|
||||
{
|
||||
case SipPlugin::Connecting:
|
||||
stateString = "Connecting";
|
||||
break;
|
||||
// Peers / Accounts, TODO
|
||||
log.append("ACCOUNTS:\n");
|
||||
// QList< Tomahawk::source_ptr > sources = SourceList::instance()->sources( true );
|
||||
// Q_FOREACH(SipPlugin *sip, SipHandler::instance()->allPlugins())
|
||||
// {
|
||||
// Q_ASSERT(sip);
|
||||
// QString stateString;
|
||||
// switch( sip->connectionState() )
|
||||
// {
|
||||
// case SipPlugin::Connecting:
|
||||
// stateString = "Connecting";
|
||||
// break;
|
||||
//
|
||||
// case SipPlugin::Connected:
|
||||
// stateString = "Connected";
|
||||
// break;
|
||||
//
|
||||
// case SipPlugin::Disconnected:
|
||||
// stateString = "Disconnected";
|
||||
// break;
|
||||
// case SipPlugin::Disconnecting:
|
||||
// stateString = "Disconnecting";
|
||||
// }
|
||||
// log.append(
|
||||
// QString(" %2 (%1): %3 (%4)\n")
|
||||
// .arg(sip->account()->accountServiceName())
|
||||
// .arg(sip->friendlyName())
|
||||
// .arg(sip->account()->accountFriendlyName())
|
||||
// .arg(stateString)
|
||||
// );
|
||||
|
||||
case SipPlugin::Connected:
|
||||
stateString = "Connected";
|
||||
break;
|
||||
|
||||
case SipPlugin::Disconnected:
|
||||
stateString = "Disconnected";
|
||||
break;
|
||||
case SipPlugin::Disconnecting:
|
||||
stateString = "Disconnecting";
|
||||
}
|
||||
log.append(
|
||||
QString(" %2 (%1): %3 (%4)\n")
|
||||
.arg(sip->name())
|
||||
.arg(sip->friendlyName())
|
||||
.arg(sip->accountName())
|
||||
.arg(stateString)
|
||||
);
|
||||
|
||||
Q_FOREACH( const QString &peerId, sip->peersOnline() )
|
||||
{
|
||||
/* enable this again, when we check the source has this peerId
|
||||
bool connected = false;
|
||||
Q_FOREACH( const Tomahawk::source_ptr &source, sources )
|
||||
{
|
||||
if( source->controlConnection() )
|
||||
{
|
||||
connected = true;
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
|
||||
QString versionString = SipHandler::instance()->versionString( peerId );
|
||||
SipInfo sipInfo = SipHandler::instance()->sipInfo( peerId );
|
||||
if( !sipInfo.isValid() )
|
||||
log.append(
|
||||
QString(" %1: %2 %3" /*"(%4)"*/ "\n")
|
||||
.arg( peerId )
|
||||
.arg( "sipinfo invalid" )
|
||||
.arg( versionString )
|
||||
// .arg( connected ? "connected" : "not connected")
|
||||
);
|
||||
else if( sipInfo.isVisible() )
|
||||
log.append(
|
||||
QString(" %1: %2:%3 %4" /*" (%5)"*/ "\n")
|
||||
.arg( peerId )
|
||||
.arg( sipInfo.host().hostName() )
|
||||
.arg( sipInfo.port() )
|
||||
.arg( versionString )
|
||||
// .arg( connected ? "connected" : "not connected")
|
||||
|
||||
);
|
||||
else
|
||||
log.append(
|
||||
QString(" %1: visible: false %2" /*" (%3)"*/ "\n")
|
||||
.arg( peerId )
|
||||
.arg( versionString )
|
||||
// .arg( connected ? "connected" : "not connected")
|
||||
|
||||
);
|
||||
}
|
||||
log.append("\n");
|
||||
}
|
||||
// Q_FOREACH( const QString &peerId, sip->peersOnline() )
|
||||
// {
|
||||
// /* enable this again, when we check the source has this peerId
|
||||
// bool connected = false;
|
||||
// Q_FOREACH( const Tomahawk::source_ptr &source, sources )
|
||||
// {
|
||||
// if( source->controlConnection() )
|
||||
// {
|
||||
// connected = true;
|
||||
// break;
|
||||
// }
|
||||
// }*/
|
||||
//
|
||||
// QString versionString = SipHandler::instance()->versionString( peerId );
|
||||
// SipInfo sipInfo = SipHandler::instance()->sipInfo( peerId );
|
||||
// if( !sipInfo.isValid() )
|
||||
// log.append(
|
||||
// QString(" %1: %2 %3" /*"(%4)"*/ "\n")
|
||||
// .arg( peerId )
|
||||
// .arg( "sipinfo invalid" )
|
||||
// .arg( versionString )
|
||||
// // .arg( connected ? "connected" : "not connected")
|
||||
// );
|
||||
// else if( sipInfo.isVisible() )
|
||||
// log.append(
|
||||
// QString(" %1: %2:%3 %4" /*" (%5)"*/ "\n")
|
||||
// .arg( peerId )
|
||||
// .arg( sipInfo.host().hostName() )
|
||||
// .arg( sipInfo.port() )
|
||||
// .arg( versionString )
|
||||
// // .arg( connected ? "connected" : "not connected")
|
||||
//
|
||||
// );
|
||||
// else
|
||||
// log.append(
|
||||
// QString(" %1: visible: false %2" /*" (%3)"*/ "\n")
|
||||
// .arg( peerId )
|
||||
// .arg( versionString )
|
||||
// // .arg( connected ? "connected" : "not connected")
|
||||
//
|
||||
// );
|
||||
// }
|
||||
// log.append("\n");
|
||||
// }
|
||||
|
||||
ui->logView->setPlainText(log);
|
||||
}
|
||||
|
@@ -32,6 +32,8 @@
|
||||
#include <QTimer>
|
||||
|
||||
#include "utils/logger.h"
|
||||
#include "accounts/ResolverAccount.h"
|
||||
#include "accounts/AccountManager.h"
|
||||
|
||||
using namespace Attica;
|
||||
|
||||
@@ -133,6 +135,20 @@ AtticaManager::resolvers() const
|
||||
}
|
||||
|
||||
|
||||
Content
|
||||
AtticaManager::resolverForId( const QString& id ) const
|
||||
{
|
||||
foreach ( const Attica::Content& c, m_resolvers )
|
||||
{
|
||||
if ( c.id() == id )
|
||||
return c;
|
||||
}
|
||||
|
||||
return Content();
|
||||
}
|
||||
|
||||
|
||||
|
||||
AtticaManager::ResolverState
|
||||
AtticaManager::resolverState ( const Content& resolver ) const
|
||||
{
|
||||
@@ -196,6 +212,38 @@ AtticaManager::userHasRated( const Content& c ) const
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AtticaManager::hasCustomAccountForAttica( const QString &id ) const
|
||||
{
|
||||
// Only last.fm at the moment contains a custom account
|
||||
if ( id == "lastfm" )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Tomahawk::Accounts::Account*
|
||||
AtticaManager::customAccountForAttica( const QString &id ) const
|
||||
{
|
||||
return m_customAccounts.value( id );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AtticaManager::registerCustomAccount( const QString &atticaId, Tomahawk::Accounts::Account *account )
|
||||
{
|
||||
m_customAccounts.insert( atticaId, account );
|
||||
}
|
||||
|
||||
|
||||
AtticaManager::Resolver
|
||||
AtticaManager::resolverData(const QString &atticaId) const
|
||||
{
|
||||
return m_resolverStates.value( atticaId );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AtticaManager::providerAdded( const Provider& provider )
|
||||
{
|
||||
@@ -218,6 +266,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();
|
||||
|
||||
@@ -236,6 +302,8 @@ AtticaManager::resolversList( BaseJob* j )
|
||||
}
|
||||
|
||||
syncServerData();
|
||||
|
||||
emit resolversLoaded( m_resolvers );
|
||||
}
|
||||
|
||||
|
||||
@@ -299,7 +367,7 @@ AtticaManager::syncServerData()
|
||||
|
||||
|
||||
void
|
||||
AtticaManager::installResolver( const Content& resolver, bool autoEnable )
|
||||
AtticaManager::installResolver( const Content& resolver, bool autoCreateAccount )
|
||||
{
|
||||
Q_ASSERT( !resolver.id().isNull() );
|
||||
|
||||
@@ -313,7 +381,7 @@ AtticaManager::installResolver( const Content& resolver, bool autoEnable )
|
||||
ItemJob< DownloadItem >* job = m_resolverProvider.downloadLink( resolver.id() );
|
||||
connect( job, SIGNAL( finished( Attica::BaseJob* ) ), this, SLOT( resolverDownloadFinished( Attica::BaseJob* ) ) );
|
||||
job->setProperty( "resolverId", resolver.id() );
|
||||
job->setProperty( "autoEnable", autoEnable );
|
||||
job->setProperty( "createAccount", autoCreateAccount );
|
||||
|
||||
job->start();
|
||||
}
|
||||
@@ -328,12 +396,11 @@ AtticaManager::upgradeResolver( const Content& resolver )
|
||||
if ( !m_resolverStates.contains( resolver.id() ) || m_resolverStates[ resolver.id() ].state != NeedsUpgrade )
|
||||
return;
|
||||
|
||||
const bool enabled = TomahawkSettings::instance()->enabledScriptResolvers().contains( m_resolverStates[ resolver.id() ].scriptPath );
|
||||
m_resolverStates[ resolver.id() ].state = Upgrading;
|
||||
emit resolverStateChanged( resolver.id() );
|
||||
|
||||
uninstallResolver( resolver );
|
||||
installResolver( resolver, enabled );
|
||||
installResolver( resolver, false );
|
||||
}
|
||||
|
||||
|
||||
@@ -350,7 +417,7 @@ AtticaManager::resolverDownloadFinished ( BaseJob* j )
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->get( QNetworkRequest( url ) );
|
||||
connect( reply, SIGNAL( finished() ), this, SLOT( payloadFetched() ) );
|
||||
reply->setProperty( "resolverId", job->property( "resolverId" ) );
|
||||
reply->setProperty( "autoEnable", job->property( "autoEnable" ) );
|
||||
reply->setProperty( "createAccount", job->property( "createAccount" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -386,10 +453,14 @@ AtticaManager::payloadFetched()
|
||||
// update with absolute, not relative, path
|
||||
m_resolverStates[ resolverId ].scriptPath = resolverPath;
|
||||
|
||||
const bool autoEnable = reply->property( "autoEnable" ).toBool();
|
||||
if ( reply->property( "createAccount" ).toBool() )
|
||||
{
|
||||
// Do the install / add to tomahawk
|
||||
Tomahawk::Accounts::Account* resolver = Tomahawk::Accounts::ResolverAccountFactory::createFromPath( resolverPath, true );
|
||||
Tomahawk::Accounts::AccountManager::instance()->addAccount( resolver );
|
||||
TomahawkSettings::instance()->addAccount( resolver->accountId() );
|
||||
}
|
||||
|
||||
// Do the install / add to tomahawk
|
||||
Tomahawk::Pipeline::instance()->addScriptResolver( resolverPath, autoEnable );
|
||||
m_resolverStates[ resolverId ].state = Installed;
|
||||
TomahawkSettingsGui::instanceGui()->setAtticaResolverStates( m_resolverStates );
|
||||
emit resolverInstalled( resolverId );
|
||||
@@ -475,6 +546,9 @@ AtticaManager::extractPayload( const QString& filename, const QString& resolverI
|
||||
void
|
||||
AtticaManager::uninstallResolver( const QString& pathToResolver )
|
||||
{
|
||||
// when is this used? find and fix
|
||||
Q_ASSERT(false);
|
||||
|
||||
// User manually removed a resolver not through attica dialog, simple remove
|
||||
QRegExp r( ".*([^/]*)/contents/code/main.js" );
|
||||
r.indexIn( pathToResolver );
|
||||
@@ -506,9 +580,21 @@ AtticaManager::uninstallResolver( const Content& resolver )
|
||||
|
||||
m_resolverStates[ resolver.id() ].state = Uninstalled;
|
||||
TomahawkSettingsGui::instanceGui()->setAtticaResolverState( resolver.id(), Uninstalled );
|
||||
|
||||
// remove account as well
|
||||
QList< Tomahawk::Accounts::Account* > accounts = Tomahawk::Accounts::AccountManager::instance()->accounts( Tomahawk::Accounts::ResolverType );
|
||||
foreach ( Tomahawk::Accounts::Account* account, accounts )
|
||||
{
|
||||
if ( Tomahawk::Accounts::AtticaResolverAccount* atticaAccount = qobject_cast< Tomahawk::Accounts::AtticaResolverAccount* >( account ) )
|
||||
{
|
||||
if ( atticaAccount->atticaId() == resolver.id() ) // this is the account we want to remove
|
||||
{
|
||||
Tomahawk::Accounts::AccountManager::instance()->removeAccount( atticaAccount );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Tomahawk::Pipeline::instance()->removeScriptResolver( pathFromId( resolver.id() ) );
|
||||
doResolverRemove( resolver.id() );
|
||||
}
|
||||
|
||||
|
@@ -26,12 +26,12 @@
|
||||
#include <QPixmap>
|
||||
|
||||
#include "dllmacro.h"
|
||||
#include "accounts/Account.h"
|
||||
|
||||
#ifdef LIBATTICA_FOUND
|
||||
#include <attica/provider.h>
|
||||
#include <attica/providermanager.h>
|
||||
#include <attica/content.h>
|
||||
#endif
|
||||
|
||||
|
||||
class DLLEXPORT AtticaManager : public QObject
|
||||
{
|
||||
@@ -71,18 +71,13 @@ public:
|
||||
}
|
||||
|
||||
explicit AtticaManager ( QObject* parent = 0 );
|
||||
#ifdef LIBATTICA_FOUND
|
||||
|
||||
virtual ~AtticaManager();
|
||||
#else
|
||||
virtual ~AtticaManager() {}
|
||||
#endif
|
||||
|
||||
#ifdef LIBATTICA_FOUND
|
||||
|
||||
bool resolversLoaded() const;
|
||||
|
||||
Attica::Content::List resolvers() const;
|
||||
Attica::Content resolverForId( const QString& id ) const;
|
||||
|
||||
ResolverState resolverState( const Attica::Content& resolver ) const;
|
||||
QPixmap iconForResolver( const Attica::Content& id ); // Looks up in icon cache
|
||||
|
||||
@@ -93,12 +88,22 @@ public:
|
||||
void uploadRating( const Attica::Content& c );
|
||||
bool userHasRated( const Attica::Content& c ) const;
|
||||
|
||||
/**
|
||||
If the resolver coming from libattica has a native custom c++ account
|
||||
as well. For example the last.fm account.
|
||||
*/
|
||||
bool hasCustomAccountForAttica( const QString& id ) const;
|
||||
Tomahawk::Accounts::Account* customAccountForAttica( const QString& id ) const;
|
||||
void registerCustomAccount( const QString& atticaId, Tomahawk::Accounts::Account* account );
|
||||
|
||||
AtticaManager::Resolver resolverData( const QString& atticaId ) const;
|
||||
|
||||
public slots:
|
||||
void installResolver( const Attica::Content& resolver, bool autoEnable = true );
|
||||
void installResolver( const Attica::Content& resolver, bool autoCreateAccount = true );
|
||||
void upgradeResolver( const Attica::Content& resolver );
|
||||
|
||||
signals:
|
||||
void resolversReloaded( const Attica::Content::List& resolvers );
|
||||
void resolversLoaded( const Attica::Content::List& resolvers );
|
||||
|
||||
void resolverStateChanged( const QString& resolverId );
|
||||
void resolverInstalled( const QString& resolverId );
|
||||
@@ -125,13 +130,25 @@ private:
|
||||
Attica::Provider m_resolverProvider;
|
||||
Attica::Content::List m_resolvers;
|
||||
StateHash m_resolverStates;
|
||||
#endif
|
||||
|
||||
QMap< QString, Tomahawk::Accounts::Account* > m_customAccounts;
|
||||
|
||||
static AtticaManager* s_instance;
|
||||
};
|
||||
|
||||
#ifdef LIBATTICA_FOUND
|
||||
class DLLEXPORT CustomAtticaAccount : public Tomahawk::Accounts::Account
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual ~CustomAtticaAccount() {}
|
||||
|
||||
virtual Attica::Content atticaContent() const = 0;
|
||||
|
||||
protected:
|
||||
// No, you can't.
|
||||
CustomAtticaAccount( const QString& id ) : Tomahawk::Accounts::Account( id ) {}
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE( Attica::Content );
|
||||
#endif
|
||||
|
||||
#endif // ATTICAMANAGER_H
|
||||
|
@@ -102,8 +102,6 @@ set( libGuiSources
|
||||
resolvers/scriptresolver.cpp
|
||||
resolvers/qtscriptresolver.cpp
|
||||
|
||||
sip/SipModel.cpp
|
||||
|
||||
utils/widgetdragfilter.cpp
|
||||
utils/xspfgenerator.cpp
|
||||
utils/jspfloader.cpp
|
||||
@@ -229,8 +227,6 @@ set( libGuiHeaders
|
||||
resolvers/scriptresolver.h
|
||||
resolvers/qtscriptresolver.h
|
||||
|
||||
sip/SipModel.h
|
||||
|
||||
utils/widgetdragfilter.h
|
||||
utils/xspfgenerator.h
|
||||
utils/jspfloader.h
|
||||
@@ -311,6 +307,14 @@ set( libSources
|
||||
|
||||
EchonestCatalogSynchronizer.cpp
|
||||
|
||||
accounts/AccountManager.cpp
|
||||
accounts/Account.cpp
|
||||
accounts/AccountModel.cpp
|
||||
accounts/AccountModelFilterProxy.cpp
|
||||
accounts/ResolverAccount.cpp
|
||||
accounts/LastFmAccount.cpp
|
||||
accounts/LastFmConfig.cpp
|
||||
|
||||
sip/SipPlugin.cpp
|
||||
sip/SipHandler.cpp
|
||||
sip/sipinfo.cpp
|
||||
@@ -445,9 +449,16 @@ set( libHeaders
|
||||
albumplaylistinterface.h
|
||||
playlist.h
|
||||
playlistplaylistinterface.h
|
||||
|
||||
viewpage.h
|
||||
|
||||
accounts/Account.h
|
||||
accounts/AccountManager.h
|
||||
accounts/AccountModel.h
|
||||
accounts/AccountModelFilterProxy.h
|
||||
accounts/ResolverAccount.h
|
||||
accounts/LastFmAccount.h
|
||||
accounts/LastFmConfig.h
|
||||
|
||||
EchonestCatalogSynchronizer.h
|
||||
|
||||
sip/SipPlugin.h
|
||||
@@ -548,6 +559,10 @@ set( libHeaders
|
||||
)
|
||||
|
||||
set( libHeaders_NoMOC
|
||||
viewpage.h
|
||||
|
||||
accounts/Account.h
|
||||
|
||||
infosystem/infoplugins/unix/imageconverter.h
|
||||
|
||||
taghandlers/tag.h
|
||||
@@ -575,6 +590,7 @@ set( libUI ${libUI}
|
||||
playlist/queueview.ui
|
||||
context/ContextWidget.ui
|
||||
infobar/infobar.ui
|
||||
accounts/LastFmConfig.ui
|
||||
)
|
||||
|
||||
include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/.. ..
|
||||
|
@@ -1,6 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 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
|
||||
@@ -24,6 +25,7 @@
|
||||
#include "dllmacro.h"
|
||||
#include "resolver.h"
|
||||
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
@@ -64,7 +66,7 @@ public slots:
|
||||
virtual void stop() = 0;
|
||||
|
||||
signals:
|
||||
void changed(); // if config widget was added/removed
|
||||
void changed(); // if config widget was added/removed, name changed, etc
|
||||
|
||||
protected:
|
||||
void setFilePath( const QString& path ) { m_filePath = path; }
|
||||
|
@@ -21,53 +21,8 @@
|
||||
#include <QDesktopServices>
|
||||
#include "settingsdialog.h"
|
||||
|
||||
// #include <QDir>
|
||||
//
|
||||
// #include "sip/SipHandler.h"
|
||||
// #include "playlistinterface.h"
|
||||
//
|
||||
// #include "utils/logger.h"
|
||||
// #include "utils/tomahawkutils.h"
|
||||
//
|
||||
// #include "database/databasecommand_updatesearchindex.h"
|
||||
// #include "database/database.h"
|
||||
|
||||
#define VERSION 5
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
inline QDataStream& operator<<(QDataStream& out, const AtticaManager::StateHash& states)
|
||||
{
|
||||
out << VERSION;
|
||||
out << (quint32)states.count();
|
||||
foreach( const QString& key, states.keys() )
|
||||
{
|
||||
AtticaManager::Resolver resolver = states[ key ];
|
||||
out << key << resolver.version << resolver.scriptPath << (qint32)resolver.state << resolver.userRating;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
inline QDataStream& operator>>(QDataStream& in, AtticaManager::StateHash& states)
|
||||
{
|
||||
quint32 count = 0, version = 0;
|
||||
in >> version;
|
||||
in >> count;
|
||||
for ( uint i = 0; i < count; i++ )
|
||||
{
|
||||
QString key, version, scriptPath;
|
||||
qint32 state, userRating;
|
||||
in >> key;
|
||||
in >> version;
|
||||
in >> scriptPath;
|
||||
in >> state;
|
||||
in >> userRating;
|
||||
states[ key ] = AtticaManager::Resolver( version, scriptPath, userRating, (AtticaManager::ResolverState)state );
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
TomahawkSettingsGui*
|
||||
TomahawkSettingsGui::instanceGui()
|
||||
{
|
||||
@@ -78,8 +33,6 @@ TomahawkSettingsGui::instanceGui()
|
||||
TomahawkSettingsGui::TomahawkSettingsGui( QObject* parent )
|
||||
: TomahawkSettings( parent )
|
||||
{
|
||||
qRegisterMetaType< AtticaManager::StateHash >( "AtticaManager::StateHash" );
|
||||
qRegisterMetaTypeStreamOperators<AtticaManager::StateHash>("AtticaManager::StateHash");
|
||||
}
|
||||
|
||||
|
||||
|
211
src/libtomahawk/accounts/Account.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Christian Muehlhaeuser <muesli@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 "Account.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
QString
|
||||
accountTypeToString( AccountType type )
|
||||
{
|
||||
switch ( type )
|
||||
{
|
||||
case SipType:
|
||||
return QObject::tr( "Friend Finders" );
|
||||
case ResolverType:
|
||||
return QObject::tr( "Music Finders" );
|
||||
case InfoType:
|
||||
case StatusPushType:
|
||||
return QObject::tr( "Status Updaters" );
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
Account::Account( const QString& accountId )
|
||||
: QObject()
|
||||
, m_enabled( false )
|
||||
, m_autoConnect( false )
|
||||
, m_accountId( accountId )
|
||||
{
|
||||
connect( this, SIGNAL( error( int, QString ) ), this, SLOT( onError( int,QString ) ) );
|
||||
connect( this, SIGNAL( connectionStateChanged( Tomahawk::Accounts::Account::ConnectionState ) ) , this, SLOT( onConnectionStateChanged( Tomahawk::Accounts::Account::ConnectionState ) ) );
|
||||
|
||||
loadFromConfig( accountId );
|
||||
}
|
||||
|
||||
|
||||
Account::~Account()
|
||||
{
|
||||
sync();
|
||||
}
|
||||
|
||||
|
||||
QWidget*
|
||||
Account::configurationWidget()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
QWidget*
|
||||
Account::aclWidget()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
QPixmap
|
||||
Account::icon() const
|
||||
{
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
void
|
||||
Account::authenticate()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Account::deauthenticate()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Account::isAuthenticated() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Account::onError( int errorCode, const QString& error )
|
||||
{
|
||||
Q_UNUSED( errorCode );
|
||||
|
||||
QMutexLocker locker( &m_mutex );
|
||||
m_cachedError = error;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Account::onConnectionStateChanged( Account::ConnectionState )
|
||||
{
|
||||
m_cachedError.clear();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Account::syncConfig()
|
||||
{
|
||||
TomahawkSettings* s = TomahawkSettings::instance();
|
||||
s->beginGroup( "accounts/" + m_accountId );
|
||||
s->setValue( "accountfriendlyname", m_accountFriendlyName );
|
||||
s->setValue( "enabled", m_enabled );
|
||||
s->setValue( "autoconnect", m_autoConnect );
|
||||
s->setValue( "credentials", m_credentials );
|
||||
s->setValue( "configuration", m_configuration );
|
||||
s->setValue( "acl", m_acl );
|
||||
s->setValue( "types", m_types );
|
||||
s->endGroup();
|
||||
s->sync();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Account::loadFromConfig( const QString& accountId )
|
||||
{
|
||||
m_accountId = accountId;
|
||||
TomahawkSettings* s = TomahawkSettings::instance();
|
||||
s->beginGroup( "accounts/" + m_accountId );
|
||||
m_accountFriendlyName = s->value( "accountfriendlyname", QString() ).toString();
|
||||
m_enabled = s->value( "enabled", false ).toBool();
|
||||
m_autoConnect = s->value( "autoconnect", false ).toBool();
|
||||
m_credentials = s->value( "credentials", QVariantHash() ).toHash();
|
||||
m_configuration = s->value( "configuration", QVariantHash() ).toHash();
|
||||
m_acl = s->value( "acl", QVariantMap() ).toMap();
|
||||
m_types = s->value( "types", QStringList() ).toStringList();
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Account::removeFromConfig()
|
||||
{
|
||||
TomahawkSettings* s = TomahawkSettings::instance();
|
||||
s->beginGroup( "accounts/" + m_accountId );
|
||||
s->remove( "accountfriendlyname" );
|
||||
s->remove( "enabled" );
|
||||
s->remove( "autoconnect" );
|
||||
s->remove( "credentials" );
|
||||
s->remove( "configuration" );
|
||||
s->remove( "acl" );
|
||||
s->remove( "types" );
|
||||
s->endGroup();
|
||||
s->remove( "accounts/" + m_accountId );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Account::setTypes( AccountTypes types )
|
||||
{
|
||||
QMutexLocker locker( &m_mutex );
|
||||
m_types = QStringList();
|
||||
if ( types & InfoType )
|
||||
m_types << "InfoType";
|
||||
if ( types & SipType )
|
||||
m_types << "SipType";
|
||||
if ( types & ResolverType )
|
||||
m_types << "ResolverType";
|
||||
if ( types & StatusPushType )
|
||||
m_types << "StatusPushType";
|
||||
syncConfig();
|
||||
}
|
||||
|
||||
|
||||
AccountTypes
|
||||
Account::types() const
|
||||
{
|
||||
QMutexLocker locker( &m_mutex );
|
||||
AccountTypes types;
|
||||
if ( m_types.contains( "InfoType" ) )
|
||||
types |= InfoType;
|
||||
if ( m_types.contains( "SipType" ) )
|
||||
types |= SipType;
|
||||
if ( m_types.contains( "ResolverType" ) )
|
||||
types |= ResolverType;
|
||||
if ( m_types.contains( "StatusPushType" ) )
|
||||
types |= StatusPushType;
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
193
src/libtomahawk/accounts/Account.h
Normal file
@@ -0,0 +1,193 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2011, Christian Muehlhaeuser <muesli@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 ACCOUNT_H
|
||||
#define ACCOUNT_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QVariantMap>
|
||||
#include <QtGui/QWidget>
|
||||
#include <QtGui/QIcon>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QUuid>
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "dllmacro.h"
|
||||
#include "tomahawksettings.h"
|
||||
|
||||
class SipPlugin;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
class InfoPlugin;
|
||||
}
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
enum AccountType
|
||||
{
|
||||
NoType = 0x00,
|
||||
|
||||
InfoType = 0x01,
|
||||
SipType = 0x02,
|
||||
ResolverType = 0x04,
|
||||
StatusPushType = 0x08
|
||||
};
|
||||
|
||||
DLLEXPORT QString accountTypeToString( AccountType type );
|
||||
|
||||
Q_DECLARE_FLAGS(AccountTypes, AccountType);
|
||||
|
||||
inline QString generateId( const QString &factoryId )
|
||||
{
|
||||
QString uniq = QUuid::createUuid().toString().mid( 1, 8 );
|
||||
return factoryId + "_" + uniq;
|
||||
}
|
||||
|
||||
class DLLEXPORT Account : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum AuthErrorCode { AuthError, ConnectionError };
|
||||
enum ConnectionState { Disconnected, Connecting, Connected, Disconnecting };
|
||||
|
||||
explicit Account( const QString &accountId );
|
||||
virtual ~Account();
|
||||
|
||||
QString accountServiceName() const { QMutexLocker locker( &m_mutex ); return m_accountServiceName; } // e.g. "Twitter", "Last.fm"
|
||||
QString accountFriendlyName() const { QMutexLocker locker( &m_mutex ); return m_accountFriendlyName; } // e.g. screen name on the service, JID, etc.
|
||||
bool enabled() const { QMutexLocker locker( &m_mutex ); return m_enabled; }
|
||||
bool autoConnect() const { QMutexLocker locker( &m_mutex ); return m_autoConnect; }
|
||||
QString accountId() const { QMutexLocker locker( &m_mutex ); return m_accountId; }
|
||||
|
||||
QVariantHash configuration() const { QMutexLocker locker( &m_mutex ); return m_configuration; }
|
||||
|
||||
/**
|
||||
* Configuration widgets can have a "dataError( bool )" signal to enable/disable the OK button in their wrapper dialogs.
|
||||
*/
|
||||
virtual QWidget* configurationWidget() = 0;
|
||||
virtual void saveConfig() {} // called when the widget has been edited. save values from config widget, call sync() to write to disk account generic settings
|
||||
|
||||
QVariantHash credentials() const { QMutexLocker locker( &m_mutex ); return m_credentials; }
|
||||
|
||||
QVariantMap acl() const { QMutexLocker locker( &m_mutex ); return m_acl; }
|
||||
virtual QWidget* aclWidget() = 0;
|
||||
|
||||
virtual QPixmap icon() const = 0;
|
||||
|
||||
virtual ConnectionState connectionState() const = 0;
|
||||
virtual bool isAuthenticated() const = 0;
|
||||
|
||||
virtual QString errorMessage() const { QMutexLocker locker( &m_mutex ); return m_cachedError; }
|
||||
|
||||
virtual Tomahawk::InfoSystem::InfoPlugin* infoPlugin() = 0;
|
||||
virtual SipPlugin* sipPlugin() = 0;
|
||||
|
||||
AccountTypes types() const;
|
||||
|
||||
void setAccountServiceName( const QString &serviceName ) { QMutexLocker locker( &m_mutex ); m_accountServiceName = serviceName; }
|
||||
void setAccountFriendlyName( const QString &friendlyName ) { QMutexLocker locker( &m_mutex ); m_accountFriendlyName = friendlyName; }
|
||||
void setEnabled( bool enabled ) { QMutexLocker locker( &m_mutex ); m_enabled = enabled; }
|
||||
void setAutoConnect( bool autoConnect ) { QMutexLocker locker( &m_mutex ); m_autoConnect = autoConnect; }
|
||||
void setAccountId( const QString &accountId ) { QMutexLocker locker( &m_mutex ); m_accountId = accountId; }
|
||||
void setCredentials( const QVariantHash &credentialHash ) { QMutexLocker locker( &m_mutex ); m_credentials = credentialHash; }
|
||||
void setConfiguration( const QVariantHash &configuration ) { QMutexLocker locker( &m_mutex ); m_configuration = configuration; }
|
||||
void setAcl( const QVariantMap &acl ) { QMutexLocker locker( &m_mutex ); m_acl = acl; }
|
||||
void setTypes( AccountTypes types );
|
||||
|
||||
void sync() { QMutexLocker locker( &m_mutex ); syncConfig(); };
|
||||
|
||||
/**
|
||||
* Removes all the settings held in the config file for this account instance
|
||||
*
|
||||
* Re-implement if you have saved additional files or config settings outside the built-in ones
|
||||
*/
|
||||
virtual void removeFromConfig();
|
||||
|
||||
public slots:
|
||||
virtual void authenticate() = 0;
|
||||
virtual void deauthenticate() = 0;
|
||||
|
||||
signals:
|
||||
void error( int errorId, const QString& errorStr );
|
||||
void connectionStateChanged( Tomahawk::Accounts::Account::ConnectionState state );
|
||||
|
||||
void configurationChanged();
|
||||
|
||||
protected:
|
||||
virtual void loadFromConfig( const QString &accountId );
|
||||
virtual void syncConfig();
|
||||
|
||||
private slots:
|
||||
void onConnectionStateChanged( Tomahawk::Accounts::Account::ConnectionState );
|
||||
void onError( int, const QString& );
|
||||
|
||||
private:
|
||||
QString m_accountServiceName;
|
||||
QString m_accountFriendlyName;
|
||||
QString m_cachedError;
|
||||
bool m_enabled;
|
||||
bool m_autoConnect;
|
||||
QString m_accountId;
|
||||
QVariantHash m_credentials;
|
||||
QVariantHash m_configuration;
|
||||
QVariantMap m_acl;
|
||||
QStringList m_types;
|
||||
mutable QMutex m_mutex;
|
||||
};
|
||||
|
||||
class DLLEXPORT AccountFactory : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AccountFactory() {}
|
||||
virtual ~AccountFactory() {}
|
||||
|
||||
// display name for plugin
|
||||
virtual QString prettyName() const = 0;
|
||||
// internal name
|
||||
virtual QString factoryId() const = 0;
|
||||
// description to be shown when user views a list of account types
|
||||
virtual QString description() const = 0;
|
||||
// if the user can create multiple
|
||||
virtual bool isUnique() const { return false; }
|
||||
|
||||
virtual QPixmap icon() const { return QPixmap(); }
|
||||
virtual bool allowUserCreation() const { return true; }
|
||||
|
||||
// What are the supported types for accounts this factory creates?
|
||||
virtual AccountTypes types() const = 0;
|
||||
|
||||
virtual Account* createAccount( const QString& accountId = QString() ) = 0;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
Q_DECLARE_INTERFACE( Tomahawk::Accounts::AccountFactory, "tomahawk.AccountFactory/1.0" )
|
||||
|
||||
Q_DECLARE_METATYPE( QList< Tomahawk::Accounts::Account* > )
|
||||
Q_DECLARE_METATYPE( Tomahawk::Accounts::AccountTypes )
|
||||
#endif
|
410
src/libtomahawk/accounts/AccountManager.cpp
Normal file
@@ -0,0 +1,410 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* 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 "AccountManager.h"
|
||||
#include "config.h"
|
||||
#include "sourcelist.h"
|
||||
#include "ResolverAccount.h"
|
||||
#include "LastFmAccount.h"
|
||||
|
||||
#include <QtCore/QLibrary>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QPluginLoader>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QTimer>
|
||||
#include <sip/SipHandler.h>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
|
||||
AccountManager* AccountManager::s_instance = 0;
|
||||
|
||||
|
||||
AccountManager*
|
||||
AccountManager::instance()
|
||||
{
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
|
||||
AccountManager::AccountManager( QObject *parent )
|
||||
: QObject( parent )
|
||||
{
|
||||
s_instance = this;
|
||||
|
||||
connect( TomahawkSettings::instance(), SIGNAL( changed() ), SLOT( onSettingsChanged() ) );
|
||||
|
||||
loadPluginFactories( findPluginFactories() );
|
||||
|
||||
// We include the resolver factory manually, not in a plugin
|
||||
ResolverAccountFactory* f = new ResolverAccountFactory();
|
||||
m_accountFactories[ f->factoryId() ] = f;
|
||||
|
||||
LastFmAccountFactory* l = new LastFmAccountFactory();
|
||||
m_accountFactories[ l->factoryId() ] = l;
|
||||
}
|
||||
|
||||
|
||||
AccountManager::~AccountManager()
|
||||
{
|
||||
delete SipHandler::instance();
|
||||
|
||||
disconnectAll();
|
||||
qDeleteAll( m_accounts );
|
||||
}
|
||||
|
||||
|
||||
QStringList
|
||||
AccountManager::findPluginFactories()
|
||||
{
|
||||
QStringList paths;
|
||||
QList< QDir > pluginDirs;
|
||||
|
||||
QDir appDir( qApp->applicationDirPath() );
|
||||
#ifdef Q_WS_MAC
|
||||
if ( appDir.dirName() == "MacOS" )
|
||||
{
|
||||
// Development convenience-hack
|
||||
appDir.cdUp();
|
||||
appDir.cdUp();
|
||||
appDir.cdUp();
|
||||
}
|
||||
#endif
|
||||
|
||||
QDir libDir( CMAKE_INSTALL_PREFIX "/lib" );
|
||||
|
||||
QDir lib64Dir( appDir );
|
||||
lib64Dir.cdUp();
|
||||
lib64Dir.cd( "lib64" );
|
||||
|
||||
pluginDirs << appDir << libDir << lib64Dir << QDir( qApp->applicationDirPath() );
|
||||
foreach ( const QDir& pluginDir, pluginDirs )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << "Checking directory for plugins:" << pluginDir;
|
||||
foreach ( QString fileName, pluginDir.entryList( QStringList() << "*tomahawk_account_*.so" << "*tomahawk_account_*.dylib" << "*tomahawk_account_*.dll", QDir::Files ) )
|
||||
{
|
||||
if ( fileName.startsWith( "libtomahawk_account" ) )
|
||||
{
|
||||
const QString path = pluginDir.absoluteFilePath( fileName );
|
||||
if ( !paths.contains( path ) )
|
||||
paths << path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountManager::loadPluginFactories( const QStringList& paths )
|
||||
{
|
||||
foreach ( QString fileName, paths )
|
||||
{
|
||||
if ( !QLibrary::isLibrary( fileName ) )
|
||||
continue;
|
||||
|
||||
tDebug() << Q_FUNC_INFO << "Trying to load plugin:" << fileName;
|
||||
loadPluginFactory( fileName );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AccountManager::hasPluginWithFactory( const QString& factory ) const
|
||||
{
|
||||
foreach( Account* account, m_accounts ) {
|
||||
if( factoryFromId( account->accountId() ) == factory )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
AccountManager::factoryFromId( const QString& accountId ) const
|
||||
{
|
||||
return accountId.split( "_" ).first();
|
||||
}
|
||||
|
||||
AccountFactory*
|
||||
AccountManager::factoryForAccount( Account* account ) const
|
||||
{
|
||||
const QString factoryId = factoryFromId( account->accountId() );
|
||||
return m_accountFactories.value( factoryId, 0 );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountManager::loadPluginFactory( const QString& path )
|
||||
{
|
||||
QPluginLoader loader( path );
|
||||
QObject* plugin = loader.instance();
|
||||
if ( !plugin )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << "Error loading plugin:" << loader.errorString();
|
||||
}
|
||||
|
||||
AccountFactory* accountfactory = qobject_cast<AccountFactory*>( plugin );
|
||||
if ( accountfactory )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << "Loaded plugin factory:" << loader.fileName() << accountfactory->factoryId() << accountfactory->prettyName();
|
||||
m_accountFactories[ accountfactory->factoryId() ] = accountfactory;
|
||||
} else
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << "Loaded invalid plugin.." << loader.fileName();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
AccountManager::enableAccount( Account* account )
|
||||
{
|
||||
if ( account->isAuthenticated() )
|
||||
return;
|
||||
|
||||
account->authenticate();
|
||||
|
||||
account->setEnabled( true );
|
||||
m_enabledAccounts << account;
|
||||
|
||||
account->sync();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountManager::disableAccount( Account* account )
|
||||
{
|
||||
if ( !account->isAuthenticated() )
|
||||
return;
|
||||
|
||||
account->deauthenticate();
|
||||
account->setEnabled( false );
|
||||
m_enabledAccounts.removeAll( account );
|
||||
|
||||
account->sync();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountManager::connectAll()
|
||||
{
|
||||
foreach( Account* acc, m_accounts )
|
||||
{
|
||||
acc->authenticate();
|
||||
m_enabledAccounts << acc;
|
||||
|
||||
}
|
||||
m_connected = true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountManager::disconnectAll()
|
||||
{
|
||||
foreach( Account* acc, m_enabledAccounts )
|
||||
acc->deauthenticate();
|
||||
|
||||
m_enabledAccounts.clear();
|
||||
SourceList::instance()->removeAllRemote();
|
||||
m_connected = false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountManager::toggleAccountsConnected()
|
||||
{
|
||||
if ( m_connected )
|
||||
disconnectAll();
|
||||
else
|
||||
connectAll();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountManager::loadFromConfig()
|
||||
{
|
||||
QStringList accountIds = TomahawkSettings::instance()->accounts();
|
||||
|
||||
foreach( const QString& accountId, accountIds )
|
||||
{
|
||||
QString pluginFactory = factoryFromId( accountId );
|
||||
if( m_accountFactories.contains( pluginFactory ) )
|
||||
{
|
||||
Account* account = loadPlugin( accountId );
|
||||
addAccount( account );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AccountManager::initSIP()
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
foreach( Account* account, accounts() )
|
||||
{
|
||||
hookupAndEnable( account, true );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Account*
|
||||
AccountManager::loadPlugin( const QString& accountId )
|
||||
{
|
||||
QString factoryName = factoryFromId( accountId );
|
||||
|
||||
Q_ASSERT( m_accountFactories.contains( factoryName ) );
|
||||
|
||||
Account* account = m_accountFactories[ factoryName ]->createAccount( accountId );
|
||||
hookupAccount( account );
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountManager::addAccount( Account* account )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << "adding account plugin";
|
||||
m_accounts.append( account );
|
||||
|
||||
if ( account->types() & Accounts::SipType )
|
||||
m_accountsByAccountType[ Accounts::SipType ].append( account );
|
||||
if ( account->types() & Accounts::InfoType )
|
||||
m_accountsByAccountType[ Accounts::InfoType ].append( account );
|
||||
if ( account->types() & Accounts::ResolverType )
|
||||
m_accountsByAccountType[ Accounts::ResolverType ].append( account );
|
||||
if ( account->types() & Accounts::StatusPushType )
|
||||
m_accountsByAccountType[ Accounts::StatusPushType ].append( account );
|
||||
|
||||
if ( account->infoPlugin() )
|
||||
InfoSystem::InfoSystem::instance()->addInfoPlugin( account->infoPlugin() );
|
||||
|
||||
emit added( account );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountManager::removeAccount( Account* account )
|
||||
{
|
||||
account->deauthenticate();
|
||||
|
||||
// emit before moving from list so accountmodel can get indexOf
|
||||
emit removed( account );
|
||||
|
||||
m_accounts.removeAll( account );
|
||||
m_enabledAccounts.removeAll( account );
|
||||
m_connectedAccounts.removeAll( account );
|
||||
foreach ( AccountType type, m_accountsByAccountType.keys() )
|
||||
{
|
||||
QList< Account* > accounts = m_accountsByAccountType.value( type );
|
||||
accounts.removeAll( account );
|
||||
m_accountsByAccountType[ type ] = accounts;
|
||||
}
|
||||
|
||||
TomahawkSettings::instance()->removeAccount( account->accountId() );
|
||||
|
||||
account->removeFromConfig();
|
||||
account->deleteLater();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountManager::hookupAccount( Account* account ) const
|
||||
{
|
||||
connect( account, SIGNAL( error( int, QString ) ), SLOT( onError( int, QString ) ) );
|
||||
connect( account, SIGNAL( connectionStateChanged( Tomahawk::Accounts::Account::ConnectionState ) ), SLOT( onStateChanged( Tomahawk::Accounts::Account::ConnectionState ) ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountManager::hookupAndEnable( Account* account, bool startup )
|
||||
{
|
||||
SipPlugin* p = account->sipPlugin();
|
||||
if ( p )
|
||||
SipHandler::instance()->hookUpPlugin( p );
|
||||
|
||||
if ( account->enabled() && ( !startup || account->autoConnect() ) )
|
||||
{
|
||||
account->authenticate();
|
||||
m_enabledAccounts << account;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountManager::onError( int code, const QString& msg )
|
||||
{
|
||||
Account* account = qobject_cast< Account* >( sender() );
|
||||
Q_ASSERT( account );
|
||||
|
||||
|
||||
qWarning() << "Failed to connect to SIP:" << account->accountFriendlyName() << code << msg;
|
||||
|
||||
if ( code == Account::AuthError )
|
||||
{
|
||||
emit authError( account );
|
||||
}
|
||||
else
|
||||
{
|
||||
QTimer::singleShot( 10000, account, SLOT( authenticate() ) );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AccountManager::onSettingsChanged()
|
||||
{
|
||||
foreach( Account* account, m_accounts )
|
||||
{
|
||||
if ( account->types() & Accounts::SipType && account->sipPlugin() )
|
||||
account->sipPlugin()->checkSettings();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountManager::onStateChanged( Account::ConnectionState state )
|
||||
{
|
||||
Account* account = qobject_cast< Account* >( sender() );
|
||||
Q_ASSERT( account );
|
||||
|
||||
if ( account->connectionState() == Account::Disconnected )
|
||||
{
|
||||
m_connectedAccounts.removeAll( account );
|
||||
emit disconnected( account );
|
||||
}
|
||||
else if ( account->connectionState() == Account::Connected )
|
||||
{
|
||||
m_connectedAccounts << account;
|
||||
emit connected( account );
|
||||
}
|
||||
|
||||
emit stateChanged( account, state );
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
};
|
108
src/libtomahawk/accounts/AccountManager.h
Normal file
@@ -0,0 +1,108 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* 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 ACCOUNTMANAGER_H
|
||||
#define ACCOUNTMANAGER_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "dllmacro.h"
|
||||
#include "infosystem/infosystem.h"
|
||||
#include "sip/SipPlugin.h"
|
||||
#include "Account.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
|
||||
class DLLEXPORT AccountManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static AccountManager* instance();
|
||||
|
||||
explicit AccountManager( QObject *parent );
|
||||
virtual ~AccountManager();
|
||||
|
||||
void loadFromConfig();
|
||||
void initSIP();
|
||||
|
||||
void enableAccount( Account* account );
|
||||
void disableAccount( Account* account );
|
||||
|
||||
QList< AccountFactory* > factories() const { return m_accountFactories.values(); }
|
||||
bool hasPluginWithFactory( const QString& factory ) const;
|
||||
AccountFactory* factoryForAccount( Account* account ) const;
|
||||
|
||||
void addAccount( Account* account );
|
||||
void hookupAndEnable( Account* account, bool startup = false ); /// Hook up signals and start the plugin
|
||||
void removeAccount( Account* account );
|
||||
|
||||
QList< Account* > accounts() const { return m_accounts; };
|
||||
QList< Account* > accounts( Tomahawk::Accounts::AccountType type ) const { return m_accountsByAccountType[ type ]; }
|
||||
|
||||
public slots:
|
||||
void connectAll();
|
||||
void disconnectAll();
|
||||
void toggleAccountsConnected();
|
||||
|
||||
signals:
|
||||
void added( Tomahawk::Accounts::Account* );
|
||||
void removed( Tomahawk::Accounts::Account* );
|
||||
|
||||
void connected( Tomahawk::Accounts::Account* );
|
||||
void disconnected( Tomahawk::Accounts::Account* );
|
||||
void authError( Tomahawk::Accounts::Account* );
|
||||
|
||||
void stateChanged( Account* p, Accounts::Account::ConnectionState state );
|
||||
|
||||
private slots:
|
||||
void onStateChanged( Tomahawk::Accounts::Account::ConnectionState state );
|
||||
void onError( int code, const QString& msg );
|
||||
|
||||
void onSettingsChanged();
|
||||
private:
|
||||
QStringList findPluginFactories();
|
||||
void loadPluginFactories( const QStringList &paths );
|
||||
void loadPluginFactory( const QString &path );
|
||||
QString factoryFromId( const QString& accountId ) const;
|
||||
|
||||
Account* loadPlugin( const QString &accountId );
|
||||
void hookupAccount( Account* ) const;
|
||||
|
||||
QList< Account* > m_accounts;
|
||||
QList< Account* > m_enabledAccounts;
|
||||
QList< Account* > m_connectedAccounts;
|
||||
bool m_connected;
|
||||
|
||||
QHash< AccountType, QList< Account* > > m_accountsByAccountType;
|
||||
QHash< QString, AccountFactory* > m_accountFactories;
|
||||
|
||||
static AccountManager* s_instance;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
670
src/libtomahawk/accounts/AccountModel.cpp
Normal file
@@ -0,0 +1,670 @@
|
||||
/* === 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 "AccountModel.h"
|
||||
|
||||
#include "Account.h"
|
||||
#include "AccountModelNode.h"
|
||||
#include "AccountManager.h"
|
||||
#include "AtticaManager.h"
|
||||
#include "ResolverAccount.h"
|
||||
|
||||
#include <attica/content.h>
|
||||
|
||||
using namespace Tomahawk;
|
||||
using namespace Accounts;
|
||||
|
||||
AccountModel::AccountModel( QObject* parent )
|
||||
: QAbstractListModel( parent )
|
||||
{
|
||||
connect( AtticaManager::instance(), SIGNAL( resolversLoaded( Attica::Content::List ) ), this, SLOT( 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 ) ) );
|
||||
|
||||
loadData();
|
||||
}
|
||||
|
||||
void
|
||||
AccountModel::loadData()
|
||||
{
|
||||
beginResetModel();
|
||||
|
||||
qDeleteAll( m_accounts );
|
||||
m_accounts.clear();
|
||||
|
||||
// Add all factories
|
||||
QList< AccountFactory* > factories = AccountManager::instance()->factories();
|
||||
QList< Account* > allAccounts = AccountManager::instance()->accounts();
|
||||
foreach ( AccountFactory* fac, factories )
|
||||
{
|
||||
if ( !fac->allowUserCreation() )
|
||||
continue;
|
||||
|
||||
qDebug() << "Creating factory node:" << fac->prettyName();
|
||||
m_accounts << new AccountModelNode( fac );
|
||||
|
||||
// remove the accounts we are dealing with
|
||||
foreach ( Account* acct, allAccounts )
|
||||
{
|
||||
if ( AccountManager::instance()->factoryForAccount( acct ) == fac )
|
||||
allAccounts.removeAll( acct );
|
||||
}
|
||||
}
|
||||
|
||||
// add all attica resolvers (installed or uninstalled)
|
||||
Attica::Content::List fromAttica = AtticaManager::instance()->resolvers();
|
||||
foreach ( const Attica::Content& content, fromAttica )
|
||||
{
|
||||
qDebug() << "Loading ATTICA ACCOUNT with content:" << content.id() << content.name();
|
||||
if ( AtticaManager::instance()->hasCustomAccountForAttica( content.id() ) )
|
||||
{
|
||||
Account* acct = AtticaManager::instance()->customAccountForAttica( content.id() );
|
||||
Q_ASSERT( acct );
|
||||
if ( acct )
|
||||
{
|
||||
m_accounts << new AccountModelNode( acct );
|
||||
allAccounts.removeAll( acct );
|
||||
}
|
||||
} else
|
||||
{
|
||||
m_accounts << new AccountModelNode( content );
|
||||
|
||||
foreach ( Account* acct, AccountManager::instance()->accounts( Accounts::ResolverType ) )
|
||||
{
|
||||
if ( AtticaResolverAccount* resolver = qobject_cast< AtticaResolverAccount* >( acct ) )
|
||||
{
|
||||
if ( resolver->atticaId() == content.id() )
|
||||
{
|
||||
allAccounts.removeAll( acct );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// All other accounts we haven't dealt with yet
|
||||
foreach ( Account* acct, allAccounts )
|
||||
{
|
||||
Q_ASSERT( !qobject_cast< AtticaResolverAccount* >( acct ) ); // This should be caught above in the attica list
|
||||
|
||||
if ( qobject_cast< ResolverAccount* >( acct ) && !qobject_cast< AtticaResolverAccount* >( acct ) )
|
||||
m_accounts << new AccountModelNode( qobject_cast< ResolverAccount* >( acct ) );
|
||||
else
|
||||
m_accounts << new AccountModelNode( acct );
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
|
||||
QVariant
|
||||
AccountModel::data( const QModelIndex& index, int role ) const
|
||||
{
|
||||
if ( !index.isValid() )
|
||||
return QVariant();
|
||||
|
||||
if ( !hasIndex( index.row(), index.column(), index.parent() ) )
|
||||
return QVariant();
|
||||
|
||||
const AccountModelNode* node = m_accounts.at( index.row() );
|
||||
// This is a top-level item. 3 cases
|
||||
|
||||
switch ( node->type )
|
||||
{
|
||||
case AccountModelNode::FactoryType:
|
||||
{
|
||||
AccountFactory* fac = node->factory;
|
||||
Q_ASSERT( fac );
|
||||
|
||||
switch ( role )
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
return fac->prettyName();
|
||||
case Qt::DecorationRole:
|
||||
return fac->icon();
|
||||
case StateRole:
|
||||
return ShippedWithTomahawk;
|
||||
case Qt::ToolTipRole:
|
||||
case DescriptionRole:
|
||||
return fac->description();
|
||||
case CanRateRole:
|
||||
return false;
|
||||
case RowTypeRole:
|
||||
return TopLevelFactory;
|
||||
case AccountData:
|
||||
return QVariant::fromValue< QObject* >( node->factory );
|
||||
case ChildrenOfFactoryRole:
|
||||
return QVariant::fromValue< QList< Tomahawk::Accounts::Account* > >( node->accounts );
|
||||
case HasConfig:
|
||||
return !node->accounts.isEmpty();
|
||||
case AccountTypeRole:
|
||||
return QVariant::fromValue< AccountTypes >( node->factory->types() );
|
||||
case Qt::CheckStateRole:
|
||||
{
|
||||
if ( node->accounts.isEmpty() )
|
||||
return Qt::Unchecked;
|
||||
|
||||
// If all are checked or unchecked, return that
|
||||
bool someOn = false, someOff = false;
|
||||
foreach ( const Account* acct, node->accounts )
|
||||
{
|
||||
if ( acct->enabled() )
|
||||
someOn = true;
|
||||
else
|
||||
someOff = true;
|
||||
}
|
||||
if ( someOn && !someOff )
|
||||
return Qt::Checked;
|
||||
else if ( someOff & !someOn )
|
||||
return Qt::Unchecked;
|
||||
else
|
||||
return Qt::PartiallyChecked;
|
||||
}
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
case AccountModelNode::AtticaType:
|
||||
{
|
||||
Attica::Content c = node->atticaContent;
|
||||
Q_ASSERT( !c.id().isNull() );
|
||||
|
||||
switch( role )
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
return c.name();
|
||||
case Qt::DecorationRole:
|
||||
return QVariant::fromValue< QPixmap >( AtticaManager::instance()->iconForResolver( c ) );
|
||||
case StateRole:
|
||||
return (int)AtticaManager::instance()->resolverState( c );
|
||||
case Qt::ToolTipRole:
|
||||
case DescriptionRole:
|
||||
return c.description();
|
||||
case AuthorRole:
|
||||
return c.author();
|
||||
case RowTypeRole:
|
||||
return TopLevelAccount;
|
||||
case RatingRole:
|
||||
return c.rating() / 20; // rating is out of 100
|
||||
case DownloadCounterRole:
|
||||
return c.downloads();
|
||||
case CanRateRole:
|
||||
return true;
|
||||
case AccountTypeRole:
|
||||
return QVariant::fromValue< AccountTypes >( AccountTypes( ResolverType ) );
|
||||
case VersionRole:
|
||||
return c.version();
|
||||
case UserHasRatedRole:
|
||||
return AtticaManager::instance()->userHasRated( c );
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
AtticaResolverAccount* atticaAcct = node->atticaAccount;
|
||||
if ( atticaAcct )
|
||||
{
|
||||
// If the resolver is installed or on disk, we expose some additional data
|
||||
switch ( role )
|
||||
{
|
||||
case HasConfig:
|
||||
return atticaAcct->configurationWidget() != 0;
|
||||
case Qt::CheckStateRole:
|
||||
return atticaAcct->enabled() ? Qt::Checked : Qt::Unchecked;
|
||||
case AccountData:
|
||||
return QVariant::fromValue< QObject* >( atticaAcct );
|
||||
case ConnectionStateRole:
|
||||
return atticaAcct->connectionState();
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
case AccountModelNode::ManualResolverType:
|
||||
case AccountModelNode::UniqueFactoryType:
|
||||
{
|
||||
if ( role == RowTypeRole )
|
||||
{
|
||||
if ( node->type == AccountModelNode::ManualResolverType )
|
||||
return TopLevelAccount;
|
||||
else
|
||||
return UniqueFactory;
|
||||
}
|
||||
else if ( role == CanDeleteRole )
|
||||
{
|
||||
return node->type == AccountModelNode::ManualResolverType;
|
||||
}
|
||||
|
||||
Account* acct = 0;
|
||||
if ( node->type == AccountModelNode::ManualResolverType )
|
||||
acct = node->resolverAccount;
|
||||
else if ( node->type == AccountModelNode::UniqueFactoryType )
|
||||
acct = node->accounts.isEmpty() ? 0 : node->accounts.first();
|
||||
|
||||
// If there's no account*, then it means it's a unique factory that hasn't been created
|
||||
if ( !acct )
|
||||
{
|
||||
Q_ASSERT( node->type == AccountModelNode::UniqueFactoryType );
|
||||
Q_ASSERT( node->factory );
|
||||
|
||||
switch( role )
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
return node->factory->prettyName();
|
||||
case Qt::DecorationRole:
|
||||
return node->factory->icon();
|
||||
case Qt::ToolTipRole:
|
||||
case DescriptionRole:
|
||||
return node->factory->description();
|
||||
case StateRole:
|
||||
return Uninstalled;
|
||||
case CanRateRole:
|
||||
return false;
|
||||
case AccountTypeRole:
|
||||
return QVariant::fromValue< AccountTypes >( node->factory->types() );
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( role )
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
return acct->accountFriendlyName();
|
||||
case Qt::DecorationRole:
|
||||
return acct->icon();
|
||||
case DescriptionRole:
|
||||
return node->type == AccountModelNode::ManualResolverType ? QString() : node->factory->description();
|
||||
case Qt::CheckStateRole:
|
||||
return acct->enabled() ? Qt::Checked : Qt::Unchecked;
|
||||
case AccountData:
|
||||
return QVariant::fromValue< QObject* >( acct );
|
||||
case ConnectionStateRole:
|
||||
return acct->connectionState();
|
||||
case HasConfig:
|
||||
return acct->configurationWidget() != 0;
|
||||
case StateRole:
|
||||
return Installed;
|
||||
case ChildrenOfFactoryRole:
|
||||
return QVariant::fromValue< QList< Tomahawk::Accounts::Account* > >( node->accounts );
|
||||
case AccountTypeRole:
|
||||
return QVariant::fromValue< AccountTypes >( acct->types() );
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
case AccountModelNode::CustomAccountType:
|
||||
{
|
||||
Q_ASSERT( node->customAccount );
|
||||
Q_ASSERT( node->factory );
|
||||
|
||||
Account* account = node->customAccount;
|
||||
// This is sort of ugly. CustomAccounts are pure Account*, but we know that
|
||||
// some might also be linked to attica resolvers (not always). If that is the case
|
||||
// they have a Attica::Content set on the node, so we use that to display some
|
||||
// extra metadata and rating
|
||||
const bool hasAttica = !node->atticaContent.id().isEmpty();
|
||||
|
||||
switch ( role )
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
return account->accountFriendlyName();
|
||||
case Qt::DecorationRole:
|
||||
return account->icon();
|
||||
case StateRole:
|
||||
return ShippedWithTomahawk;
|
||||
case Qt::ToolTipRole:
|
||||
case DescriptionRole:
|
||||
return hasAttica ? node->atticaContent.description() : node->factory->description();
|
||||
case CanRateRole:
|
||||
return hasAttica;
|
||||
case AuthorRole:
|
||||
return hasAttica ? node->atticaContent.author() : QString();
|
||||
case RatingRole:
|
||||
return hasAttica ? node->atticaContent.rating() / 20 : 0; // rating is out of 100
|
||||
case DownloadCounterRole:
|
||||
return hasAttica ? node->atticaContent.downloads() : QVariant();
|
||||
case RowTypeRole:
|
||||
return CustomAccount;
|
||||
case AccountData:
|
||||
return QVariant::fromValue< QObject* >( account );
|
||||
case HasConfig:
|
||||
return account->configurationWidget() != 0;
|
||||
case AccountTypeRole:
|
||||
return QVariant::fromValue< AccountTypes >( account->types() );
|
||||
case Qt::CheckStateRole:
|
||||
return account->enabled() ? Qt::Checked : Qt::Unchecked;
|
||||
case ConnectionStateRole:
|
||||
return account->connectionState();
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 = m_accounts.at( index.row() );
|
||||
|
||||
if ( role == CheckboxClickedRole )
|
||||
{
|
||||
Account* acct = 0;
|
||||
switch ( node->type )
|
||||
{
|
||||
case AccountModelNode::UniqueFactoryType:
|
||||
{
|
||||
const Qt::CheckState state = static_cast< Qt::CheckState >( value.toInt() );
|
||||
if ( node->accounts.isEmpty() )
|
||||
{
|
||||
Q_ASSERT( state == Qt::Checked ); // How could we have a checked unique factory w/ no account??
|
||||
// No account for this unique factory, create it
|
||||
// Don't add it to node->accounts here, slot attached to accountmanager::accountcreated will do it for us
|
||||
acct = node->factory->createAccount();
|
||||
AccountManager::instance()->addAccount( acct );
|
||||
TomahawkSettings::instance()->addAccount( acct->accountId() );
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_ASSERT( node->accounts.size() == 1 );
|
||||
acct = node->accounts.first();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AccountModelNode::AtticaType:
|
||||
{
|
||||
// This may or may not be installed. if it's not installed yet, install it, then go ahead and enable it
|
||||
Q_ASSERT( node->atticaContent.isValid() );
|
||||
|
||||
Attica::Content resolver = node->atticaContent;
|
||||
AtticaManager::ResolverState state = AtticaManager::instance()->resolverState( resolver );
|
||||
qDebug() << "Attica resolver was checked! Current state is:" << state << "and so..";
|
||||
if ( state == AtticaManager::Installed && !node->atticaAccount )
|
||||
{
|
||||
// Something is wrong, reinstall
|
||||
qDebug() << "Found installed state but no resolver, uninstalling first";
|
||||
AtticaManager::instance()->uninstallResolver( resolver );
|
||||
state = AtticaManager::Uninstalled;
|
||||
}
|
||||
|
||||
if ( state == AtticaManager::Installed )
|
||||
{
|
||||
qDebug() << "Already installed with resolver, just enabling";
|
||||
acct = node->atticaAccount;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( m_waitingForAtticaInstall.contains( resolver.id() ) )
|
||||
{
|
||||
// in progress, ignore
|
||||
return true;
|
||||
}
|
||||
|
||||
qDebug() << "Kicked off fetch+install, now waiting";
|
||||
m_waitingForAtticaInstall.insert( resolver.id() );
|
||||
|
||||
AtticaManager::instance()->installResolver( resolver );
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
case AccountModelNode::ManualResolverType:
|
||||
acct = node->resolverAccount;
|
||||
break;
|
||||
case AccountModelNode::CustomAccountType:
|
||||
acct = node->customAccount;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
};
|
||||
|
||||
if ( node->type == AccountModelNode::FactoryType )
|
||||
{
|
||||
// Turn on or off all accounts for this factory
|
||||
|
||||
Qt::CheckState state = static_cast< Qt::CheckState >( value.toInt() );
|
||||
|
||||
foreach ( Account* acct, node->accounts )
|
||||
{
|
||||
state == Qt::Checked ? AccountManager::instance()->enableAccount( acct )
|
||||
: AccountManager::instance()->disableAccount( acct );
|
||||
}
|
||||
|
||||
emit dataChanged( index, index );
|
||||
return true;
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
emit dataChanged( index, index );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// The install/create/remove/etc button was clicked. Handle it properly depending on this item
|
||||
if ( role == CustomButtonRole )
|
||||
{
|
||||
if ( node->type == AccountModelNode::FactoryType )
|
||||
{
|
||||
// Make a new account of this factory type
|
||||
emit createAccount( node->factory );
|
||||
return true;
|
||||
}
|
||||
else if ( node->type == AccountModelNode::ManualResolverType )
|
||||
{
|
||||
Q_ASSERT( node->resolverAccount );
|
||||
AccountManager::instance()->removeAccount( node->resolverAccount );
|
||||
|
||||
return true;
|
||||
}
|
||||
Q_ASSERT( false ); // Should not be here, only the above two types should have this button
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
qDebug() << "IN ACCOUNT ADDED, new account:" << account->accountFriendlyName();
|
||||
AccountFactory* factory = AccountManager::instance()->factoryForAccount( account );
|
||||
AtticaResolverAccount* attica = qobject_cast< AtticaResolverAccount* >( account );
|
||||
for ( int i = 0; i < m_accounts.size(); i++ )
|
||||
{
|
||||
AccountModelNode* n = m_accounts.at( i );
|
||||
bool thisIsTheOne = false;
|
||||
qDebug() << "Checking for added account's related factory or attica:" << n->factory << attica;
|
||||
if ( attica )
|
||||
qDebug() << n->atticaContent.id() << n->atticaContent.name() << attica->atticaId();
|
||||
if ( n->factory == factory )
|
||||
{
|
||||
n->accounts << account;
|
||||
thisIsTheOne = true;
|
||||
}
|
||||
else if ( attica && n->atticaContent.id() == attica->atticaId() )
|
||||
{
|
||||
|
||||
n->atticaAccount = attica;
|
||||
n->atticaContent = AtticaManager::instance()->resolverForId( attica->atticaId() );
|
||||
thisIsTheOne = true;
|
||||
|
||||
if ( m_waitingForAtticaInstall.contains( attica->atticaId() ) )
|
||||
AccountManager::instance()->enableAccount( account );
|
||||
|
||||
m_waitingForAtticaInstall.remove( attica->atticaId() );
|
||||
}
|
||||
|
||||
if ( thisIsTheOne )
|
||||
{
|
||||
const QModelIndex idx = index( i, 0, QModelIndex() );
|
||||
dataChanged( idx, idx );
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Ok, just a plain resolver. add it at the end
|
||||
if ( ResolverAccount* resolver = qobject_cast< ResolverAccount* >( account ) )
|
||||
{
|
||||
Q_ASSERT( qobject_cast< AtticaResolverAccount* >( account ) == 0 ); // should NOT get attica accounts here, should be caught above
|
||||
const int count = m_accounts.size();
|
||||
beginInsertRows( QModelIndex(), count, count );
|
||||
m_accounts << new AccountModelNode( resolver );
|
||||
endInsertRows();
|
||||
|
||||
emit scrollTo( index( m_accounts.size() - 1, 0, QModelIndex() ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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_accounts.size(); i++ )
|
||||
{
|
||||
AccountModelNode* n = m_accounts.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->accounts.size() && n->accounts.first() == 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->accounts.size(); k++ )
|
||||
{
|
||||
Account* childAccount = n->accounts.at( k );
|
||||
|
||||
if ( childAccount == account )
|
||||
{
|
||||
const QModelIndex idx = index( i, 0, QModelIndex() );
|
||||
emit dataChanged( idx, idx );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountModel::accountRemoved( Account* account )
|
||||
{
|
||||
// Find the row this belongs to and update/remove
|
||||
AccountFactory* factory = AccountManager::instance()->factoryForAccount( account );
|
||||
qDebug() << "AccountModel got account removed:" << account->accountFriendlyName();
|
||||
for ( int i = 0; i < m_accounts.size(); i++ )
|
||||
{
|
||||
AccountModelNode* n = m_accounts.at( i );
|
||||
|
||||
bool found = false;
|
||||
// Account in a factory, remove child and update
|
||||
if ( ( n->type == AccountModelNode::FactoryType && n->factory == factory ) ||
|
||||
( n->type == AccountModelNode::UniqueFactoryType && n->accounts.size() && n->accounts.first() == account ) )
|
||||
{
|
||||
n->accounts.removeAll( account );
|
||||
found = true;
|
||||
}
|
||||
|
||||
// Attica account, just clear the account but leave the attica shell
|
||||
if ( n->type == AccountModelNode::AtticaType && n->atticaAccount && n->atticaAccount == account )
|
||||
{
|
||||
n->atticaAccount = 0;
|
||||
found = true;
|
||||
}
|
||||
|
||||
if ( found )
|
||||
{
|
||||
qDebug() << "Found account removed but we don't want to delete a row!" << i << n->type << n->factory;
|
||||
const QModelIndex idx = index( i, 0, QModelIndex() );
|
||||
emit dataChanged( idx, idx );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Manual resolver added, remove the row now
|
||||
if ( n->type == AccountModelNode::ManualResolverType && n->resolverAccount && n->resolverAccount == account )
|
||||
{
|
||||
qDebug() << "Found account removed AND REMOVING IT FROM THE LIST!" << n->factory << n->type << n->accounts << i;
|
||||
|
||||
beginRemoveRows( QModelIndex(), i, i );
|
||||
m_accounts.removeAt( i );
|
||||
endRemoveRows();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
AccountModel::rowCount( const QModelIndex& ) const
|
||||
{
|
||||
return m_accounts.size();
|
||||
}
|
||||
|
113
src/libtomahawk/accounts/AccountModel.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* === 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 TOMAHAWK_ACCOUNTS_ACCOUNTMODEL_H
|
||||
#define TOMAHAWK_ACCOUNTS_ACCOUNTMODEL_H
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
#include "Account.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
namespace Accounts {
|
||||
|
||||
class AccountModelNode;
|
||||
|
||||
class DLLEXPORT AccountModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum Roles {
|
||||
RowTypeRole = Qt::UserRole + 1, // RowType enum
|
||||
|
||||
// Used by top-level accounts
|
||||
DescriptionRole = Qt::UserRole + 17,
|
||||
StateRole = Qt::UserRole + 18, // ItemState,
|
||||
RatingRole = Qt::UserRole + 19,
|
||||
DownloadCounterRole = Qt::UserRole + 20,
|
||||
VersionRole = Qt::UserRole + 21,
|
||||
AuthorRole = Qt::UserRole + 22,
|
||||
UserHasRatedRole = Qt::UserRole + 24,
|
||||
|
||||
// used by both
|
||||
ConnectionStateRole = Qt::UserRole + 25,
|
||||
HasConfig = Qt::UserRole + 26,
|
||||
ErrorString = Qt::UserRole + 27,
|
||||
|
||||
// used by individual accounts
|
||||
AccountData = Qt::UserRole + 28, // raw plugin
|
||||
CanRateRole = Qt::UserRole + 32,
|
||||
AccountTypeRole = Qt::UserRole + 33,
|
||||
CanDeleteRole = Qt::UserRole + 34,
|
||||
|
||||
CheckboxClickedRole = Qt::UserRole + 29, // the checkbox for this row was toggled
|
||||
CustomButtonRole = Qt::UserRole + 30, // the add account or remove account button
|
||||
|
||||
// Used by factories
|
||||
ChildrenOfFactoryRole = Qt::UserRole + 31
|
||||
};
|
||||
|
||||
enum RowType {
|
||||
TopLevelFactory,
|
||||
TopLevelAccount,
|
||||
UniqueFactory,
|
||||
CustomAccount
|
||||
};
|
||||
|
||||
enum ItemState {
|
||||
Uninstalled = 0, // Attica resolver states
|
||||
Installing,
|
||||
Installed,
|
||||
NeedsUpgrade,
|
||||
Upgrading,
|
||||
Failed,
|
||||
ShippedWithTomahawk, // Built-in account/factory state: Can't uninstall or uninstall, just create
|
||||
};
|
||||
|
||||
explicit AccountModel( QObject* parent = 0 );
|
||||
|
||||
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 = Qt::EditRole);
|
||||
|
||||
signals:
|
||||
void createAccount( Tomahawk::Accounts::AccountFactory* factory );
|
||||
void scrollTo( const QModelIndex& idx );
|
||||
|
||||
private slots:
|
||||
void loadData();
|
||||
|
||||
void accountAdded( Tomahawk::Accounts::Account* );
|
||||
void accountRemoved( Tomahawk::Accounts::Account* );
|
||||
void accountStateChanged( Account*, Accounts::Account::ConnectionState );
|
||||
|
||||
private:
|
||||
QList< AccountModelNode* > m_accounts;
|
||||
QSet< QString > m_waitingForAtticaInstall;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // TOMAHAWK_ACCOUNTS_ACCOUNTMODEL_H
|
72
src/libtomahawk/accounts/AccountModelFilterProxy.cpp
Normal file
@@ -0,0 +1,72 @@
|
||||
/* === 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 "AccountModelFilterProxy.h"
|
||||
|
||||
#include "AccountModel.h"
|
||||
|
||||
|
||||
using namespace Tomahawk;
|
||||
using namespace Accounts;
|
||||
|
||||
AccountModelFilterProxy::AccountModelFilterProxy( QObject* parent )
|
||||
: QSortFilterProxyModel(parent)
|
||||
, m_filterType( NoType )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountModelFilterProxy::setSourceModel( QAbstractItemModel* sourceModel )
|
||||
{
|
||||
connect( sourceModel, SIGNAL( scrollTo( QModelIndex ) ), this, SLOT( onScrollTo( QModelIndex ) ) );
|
||||
QSortFilterProxyModel::setSourceModel( sourceModel );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AccountModelFilterProxy::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const
|
||||
{
|
||||
if ( m_filterType == NoType )
|
||||
return true;
|
||||
|
||||
const QModelIndex idx = sourceModel()->index( sourceRow, 0, sourceParent );
|
||||
const AccountTypes types = static_cast< AccountTypes >( idx.data( AccountModel::AccountTypeRole ).value< AccountTypes >() );
|
||||
|
||||
return types.testFlag( m_filterType );
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountModelFilterProxy::setFilterType( AccountType type )
|
||||
{
|
||||
if ( type == m_filterType )
|
||||
return;
|
||||
|
||||
m_filterType = type;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AccountModelFilterProxy::onScrollTo( const QModelIndex& idx )
|
||||
{
|
||||
emit scrollTo( mapFromSource( idx ) );
|
||||
}
|
56
src/libtomahawk/accounts/AccountModelFilterProxy.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2012, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 ACCOUNTMODELFILTERPROXY_H
|
||||
#define ACCOUNTMODELFILTERPROXY_H
|
||||
|
||||
#include "Account.h"
|
||||
#include "dllmacro.h"
|
||||
|
||||
#include <QSortFilterProxyModel>
|
||||
|
||||
namespace Tomahawk {
|
||||
namespace Accounts {
|
||||
|
||||
class DLLEXPORT AccountModelFilterProxy : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AccountModelFilterProxy( QObject* parent = 0 );
|
||||
|
||||
void setFilterType( Tomahawk::Accounts::AccountType type );
|
||||
|
||||
virtual void setSourceModel( QAbstractItemModel* sourceModel );
|
||||
|
||||
signals:
|
||||
void scrollTo( const QModelIndex& idx );
|
||||
|
||||
protected:
|
||||
virtual bool filterAcceptsRow ( int sourceRow, const QModelIndex& sourceParent ) const;
|
||||
|
||||
private slots:
|
||||
void onScrollTo( const QModelIndex& idx );
|
||||
|
||||
private:
|
||||
Tomahawk::Accounts::AccountType m_filterType;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif // ACCOUNTMODELFILTERPROXY_H
|
145
src/libtomahawk/accounts/AccountModelNode.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/* === 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 TOMAHAWK_ACCOUNTS_ACCOUNTMODELNODE_H
|
||||
#define TOMAHAWK_ACCOUNTS_ACCOUNTMODELNODE_H
|
||||
|
||||
#include "Account.h"
|
||||
#include "AccountManager.h"
|
||||
#include "ResolverAccount.h"
|
||||
#include "AtticaManager.h"
|
||||
|
||||
#include <attica/content.h>
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
namespace Accounts {
|
||||
|
||||
/**
|
||||
* Node for account tree.
|
||||
*
|
||||
* Basically a union with possible types:
|
||||
* 1) AccountFactory* for all factories that have child accounts. Also a list of children
|
||||
* 2) Attica::Content for AtticaResolverAccounts (with associated AtticaResolverAccount*) (all synchrotron resolvers)
|
||||
* 3) ResolverAccount* for manually added resolvers (from file).
|
||||
* 4) Account* for custom accounts. These may be hybrid infosystem/resolver/sip plugins or other special accounts
|
||||
*
|
||||
* These are the top-level items in tree.
|
||||
*
|
||||
* Top level nodes all look the same to the user. The only difference is that services that have login (and thus
|
||||
* can have multiple logins at once) allow a user to create multiple children with specific login information.
|
||||
* All other top level accounts (Account*, Attica::Content, ResolverAccount*) behave the same to the user, they can
|
||||
* simply toggle on/off.
|
||||
*
|
||||
*/
|
||||
|
||||
struct AccountModelNode {
|
||||
enum NodeType {
|
||||
FactoryType,
|
||||
UniqueFactoryType,
|
||||
AtticaType,
|
||||
ManualResolverType,
|
||||
CustomAccountType
|
||||
};
|
||||
AccountModelNode* parent;
|
||||
NodeType type;
|
||||
|
||||
/// 1, 4
|
||||
AccountFactory* factory;
|
||||
QList< Account* > accounts; // list of children accounts (actually existing and configured accounts)
|
||||
|
||||
/// 2.
|
||||
Attica::Content atticaContent;
|
||||
AtticaResolverAccount* atticaAccount;
|
||||
|
||||
/// 3.
|
||||
ResolverAccount* resolverAccount;
|
||||
|
||||
/// 4.
|
||||
Account* customAccount;
|
||||
|
||||
// Construct in one of four ways. Then access the corresponding members
|
||||
explicit AccountModelNode( AccountFactory* fac ) : type( FactoryType )
|
||||
{
|
||||
init();
|
||||
factory = fac;
|
||||
|
||||
if ( fac->isUnique() )
|
||||
type = UniqueFactoryType;
|
||||
|
||||
// Initialize factory nodes with their children
|
||||
foreach ( Account* acct, AccountManager::instance()->accounts() )
|
||||
{
|
||||
if ( AccountManager::instance()->factoryForAccount( acct ) == fac )
|
||||
{
|
||||
qDebug() << "Found account for factory:" << acct->accountFriendlyName();
|
||||
accounts.append( acct );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
explicit AccountModelNode( Attica::Content cnt ) : type( AtticaType )
|
||||
{
|
||||
init();
|
||||
atticaContent = cnt;
|
||||
|
||||
qDebug() << "Creating attica model node for resolver:" << cnt.id();
|
||||
|
||||
foreach ( Account* acct, AccountManager::instance()->accounts( Accounts::ResolverType ) )
|
||||
{
|
||||
if ( AtticaResolverAccount* resolver = qobject_cast< AtticaResolverAccount* >( acct ) )
|
||||
{
|
||||
if ( resolver->atticaId() == atticaContent.id() )
|
||||
{
|
||||
qDebug() << "found atticaaccount :" << resolver->accountFriendlyName();
|
||||
atticaAccount = resolver;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
explicit AccountModelNode( ResolverAccount* ra ) : type( ManualResolverType )
|
||||
{
|
||||
init();
|
||||
resolverAccount = ra;
|
||||
}
|
||||
|
||||
explicit AccountModelNode( Account* account ) : type( CustomAccountType )
|
||||
{
|
||||
init();
|
||||
customAccount = account;
|
||||
factory = AccountManager::instance()->factoryForAccount( account );
|
||||
|
||||
if ( CustomAtticaAccount* customAtticaAccount = qobject_cast< CustomAtticaAccount* >( account ) )
|
||||
atticaContent = customAtticaAccount->atticaContent();
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
factory = 0;
|
||||
atticaAccount = 0;
|
||||
resolverAccount = 0;
|
||||
customAccount = 0;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif // TOMAHAWK_ACCOUNTS_ACCOUNTMODELNODE_H
|
268
src/libtomahawk/accounts/LastFmAccount.cpp
Normal file
@@ -0,0 +1,268 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2012, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "LastFmAccount.h"
|
||||
#include "LastFmConfig.h"
|
||||
|
||||
#include "infosystem/infosystem.h"
|
||||
#include "infosystem/infoplugins/generic/lastfmplugin.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "resolvers/qtscriptresolver.h"
|
||||
#include "AtticaManager.h"
|
||||
#include "pipeline.h"
|
||||
#include "accounts/AccountManager.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
using namespace InfoSystem;
|
||||
using namespace Accounts;
|
||||
|
||||
LastFmAccountFactory::LastFmAccountFactory()
|
||||
{
|
||||
m_icon.load( RESPATH "images/lastfm-icon.png" );
|
||||
}
|
||||
|
||||
|
||||
Account*
|
||||
LastFmAccountFactory::createAccount( const QString& accountId )
|
||||
{
|
||||
return new LastFmAccount( accountId.isEmpty() ? generateId( factoryId() ) : accountId );
|
||||
}
|
||||
|
||||
|
||||
QPixmap
|
||||
LastFmAccountFactory::icon() const
|
||||
{
|
||||
return m_icon;
|
||||
}
|
||||
|
||||
|
||||
LastFmAccount::LastFmAccount( const QString& accountId )
|
||||
: CustomAtticaAccount( accountId )
|
||||
{
|
||||
m_infoPlugin = QWeakPointer< LastFmPlugin >( new LastFmPlugin( this ) );
|
||||
|
||||
setAccountFriendlyName( "Last.Fm" );
|
||||
m_icon.load( RESPATH "images/lastfm-icon.png" );
|
||||
|
||||
AtticaManager::instance()->registerCustomAccount( "lastfm", this );
|
||||
|
||||
connect( AtticaManager::instance(), SIGNAL( resolverInstalled( QString ) ), this, SLOT( resolverInstalled( QString ) ) );
|
||||
|
||||
const Attica::Content res = AtticaManager::instance()->resolverForId( "lastfm" );
|
||||
const AtticaManager::ResolverState state = AtticaManager::instance()->resolverState( res );
|
||||
|
||||
if ( state == AtticaManager::Installed )
|
||||
{
|
||||
hookupResolver();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LastFmAccount::~LastFmAccount()
|
||||
{
|
||||
delete m_infoPlugin.data();
|
||||
delete m_resolver.data();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmAccount::authenticate()
|
||||
{
|
||||
const Attica::Content res = AtticaManager::instance()->resolverForId( "lastfm" );
|
||||
const AtticaManager::ResolverState state = AtticaManager::instance()->resolverState( res );
|
||||
|
||||
qDebug() << "Last.FM account authenticating...";
|
||||
if ( m_resolver.isNull() && state == AtticaManager::Installed )
|
||||
{
|
||||
hookupResolver();
|
||||
}
|
||||
else if ( m_resolver.isNull() )
|
||||
{
|
||||
AtticaManager::instance()->installResolver( res, false );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_resolver.data()->start();
|
||||
}
|
||||
|
||||
emit connectionStateChanged( connectionState() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmAccount::deauthenticate()
|
||||
{
|
||||
if ( m_resolver.data()->running() )
|
||||
m_resolver.data()->stop();
|
||||
|
||||
emit connectionStateChanged( connectionState() );
|
||||
}
|
||||
|
||||
|
||||
QWidget*
|
||||
LastFmAccount::configurationWidget()
|
||||
{
|
||||
if ( m_configWidget.isNull() )
|
||||
m_configWidget = QWeakPointer<LastFmConfig>( new LastFmConfig( this ) );
|
||||
|
||||
return m_configWidget.data();
|
||||
}
|
||||
|
||||
|
||||
Account::ConnectionState
|
||||
LastFmAccount::connectionState() const
|
||||
{
|
||||
return (!m_resolver.isNull() && m_resolver.data()->running()) ? Account::Connected : Account::Disconnected;
|
||||
}
|
||||
|
||||
|
||||
QPixmap
|
||||
LastFmAccount::icon() const
|
||||
{
|
||||
return m_icon;
|
||||
}
|
||||
|
||||
|
||||
InfoPlugin*
|
||||
LastFmAccount::infoPlugin()
|
||||
{
|
||||
return m_infoPlugin.data();
|
||||
}
|
||||
|
||||
bool
|
||||
LastFmAccount::isAuthenticated() const
|
||||
{
|
||||
return !m_resolver.isNull() && m_resolver.data()->running();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmAccount::saveConfig()
|
||||
{
|
||||
if ( !m_configWidget.isNull() )
|
||||
{
|
||||
setUsername( m_configWidget.data()->username() );
|
||||
setPassword( m_configWidget.data()->password() );
|
||||
setScrobble( m_configWidget.data()->scrobble() );
|
||||
}
|
||||
|
||||
m_infoPlugin.data()->settingsChanged();
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
LastFmAccount::password() const
|
||||
{
|
||||
return credentials().value( "password" ).toString();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmAccount::setPassword( const QString& password )
|
||||
{
|
||||
QVariantHash creds = credentials();
|
||||
creds[ "password" ] = password;
|
||||
setCredentials( creds );
|
||||
}
|
||||
|
||||
QString
|
||||
LastFmAccount::sessionKey() const
|
||||
{
|
||||
return credentials().value( "sessionkey" ).toString();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmAccount::setSessionKey( const QString& sessionkey )
|
||||
{
|
||||
QVariantHash creds = credentials();
|
||||
creds[ "sessionkey" ] = sessionkey;
|
||||
setCredentials( creds );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
LastFmAccount::username() const
|
||||
{
|
||||
return credentials().value( "username" ).toString();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmAccount::setUsername( const QString& username )
|
||||
{
|
||||
QVariantHash creds = credentials();
|
||||
creds[ "username" ] = username;
|
||||
setCredentials( creds );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
LastFmAccount::scrobble() const
|
||||
{
|
||||
return configuration().value( "scrobble" ).toBool();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmAccount::setScrobble( bool scrobble )
|
||||
{
|
||||
QVariantHash conf;
|
||||
conf[ "scrobble" ] = scrobble;
|
||||
setConfiguration( conf );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmAccount::resolverInstalled( const QString &resolverId )
|
||||
{
|
||||
if ( resolverId == "lastfm" )
|
||||
{
|
||||
// We requested this install, so we want to launch it
|
||||
hookupResolver();
|
||||
AccountManager::instance()->enableAccount( this );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LastFmAccount::resolverChanged()
|
||||
{
|
||||
emit connectionStateChanged( connectionState() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmAccount::hookupResolver()
|
||||
{
|
||||
// If there is a last.fm resolver from attica installed, create the corresponding ExternalResolver* and hook up to it
|
||||
const Attica::Content res = AtticaManager::instance()->resolverForId( "lastfm" );
|
||||
const AtticaManager::ResolverState state = AtticaManager::instance()->resolverState( res );
|
||||
Q_ASSERT( state == AtticaManager::Installed );
|
||||
|
||||
const AtticaManager::Resolver data = AtticaManager::instance()->resolverData( res.id() );
|
||||
|
||||
m_resolver = QWeakPointer< ExternalResolverGui >( qobject_cast< ExternalResolverGui* >( Pipeline::instance()->addScriptResolver( data.scriptPath, enabled() ) ) );
|
||||
connect( m_resolver.data(), SIGNAL( changed() ), this, SLOT( resolverChanged() ) );
|
||||
}
|
||||
|
||||
|
||||
Attica::Content
|
||||
LastFmAccount::atticaContent() const
|
||||
{
|
||||
return AtticaManager::instance()->resolverForId( "lastfm" );
|
||||
}
|
113
src/libtomahawk/accounts/LastFmAccount.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2012, Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 LASTFMACCOUNT_H
|
||||
#define LASTFMACCOUNT_H
|
||||
|
||||
#include "accounts/Account.h"
|
||||
#include "AtticaManager.h"
|
||||
|
||||
#include <attica/content.h>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Tomahawk {
|
||||
class ExternalResolverGui;
|
||||
|
||||
namespace InfoSystem {
|
||||
class LastFmPlugin;
|
||||
}
|
||||
|
||||
namespace Accounts {
|
||||
|
||||
class LastFmConfig;
|
||||
|
||||
class LastFmAccountFactory : public AccountFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
LastFmAccountFactory();
|
||||
|
||||
virtual Account* createAccount(const QString& accountId = QString());
|
||||
virtual QString description() const { return tr( "Scrobble your tracks to last.fm, and find freely downloadable tracks to play" ); }
|
||||
virtual QString factoryId() const { return "lastfmaccount"; }
|
||||
virtual QString prettyName() const { return "Last.fm"; }
|
||||
virtual AccountTypes types() const { return AccountTypes( InfoType | StatusPushType ); }
|
||||
virtual bool allowUserCreation() const { return false; }
|
||||
virtual QPixmap icon() const;
|
||||
virtual bool isUnique() const { return true; }
|
||||
|
||||
private:
|
||||
QPixmap m_icon;
|
||||
};
|
||||
|
||||
/**
|
||||
* 3.Last.Fm account is special. It is both an attica resolver *and* a InfoPlugin. We always want the infoplugin,
|
||||
* but the user can install the attica resolver on-demand. So we take care of both there.
|
||||
*
|
||||
*/
|
||||
class LastFmAccount : public CustomAtticaAccount
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LastFmAccount( const QString& accountId );
|
||||
~LastFmAccount();
|
||||
|
||||
virtual void deauthenticate();
|
||||
virtual void authenticate();
|
||||
|
||||
virtual SipPlugin* sipPlugin() { return 0; }
|
||||
virtual Tomahawk::InfoSystem::InfoPlugin* infoPlugin();
|
||||
|
||||
virtual bool isAuthenticated() const;
|
||||
|
||||
virtual ConnectionState connectionState() const;
|
||||
virtual QPixmap icon() const;
|
||||
virtual QWidget* aclWidget() { return 0; }
|
||||
virtual QWidget* configurationWidget();
|
||||
virtual void saveConfig();
|
||||
|
||||
QString username() const;
|
||||
void setUsername( const QString& );
|
||||
QString password() const;
|
||||
void setPassword( const QString& );
|
||||
QString sessionKey() const;
|
||||
void setSessionKey( const QString& );
|
||||
bool scrobble() const;
|
||||
void setScrobble( bool scrobble );
|
||||
|
||||
Attica::Content atticaContent() const;
|
||||
|
||||
private slots:
|
||||
void resolverInstalled( const QString& resolverId );
|
||||
|
||||
void resolverChanged();
|
||||
private:
|
||||
void hookupResolver();
|
||||
|
||||
QWeakPointer<Tomahawk::ExternalResolverGui> m_resolver;
|
||||
QWeakPointer<Tomahawk::InfoSystem::LastFmPlugin> m_infoPlugin;
|
||||
QWeakPointer<LastFmConfig> m_configWidget;
|
||||
QPixmap m_icon;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // LASTFMACCOUNT_H
|
134
src/libtomahawk/accounts/LastFmConfig.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
/* === 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 "LastFmConfig.h"
|
||||
|
||||
#include "LastFmAccount.h"
|
||||
#include <utils/tomahawkutils.h>
|
||||
#include "ui_LastFmConfig.h"
|
||||
#include "lastfm/ws.h"
|
||||
#include "lastfm/XmlQuery"
|
||||
|
||||
using namespace Tomahawk::Accounts;
|
||||
|
||||
LastFmConfig::LastFmConfig( LastFmAccount* account )
|
||||
: QWidget( 0 )
|
||||
, m_account( account )
|
||||
{
|
||||
m_ui = new Ui_LastFmConfig;
|
||||
m_ui->setupUi( this );
|
||||
|
||||
m_ui->username->setText( m_account->username() );
|
||||
m_ui->password->setText( m_account->password() );
|
||||
m_ui->enable->setChecked( m_account->scrobble() );
|
||||
|
||||
connect( m_ui->testLogin, SIGNAL( clicked( bool ) ), this, SLOT( testLogin( bool ) ) );
|
||||
|
||||
// #ifdef Q_WS_MAC // FIXME
|
||||
// m_ui->testLogin->setVisible( false );
|
||||
// #endif
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
LastFmConfig::password() const
|
||||
{
|
||||
return m_ui->password->text();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
LastFmConfig::scrobble() const
|
||||
{
|
||||
return m_ui->enable->isChecked();
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
LastFmConfig::username() const
|
||||
{
|
||||
return m_ui->username->text().trimmed();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmConfig::testLogin(bool )
|
||||
{
|
||||
m_ui->testLogin->setEnabled( false );
|
||||
m_ui->testLogin->setText( "Testing..." );
|
||||
|
||||
QString authToken = TomahawkUtils::md5( ( m_ui->username->text().toLower() + TomahawkUtils::md5( m_ui->password->text().toUtf8() ) ).toUtf8() );
|
||||
|
||||
// now authenticate w/ last.fm and get our session key
|
||||
QMap<QString, QString> query;
|
||||
query[ "method" ] = "auth.getMobileSession";
|
||||
query[ "username" ] = m_ui->username->text().toLower();
|
||||
query[ "authToken" ] = authToken;
|
||||
|
||||
// ensure they have up-to-date settings
|
||||
lastfm::setNetworkAccessManager( TomahawkUtils::nam() );
|
||||
|
||||
QNetworkReply* authJob = lastfm::ws::post( query );
|
||||
|
||||
connect( authJob, SIGNAL( finished() ), SLOT( onLastFmFinished() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmConfig::onLastFmFinished()
|
||||
{
|
||||
QNetworkReply* authJob = dynamic_cast<QNetworkReply*>( sender() );
|
||||
if( !authJob )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "No auth job returned!";
|
||||
return;
|
||||
}
|
||||
if( authJob->error() == QNetworkReply::NoError )
|
||||
{
|
||||
lastfm::XmlQuery lfm = lastfm::XmlQuery( authJob->readAll() );
|
||||
|
||||
if( lfm.children( "error" ).size() > 0 )
|
||||
{
|
||||
qDebug() << "ERROR from last.fm:" << lfm.text();
|
||||
m_ui->testLogin->setText( tr( "Failed" ) );
|
||||
m_ui->testLogin->setEnabled( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui->testLogin->setText( tr( "Success" ) );
|
||||
m_ui->testLogin->setEnabled( false );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( authJob->error() )
|
||||
{
|
||||
case QNetworkReply::ContentOperationNotPermittedError:
|
||||
case QNetworkReply::AuthenticationRequiredError:
|
||||
m_ui->testLogin->setText( tr( "Failed" ) );
|
||||
m_ui->testLogin->setEnabled( true );
|
||||
break;
|
||||
|
||||
default:
|
||||
qDebug() << "Couldn't get last.fm auth result";
|
||||
m_ui->testLogin->setText( tr( "Could not contact server" ) );
|
||||
m_ui->testLogin->setEnabled( true );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
53
src/libtomahawk/accounts/LastFmConfig.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/* === 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 LASTFMCONFIG_H
|
||||
#define LASTFMCONFIG_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class Ui_LastFmConfig;
|
||||
|
||||
namespace Tomahawk {
|
||||
namespace Accounts {
|
||||
|
||||
class LastFmAccount;
|
||||
|
||||
class LastFmConfig : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LastFmConfig( LastFmAccount* account );
|
||||
|
||||
QString username() const;
|
||||
QString password() const;
|
||||
bool scrobble() const;
|
||||
|
||||
public slots:
|
||||
void testLogin( bool );
|
||||
void onLastFmFinished();
|
||||
|
||||
private:
|
||||
LastFmAccount* m_account;
|
||||
Ui_LastFmConfig* m_ui;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // LASTFMCONFIG_H
|
88
src/libtomahawk/accounts/LastFmConfig.ui
Normal file
@@ -0,0 +1,88 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LastFmConfig</class>
|
||||
<widget class="QWidget" name="LastFmConfig">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>220</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="margin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="../../../resources.qrc">:/data/images/lastfm-icon.png</pixmap>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="enable">
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Scrobble tracks to Last.fm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Username:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="username"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Password:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="password">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="testLogin">
|
||||
<property name="text">
|
||||
<string>Test Login</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../../resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
245
src/libtomahawk/accounts/ResolverAccount.cpp
Normal file
@@ -0,0 +1,245 @@
|
||||
/* === 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 "ResolverAccount.h"
|
||||
|
||||
#include "ExternalResolver.h"
|
||||
#include "ExternalResolverGui.h"
|
||||
#include "AccountManager.h"
|
||||
#include <pipeline.h>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
|
||||
using namespace Tomahawk;
|
||||
using namespace Accounts;
|
||||
|
||||
Account*
|
||||
ResolverAccountFactory::createAccount( const QString& accountId )
|
||||
{
|
||||
// Can't use this to create new accounts. Needs to be able to find account in config
|
||||
// to load proper resolver account type. Creation is done from AtticaManager when path is known
|
||||
Q_ASSERT( !accountId.isEmpty() );
|
||||
|
||||
// If it's an attica resolver, return it instead so we get an icon
|
||||
const bool isFromAttica = TomahawkSettings::instance()->value( QString( "accounts/%1/atticaresolver" ).arg( accountId ), false ).toBool();
|
||||
if ( isFromAttica )
|
||||
return new AtticaResolverAccount( accountId );
|
||||
else
|
||||
return new ResolverAccount( accountId );
|
||||
}
|
||||
|
||||
|
||||
Account*
|
||||
ResolverAccountFactory::createFromPath( const QString& path, bool isAttica )
|
||||
{
|
||||
if ( isAttica )
|
||||
{
|
||||
QFileInfo info( path );
|
||||
return new AtticaResolverAccount( generateId( "resolveraccount" ), path, info.baseName() );
|
||||
}
|
||||
else
|
||||
return new ResolverAccount( generateId( "resolveraccount" ), path );
|
||||
}
|
||||
|
||||
|
||||
ResolverAccount::ResolverAccount( const QString& accountId )
|
||||
: Account( accountId )
|
||||
{
|
||||
|
||||
const QString path = configuration()[ "path" ].toString();
|
||||
|
||||
// We should have a valid saved path
|
||||
Q_ASSERT( !path.isEmpty() );
|
||||
|
||||
m_resolver = QWeakPointer< ExternalResolverGui >( qobject_cast< ExternalResolverGui* >( Pipeline::instance()->addScriptResolver( path, enabled() ) ) );
|
||||
connect( m_resolver.data(), SIGNAL( changed() ), this, SLOT( resolverChanged() ) );
|
||||
|
||||
// What resolver do we have here? Should only be types that are 'real' resolvers
|
||||
Q_ASSERT ( !m_resolver.isNull() );
|
||||
|
||||
setAccountFriendlyName( m_resolver.data()->name() );
|
||||
setTypes( AccountType( ResolverType ) );
|
||||
}
|
||||
|
||||
|
||||
ResolverAccount::ResolverAccount( const QString& accountId, const QString& path )
|
||||
: Account( accountId )
|
||||
{
|
||||
QVariantHash configuration;
|
||||
configuration[ "path" ] = path;
|
||||
setConfiguration( configuration );
|
||||
setEnabled( true );
|
||||
|
||||
m_resolver = QWeakPointer< ExternalResolverGui >( qobject_cast< ExternalResolverGui* >( Pipeline::instance()->addScriptResolver( path, true ) ) );
|
||||
connect( m_resolver.data(), SIGNAL( changed() ), this, SLOT( resolverChanged() ) );
|
||||
|
||||
// What resolver do we have here? Should only be types that are 'real' resolvers
|
||||
Q_ASSERT ( m_resolver.data() );
|
||||
|
||||
setAccountFriendlyName( m_resolver.data()->name() );
|
||||
setTypes( AccountType( ResolverType ) );
|
||||
}
|
||||
|
||||
|
||||
ResolverAccount::~ResolverAccount()
|
||||
{
|
||||
if ( m_resolver.isNull() )
|
||||
return;
|
||||
|
||||
Pipeline::instance()->removeScriptResolver( m_resolver.data()->filePath() );
|
||||
delete m_resolver.data();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
ResolverAccount::authenticate()
|
||||
{
|
||||
Q_ASSERT( !m_resolver.isNull() );
|
||||
qDebug() << Q_FUNC_INFO << "Authenticating/starting resolver, exists?" << m_resolver;
|
||||
|
||||
if ( !m_resolver.data()->running() )
|
||||
m_resolver.data()->start();
|
||||
|
||||
emit connectionStateChanged( connectionState() );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ResolverAccount::isAuthenticated() const
|
||||
{
|
||||
return m_resolver.data()->running();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ResolverAccount::deauthenticate()
|
||||
{
|
||||
if ( m_resolver.data()->running() )
|
||||
m_resolver.data()->stop();
|
||||
|
||||
emit connectionStateChanged( connectionState() );
|
||||
|
||||
}
|
||||
|
||||
|
||||
Account::ConnectionState
|
||||
ResolverAccount::connectionState() const
|
||||
{
|
||||
if ( m_resolver.data()->running() )
|
||||
return Connected;
|
||||
else
|
||||
return Disconnected;
|
||||
}
|
||||
|
||||
|
||||
QWidget*
|
||||
ResolverAccount::configurationWidget()
|
||||
{
|
||||
return m_resolver.data()->configUI();
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
ResolverAccount::errorMessage() const
|
||||
{
|
||||
// TODO
|
||||
// return m_resolver->error();
|
||||
return QString();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ResolverAccount::removeFromConfig()
|
||||
{
|
||||
// TODO
|
||||
Account::removeFromConfig();
|
||||
}
|
||||
|
||||
|
||||
void ResolverAccount::saveConfig()
|
||||
{
|
||||
Account::saveConfig();
|
||||
m_resolver.data()->saveConfig();
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
ResolverAccount::path() const
|
||||
{
|
||||
return m_resolver.data()->filePath();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ResolverAccount::resolverChanged()
|
||||
{
|
||||
setAccountFriendlyName( m_resolver.data()->name() );
|
||||
emit connectionStateChanged( connectionState() );
|
||||
}
|
||||
|
||||
|
||||
/// AtticaResolverAccount
|
||||
|
||||
AtticaResolverAccount::AtticaResolverAccount( const QString& accountId )
|
||||
: ResolverAccount( accountId )
|
||||
{
|
||||
TomahawkSettings::instance()->setValue( QString( "accounts/%1/atticaresolver" ).arg( accountId ), true );
|
||||
|
||||
m_atticaId = configuration().value( "atticaId" ).toString();
|
||||
loadIcon();
|
||||
}
|
||||
|
||||
AtticaResolverAccount::AtticaResolverAccount( const QString& accountId, const QString& path, const QString& atticaId )
|
||||
: ResolverAccount( accountId, path )
|
||||
, m_atticaId( atticaId )
|
||||
{
|
||||
QVariantHash conf = configuration();
|
||||
conf[ "atticaId" ] = atticaId;
|
||||
setConfiguration( conf );
|
||||
|
||||
TomahawkSettings::instance()->setValue( QString( "accounts/%1/atticaresolver" ).arg( accountId ), true );
|
||||
|
||||
loadIcon();
|
||||
}
|
||||
|
||||
|
||||
AtticaResolverAccount::~AtticaResolverAccount()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
AtticaResolverAccount::loadIcon()
|
||||
{
|
||||
const QFileInfo fi( m_resolver.data()->filePath() );
|
||||
QDir codeDir = fi.absoluteDir();
|
||||
codeDir.cd( "../images" );
|
||||
|
||||
if ( codeDir.exists() && codeDir.exists( "icon.png" ) )
|
||||
m_icon.load( codeDir.absoluteFilePath( "icon.png" ) );
|
||||
|
||||
}
|
||||
|
||||
|
||||
QPixmap
|
||||
AtticaResolverAccount::icon() const
|
||||
{
|
||||
return m_icon;
|
||||
}
|
124
src/libtomahawk/accounts/ResolverAccount.h
Normal file
@@ -0,0 +1,124 @@
|
||||
/* === 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 RESOLVERACCOUNT_H
|
||||
#define RESOLVERACCOUNT_H
|
||||
|
||||
#include "accounts/Account.h"
|
||||
#include "dllmacro.h"
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
class ExternalResolverGui;
|
||||
|
||||
namespace Accounts {
|
||||
|
||||
class DLLEXPORT ResolverAccountFactory : public AccountFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ResolverAccountFactory() {}
|
||||
virtual ~ResolverAccountFactory() {}
|
||||
|
||||
virtual Account* createAccount(const QString& accountId = QString());
|
||||
virtual QString factoryId() const { return "resolveraccount"; }
|
||||
virtual QString description() const { return QString(); }
|
||||
virtual QString prettyName() const { return QString(); } // Internal, not displayed
|
||||
AccountTypes types() const { return AccountTypes( ResolverType ); };
|
||||
virtual bool allowUserCreation() const { return false; }
|
||||
|
||||
// Used to create a new resolver from a script on disk, either chosen by
|
||||
// the user, or installed from synchrotron
|
||||
static Account* createFromPath( const QString& path, bool isAttica );
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper wrapper class that is a resolver-only account.
|
||||
*
|
||||
* Contains the resolver* that is it wrapping
|
||||
*/
|
||||
class DLLEXPORT ResolverAccount : public Account
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
// Loads from config. Must already exist.
|
||||
explicit ResolverAccount( const QString& accountId );
|
||||
virtual ~ResolverAccount();
|
||||
|
||||
virtual void authenticate();
|
||||
virtual void deauthenticate();
|
||||
virtual bool isAuthenticated() const;
|
||||
virtual Tomahawk::Accounts::Account::ConnectionState connectionState() const;
|
||||
|
||||
virtual QWidget* configurationWidget();
|
||||
virtual QString errorMessage() const;
|
||||
|
||||
virtual void saveConfig();
|
||||
virtual void removeFromConfig();
|
||||
|
||||
QString path() const;
|
||||
|
||||
// Not relevant
|
||||
virtual QPixmap icon() const { return QPixmap(); }
|
||||
virtual SipPlugin* sipPlugin() { return 0; }
|
||||
virtual Tomahawk::InfoSystem::InfoPlugin* infoPlugin() { return 0; }
|
||||
virtual QWidget* aclWidget() { return 0; }
|
||||
|
||||
private slots:
|
||||
void resolverChanged();
|
||||
|
||||
protected:
|
||||
// Created by factory, when user installs a new resolver
|
||||
ResolverAccount( const QString& accountId, const QString& path );
|
||||
QWeakPointer<ExternalResolverGui> m_resolver;
|
||||
|
||||
friend class ResolverAccountFactory;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Extends ResolverAccount with what attica additionally provides---e.g. icon
|
||||
* Assumes certain file layout on disk.
|
||||
*/
|
||||
class AtticaResolverAccount : public ResolverAccount
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
// Loads from config
|
||||
explicit AtticaResolverAccount( const QString& accountId );
|
||||
virtual ~AtticaResolverAccount();
|
||||
|
||||
virtual QPixmap icon() const;
|
||||
|
||||
QString atticaId() const { return m_atticaId; }
|
||||
private:
|
||||
// Created by factory, when user installs a new resolver
|
||||
AtticaResolverAccount( const QString& accountId, const QString& path, const QString& atticaId );
|
||||
|
||||
void loadIcon();
|
||||
|
||||
QPixmap m_icon;
|
||||
QString m_atticaId;
|
||||
|
||||
friend class ResolverAccountFactory;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // RESOLVERACCOUNT_H
|
@@ -1,74 +0,0 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.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 ACCOUNT_H
|
||||
#define ACCOUNT_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QVariantMap>
|
||||
#include <QtGui/QWidget>
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "dllmacro.h"
|
||||
#include "infosystem/infosystem.h"
|
||||
#include "sip/SipPlugin.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class DLLEXPORT Account
|
||||
{
|
||||
|
||||
typedef QMap< QString, bool > ACLMap;
|
||||
|
||||
public:
|
||||
enum AccountTypes { InfoType, SipType };
|
||||
|
||||
explicit Account();
|
||||
virtual ~Account();
|
||||
|
||||
QString accountServiceName(); // e.g. "Twitter", "Last.fm"
|
||||
void setAccountServiceName( const QString &serviceName );
|
||||
|
||||
QString accountFriendlyName(); // e.g. screen name on the service, JID, etc.
|
||||
void setAccountFriendlyName( const QString &friendlyName );
|
||||
|
||||
bool autoConnect();
|
||||
void setAutoConnect( bool autoConnect );
|
||||
|
||||
QStringMap credentials();
|
||||
void setCredentials( const QStringMap &credentialMap );
|
||||
|
||||
QVariantMap configuration();
|
||||
void setConfiguration( const QVariantMap &configuration );
|
||||
QWidget* configurationWidget();
|
||||
|
||||
ACLMap acl();
|
||||
void setAcl( const ACLMap &acl );
|
||||
QWidget* aclWidget();
|
||||
|
||||
QSet< AccountTypes > types();
|
||||
void setTypes( const QSet< AccountTypes > types );
|
||||
|
||||
Tomahawk::InfoSystem::InfoPlugin* infoPlugin();
|
||||
SipPlugin* sipPlugin();
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif // ACCOUNT_H
|
@@ -250,6 +250,7 @@ void
|
||||
DatabaseWorker::logOp( DatabaseCommandLoggable* command )
|
||||
{
|
||||
TomahawkSqlQuery oplogquery = m_dbimpl->newquery();
|
||||
qDebug() << "INSERTING INTO OPTLOG:" << command->source()->id() << command->guid() << command->commandname();
|
||||
oplogquery.prepare( "INSERT INTO oplog(source, guid, command, singleton, compressed, json) "
|
||||
"VALUES(?, ?, ?, ?, ?, ?)" );
|
||||
|
||||
|
@@ -323,12 +323,12 @@ hypemPlugin::chartReturned()
|
||||
QList< InfoStringHash > top_tracks;
|
||||
QStringList top_artists;
|
||||
|
||||
if( url.contains( "artists" ) )
|
||||
if ( url.contains( "artists" ) )
|
||||
setChartType( Artist );
|
||||
else
|
||||
setChartType( Track );
|
||||
|
||||
foreach(QVariant result, res )
|
||||
foreach ( QVariant result, res )
|
||||
{
|
||||
QString title, artist;
|
||||
QVariantMap chartMap = result.toMap();
|
||||
@@ -339,28 +339,21 @@ hypemPlugin::chartReturned()
|
||||
title = chartMap.value( "title" ).toString();
|
||||
artist = chartMap.value( "artist" ).toString();
|
||||
|
||||
if( chartType() == Track )
|
||||
if ( chartType() == Track )
|
||||
{
|
||||
InfoStringHash pair;
|
||||
pair["artist"] = artist;
|
||||
pair["track"] = title;
|
||||
top_tracks << pair;
|
||||
|
||||
qDebug() << "HypemChart type is track";
|
||||
}
|
||||
|
||||
|
||||
if( chartType() == Artist )
|
||||
{
|
||||
|
||||
if ( chartType() == Artist )
|
||||
top_artists << artist;
|
||||
qDebug() << "HypemChart type is artist";
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( chartType() == Track )
|
||||
if ( chartType() == Track )
|
||||
{
|
||||
tDebug() << "HypemPlugin:" << "\tgot " << top_tracks.size() << " tracks";
|
||||
returnedData["tracks"] = QVariant::fromValue( top_tracks );
|
||||
@@ -369,7 +362,7 @@ hypemPlugin::chartReturned()
|
||||
|
||||
|
||||
|
||||
if( chartType() == Artist )
|
||||
if ( chartType() == Artist )
|
||||
{
|
||||
tDebug() << "HypemPlugin:" << "\tgot " << top_artists.size() << " artists";
|
||||
returnedData["artists"] = top_artists;
|
||||
|
@@ -26,34 +26,37 @@
|
||||
#include "album.h"
|
||||
#include "typedefs.h"
|
||||
#include "audio/audioengine.h"
|
||||
#include "tomahawksettings.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "utils/logger.h"
|
||||
#include "accounts/LastFmAccount.h"
|
||||
|
||||
#include <lastfm/ws.h>
|
||||
#include <lastfm/XmlQuery>
|
||||
|
||||
#include <qjson/parser.h>
|
||||
|
||||
using namespace Tomahawk::Accounts;
|
||||
using namespace Tomahawk::InfoSystem;
|
||||
|
||||
|
||||
LastFmPlugin::LastFmPlugin()
|
||||
LastFmPlugin::LastFmPlugin( LastFmAccount* account )
|
||||
: InfoPlugin()
|
||||
, m_account( account )
|
||||
, m_scrobbler( 0 )
|
||||
{
|
||||
m_supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages << InfoArtistSimilars << InfoArtistSongs << InfoChart << InfoChartCapabilities;
|
||||
m_supportedPushTypes << InfoSubmitScrobble << InfoSubmitNowPlaying << InfoLove << InfoUnLove;
|
||||
|
||||
// Flush session key cache
|
||||
TomahawkSettings::instance()->setLastFmSessionKey( QByteArray() );
|
||||
// TODO WHY FLUSH
|
||||
// m_account->setSessionKey( QByteArray() );
|
||||
|
||||
lastfm::ws::ApiKey = "7194b85b6d1f424fe1668173a78c0c4a";
|
||||
lastfm::ws::SharedSecret = "ba80f1df6d27ae63e9cb1d33ccf2052f";
|
||||
lastfm::ws::Username = TomahawkSettings::instance()->lastFmUsername();
|
||||
lastfm::ws::Username = m_account->username();
|
||||
lastfm::setNetworkAccessManager( TomahawkUtils::nam() );
|
||||
|
||||
m_pw = TomahawkSettings::instance()->lastFmPassword();
|
||||
m_pw = m_account->password();
|
||||
|
||||
//HACK work around a bug in liblastfm---it doesn't create its config dir, so when it
|
||||
// tries to write the track cache, it fails silently. until we have a fixed version, do this
|
||||
@@ -69,9 +72,6 @@ LastFmPlugin::LastFmPlugin()
|
||||
|
||||
m_badUrls << QUrl( "http://cdn.last.fm/flatness/catalogue/noimage" );
|
||||
|
||||
connect( TomahawkSettings::instance(), SIGNAL( changed() ),
|
||||
SLOT( settingsChanged() ), Qt::QueuedConnection );
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( settingsChanged() ) );
|
||||
}
|
||||
|
||||
@@ -706,23 +706,23 @@ LastFmPlugin::artistImagesReturned()
|
||||
void
|
||||
LastFmPlugin::settingsChanged()
|
||||
{
|
||||
if ( !m_scrobbler && TomahawkSettings::instance()->scrobblingEnabled() )
|
||||
if ( !m_scrobbler && m_account->scrobble() )
|
||||
{ // can simply create the scrobbler
|
||||
lastfm::ws::Username = TomahawkSettings::instance()->lastFmUsername();
|
||||
m_pw = TomahawkSettings::instance()->lastFmPassword();
|
||||
lastfm::ws::Username = m_account->username();
|
||||
m_pw = m_account->password();
|
||||
|
||||
createScrobbler();
|
||||
}
|
||||
else if ( m_scrobbler && !TomahawkSettings::instance()->scrobblingEnabled() )
|
||||
else if ( m_scrobbler && !m_account->scrobble() )
|
||||
{
|
||||
delete m_scrobbler;
|
||||
m_scrobbler = 0;
|
||||
}
|
||||
else if ( TomahawkSettings::instance()->lastFmUsername() != lastfm::ws::Username ||
|
||||
TomahawkSettings::instance()->lastFmPassword() != m_pw )
|
||||
else if ( m_account->username() != lastfm::ws::Username ||
|
||||
m_account->password() != m_pw )
|
||||
{
|
||||
lastfm::ws::Username = TomahawkSettings::instance()->lastFmUsername();
|
||||
m_pw = TomahawkSettings::instance()->lastFmPassword();
|
||||
lastfm::ws::Username = m_account->username();
|
||||
m_pw = m_account->password();
|
||||
// credentials have changed, have to re-create scrobbler for them to take effect
|
||||
if ( m_scrobbler )
|
||||
{
|
||||
@@ -752,16 +752,16 @@ LastFmPlugin::onAuthenticated()
|
||||
if ( lfm.children( "error" ).size() > 0 )
|
||||
{
|
||||
tLog() << "Error from authenticating with Last.fm service:" << lfm.text();
|
||||
TomahawkSettings::instance()->setLastFmSessionKey( QByteArray() );
|
||||
m_account->setSessionKey( QByteArray() );
|
||||
}
|
||||
else
|
||||
{
|
||||
lastfm::ws::SessionKey = lfm[ "session" ][ "key" ].text();
|
||||
|
||||
TomahawkSettings::instance()->setLastFmSessionKey( lastfm::ws::SessionKey.toLatin1() );
|
||||
m_account->setSessionKey( lastfm::ws::SessionKey.toLatin1() );
|
||||
|
||||
// qDebug() << "Got session key from last.fm";
|
||||
if ( TomahawkSettings::instance()->scrobblingEnabled() )
|
||||
if ( m_account->scrobble() )
|
||||
m_scrobbler = new lastfm::Audioscrobbler( "thk" );
|
||||
}
|
||||
}
|
||||
@@ -777,7 +777,7 @@ LastFmPlugin::onAuthenticated()
|
||||
void
|
||||
LastFmPlugin::createScrobbler()
|
||||
{
|
||||
if ( TomahawkSettings::instance()->lastFmSessionKey().isEmpty() ) // no session key, so get one
|
||||
if ( m_account->sessionKey().isEmpty() ) // no session key, so get one
|
||||
{
|
||||
qDebug() << "LastFmPlugin::createScrobbler Session key is empty";
|
||||
QString authToken = TomahawkUtils::md5( ( lastfm::ws::Username.toLower() + TomahawkUtils::md5( m_pw.toUtf8() ) ).toUtf8() );
|
||||
@@ -793,7 +793,7 @@ LastFmPlugin::createScrobbler()
|
||||
else
|
||||
{
|
||||
qDebug() << "LastFmPlugin::createScrobbler Already have session key";
|
||||
lastfm::ws::SessionKey = TomahawkSettings::instance()->lastFmSessionKey();
|
||||
lastfm::ws::SessionKey = m_account->sessionKey();
|
||||
|
||||
m_scrobbler = new lastfm::Audioscrobbler( "thk" );
|
||||
}
|
||||
|
@@ -32,6 +32,11 @@ class QNetworkReply;
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace Accounts
|
||||
{
|
||||
class LastFmAccount;
|
||||
}
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
|
||||
@@ -40,7 +45,7 @@ class LastFmPlugin : public InfoPlugin
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LastFmPlugin();
|
||||
LastFmPlugin( Accounts::LastFmAccount* account );
|
||||
virtual ~LastFmPlugin();
|
||||
|
||||
public slots:
|
||||
@@ -74,6 +79,7 @@ private:
|
||||
|
||||
void dataError( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
Accounts::LastFmAccount* m_account;
|
||||
QList<lastfm::Track> parseTrackList( QNetworkReply * reply );
|
||||
|
||||
lastfm::MutableTrack m_track;
|
||||
@@ -88,3 +94,5 @@ private:
|
||||
}
|
||||
|
||||
#endif // LASTFMPLUGIN_H
|
||||
|
||||
class A;
|
||||
|
@@ -1,6 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2012 Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -45,6 +46,9 @@ InfoSystem* InfoSystem::s_instance = 0;
|
||||
InfoSystem*
|
||||
InfoSystem::instance()
|
||||
{
|
||||
if ( !s_instance )
|
||||
s_instance = new InfoSystem( 0 );
|
||||
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
@@ -100,6 +104,9 @@ void
|
||||
InfoSystem::init()
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
if ( m_inited )
|
||||
return;
|
||||
|
||||
if ( !m_infoSystemCacheThreadController->cache() || !m_infoSystemWorkerThreadController->worker() )
|
||||
{
|
||||
QTimer::singleShot( 0, this, SLOT( init() ) );
|
||||
@@ -111,17 +118,17 @@ InfoSystem::init()
|
||||
|
||||
connect( cache, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
worker, SLOT( infoSlot( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
|
||||
|
||||
|
||||
connect( worker, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
this, SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ), Qt::UniqueConnection );
|
||||
|
||||
|
||||
connect( worker, SIGNAL( finished( QString ) ), this, SIGNAL( finished( QString ) ), Qt::UniqueConnection );
|
||||
|
||||
|
||||
connect( worker, SIGNAL( finished( QString, Tomahawk::InfoSystem::InfoType ) ),
|
||||
this, SIGNAL( finished( QString, Tomahawk::InfoSystem::InfoType ) ), Qt::UniqueConnection );
|
||||
|
||||
QMetaObject::invokeMethod( worker, "init", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoSystemCache*, cache ) );
|
||||
|
||||
|
||||
m_inited = true;
|
||||
}
|
||||
|
||||
@@ -195,6 +202,19 @@ InfoSystem::pushInfo( const QString &caller, const InfoTypeMap &input )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystem::addInfoPlugin( InfoPlugin* plugin )
|
||||
{
|
||||
// Init is not complete (waiting for worker th read to start and create worker object) so keep trying till then
|
||||
if ( !m_inited || !m_infoSystemWorkerThreadController->worker() )
|
||||
{
|
||||
QMetaObject::invokeMethod( this, "addInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPlugin*, plugin ) );
|
||||
return;
|
||||
}
|
||||
QMetaObject::invokeMethod( m_infoSystemWorkerThreadController->worker(), "addInfoPlugin", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoPlugin*, plugin ) );
|
||||
}
|
||||
|
||||
|
||||
InfoSystemCacheThread::InfoSystemCacheThread( QObject *parent )
|
||||
: QThread( parent )
|
||||
{
|
||||
|
@@ -134,7 +134,7 @@ struct InfoRequestData {
|
||||
QVariantMap customData;
|
||||
uint timeoutMillis;
|
||||
bool allSources;
|
||||
|
||||
|
||||
InfoRequestData()
|
||||
: requestId( TomahawkUtils::infosystemRequestId() )
|
||||
, internalId( TomahawkUtils::infosystemRequestId() )
|
||||
@@ -145,7 +145,7 @@ struct InfoRequestData {
|
||||
, timeoutMillis( 10000 )
|
||||
, allSources( false )
|
||||
{}
|
||||
|
||||
|
||||
InfoRequestData( const quint64 rId, const QString &callr, const Tomahawk::InfoSystem::InfoType typ, const QVariant &inputvar, const QVariantMap &custom )
|
||||
: requestId( rId )
|
||||
, internalId( TomahawkUtils::infosystemRequestId() )
|
||||
@@ -242,6 +242,10 @@ public:
|
||||
bool pushInfo( const QString &caller, const InfoType type, const QVariant &input );
|
||||
bool pushInfo( const QString &caller, const InfoTypeMap &input );
|
||||
|
||||
public slots:
|
||||
// InfoSystem takes ownership of InfoPlugins
|
||||
void addInfoPlugin( Tomahawk::InfoSystem::InfoPlugin* plugin );
|
||||
|
||||
signals:
|
||||
void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
void finished( QString target );
|
||||
@@ -249,7 +253,7 @@ signals:
|
||||
|
||||
private slots:
|
||||
void init();
|
||||
|
||||
|
||||
private:
|
||||
bool m_inited;
|
||||
InfoSystemCacheThread* m_infoSystemCacheThreadController;
|
||||
@@ -289,5 +293,6 @@ Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoRequestData );
|
||||
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoStringHash );
|
||||
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoSystemCache* );
|
||||
Q_DECLARE_METATYPE( QList< Tomahawk::InfoSystem::InfoStringHash > );
|
||||
Q_DECLARE_METATYPE( Tomahawk::InfoSystem::InfoPlugin* );
|
||||
|
||||
#endif // TOMAHAWK_INFOSYSTEM_H
|
||||
|
@@ -1,6 +1,7 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2012 Leo Franchi <lfranchi@kde.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -27,7 +28,6 @@
|
||||
#include "infoplugins/generic/musixmatchplugin.h"
|
||||
#include "infoplugins/generic/chartsplugin.h"
|
||||
#include "infoplugins/generic/spotifyPlugin.h"
|
||||
#include "infoplugins/generic/lastfmplugin.h"
|
||||
#include "infoplugins/generic/musicbrainzPlugin.h"
|
||||
#include "infoplugins/generic/hypemPlugin.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
@@ -41,7 +41,6 @@
|
||||
#include "infoplugins/unix/mprisplugin.h"
|
||||
#endif
|
||||
|
||||
#include "lastfm/NetworkAccessManager"
|
||||
#include "infoplugins/generic/RoviPlugin.h"
|
||||
|
||||
namespace Tomahawk
|
||||
@@ -78,71 +77,56 @@ void
|
||||
InfoSystemWorker::init( Tomahawk::InfoSystem::InfoSystemCache* cache )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
m_cache = cache;
|
||||
#ifndef ENABLE_HEADLESS
|
||||
InfoPluginPtr enptr( new EchoNestPlugin() );
|
||||
m_plugins.append( enptr );
|
||||
registerInfoTypes( enptr, enptr.data()->supportedGetTypes(), enptr.data()->supportedPushTypes() );
|
||||
InfoPluginPtr mmptr( new MusixMatchPlugin() );
|
||||
m_plugins.append( mmptr );
|
||||
registerInfoTypes( mmptr, mmptr.data()->supportedGetTypes(), mmptr.data()->supportedPushTypes() );
|
||||
InfoPluginPtr mbptr( new MusicBrainzPlugin() );
|
||||
m_plugins.append( mbptr );
|
||||
registerInfoTypes( mbptr, mbptr.data()->supportedGetTypes(), mbptr.data()->supportedPushTypes() );
|
||||
InfoPluginPtr lfmptr( new LastFmPlugin() );
|
||||
m_plugins.append( lfmptr );
|
||||
registerInfoTypes( lfmptr, lfmptr.data()->supportedGetTypes(), lfmptr.data()->supportedPushTypes() );
|
||||
InfoPluginPtr sptr( new ChartsPlugin() );
|
||||
m_plugins.append( sptr );
|
||||
registerInfoTypes( sptr, sptr.data()->supportedGetTypes(), sptr.data()->supportedPushTypes() );
|
||||
InfoPluginPtr roviptr( new RoviPlugin() );
|
||||
m_plugins.append( roviptr );
|
||||
registerInfoTypes( roviptr, roviptr.data()->supportedGetTypes(), roviptr.data()->supportedPushTypes() );
|
||||
InfoPluginPtr spotptr( new SpotifyPlugin() );
|
||||
m_plugins.append( spotptr );
|
||||
registerInfoTypes( spotptr, spotptr.data()->supportedGetTypes(), spotptr.data()->supportedPushTypes() );
|
||||
InfoPluginPtr hypeptr( new hypemPlugin() );
|
||||
m_plugins.append( hypeptr );
|
||||
registerInfoTypes( hypeptr, hypeptr.data()->supportedGetTypes(), hypeptr.data()->supportedPushTypes() );
|
||||
addInfoPlugin( new EchoNestPlugin() );
|
||||
addInfoPlugin( new MusixMatchPlugin() );
|
||||
addInfoPlugin( new MusicBrainzPlugin() );
|
||||
addInfoPlugin( new ChartsPlugin() );
|
||||
addInfoPlugin( new RoviPlugin() );
|
||||
addInfoPlugin( new SpotifyPlugin() );
|
||||
addInfoPlugin( new hypemPlugin() );
|
||||
#endif
|
||||
|
||||
#ifdef Q_WS_MAC
|
||||
InfoPluginPtr admptr( new AdiumPlugin() );
|
||||
m_plugins.append( admptr );
|
||||
registerInfoTypes( admptr, admptr.data()->supportedGetTypes(), admptr.data()->supportedPushTypes() );
|
||||
#endif
|
||||
#ifndef ENABLE_HEADLESS
|
||||
#ifdef Q_WS_X11
|
||||
InfoPluginPtr fdonotifyptr( new FdoNotifyPlugin() );
|
||||
m_plugins.append( fdonotifyptr );
|
||||
registerInfoTypes( fdonotifyptr, fdonotifyptr.data()->supportedGetTypes(), fdonotifyptr.data()->supportedPushTypes() );
|
||||
InfoPluginPtr mprisptr( new MprisPlugin() );
|
||||
m_plugins.append( mprisptr );
|
||||
registerInfoTypes( mprisptr, mprisptr.data()->supportedGetTypes(), mprisptr.data()->supportedPushTypes() );
|
||||
#endif
|
||||
#ifdef Q_WS_MAC
|
||||
addInfoPlugin( new AdiumPlugin() );
|
||||
#endif
|
||||
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
|
||||
{
|
||||
connect(
|
||||
plugin.data(),
|
||||
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
this,
|
||||
SLOT( infoSlot( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
Qt::UniqueConnection
|
||||
);
|
||||
#ifndef ENABLE_HEADLESS
|
||||
#ifdef Q_WS_X11
|
||||
addInfoPlugin( new FdoNotifyPlugin() );
|
||||
addInfoPlugin( new MprisPlugin() );
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
connect(
|
||||
plugin.data(),
|
||||
SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) ),
|
||||
cache,
|
||||
SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) )
|
||||
);
|
||||
connect(
|
||||
plugin.data(),
|
||||
SIGNAL( updateCache( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ),
|
||||
cache,
|
||||
SLOT( updateCacheSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) )
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
InfoSystemWorker::addInfoPlugin( InfoPlugin* plugin )
|
||||
{
|
||||
InfoPluginPtr weakptr( plugin );
|
||||
m_plugins.append( weakptr );
|
||||
registerInfoTypes( weakptr, weakptr.data()->supportedGetTypes(), weakptr.data()->supportedPushTypes() );
|
||||
|
||||
connect(
|
||||
plugin,
|
||||
SIGNAL( info( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
this,
|
||||
SLOT( infoSlot( Tomahawk::InfoSystem::InfoRequestData, QVariant ) ),
|
||||
Qt::UniqueConnection
|
||||
);
|
||||
|
||||
connect(
|
||||
plugin,
|
||||
SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) ),
|
||||
m_cache,
|
||||
SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoRequestData ) )
|
||||
);
|
||||
connect(
|
||||
plugin,
|
||||
SIGNAL( updateCache( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ),
|
||||
m_cache,
|
||||
SLOT( updateCacheSlot( Tomahawk::InfoSystem::InfoStringHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) )
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -37,7 +37,9 @@ namespace Tomahawk {
|
||||
|
||||
namespace InfoSystem {
|
||||
|
||||
|
||||
class InfoSystemCache;
|
||||
|
||||
|
||||
class DLLEXPORT InfoSystemWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -47,33 +49,37 @@ public:
|
||||
~InfoSystemWorker();
|
||||
|
||||
void registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &getTypes, const QSet< InfoType > &pushTypes );
|
||||
QNetworkAccessManager* nam() const;
|
||||
|
||||
|
||||
signals:
|
||||
void info( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
void finished( QString target );
|
||||
void finished( QString target, Tomahawk::InfoSystem::InfoType type );
|
||||
|
||||
|
||||
public slots:
|
||||
void init( Tomahawk::InfoSystem::InfoSystemCache* cache );
|
||||
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
void pushInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input );
|
||||
|
||||
void infoSlot( Tomahawk::InfoSystem::InfoRequestData requestData, QVariant output );
|
||||
|
||||
|
||||
void addInfoPlugin( Tomahawk::InfoSystem::InfoPlugin* plugin );
|
||||
|
||||
private slots:
|
||||
void checkTimeoutsTimerFired();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
void checkFinished( const Tomahawk::InfoSystem::InfoRequestData &target );
|
||||
QList< InfoPluginPtr > determineOrderedMatches( const InfoType type ) const;
|
||||
|
||||
|
||||
QHash< QString, QHash< InfoType, int > > m_dataTracker;
|
||||
QMultiMap< qint64, quint64 > m_timeRequestMapper;
|
||||
QHash< uint, bool > m_requestSatisfiedMap;
|
||||
QHash< uint, InfoRequestData* > m_savedRequestMap;
|
||||
|
||||
|
||||
// NOTE Cache object lives in a different thread, do not call methods on it directly
|
||||
InfoSystemCache* m_cache;
|
||||
|
||||
// For now, statically instantiate plugins; this is just somewhere to keep them
|
||||
QList< InfoPluginPtr > m_plugins;
|
||||
|
||||
|
@@ -65,7 +65,10 @@ Pipeline::~Pipeline()
|
||||
m_running = false;
|
||||
|
||||
// stop script resolvers
|
||||
qDeleteAll( m_scriptResolvers );
|
||||
foreach ( QWeakPointer< ExternalResolver > r, m_scriptResolvers )
|
||||
if ( !r.isNull() )
|
||||
r.data()->deleteLater();
|
||||
|
||||
m_scriptResolvers.clear();
|
||||
}
|
||||
|
||||
@@ -134,7 +137,7 @@ Pipeline::addScriptResolver( const QString& path, bool start )
|
||||
if ( !res )
|
||||
continue;
|
||||
|
||||
m_scriptResolvers << res;
|
||||
m_scriptResolvers << QWeakPointer< ExternalResolver >( res );
|
||||
if ( start )
|
||||
res->start();
|
||||
|
||||
@@ -148,10 +151,10 @@ Pipeline::addScriptResolver( const QString& path, bool start )
|
||||
void
|
||||
Pipeline::stopScriptResolver( const QString& path )
|
||||
{
|
||||
foreach ( ExternalResolver* res, m_scriptResolvers )
|
||||
foreach ( QWeakPointer< ExternalResolver > res, m_scriptResolvers )
|
||||
{
|
||||
if ( res->filePath() == path )
|
||||
res->stop();
|
||||
if ( res.data()->filePath() == path )
|
||||
res.data()->stop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,18 +162,21 @@ Pipeline::stopScriptResolver( const QString& path )
|
||||
void
|
||||
Pipeline::removeScriptResolver( const QString& scriptPath )
|
||||
{
|
||||
ExternalResolver* r = 0;
|
||||
foreach ( ExternalResolver* res, m_scriptResolvers )
|
||||
QWeakPointer< ExternalResolver > r;
|
||||
foreach ( QWeakPointer< ExternalResolver > res, m_scriptResolvers )
|
||||
{
|
||||
if ( res->filePath() == scriptPath )
|
||||
if ( res.isNull() )
|
||||
continue;
|
||||
|
||||
if ( res.data()->filePath() == scriptPath )
|
||||
r = res;
|
||||
}
|
||||
m_scriptResolvers.removeAll( r );
|
||||
|
||||
if ( r )
|
||||
if ( !r.isNull() )
|
||||
{
|
||||
r->stop();
|
||||
r->deleteLater();
|
||||
r.data()->stop();
|
||||
r.data()->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,10 +184,10 @@ Pipeline::removeScriptResolver( const QString& scriptPath )
|
||||
ExternalResolver*
|
||||
Pipeline::resolverForPath( const QString& scriptPath )
|
||||
{
|
||||
foreach ( ExternalResolver* res, m_scriptResolvers )
|
||||
foreach ( QWeakPointer< ExternalResolver > res, m_scriptResolvers )
|
||||
{
|
||||
if ( res->filePath() == scriptPath )
|
||||
return res;
|
||||
if ( res.data()->filePath() == scriptPath )
|
||||
return res.data();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|