diff --git a/data/images/account-settings.png b/data/images/account-settings.png
new file mode 100644
index 000000000..19fddebe8
Binary files /dev/null and b/data/images/account-settings.png differ
diff --git a/data/images/advanced-settings.png b/data/images/advanced-settings.png
new file mode 100644
index 000000000..9d3ebb405
Binary files /dev/null and b/data/images/advanced-settings.png differ
diff --git a/data/images/lastfm-settings.png b/data/images/lastfm-settings.png
new file mode 100644
index 000000000..ff57ab5a3
Binary files /dev/null and b/data/images/lastfm-settings.png differ
diff --git a/data/images/music-settings.png b/data/images/music-settings.png
new file mode 100644
index 000000000..3dd854027
Binary files /dev/null and b/data/images/music-settings.png differ
diff --git a/data/images/resolvers-settings.png b/data/images/resolvers-settings.png
new file mode 100644
index 000000000..28f88d2b5
Binary files /dev/null and b/data/images/resolvers-settings.png differ
diff --git a/data/images/sipplugin-offline.png b/data/images/sipplugin-offline.png
new file mode 100644
index 000000000..fd50901be
Binary files /dev/null and b/data/images/sipplugin-offline.png differ
diff --git a/data/images/sipplugin-online.png b/data/images/sipplugin-online.png
new file mode 100644
index 000000000..1221e1310
Binary files /dev/null and b/data/images/sipplugin-online.png differ
diff --git a/include/tomahawk/tomahawkapp.h b/include/tomahawk/tomahawkapp.h
index 1547254dd..d814ea32d 100644
--- a/include/tomahawk/tomahawkapp.h
+++ b/include/tomahawk/tomahawkapp.h
@@ -82,7 +82,7 @@ public:
void init();
static TomahawkApp* instance();
- SipHandler* sipHandler() { return m_sipHandler; }
+ SipHandler* sipHandler();
XMPPBot* xmppBot() { return m_xmppBot; }
#ifndef TOMAHAWK_HEADLESS
@@ -119,7 +119,6 @@ private:
Database* m_database;
ScanManager *m_scanManager;
AudioEngine* m_audioEngine;
- SipHandler* m_sipHandler;
Servent* m_servent;
Tomahawk::InfoSystem::InfoSystem* m_infoSystem;
XMPPBot* m_xmppBot;
diff --git a/resources.qrc b/resources.qrc
index acaac9674..6d0f9b26f 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -79,6 +79,13 @@
./data/images/add.png
./data/images/recently-played.png
./data/images/supercollection.png
+./data/images/sipplugin-online.png
+./data/images/sipplugin-offline.png
+./data/images/advanced-settings.png
+./data/images/account-settings.png
+./data/images/music-settings.png
+./data/images/resolvers-settings.png
+./data/images/lastfm-settings.png
./data/topbar-radiobuttons.css
./data/icons/tomahawk-icon-16x16.png
./data/icons/tomahawk-icon-32x32.png
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5186ddd2b..45cf481d1 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,15 +106,18 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui}
tomahawktrayicon.h
audiocontrols.h
settingsdialog.h
+ configdelegatebase.h
resolverconfigdelegate.h
+ sipconfigdelegate.h
resolversmodel.h
- resolverconfigwrapper.h
+ delegateconfigwrapper.h
tomahawkwindow.h
)
SET( tomahawkUI ${tomahawkUI}
tomahawkwindow.ui
settingsdialog.ui
+ stackedsettingsdialog.ui
proxydialog.ui
audiocontrols.ui
diff --git a/src/configdelegatebase.cpp b/src/configdelegatebase.cpp
new file mode 100644
index 000000000..2ddd010c6
--- /dev/null
+++ b/src/configdelegatebase.cpp
@@ -0,0 +1,120 @@
+/*
+ Copyright (C) 2011 Leo Franchi
+
+ 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 .
+*/
+
+
+#include "configdelegatebase.h"
+
+#include "utils/tomahawkutils.h"
+
+#include
+#include
+#include
+
+ConfigDelegateBase::ConfigDelegateBase ( QObject* parent )
+ : QStyledItemDelegate ( parent )
+ , m_configPressed( false )
+{
+
+}
+
+
+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
+{
+ m_checkRect = opt.rect;
+ 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;
+ 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 );
+}
+
+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 = false;
+
+ QMouseEvent* me = static_cast< QMouseEvent* >( event );
+ if( me->button() != Qt::LeftButton || !m_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 ) {
+ QMouseEvent* me = static_cast< QMouseEvent* >( event );
+ if( me->button() == Qt::LeftButton && configRectForIndex( option, index ).contains( me->pos() ) ) {
+ m_configPressed = true;
+
+ emit configPressed( index );
+ return true;
+ }
+ }
+
+ return QStyledItemDelegate::editorEvent( event, model, option, index );
+}
diff --git a/src/configdelegatebase.h b/src/configdelegatebase.h
new file mode 100644
index 000000000..c9f01b864
--- /dev/null
+++ b/src/configdelegatebase.h
@@ -0,0 +1,54 @@
+/*
+ Copyright (C) 2011 Leo Franchi
+
+ 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 .
+*/
+
+
+#ifndef CONFIGDELEGATEBASE_H
+#define CONFIGDELEGATEBASE_H
+
+#include "dllmacro.h"
+
+#include
+
+#define PADDING 4
+
+class QPainter;
+class DLLEXPORT ConfigDelegateBase : public QStyledItemDelegate
+{
+ Q_OBJECT
+public:
+ ConfigDelegateBase( QObject* parent = 0 );
+ virtual QSize sizeHint ( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
+
+ virtual bool editorEvent ( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
+
+ // 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;
+
+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:
+ mutable QRect m_checkRect;
+ mutable QRect m_configRect;
+ bool m_configPressed;
+};
+
+#endif // CONFIGDELEGATEBASE_H
diff --git a/src/resolverconfigwrapper.h b/src/delegateconfigwrapper.h
similarity index 89%
rename from src/resolverconfigwrapper.h
rename to src/delegateconfigwrapper.h
index e43700e38..0476ea8c2 100644
--- a/src/resolverconfigwrapper.h
+++ b/src/delegateconfigwrapper.h
@@ -22,14 +22,16 @@
#include
#include
-class ResolverConfigWrapper : public QDialog
+class DelegateConfigWrapper : public QDialog
{
Q_OBJECT
public:
- ResolverConfigWrapper( QWidget* conf, const QString& title, QWidget* parent ) : QDialog( parent ), m_widget( conf )
+ DelegateConfigWrapper( QWidget* conf, const QString& title, QWidget* parent ) : QDialog( parent ), m_widget( conf )
{
- setWindowTitle( title );
+ m_widget->setVisible( true );
+ m_widget->setWindowFlags( Qt::Sheet );
+ setWindowTitle( title );
QVBoxLayout* v = new QVBoxLayout( this );
v->addWidget( m_widget );
@@ -46,6 +48,7 @@ public slots:
// let the config widget live to see another day
layout()->removeWidget( m_widget );
m_widget->setParent( 0 );
+ m_widget->setVisible( false );
QDialogButtonBox* buttons = qobject_cast< QDialogButtonBox* >( sender() );
if( buttons->standardButton( b ) == QDialogButtonBox::Ok )
@@ -59,6 +62,7 @@ public slots:
{
layout()->removeWidget( m_widget );
m_widget->setParent( 0 );
+ m_widget->setVisible( false );
}
private:
diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt
index 3e1d9e258..aab9a3e60 100644
--- a/src/libtomahawk/CMakeLists.txt
+++ b/src/libtomahawk/CMakeLists.txt
@@ -33,6 +33,7 @@ set( libSources
sip/SipPlugin.cpp
sip/SipHandler.cpp
+ sip/SipModel.cpp
audio/audioengine.cpp
@@ -193,6 +194,7 @@ set( libHeaders
sip/SipPlugin.h
sip/SipHandler.h
+ sip/SipModel.h
audio/audioengine.h
diff --git a/src/libtomahawk/sip/SipHandler.cpp b/src/libtomahawk/sip/SipHandler.cpp
index a3b7b0375..bf0408707 100644
--- a/src/libtomahawk/sip/SipHandler.cpp
+++ b/src/libtomahawk/sip/SipHandler.cpp
@@ -42,6 +42,8 @@ SipHandler* SipHandler::s_instance = 0;
SipHandler* SipHandler::instance()
{
+ if( s_instance == 0 )
+ s_instance = new SipHandler( 0 );
return s_instance;
}
@@ -51,7 +53,7 @@ SipHandler::SipHandler( QObject* parent )
{
s_instance = this;
- loadPlugins( findPlugins() );
+ loadPluginFactories( findPluginFactories() );
connect( TomahawkSettings::instance(), SIGNAL( changed() ), SLOT( onSettingsChanged() ) );
}
@@ -59,14 +61,7 @@ SipHandler::SipHandler( QObject* parent )
SipHandler::~SipHandler()
{
- disconnectPlugins();
-}
-
-
-QList< SipPlugin* >
-SipHandler::plugins() const
-{
- return m_plugins;
+ disconnectAll();
}
const QPixmap SipHandler::avatar( const QString& name ) const
@@ -95,7 +90,7 @@ SipHandler::onSettingsChanged()
QStringList
-SipHandler::findPlugins()
+SipHandler::findPluginFactories()
{
QStringList paths;
QList< QDir > pluginDirs;
@@ -137,7 +132,7 @@ SipHandler::findPlugins()
void
-SipHandler::loadPlugins( const QStringList& paths )
+SipHandler::loadPluginFactories( const QStringList& paths )
{
foreach ( QString fileName, paths )
{
@@ -145,13 +140,67 @@ SipHandler::loadPlugins( const QStringList& paths )
continue;
qDebug() << "Trying to load plugin:" << fileName;
- loadPlugin( fileName );
+ loadPluginFactory( fileName );
}
}
+SipPlugin*
+SipHandler::createPlugin( const QString& factoryId )
+{
+ Q_ASSERT( m_pluginFactories.contains( factoryId ) );
+
+ SipPlugin* sip = m_pluginFactories[ factoryId ]->createPlugin();
+ hookUpPlugin( sip );
+
+ emit pluginAdded( sip );
+ return sip;
+}
+
+SipPlugin*
+SipHandler::loadPlugin( const QString& pluginId )
+{
+ QString factoryName = factoryFromId( pluginId );
+
+ Q_ASSERT( m_pluginFactories.contains( factoryName ) );
+
+ SipPlugin* sip = m_pluginFactories[ factoryName ]->createPlugin( pluginId );
+ hookUpPlugin( sip );
+
+ // caller responsible for calling pluginAdded()
+ return sip;
+}
+
+void
+SipHandler::removePlugin( SipPlugin* p )
+{
+ p->disconnectPlugin();
+
+ m_allPlugins.removeAll( p );
+ m_enabledPlugins.removeAll( p );
+
+ TomahawkSettings::instance()->removeSipPlugin( p->pluginId() );
+
+ emit pluginRemoved( p );
+}
+
void
-SipHandler::loadPlugin( const QString& path )
+SipHandler::hookUpPlugin( SipPlugin* sip )
+{
+ QObject::connect( sip, SIGNAL( peerOnline( QString ) ), SLOT( onPeerOnline( QString ) ) );
+ QObject::connect( sip, SIGNAL( peerOffline( QString ) ), SLOT( onPeerOffline( QString ) ) );
+ QObject::connect( sip, SIGNAL( msgReceived( QString, QString ) ), SLOT( onMessage( QString, QString ) ) );
+
+ QObject::connect( sip, SIGNAL( error( int, QString ) ), SLOT( onError( int, QString ) ) );
+ QObject::connect( sip, SIGNAL( stateChanged( SipPlugin::ConnectionState ) ), SLOT( onStateChanged( SipPlugin::ConnectionState ) ) );
+
+ QObject::connect( sip, SIGNAL( avatarReceived( QString, QPixmap ) ), SLOT( onAvatarReceived( QString, QPixmap ) ) );
+ QObject::connect( sip, SIGNAL( avatarReceived( QPixmap ) ), SLOT( onAvatarReceived( QPixmap ) ) );
+}
+
+
+void
+SipHandler::loadPluginFactory( const QString& path )
{
QPluginLoader loader( path );
QObject* plugin = loader.instance();
@@ -160,37 +209,24 @@ SipHandler::loadPlugin( const QString& path )
qDebug() << "Error loading plugin:" << loader.errorString();
}
- SipPlugin* sip = qobject_cast(plugin);
- if ( sip )
+ SipPluginFactory* sipfactory = qobject_cast(plugin);
+ if ( sipfactory )
{
- if ( pluginLoaded( sip->name() ) )
- {
- qDebug() << "Plugin" << sip->name() << "already loaded! Not loading:" << loader.fileName();
- return;
- }
- qDebug() << "Loaded plugin:" << loader.fileName();
-
- QObject::connect( sip, SIGNAL( peerOnline( QString ) ), SLOT( onPeerOnline( QString ) ) );
- QObject::connect( sip, SIGNAL( peerOffline( QString ) ), SLOT( onPeerOffline( QString ) ) );
- QObject::connect( sip, SIGNAL( msgReceived( QString, QString ) ), SLOT( onMessage( QString, QString ) ) );
-
- QObject::connect( sip, SIGNAL( connected() ), SIGNAL( connected() ) );
- QObject::connect( sip, SIGNAL( disconnected() ), SIGNAL( disconnected() ) );
- QObject::connect( sip, SIGNAL( error( int, QString ) ), SLOT( onError( int, QString ) ) );
-
- QObject::connect( sip, SIGNAL( avatarReceived( QString, QPixmap ) ), SLOT( onAvatarReceived( QString, QPixmap ) ) );
- QObject::connect( sip, SIGNAL( avatarReceived( QPixmap ) ), SLOT( onAvatarReceived( QPixmap ) ) );
- m_plugins << sip;
+ qDebug() << "Loaded plugin factory:" << loader.fileName() << sipfactory->factoryId() << sipfactory->prettyName();
+ m_pluginFactories[ sipfactory->factoryId() ] = sipfactory;
+ } else
+ {
+ qDebug() << "Loaded invalid plugin.." << loader.fileName();
}
}
bool
-SipHandler::pluginLoaded( const QString& name ) const
+SipHandler::pluginLoaded( const QString& pluginId ) const
{
- foreach( SipPlugin* plugin, m_plugins )
+ foreach( SipPlugin* plugin, m_allPlugins )
{
- if ( plugin->name() == name )
+ if ( plugin->pluginId() == pluginId )
return true;
}
@@ -201,15 +237,111 @@ SipHandler::pluginLoaded( const QString& name ) const
void
SipHandler::checkSettings()
{
- foreach( SipPlugin* sip, m_plugins )
+ foreach( SipPlugin* sip, m_allPlugins )
{
sip->checkSettings();
}
}
+void
+SipHandler::addSipPlugin( SipPlugin* p, bool enabled, bool startup )
+{
+ m_allPlugins << p;
+
+ if ( enabled )
+ {
+ p->connectPlugin( startup );
+ m_enabledPlugins << p;
+ }
+
+ emit pluginAdded( p );
+}
void
-SipHandler::connectPlugins( bool startup, const QString &pluginName )
+SipHandler::removeSipPlugin( SipPlugin* p )
+{
+ p->disconnectPlugin();
+ emit pluginRemoved( p );
+ // emit first so sipmodel can find the indexOf
+
+ TomahawkSettings::instance()->removeSipPlugin( p->pluginId() );
+ m_allPlugins.removeAll( p );
+ m_enabledPlugins.removeAll( p );
+}
+
+bool
+SipHandler::hasPluginType( const QString& factoryId ) const
+{
+ foreach( SipPlugin* p, m_allPlugins ) {
+ if( factoryFromId( p->pluginId() ) == factoryId )
+ return true;
+ }
+ return false;
+}
+
+
+void
+SipHandler::loadFromConfig( bool startup )
+{
+ 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 );
+ addSipPlugin( p, enabled.contains( pluginId ), startup );
+ }
+ }
+ m_connected = true;
+}
+
+void
+SipHandler::connectAll()
+{
+ foreach( SipPlugin* sip, m_enabledPlugins )
+ {
+ sip->connectPlugin();
+ }
+ m_connected = true;
+}
+
+
+void
+SipHandler::disconnectAll()
+{
+ foreach( SipPlugin* p, m_connectedPlugins )
+ p->disconnectPlugin();
+
+ SourceList::instance()->removeAllRemote();
+ m_connected = false;
+}
+
+void
+SipHandler::disablePlugin( SipPlugin* p )
+{
+ Q_ASSERT( m_enabledPlugins.contains( p ) );
+
+ TomahawkSettings::instance()->disableSipPlugin( p->pluginId() );
+ p->disconnectPlugin();
+
+ m_enabledPlugins.removeAll( p );
+}
+
+void
+SipHandler::enablePlugin( SipPlugin* p )
+{
+ Q_ASSERT( !m_enabledPlugins.contains( p ) );
+ p->connectPlugin();
+
+ TomahawkSettings::instance()->enableSipPlugin( p->pluginId() );
+ m_enabledPlugins << p;
+}
+
+
+void
+SipHandler::connectPlugin( bool startup, const QString &pluginId )
{
#ifndef TOMAHAWK_HEADLESS
if ( !TomahawkSettings::instance()->acceptedLegalWarning() )
@@ -226,33 +358,49 @@ SipHandler::connectPlugins( bool startup, const QString &pluginName )
TomahawkSettings::instance()->setAcceptedLegalWarning( true );
}
#endif
- foreach( SipPlugin* sip, m_plugins )
+ foreach( SipPlugin* sip, m_allPlugins )
{
- if ( pluginName.isEmpty() || ( !pluginName.isEmpty() && sip->name() == pluginName ) )
+ if ( sip->pluginId() == pluginId )
+ {
+ Q_ASSERT( m_enabledPlugins.contains( sip ) ); // make sure the plugin we're connecting is enabled. should always be the case
sip->connectPlugin( startup );
- }
-
- if ( pluginName.isEmpty() )
- {
- m_connected = true;
+ }
}
}
void
-SipHandler::disconnectPlugins( const QString &pluginName )
+SipHandler::disconnectPlugin( const QString &pluginName )
{
- foreach( SipPlugin* sip, m_plugins )
+ foreach( SipPlugin* sip, m_connectedPlugins )
{
- if ( pluginName.isEmpty() || ( !pluginName.isEmpty() && sip->name() == pluginName ) )
+ if ( sip->name() == pluginName )
sip->disconnectPlugin();
}
+}
- if ( pluginName.isEmpty() )
- {
- SourceList::instance()->removeAllRemote();
- m_connected = false;
- }
+QList< SipPlugin* >
+SipHandler::allPlugins() const
+{
+ return m_allPlugins;
+}
+
+QList< SipPlugin* >
+SipHandler::enabledPlugins() const
+{
+ return m_enabledPlugins;
+}
+
+QList< SipPlugin* >
+SipHandler::connectedPlugins() const
+{
+ return m_connectedPlugins;
+}
+
+QList< SipPluginFactory* >
+SipHandler::pluginFactories() const
+{
+ return m_pluginFactories.values();
}
@@ -260,9 +408,9 @@ void
SipHandler::toggleConnect()
{
if( m_connected )
- disconnectPlugins();
+ disconnectAll();
else
- connectPlugins();
+ connectAll();
}
@@ -368,20 +516,43 @@ SipHandler::onMessage( const QString& from, const QString& msg )
void
SipHandler::onError( int code, const QString& msg )
{
- qWarning() << "Failed to connect to SIP:" << code << msg;
+ SipPlugin* sip = qobject_cast< SipPlugin* >( sender() );
+ Q_ASSERT( sip );
+
+ qWarning() << "Failed to connect to SIP:" << sip->accountName() << code << msg;
if ( code == SipPlugin::AuthError )
{
- emit authError();
+ emit authError( sip );
}
else
{
- SipPlugin* sip = qobject_cast(sender());
QTimer::singleShot( 10000, sip, SLOT( connectPlugin() ) );
}
}
-void SipHandler::onAvatarReceived( const QString& from, const QPixmap& avatar )
+void
+SipHandler::onStateChanged( SipPlugin::ConnectionState state )
+{
+ SipPlugin* sip = qobject_cast< SipPlugin* >( sender() );
+ Q_ASSERT( sip );
+
+ if ( sip->connectionState() == SipPlugin::Disconnected )
+ {
+ m_connectedPlugins.removeAll( sip );
+ emit disconnected( sip );
+ } else if ( sip->connectionState() == SipPlugin::Connected )
+ {
+ m_connectedPlugins.removeAll( sip );
+ emit disconnected( sip );
+ }
+
+ emit stateChanged( sip, state );
+}
+
+
+void
+SipHandler::onAvatarReceived( const QString& from, const QPixmap& avatar )
{
qDebug() << Q_FUNC_INFO << "Set avatar on source for " << from;
Q_ASSERT(!avatar.isNull());
@@ -413,8 +584,23 @@ void SipHandler::onAvatarReceived( const QString& from, const QPixmap& avatar )
}
}
-void SipHandler::onAvatarReceived( const QPixmap& avatar )
+void
+SipHandler::onAvatarReceived( const QPixmap& avatar )
{
qDebug() << Q_FUNC_INFO << "Set own avatar on MyCollection";
SourceList::instance()->getLocal()->setAvatar( avatar );
}
+
+
+QString
+SipHandler::factoryFromId( const QString& pluginId ) const
+{
+ return pluginId.split( "_" ).first();
+}
+
+SipPluginFactory*
+SipHandler::factoryFromPlugin( SipPlugin* p ) const
+{
+ QString factoryId = factoryFromId( p->pluginId() );
+ return m_pluginFactories.value( factoryId, 0 );
+}
diff --git a/src/libtomahawk/sip/SipHandler.h b/src/libtomahawk/sip/SipHandler.h
index 1c1c6f5bc..e108c1d28 100644
--- a/src/libtomahawk/sip/SipHandler.h
+++ b/src/libtomahawk/sip/SipHandler.h
@@ -38,28 +38,56 @@ public:
SipHandler( QObject* parent );
~SipHandler();
- QList< SipPlugin* > plugins() const;
+ QList< SipPluginFactory* > pluginFactories() const;
+ QList< SipPlugin* > allPlugins() const;
+ QList< SipPlugin* > enabledPlugins() const;
+ QList< SipPlugin* > connectedPlugins() const;
+ void loadFromConfig( bool startup = false );
+
+ void addSipPlugin( SipPlugin* p, bool enable = true, bool connectImmediately = true );
+ void removeSipPlugin( SipPlugin* p );
+
+ bool hasPluginType( const QString& factoryId ) const;
+ SipPluginFactory* factoryFromPlugin( SipPlugin* p ) const;
const QPixmap avatar( const QString& name ) const;
public slots:
- void addContact( const QString& id ) { qDebug() << Q_FUNC_INFO << id; }
-
void checkSettings();
- void connectPlugins( bool startup = false, const QString &pluginName = QString() );
- void disconnectPlugins( const QString &pluginName = QString() );
+
+ void enablePlugin( SipPlugin* p );
+ void disablePlugin( SipPlugin* p );
+
+ void connectPlugin( bool startup = false, const QString &pluginId = QString() );
+ void disconnectPlugin( const QString &pluginId = QString() );
+ void connectAll();
+ void disconnectAll();
+
void toggleConnect();
+ // create a new plugin of the given name. the name is the value returned in SipPluginFactory::pluginName
+ // be default sip plugins are NOt connected when created
+ SipPlugin* createPlugin( const QString& factoryName );
+ // load a plugin with the given id
+ SipPlugin* loadPlugin( const QString& pluginId );
+ void removePlugin( SipPlugin* p );
+
signals:
- void connected();
- void disconnected();
- void authError();
+ void connected( SipPlugin* );
+ void disconnected( SipPlugin* );
+ void authError( SipPlugin* );
+
+ void stateChanged( SipPlugin* p, SipPlugin::ConnectionState state );
+
+ void pluginAdded( SipPlugin* p );
+ void pluginRemoved( SipPlugin* p );
private slots:
void onMessage( const QString&, const QString& );
void onPeerOffline( const QString& );
void onPeerOnline( const QString& );
void onError( int code, const QString& msg );
+ void onStateChanged( SipPlugin::ConnectionState );
void onSettingsChanged();
@@ -73,13 +101,18 @@ private slots:
private:
static SipHandler *s_instance;
- QStringList findPlugins();
- bool pluginLoaded( const QString& name ) const;
+ QStringList findPluginFactories();
+ bool pluginLoaded( const QString& pluginId ) const;
+ void hookUpPlugin( SipPlugin* p );
- void loadPlugins( const QStringList& paths );
- void loadPlugin( const QString& path );
+ void loadPluginFactories( const QStringList& paths );
+ void loadPluginFactory( const QString& path );
+ QString factoryFromId( const QString& pluginId ) const;
- QList< SipPlugin* > m_plugins;
+ QHash< QString, SipPluginFactory* > m_pluginFactories;
+ QList< SipPlugin* > m_allPlugins;
+ QList< SipPlugin* > m_enabledPlugins;
+ QList< SipPlugin* > m_connectedPlugins;
bool m_connected;
diff --git a/src/libtomahawk/sip/SipModel.cpp b/src/libtomahawk/sip/SipModel.cpp
new file mode 100644
index 000000000..8ac36cbcb
--- /dev/null
+++ b/src/libtomahawk/sip/SipModel.cpp
@@ -0,0 +1,213 @@
+/*
+ Copyright (C) 2011 Leo Franchi
+
+ 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 .
+*/
+
+
+#include "SipModel.h"
+
+#include "tomahawksettings.h"
+#include "tomahawk/tomahawkapp.h"
+#include "sip/SipHandler.h"
+#include "sip/SipPlugin.h"
+
+SipModel::SipModel( QObject* parent )
+ : QAbstractItemModel( parent )
+{
+ connect( SipHandler::instance(), SIGNAL( stateChanged( SipPlugin*, SipPlugin::ConnectionState ) ), this, SLOT( pluginStateChanged( SipPlugin* ) ) );
+ connect( SipHandler::instance(), SIGNAL( pluginAdded( SipPlugin* ) ), this, SLOT( pluginAdded( SipPlugin* ) ) );
+ connect( SipHandler::instance(), SIGNAL( pluginRemoved( SipPlugin* ) ), this, SLOT( pluginRemoved( SipPlugin* ) ) );
+
+ // TODO disable inline factories for now
+ /*
+ foreach( SipPluginFactory* f, SipHandler::instance()->pluginFactories() ) {
+ if( f->isCreatable() )
+ m_factories << f;
+ } */
+
+}
+
+
+SipModel::~SipModel()
+{
+
+}
+
+QVariant
+SipModel::data( const QModelIndex& index, int role ) const
+{
+ if( !index.isValid() )
+ return QVariant();
+
+ if( !index.parent().isValid() && index.row() == SipHandler::instance()->allPlugins().count() ) { // last row, this is the factory
+ if( role == Qt::DisplayRole )
+ return tr( "Add New Account..." );
+ else if( role == FactoryRole )
+ return true;
+ else
+ return QVariant();
+ }
+
+ if( !index.parent().isValid() ) { // account
+ QList< SipPlugin* > plugins = SipHandler::instance()->allPlugins();
+ Q_ASSERT( index.row() <= plugins.size() );
+ SipPlugin* p = plugins[ index.row() ];
+ switch( role )
+ {
+ case Qt::DisplayRole:
+ case SipModel::PluginName:
+ 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 SipModel::SipPluginData:
+ return QVariant::fromValue< QObject* >( p );
+ case Qt::CheckStateRole:
+ return SipHandler::instance()->enabledPlugins().contains( p ) ? Qt::Checked : Qt::Unchecked;
+ default:
+ return QVariant();
+ }
+ }
+
+ if( index.parent().isValid() ) { // this is a factory type
+ SipPluginFactory* p = m_factories.at( index.row() );
+ switch( role )
+ {
+ case Qt::DisplayRole:
+ return p->prettyName();
+ case SipModel::FactoryItemRole:
+ return true;
+ case SipModel::FactoryItemIcon:
+ return p->icon();
+ case SipModel::SipPluginFactoryData:
+ return QVariant::fromValue< QObject* >( p );
+ default:
+ return QVariant();
+ }
+ }
+
+ return QVariant();
+}
+
+bool
+SipModel::setData( const QModelIndex& index, const QVariant& value, int role )
+{
+ Q_ASSERT( index.isValid() && index.row() <= SipHandler::instance()->allPlugins().count() );
+
+ if( role == Qt::CheckStateRole ) {
+ Qt::CheckState state = static_cast< Qt::CheckState >( value.toInt() );
+ QList< SipPlugin* > plugins = SipHandler::instance()->allPlugins();
+ SipPlugin* p = plugins[ index.row() ];
+
+ if( state == Qt::Checked && !SipHandler::instance()->enabledPlugins().contains( p ) ) {
+ SipHandler::instance()->enablePlugin( p );
+ } else if( state == Qt::Unchecked ) {
+ SipHandler::instance()->disablePlugin( p );
+ }
+ dataChanged( index, index );
+
+ return true;
+ }
+ 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();
+
+// qDebug() << "Creating index for non-top level row!";
+ // it's a child of the Add Account, e.g. a factory
+ if( hasIndex( row, column, parent ) ) {
+ return createIndex( row, column, 1 /* magic */ );
+ }
+
+ return QModelIndex();
+}
+
+QModelIndex
+SipModel::parent( const QModelIndex& child ) const
+{
+ if( !child.isValid() )
+ return QModelIndex();
+
+ if( child.internalId() == 1 ) {
+ return index( SipHandler::instance()->allPlugins().size(), 0, QModelIndex() );
+ }
+
+ return QModelIndex();
+}
+
+int
+SipModel::rowCount( const QModelIndex& parent ) const
+{
+ if( !parent.isValid() ) // invalid root node
+ return SipHandler::instance()->allPlugins().size() /* TODO inline factories disabled + 1*/;
+ if( parent.isValid() && !parent.parent().isValid() ) { // top level item
+ if( parent.row() == SipHandler::instance()->allPlugins().count() ) {// last row, this is the factory
+ return m_factories.count();
+ }
+ }
+
+ return 0;
+}
+
+int
+SipModel::columnCount(const QModelIndex& parent) const
+{
+ Q_UNUSED( parent );
+ return 1;
+}
+
+Qt::ItemFlags
+SipModel::flags( const QModelIndex& index ) const
+{
+ if( index.data( SipModel::FactoryRole ).toBool() || index.data( SipModel::FactoryItemRole ).toBool() )
+ return QAbstractItemModel::flags( index ) & ~Qt::ItemIsSelectable;
+ return QAbstractItemModel::flags( index ) | Qt::ItemIsUserCheckable;
+}
+
+void
+SipModel::pluginAdded( SipPlugin* p )
+{
+ // we assume sip plugins are added at the end of the list.
+ Q_ASSERT( SipHandler::instance()->allPlugins().last() == p );
+ int size = SipHandler::instance()->allPlugins().count() - 1;
+ beginInsertRows( QModelIndex(), size, size );
+ endInsertRows();
+}
+
+void
+SipModel::pluginRemoved( SipPlugin* p )
+{
+ int idx = SipHandler::instance()->allPlugins().indexOf( p );
+ beginRemoveRows( QModelIndex(), idx, idx );
+ endRemoveRows();
+}
+
+void
+SipModel::pluginStateChanged( SipPlugin* p )
+{
+ int at = SipHandler::instance()->allPlugins().indexOf( p );
+ QModelIndex idx = index( at, 0, QModelIndex() );
+ emit dataChanged( idx, idx );
+}
+
diff --git a/src/libtomahawk/sip/SipModel.h b/src/libtomahawk/sip/SipModel.h
new file mode 100644
index 000000000..18e15cf0b
--- /dev/null
+++ b/src/libtomahawk/sip/SipModel.h
@@ -0,0 +1,67 @@
+/*
+
+ Copyright (C) 2011 Leo Franchi
+
+ 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 .
+*/
+
+
+#ifndef SIPMODEL_H
+#define SIPMODEL_H
+
+#include "dllmacro.h"
+
+#include
+#include
+
+class SipPluginFactory;
+class SipPlugin;
+
+class DLLEXPORT SipModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ enum Roles {
+ PluginName = Qt::UserRole + 15,
+ ConnectionStateRole = Qt::UserRole + 17,
+ HasConfig = Qt::UserRole + 18,
+ FactoryRole = Qt::UserRole + 19,
+ ErrorString = Qt::UserRole + 20,
+ FactoryItemRole = Qt::UserRole + 21,
+ FactoryItemIcon = Qt::UserRole + 22,
+ SipPluginData = Qt::UserRole + 23,
+ SipPluginFactoryData = Qt::UserRole + 24
+ };
+
+ 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;
+ virtual Qt::ItemFlags flags(const QModelIndex& index) const;
+ virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
+
+private slots:
+ void pluginAdded( SipPlugin* p );
+ void pluginRemoved( SipPlugin* p );
+ void pluginStateChanged( SipPlugin* p );
+
+private:
+ QList< SipPluginFactory* > m_factories;
+};
+
+#endif // SIPMODEL_H
diff --git a/src/libtomahawk/sip/SipPlugin.cpp b/src/libtomahawk/sip/SipPlugin.cpp
index bb849637f..1bde2db64 100644
--- a/src/libtomahawk/sip/SipPlugin.cpp
+++ b/src/libtomahawk/sip/SipPlugin.cpp
@@ -17,7 +17,28 @@
* along with Tomahawk. If not, see .
*/
-#include
+#include "sip/SipPlugin.h"
+
+#include
+
+QString
+SipPluginFactory::generateId()
+{
+ QString uniq = QUuid::createUuid().toString().mid( 1, 8 );
+ return factoryId() + "_" + uniq;
+}
+
+SipPlugin::SipPlugin( const QString& pluginId, QObject* parent )
+ : QObject( parent )
+ , m_pluginId( pluginId )
+{
+
+}
+
+QString SipPlugin::pluginId() const
+{
+ return m_pluginId;
+}
QMenu*
@@ -33,8 +54,20 @@ SipPlugin::configWidget()
return 0;
}
+QString
+SipPlugin::errorMessage() const
+{
+ return QString();
+}
+
+QIcon
+SipPlugin::icon() const
+{
+ return QIcon();
+}
+
void
SipPlugin::setProxy( const QNetworkProxy& proxy )
{
qDebug() << Q_FUNC_INFO << "Not implemented";
-}
\ No newline at end of file
+}
diff --git a/src/libtomahawk/sip/SipPlugin.h b/src/libtomahawk/sip/SipPlugin.h
index bc7640349..d50647412 100644
--- a/src/libtomahawk/sip/SipPlugin.h
+++ b/src/libtomahawk/sip/SipPlugin.h
@@ -28,21 +28,53 @@
#include "dllmacro.h"
+class SipPlugin;
+
+class DLLEXPORT SipPluginFactory : public QObject
+{
+ Q_OBJECT
+public:
+ SipPluginFactory() {}
+ virtual ~SipPluginFactory() {}
+
+ // display name for plugin
+ virtual QString prettyName() const = 0;
+ // internal name
+ virtual QString factoryId() const = 0;
+ // if the user can create multiple
+ virtual QIcon icon() const { return QIcon(); }
+ virtual bool isUnique() const { return false; }
+
+ virtual SipPlugin* createPlugin( const QString& pluginId = QString() ) = 0;
+
+protected:
+ QString generateId();
+};
+
class DLLEXPORT SipPlugin : public QObject
{
Q_OBJECT
public:
enum SipErrorCode { AuthError, ConnectionError }; // Placeholder for errors, to be defined
+ enum ConnectionState { Disconnected, Connecting, Connected };
+ explicit SipPlugin( const QString& pluginId, QObject* parent = 0 );
virtual ~SipPlugin() {}
- virtual bool isValid() = 0;
- virtual const QString name() = 0;
- virtual const QString friendlyName() = 0;
- virtual const QString accountName() = 0;
+ // plugin id is "pluginfactoryname_someuniqueid". get it from SipPluginFactory::generateId
+ QString pluginId() const;
+
+ virtual bool isValid() const = 0;
+ virtual const QString name() const = 0;
+ 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 void saveConfig() {} // called when the widget has been edited
+ virtual QIcon icon() const;
public slots:
virtual bool connectPlugin( bool startup = false ) = 0;
@@ -56,8 +88,7 @@ public slots:
signals:
void error( int, const QString& );
- void connected();
- void disconnected();
+ void stateChanged( SipPlugin::ConnectionState state );
void peerOnline( const QString& );
void peerOffline( const QString& );
@@ -72,8 +103,11 @@ signals:
void addMenu( QMenu* menu );
void removeMenu( QMenu* menu );
+
+private:
+ QString m_pluginId;
};
-Q_DECLARE_INTERFACE( SipPlugin, "tomahawk.Sip/1.0" )
+Q_DECLARE_INTERFACE( SipPluginFactory, "tomahawk.SipFactory/1.0" )
#endif
diff --git a/src/libtomahawk/tomahawksettings.cpp b/src/libtomahawk/tomahawksettings.cpp
index 9e89383ac..23072ef28 100644
--- a/src/libtomahawk/tomahawksettings.cpp
+++ b/src/libtomahawk/tomahawksettings.cpp
@@ -25,8 +25,9 @@
#include
#include
+#include "sip/SipHandler.h"
-#define VERSION 2
+#define VERSION 3
TomahawkSettings* TomahawkSettings::s_instance = 0;
@@ -46,6 +47,7 @@ TomahawkSettings::TomahawkSettings( QObject* parent )
if( !contains( "configversion") )
{
setValue( "configversion", VERSION );
+ doInitialSetup();
}
else if( value( "configversion" ).toUInt() != VERSION )
{
@@ -53,11 +55,15 @@ TomahawkSettings::TomahawkSettings( QObject* parent )
<< "new:" << VERSION
<< "Doing upgrade, if any...";
+ int current = value( "configversion" ).toUInt();
+ while( current < VERSION )
+ {
+ doUpgrade( current, current + 1 );
+
+ current++;
+ }
// insert upgrade code here as required
setValue( "configversion", VERSION );
- if( contains( "script/resolvers") ) {
- setValue( "script/loadedresolvers", value( "script/resolvers" ) );
- }
}
}
@@ -67,6 +73,71 @@ TomahawkSettings::~TomahawkSettings()
s_instance = 0;
}
+void
+TomahawkSettings::doInitialSetup()
+{
+ // by default we add a local network resolver
+ addSipPlugin( "sipzeroconf_autocreated" );
+}
+
+
+void
+TomahawkSettings::doUpgrade( int oldVersion, int newVersion )
+{
+ Q_UNUSED( newVersion );
+
+ if( oldVersion == 1 )
+ {
+ qDebug() << "Migrating config from verson 1 to 2: script resolver config name";
+ if( contains( "script/resolvers" ) ) {
+ setValue( "script/loadedresolvers", value( "script/resolvers" ) );
+ remove( "script/resolvers" );
+ }
+ } else if( oldVersion == 2 )
+ {
+ qDebug() << "Migrating config from version 2 to 3: Converting jabber and twitter accounts to new SIP Factory approach";
+ // migrate old accounts to new system. only jabber and twitter, and max one each. create a new plugin for each if needed
+ // not pretty as we hardcode a plugin id and assume that we know how the config layout is, but hey, this is migration after all
+ if( contains( "jabber/username" ) && contains( "jabber/password" ) )
+ {
+ setValue( "sipjabber_legacy/username", value( "jabber/username" ) );
+ setValue( "sipjabber_legacy/password", value( "jabber/password" ) );
+ setValue( "sipjabber_legacy/autoconnect", value( "jabber/autoconnect" ) );
+ setValue( "sipjabber_legacy/port", value( "jabber/port" ) );
+ setValue( "sipjabber_legacy/server", value( "jabber/server" ) );
+
+ addSipPlugin( "sipjabber_legacy" );
+
+ remove( "jabber/username" );
+ remove( "jabber/password" );
+ remove( "jabber/autoconnect" );
+ remove( "jabber/server" );
+ remove( "jabber/port" );
+ }
+ if( contains( "twitter/ScreenName" ) && contains( "twitter/OAuthToken" ) )
+ {
+ setValue( "siptwitter_legacy/ScreenName", value( "twitter/ScreenName" ) );
+ setValue( "siptwitter_legacy/OAuthToken", value( "twitter/OAuthToken" ) );
+ setValue( "siptwitter_legacy/OAuthTokenSecret", value( "twitter/OAuthTokenSecret" ) );
+ setValue( "siptwitter_legacy/CachedFriendsSinceID", value( "twitter/CachedFriendsSinceID" ) );
+ setValue( "siptwitter_legacy/CachedMentionsSinceID", value( "twitter/CachedMentionsSinceID" ) );
+ setValue( "siptwitter_legacy/CachedDirectMessagesSinceID", value( "twitter/CachedDirectMessagesSinceID" ) );
+ setValue( "siptwitter_legacy/CachedPeers", value( "twitter/CachedPeers" ) );
+ setValue( "siptwitter_legacy/AutoConnect", value( "jabber/autoconnect" ) );
+
+ addSipPlugin( "siptwitter_legacy" );
+ remove( "twitter/ScreenName" );
+ remove( "twitter/OAuthToken" );
+ remove( "twitter/OAuthTokenSecret" );
+ remove( "twitter/CachedFriendsSinceID" );
+ remove( "twitter/CachedMentionsSinceID" );
+ remove( "twitter/CachedDirectMessagesSinceID" );
+ }
+ // create a zeroconf plugin too
+ addSipPlugin( "sipzeroconf_legacy" );
+ }
+}
+
QStringList
TomahawkSettings::scannerPaths()
@@ -326,76 +397,66 @@ TomahawkSettings::setBookmarkPlaylist( const QString& guid )
setValue( "playlists/bookmark", guid );
}
-
-bool
-TomahawkSettings::jabberAutoConnect() const
+QStringList
+TomahawkSettings::sipPlugins() const
{
- return value( "jabber/autoconnect", true ).toBool();
+ return value( "sip/allplugins", QStringList() ).toStringList();
}
-
void
-TomahawkSettings::setJabberAutoConnect( bool autoconnect )
+TomahawkSettings::setSipPlugins( const QStringList& plugins )
{
- setValue( "jabber/autoconnect", autoconnect );
+ setValue( "sip/allplugins", plugins );
}
-
-unsigned int
-TomahawkSettings::jabberPort() const
+QStringList
+TomahawkSettings::enabledSipPlugins() const
{
- return value( "jabber/port", 5222 ).toUInt();
+ return value( "sip/enabledplugins", QStringList() ).toStringList();
}
-
void
-TomahawkSettings::setJabberPort( int port )
+TomahawkSettings::setEnabledSipPlugins( const QStringList& list )
{
- if ( port < 0 )
- return;
- setValue( "jabber/port", port );
+ setValue( "sip/enabledplugins", list );
}
-
-QString
-TomahawkSettings::jabberServer() const
-{
- return value( "jabber/server" ).toString();
-}
-
-
void
-TomahawkSettings::setJabberServer( const QString& server )
+TomahawkSettings::enableSipPlugin( const QString& pluginId )
{
- setValue( "jabber/server", server );
+ QStringList list = enabledSipPlugins();
+ list << pluginId;
+ setEnabledSipPlugins( list );
}
-
-QString
-TomahawkSettings::jabberUsername() const
-{
- return value( "jabber/username" ).toString();
-}
-
-
void
-TomahawkSettings::setJabberUsername( const QString& username )
+TomahawkSettings::disableSipPlugin( const QString& pluginId )
{
- setValue( "jabber/username", username );
+ QStringList list = enabledSipPlugins();
+ list.removeAll( pluginId );
+ setEnabledSipPlugins( list );
}
-
-QString
-TomahawkSettings::jabberPassword() const
-{
- return value( "jabber/password" ).toString();
-}
-
-
void
-TomahawkSettings::setJabberPassword( const QString& pw )
+TomahawkSettings::addSipPlugin( const QString& pluginId, bool enable )
{
- setValue( "jabber/password", pw );
+ QStringList list = sipPlugins();
+ list << pluginId;
+ setSipPlugins( list );
+
+ if ( enable )
+ enableSipPlugin( pluginId );
+}
+
+void
+TomahawkSettings::removeSipPlugin( const QString& pluginId )
+{
+ QStringList list = sipPlugins();
+ list.removeAll( pluginId );
+ setSipPlugins( list );
+
+ if( enabledSipPlugins().contains( pluginId ) )
+ disableSipPlugin( pluginId );
}
@@ -497,90 +558,6 @@ TomahawkSettings::setLastFmUsername( const QString& username )
setValue( "lastfm/username", username );
}
-QString
-TomahawkSettings::twitterScreenName() const
-{
- return value( "twitter/ScreenName" ).toString();
-}
-
-void
-TomahawkSettings::setTwitterScreenName( const QString& screenName )
-{
- setValue( "twitter/ScreenName", screenName );
-}
-
-QString
-TomahawkSettings::twitterOAuthToken() const
-{
- return value( "twitter/OAuthToken" ).toString();
-}
-
-void
-TomahawkSettings::setTwitterOAuthToken( const QString& oauthtoken )
-{
- setValue( "twitter/OAuthToken", oauthtoken );
-}
-
-QString
-TomahawkSettings::twitterOAuthTokenSecret() const
-{
- return value( "twitter/OAuthTokenSecret" ).toString();
-}
-
-void
-TomahawkSettings::setTwitterOAuthTokenSecret( const QString& oauthtokensecret )
-{
- setValue( "twitter/OAuthTokenSecret", oauthtokensecret );
-}
-
-qint64
-TomahawkSettings::twitterCachedFriendsSinceId() const
-{
- return value( "twitter/CachedFriendsSinceID", 0 ).toLongLong();
-}
-
-void
-TomahawkSettings::setTwitterCachedFriendsSinceId( qint64 cachedId )
-{
- setValue( "twitter/CachedFriendsSinceID", cachedId );
-}
-
-qint64
-TomahawkSettings::twitterCachedMentionsSinceId() const
-{
- return value( "twitter/CachedMentionsSinceID", 0 ).toLongLong();
-}
-
-void
-TomahawkSettings::setTwitterCachedMentionsSinceId( qint64 cachedId )
-{
- setValue( "twitter/CachedMentionsSinceID", cachedId );
-}
-
-qint64
-TomahawkSettings::twitterCachedDirectMessagesSinceId() const
-{
- return value( "twitter/CachedDirectMessagesSinceID", 0 ).toLongLong();
-}
-
-void
-TomahawkSettings::setTwitterCachedDirectMessagesSinceId( qint64 cachedId )
-{
- setValue( "twitter/CachedDirectMessagesSinceID", cachedId );
-}
-
-QHash
-TomahawkSettings::twitterCachedPeers() const
-{
- return value( "twitter/CachedPeers", QHash() ).toHash();
-}
-
-void
-TomahawkSettings::setTwitterCachedPeers( const QHash &cachedPeers )
-{
- setValue( "twitter/CachedPeers", cachedPeers );
-}
-
bool
TomahawkSettings::scrobblingEnabled() const
{
diff --git a/src/libtomahawk/tomahawksettings.h b/src/libtomahawk/tomahawksettings.h
index c9a91391c..366355bb4 100644
--- a/src/libtomahawk/tomahawksettings.h
+++ b/src/libtomahawk/tomahawksettings.h
@@ -69,24 +69,22 @@ public:
QStringList recentlyPlayedPlaylistGuids() const;
void appendRecentlyPlayedPlaylist( const Tomahawk::playlist_ptr& playlist );
+ /// SIP plugins
+ // all plugins we know about. loaded, unloaded, enabled, disabled.
+ void setSipPlugins( const QStringList& plugins );
+ QStringList sipPlugins() const;
+
void setBookmarkPlaylist( const QString& guid );
QString bookmarkPlaylist() const;
- /// Jabber settings
- bool jabberAutoConnect() const; /// true by default
- void setJabberAutoConnect( bool autoconnect = false );
+ // just the enabled sip plugins.
+ void setEnabledSipPlugins( const QStringList& list );
+ QStringList enabledSipPlugins() const;
+ void enableSipPlugin( const QString& pluginId );
+ void disableSipPlugin( const QString& pluginId );
- QString jabberUsername() const;
- void setJabberUsername( const QString& username );
-
- QString jabberPassword() const;
- void setJabberPassword( const QString& pw );
-
- QString jabberServer() const;
- void setJabberServer( const QString& server );
-
- unsigned int jabberPort() const; // default is 5222
- void setJabberPort( int port );
+ void addSipPlugin( const QString& pluginId, bool enable = true );
+ void removeSipPlugin( const QString& pluginId );
/// Network settings
enum ExternalAddressMode { Lan, Upnp };
@@ -138,28 +136,6 @@ public:
QByteArray lastFmSessionKey() const;
void setLastFmSessionKey( const QByteArray& key );
- /// Twitter settings
- 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 );
-
- QHash twitterCachedPeers() const;
- void setTwitterCachedPeers( const QHash &cachedPeers );
-
/// XMPP Component Settings
QString xmppBotServer() const;
void setXmppBotServer( const QString &server );
@@ -186,6 +162,9 @@ signals:
void recentlyPlayedPlaylistAdded( const Tomahawk::playlist_ptr& playlist );
private:
+ void doInitialSetup();
+ void doUpgrade( int oldVersion, int newVersion );
+
static TomahawkSettings* s_instance;
};
diff --git a/src/resolverconfigdelegate.cpp b/src/resolverconfigdelegate.cpp
index 0f98e49f8..dc291a69b 100644
--- a/src/resolverconfigdelegate.cpp
+++ b/src/resolverconfigdelegate.cpp
@@ -27,12 +27,11 @@
#include
#define PADDING 4
-
+#define ICONSIZE 24
ResolverConfigDelegate::ResolverConfigDelegate( QObject* parent )
- : QStyledItemDelegate( parent )
- , m_configPressed( false )
+ : ConfigDelegateBase( parent )
{
-
+ connect( this, SIGNAL( configPressed( QModelIndex ) ), this, SLOT( onConfigPressed( QModelIndex ) ) );
}
void
@@ -61,36 +60,31 @@ 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;
- QRect confRect = QRect( rightSplit - rectW - 2 * PADDING, 2 * PADDING + top, rectW, rectW );
+ QRect confRect = QRect( rightSplit - ICONSIZE - 2 * PADDING, 2 * PADDING + top, ICONSIZE, ICONSIZE );
+
// 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 +100,21 @@ ResolverConfigDelegate::paint( QPainter* painter, const QStyleOptionViewItem& op
}
-QSize
-ResolverConfigDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
+QRect
+ResolverConfigDelegate::configRectForIndex( const QStyleOptionViewItem& option, const QModelIndex& idx ) const
{
- int width = QStyledItemDelegate::sizeHint( option, index ).width();
-
QStyleOptionViewItemV4 opt = option;
- initStyleOption( &opt, index );
+ initStyleOption( &opt, idx );
+ QRect itemRect = opt.rect;
+ int top = itemRect.top();
-
- 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() );
+ QRect confRect = QRect( itemRect.width() - ICONSIZE - 2 * PADDING, 2 * PADDING + top, ICONSIZE, ICONSIZE );
+ return confRect;
}
-bool
-ResolverConfigDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
+
+void
+ResolverConfigDelegate::onConfigPressed( const QModelIndex& idx )
{
-// 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..b376044bf 100644
--- a/src/resolverconfigdelegate.h
+++ b/src/resolverconfigdelegate.h
@@ -20,23 +20,22 @@
#ifndef RESOLVERCONFIGDELEGATE_H
#define RESOLVERCONFIGDELEGATE_H
-#include
+#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 );
+ virtual QRect configRectForIndex ( const QStyleOptionViewItem& option, const QModelIndex& idx ) const;
+
+private slots:
+ void onConfigPressed ( const QModelIndex& );
signals:
void openConfig( const QString& resolverPath );
-
-private:
- bool m_configPressed;
};
#endif // RESOLVERCONFIGDELEGATE_H
diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp
index fee043b4b..82466d9e0 100644
--- a/src/settingsdialog.cpp
+++ b/src/settingsdialog.cpp
@@ -32,7 +32,6 @@
#endif
#include "settingsdialog.h"
-#include "ui_settingsdialog.h"
#include "ui_proxydialog.h"
#include "tomahawk/tomahawkapp.h"
#include "musicscanner.h"
@@ -42,7 +41,11 @@
#include "scanmanager.h"
#include "resolverconfigdelegate.h"
#include "resolversmodel.h"
-#include "resolverconfigwrapper.h"
+#include "delegateconfigwrapper.h"
+#include "sip/SipModel.h"
+#include "sipconfigdelegate.h"
+
+#include "ui_stackedsettingsdialog.h"
static QString
md5( const QByteArray& src )
@@ -53,10 +56,12 @@ md5( const QByteArray& src )
SettingsDialog::SettingsDialog( QWidget *parent )
: QDialog( parent )
- , ui( new Ui::SettingsDialog )
+ , ui( new Ui_StackedSettingsDialog )
, m_proxySettings( this )
, m_rejected( false )
, m_testLastFmQuery( 0 )
+ , m_sipModel( 0 )
+ , m_resolversModel( 0 )
{
ui->setupUi( this );
TomahawkSettings* s = TomahawkSettings::instance();
@@ -66,32 +71,37 @@ SettingsDialog::SettingsDialog( QWidget *parent )
ui->checkBoxUpnp->setChecked( s->externalAddressMode() == TomahawkSettings::Upnp );
ui->checkBoxUpnp->setEnabled( !s->preferStaticHostPort() );
- // JABBER
- ui->checkBoxJabberAutoConnect->setChecked( s->jabberAutoConnect() );
- ui->jabberUsername->setText( s->jabberUsername() );
- ui->jabberPassword->setText( s->jabberPassword() );
- ui->jabberServer->setText( s->jabberServer() );
- ui->jabberPort->setValue( s->jabberPort() );
+ createIcons();
+#ifdef Q_WS_X11
+ ui->listWidget->setFrameShape( QFrame::StyledPanel );
+ ui->listWidget->setFrameShadow( QFrame::Sunken );
+ setContentsMargins( 4, 4, 4, 4 );
+#else
+ ui->verticalLayout->removeItem( ui->verticalSpacer_3 );
+#endif
+
+ // SIP PLUGINS
+ SipConfigDelegate* sipdel = new SipConfigDelegate( this );
+ ui->accountsView->setItemDelegate( sipdel );
+ ui->accountsView->setContextMenuPolicy( Qt::CustomContextMenu );
+
+ connect( ui->accountsView, SIGNAL( clicked( QModelIndex ) ), this, SLOT( sipItemClicked( QModelIndex ) ) );
+ connect( sipdel, SIGNAL( openConfig( SipPlugin* ) ), this, SLOT( openSipConfig( SipPlugin* ) ) );
+ connect( ui->accountsView, SIGNAL( customContextMenuRequested( QPoint ) ), this, SLOT( sipContextMenuRequest( QPoint ) ) );
+ m_sipModel = new SipModel( this );
+ ui->accountsView->setModel( m_sipModel );
+
+ setupSipButtons();
ui->staticHostName->setText( s->externalHostname() );
ui->staticPort->setValue( s->externalPort() );
ui->proxyButton->setVisible( false );
- // SIP PLUGINS
- foreach(SipPlugin *plugin, APP->sipHandler()->plugins())
- {
- if(plugin->configWidget())
- {
- qDebug() << "Adding configWidget for " << plugin->name();
- ui->tabWidget->addTab(plugin->configWidget(), plugin->friendlyName());
- }
- }
-
// MUSIC SCANNER
//FIXME: MULTIPLECOLLECTIONDIRS
if ( s->scannerPaths().count() )
- ui->lineEditMusicPath->setText( s->scannerPaths().first() );
+ ui->lineEditMusicPath_2->setText( s->scannerPaths().first() );
ui->checkBoxWatchForChanges->setChecked( s->watchForChanges() );
// LAST FM
@@ -112,10 +122,12 @@ SettingsDialog::SettingsDialog( QWidget *parent )
connect( ui->addScript, SIGNAL( clicked( bool ) ), this, SLOT( addScriptResolver() ) );
connect( ui->removeScript, SIGNAL( clicked( bool ) ), this, SLOT( removeScriptResolver() ) );
- connect( ui->buttonBrowse, SIGNAL( clicked() ), SLOT( showPathSelector() ) );
+ connect( ui->buttonBrowse_2, SIGNAL( clicked() ), SLOT( showPathSelector() ) );
connect( ui->proxyButton, SIGNAL( clicked() ), SLOT( showProxySettings() ) );
connect( ui->checkBoxStaticPreferred, SIGNAL( toggled(bool) ), SLOT( toggleUpnp(bool) ) );
connect( this, SIGNAL( rejected() ), SLOT( onRejected() ) );
+
+ ui->listWidget->setCurrentRow( 0 );
}
@@ -131,16 +143,10 @@ SettingsDialog::~SettingsDialog()
s->setPreferStaticHostPort( ui->checkBoxStaticPreferred->checkState() == Qt::Checked );
s->setExternalAddressMode( ui->checkBoxUpnp->checkState() == Qt::Checked ? TomahawkSettings::Upnp : TomahawkSettings::Lan );
- s->setJabberAutoConnect( ui->checkBoxJabberAutoConnect->checkState() == Qt::Checked );
- s->setJabberUsername( ui->jabberUsername->text() );
- s->setJabberPassword( ui->jabberPassword->text() );
- s->setJabberServer( ui->jabberServer->text() );
- s->setJabberPort( ui->jabberPort->value() );
-
s->setExternalHostname( ui->staticHostName->text() );
s->setExternalPort( ui->staticPort->value() );
- s->setScannerPaths( QStringList( ui->lineEditMusicPath->text() ) );
+ s->setScannerPaths( QStringList( ui->lineEditMusicPath_2->text() ) );
s->setWatchForChanges( ui->checkBoxWatchForChanges->isChecked() );
s->setScrobblingEnabled( ui->checkBoxEnableLastfm->isChecked() );
@@ -158,6 +164,93 @@ SettingsDialog::~SettingsDialog()
delete ui;
}
+void
+SettingsDialog::createIcons()
+{
+ /// Not fun but QListWidget sucks. Do our max-width calculation manually
+ /// so the icons arre lined up.
+ // Resolvers is the longest string... in english. fml.
+
+ int maxlen = 0;
+ QFontMetrics fm( font() );
+ QListWidgetItem *accountsButton = new QListWidgetItem( ui->listWidget );
+ accountsButton->setIcon( QIcon( RESPATH "images/account-settings.png" ) );
+ accountsButton->setText( tr( "Accounts" ) );
+ accountsButton->setTextAlignment( Qt::AlignHCenter );
+ accountsButton->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
+ maxlen = fm.width( accountsButton->text() );
+
+ QListWidgetItem *musicButton = new QListWidgetItem( ui->listWidget );
+ musicButton->setIcon( QIcon( RESPATH "images/music-settings.png" ) );
+ musicButton->setText( tr( "Music" ) );
+ musicButton->setTextAlignment( Qt::AlignHCenter );
+ musicButton->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
+ maxlen = qMax( fm.width( musicButton->text() ), maxlen );
+
+ QListWidgetItem *lastfmButton = new QListWidgetItem( ui->listWidget );
+ lastfmButton->setIcon( QIcon( RESPATH "images/lastfm-settings.png" ) );
+ lastfmButton->setText( tr( "Last.fm" ) );
+ lastfmButton->setTextAlignment( Qt::AlignHCenter );
+ lastfmButton->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
+ maxlen = qMax( fm.width( lastfmButton->text() ), maxlen );
+
+ QListWidgetItem *resolversButton = new QListWidgetItem( ui->listWidget );
+ resolversButton->setIcon( QIcon( RESPATH "images/resolvers-settings.png" ) );
+ resolversButton->setText( tr( "Resolvers" ) );
+ resolversButton->setTextAlignment( Qt::AlignHCenter );
+ resolversButton->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
+ maxlen = qMax( fm.width( resolversButton->text() ), maxlen );
+
+ QListWidgetItem *advancedButton = new QListWidgetItem( ui->listWidget );
+ advancedButton->setIcon( QIcon( RESPATH "images/advanced-settings.png" ) );
+ advancedButton->setText( tr( "Advanced" ) );
+ advancedButton->setTextAlignment( Qt::AlignHCenter );
+ advancedButton->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled );
+ maxlen = qMax( fm.width( advancedButton->text() ), maxlen );
+
+ maxlen += 15; // padding
+ accountsButton->setSizeHint( QSize( maxlen, 60 ) );
+ musicButton->setSizeHint( QSize( maxlen, 60 ) );
+ lastfmButton->setSizeHint( QSize( maxlen, 60 ) );
+ resolversButton->setSizeHint( QSize( maxlen, 60 ) );
+ advancedButton->setSizeHint( QSize( maxlen, 60 ) );
+
+#ifndef Q_WS_MAC
+ // doesn't listen to sizehint...
+ ui->listWidget->setMaximumWidth( maxlen + 8 );
+#endif
+
+ connect( ui->listWidget, SIGNAL( currentItemChanged( QListWidgetItem* ,QListWidgetItem* ) ), this, SLOT( changePage( QListWidgetItem*, QListWidgetItem* ) ) );
+}
+
+void
+SettingsDialog::setupSipButtons()
+{
+ foreach( SipPluginFactory* f, SipHandler::instance()->pluginFactories() ) {
+ if( f->isUnique() && SipHandler::instance()->hasPluginType( f->factoryId() ) ) {
+ continue;
+ }
+
+ QAction* action = new QAction( f->icon(), f->prettyName(), ui->addSipButton );
+ action->setProperty( "factory", QVariant::fromValue< QObject* >( f ) );
+ ui->addSipButton->addAction( action );
+
+ connect( action, SIGNAL( triggered(bool) ), this, SLOT( factoryActionTriggered( bool ) ) );
+ }
+
+ connect( ui->removeSipButton, SIGNAL( clicked( bool ) ), this, SLOT( sipPluginDeleted( bool ) ) );
+}
+
+
+void
+SettingsDialog::changePage( QListWidgetItem* current, QListWidgetItem* previous )
+{
+ if( !current )
+ current = previous;
+
+ ui->stackedWidget->setCurrentIndex( ui->listWidget->row(current) );
+}
+
void
SettingsDialog::showPathSelector()
@@ -171,7 +264,7 @@ SettingsDialog::showPathSelector()
if ( path.isEmpty() )
return;
- ui->lineEditMusicPath->setText( path );
+ ui->lineEditMusicPath_2->setText( path );
}
@@ -375,8 +468,8 @@ SettingsDialog::openResolverConfig( const QString& resolver )
{
Tomahawk::ExternalResolver* r = TomahawkApp::instance()->resolverForPath( resolver );
if( r && r->configUI() ) {
- ResolverConfigWrapper dialog( r->configUI(), "Resolver Config", this );
- QWeakPointer< ResolverConfigWrapper > watcher( &dialog );
+ DelegateConfigWrapper dialog( r->configUI(), "Resolver Config", this );
+ QWeakPointer< DelegateConfigWrapper > watcher( &dialog );
int ret = dialog.exec();
if( !watcher.isNull() && ret == QDialog::Accepted ) {
// send changed config to resolver
@@ -384,3 +477,140 @@ SettingsDialog::openResolverConfig( const QString& resolver )
}
}
}
+
+void
+SettingsDialog::sipItemClicked( const QModelIndex& item )
+{
+ if( item.data( SipModel::FactoryRole ).toBool() )
+ if( ui->accountsView->isExpanded( item ) )
+ ui->accountsView->collapse( item );
+ else
+ ui->accountsView->expand( item );
+ else if( item.data( SipModel::FactoryItemRole ).toBool() )
+ sipFactoryClicked( qobject_cast( item.data( SipModel::SipPluginFactoryData ).value< QObject* >() ) );
+}
+
+void
+SettingsDialog::openSipConfig( SipPlugin* p )
+{
+ if( p->configWidget() ) {
+ DelegateConfigWrapper dialog( p->configWidget(), QString("%1 Config" ).arg( p->friendlyName() ), this );
+ QWeakPointer< DelegateConfigWrapper > watcher( &dialog );
+ int ret = dialog.exec();
+ if( !watcher.isNull() && ret == QDialog::Accepted ) {
+ // send changed config to resolver
+ p->saveConfig();
+ }
+ }
+}
+
+void
+SettingsDialog::factoryActionTriggered( bool )
+{
+ Q_ASSERT( sender() && qobject_cast< QAction* >( sender() ) );
+
+ QAction* a = qobject_cast< QAction* >( sender() );
+ Q_ASSERT( qobject_cast< SipPluginFactory* >( a->property( "factory" ).value< QObject* >() ) );
+
+ SipPluginFactory* f = qobject_cast< SipPluginFactory* >( a->property( "factory" ).value< QObject* >() );
+ sipFactoryClicked( f );
+}
+
+
+void
+SettingsDialog::sipFactoryClicked( SipPluginFactory* factory )
+{
+ //if exited with OK, create it, if not, delete it immediately!
+ SipPlugin* p = factory->createPlugin();
+ bool added = false;
+ if( p->configWidget() ) {
+ DelegateConfigWrapper dialog( p->configWidget(), QString("%1 Config" ).arg( p->friendlyName() ), this );
+ QWeakPointer< DelegateConfigWrapper > watcher( &dialog );
+ int ret = dialog.exec();
+ if( !watcher.isNull() && ret == QDialog::Accepted ) {
+ // send changed config to resolver
+ p->saveConfig();
+
+ // accepted, so add it to tomahawk
+ TomahawkSettings::instance()->addSipPlugin( p->pluginId() );
+ SipHandler::instance()->addSipPlugin( p );
+
+ added = true;
+ } else {
+ // canceled, delete it
+ added = false;
+ }
+ } else {
+ // no config, so just add it
+ added = true;
+ TomahawkSettings::instance()->addSipPlugin( p->pluginId() );
+ SipHandler::instance()->addSipPlugin( p );
+ }
+
+ SipPluginFactory* f = SipHandler::instance()->factoryFromPlugin( p );
+ if( added && f && f->isUnique() ) {
+ // remove from actions list
+ QAction* toremove = 0;
+ foreach( QAction* a, ui->addSipButton->actions() )
+ {
+ if( f == qobject_cast< SipPluginFactory* >( a->property( "factory" ).value< QObject* >() ) )
+ {
+ toremove = a;
+ break;
+ }
+ }
+ if( toremove )
+ ui->addSipButton->removeAction( toremove );
+ } else if( added == false ) { // user pressed cancel
+ delete p;
+ }
+}
+
+void
+SettingsDialog::sipContextMenuRequest( const QPoint& p )
+{
+ QModelIndex idx = ui->accountsView->indexAt( p );
+ // if it's an account, allow to delete
+ if( idx.isValid() && !idx.data( SipModel::FactoryRole ).toBool() && !idx.data( SipModel::FactoryItemRole ).toBool() )
+ {
+ QList< QAction* > acts;
+ acts << new QAction( tr( "Delete Account" ), this );
+ acts.first()->setProperty( "sipplugin", idx.data( SipModel::SipPluginData ) );
+ connect( acts.first(), SIGNAL( triggered( bool ) ), this, SLOT( sipPluginRowDeleted( bool ) ) );
+ QMenu::exec( acts, ui->accountsView->mapToGlobal( p ) );
+ }
+}
+
+void
+SettingsDialog::sipPluginRowDeleted( bool )
+{
+ SipPlugin* p = qobject_cast< SipPlugin* >( qobject_cast< QAction* >( sender() )->property( "sipplugin" ).value< QObject* >() );
+ SipHandler::instance()->removeSipPlugin( p );
+}
+
+void
+SettingsDialog::sipPluginDeleted( bool )
+{
+ QModelIndexList indexes = ui->accountsView->selectionModel()->selectedIndexes();
+ // if it's an account, allow to delete
+ foreach( const QModelIndex& idx, indexes )
+ {
+ if( idx.isValid() && !idx.data( SipModel::FactoryRole ).toBool() && !idx.data( SipModel::FactoryItemRole ).toBool() )
+ {
+ SipPlugin* p = qobject_cast< SipPlugin* >( idx.data( SipModel::SipPluginData ).value< QObject* >() );
+
+ if( SipPluginFactory* f = SipHandler::instance()->factoryFromPlugin( p ) )
+ {
+ if( f->isUnique() ) // just deleted a unique plugin->re-add to add menu
+ {
+ QAction* action = new QAction( f->icon(), f->prettyName(), ui->addSipButton );
+ action->setProperty( "factory", QVariant::fromValue< QObject* >( f ) );
+ ui->addSipButton->addAction( action );
+
+ connect( action, SIGNAL( triggered(bool) ), this, SLOT( factoryActionTriggered( bool ) ) );
+ }
+ }
+ SipHandler::instance()->removeSipPlugin( p );
+ }
+ }
+}
diff --git a/src/settingsdialog.h b/src/settingsdialog.h
index 880c319da..00f1eb4e0 100644
--- a/src/settingsdialog.h
+++ b/src/settingsdialog.h
@@ -20,7 +20,13 @@
#define SETTINGSDIALOG_H
#include
+#include
+class QListWidgetItem;
+class Ui_StackedSettingsDialog;
+class SipPluginFactory;
+class SipPlugin;
+class SipModel;
class ResolversModel;
class QNetworkReply;
@@ -73,13 +79,26 @@ private slots:
void scriptSelectionChanged();
void removeScriptResolver();
void openResolverConfig( const QString& );
+ void sipItemClicked ( const QModelIndex& );
+ void openSipConfig( SipPlugin* );
+ void factoryActionTriggered ( bool );
+ void sipFactoryClicked( SipPluginFactory* );
+ void sipContextMenuRequest( const QPoint& );
+ void sipPluginDeleted( bool );
+ void sipPluginRowDeleted( bool );
+
+ void changePage( QListWidgetItem*, QListWidgetItem* );
private:
- Ui::SettingsDialog* ui;
+ void createIcons();
+ void setupSipButtons();
+
+ Ui_StackedSettingsDialog* ui;
ProxyDialog m_proxySettings;
bool m_rejected;
QNetworkReply* m_testLastFmQuery;
+ SipModel* m_sipModel;
ResolversModel* m_resolversModel;
};
diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui
index 57fc1b306..3ccf7d55e 100644
--- a/src/settingsdialog.ui
+++ b/src/settingsdialog.ui
@@ -25,6 +25,35 @@
0
+
+
+ Accounts
+
+
+ -
+
+
+ 0
+
+
+ false
+
+
+ false
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+
+
+
Jabber
diff --git a/src/sip/jabber/jabber.cpp b/src/sip/jabber/jabber.cpp
index dab22ac5b..7b1f1c250 100644
--- a/src/sip/jabber/jabber.cpp
+++ b/src/sip/jabber/jabber.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -42,21 +42,21 @@ JabberPlugin::setProxy( QNetworkProxy* proxy )
const QString
-JabberPlugin::name()
+JabberPlugin::name() const
{
return QString( MYNAME );
}
const QString
-JabberPlugin::friendlyName()
+JabberPlugin::friendlyName() const
{
return QString( "Jabber" );
}
const QString
-JabberPlugin::accountName()
+JabberPlugin::accountName() const
{
return TomahawkSettings::instance()->jabberUsername();
}
@@ -128,6 +128,7 @@ JabberPlugin::onConnected()
emit addMenu( m_menu );
}
+
emit connected();
}
diff --git a/src/sip/jabber/jabber.h b/src/sip/jabber/jabber.h
index b3d868896..53e264c24 100644
--- a/src/sip/jabber/jabber.h
+++ b/src/sip/jabber/jabber.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -37,10 +37,10 @@ public:
virtual ~JabberPlugin() { delete p; }
//FIXME: Make this more correct
- virtual bool isValid() { return true; }
- virtual const QString name();
- virtual const QString friendlyName();
- virtual const QString accountName();
+ virtual bool isValid() const { return true; }
+ virtual const QString name() const;
+ virtual const QString friendlyName() const;
+ virtual const QString accountName() const;
virtual QMenu* menu();
void setProxy( QNetworkProxy* proxy );
@@ -51,7 +51,7 @@ public slots:
void disconnectPlugin()
{
onDisconnected();
-
+
if ( p )
p->disconnect();
@@ -84,7 +84,7 @@ private slots:
void showAddFriendDialog();
void onConnected();
void onDisconnected();
-
+
private:
Jabber_p* p;
QMenu* m_menu;
diff --git a/src/sip/jreen/CMakeLists.txt b/src/sip/jreen/CMakeLists.txt
index 3cc053545..d439d5164 100644
--- a/src/sip/jreen/CMakeLists.txt
+++ b/src/sip/jreen/CMakeLists.txt
@@ -20,13 +20,19 @@ set( jabberHeaders
avatarmanager.h
)
+set( jabberUI
+ configwidget.ui
+)
+
include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ..
${QT_INCLUDE_DIR}
${LIBJREEN_INCLUDE_DIR}
)
+qt4_add_resources( RC_SRCS "resources.qrc" )
+qt4_wrap_ui( jabberUI_H ${jabberUI} )
qt4_wrap_cpp( jabberMoc ${jabberHeaders} )
-add_library( tomahawk_sipjabber SHARED ${jabberSources} ${jabberMoc} )
+add_library( tomahawk_sipjabber SHARED ${jabberSources} ${jabberMoc} ${jabberUI_H} ${RC_SRCS} )
IF( WIN32 )
SET( OS_SPECIFIC_LINK_LIBRARIES
@@ -49,3 +55,6 @@ IF( APPLE )
ENDIF( APPLE )
install( TARGETS tomahawk_sipjabber DESTINATION lib${LIB_SUFFIX} )
+
+
+add_subdirectory(googlewrapper)
diff --git a/src/sip/jreen/configwidget.ui b/src/sip/jreen/configwidget.ui
new file mode 100644
index 000000000..b11a48282
--- /dev/null
+++ b/src/sip/jreen/configwidget.ui
@@ -0,0 +1,264 @@
+
+
+ JabberConfig
+
+
+
+ 0
+ 0
+ 437
+ 207
+
+
+
+ Form
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ Configure this Jabber account
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ Login Information
+
+
+
-
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Jabber ID:
+
+
+ jabberUsername
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ e.g. user@example.com
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Password:
+
+
+ jabberPassword
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ QLineEdit::Password
+
+
+
+
+
+ -
+
+
+ Connect automatically when Tomahawk starts
+
+
+
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+ Advanced Jabber Settings
+
+
+
-
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 50
+ 0
+
+
+
+ Server:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ jabberServer
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ Port:
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 90
+ 0
+
+
+
+
+ 90
+ 16777215
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ 1
+
+
+ 65535
+
+
+ 5222
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
diff --git a/src/sip/jreen/googlewrapper/CMakeLists.txt b/src/sip/jreen/googlewrapper/CMakeLists.txt
new file mode 100644
index 000000000..f035266d0
--- /dev/null
+++ b/src/sip/jreen/googlewrapper/CMakeLists.txt
@@ -0,0 +1,32 @@
+
+# fake google plugin
+
+set( googleHeaders
+ ../jabber.h
+ ../tomahawksipmessage.h
+ ../tomahawksipmessagefactory.h
+ ../avatarmanager.h
+ googlewrapper.h )
+
+set( googleSources
+ ../jabber.cpp
+ ../tomahawksipmessage.cpp
+ ../tomahawksipmessagefactory.cpp
+ ../avatarmanager.cpp
+ googlewrapper.cpp )
+
+add_definitions(-DGOOGLE_WRAPPER)
+
+qt4_add_resources( RCX_SRCS "resources.qrc" )
+
+qt4_wrap_cpp( googleMoc ../jabber.h ../avatarmanager.h googlewrapper.h )
+add_library( tomahawk_sipgoogle SHARED ${googleSources} ${googleMoc} ${googleMoc} ${RCX_SRCS} )
+
+target_link_libraries( tomahawk_sipgoogle
+ ${QT_LIBRARIES}
+ ${LIBJREEN_LIBRARY}
+ ${OS_SPECIFIC_LINK_LIBRARIES}
+ tomahawklib
+)
+
+install( TARGETS tomahawk_sipgoogle DESTINATION lib${LIB_SUFFIX} )
diff --git a/src/sip/jreen/googlewrapper/gmail-logo.png b/src/sip/jreen/googlewrapper/gmail-logo.png
new file mode 100644
index 000000000..e31298c1a
Binary files /dev/null and b/src/sip/jreen/googlewrapper/gmail-logo.png differ
diff --git a/src/sip/jreen/googlewrapper/googlewrapper.cpp b/src/sip/jreen/googlewrapper/googlewrapper.cpp
new file mode 100644
index 000000000..9eeae3acd
--- /dev/null
+++ b/src/sip/jreen/googlewrapper/googlewrapper.cpp
@@ -0,0 +1,54 @@
+/*
+
+ Copyright (C) 2011 Leo Franchi
+
+ 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 .
+*/
+
+
+#include "googlewrapper.h"
+#include
+
+#include "ui_configwidget.h"
+
+SipPlugin*
+GoogleWrapperFactory::createPlugin( const QString& pluginId )
+{
+ return new GoogleWrapper( pluginId.isEmpty() ? generateId() : pluginId );
+}
+
+QIcon
+GoogleWrapperFactory::icon() const
+{
+ return QIcon( ":/gmail-logo.png" );
+}
+
+GoogleWrapper::GoogleWrapper ( const QString& pluginID )
+ : JabberPlugin ( pluginID )
+{
+ m_ui->headerLabel->setText( tr( "Configure this Google Account" ) );
+ m_ui->emailLabel->setText( tr( "GMail Address" ) );
+
+}
+
+QIcon
+GoogleWrapper::icon() const
+{
+ return QIcon( ":/gmail-logo.png" );
+}
+
+
+#ifdef GOOGLE_WRAPPER
+Q_EXPORT_PLUGIN2( sipfactory, GoogleWrapperFactory )
+#endif
diff --git a/src/sip/jreen/googlewrapper/googlewrapper.h b/src/sip/jreen/googlewrapper/googlewrapper.h
new file mode 100644
index 000000000..80fe3290a
--- /dev/null
+++ b/src/sip/jreen/googlewrapper/googlewrapper.h
@@ -0,0 +1,51 @@
+/*
+ Copyright (C) 2011 Leo Franchi
+
+ 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 .
+*/
+
+
+#ifndef GOOGLEWRAPPER_H
+#define GOOGLEWRAPPER_H
+
+#include "sip/jreen/jabber.h"
+
+class SIPDLLEXPORT GoogleWrapperFactory : public SipPluginFactory
+{
+ Q_OBJECT
+ Q_INTERFACES( SipPluginFactory )
+
+public:
+ GoogleWrapperFactory() {}
+ virtual ~GoogleWrapperFactory() {}
+
+ virtual QString prettyName() const { return "GMail"; }
+ virtual QString factoryId() const { return "sipgoogle"; }
+ virtual QIcon icon() const;
+ virtual SipPlugin* createPlugin( const QString& pluginId );
+};
+
+class SIPDLLEXPORT GoogleWrapper : public JabberPlugin
+{
+ Q_OBJECT
+public:
+ GoogleWrapper( const QString& pluginID );
+ virtual ~GoogleWrapper() {}
+
+ virtual const QString name() const { return QString( "GMail" ); }
+ virtual const QString friendlyName() const { return "GMail Friends"; }
+ virtual QIcon icon() const;
+};
+
+#endif // GOOGLEWRAPPER_H
diff --git a/src/sip/jreen/googlewrapper/resources.qrc b/src/sip/jreen/googlewrapper/resources.qrc
new file mode 100644
index 000000000..b3838d682
--- /dev/null
+++ b/src/sip/jreen/googlewrapper/resources.qrc
@@ -0,0 +1,5 @@
+
+
+gmail-logo.png
+
+
diff --git a/src/sip/jreen/jabber-icon.png b/src/sip/jreen/jabber-icon.png
new file mode 100644
index 000000000..1b5f78b2f
Binary files /dev/null and b/src/sip/jreen/jabber-icon.png differ
diff --git a/src/sip/jreen/jabber.cpp b/src/sip/jreen/jabber.cpp
index 3c4f519c3..f85669947 100644
--- a/src/sip/jreen/jabber.cpp
+++ b/src/sip/jreen/jabber.cpp
@@ -43,20 +43,44 @@
#include
#include
-JabberPlugin::JabberPlugin()
- : m_menu( 0 )
+#include "ui_configwidget.h"
+
+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_menu( 0 )
, m_addFriendAction( 0 )
- , m_connected(false)
+ , m_state( Disconnected )
{
qDebug() << Q_FUNC_INFO;
qsrand(QDateTime::currentDateTime().toTime_t());
- // load settings
- m_currentUsername = TomahawkSettings::instance()->jabberUsername();
- m_currentServer = TomahawkSettings::instance()->jabberServer();
- m_currentPassword = TomahawkSettings::instance()->jabberPassword();
- m_currentPort = TomahawkSettings::instance()->jabberPort();
+ m_configWidget = QWeakPointer< QWidget >( new QWidget );
+ m_ui = new Ui_JabberConfig;
+ m_ui->setupUi( m_configWidget.data() );
+ m_configWidget.data()->setVisible( false );
+
+ m_ui->checkBoxAutoConnect->setChecked( readAutoConnect() );
+ m_ui->jabberUsername->setText( accountName() );
+ m_ui->jabberPassword->setText( readPassword() );
+ m_ui->jabberServer->setText( readServer() );
+ m_ui->jabberPort->setValue( readPort() );
+ m_currentUsername = accountName();
+ m_currentServer = readServer();
+ m_currentPassword = readPassword();
+ m_currentPort = readPort();
// setup JID object
Jreen::JID jid = Jreen::JID( accountName() );
@@ -135,21 +159,21 @@ JabberPlugin::setProxy( const QNetworkProxy &proxy )
const QString
-JabberPlugin::name()
+JabberPlugin::name() const
{
return QString( MYNAME );
}
const QString
-JabberPlugin::friendlyName()
+JabberPlugin::friendlyName() const
{
return QString( "Jabber" );
}
const QString
-JabberPlugin::accountName()
+JabberPlugin::accountName() const
{
- return TomahawkSettings::instance()->jabberUsername();
+ return TomahawkSettings::instance()->value( pluginId() + "/username" ).toString();
}
QMenu*
@@ -158,31 +182,51 @@ JabberPlugin::menu()
return m_menu;
}
+QWidget*
+JabberPlugin::configWidget()
+{
+ return m_configWidget.data();
+}
+
+QIcon
+JabberPlugin::icon() const
+{
+ return QIcon( ":/jabber-icon.png" );
+}
+
+
bool
JabberPlugin::connectPlugin( bool startup )
{
qDebug() << Q_FUNC_INFO;
- if ( startup && !TomahawkSettings::instance()->jabberAutoConnect() )
+ if ( startup && !readAutoConnect() )
return false;
- qDebug() << "Connecting to the XMPP server..." << m_connected;
+ if(m_client->isConnected())
+ {
+ qDebug() << Q_FUNC_INFO << "Already connected to server, not connecting again...";
+ return true; //FIXME: should i return false here?!
+ }
+
+ qDebug() << "Connecting to the XMPP server...";
+
qDebug() << m_client->jid().full();
- //m_client->setServer( m_client->jid().domain() );
qDebug() << m_client->server() << m_client->port();
+ //FIXME: we're badly workarounding some missing reconnection api here, to be fixed soon
QTimer::singleShot(1000, m_client, SLOT( connectToServer() ) );
- //m_client->connectToServer();
+
+ m_state = Connecting;
+ emit stateChanged( m_state );
return true;
}
void
JabberPlugin::disconnectPlugin()
{
- qDebug() << Q_FUNC_INFO << m_connected;
-
- if(!m_connected)
+ if(!m_client->isConnected())
return;
foreach(const Jreen::JID &peer, m_peers.keys())
@@ -215,8 +259,6 @@ JabberPlugin::onConnect()
emit jidChanged( m_client->jid().full() );
}
- emit connected();
-
qDebug() << "Connected as:" << m_client->jid().full();
// set presence to least valid value
@@ -240,7 +282,8 @@ 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_connected = true;
+ m_state = Connected;
+ emit stateChanged( m_state );
addMenuHelper();
}
@@ -323,14 +366,13 @@ JabberPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
Q_ASSERT(false);
break;
}
+ m_state = Disconnected;
+ emit stateChanged( m_state );
- emit disconnected();
removeMenuHelper();
if(reconnect)
QTimer::singleShot(reconnectInSeconds*1000, this, SLOT(connectPlugin()));
-
- m_connected = false;
}
void
@@ -435,25 +477,29 @@ void
JabberPlugin::checkSettings()
{
bool reconnect = false;
- if ( m_currentUsername != TomahawkSettings::instance()->jabberUsername() )
+ if ( m_currentUsername != accountName() )
reconnect = true;
- if ( m_currentPassword != TomahawkSettings::instance()->jabberPassword() )
+ if ( m_currentPassword != readPassword() )
reconnect = true;
- if ( m_currentServer != TomahawkSettings::instance()->jabberServer() )
+ if ( m_currentServer != readServer() )
reconnect = true;
- if ( m_currentPort != TomahawkSettings::instance()->jabberPort() )
+ if ( m_currentPort != readPort() )
reconnect = true;
+ m_currentUsername = accountName();
+ m_currentPassword = readPassword();
+ m_currentServer = readServer();
+ m_currentPort = readPort();
if ( reconnect )
{
qDebug() << Q_FUNC_INFO << "Reconnecting jreen plugin...";
disconnectPlugin();
- m_currentUsername = TomahawkSettings::instance()->jabberUsername();
- m_currentPassword = TomahawkSettings::instance()->jabberPassword();
- m_currentServer = TomahawkSettings::instance()->jabberServer();
- m_currentPort = TomahawkSettings::instance()->jabberPort();
+ m_currentUsername = accountName();
+ m_currentPassword = readPassword();
+ m_currentServer = readServer();
+ m_currentPort = readPort();
setupClientHelper();
@@ -844,5 +890,49 @@ void JabberPlugin::onNewAvatar(const QString& jid)
}
+QString
+JabberPlugin::readPassword()
+{
+ return TomahawkSettings::instance()->value( pluginId() + "/password" ).toString();
+}
-Q_EXPORT_PLUGIN2( sip, JabberPlugin )
+int
+JabberPlugin::readPort()
+{
+ return TomahawkSettings::instance()->value( pluginId() + "/port", 5222 ).toInt();
+}
+
+QString
+JabberPlugin::readServer()
+{
+ return TomahawkSettings::instance()->value( pluginId() + "/server" ).toString();
+}
+
+bool
+JabberPlugin::readAutoConnect()
+{
+ return TomahawkSettings::instance()->value( pluginId() + "/autoconnect", true ).toBool();
+}
+
+void
+JabberPlugin::saveConfig()
+{
+ TomahawkSettings::instance()->setValue( pluginId() + "/autoconnect", m_ui->checkBoxAutoConnect->isChecked() );
+ 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();
+}
+
+
+SipPlugin::ConnectionState
+JabberPlugin::connectionState() const
+{
+ return m_state;
+}
+
+#ifndef GOOGLE_WRAPPER
+Q_EXPORT_PLUGIN2( sipfactory, JabberFactory )
+#endif
diff --git a/src/sip/jreen/jabber.h b/src/sip/jreen/jabber.h
index cb0b3c2b8..cf35ed927 100644
--- a/src/sip/jreen/jabber.h
+++ b/src/sip/jreen/jabber.h
@@ -46,21 +46,41 @@
#include "../sipdllmacro.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
{
Q_OBJECT
- Q_INTERFACES( SipPlugin )
public:
- JabberPlugin();
+ JabberPlugin( const QString& pluginId );
virtual ~JabberPlugin();
//FIXME: Make this more correct
- virtual bool isValid() { return true; }
- virtual const QString name();
- virtual const QString friendlyName();
- virtual const QString accountName();
+ 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;
virtual QMenu* menu();
+ virtual QIcon icon() const;
+ virtual QWidget* configWidget();
+ virtual void saveConfig();
signals:
void jidChanged( const QString& );
@@ -74,6 +94,9 @@ public slots:
void addContact( const QString &jid, const QString& msg = QString() );
void setProxy( const QNetworkProxy &proxy );
+protected:
+ Ui_JabberConfig* m_ui; // so the google wrapper can change the config dialog a bit
+
private slots:
void showAddFriendDialog();
void onConnect();
@@ -93,6 +116,11 @@ private slots:
void onNewAvatar( const QString &jid );
private:
+ QString readPassword();
+ QString readServer();
+ bool readAutoConnect();
+ int readPort();
+
void setupClientHelper();
void addMenuHelper();
void removeMenuHelper();
@@ -100,8 +128,6 @@ private:
bool presenceMeansOnline( Jreen::Presence::Type p );
void handlePeerStatus( const Jreen::JID &jid, Jreen::Presence::Type presenceType );
- bool m_connected;
-
QMenu* m_menu;
QAction* m_addFriendAction;
@@ -109,6 +135,10 @@ private:
QString m_currentPassword;
QString m_currentServer;
unsigned int m_currentPort;
+ ConnectionState m_state;
+
+ QWeakPointer< QWidget > m_configWidget;
+
QString m_currentResource;
// sort out
diff --git a/src/sip/jreen/resources.qrc b/src/sip/jreen/resources.qrc
new file mode 100644
index 000000000..9700ac51f
--- /dev/null
+++ b/src/sip/jreen/resources.qrc
@@ -0,0 +1,5 @@
+
+
+jabber-icon.png
+
+
diff --git a/src/sip/twitter/CMakeLists.txt b/src/sip/twitter/CMakeLists.txt
index f50abba2d..7944173fd 100644
--- a/src/sip/twitter/CMakeLists.txt
+++ b/src/sip/twitter/CMakeLists.txt
@@ -26,9 +26,10 @@ include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ..
${CMAKE_SOURCE_DIR}/thirdparty/qtweetlib/tomahawk-custom
)
+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} )
+add_library( tomahawk_siptwitter SHARED ${twitterUI_H} ${twitterSources} ${twitterMoc} ${RC_SRCS} )
IF( WIN32 )
SET( OS_SPECIFIC_LINK_LIBRARIES
diff --git a/src/sip/twitter/resources.qrc b/src/sip/twitter/resources.qrc
new file mode 100644
index 000000000..fc7df302f
--- /dev/null
+++ b/src/sip/twitter/resources.qrc
@@ -0,0 +1,5 @@
+
+
+twitter-icon.png
+
+
diff --git a/src/sip/twitter/twitter-icon.png b/src/sip/twitter/twitter-icon.png
new file mode 100644
index 000000000..aab1fca87
Binary files /dev/null and b/src/sip/twitter/twitter-icon.png differ
diff --git a/src/sip/twitter/twitter.cpp b/src/sip/twitter/twitter.cpp
index 65a9af55e..608e3a2a5 100644
--- a/src/sip/twitter/twitter.cpp
+++ b/src/sip/twitter/twitter.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -35,10 +35,21 @@
static QString s_gotTomahawkRegex = QString( "^(@[a-zA-Z0-9]+ )?(Got Tomahawk\\?) (\\{[a-fA-F0-9\\-]+\\}) (.*)$" );
-TwitterPlugin::TwitterPlugin()
- : SipPlugin()
+SipPlugin*
+TwitterFactory::createPlugin( const QString& pluginId )
+{
+ return new TwitterPlugin( pluginId.isEmpty() ? generateId() : pluginId );
+}
+
+QIcon TwitterFactory::icon() const
+{
+ return QIcon( ":/twitter-icon.png" );
+}
+
+
+TwitterPlugin::TwitterPlugin( const QString& pluginId )
+ : SipPlugin( pluginId )
, m_isAuthed( false )
- , m_isOnline( false )
, m_checkTimer( this )
, m_connectTimer( this )
, m_cachedFriendsSinceId( 0 )
@@ -48,7 +59,7 @@ TwitterPlugin::TwitterPlugin()
, m_keyCache()
, m_finishedFriends( false )
, m_finishedMentions( false )
- , m_configWidget( 0 )
+ , m_state( Disconnected )
{
qDebug() << Q_FUNC_INFO;
m_checkTimer.setInterval( 60000 );
@@ -58,51 +69,75 @@ TwitterPlugin::TwitterPlugin()
m_connectTimer.setInterval( 60000 );
m_connectTimer.setSingleShot( false );
connect( &m_connectTimer, SIGNAL( timeout() ), SLOT( connectTimerFired() ) );
+
+ m_configWidget = QWeakPointer< TwitterConfigWidget >( new TwitterConfigWidget( this, 0 ) );
+ connect( m_configWidget.data(), SIGNAL( twitterAuthed( bool ) ), SLOT( configDialogAuthedSignalSlot( bool ) ) );
+
}
void
TwitterPlugin::configDialogAuthedSignalSlot( bool authed )
{
- m_isAuthed = authed;
+
if ( !authed )
{
- TomahawkSettings::instance()->setTwitterScreenName( QString() );
- TomahawkSettings::instance()->setTwitterOAuthToken( QString() );
- TomahawkSettings::instance()->setTwitterOAuthTokenSecret( QString() );
+ if( m_isAuthed ) {
+ m_state = Disconnected;
+ emit stateChanged( m_state );
+ }
+
+ setTwitterScreenName( QString() );
+ setTwitterOAuthToken( QString() );
+ setTwitterOAuthTokenSecret( QString() );
}
+
+ m_isAuthed = authed;
}
bool
-TwitterPlugin::isValid()
+TwitterPlugin::isValid() const
{
return m_isAuthed;
}
const QString
-TwitterPlugin::name()
+TwitterPlugin::name() const
{
return QString( MYNAME );
}
const QString
-TwitterPlugin::friendlyName()
+TwitterPlugin::friendlyName() const
{
return tr("Twitter");
}
const QString
-TwitterPlugin::accountName()
+TwitterPlugin::accountName() const
{
- return QString( TomahawkSettings::instance()->twitterScreenName() );
+ if( twitterScreenName().isEmpty() )
+ return friendlyName();
+ else
+ return twitterScreenName();
}
+QIcon
+TwitterPlugin::icon() const
+{
+ return QIcon( ":/twitter-icon.png" );
+}
+
+
+SipPlugin::ConnectionState
+TwitterPlugin::connectionState() const
+{
+ return m_state;
+}
+
+
QWidget* TwitterPlugin::configWidget()
{
- m_configWidget = new TwitterConfigWidget( this );
-
- connect( m_configWidget, SIGNAL( twitterAuthed(bool) ), SLOT( configDialogAuthedSignalSlot(bool) ) );
-
- return m_configWidget;
+ return m_configWidget.data();
}
bool
@@ -110,9 +145,7 @@ TwitterPlugin::connectPlugin( bool /*startup*/ )
{
qDebug() << Q_FUNC_INFO;
- TomahawkSettings *settings = TomahawkSettings::instance();
-
- m_cachedPeers = settings->twitterCachedPeers();
+ m_cachedPeers = twitterCachedPeers();
QList peerlist = m_cachedPeers.keys();
qStableSort( peerlist.begin(), peerlist.end() );
foreach( QString screenName, peerlist )
@@ -122,20 +155,23 @@ TwitterPlugin::connectPlugin( bool /*startup*/ )
qDebug() << "TwitterPlugin : " << screenName << ", key " << prop << ", value " << ( cachedPeer[prop].canConvert< QString >() ? cachedPeer[prop].toString() : QString::number( cachedPeer[prop].toInt() ) );
QMetaObject::invokeMethod( this, "registerOffer", Q_ARG( QString, screenName ), QGenericArgument( "QHash< QString, QVariant >", (const void*)&cachedPeer ) );
}
-
- if ( settings->twitterOAuthToken().isEmpty() || settings->twitterOAuthTokenSecret().isEmpty() )
+
+ if ( twitterOAuthToken().isEmpty() || twitterOAuthTokenSecret().isEmpty() )
{
qDebug() << "TwitterPlugin has empty Twitter credentials; not connecting";
return m_cachedPeers.isEmpty();
}
-
+
if ( refreshTwitterAuth() )
{
- QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( m_twitterAuth.data(), this );
- connect( credVerifier, SIGNAL( parsedUser(const QTweetUser &) ), SLOT( connectAuthVerifyReply(const QTweetUser &) ) );
- credVerifier->verify();
+ QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( m_twitterAuth.data(), this );
+ connect( credVerifier, SIGNAL( parsedUser(const QTweetUser &) ), SLOT( connectAuthVerifyReply(const QTweetUser &) ) );
+ credVerifier->verify();
+
+ m_state = Connecting;
+ emit stateChanged( m_state );
}
-
+
return true;
}
@@ -152,8 +188,6 @@ TwitterPlugin::refreshTwitterAuth()
if( m_twitterAuth.isNull() )
return false;
-
- TomahawkSettings *settings = TomahawkSettings::instance();
m_twitterAuth.data()->setOAuthToken( settings->twitterOAuthToken().toLatin1() );
m_twitterAuth.data()->setOAuthTokenSecret( settings->twitterOAuthTokenSecret().toLatin1() );
@@ -181,7 +215,8 @@ TwitterPlugin::disconnectPlugin()
delete m_twitterAuth.data();
m_cachedPeers.empty();
- m_isOnline = false;
+ m_state = Disconnected;
+ emit stateChanged( m_state );
}
void
@@ -191,6 +226,8 @@ TwitterPlugin::connectAuthVerifyReply( const QTweetUser &user )
{
qDebug() << "TwitterPlugin could not authenticate to Twitter";
m_isAuthed = false;
+ m_state = Disconnected;
+ emit stateChanged( m_state );
}
else
{
@@ -198,7 +235,7 @@ TwitterPlugin::connectAuthVerifyReply( const QTweetUser &user )
m_isAuthed = true;
if ( !m_twitterAuth.isNull() )
{
- TomahawkSettings::instance()->setTwitterScreenName( user.screenName() );
+ setTwitterScreenName( user.screenName() );
m_friendsTimeline = QWeakPointer( new QTweetFriendsTimeline( m_twitterAuth.data(), this ) );
m_mentions = QWeakPointer( new QTweetMentions( m_twitterAuth.data(), this ) );
m_directMessages = QWeakPointer( new QTweetDirectMessages( m_twitterAuth.data(), this ) );
@@ -210,7 +247,8 @@ TwitterPlugin::connectAuthVerifyReply( const QTweetUser &user )
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_isOnline = true;
+ m_state = Connected;
+ emit stateChanged( m_state );
m_connectTimer.start();
m_checkTimer.start();
QMetaObject::invokeMethod( this, "checkTimerFired", Qt::AutoConnection );
@@ -228,6 +266,8 @@ TwitterPlugin::connectAuthVerifyReply( const QTweetUser &user )
{
qDebug() << "TwitterPlugin auth pointer was null!";
m_isAuthed = false;
+ m_state = Disconnected;
+ emit stateChanged( m_state );
}
}
}
@@ -240,18 +280,18 @@ TwitterPlugin::checkTimerFired()
return;
if ( m_cachedFriendsSinceId == 0 )
- m_cachedFriendsSinceId = TomahawkSettings::instance()->twitterCachedFriendsSinceId();
-
+ m_cachedFriendsSinceId = twitterCachedFriendsSinceId();
+
qDebug() << "TwitterPlugin looking at friends timeline since id " << m_cachedFriendsSinceId;
-
+
if ( !m_friendsTimeline.isNull() )
- m_friendsTimeline.data()->fetch( m_cachedFriendsSinceId, 0, 800 );
-
+ m_friendsTimeline.data()->fetch( m_cachedFriendsSinceId, 0, 800 );
+
if ( m_cachedMentionsSinceId == 0 )
- m_cachedMentionsSinceId = TomahawkSettings::instance()->twitterCachedMentionsSinceId();
-
+ m_cachedMentionsSinceId = twitterCachedMentionsSinceId();
+
qDebug() << "TwitterPlugin looking at mentions timeline since id " << m_cachedMentionsSinceId;
-
+
if ( !m_mentions.isNull() )
m_mentions.data()->fetch( m_cachedMentionsSinceId, 0, 800 );
}
@@ -262,7 +302,7 @@ TwitterPlugin::connectTimerFired()
if ( !isValid() || m_cachedPeers.isEmpty() || m_twitterAuth.isNull() )
return;
- QString myScreenName = TomahawkSettings::instance()->twitterScreenName();
+ QString myScreenName = twitterScreenName();
QList peerlist = m_cachedPeers.keys();
qStableSort( peerlist.begin(), peerlist.end() );
foreach( QString screenName, peerlist )
@@ -275,20 +315,20 @@ TwitterPlugin::connectTimerFired()
m_cachedPeers[screenName] = peerData;
continue;
}
-
+
if ( QDateTime::currentMSecsSinceEpoch() - peerData["lastseen"].toLongLong() > 1209600000 ) // 2 weeks
{
qDebug() << "Aging peer " << screenName << " out of cache";
m_cachedPeers.remove( screenName );
continue;
}
-
+
if ( !peerData.contains( "host" ) || !peerData.contains( "port" ) || !peerData.contains( "pkey" ) )
{
qDebug() << "TwitterPlugin 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 ), QGenericArgument( "QHash< QString, QVariant >", (const void*)&peerData ) );
}
}
@@ -296,7 +336,7 @@ TwitterPlugin::connectTimerFired()
void
TwitterPlugin::parseGotTomahawk( const QRegExp ®ex, const QString &screenName, const QString &text )
{
- QString myScreenName = TomahawkSettings::instance()->twitterScreenName();
+ QString myScreenName = twitterScreenName();
qDebug() << "TwitterPlugin 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 ) )
@@ -304,7 +344,7 @@ TwitterPlugin::parseGotTomahawk( const QRegExp ®ex, const QString &screenName
qDebug() << "TwitterPlugin skipping mention because it's directed @someone that isn't us";
return;
}
-
+
QString node;
for ( int i = 0; i < regex.captureCount(); ++i )
{
@@ -322,13 +362,13 @@ TwitterPlugin::parseGotTomahawk( const QRegExp ®ex, const QString &screenName
}
else
qDebug() << "TwitterPlugin parsed node " << node << " out of the tweet";
-
+
if ( screenName == myScreenName && node == Database::instance()->dbid() )
{
qDebug() << "My screen name and my dbid found; ignoring";
return;
}
-
+
QHash< QString, QVariant > peerData;
if( m_cachedPeers.contains( screenName ) )
{
@@ -345,14 +385,14 @@ TwitterPlugin::friendsTimelineStatuses( const QList< QTweetStatus > &statuses )
{
qDebug() << Q_FUNC_INFO;
QRegExp regex( s_gotTomahawkRegex, Qt::CaseSensitive, QRegExp::RegExp2 );
- QString myScreenName = TomahawkSettings::instance()->twitterScreenName();
-
+ QString myScreenName = twitterScreenName();
+
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
@@ -361,7 +401,7 @@ TwitterPlugin::friendsTimelineStatuses( const QList< QTweetStatus > &statuses )
latestHash[status.user().screenName()] = status;
}
}
-
+
foreach( QTweetStatus status, latestHash.values() )
{
if ( status.id() > m_cachedFriendsSinceId )
@@ -370,9 +410,9 @@ TwitterPlugin::friendsTimelineStatuses( const QList< QTweetStatus > &statuses )
qDebug() << "TwitterPlugin checking mention from " << status.user().screenName() << " with content " << status.text();
parseGotTomahawk( regex, status.user().screenName(), status.text() );
}
-
- TomahawkSettings::instance()->setTwitterCachedFriendsSinceId( m_cachedFriendsSinceId );
-
+
+ setTwitterCachedFriendsSinceId( m_cachedFriendsSinceId );
+
m_finishedFriends = true;
QMetaObject::invokeMethod( this, "pollDirectMessages", Qt::AutoConnection );
}
@@ -382,13 +422,13 @@ TwitterPlugin::mentionsStatuses( const QList< QTweetStatus > &statuses )
{
qDebug() << 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
@@ -397,18 +437,18 @@ TwitterPlugin::mentionsStatuses( const QList< QTweetStatus > &statuses )
latestHash[status.user().screenName()] = status;
}
}
-
+
foreach( QTweetStatus status, latestHash.values() )
{
if ( status.id() > m_cachedMentionsSinceId )
m_cachedMentionsSinceId = status.id();
-
+
qDebug() << "TwitterPlugin checking mention from " << status.user().screenName() << " with content " << status.text();
parseGotTomahawk( regex, status.user().screenName(), status.text() );
}
-
- TomahawkSettings::instance()->setTwitterCachedMentionsSinceId( m_cachedMentionsSinceId );
-
+
+ setTwitterCachedMentionsSinceId( m_cachedMentionsSinceId );
+
m_finishedMentions = true;
QMetaObject::invokeMethod( this, "pollDirectMessages", Qt::AutoConnection );
}
@@ -418,18 +458,18 @@ TwitterPlugin::pollDirectMessages()
{
if ( !m_finishedMentions || !m_finishedFriends )
return;
-
+
m_finishedFriends = false;
m_finishedMentions = false;
-
+
if ( !isValid() )
return;
-
+
if ( m_cachedDirectMessagesSinceId == 0 )
- m_cachedDirectMessagesSinceId = TomahawkSettings::instance()->twitterCachedDirectMessagesSinceId();
-
+ m_cachedDirectMessagesSinceId = twitterCachedDirectMessagesSinceId();
+
qDebug() << "TwitterPlugin looking for direct messages since id " << m_cachedDirectMessagesSinceId;
-
+
if ( !m_directMessages.isNull() )
m_directMessages.data()->fetch( m_cachedDirectMessagesSinceId, 0, 800 );
}
@@ -438,10 +478,10 @@ void
TwitterPlugin::directMessages( const QList< QTweetDMStatus > &messages )
{
qDebug() << Q_FUNC_INFO;
-
+
QRegExp regex( s_gotTomahawkRegex, Qt::CaseSensitive, QRegExp::RegExp2 );
- QString myScreenName = TomahawkSettings::instance()->twitterScreenName();
-
+ QString myScreenName = twitterScreenName();
+
QHash< QString, QTweetDMStatus > latestHash;
foreach ( QTweetDMStatus status, messages )
{
@@ -458,7 +498,7 @@ TwitterPlugin::directMessages( const QList< QTweetDMStatus > &messages )
if ( port == 0 )
continue;
}
-
+
if ( !latestHash.contains( status.senderScreenName() ) )
latestHash[status.senderScreenName()] = status;
else
@@ -467,13 +507,13 @@ TwitterPlugin::directMessages( const QList< QTweetDMStatus > &messages )
latestHash[status.senderScreenName()] = status;
}
}
-
+
foreach( QTweetDMStatus status, latestHash.values() )
{
qDebug() << "TwitterPlugin 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
@@ -494,12 +534,12 @@ TwitterPlugin::directMessages( const QList< QTweetDMStatus > &messages )
continue;
}
qDebug() << "TwitterPlugin 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];
-
-
+
+
QHash< QString, QVariant > peerData = ( m_cachedPeers.contains( status.senderScreenName() ) ) ?
m_cachedPeers[status.senderScreenName()].toHash() :
QHash< QString, QVariant >();
-
+
peerData["host"] = QVariant::fromValue< QString >( host );
peerData["port"] = QVariant::fromValue< int >( port );
peerData["pkey"] = QVariant::fromValue< QString >( pkey );
@@ -517,7 +557,7 @@ TwitterPlugin::directMessages( const QList< QTweetDMStatus > &messages )
}
}
- TomahawkSettings::instance()->setTwitterCachedDirectMessagesSinceId( m_cachedDirectMessagesSinceId );
+ setTwitterCachedDirectMessagesSinceId( m_cachedDirectMessagesSinceId );
}
void
@@ -573,7 +613,7 @@ TwitterPlugin::registerOffer( const QString &screenName, const QHash< QString, Q
qDebug() << "TwitterPlugin 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() << "TwitterPlugin needs to send and has node";
@@ -590,12 +630,12 @@ TwitterPlugin::registerOffer( const QString &screenName, const QHash< QString, Q
{
_peerData["lastseen"] = QString::number( QDateTime::currentMSecsSinceEpoch() );
m_cachedPeers[screenName] = QVariant::fromValue< QHash< QString, QVariant > >( _peerData );
- TomahawkSettings::instance()->setTwitterCachedPeers( m_cachedPeers );
+ setTwitterCachedPeers( m_cachedPeers );
}
- if ( m_isOnline && _peerData.contains( "host" ) && _peerData.contains( "port" ) && _peerData.contains( "pkey" ) )
+ if ( m_state == Connected && _peerData.contains( "host" ) && _peerData.contains( "port" ) && _peerData.contains( "pkey" ) )
QMetaObject::invokeMethod( this, "makeConnection", Q_ARG( QString, screenName ), QGenericArgument( "QHash< QString, QVariant >", (const void*)&_peerData ) );
-
+
}
void
@@ -636,7 +676,7 @@ TwitterPlugin::directMessagePosted( const QTweetDMStatus& message )
{
qDebug() << Q_FUNC_INFO;
qDebug() << "TwitterPlugin sent message to " << message.recipientScreenName() << " containing: " << message.text();
-
+
}
void
@@ -662,4 +702,89 @@ TwitterPlugin::checkSettings()
connectPlugin( false );
}
-Q_EXPORT_PLUGIN2( sip, TwitterPlugin )
+
+QString
+TwitterPlugin::twitterScreenName() const
+{
+ return TomahawkSettings::instance()->value( pluginId() + "/ScreenName" ).toString();
+}
+
+void
+TwitterPlugin::setTwitterScreenName( const QString& screenName )
+{
+ TomahawkSettings::instance()->setValue( pluginId() + "/ScreenName", screenName );
+}
+
+QString
+TwitterPlugin::twitterOAuthToken() const
+{
+ return TomahawkSettings::instance()->value( pluginId() + "/OAuthToken" ).toString();
+}
+
+void
+TwitterPlugin::setTwitterOAuthToken( const QString& oauthtoken )
+{
+ TomahawkSettings::instance()->setValue( pluginId() + "/OAuthToken", oauthtoken );
+}
+
+QString
+TwitterPlugin::twitterOAuthTokenSecret() const
+{
+ return TomahawkSettings::instance()->value( pluginId() + "/OAuthTokenSecret" ).toString();
+}
+
+void
+TwitterPlugin::setTwitterOAuthTokenSecret( const QString& oauthtokensecret )
+{
+ TomahawkSettings::instance()->setValue( pluginId() + "/OAuthTokenSecret", oauthtokensecret );
+}
+
+qint64
+TwitterPlugin::twitterCachedFriendsSinceId() const
+{
+ return TomahawkSettings::instance()->value( pluginId() + "/CachedFriendsSinceID", 0 ).toLongLong();
+}
+
+void
+TwitterPlugin::setTwitterCachedFriendsSinceId( qint64 cachedId )
+{
+ TomahawkSettings::instance()->setValue( pluginId() + "/CachedFriendsSinceID", cachedId );
+}
+
+qint64
+TwitterPlugin::twitterCachedMentionsSinceId() const
+{
+ return TomahawkSettings::instance()->value( pluginId() + "/CachedMentionsSinceID", 0 ).toLongLong();
+}
+
+void
+TwitterPlugin::setTwitterCachedMentionsSinceId( qint64 cachedId )
+{
+ TomahawkSettings::instance()->setValue( pluginId() + "/CachedMentionsSinceID", cachedId );
+}
+
+qint64
+TwitterPlugin::twitterCachedDirectMessagesSinceId() const
+{
+ return TomahawkSettings::instance()->value( pluginId() + "/CachedDirectMessagesSinceID", 0 ).toLongLong();
+}
+
+void
+TwitterPlugin::setTwitterCachedDirectMessagesSinceId( qint64 cachedId )
+{
+ TomahawkSettings::instance()->setValue( pluginId() + "/CachedDirectMessagesSinceID", cachedId );
+}
+
+QHash
+TwitterPlugin::twitterCachedPeers() const
+{
+ return TomahawkSettings::instance()->value( pluginId() + "/CachedPeers", QHash() ).toHash();
+}
+
+void
+TwitterPlugin::setTwitterCachedPeers( const QHash &cachedPeers )
+{
+ TomahawkSettings::instance()->setValue( pluginId() + "/CachedPeers", cachedPeers );
+}
+
+Q_EXPORT_PLUGIN2( sipfactory, TwitterFactory )
diff --git a/src/sip/twitter/twitter.h b/src/sip/twitter/twitter.h
index 418cc1f07..154fe7d5f 100644
--- a/src/sip/twitter/twitter.h
+++ b/src/sip/twitter/twitter.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -40,21 +40,36 @@
#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
{
Q_OBJECT
- Q_INTERFACES( SipPlugin )
-
+
public:
- TwitterPlugin();
+ TwitterPlugin( const QString& pluginId );
virtual ~TwitterPlugin() {}
-
- virtual bool isValid();
- virtual const QString name();
- virtual const QString accountName();
- virtual const QString friendlyName();
+ 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();
public slots:
@@ -98,6 +113,21 @@ private slots:
private:
bool refreshTwitterAuth();
void parseGotTomahawk( const QRegExp ®ex, const QString &screenName, const QString &text );
+ // handle per-plugin config
+ 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 );
+ QHash twitterCachedPeers() const;
+ void setTwitterCachedPeers( const QHash &cachedPeers );
QWeakPointer< TomahawkOAuthTwitter > m_twitterAuth;
QWeakPointer< QTweetFriendsTimeline > m_friendsTimeline;
@@ -105,8 +135,8 @@ private:
QWeakPointer< QTweetDirectMessages > m_directMessages;
QWeakPointer< QTweetDirectMessageNew > m_directMessageNew;
QWeakPointer< QTweetDirectMessageDestroy > m_directMessageDestroy;
+
bool m_isAuthed;
- bool m_isOnline;
QTimer m_checkTimer;
QTimer m_connectTimer;
qint64 m_cachedFriendsSinceId;
@@ -116,8 +146,12 @@ private:
QSet m_keyCache;
bool m_finishedFriends;
bool m_finishedMentions;
+ ConnectionState m_state;
- TwitterConfigWidget *m_configWidget;
+ QWeakPointer m_configWidget;
+
+ // for settings access
+ friend class TwitterConfigWidget;
};
#endif
diff --git a/src/sip/twitter/twitterconfigwidget.cpp b/src/sip/twitter/twitterconfigwidget.cpp
index 379cfea20..580ac3471 100644
--- a/src/sip/twitter/twitterconfigwidget.cpp
+++ b/src/sip/twitter/twitterconfigwidget.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -17,6 +17,7 @@
*/
#include "twitterconfigwidget.h"
+#include "twitter.h"
#include "ui_twitterconfigwidget.h"
#include "tomahawksettings.h"
@@ -30,7 +31,7 @@
#include
-TwitterConfigWidget::TwitterConfigWidget( SipPlugin* plugin, QWidget *parent ) :
+TwitterConfigWidget::TwitterConfigWidget( TwitterPlugin* plugin, QWidget *parent ) :
QWidget( parent ),
ui( new Ui::TwitterConfigWidget ),
m_plugin( plugin )
@@ -47,9 +48,8 @@ TwitterConfigWidget::TwitterConfigWidget( SipPlugin* plugin, QWidget *parent ) :
ui->twitterTweetComboBox->setCurrentIndex( 0 );
ui->twitterUserTweetLineEdit->setReadOnly( true );
ui->twitterUserTweetLineEdit->setEnabled( false );
-
- TomahawkSettings* s = TomahawkSettings::instance();
- if ( s->twitterOAuthToken().isEmpty() || s->twitterOAuthTokenSecret().isEmpty() || s->twitterScreenName().isEmpty() )
+
+ if ( m_plugin->twitterOAuthToken().isEmpty() || m_plugin->twitterOAuthTokenSecret().isEmpty() || m_plugin->twitterScreenName().isEmpty() )
{
ui->twitterStatusLabel->setText( tr( "Status: No saved credentials" ) );
ui->twitterAuthenticateButton->setText( tr( "Authenticate" ) );
@@ -58,12 +58,12 @@ TwitterConfigWidget::TwitterConfigWidget( SipPlugin* plugin, QWidget *parent ) :
ui->twitterTweetGotTomahawkButton->setVisible( false );
ui->twitterUserTweetLineEdit->setVisible( false );
ui->twitterTweetComboBox->setVisible( false );
-
+
emit twitterAuthed( false );
}
else
{
- ui->twitterStatusLabel->setText( tr( "Status: Credentials saved for %1" ).arg( s->twitterScreenName() ) );
+ ui->twitterStatusLabel->setText( tr( "Status: Credentials saved for %1" ).arg( m_plugin->twitterScreenName() ) );
ui->twitterAuthenticateButton->setText( tr( "De-authenticate" ) );
ui->twitterInstructionsInfoLabel->setVisible( true );
ui->twitterGlobalTweetLabel->setVisible( true );
@@ -96,11 +96,10 @@ TwitterConfigWidget::authenticateTwitter()
qDebug() << Q_FUNC_INFO;
TomahawkOAuthTwitter *twitAuth = new TomahawkOAuthTwitter( TomahawkUtils::nam(), this );
twitAuth->authorizePin();
-
- TomahawkSettings* s = TomahawkSettings::instance();
- s->setTwitterOAuthToken( twitAuth->oauthToken() );
- s->setTwitterOAuthTokenSecret( twitAuth->oauthTokenSecret() );
-
+
+ m_plugin->setTwitterOAuthToken( twitAuth->oauthToken() );
+ m_plugin->setTwitterOAuthTokenSecret( twitAuth->oauthTokenSecret() );
+
QTweetAccountVerifyCredentials *credVerifier = new QTweetAccountVerifyCredentials( twitAuth, this );
connect( credVerifier, SIGNAL( parsedUser( const QTweetUser & ) ), SLOT( authenticateVerifyReply( const QTweetUser & ) ) );
connect( credVerifier, SIGNAL( error( QTweetNetBase::ErrorCode, QString ) ), SLOT( authenticateVerifyError( QTweetNetBase::ErrorCode, QString ) ) );
@@ -118,12 +117,11 @@ TwitterConfigWidget::authenticateVerifyReply( const QTweetUser &user )
return;
}
- TomahawkSettings* s = TomahawkSettings::instance();
- s->setTwitterScreenName( user.screenName() );
- s->setTwitterCachedFriendsSinceId( 0 );
- s->setTwitterCachedMentionsSinceId( 0 );
-
- ui->twitterStatusLabel->setText( tr( "Status: Credentials saved for %1" ).arg( s->twitterScreenName() ) );
+ m_plugin->setTwitterScreenName( user.screenName() );
+ m_plugin->setTwitterCachedFriendsSinceId( 0 );
+ m_plugin->setTwitterCachedMentionsSinceId( 0 );
+
+ ui->twitterStatusLabel->setText( tr( "Status: Credentials saved for %1" ).arg( m_plugin->twitterScreenName() ) );
ui->twitterAuthenticateButton->setText( tr( "De-authenticate" ) );
ui->twitterInstructionsInfoLabel->setVisible( true );
ui->twitterGlobalTweetLabel->setVisible( true );
@@ -132,7 +130,7 @@ TwitterConfigWidget::authenticateVerifyReply( const QTweetUser &user )
ui->twitterTweetComboBox->setVisible( true );
m_plugin->connectPlugin( false );
-
+
emit twitterAuthed( true );
}
@@ -150,11 +148,10 @@ void
TwitterConfigWidget::deauthenticateTwitter()
{
qDebug() << Q_FUNC_INFO;
- TomahawkSettings* s = TomahawkSettings::instance();
- s->setTwitterOAuthToken( QString() );
- s->setTwitterOAuthTokenSecret( QString() );
- s->setTwitterScreenName( QString() );
-
+ m_plugin->setTwitterOAuthToken( QString() );
+ m_plugin->setTwitterOAuthTokenSecret( QString() );
+ m_plugin->setTwitterScreenName( QString() );
+
ui->twitterStatusLabel->setText(tr("Status: No saved credentials"));
ui->twitterAuthenticateButton->setText( tr( "Authenticate" ) );
ui->twitterInstructionsInfoLabel->setVisible( false );
@@ -162,7 +159,7 @@ TwitterConfigWidget::deauthenticateTwitter()
ui->twitterTweetGotTomahawkButton->setVisible( false );
ui->twitterUserTweetLineEdit->setVisible( false );
ui->twitterTweetComboBox->setVisible( false );
-
+
emit twitterAuthed( false );
}
@@ -180,7 +177,7 @@ TwitterConfigWidget::tweetComboBoxIndexChanged( int index )
ui->twitterUserTweetLineEdit->setReadOnly( false );
ui->twitterUserTweetLineEdit->setEnabled( true );
}
-
+
if( ui->twitterTweetComboBox->currentText() == tr( "Direct Message" ) ) //FIXME: use data!
ui->twitterTweetGotTomahawkButton->setText( tr( "Send Message!" ) );
else
@@ -191,16 +188,15 @@ void
TwitterConfigWidget::startPostGotTomahawkStatus()
{
m_postGTtype = ui->twitterTweetComboBox->currentText();
-
+
if ( m_postGTtype != "Global Tweet" && ( ui->twitterUserTweetLineEdit->text().isEmpty() || 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";
- TomahawkSettings* s = TomahawkSettings::instance();
- if ( s->twitterOAuthToken().isEmpty() || s->twitterOAuthTokenSecret().isEmpty() || s->twitterScreenName().isEmpty() )
+ if ( m_plugin->twitterOAuthToken().isEmpty() || m_plugin->twitterOAuthTokenSecret().isEmpty() || m_plugin->twitterScreenName().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 );
@@ -223,11 +219,8 @@ TwitterConfigWidget::postGotTomahawkStatusAuthVerifyReply( const QTweetUser &use
emit twitterAuthed( false );
return;
}
- TomahawkSettings* s = TomahawkSettings::instance();
- s->setTwitterScreenName( user.screenName() );
+ m_plugin->setTwitterScreenName( user.screenName() );
TomahawkOAuthTwitter *twitAuth = new TomahawkOAuthTwitter( TomahawkUtils::nam(), this );
- twitAuth->setOAuthToken( s->twitterOAuthToken().toLatin1() );
- twitAuth->setOAuthTokenSecret( s->twitterOAuthTokenSecret().toLatin1() );
if ( m_postGTtype != "Direct Message" )
{
QTweetStatusUpdate *statUpdate = new QTweetStatusUpdate( twitAuth, this );
diff --git a/src/sip/twitter/twitterconfigwidget.h b/src/sip/twitter/twitterconfigwidget.h
index 85fabce90..3a059bfa8 100644
--- a/src/sip/twitter/twitterconfigwidget.h
+++ b/src/sip/twitter/twitterconfigwidget.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -28,6 +28,7 @@
#include
+class TwitterPlugin;
namespace Ui {
class TwitterConfigWidget;
@@ -38,12 +39,12 @@ class TwitterConfigWidget : public QWidget
Q_OBJECT
public:
- explicit TwitterConfigWidget( SipPlugin* plugin = 0, QWidget *parent = 0 );
+ explicit TwitterConfigWidget( TwitterPlugin* plugin = 0, QWidget *parent = 0 );
~TwitterConfigWidget();
signals:
void twitterAuthed( bool authed );
-
+
private slots:
void authDeauthTwitter();
void startPostGotTomahawkStatus();
@@ -58,9 +59,9 @@ private slots:
private:
void authenticateTwitter();
void deauthenticateTwitter();
-
+
Ui::TwitterConfigWidget *ui;
- SipPlugin *m_plugin;
+ TwitterPlugin *m_plugin;
QString m_postGTtype;
};
diff --git a/src/sip/twitter/twitterconfigwidget.ui b/src/sip/twitter/twitterconfigwidget.ui
index 1bb728fd0..949b68cbc 100644
--- a/src/sip/twitter/twitterconfigwidget.ui
+++ b/src/sip/twitter/twitterconfigwidget.ui
@@ -6,10 +6,16 @@
0
0
- 795
- 509
+ 438
+ 266
+
+
+ 0
+ 0
+
+
-
diff --git a/src/sip/zeroconf/CMakeLists.txt b/src/sip/zeroconf/CMakeLists.txt
index 199704dff..730678e3c 100644
--- a/src/sip/zeroconf/CMakeLists.txt
+++ b/src/sip/zeroconf/CMakeLists.txt
@@ -15,12 +15,13 @@ set( zeroconfHeaders
tomahawkzeroconf.h
)
-include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ..
+include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ..
${QT_INCLUDE_DIR}
)
+qt4_add_resources( RC_SRCS "resources.qrc" )
qt4_wrap_cpp( zeroconfMoc ${zeroconfHeaders} )
-add_library( tomahawk_sipzeroconf SHARED ${zeroconfSources} ${zeroconfMoc} )
+add_library( tomahawk_sipzeroconf SHARED ${zeroconfSources} ${zeroconfMoc} ${RC_SRCS} )
IF( WIN32 )
SET( OS_SPECIFIC_LINK_LIBRARIES
diff --git a/src/sip/zeroconf/resources.qrc b/src/sip/zeroconf/resources.qrc
new file mode 100644
index 000000000..32e3d457e
--- /dev/null
+++ b/src/sip/zeroconf/resources.qrc
@@ -0,0 +1,5 @@
+
+
+zeroconf-icon.png
+
+
diff --git a/src/sip/zeroconf/zeroconf-icon.png b/src/sip/zeroconf/zeroconf-icon.png
new file mode 100644
index 000000000..7371f8eae
Binary files /dev/null and b/src/sip/zeroconf/zeroconf-icon.png differ
diff --git a/src/sip/zeroconf/zeroconf.cpp b/src/sip/zeroconf/zeroconf.cpp
index 7e6bbf955..d169ba41f 100644
--- a/src/sip/zeroconf/zeroconf.cpp
+++ b/src/sip/zeroconf/zeroconf.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -20,24 +20,43 @@
#include
+SipPlugin*
+ZeroconfFactory::createPlugin( const QString& pluginId )
+{
+ return new ZeroconfPlugin( pluginId.isEmpty() ? generateId() : pluginId );
+}
+
const QString
-ZeroconfPlugin::name()
+ZeroconfPlugin::name() const
{
return QString( MYNAME );
}
const QString
-ZeroconfPlugin::accountName()
+ZeroconfPlugin::accountName() const
{
- return QString();
+ return QString( MYNAME );
}
const QString
-ZeroconfPlugin::friendlyName()
+ZeroconfPlugin::friendlyName() const
{
- return QString( "Zeroconf" );
+ return QString( MYNAME );
}
+SipPlugin::ConnectionState
+ZeroconfPlugin::connectionState() const
+{
+ return m_state;
+}
+
+QIcon
+ZeroconfFactory::icon() const
+{
+ return QIcon( ":/zeroconf-icon.png" );
+}
+
+
bool
ZeroconfPlugin::connectPlugin( bool /*startup*/ )
{
@@ -47,7 +66,7 @@ ZeroconfPlugin::connectPlugin( bool /*startup*/ )
SLOT( lanHostFound( QString, int, QString, QString ) ) );
m_zeroconf->advertise();
- m_isOnline = true;
+ m_state = Connected;
foreach( const QStringList& nodeSet, m_cachedNodes )
{
@@ -61,12 +80,19 @@ ZeroconfPlugin::connectPlugin( bool /*startup*/ )
void
ZeroconfPlugin::disconnectPlugin()
{
- m_isOnline = false;
+ m_state = Disconnected;
delete m_zeroconf;
m_zeroconf = 0;
}
+QIcon
+ZeroconfPlugin::icon() const
+{
+ return QIcon( ":/zeroconf-icon.png" );
+}
+
+
void
ZeroconfPlugin::lanHostFound( const QString& host, int port, const QString& name, const QString& nodeid )
{
@@ -75,7 +101,7 @@ ZeroconfPlugin::lanHostFound( const QString& host, int port, const QString& name
qDebug() << "Found LAN host:" << host << port << nodeid;
- if ( !m_isOnline )
+ if ( m_state != Connected )
{
qDebug() << "Not online, so not connecting.";
QStringList nodeSet;
@@ -83,11 +109,11 @@ ZeroconfPlugin::lanHostFound( const QString& host, int port, const QString& name
m_cachedNodes.append( nodeSet );
return;
}
-
+
if ( !Servent::instance()->connectedToSession( nodeid ) )
Servent::instance()->connectToPeer( host, port, "whitelist", name, nodeid );
else
qDebug() << "Already connected to" << host;
}
-Q_EXPORT_PLUGIN2( sip, ZeroconfPlugin )
+Q_EXPORT_PLUGIN2( sipfactory, ZeroconfFactory )
diff --git a/src/sip/zeroconf/zeroconf.h b/src/sip/zeroconf/zeroconf.h
index 059f4727a..6457e319e 100644
--- a/src/sip/zeroconf/zeroconf.h
+++ b/src/sip/zeroconf/zeroconf.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -24,17 +24,33 @@
#include "../sipdllmacro.h"
-#define MYNAME "SIPZEROCONF"
+#define MYNAME "Local Network"
+
+class SIPDLLEXPORT ZeroconfFactory : public SipPluginFactory
+{
+ 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; }
+ virtual QIcon icon() const;
+
+ virtual SipPlugin* createPlugin ( const QString& pluginId = QString() );
+};
class SIPDLLEXPORT ZeroconfPlugin : public SipPlugin
{
Q_OBJECT
- Q_INTERFACES( SipPlugin )
public:
- ZeroconfPlugin()
- : m_zeroconf( 0 )
- , m_isOnline( false )
+ ZeroconfPlugin( const QString& pluginId )
+ : SipPlugin( pluginId )
+ , m_zeroconf( 0 )
+ , m_state( Disconnected )
, m_cachedNodes()
{
qDebug() << Q_FUNC_INFO;
@@ -44,11 +60,13 @@ public:
{
qDebug() << Q_FUNC_INFO;
}
-
- virtual bool isValid() { return true; }
- virtual const QString name();
- virtual const QString friendlyName();
- virtual const QString accountName();
+
+ virtual const QString name() const;
+ virtual const QString friendlyName() const;
+ virtual const QString accountName() const;
+ virtual ConnectionState connectionState() const;
+ virtual bool isValid() const { return true; };
+ virtual QIcon icon() const;
public slots:
virtual bool connectPlugin( bool startup );
@@ -77,7 +95,7 @@ private slots:
private:
TomahawkZeroconf* m_zeroconf;
- bool m_isOnline;
+ ConnectionState m_state;
QVector m_cachedNodes;
};
diff --git a/src/sipconfigdelegate.cpp b/src/sipconfigdelegate.cpp
new file mode 100644
index 000000000..4223f3a59
--- /dev/null
+++ b/src/sipconfigdelegate.cpp
@@ -0,0 +1,253 @@
+/*
+ Copyright (C) 2011 Leo Franchi
+
+ 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 .
+*/
+
+
+#include "sipconfigdelegate.h"
+
+#include "sip/SipModel.h"
+#include "sip/SipPlugin.h"
+#include "utils/tomahawkutils.h"
+#include
+#include
+
+#define ICONSIZE 24
+SipConfigDelegate::SipConfigDelegate( QObject* parent )
+ : ConfigDelegateBase ( parent )
+{
+ connect( this, SIGNAL( configPressed( QModelIndex ) ), this, SLOT( askedForEdit( QModelIndex ) ) );
+}
+
+bool
+SipConfigDelegate::editorEvent ( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index )
+{
+ return ConfigDelegateBase::editorEvent( event, model, option, index );
+}
+
+void
+SipConfigDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
+{
+ QStyleOptionViewItemV4 opt = option;
+ initStyleOption( &opt, index );
+ QRect itemRect = opt.rect;
+ int top = itemRect.top();
+ int mid = itemRect.height() / 2;
+
+ // one line bold for account name
+ // space below it fro an error
+ // checkbox, icon, name, online/offline status, config icon
+ QFont name = opt.font;
+ name.setPointSize( name.pointSize() + 2 );
+ name.setBold( true );
+
+ QFont error = opt.font;
+ error.setItalic( true );
+ error.setPointSize( error.pointSize() - 2 );
+
+ // draw the background
+ const QWidget* w = opt.widget;
+ QStyle* style = w ? w->style() : QApplication::style();
+ style->drawPrimitive( QStyle::PE_PanelItemViewItem, &opt, painter, w );
+
+ int checkLeftEdge = 8;
+ int iconLeftEdge = checkLeftEdge + ICONSIZE + PADDING;
+ int textLeftEdge = iconLeftEdge + ICONSIZE + PADDING;
+
+ if( index.data( SipModel::FactoryRole ).toBool() ) { // this is the "add new account" row
+ // draw a border and background
+ painter->save();
+ painter->setRenderHints( QPainter::Antialiasing );
+ painter->setBrush( QApplication::palette().color( QPalette::Active, QPalette::Highlight ).lighter( 150 ) );
+ QPainterPath roundedRect;
+ roundedRect.addRoundedRect( itemRect.adjusted( 1, 1, -1, -1 ), 3, 3 );
+ painter->drawPath( roundedRect );
+ painter->setBrush( QApplication::palette().color( QPalette::Active, QPalette::Highlight ).lighter( 170 ) );
+ painter->fillPath( roundedRect, painter->brush() );
+ painter->restore();
+
+ // draw "+" icon in checkbox column
+ int rectW = 18;
+ int diff = ( ICONSIZE/ 2 ) - ( rectW / 2) ;
+ int pos = ( mid ) - ( rectW / 2 );
+ QRect plusRect = QRect( checkLeftEdge + diff, pos + top, rectW, rectW );
+ QPixmap p( RESPATH "images/list-add.png" );
+ painter->drawPixmap( plusRect, p );
+
+ // draw text
+ QFont f = opt.font;
+ f.setPointSize( f.pointSize() );
+ f.setBold( true );
+ QFontMetrics fm( f );
+ QString text = index.data( Qt::DisplayRole ).toString();
+ QRect textR = fm.boundingRect( text );
+ textR.moveLeft( textLeftEdge );
+ textR.moveTop( mid - ( textR.height() / 2 ) + top );
+ textR.setRight( itemRect.right() );
+ painter->setFont( f );
+ painter->drawText( textR, text );
+ } else if( index.data( SipModel::FactoryItemRole ).toBool() ) { // this is an account type
+
+// ConfigDelegateBase::paint( painter, opt, index );
+// int indent = 10;
+ // draw a border and background
+ painter->save();
+ painter->setRenderHints( QPainter::Antialiasing );
+ painter->setBrush( QApplication::palette().color( QPalette::Active, QPalette::Highlight ).lighter( 170 ) );
+ QPainterPath roundedRect;
+ roundedRect.addRoundedRect( itemRect.adjusted( 1, 1, -1, -1 ), 3, 3 );
+ painter->drawPath( roundedRect );
+ painter->setBrush( QApplication::palette().color( QPalette::Active, QPalette::Highlight ).lighter( 180 ) );
+ painter->fillPath( roundedRect, painter->brush() );
+ painter->restore();
+
+ QIcon icon = index.data( SipModel::FactoryItemIcon ).value< QIcon >();
+ if( !icon.isNull() ) {
+ int rectW = 18;
+ int diff = ( ICONSIZE/ 2 ) - ( rectW / 2) ;
+ int pos = ( mid ) - ( rectW / 2 );
+ QRect rect = QRect( checkLeftEdge + diff, pos + top, rectW, rectW );
+ QPixmap p( icon.pixmap( rect.size() ) );
+ painter->drawPixmap( rect, p );
+ }
+
+ // draw text
+ QFont f = opt.font;
+ f.setPointSize( f.pointSize() );
+ f.setBold( true );
+ QFontMetrics fm( f );
+ QString text = index.data( Qt::DisplayRole ).toString();
+ QRect textR = fm.boundingRect( text );
+ textR.moveLeft( textLeftEdge );
+ textR.moveTop( mid - ( textR.height() / 2 ) + top );
+ textR.setRight( itemRect.right() );
+ painter->setFont( f );
+ painter->drawText( textR, text );
+ } else { // this is an existing account to show
+ // draw checkbox first
+ int pos = ( mid ) - ( ICONSIZE / 2 );
+ QRect checkRect = QRect( checkLeftEdge, pos + top, ICONSIZE, ICONSIZE );
+ opt.rect = checkRect;
+ drawCheckBox( opt, painter, w );
+
+ // draw the icon if it exists
+ pos = ( mid ) - ( ICONSIZE / 2 );
+ if( !index.data( Qt::DecorationRole ).value< QIcon >().isNull() ) {
+ QRect prect = QRect( iconLeftEdge, pos + top, ICONSIZE, ICONSIZE );
+
+ painter->save();
+ painter->drawPixmap( prect, index.data( Qt::DecorationRole ).value< QIcon >().pixmap( prect.size() ) );
+ painter->restore();
+ }
+
+ // from the right edge--config status and online/offline
+ QRect confRect = QRect( itemRect.width() - ICONSIZE - 2 * PADDING, mid - ICONSIZE / 2 + top, ICONSIZE, ICONSIZE );
+ if( index.data( SipModel::HasConfig ).toBool() ) {
+
+ QStyleOptionToolButton topt;
+ topt.rect = confRect;
+ topt.pos = confRect.topLeft();
+
+ drawConfigWrench( painter, opt, topt );
+ }
+
+ // draw the online/offline status
+ int statusIconSize = 10;
+ int statusX = confRect.left() - 2*PADDING - statusIconSize;
+ QFont statusF = opt.font;
+ statusF.setPointSize( statusF.pointSize() - 2 );
+ QFontMetrics statusFM( statusF );
+
+ QPixmap p;
+ QString statusText;
+ if( index.data( SipModel::ConnectionStateRole ).toInt() == SipPlugin::Connected ) {
+ p = QPixmap( RESPATH "images/sipplugin-online.png" );
+ statusText = tr( "Online" );
+ } else {
+ p = QPixmap( RESPATH "images/sipplugin-offline.png" );
+ statusText = tr( "Offline" );
+ }
+ p = p.scaled( statusIconSize, statusIconSize, Qt::KeepAspectRatio, Qt::SmoothTransformation );
+ painter->drawPixmap( statusX, mid - statusIconSize / 2 + top, statusIconSize, statusIconSize, p );
+ int width = statusFM.width( statusText );
+ statusX = statusX - PADDING - width;
+ painter->save();
+ painter->setFont( statusF );
+ painter->drawText( QRect( statusX, mid - statusFM.height() / 2 + top, width, statusFM.height() ), statusText );
+ painter->restore();
+
+ // name
+ painter->save();
+ QFontMetrics namefm( name );
+ int nameHeight = namefm.boundingRect( "test" ).height();
+ // pos will the top-left point of the text rect
+ pos = mid - ( nameHeight / 2 );
+ // TODO bound with config icon and offline/online status
+ width = itemRect.width() - textLeftEdge;
+
+ if( !index.data( SipModel::ErrorString ).toString().isEmpty() ) { // error, show that too
+ QRect errorRect( textLeftEdge, mid + top, width, mid - PADDING );
+
+ QFontMetrics errorFm( error );
+ QString str = errorFm.elidedText( index.data( SipModel::ErrorString ).toString(), Qt::ElideRight, errorRect.width() );
+ painter->setFont( error );
+ painter->drawText( errorRect, str );
+
+ pos = mid - errorRect.height() - 2; // move the name rect up
+ }
+ QString nameStr = namefm.elidedText( index.data( Qt::DisplayRole ).toString(), Qt::ElideRight, width );
+ painter->setFont( name );
+ painter->drawText( QRect( textLeftEdge, pos + top, width, nameHeight ), nameStr );
+ painter->restore();
+ }
+}
+
+QRect
+SipConfigDelegate::configRectForIndex( const QStyleOptionViewItem& option, const QModelIndex& idx ) const
+{
+ QStyleOptionViewItemV4 opt = option;
+ initStyleOption( &opt, idx );
+ QRect itemRect = opt.rect;
+ QRect confRect = QRect( itemRect.width() - ICONSIZE - 2 * PADDING, (opt.rect.height() / 2) - ICONSIZE / 2 + opt.rect.top(), ICONSIZE, ICONSIZE );
+ return confRect;
+}
+
+
+QSize
+SipConfigDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
+{
+ if( index.data( SipModel::FactoryRole ).toBool() || index.data( SipModel::FactoryItemRole ).toBool() ) { // this is the "add new account" row
+ // enough space for one line of text
+ QStyleOptionViewItemV4 opt = option;
+ initStyleOption( &opt, index );
+ int width = QStyledItemDelegate::sizeHint( option, index ).width();
+
+ QFont name = opt.font;
+ name.setPointSize( name.pointSize() + 1 );
+ name.setBold( true );
+ QFontMetrics sfm( name );
+ return QSize( width, 3 * PADDING + sfm.height() );
+ } else { // this is an existing account to show
+ return ConfigDelegateBase::sizeHint( option, index );
+ }
+}
+
+void
+SipConfigDelegate::askedForEdit( const QModelIndex& idx )
+{
+ emit openConfig( qobject_cast< SipPlugin* >( idx.data( SipModel::SipPluginData ).value< QObject* >() ) );
+}
+
+
diff --git a/src/sipconfigdelegate.h b/src/sipconfigdelegate.h
new file mode 100644
index 000000000..c69ed9edc
--- /dev/null
+++ b/src/sipconfigdelegate.h
@@ -0,0 +1,45 @@
+/*
+ Copyright (C) 2011 Leo Franchi
+
+ 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 .
+*/
+
+
+#ifndef SIPCONFIGDELEGATE_H
+#define SIPCONFIGDELEGATE_H
+
+#include "configdelegatebase.h"
+
+class SipPlugin;
+class SipPluginFactory;
+class SipConfigDelegate : public ConfigDelegateBase
+{
+ Q_OBJECT
+public:
+ SipConfigDelegate( QObject* parent = 0);
+
+ virtual void paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
+ virtual bool editorEvent ( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
+ virtual QSize sizeHint ( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
+
+ virtual QRect configRectForIndex( const QStyleOptionViewItem& option, const QModelIndex& idx ) const;
+private slots:
+ void askedForEdit( const QModelIndex& idx );
+
+signals:
+ void sipFactoryClicked( SipPluginFactory* );
+ void openConfig( SipPlugin* );
+};
+
+#endif // SIPCONFIGDELEGATE_H
diff --git a/src/sourcetree/items/categoryitems.cpp b/src/sourcetree/items/categoryitems.cpp
index 2ba177d20..da1121631 100644
--- a/src/sourcetree/items/categoryitems.cpp
+++ b/src/sourcetree/items/categoryitems.cpp
@@ -167,7 +167,6 @@ CategoryItem::insertItems( QList< SourceTreeItem* > items )
curCount--;
beginRowsAdded( curCount, curCount + items.size() - 1 );
foreach( SourceTreeItem* item, items ) {
- int index = m_showAdd ? children().count() - 1 : children().count();
insertChild( children().count() - 1, item );
}
endRowsAdded();
@@ -180,4 +179,4 @@ CategoryItem::activate()
if( m_category == SourcesModel::StationsCategory ) {
// TODO activate stations page
}
-}
\ No newline at end of file
+}
diff --git a/src/sourcetree/sourcesmodel.cpp b/src/sourcetree/sourcesmodel.cpp
index 4577b3264..61adc5f0b 100644
--- a/src/sourcetree/sourcesmodel.cpp
+++ b/src/sourcetree/sourcesmodel.cpp
@@ -44,7 +44,7 @@ SourcesModel::SourcesModel( QObject* parent )
appendItem( source_ptr() );
// add misc children of root node
- GenericPageItem* recent = new GenericPageItem( this, m_rootItem->children().at( 0 ), tr( "Recently Played" ), QIcon( RESPATH "images/recently-played.png" ),
+ new GenericPageItem( this, m_rootItem->children().at( 0 ), tr( "Recently Played" ), QIcon( RESPATH "images/recently-played.png" ),
boost::bind( &ViewManager::showWelcomePage, ViewManager::instance() ),
boost::bind( &ViewManager::welcomeWidget, ViewManager::instance() )
);
@@ -193,10 +193,9 @@ SourcesModel::flags( const QModelIndex& index ) const
void
SourcesModel::appendItem( const Tomahawk::source_ptr& source )
{
-
beginInsertRows( QModelIndex(), rowCount(), rowCount() );
// append to end
- CollectionItem* item = new CollectionItem( this, m_rootItem, source );
+ new CollectionItem( this, m_rootItem, source );
endInsertRows();
}
@@ -339,7 +338,7 @@ SourcesModel::linkSourceItemToPage( SourceTreeItem* item, ViewPage* p )
// TODO handle removal
m_sourceTreeLinks[ p ] = item;
- if( m_viewPageDelayedCacheItem = p )
+ if( m_viewPageDelayedCacheItem == p )
emit selectRequest( indexFromItem( item ) );
m_viewPageDelayedCacheItem = 0;
diff --git a/src/sourcetree/sourcetreeview.cpp b/src/sourcetree/sourcetreeview.cpp
index 3caf2b908..a504126ed 100644
--- a/src/sourcetree/sourcetreeview.cpp
+++ b/src/sourcetree/sourcetreeview.cpp
@@ -411,14 +411,12 @@ SourceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, co
CollectionItem* colItem = qobject_cast< CollectionItem* >( item );
Q_ASSERT( colItem );
bool status = !( !colItem || colItem->source().isNull() || !colItem->source()->isOnline() );
-
+ QPixmap avatar( RESPATH "images/user-avatar.png" );
QString tracks;
QString name = index.data().toString();
int figWidth = 0;
- QRect iconRect = option.rect.adjusted( 4, 6, -option.rect.width() + option.rect.height() - 12 + 4, -6 );
- QPixmap avatar = index.data( Qt::DecorationRole ).value< QIcon >().pixmap( iconRect.size() );
if ( status && colItem && !colItem->source().isNull() )
{
tracks = QString::number( colItem->source()->trackCount() );
@@ -428,6 +426,7 @@ SourceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, co
name = colItem->source()->friendlyName();
}
+ QRect iconRect = option.rect.adjusted( 4, 6, -option.rect.width() + option.rect.height() - 12 + 4, -6 );
painter->drawPixmap( iconRect, avatar.scaledToHeight( iconRect.height(), Qt::SmoothTransformation ) );
diff --git a/src/stackedsettingsdialog.ui b/src/stackedsettingsdialog.ui
new file mode 100644
index 000000000..2bb477cca
--- /dev/null
+++ b/src/stackedsettingsdialog.ui
@@ -0,0 +1,676 @@
+
+
+ StackedSettingsDialog
+
+
+
+ 0
+ 0
+ 641
+ 370
+
+
+
+ Tomahawk Settings
+
+
+
+ 0
+
+
+ 2
+
+
+ 0
+
+
+ 0
+
+
-
+
+
-
+
+
-
+
+
+
+ 16777215
+ 16777215
+
+
+
+ Qt::NoFocus
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Sunken
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ Qt::ScrollBarAlwaysOff
+
+
+ true
+
+
+
+ 48
+ 48
+
+
+
+ QListView::Static
+
+
+ QListView::Adjust
+
+
+ QListView::Batched
+
+
+ 1
+
+
+ QListView::IconMode
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Fixed
+
+
+
+ 1
+ 4
+
+
+
+
+
+
+ -
+
+
+ 0
+
+
+
+
+ 0
+
+
-
+
+
+ Accounts
+
+
+
-
+
+
+ Connect to your friends with Google Chat, Twitter, and more.
+
+
+
+ -
+
+
-
+
+
+ 0
+
+
+ false
+
+
+ false
+
+
+ true
+
+
+ true
+
+
+ false
+
+
+
+ -
+
+
-
+
+
+ ...
+
+
+
+ :/data/images/list-add.png:/data/images/list-add.png
+
+
+ QToolButton::InstantPopup
+
+
+
+ -
+
+
+ ...
+
+
+
+ :/data/images/list-remove.png:/data/images/list-remove.png
+
+
+ QToolButton::DelayedPopup
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+ -
+
+
+
+ 50
+ false
+
+
+
+ Local Music Information
+
+
+
+ 2
+
+
-
+
+
+ Path to scan for music files:
+
+
+
+ -
+
+
-
+
+
+ -
+
+
+ ...
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Watch for changes
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+ 0
+
+ -
+
+
+ Last.fm Login
+
+
+
+ 2
+
+
-
+
+
+ Qt::LeftToRight
+
+
+ Scrobble tracks to Last.fm
+
+
+
+ -
+
+
-
+
+
+ Username:
+
+
+
+ -
+
+
+ -
+
+
+ Password:
+
+
+
+ -
+
+
+ QLineEdit::Password
+
+
+
+
+
+ -
+
+
-
+
+
+ Test Login
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+ -
+
+
+ Script Resolvers
+
+
+
+ 2
+
+
-
+
+
+ Script resolver search for a given track to make it playable.
+
+
+
+ -
+
+
-
+
+
+ true
+
+
+ QAbstractItemView::SingleSelection
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+ true
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+
+
+
+
+ :/data/images/list-add.png:/data/images/list-add.png
+
+
+
+ -
+
+
+
+
+
+
+ :/data/images/list-remove.png:/data/images/list-remove.png
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Advanced Network Settings
+
+
+
+ 2
+
+
-
+
+
-
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ If you're having difficulty connecting to peers, try setting this to your external IP address/host name and a port number (default 50210). Make sure to forward that port to this machine!
+
+
+ true
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Static Host Name:
+
+
+
+ -
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Static Port:
+
+
+
+ -
+
+
+ 65535
+
+
+ 50210
+
+
+
+
+
+ -
+
+
+ Qt::RightToLeft
+
+
+ Always use static host name/port? (Overrides UPnP discovery/port forwarding)
+
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Proxy Settings...
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ Qt::RightToLeft
+
+
+ Playdar HTTP API
+
+
+ true
+
+
+
+ -
+
+
+ Qt::RightToLeft
+
+
+ Use UPnP to establish port forward
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ StackedSettingsDialog
+ accept()
+
+
+ 222
+ 347
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ StackedSettingsDialog
+ reject()
+
+
+ 290
+ 353
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/src/tomahawkapp.cpp b/src/tomahawkapp.cpp
index d4c8e0947..2be55293e 100644
--- a/src/tomahawkapp.cpp
+++ b/src/tomahawkapp.cpp
@@ -247,7 +247,6 @@ TomahawkApp::init()
QNetworkProxy::setApplicationProxy( *TomahawkUtils::proxy() );
qDebug() << "Init SIP system.";
- m_sipHandler = new SipHandler( this );
#ifndef TOMAHAWK_HEADLESS
if ( !m_headless )
@@ -323,6 +322,12 @@ TomahawkApp::audioControls()
}
#endif
+SipHandler*
+TomahawkApp::sipHandler()
+{
+ return SipHandler::instance();
+}
+
void
TomahawkApp::registerMetaTypes()
{
@@ -501,14 +506,15 @@ TomahawkApp::setupSIP()
qDebug() << Q_FUNC_INFO;
//FIXME: jabber autoconnect is really more, now that there is sip -- should be renamed and/or split out of jabber-specific settings
- if( !arguments().contains( "--nosip" ) && TomahawkSettings::instance()->jabberAutoConnect() )
+ if( !arguments().contains( "--nosip" ) )
{
#ifdef GLOOX_FOUND
m_xmppBot = new XMPPBot( this );
#endif
qDebug() << "Connecting SIP classes";
- m_sipHandler->connectPlugins( true );
+ SipHandler::instance()->loadFromConfig( true );
+
// m_sipHandler->setProxy( *TomahawkUtils::proxy() );
}
diff --git a/src/tomahawkwindow.cpp b/src/tomahawkwindow.cpp
index 56fdcb1ea..6885e24eb 100644
--- a/src/tomahawkwindow.cpp
+++ b/src/tomahawkwindow.cpp
@@ -179,7 +179,9 @@ TomahawkWindow::TomahawkWindow( QWidget* parent )
statusBar()->addPermanentWidget( m_audioControls, 1 );
// propagate sip menu
- foreach( SipPlugin *plugin, APP->sipHandler()->plugins() )
+ connect( SipHandler::instance(), SIGNAL( pluginAdded( SipPlugin* ) ), this, SLOT( onSipPluginAdded( SiPlugin* ) ) );
+ connect( SipHandler::instance(), SIGNAL( pluginRemoved( SipPlugin* ) ), this, SLOT( onSipPluginRemoved( SiPlugin* ) ) );
+ foreach( SipPlugin *plugin, APP->sipHandler()->allPlugins() )
{
connect( plugin, SIGNAL( addMenu( QMenu* ) ), this, SLOT( pluginMenuAdded( QMenu* ) ) );
connect( plugin, SIGNAL( removeMenu( QMenu* ) ), this, SLOT( pluginMenuRemoved( QMenu* ) ) );
@@ -501,6 +503,19 @@ TomahawkWindow::onSipDisconnected()
ui->actionToggleConnect->setText( tr( "Go &online" ) );
}
+void
+TomahawkWindow::onSipPluginAdded( SipPlugin* p )
+{
+ connect( p, SIGNAL( addMenu( QMenu* ) ), this, SLOT( pluginMenuAdded( QMenu* ) ) );
+ connect( p, SIGNAL( removeMenu( QMenu* ) ), this, SLOT( pluginMenuRemoved( QMenu* ) ) );
+}
+
+void
+TomahawkWindow::onSipPluginRemoved( SipPlugin* p )
+{
+ Q_UNUSED( p );
+}
+
void
TomahawkWindow::onSipError()
diff --git a/src/tomahawkwindow.h b/src/tomahawkwindow.h
index ae5073461..f86a5b54d 100644
--- a/src/tomahawkwindow.h
+++ b/src/tomahawkwindow.h
@@ -27,6 +27,7 @@
#include "result.h"
+class SipPlugin;
class SourceTreeView;
class QAction;
@@ -83,6 +84,9 @@ private slots:
void showAboutTomahawk();
void checkForUpdates();
+ void onSipPluginAdded( SipPlugin* p );
+ void onSipPluginRemoved( SipPlugin* p );
+
void minimize();
void maximize();
diff --git a/thirdparty/jreen b/thirdparty/jreen
index 8f995f246..40fd6b0a3 160000
--- a/thirdparty/jreen
+++ b/thirdparty/jreen
@@ -1 +1 @@
-Subproject commit 8f995f246637f533feb7124744e113034a32b505
+Subproject commit 40fd6b0a3dbc729fdf1db8490848b43d5b1f57f5