Hello folks,

A problem that has been bugging me for quite a while now since kopete
shifted into kde4 is the fact that all the profile photos are all
completely scaled in a rather odd and bad way. As it turns out,
something called the avatar manager made its appearance at some point
and most protocols shifted to using the avatar manager to store
contact photos. Now the avatar manager either down sizes photos and/or
pads them with transparent pixels until the image fits in a 96x96
square. This causes problems in displaying the avatar of contacts in
the contact list and the chat box since certain avatars (most notably
almost all aim avatars) appear incredibly small. I've attached a patch
that modifies the avatar manager to also store the original photo and
modified all the protocols that do use the avatar manager for contact
photos to use the original (no reason to use the resized one).

I realize that the better solution would be to have the avatar manager
never resizing photos and let protocols that have profile picture size
restrictions to resize the photos themselves. However, until that
happens at least this patch (a bit of a hack) will allow reasonable
profile pictures to appear once again :)

--Benson Tsai
diff --git a/kopete/libkopete/kopeteavatarmanager.cpp b/kopete/libkopete/kopeteavatarmanager.cpp
index 4e810b5..e22539b 100644
--- a/kopete/libkopete/kopeteavatarmanager.cpp
+++ b/kopete/libkopete/kopeteavatarmanager.cpp
@@ -25,6 +25,7 @@
 #include <QtCore/QStringList>
 #include <QtCore/QDir>
 #include <QtGui/QPainter>
+#include <QtGui/QImageReader>
 
 // KDE includes
 #include <kdebug.h>
@@ -121,20 +122,46 @@ Kopete::AvatarManager::AvatarEntry AvatarManager::add(Kopete::AvatarManager::Ava
 			break;
 	}
 
+	KUrl dataUrl(avatarUrl);
+
 	kDebug(14010) << "Base directory: " << avatarUrl.path();
 
 	// Second, open the avatar configuration in current directory.
 	KUrl configUrl = avatarUrl;
 	configUrl.addPath( AvatarConfig );
 	
