summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2011-03-08 22:00:09 (GMT)
committerRemko Tronçon <git@el-tramo.be>2011-03-08 22:00:09 (GMT)
commit87ff1525f682105fa4e5a9a75dc7d844b19cfdbb (patch)
tree54dabebb45f639fcd597b9a75d6084230fffd82e /Swift/QtUI
parent27d21b371f24272466a2d6a5bf2e2b717ee2d9fc (diff)
downloadswift-87ff1525f682105fa4e5a9a75dc7d844b19cfdbb.zip
swift-87ff1525f682105fa4e5a9a75dc7d844b19cfdbb.tar.bz2
Cache rounded avatars.
Resolves: #770
Diffstat (limited to 'Swift/QtUI')
-rw-r--r--Swift/QtUI/QtChatWindow.cpp6
-rw-r--r--Swift/QtUI/QtRosterHeader.cpp33
-rw-r--r--Swift/QtUI/QtScaledAvatarCache.cpp56
-rw-r--r--Swift/QtUI/QtScaledAvatarCache.h22
-rw-r--r--Swift/QtUI/Roster/RosterDelegate.cpp31
-rw-r--r--Swift/QtUI/Roster/RosterModel.cpp10
-rw-r--r--Swift/QtUI/Roster/RosterModel.h2
-rw-r--r--Swift/QtUI/SConscript1
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",