diff options
| -rw-r--r-- | Swift/QtUI/QtChatWindow.cpp | 6 | ||||
| -rw-r--r-- | Swift/QtUI/QtRosterHeader.cpp | 33 | ||||
| -rw-r--r-- | Swift/QtUI/QtScaledAvatarCache.cpp | 56 | ||||
| -rw-r--r-- | Swift/QtUI/QtScaledAvatarCache.h | 22 | ||||
| -rw-r--r-- | Swift/QtUI/Roster/RosterDelegate.cpp | 31 | ||||
| -rw-r--r-- | Swift/QtUI/Roster/RosterModel.cpp | 10 | ||||
| -rw-r--r-- | Swift/QtUI/Roster/RosterModel.h | 2 | ||||
| -rw-r--r-- | Swift/QtUI/SConscript | 1 | 
8 files changed, 115 insertions, 46 deletions
| diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 998912a..1a909fd 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -13,6 +13,7 @@  #include "MessageSnippet.h"  #include "SystemMessageSnippet.h"  #include "QtTextEdit.h" +#include "QtScaledAvatarCache.h"  #include "SwifTools/TabComplete.h" @@ -20,6 +21,7 @@  #include <QBoxLayout>  #include <QCloseEvent>  #include <QComboBox> +#include <QFileInfo>  #include <QLineEdit>  #include <QSplitter>  #include <QString> @@ -264,6 +266,8 @@ std::string QtChatWindow::addMessage(const std::string &message, const std::stri  		onAllMessagesRead();  	} +	QString scaledAvatarPath = QtScaledAvatarCache(32).getScaledAvatarPath(avatarPath.c_str()); +  	QString htmlString;  	if (label) {  		htmlString = QString("<span style=\"border: thin dashed grey; padding-left: .5em; padding-right: .5em; color: %1; background-color: %2; font-size: 90%; margin-right: .5em; \">").arg(Qt::escape(P2QSTRING(label->getForegroundColor()))).arg(Qt::escape(P2QSTRING(label->getBackgroundColor()))); @@ -277,7 +281,7 @@ std::string QtChatWindow::addMessage(const std::string &message, const std::stri  	htmlString += styleSpanStart + messageHTML + styleSpanEnd;  	bool appendToPrevious = !previousMessageWasSystem_ && !previousMessageWasPresence_ && ((senderIsSelf && previousMessageWasSelf_) || (!senderIsSelf && !previousMessageWasSelf_ && previousSenderName_ == P2QSTRING(senderName))); -	QString qAvatarPath =  avatarPath.empty() ? "qrc:/icons/avatar.png" : QUrl::fromLocalFile(P2QSTRING(avatarPath)).toEncoded(); +	QString qAvatarPath =  scaledAvatarPath.isEmpty() ? "qrc:/icons/avatar.png" : QUrl::fromLocalFile(scaledAvatarPath).toEncoded();  	std::string id = id_.generateID();  	messageLog_->addMessage(boost::shared_ptr<ChatSnippet>(new MessageSnippet(htmlString, Qt::escape(P2QSTRING(senderName)), B2QDATE(time), qAvatarPath, senderIsSelf, appendToPrevious, theme_, P2QSTRING(id)))); diff --git a/Swift/QtUI/QtRosterHeader.cpp b/Swift/QtUI/QtRosterHeader.cpp index 18bb980..5fb4d1a 100644 --- a/Swift/QtUI/QtRosterHeader.cpp +++ b/Swift/QtUI/QtRosterHeader.cpp @@ -8,6 +8,7 @@  #include <QHBoxLayout>  #include <QVBoxLayout> +#include <QFileInfo>  #include <QIcon>  #include <QSizePolicy>  #include <qdebug.h> @@ -19,6 +20,7 @@  #include <Swift/QtUI/QtElidingLabel.h>  #include <Swift/QtUI/QtClickableLabel.h>  #include <Swift/QtUI/QtNameWidget.h> +#include "QtScaledAvatarCache.h"  namespace Swift {  QtRosterHeader::QtRosterHeader(QtSettingsProvider* settings, QWidget* parent) : QWidget(parent) { @@ -71,28 +73,15 @@ void QtRosterHeader::setConnecting() {  }  void QtRosterHeader::setAvatar(const QString& path) { -	QIcon avatar(path); -	if (avatar.isNull()) { -		//qDebug() << "Setting null avatar"; -		avatar = QIcon(":/icons/avatar.png"); -	}  - -	// Apply a rounded rectangle mask -	// FIXME: -	// - We shouldn't go via a 128x128 pixmap -	// - Something tells me we can do this with clever composition mode + -	//   1 drawRectangle on the avatarPixmap, but i haven't figured it out yet. -	QPixmap avatarPixmap = avatar.pixmap(128, 128); -	QPixmap maskedAvatar(avatarPixmap.size()); -	maskedAvatar.fill(QColor(0, 0, 0, 0)); -	QPainter maskPainter(&maskedAvatar); -	maskPainter.setBrush(Qt::black); -	maskPainter.drawRoundedRect(maskedAvatar.rect(), 13, 13); -	maskPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); -	maskPainter.drawPixmap(0, 0, avatarPixmap); -	maskPainter.end(); - -	avatarLabel_->setPixmap(maskedAvatar.scaled(avatarSize_, avatarSize_, Qt::KeepAspectRatio, Qt::SmoothTransformation)); +	QString scaledAvatarPath = QtScaledAvatarCache(avatarSize_).getScaledAvatarPath(path); +	QPixmap avatar; +	if (QFileInfo(scaledAvatarPath).exists()) { +		avatar.load(scaledAvatarPath); +	} +	else { +		avatar = QPixmap(":/icons/avatar.png").scaled(avatarSize_, avatarSize_, Qt::KeepAspectRatio, Qt::SmoothTransformation); +	} +	avatarLabel_->setPixmap(avatar);  }  void QtRosterHeader::setNick(const QString& nick) { diff --git a/Swift/QtUI/QtScaledAvatarCache.cpp b/Swift/QtUI/QtScaledAvatarCache.cpp new file mode 100644 index 0000000..6abff87 --- /dev/null +++ b/Swift/QtUI/QtScaledAvatarCache.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include "QtScaledAvatarCache.h" + +#include <QFileInfo> +#include <QDir> +#include <QPixmap> +#include <QImage> +#include <QImageReader> +#include <QPainter> +#include <QByteArray> + +namespace Swift { + +QtScaledAvatarCache::QtScaledAvatarCache(int size) : size(size) { +} + +QString QtScaledAvatarCache::getScaledAvatarPath(const QString& path) { +	QFileInfo avatarFile(path); +	if (avatarFile.exists()) { +		if (!avatarFile.dir().exists(QString::number(size))) { +			if (!avatarFile.dir().mkdir(QString::number(size))) { +				return path; +			} +		} +		QDir targetDir(avatarFile.dir().absoluteFilePath(QString::number(size))); +		QString targetFile = targetDir.absoluteFilePath(avatarFile.baseName()); +		if (!QFileInfo(targetFile).exists()) { +			QPixmap avatarPixmap; +			avatarPixmap.load(path); +			QPixmap maskedAvatar(avatarPixmap.size()); +			maskedAvatar.fill(QColor(0, 0, 0, 0)); +			QPainter maskPainter(&maskedAvatar); +			maskPainter.setBrush(Qt::black); +			maskPainter.drawRoundedRect(maskedAvatar.rect(), 25.0, 25.0, Qt::RelativeSize); +			maskPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); +			maskPainter.drawPixmap(0, 0, avatarPixmap); +			maskPainter.end(); +			 +			if (!maskedAvatar.scaled(size, size, Qt::KeepAspectRatio, Qt::SmoothTransformation).save(targetFile, "PNG")) { +				return path; +			} +		} +		return targetFile; +	} +	else { +		return path; +	} +} + + +} diff --git a/Swift/QtUI/QtScaledAvatarCache.h b/Swift/QtUI/QtScaledAvatarCache.h new file mode 100644 index 0000000..cc3ac07 --- /dev/null +++ b/Swift/QtUI/QtScaledAvatarCache.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include <string> +#include <QString> + +namespace Swift { +	class QtScaledAvatarCache { +		public: +			QtScaledAvatarCache(int size); + +			QString getScaledAvatarPath(const QString& path); + +		private: +			int size; +	}; +} diff --git a/Swift/QtUI/Roster/RosterDelegate.cpp b/Swift/QtUI/Roster/RosterDelegate.cpp index 47ae948..aaa6236 100644 --- a/Swift/QtUI/Roster/RosterDelegate.cpp +++ b/Swift/QtUI/Roster/RosterDelegate.cpp @@ -12,6 +12,7 @@  #include <QBrush>  #include <QFontMetrics>  #include <QPainterPath> +#include <QFileInfo>  #include <QPolygon>  #include <qdebug.h>  #include <QBitmap> @@ -21,6 +22,7 @@  #include "QtTreeWidget.h"  #include "RosterModel.h" +#include "QtScaledAvatarCache.h"  namespace Swift { @@ -86,23 +88,18 @@ void RosterDelegate::paintContact(QPainter* painter, const QStyleOptionViewItem&  	int calculatedAvatarSize = presenceIconRegion.height();  	//This overlaps the presenceIcon, so must be painted first  	QRect avatarRegion(QPoint(presenceIconRegion.right() - presenceIconWidth_ / 2, presenceIconRegion.top()), QSize(calculatedAvatarSize, calculatedAvatarSize)); -	QIcon avatar = index.data(AvatarRole).isValid() && !index.data(AvatarRole).value<QIcon>().isNull() -		? index.data(AvatarRole).value<QIcon>() -		: QIcon(":/icons/avatar.png"); - -	// Apply a rounded rectangle mask -	// FIXME: We shouldn't go via a 128x128 pixmap -	QPixmap avatarPixmap = avatar.pixmap(128, 128); -	QPixmap maskedAvatar(avatarPixmap.size()); -	maskedAvatar.fill(QColor(0, 0, 0, 0)); -	QPainter maskPainter(&maskedAvatar); -	maskPainter.setBrush(Qt::black); -	maskPainter.drawRoundedRect(maskedAvatar.rect(), 13, 13); -	maskPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); -	maskPainter.drawPixmap(0, 0, avatarPixmap); -	maskPainter.end(); - -	avatarPixmap = maskedAvatar.scaled(avatarRegion.height(), avatarRegion.width(), Qt::KeepAspectRatio, Qt::SmoothTransformation); + +	QPixmap avatarPixmap; +	if (index.data(AvatarRole).isValid() && !index.data(AvatarRole).value<QString>().isNull()) { +		QString avatarPath = index.data(AvatarRole).value<QString>(); +		QString scaledAvatarPath = QtScaledAvatarCache(avatarRegion.height()).getScaledAvatarPath(avatarPath); +		if (QFileInfo(scaledAvatarPath).exists()) { +			avatarPixmap.load(scaledAvatarPath); +		} +	} +	if (avatarPixmap.isNull()) { +		avatarPixmap = QPixmap(":/icons/avatar.png").scaled(avatarRegion.height(), avatarRegion.width(), Qt::KeepAspectRatio, Qt::SmoothTransformation); +	}  	painter->drawPixmap(avatarRegion.topLeft() + QPoint(((avatarRegion.width() - avatarPixmap.width()) / 2), (avatarRegion.height() - avatarPixmap.height()) / 2), avatarPixmap); diff --git a/Swift/QtUI/Roster/RosterModel.cpp b/Swift/QtUI/Roster/RosterModel.cpp index 2399a21..1fc20dd 100644 --- a/Swift/QtUI/Roster/RosterModel.cpp +++ b/Swift/QtUI/Roster/RosterModel.cpp @@ -135,12 +135,12 @@ QString RosterModel::getToolTip(RosterItem* item) const {  	return tip;  } -QIcon RosterModel::getAvatar(RosterItem* item) const { +QString RosterModel::getAvatar(RosterItem* item) const {  	ContactRosterItem* contact = dynamic_cast<ContactRosterItem*>(item); -	if (!contact) return QIcon(); -	std::string path = contact->getAvatarPath(); -	 -	return path.empty() ? QIcon() : QIcon(P2QSTRING(path)); +	if (!contact) { +		return ""; +	} +	return QString(contact->getAvatarPath().c_str());  }  QString RosterModel::getStatusText(RosterItem* item) const { diff --git a/Swift/QtUI/Roster/RosterModel.h b/Swift/QtUI/Roster/RosterModel.h index 964f680..bd34e9c 100644 --- a/Swift/QtUI/Roster/RosterModel.h +++ b/Swift/QtUI/Roster/RosterModel.h @@ -44,7 +44,7 @@ namespace Swift {  			QColor getTextColor(RosterItem* item) const;  			QColor getBackgroundColor(RosterItem* item) const;  			QString getToolTip(RosterItem* item) const; -			QIcon getAvatar(RosterItem* item) const; +			QString getAvatar(RosterItem* item) const;  			QString getStatusText(RosterItem* item) const;  			QIcon getPresenceIcon(RosterItem* item) const;  			int getChildCount(RosterItem* item) const; diff --git a/Swift/QtUI/SConscript b/Swift/QtUI/SConscript index b8c3ebe..a924960 100644 --- a/Swift/QtUI/SConscript +++ b/Swift/QtUI/SConscript @@ -75,6 +75,7 @@ sources = [      "QtNameWidget.cpp",      "QtSettingsProvider.cpp",      "QtStatusWidget.cpp", +		"QtScaledAvatarCache.cpp",      "QtSwift.cpp",      "QtChatView.cpp",      "QtChatTheme.cpp", | 
 Swift
 Swift