-	QImage avatar;
-	if( !newEntry.path.isEmpty() && newEntry.image.isNull() )
-	{
+	QByteArray data = newEntry.data;
+	QImage avatar = newEntry.image;
+
+	if(!data.isNull()){
+		avatar.loadFromData(data);
+	}
+	else if(!newEntry.dataPath.isEmpty()){
+		QFile f(newEntry.dataPath);
+		f.open(QIODevice::ReadOnly);
+		data = f.readAll();
+		f.close();
+
+		avatar.loadFromData(data);
+	}
+	else if(!avatar.isNull()){
+		QByteArray tempArray;
+		QBuffer tempBuffer(&tempArray);
+		tempBuffer.open( QIODevice::WriteOnly );
+		avatar.save(&tempBuffer, "PNG");
+		
+		data = tempArray;
+	}
+	else if(!newEntry.path.isEmpty()){
 		avatar = QImage(newEntry.path);
+
+		QFile f(newEntry.path);
+		f.open(QIODevice::ReadOnly);
+		data = f.readAll();
+		f.close();
 	}
-	else
-	{
-		avatar = newEntry.image;
+	else{
+		kDebug() << "Warning: No valid image source!";
 	}
 
 	// Scale avatar
@@ -169,21 +196,49 @@ Kopete::AvatarManager::AvatarEntry AvatarManager::add(Kopete::AvatarManager::Ava
 		kDebug(14010) << "Saving of " << avatarUrl.path() << " failed !";
 		return AvatarEntry();
 	}
-	else
-	{
-		// Save metadata of image
-		KConfigGroup avatarConfig(KSharedConfig::openConfig( configUrl.path(), KConfig::SimpleConfig), newEntry.name );
+
+	QString dataFilename;
+
+	// for the contact avatar, save it with the contactId + .png
+	if (newEntry.category == AvatarManager::Contact && newEntry.contact){
+		dataFilename = newEntry.contact->contactId() + QLatin1String("_");
+	}
+
+	dataFilename += KMD5(data).hexDigest();
+
+	QBuffer buffer(&data);
+	buffer.open(QIODevice::ReadOnly);
+	QImageReader ir(&buffer);
+	kDebug() << "Can read image stored in buffer? " << ir.canRead();
+	dataFilename += QLatin1String(".") + QLatin1String(ir.format());
+
+	// Save (original) data on disk
+	dataUrl.addPath(dataFilename);
+	kDebug(14010) << "Saving " << dataUrl.path() << " on disk.";
+	QFile f(dataUrl.path());
+	if(!f.open(QIODevice::WriteOnly)){
+		kDebug(14010) << "Saving of " << dataUrl.path() << " failed !";
+		return AvatarEntry();
+	}
+	int i = f.write(data);
+	kDebug() << "Wrote " << i << " bytes out of " << data.size();
+	f.flush();
+	f.close();
+
+	// Save metadata of image
+	KConfigGroup avatarConfig(KSharedConfig::openConfig( configUrl.path(), KConfig::SimpleConfig), newEntry.name );
 	
-		avatarConfig.writeEntry( "Filename", avatarFilename );
-		avatarConfig.writeEntry( "Category", int(newEntry.category) );
+	avatarConfig.writeEntry( "Filename", avatarFilename );
+	avatarConfig.writeEntry( "DataFilename", dataFilename );
+	avatarConfig.writeEntry( "Category", int(newEntry.category) );
 
-		avatarConfig.sync();
+	avatarConfig.sync();
 	
-		// Add final path to the new entry for avatarAdded signal
-		newEntry.path = avatarUrl.path();
+	// Add final path to the new entry for avatarAdded signal
+	newEntry.path = avatarUrl.path();
+	newEntry.dataPath = dataUrl.path();
 
-		emit avatarAdded(newEntry);
-	}
+	emit avatarAdded(newEntry);
 
 	return newEntry;
 }
@@ -358,6 +413,11 @@ void AvatarQueryJob::Private::listAvatarDirectory(const QString &relativeDirecto
 			avatarPath.addPath( filename );
 			listedEntry.path = avatarPath.path();
 
+			QString dataFilename = cg.readEntry( "DataFilename", QString() );
+			KUrl dataPath(avatarDirectory);
+			dataPath.addPath( dataFilename );
+			listedEntry.dataPath = dataPath.path();
+
 			avatarList << listedEntry;
 		}
                 delete avatarConfig;
diff --git a/kopete/libkopete/kopeteavatarmanager.h b/kopete/libkopete/kopeteavatarmanager.h
index 09b0012..dcff774 100644
--- a/kopete/libkopete/kopeteavatarmanager.h
+++ b/kopete/libkopete/kopeteavatarmanager.h
@@ -129,6 +129,8 @@ public:
 		QString name; ///< name is a friendly name to identity the avatar
 		QString path; ///< path is the full path to the image on disk
 		QImage image; ///< image is used when adding a new avatar, AvatarManager will write the image on disk.
+		QByteArray data; ///< original data used to construct the image
+		QString dataPath; ///< path is the full path to the data on disk
 		Kopete::Contact *contact; ///< contact is used when adding a new contact avatar. AvatarManager use it to create the final url.
 		AvatarManager::AvatarCategory category; ///< category in which the avatar belong
 	} AvatarEntry;
diff --git a/kopete/protocols/jabber/jabberbasecontact.cpp b/kopete/protocols/jabber/jabberbasecontact.cpp
index ebdd7e2..84b9bef 100644
--- a/kopete/protocols/jabber/jabberbasecontact.cpp
+++ b/kopete/protocols/jabber/jabberbasecontact.cpp
@@ -663,10 +663,10 @@ void JabberBaseContact::setPropertiesFromVCard ( const XMPP::VCard &vCard )
 		entry = Kopete::AvatarManager::self()->add(entry);
 
 		// Save the image to the disk, then set the property.
-		if(!entry.path.isNull())
+		if(!entry.dataPath.isNull())
 		{
 			kDebug( JABBER_DEBUG_GLOBAL ) << "Setting photo for contact: " << contactId();
-			setProperty( protocol()->propPhoto, entry.path );
+			setProperty( protocol()->propPhoto, entry.dataPath );
 		}
 	}
 }
