PageRenderTime 494ms CodeModel.GetById 80ms app.highlight 19ms RepoModel.GetById 52ms app.codeStats 0ms

/src/sip/jabber/avatarmanager.cpp

http://github.com/tomahawk-player/tomahawk
C++ | 192 lines | 125 code | 37 blank | 30 comment | 12 complexity | 834f23217387ee30a6ec4e1e412482f9 MD5 | raw file
  1/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
  2 *
  3 *   Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
  4 *
  5 *   Tomahawk is free software: you can redistribute it and/or modify
  6 *   it under the terms of the GNU General Public License as published by
  7 *   the Free Software Foundation, either version 3 of the License, or
  8 *   (at your option) any later version.
  9 *
 10 *   Tomahawk is distributed in the hope that it will be useful,
 11 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 12 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 13 *   GNU General Public License for more details.
 14 *
 15 *   You should have received a copy of the GNU General Public License
 16 *   along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
 17 */
 18
 19#include "avatarmanager.h"
 20
 21#include "utils/tomahawkutils.h"
 22
 23#include <jreen/vcard.h>
 24#include <jreen/vcardupdate.h>
 25#include <jreen/presence.h>
 26#include <jreen/iqreply.h>
 27
 28#include <QDir>
 29#include <QCryptographicHash>
 30#include <QPixmap>
 31
 32#include "utils/logger.h"
 33
 34
 35AvatarManager::AvatarManager(Jreen::Client *client) :
 36    m_cacheDir(TomahawkUtils::appDataDir().absolutePath().append("/jreen/"))
 37{
 38    m_client = client;
 39
 40    m_cachedAvatars = m_cacheDir.entryList();
 41
 42    connect(m_client, SIGNAL(serverFeaturesReceived(QSet<QString>)), SLOT(onNewConnection()));
 43    connect(m_client, SIGNAL(presenceReceived(Jreen::Presence)), SLOT(onNewPresence(Jreen::Presence)));
 44    connect(m_client, SIGNAL(iqReceived(Jreen::IQ)), SLOT(onNewIq(Jreen::IQ)));
 45
 46    connect(this, SIGNAL(newAvatar(QString)), SLOT(onNewAvatar(QString)));
 47}
 48
 49AvatarManager::~AvatarManager()
 50{
 51}
 52
 53void AvatarManager::onNewConnection()
 54{
 55    fetchVCard( m_client->jid().bare() );
 56}
 57
 58
 59void AvatarManager::fetchVCard(const QString &jid)
 60{
 61//    qDebug() << Q_FUNC_INFO;
 62
 63    Jreen::IQ iq(Jreen::IQ::Get, jid );
 64    iq.addExtension(new Jreen::VCard());
 65    Jreen::IQReply *reply = m_client->send(iq);
 66    connect(reply, SIGNAL(received(Jreen::IQ)), SLOT(onNewIq(Jreen::IQ)));
 67}
 68
 69void AvatarManager::onNewPresence(const Jreen::Presence& presence)
 70{
 71    Jreen::VCardUpdate::Ptr update = presence.payload<Jreen::VCardUpdate>();
 72    if(update)
 73    {
 74//        qDebug() << "vcard: found update for" << presence.from().full();
 75        if(!isCached(update->photoHash()))
 76        {
 77//            qDebug() << presence.from().full() << "vcard: photo not cached, starting request..." << update->photoHash();
 78            fetchVCard( presence.from().bare() );
 79        }
 80        else
 81        {
 82//            qDebug() << presence.from().full() << "vcard: photo already cached no request necessary " << update->photoHash();
 83            m_JidsAvatarHashes.insert( update->photoHash(), presence.from().bare() );
 84
 85            if ( !this->avatar( presence.from().bare() ).isNull() )
 86                emit newAvatar(presence.from().bare());
 87        }
 88    }
 89    else
 90    {
 91//        qDebug() << Q_FUNC_INFO << presence.from().full() << "got no statusupdateextension";
 92
 93        //TODO: do we want this? might fetch avatars for broken clients
 94        fetchVCard( presence.from().bare() );
 95    }
 96}
 97
 98void AvatarManager::onNewIq(const Jreen::IQ& iq)
 99{
100    Jreen::VCard::Ptr vcard = iq.payload<Jreen::VCard>();
101    if(vcard)
102    {
103        iq.accept();
104
105//        qDebug() << Q_FUNC_INFO << "Got vcard from " << iq.from().full();
106
107        QString id = iq.from().full();
108        QString avatarHash;
109
110        const Jreen::VCard::Photo &photo = vcard->photo();
111        if (!photo.data().isEmpty()) {
112//            qDebug() << "vcard: got photo data" << id;
113
114            avatarHash = QCryptographicHash::hash(photo.data(), QCryptographicHash::Sha1).toHex();
115
116            if (!m_cacheDir.exists())
117                m_cacheDir.mkpath( avatarDir( avatarHash ).absolutePath() );
118
119
120            QFile file(avatarPath(avatarHash));
121            if (file.open(QIODevice::WriteOnly)) {
122                file.write(photo.data());
123                file.close();
124            }
125
126            m_cachedAvatars.append(avatarHash);
127            m_JidsAvatarHashes.insert( avatarHash, iq.from().bare() );
128
129            Q_ASSERT(!this->avatar(iq.from().bare()).isNull());
130            emit newAvatar(iq.from().bare());
131        }
132        else
133        {
134//            qDebug() << "vcard: got no photo data" << id;
135        }
136
137        // got own presence
138        if ( m_client->jid().bare() == id )
139        {
140//            qDebug() << Q_FUNC_INFO << "got own vcard";
141
142            Jreen::Presence presence = m_client->presence();
143            Jreen::VCardUpdate::Ptr update = presence.payload<Jreen::VCardUpdate>();
144            if (update->photoHash() != avatarHash)
145            {
146                qDebug() << Q_FUNC_INFO << "Updating own presence...";
147
148                update->setPhotoHash(avatarHash);
149                m_client->send(presence);
150            }
151        }
152    }
153}
154
155QPixmap AvatarManager::avatar(const QString &jid) const
156{
157    if( isCached( avatarHash( jid ) ) )
158    {
159        return QPixmap( avatarPath( avatarHash( jid ) ) );
160    }
161    else
162    {
163        return QPixmap();
164    }
165}
166
167QString AvatarManager::avatarHash(const QString &jid) const
168{
169    //qDebug() << Q_FUNC_INFO << jid << m_JidsAvatarHashes.key(jid);
170    return m_JidsAvatarHashes.key(jid);
171}
172
173QDir AvatarManager::avatarDir(const QString&) const
174{
175    return m_cacheDir;
176}
177
178QString AvatarManager::avatarPath(const QString &avatarHash) const
179{
180    Q_ASSERT(!avatarHash.contains("@"));
181    return avatarDir(avatarHash).absoluteFilePath(avatarHash);
182}
183
184bool AvatarManager::isCached(const QString &avatarHash) const
185{
186    return m_cachedAvatars.contains( avatarHash );
187}
188
189void AvatarManager::onNewAvatar(const QString&)
190{
191//    qDebug() << Q_FUNC_INFO <<  "Found new Avatar..." << jid;
192}