diff --git a/resources.qrc b/resources.qrc index acaac9674..c76ed448e 100644 --- a/resources.qrc +++ b/resources.qrc @@ -79,6 +79,8 @@ <file>./data/images/add.png</file> <file>./data/images/recently-played.png</file> <file>./data/images/supercollection.png</file> +<file>./data/images/sipplugin-online.png</file> +<file>./data/images/sipplugin-offline.png</file> <file>./data/topbar-radiobuttons.css</file> <file>./data/icons/tomahawk-icon-16x16.png</file> <file>./data/icons/tomahawk-icon-32x32.png</file> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5186ddd2b..fdafa8fb1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,8 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui} tomahawktrayicon.cpp audiocontrols.cpp settingsdialog.cpp + configdelegatebase.cpp + sipconfigdelegate.cpp resolverconfigdelegate.cpp resolversmodel.cpp tomahawkwindow.cpp @@ -104,7 +106,9 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui} tomahawktrayicon.h audiocontrols.h settingsdialog.h + configdelegatebase.h resolverconfigdelegate.h + sipconfigdelegate.h resolversmodel.h resolverconfigwrapper.h tomahawkwindow.h diff --git a/src/libtomahawk/sip/SipHandler.cpp b/src/libtomahawk/sip/SipHandler.cpp index 2434862db..a5a9290c3 100644 --- a/src/libtomahawk/sip/SipHandler.cpp +++ b/src/libtomahawk/sip/SipHandler.cpp @@ -195,8 +195,6 @@ SipHandler::hookUpPlugin( SipPlugin* sip ) QObject::connect( sip, SIGNAL( avatarReceived( QString, QPixmap ) ), SLOT( onAvatarReceived( QString, QPixmap ) ) ); QObject::connect( sip, SIGNAL( avatarReceived( QPixmap ) ), SLOT( onAvatarReceived( QPixmap ) ) ); - m_allPlugins << sip; - emit pluginAdded( sip ); } @@ -248,16 +246,21 @@ SipHandler::checkSettings() void SipHandler::loadFromConfig( bool startup ) { - QStringList pluginIds = TomahawkSettings::instance()->enabledSipPlugins(); + QStringList pluginIds = TomahawkSettings::instance()->sipPlugins(); + QStringList enabled = TomahawkSettings::instance()->enabledSipPlugins(); foreach( const QString& pluginId, pluginIds ) { QString pluginFactory = factoryFromId( pluginId ); if( m_pluginFactories.contains( pluginFactory ) ) { SipPlugin* p = loadPlugin( pluginId ); - p->connectPlugin( startup ); + m_allPlugins << p; - m_enabledPlugins << p; + if ( enabled.contains( pluginId ) ) + { + p->connectPlugin( startup ); + m_enabledPlugins << p; + } } } m_connected = true; diff --git a/src/libtomahawk/sip/SipModel.cpp b/src/libtomahawk/sip/SipModel.cpp index 86ce30d22..b47d115de 100644 --- a/src/libtomahawk/sip/SipModel.cpp +++ b/src/libtomahawk/sip/SipModel.cpp @@ -23,7 +23,7 @@ #include "sip/SipHandler.h" SipModel::SipModel( QObject* parent ) - : QAbstractListModel( parent ) + : QAbstractItemModel( parent ) { connect( SipHandler::instance(), SIGNAL( stateChanged( SipPlugin*, SipPlugin::ConnectionState ) ), this, SLOT( pluginStateChanged( SipPlugin* ) ) ); } @@ -56,15 +56,15 @@ SipModel::data( const QModelIndex& index, int role ) const { case Qt::DisplayRole: case SipModel::PluginName: - { - p->accountName(); - } + return p->accountName(); case SipModel::ConnectionStateRole: return p->connectionState(); case SipModel::HasConfig: return ( p->configWidget() == 0 ); case SipModel::FactoryRole: return false; + case Qt::DecorationRole: + return p->icon(); case Qt::CheckStateRole: return SipHandler::instance()->enabledPlugins().contains( p ) ? Qt::Checked : Qt::Unchecked; default: @@ -94,11 +94,44 @@ SipModel::setData( const QModelIndex& index, const QVariant& value, int role ) return false; } +QModelIndex +SipModel::index( int row, int column, const QModelIndex& parent ) const +{ + if( !parent.isValid() ) + return hasIndex( row, column, parent ) ? createIndex( row, column, 0 ) : QModelIndex(); + + // it's a child of the Add Account, e.g. a factory + if( hasIndex( row, column, parent ) ) { + createIndex( row, column, 1 /* magic */ ); + } + + return QModelIndex(); +} + +QModelIndex +SipModel::parent( const QModelIndex& child ) const +{ + if( !child.isValid() ) + return QModelIndex(); + + if( child.internalId() == 1 ) { + return createIndex( SipHandler::instance()->allPlugins().size() - 1, 0, 0 ); + } + + return QModelIndex(); +} int SipModel::rowCount( const QModelIndex& parent ) const { - return SipHandler::instance()->allPlugins().size() + 1; + if( !parent.isValid() ) { // top level item + if( parent.row() == SipHandler::instance()->allPlugins().count() ) { // last row, this is the factory + return SipHandler::instance()->pluginFactories().count(); + } else { + return SipHandler::instance()->allPlugins().size() + 1; + } + } + return 0; } int diff --git a/src/libtomahawk/sip/SipModel.h b/src/libtomahawk/sip/SipModel.h index 3e46c19e1..f3f8ca07e 100644 --- a/src/libtomahawk/sip/SipModel.h +++ b/src/libtomahawk/sip/SipModel.h @@ -27,7 +27,7 @@ class SipPlugin; -class DLLEXPORT SipModel : public QAbstractListModel +class DLLEXPORT SipModel : public QAbstractItemModel { Q_OBJECT public: @@ -35,12 +35,15 @@ public: PluginName = Qt::UserRole + 15, ConnectionStateRole = Qt::UserRole + 17, HasConfig = Qt::UserRole + 18, - FactoryRole = Qt::UserRole + 19 + FactoryRole = Qt::UserRole + 19, + ErrorString = Qt::UserRole + 20 }; explicit SipModel( QObject* parent = 0 ); virtual ~SipModel(); + virtual QModelIndex index ( int row, int column, const QModelIndex& parent = QModelIndex() ) const; + virtual QModelIndex parent ( const QModelIndex& child ) const; virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const; virtual int rowCount( const QModelIndex& parent = QModelIndex() ) const; virtual int columnCount( const QModelIndex& parent ) const; diff --git a/src/libtomahawk/sip/SipPlugin.cpp b/src/libtomahawk/sip/SipPlugin.cpp index 4f6ec7156..f10cd0710 100644 --- a/src/libtomahawk/sip/SipPlugin.cpp +++ b/src/libtomahawk/sip/SipPlugin.cpp @@ -52,3 +52,15 @@ SipPlugin::configWidget() { return 0; } + +QString +SipPlugin::errorMessage() const +{ + return QString(); +} + +QIcon +SipPlugin::icon() const +{ + return QIcon(); +} diff --git a/src/libtomahawk/sip/SipPlugin.h b/src/libtomahawk/sip/SipPlugin.h index 1c1bc9fb4..470695df7 100644 --- a/src/libtomahawk/sip/SipPlugin.h +++ b/src/libtomahawk/sip/SipPlugin.h @@ -35,9 +35,9 @@ public: virtual ~SipPluginFactory() {} // display name for plugin - virtual QString prettyName() = 0; + virtual QString prettyName() const = 0; // internal name - virtual QString factoryId() = 0; + virtual QString factoryId() const = 0; virtual SipPlugin* createPlugin( const QString& pluginId = QString() ) = 0; protected: @@ -63,8 +63,10 @@ public: virtual const QString friendlyName() const = 0; virtual const QString accountName() const = 0; virtual ConnectionState connectionState() const = 0; + virtual QString errorMessage() const; virtual QMenu* menu(); virtual QWidget* configWidget(); + virtual QIcon icon() const; public slots: virtual bool connectPlugin( bool startup = false ) = 0; diff --git a/src/resolverconfigdelegate.cpp b/src/resolverconfigdelegate.cpp index 0f98e49f8..cec5d4336 100644 --- a/src/resolverconfigdelegate.cpp +++ b/src/resolverconfigdelegate.cpp @@ -29,10 +29,9 @@ #define PADDING 4 ResolverConfigDelegate::ResolverConfigDelegate( QObject* parent ) - : QStyledItemDelegate( parent ) - , m_configPressed( false ) + : ConfigDelegateBase( parent ) { - + connect( this, SIGNAL( configPressed( QModelIndex ) ), this, SLOT( onConfigPressed( QModelIndex ) ) ); } void @@ -61,36 +60,32 @@ ResolverConfigDelegate::paint( QPainter* painter, const QStyleOptionViewItem& op style->drawPrimitive( QStyle::PE_PanelItemViewItem, &opt, painter, w ); int rightSplit = itemRect.width(); - int rectW = opt.rect.height() - 4 * PADDING; + int rectW = 24; QRect confRect = QRect( rightSplit - rectW - 2 * PADDING, 2 * PADDING + top, rectW, rectW ); + // if the resolver has a config widget, paint it first (right-aligned) if( index.data( ResolversModel::HasConfig ).toBool() ) { - // draw it the same size as the check belox QStyleOptionToolButton topt; - topt.font = opt.font; - topt.icon = QIcon( RESPATH "images/configure.png" ); - topt.iconSize = QSize( 16, 16 ); topt.rect = confRect; - topt.subControls = QStyle::SC_ToolButton; - topt.activeSubControls = QStyle::SC_None; - topt.features = QStyleOptionToolButton::None; topt.pos = confRect.topLeft(); - topt.state = m_configPressed ? QStyle::State_On : QStyle::State_Raised; - if( opt.state & QStyle::State_MouseOver || m_configPressed ) - topt.state |= QStyle::State_HasFocus; - style->drawComplexControl( QStyle::CC_ToolButton, &topt, painter, w ); + + drawConfigWrench( painter, opt, topt ); } // draw check - confRect.moveTo( 2 * PADDING, 2 * PADDING + top ); - opt.rect = confRect; - opt.checkState == Qt::Checked ? opt.state |= QStyle::State_On : opt.state |= QStyle::State_Off; - style->drawPrimitive( QStyle::PE_IndicatorViewItemCheck, &opt, painter, w ); + QRect checkRect = confRect; + checkRect.moveTo( 2 * PADDING, 2 * PADDING + top ); + opt.rect = checkRect; + drawCheckBox( opt, painter, w ); itemRect.setX( opt.rect.topRight().x() + PADDING ); painter->save(); painter->setFont( name ); QRect textRect = itemRect.adjusted( PADDING, PADDING, -PADDING, -PADDING ); + + if( index.data( ResolversModel::HasConfig ).toBool() ) + textRect.setRight( confRect.topLeft().x() - PADDING ); + textRect.setBottom( itemRect.height() / 2 + top ); QString nameStr = bfm.elidedText( index.data( ResolversModel::ResolverName ).toString(),Qt::ElideRight, textRect.width() ); painter->drawText( textRect, nameStr ); @@ -106,71 +101,8 @@ ResolverConfigDelegate::paint( QPainter* painter, const QStyleOptionViewItem& op } -QSize -ResolverConfigDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const +void +ResolverConfigDelegate::onConfigPressed( const QModelIndex& idx ) { - 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, 3 * PADDING + bfm.height() + sfm.height() ); -} - -bool -ResolverConfigDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index) -{ -// qDebug() << "EDITOR EVENT!" << ( event->type() == QEvent::MouseButtonRelease ); - - QStyleOptionViewItemV4 viewOpt( option ); - initStyleOption( &viewOpt, index ); - const QWidget* w = viewOpt.widget; - QStyle* style = w ? w->style() : QApplication::style(); - int top = viewOpt.rect.top(); - - if( event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::MouseButtonDblClick ) { - m_configPressed = false; - - int rectW = option.rect.height() - 4 * PADDING; - QRect checkRect = QRect( 2 * PADDING, 2 * PADDING + top, rectW, rectW ); - QMouseEvent* me = static_cast< QMouseEvent* >( event ); - if( me->button() != Qt::LeftButton || !checkRect.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 ) { - int rightSplit = viewOpt.rect.width(); - int rectW = viewOpt.rect.height() - 4 * PADDING; - QRect confRect = QRect( rightSplit - rectW - 2 * PADDING, 2 * PADDING + top, rectW, rectW ); - - QMouseEvent* me = static_cast< QMouseEvent* >( event ); - if( me->button() == Qt::LeftButton && confRect.contains( me->pos() ) ) { - m_configPressed = true; - - emit openConfig( index.data( ResolversModel::ResolverPath ).toString() ); - return true; - } - } - - return QStyledItemDelegate::editorEvent( event, model, option, index ); + emit openConfig( idx.data( ResolversModel::ResolverPath ).toString() ); } diff --git a/src/resolverconfigdelegate.h b/src/resolverconfigdelegate.h index 280e63ccb..84ed8f018 100644 --- a/src/resolverconfigdelegate.h +++ b/src/resolverconfigdelegate.h @@ -20,23 +20,21 @@ #ifndef RESOLVERCONFIGDELEGATE_H #define RESOLVERCONFIGDELEGATE_H -#include <QStyledItemDelegate> +#include "configdelegatebase.h" -class ResolverConfigDelegate : public QStyledItemDelegate +class ResolverConfigDelegate : public ConfigDelegateBase { Q_OBJECT public: explicit ResolverConfigDelegate(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 ); + +private slots: + void onConfigPressed ( const QModelIndex& ); signals: void openConfig( const QString& resolverPath ); - -private: - bool m_configPressed; }; #endif // RESOLVERCONFIGDELEGATE_H diff --git a/src/resolvers/scriptresolver.cpp b/src/resolvers/scriptresolver.cpp index d119e9e4e..a713f186c 100644 --- a/src/resolvers/scriptresolver.cpp +++ b/src/resolvers/scriptresolver.cpp @@ -165,12 +165,6 @@ ScriptResolver::handleMsg( const QByteArray& msg ) rp->setMimetype( TomahawkUtils::extensionToMimetype( m.value( "extension" ).toString() ) ); Q_ASSERT( !rp->mimetype().isEmpty() ); } - if ( m.contains( "year" ) ) - { - QVariantMap attr; - attr[ "releaseyear" ] = m.value( "year" ); - rp->setAttributes( attr ); - } results << rp; } diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp index 409be8a7a..8fd01977c 100644 --- a/src/settingsdialog.cpp +++ b/src/settingsdialog.cpp @@ -44,6 +44,7 @@ #include "resolversmodel.h" #include "resolverconfigwrapper.h" #include "sip/SipModel.h" +#include "sipconfigdelegate.h" static QString md5( const QByteArray& src ) @@ -70,9 +71,9 @@ SettingsDialog::SettingsDialog( QWidget *parent ) ui->checkBoxUpnp->setEnabled( !s->preferStaticHostPort() ); // SIP PLUGINS -// SipPluginDelegate* ad = new SipPluginDelegate( this ); -// ui->accountsView->setItemDelegate( ad ); -// connect( ad, SIGNAL( openConfig( QString ) ), this, SLOT( openSipPluginConfig( QString ) ) ); + SipConfigDelegate* sipdel = new SipConfigDelegate( this ); + ui->accountsView->setItemDelegate( sipdel ); +// connect( sipdel, SIGNAL( openConfig( SipPlugin* ) ), this, SLOT( openSipPluginConfig( SipPlugin* ) ) ); m_sipModel = new SipModel( this ); ui->accountsView->setModel( m_sipModel ); diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui index 4e153c586..ab0e58628 100644 --- a/src/settingsdialog.ui +++ b/src/settingsdialog.ui @@ -31,7 +31,20 @@ </attribute> <layout class="QVBoxLayout" name="verticalLayout_20"> <item> - <widget class="QListView" name="accountsView"/> + <widget class="QTreeView" name="accountsView"> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <property name="uniformRowHeights"> + <bool>false</bool> + </property> + <property name="animated"> + <bool>true</bool> + </property> + <property name="headerHidden"> + <bool>true</bool> + </property> + </widget> </item> </layout> </widget>