diff --git a/kopete/protocols/msn/msncontact.cpp b/kopete/protocols/msn/msncontact.cpp
index 7de545e..6d1e898 100644
--- a/kopete/protocols/msn/msncontact.cpp
+++ b/kopete/protocols/msn/msncontact.cpp
@@ -711,7 +711,7 @@ void MSNContact::setDisplayPicture(KTemporaryFile *f)
 	if (entry.path.isNull())
 		return;
 
-	setProperty( Kopete::Global::Properties::self()->photo() , entry.path );
+	setProperty( Kopete::Global::Properties::self()->photo() , entry.dataPath );
 	emit displayPictureChanged();
 }
 
diff --git a/kopete/protocols/oscar/oscarcontact.cpp b/kopete/protocols/oscar/oscarcontact.cpp
index 17c811b..a029d02 100644
--- a/kopete/protocols/oscar/oscarcontact.cpp
+++ b/kopete/protocols/oscar/oscarcontact.cpp
@@ -452,10 +452,10 @@ void OscarContact::haveIcon( const QString& user, QByteArray icon )
 		entry = Kopete::AvatarManager::self()->add(entry);
 
 		setProperty( static_cast<OscarProtocol*>(protocol())->buddyIconHash, m_details.buddyIconHash() );
-		if (!entry.path.isNull())
+		if (!entry.dataPath.isNull())
 		{
 			removeProperty( Kopete::Global::Properties::self()->photo() );
-			setProperty( Kopete::Global::Properties::self()->photo(), entry.path );
+			setProperty( Kopete::Global::Properties::self()->photo(), entry.dataPath );
 		}
 
 		m_buddyIconDirty = false;
diff --git a/kopete/protocols/telepathy/telepathycontact.cpp b/kopete/protocols/telepathy/telepathycontact.cpp
index 09820a3..d105a8b 100644
--- a/kopete/protocols/telepathy/telepathycontact.cpp
+++ b/kopete/protocols/telepathy/telepathycontact.cpp
@@ -238,12 +238,12 @@ void TelepathyContact::telepathyAvatarReceived(QtTapioca::ContactBase *contactBa
 
 	Kopete::AvatarManager::AvatarEntry result = Kopete::AvatarManager::self()->add( newAvatar );
 	
-	if( !result.path.isEmpty() )
+	if( !result.dataPath.isEmpty() )
 	{
 		kDebug(TELEPATHY_DEBUG_AREA) << "Setting avatar information for " << contactId();
 
 		// Set avatar in Kopete
-		setProperty( Kopete::Global::Properties::self()->photo(), result.path );
+		setProperty( Kopete::Global::Properties::self()->photo(), result.dataPath );
 		setProperty( TelepathyProtocol::protocol()->propAvatarToken, avatar->token() );
 	}
 	else
diff --git a/kopete/protocols/yahoo/yahoocontact.cpp b/kopete/protocols/yahoo/yahoocontact.cpp
index b57a7cb..c76abd7 100644
--- a/kopete/protocols/yahoo/yahoocontact.cpp
+++ b/kopete/protocols/yahoo/yahoocontact.cpp
@@ -585,10 +585,10 @@ void YahooContact::setDisplayPicture(KTemporaryFile *f, int checksum)
 	entry.image = QImage(f->fileName());
 	entry = Kopete::AvatarManager::self()->add(entry);
 
-	if (!entry.path.isNull())
+	if (!entry.dataPath.isNull())
 	{
 		setProperty( Kopete::Global::Properties::self()->photo(), QString() );
-		setProperty( Kopete::Global::Properties::self()->photo() , entry.path );
+		setProperty( Kopete::Global::Properties::self()->photo() , entry.dataPath );
 		emit displayPictureChanged();
 	}
 
_______________________________________________
kopete-devel mailing list
kopete-devel@kde.org
https://mail.kde.org/mailman/listinfo/kopete-devel

Reply via email to