Merge pull request #1576 from csoler/v0.6-ImprovedGUI

attempt to use a cache for user-defined avatars. Should reduce memory…
This commit is contained in:
csoler 2019-06-18 09:17:03 +02:00 committed by GitHub
commit 2f81b11dee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 254 additions and 209 deletions

View File

@ -322,8 +322,8 @@ void ChatLobbyWidget::lobbyTreeWidgetCustomPopupMenu(QPoint)
QPixmap pixmap ; QPixmap pixmap ;
if(idd.mAvatar.mSize == 0 || !pixmap.loadFromData(idd.mAvatar.mData, idd.mAvatar.mSize, "PNG")) if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap, GxsIdDetails::SMALL))
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(*it)) ; pixmap = GxsIdDetails::makeDefaultIcon(*it,GxsIdDetails::SMALL) ;
QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(subscribeChatLobbyAs())); QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(subscribeChatLobbyAs()));
action->setData(QString::fromStdString((*it).toStdString())) ; action->setData(QString::fromStdString((*it).toStdString())) ;

View File

@ -270,8 +270,8 @@ void CreateCircleDialog::addMember(const RsGxsIdGroup &idGroup)
QPixmap pixmap ; QPixmap pixmap ;
if(idGroup.mImage.mSize == 0 || !pixmap.loadFromData(idGroup.mImage.mData, idGroup.mImage.mSize, "PNG")) if(idGroup.mImage.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idGroup.mImage.mData, idGroup.mImage.mSize, pixmap, GxsIdDetails::SMALL))
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(RsGxsId(idGroup.mMeta.mGroupId))); pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(idGroup.mMeta.mGroupId),GxsIdDetails::SMALL);
if (idGroup.mPgpKnown){ if (idGroup.mPgpKnown){
RsPeerDetails details; RsPeerDetails details;
@ -331,8 +331,8 @@ void CreateCircleDialog::addCircle(const RsGxsCircleDetails &cirDetails)
QPixmap pixmap ; QPixmap pixmap ;
if(gxs_details.mAvatar.mSize == 0 || !pixmap.loadFromData(gxs_details.mAvatar.mData, gxs_details.mAvatar.mSize, "PNG")) if(gxs_details.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(gxs_details.mAvatar.mData, gxs_details.mAvatar.mSize, pixmap, GxsIdDetails::SMALL))
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(gxs_details.mId)); pixmap = GxsIdDetails::makeDefaultIcon(gxs_details.mId,GxsIdDetails::SMALL);
addMember(keyId, idtype, nickname, QIcon(pixmap)); addMember(keyId, idtype, nickname, QIcon(pixmap));
@ -814,8 +814,8 @@ void CreateCircleDialog::loadIdentities(uint32_t token)
QPixmap pixmap ; QPixmap pixmap ;
if(idGroup.mImage.mSize == 0 || !pixmap.loadFromData(idGroup.mImage.mData, idGroup.mImage.mSize, "PNG")) if(idGroup.mImage.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idGroup.mImage.mData, idGroup.mImage.mSize, pixmap, GxsIdDetails::SMALL))
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(RsGxsId(idGroup.mMeta.mGroupId))) ; pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(idGroup.mMeta.mGroupId),GxsIdDetails::SMALL) ;
if (idGroup.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility) if (idGroup.mMeta.mGroupFlags & RSGXSID_GROUPFLAG_REALID_kept_for_compatibility)
{ {

View File

@ -183,11 +183,11 @@ void IdDetailsDialog::insertIdDetails(uint32_t token)
QPixmap pixmap; QPixmap pixmap;
if(data.mImage.mSize > 0 && pixmap.loadFromData(data.mImage.mData, data.mImage.mSize, "PNG")) if(data.mImage.mSize > 0 && GxsIdDetails::loadPixmapFromData(data.mImage.mData, data.mImage.mSize, pixmap, GxsIdDetails::LARGE))
ui->avatarLabel->setPixmap(pixmap) ; ui->avatarLabel->setPixmap(pixmap);
else else
{ {
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId)) ) ; pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId),GxsIdDetails::LARGE) ;
ui->avatarLabel->setPixmap(pixmap) ; // we need to use the default pixmap here, generated from the ID ui->avatarLabel->setPixmap(pixmap) ; // we need to use the default pixmap here, generated from the ID
} }

View File

@ -752,8 +752,8 @@ void IdDialog::loadCircleGroupMeta(const uint32_t &token)
QPixmap pixmap ; QPixmap pixmap ;
if(idd.mAvatar.mSize == 0 || !pixmap.loadFromData(idd.mAvatar.mData, idd.mAvatar.mSize, "PNG")) if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap,GxsIdDetails::SMALL))
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(it->first)) ; pixmap = GxsIdDetails::makeDefaultIcon(it->first,GxsIdDetails::SMALL) ;
if(has_id) if(has_id)
subitem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromUtf8(idd.mNickname.c_str())) ; subitem->setText(CIRCLEGROUP_CIRCLE_COL_GROUPNAME, QString::fromUtf8(idd.mNickname.c_str())) ;
@ -1551,8 +1551,8 @@ bool IdDialog::fillIdListItem(const RsGxsIdGroup& data, QTreeWidgetItem *&item,
QPixmap pixmap ; QPixmap pixmap ;
if(data.mImage.mSize == 0 || !pixmap.loadFromData(data.mImage.mData, data.mImage.mSize, "PNG")) if(data.mImage.mSize == 0 || !GxsIdDetails::loadPixmapFromData(data.mImage.mData, data.mImage.mSize, pixmap,GxsIdDetails::SMALL))
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId))) ; pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId),GxsIdDetails::SMALL) ;
item->setIcon(RSID_COL_NICKNAME, QIcon(pixmap)); item->setIcon(RSID_COL_NICKNAME, QIcon(pixmap));
@ -1797,8 +1797,8 @@ void IdDialog::insertIdDetails(uint32_t token)
QPixmap pixmap ; QPixmap pixmap ;
if(data.mImage.mSize == 0 || !pixmap.loadFromData(data.mImage.mData, data.mImage.mSize, "PNG")) if(data.mImage.mSize == 0 || !GxsIdDetails::loadPixmapFromData(data.mImage.mData, data.mImage.mSize, pixmap,GxsIdDetails::LARGE))
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId))) ; pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId),GxsIdDetails::LARGE) ;
#ifdef ID_DEBUG #ifdef ID_DEBUG
std::cerr << "Setting header frame image : " << pixmap.width() << " x " << pixmap.height() << std::endl; std::cerr << "Setting header frame image : " << pixmap.width() << " x " << pixmap.height() << std::endl;
@ -2470,8 +2470,8 @@ void IdDialog::IdListCustomPopupMenu( QPoint )
QPixmap pixmap ; QPixmap pixmap ;
if(idd.mAvatar.mSize == 0 || !pixmap.loadFromData(idd.mAvatar.mData, idd.mAvatar.mSize, "PNG")) if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap,GxsIdDetails::SMALL))
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(*it)) ; pixmap = GxsIdDetails::makeDefaultIcon(*it,GxsIdDetails::SMALL) ;
QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(chatIdentity())); QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(chatIdentity()));
action->setData(QString::fromStdString((*it).toStdString())) ; action->setData(QString::fromStdString((*it).toStdString())) ;

View File

@ -195,7 +195,7 @@ void IdEditDialog::setAvatar(const QPixmap &avatar)
ui->avatarLabel->setPixmap(mAvatar); ui->avatarLabel->setPixmap(mAvatar);
} else { } else {
// we need to use the default pixmap here, generated from the ID // we need to use the default pixmap here, generated from the ID
ui->avatarLabel->setPixmap(QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(RsGxsId(mEditGroup.mMeta.mGroupId)))); ui->avatarLabel->setPixmap(GxsIdDetails::makeDefaultIcon(RsGxsId(mEditGroup.mMeta.mGroupId)));
} }
} }
@ -257,9 +257,8 @@ void IdEditDialog::loadExistingId(uint32_t token)
mGroupId = mEditGroup.mMeta.mGroupId; mGroupId = mEditGroup.mMeta.mGroupId;
QPixmap avatar; QPixmap avatar;
if (mEditGroup.mImage.mSize > 0) { if (mEditGroup.mImage.mSize > 0)
avatar.loadFromData(mEditGroup.mImage.mData, mEditGroup.mImage.mSize, "PNG"); GxsIdDetails::loadPixmapFromData(mEditGroup.mImage.mData, mEditGroup.mImage.mSize, avatar,GxsIdDetails::LARGE);
}
setAvatar(avatar); setAvatar(avatar);

View File

@ -100,7 +100,8 @@ void IdentityWidget::updateData(const RsGxsIdGroup &gxs_group_info)
ui->labelPositive->setText(QString::number(info.mFriendsPositiveVotes)); ui->labelPositive->setText(QString::number(info.mFriendsPositiveVotes));
ui->labelNegative->setText(QString::number(info.mFriendsNegativeVotes)); ui->labelNegative->setText(QString::number(info.mFriendsNegativeVotes));
if (!_havePGPDetail) { if (!_havePGPDetail)
{
QFont font = ui->labelName->font(); QFont font = ui->labelName->font();
font.setItalic(false); font.setItalic(false);
ui->labelName->setFont(font); ui->labelName->setFont(font);
@ -111,20 +112,16 @@ void IdentityWidget::updateData(const RsGxsIdGroup &gxs_group_info)
ui->labelKeyId->setVisible(false); ui->labelKeyId->setVisible(false);
/// (TODO) Get real ident icon /// (TODO) Get real ident icon
QImage image; QPixmap pixmap;
if(!( (_group_info.mImage.mSize > 0) && image.loadFromData(_group_info.mImage.mData, _group_info.mImage.mSize, "PNG") )) if(!( (_group_info.mImage.mSize > 0) && GxsIdDetails::loadPixmapFromData(_group_info.mImage.mData, _group_info.mImage.mSize, pixmap) ))
image = GxsIdDetails::makeDefaultIcon(RsGxsId(_group_info.mMeta.mGroupId)); pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(_group_info.mMeta.mGroupId));
if (_avatar != image) {
_avatar = image;
_scene->clear();
_scene->addPixmap(QPixmap::fromImage(image.scaled(ui->graphicsView->width(),ui->graphicsView->height())));
emit imageUpdated();
}//if (_avatar != image)
}//if (!_havePGPDetail)
//}//if (_group_info != gxs_group_info) _avatar = pixmap.toImage();
_scene->clear();
_scene->addPixmap(pixmap.scaled(ui->graphicsView->width(),ui->graphicsView->height()));
emit imageUpdated();
}
} }
void IdentityWidget::updateData(const RsPeerDetails &pgp_details) void IdentityWidget::updateData(const RsPeerDetails &pgp_details)
@ -136,12 +133,10 @@ void IdentityWidget::updateData(const RsPeerDetails &pgp_details)
_nickname = QString::fromUtf8(_details.name.c_str()); _nickname = QString::fromUtf8(_details.name.c_str());
if (!_haveGXSId) m_myName = _nickname; if (!_haveGXSId) m_myName = _nickname;
ui->labelName->setText(m_myName); ui->labelName->setText(m_myName);
if (_haveGXSId) { if (_haveGXSId)
ui->labelName->setToolTip(tr("GXS name:") + (" "+m_myName) + ("\n") ui->labelName->setToolTip(tr("GXS name:") + (" "+m_myName) + ("\n") +(tr("PGP name:")+(" "+_nickname)));
+(tr("PGP name:")+(" "+_nickname))); else
} else {//if (m_myName != _nickname)
ui->labelName->setToolTip(tr("PGP name:")+(" "+_nickname)); ui->labelName->setToolTip(tr("PGP name:")+(" "+_nickname));
}//else (m_myName != _nickname)
QFont font = ui->labelName->font(); QFont font = ui->labelName->font();
font.setItalic(true); font.setItalic(true);
@ -210,11 +205,6 @@ void IdentityWidget::setIsSelected(bool value)
font.setBold(value); font.setBold(value);
ui->labelName->setFont(font); ui->labelName->setFont(font);
} }
/*
bool IdentityWidget::isSelected()
{
return m_isSelected;
}*/
void IdentityWidget::setIsCurrent(bool value) void IdentityWidget::setIsCurrent(bool value)
{ {
@ -227,11 +217,6 @@ void IdentityWidget::setIsCurrent(bool value)
ui->label_NegIcon_2->setVisible(value); ui->label_NegIcon_2->setVisible(value);
ui->pbAdd->setVisible(value); ui->pbAdd->setVisible(value);
} }
/*
bool IdentityWidget::isCurrent()
{
return m_isCurrent;
}*/
void IdentityWidget::pbAdd_clicked() void IdentityWidget::pbAdd_clicked()
{ {

View File

@ -426,15 +426,15 @@ void PeopleDialog::iw_AddButtonClickedExt()
{ {
IdentityWidget *dest= IdentityWidget *dest=
qobject_cast<IdentityWidget *>(QObject::sender()); qobject_cast<IdentityWidget *>(QObject::sender());
if (dest) { if (dest)
{
QMenu contextMnu( this ); QMenu contextMnu( this );
QMenu *mnu = contextMnu.addMenu(QIcon(":/icons/png/circles.png"),tr("Invite to Circle")) ; QMenu *mnu = contextMnu.addMenu(QIcon(":/icons/png/circles.png"),tr("Invite to Circle")) ;
std::map<RsGxsGroupId, CircleWidget*>::iterator itCurs; std::map<RsGxsGroupId, CircleWidget*>::iterator itCurs;
for( itCurs =_ext_circles_widgets.begin(); for( itCurs =_ext_circles_widgets.begin(); itCurs != _ext_circles_widgets.end(); ++itCurs)
itCurs != _ext_circles_widgets.end(); {
++itCurs) {
CircleWidget *curs = itCurs->second; CircleWidget *curs = itCurs->second;
QIcon icon = QIcon(curs->getImage()); QIcon icon = QIcon(curs->getImage());
QString name = curs->getName(); QString name = curs->getName();
@ -442,7 +442,7 @@ void PeopleDialog::iw_AddButtonClickedExt()
QAction *action = mnu->addAction(icon, name, this, SLOT(addToCircleExt())); QAction *action = mnu->addAction(icon, name, this, SLOT(addToCircleExt()));
action->setData(QString::fromStdString(curs->groupInfo().mGroupId.toStdString()) action->setData(QString::fromStdString(curs->groupInfo().mGroupId.toStdString())
+ ";" + QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString())); + ";" + QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString()));
}//for( itCurs =_ext_circles_widgets.begin(); }
std::list<RsGxsId> own_identities ; std::list<RsGxsId> own_identities ;
rsIdentity->getOwnIds(own_identities) ; rsIdentity->getOwnIds(own_identities) ;
@ -467,8 +467,8 @@ void PeopleDialog::iw_AddButtonClickedExt()
QPixmap pixmap ; QPixmap pixmap ;
if(idd.mAvatar.mSize == 0 || !pixmap.loadFromData(idd.mAvatar.mData, idd.mAvatar.mSize, "PNG")) if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap,GxsIdDetails::SMALL))
pixmap = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(*it)) ; pixmap = GxsIdDetails::makeDefaultIcon(*it,GxsIdDetails::SMALL) ;
QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(chatIdentity())); QAction *action = mnu->addAction(QIcon(pixmap), QString("%1 (%2)").arg(QString::fromUtf8(idd.mNickname.c_str()), QString::fromStdString((*it).toStdString())), this, SLOT(chatIdentity()));
action->setData(QString::fromStdString((*it).toStdString()) + ";" + QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString())) ; action->setData(QString::fromStdString((*it).toStdString()) + ";" + QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString())) ;
@ -492,7 +492,7 @@ void PeopleDialog::iw_AddButtonClickedExt()
actionDetails->setData( QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString())); actionDetails->setData( QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString()));
contextMnu.exec(QCursor::pos()); contextMnu.exec(QCursor::pos());
}//if (dest) }
} }
void PeopleDialog::iw_AddButtonClickedInt() void PeopleDialog::iw_AddButtonClickedInt()
@ -513,10 +513,10 @@ void PeopleDialog::iw_AddButtonClickedInt()
QAction *action = contextMnu.addAction(icon, name, this, SLOT(addToCircleInt())); QAction *action = contextMnu.addAction(icon, name, this, SLOT(addToCircleInt()));
action->setData(QString::fromStdString(curs->groupInfo().mGroupId.toStdString()) action->setData(QString::fromStdString(curs->groupInfo().mGroupId.toStdString())
+ ";" + QString::fromStdString(dest->details().gpg_id.toStdString())); + ";" + QString::fromStdString(dest->details().gpg_id.toStdString()));
}//for( itCurs =_int_circles_widgets.begin(); }
contextMnu.exec(QCursor::pos()); contextMnu.exec(QCursor::pos());
}//if (dest) }
} }
void PeopleDialog::addToCircleExt() void PeopleDialog::addToCircleExt()

View File

@ -21,6 +21,7 @@
#include <QPixmap> #include <QPixmap>
#include "AlbumDialog.h" #include "AlbumDialog.h"
#include "gui/gxs/GxsIdDetails.h"
#include "ui_AlbumDialog.h" #include "ui_AlbumDialog.h"
#include "retroshare/rsgxsflags.h" #include "retroshare/rsgxsflags.h"
@ -60,7 +61,7 @@ void AlbumDialog::setUp()
QPixmap qtn; QPixmap qtn;
qtn.loadFromData(mAlbum.mThumbnail.data, mAlbum.mThumbnail.size, mAlbum.mThumbnail.type.c_str()); GxsIdDetails::loadPixmapFromData(mAlbum.mThumbnail.data, mAlbum.mThumbnail.size, mAlbum.mThumbnail.type.c_str(),qtn);
if(mAlbum.mThumbnail.size != 0) if(mAlbum.mThumbnail.size != 0)
{ {

View File

@ -165,7 +165,7 @@ void PostedDialog::loadGroupSummaryToken(const uint32_t &token, std::list<RsGrou
if (group.mGroupImage.mData != NULL) { if (group.mGroupImage.mData != NULL) {
QPixmap image; QPixmap image;
image.loadFromData(group.mGroupImage.mData, group.mGroupImage.mSize, "PNG"); GxsIdDetails::loadPixmapFromData(group.mGroupImage.mData, group.mGroupImage.mSize, image,GxsIdDetails::ORIGINAL);
postedData->mIcon[group.mMeta.mGroupId] = image; postedData->mIcon[group.mMeta.mGroupId] = image;
} }

View File

@ -20,6 +20,7 @@
#include <QBuffer> #include <QBuffer>
#include "PostedGroupDialog.h" #include "PostedGroupDialog.h"
#include "gui/gxs/GxsIdDetails.h"
#include <retroshare/rswiki.h> #include <retroshare/rswiki.h>
#include <iostream> #include <iostream>
@ -163,9 +164,9 @@ bool PostedGroupDialog::service_loadGroup(uint32_t token, Mode /*mode*/, RsGroup
if (group.mGroupImage.mData) { if (group.mGroupImage.mData) {
QPixmap pixmap; QPixmap pixmap;
if (pixmap.loadFromData(group.mGroupImage.mData, group.mGroupImage.mSize, "PNG")) { if (GxsIdDetails::loadPixmapFromData(group.mGroupImage.mData, group.mGroupImage.mSize, pixmap,GxsIdDetails::ORIGINAL))
setLogo(pixmap); setLogo(pixmap);
}
} else { } else {
setLogo(QPixmap(":/icons/png/posted.png")); setLogo(QPixmap(":/icons/png/posted.png"));
} }

View File

@ -25,6 +25,7 @@
#include "rshare.h" #include "rshare.h"
#include "PostedItem.h" #include "PostedItem.h"
#include "gui/feeds/FeedHolder.h" #include "gui/feeds/FeedHolder.h"
#include "gui/gxs/GxsIdDetails.h"
#include "util/misc.h" #include "util/misc.h"
#include "ui_PostedItem.h" #include "ui_PostedItem.h"
@ -255,7 +256,7 @@ void PostedItem::fill()
if(mPost.mImage.mData != NULL) if(mPost.mImage.mData != NULL)
{ {
QPixmap pixmap; QPixmap pixmap;
pixmap.loadFromData(mPost.mImage.mData, mPost.mImage.mSize, "PNG"); GxsIdDetails::loadPixmapFromData(mPost.mImage.mData, mPost.mImage.mSize, pixmap,GxsIdDetails::ORIGINAL);
// Wiping data - as its been passed to thumbnail. // Wiping data - as its been passed to thumbnail.
QPixmap sqpixmap = pixmap.scaled(desired_width,desired_height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); QPixmap sqpixmap = pixmap.scaled(desired_width,desired_height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);

View File

@ -41,7 +41,7 @@ void AvatarDefs::getOwnAvatar(QPixmap &avatar, const QString& defaultImage)
} }
/* load image */ /* load image */
avatar.loadFromData(data, size, "PNG") ; GxsIdDetails::loadPixmapFromData(data, size, avatar,GxsIdDetails::ORIGINAL) ;
free(data); free(data);
} }
@ -58,7 +58,7 @@ void AvatarDefs::getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, cons
} }
/* load image */ /* load image */
avatar.loadFromData(data, size, "PNG") ; GxsIdDetails::loadPixmapFromData(data, size, avatar, GxsIdDetails::LARGE) ;
free(data); free(data);
} }
@ -77,8 +77,8 @@ void AvatarDefs::getAvatarFromGxsId(const RsGxsId& gxsId, QPixmap &avatar, const
/* load image */ /* load image */
if(details.mAvatar.mSize == 0 || !avatar.loadFromData(details.mAvatar.mData, details.mAvatar.mSize, "PNG")) if(details.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(details.mAvatar.mData, details.mAvatar.mSize, avatar,GxsIdDetails::LARGE))
avatar = QPixmap::fromImage(GxsIdDetails::makeDefaultIcon(gxsId)); avatar = GxsIdDetails::makeDefaultIcon(gxsId,GxsIdDetails::LARGE);
} }
void AvatarDefs::getAvatarFromGpgId(const RsPgpId& gpgId, QPixmap &avatar, const QString& defaultImage) void AvatarDefs::getAvatarFromGpgId(const RsPgpId& gpgId, QPixmap &avatar, const QString& defaultImage)
@ -109,7 +109,7 @@ void AvatarDefs::getAvatarFromGpgId(const RsPgpId& gpgId, QPixmap &avatar, const
} }
/* load image */ /* load image */
avatar.loadFromData(data, size, "PNG") ; GxsIdDetails::loadPixmapFromData(data, size, avatar);
free(data); free(data);
} }

View File

@ -45,6 +45,9 @@ AvatarDialog::AvatarDialog(QWidget *parent) :
updateInterface(); updateInterface();
} }
const int AvatarDialog::RS_AVATAR_DEFAULT_IMAGE_W = 64;
const int AvatarDialog::RS_AVATAR_DEFAULT_IMAGE_H = 64;
AvatarDialog::~AvatarDialog() AvatarDialog::~AvatarDialog()
{ {
delete(ui); delete(ui);
@ -52,7 +55,7 @@ AvatarDialog::~AvatarDialog()
void AvatarDialog::changeAvatar() void AvatarDialog::changeAvatar()
{ {
QPixmap img = misc::getOpenThumbnailedPicture(this, tr("Load Avatar"), 128, 128); QPixmap img = misc::getOpenThumbnailedPicture(this, tr("Load Avatar"), RS_AVATAR_DEFAULT_IMAGE_W,RS_AVATAR_DEFAULT_IMAGE_H);
if (img.isNull()) if (img.isNull())
return; return;

View File

@ -35,6 +35,9 @@ class AvatarDialog : public QDialog
Q_OBJECT Q_OBJECT
public: public:
static const int RS_AVATAR_DEFAULT_IMAGE_W ;
static const int RS_AVATAR_DEFAULT_IMAGE_H ;
AvatarDialog(QWidget *parent = 0); AvatarDialog(QWidget *parent = 0);
~AvatarDialog(); ~AvatarDialog();

View File

@ -18,6 +18,7 @@
* * * *
*******************************************************************************/ *******************************************************************************/
#include "gui/gxs/GxsIdDetails.h"
#include "GxsChannelGroupItem.h" #include "GxsChannelGroupItem.h"
#include "ui_GxsChannelGroupItem.h" #include "ui_GxsChannelGroupItem.h"
@ -134,7 +135,7 @@ void GxsChannelGroupItem::fill()
if (mGroup.mImage.mData != NULL) { if (mGroup.mImage.mData != NULL) {
QPixmap chanImage; QPixmap chanImage;
chanImage.loadFromData(mGroup.mImage.mData, mGroup.mImage.mSize, "PNG"); GxsIdDetails::loadPixmapFromData(mGroup.mImage.mData, mGroup.mImage.mSize, chanImage,GxsIdDetails::ORIGINAL);
ui->logoLabel->setPixmap(QPixmap(chanImage)); ui->logoLabel->setPixmap(QPixmap(chanImage));
} }

View File

@ -22,6 +22,7 @@
#include <QFileInfo> #include <QFileInfo>
#include <QStyle> #include <QStyle>
#include "gui/gxs/GxsIdDetails.h"
#include "rshare.h" #include "rshare.h"
#include "GxsChannelPostItem.h" #include "GxsChannelPostItem.h"
#include "ui_GxsChannelPostItem.h" #include "ui_GxsChannelPostItem.h"
@ -392,7 +393,7 @@ void GxsChannelPostItem::fill()
if(mPost.mThumbnail.mData != NULL) if(mPost.mThumbnail.mData != NULL)
{ {
QPixmap thumbnail; QPixmap thumbnail;
thumbnail.loadFromData(mPost.mThumbnail.mData, mPost.mThumbnail.mSize, "PNG"); GxsIdDetails::loadPixmapFromData(mPost.mThumbnail.mData, mPost.mThumbnail.mSize, thumbnail,GxsIdDetails::ORIGINAL);
// Wiping data - as its been passed to thumbnail. // Wiping data - as its been passed to thumbnail.
ui->logoLabel->setPixmap(thumbnail); ui->logoLabel->setPixmap(thumbnail);
} }

View File

@ -23,6 +23,7 @@
#include "FeedHolder.h" #include "FeedHolder.h"
#include "gui/RetroShareLink.h" #include "gui/RetroShareLink.h"
#include "gui/gxs/GxsIdDetails.h"
/**** /****
* #define DEBUG_ITEM 1 * #define DEBUG_ITEM 1
@ -137,7 +138,7 @@ void PostedGroupItem::fill()
if (mGroup.mGroupImage.mData != NULL) { if (mGroup.mGroupImage.mData != NULL) {
QPixmap postedImage; QPixmap postedImage;
postedImage.loadFromData(mGroup.mGroupImage.mData, mGroup.mGroupImage.mSize, "PNG"); GxsIdDetails::loadPixmapFromData(mGroup.mGroupImage.mData, mGroup.mGroupImage.mSize, postedImage,GxsIdDetails::ORIGINAL);
ui->logoLabel->setPixmap(QPixmap(postedImage)); ui->logoLabel->setPixmap(QPixmap(postedImage));
} else { } else {
ui->logoLabel->setPixmap(QPixmap(":/images/posted_64.png")); ui->logoLabel->setPixmap(QPixmap(":/images/posted_64.png"));

View File

@ -24,6 +24,8 @@
#include <QMutexLocker> #include <QMutexLocker>
#include <math.h> #include <math.h>
#include <util/rsdir.h>
#include "gui/common/AvatarDialog.h"
#include "GxsIdDetails.h" #include "GxsIdDetails.h"
#include "retroshare-gui/RsAutoUpdatePage.h" #include "retroshare-gui/RsAutoUpdatePage.h"
@ -66,10 +68,13 @@
uint32_t GxsIdDetails::mImagesAllocated = 0; uint32_t GxsIdDetails::mImagesAllocated = 0;
time_t GxsIdDetails::mLastIconCacheCleaning = time(NULL); time_t GxsIdDetails::mLastIconCacheCleaning = time(NULL);
std::map<RsGxsId,std::pair<time_t,QImage> > GxsIdDetails::mDefaultIconCache ; std::map<RsGxsId,std::pair<time_t,QPixmap>[4] > GxsIdDetails::mDefaultIconCache ;
#define ICON_CACHE_STORAGE_TIME 600 QMutex GxsIdDetails::mMutex;
#define DELAY_BETWEEN_ICON_CACHE_CLEANING 300 QMutex GxsIdDetails::mIconCacheMutex;
#define ICON_CACHE_STORAGE_TIME 240
#define DELAY_BETWEEN_ICON_CACHE_CLEANING 120
void ReputationItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const void ReputationItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{ {
@ -184,7 +189,8 @@ void GxsIdDetails::timerEvent(QTimerEvent *event)
killTimer(mCheckTimerId); killTimer(mCheckTimerId);
mCheckTimerId = 0; mCheckTimerId = 0;
if (rsIdentity) { if (rsIdentity)
{
QMutexLocker lock(&mMutex); QMutexLocker lock(&mMutex);
if (mProcessDisableCount == 0) { if (mProcessDisableCount == 0) {
@ -236,14 +242,14 @@ void GxsIdDetails::timerEvent(QTimerEvent *event)
} }
} }
QMutexLocker lock(&mMutex); bool empty = false ;
{
QMutexLocker lock(&mMutex);
empty = mPendingData.empty();
}
if (mPendingData.empty()) { if (!empty) /* Start timer */
/* All done */
} else {
/* Start timer */
doStartTimer(); doStartTimer();
}
} }
} }
@ -266,7 +272,7 @@ void GxsIdDetails::enableProcess(bool enable)
return; return;
} }
QMutexLocker lock(&mInstance->mMutex); QMutexLocker lock(&mMutex);
if (enable) { if (enable) {
--mInstance->mProcessDisableCount; --mInstance->mProcessDisableCount;
@ -292,7 +298,7 @@ bool GxsIdDetails::process(const RsGxsId &id, GxsIdDetailsCallbackFunction callb
// remove any existing call for this object. This is needed for when the same widget is used to display IDs that vary in time. // remove any existing call for this object. This is needed for when the same widget is used to display IDs that vary in time.
{ {
QMutexLocker lock(&mInstance->mMutex); QMutexLocker lock(&mMutex);
// check if a pending request is not already on its way. If so, replace it. // check if a pending request is not already on its way. If so, replace it.
@ -339,7 +345,7 @@ bool GxsIdDetails::process(const RsGxsId &id, GxsIdDetailsCallbackFunction callb
pendingData.mData = data; pendingData.mData = data;
{ {
QMutexLocker lock(&mInstance->mMutex); QMutexLocker lock(&mMutex);
// check if a pending request is not already on its way. If so, replace it. // check if a pending request is not already on its way. If so, replace it.
@ -376,79 +382,6 @@ static bool findTagIcon(int tag_class, int /*tag_type*/, QIcon &icon)
return true; return true;
} }
//QImage GxsIdDetails::makeDefaultIcon(const RsGxsId& id)
//{
// static std::map<RsGxsId,QImage> image_cache ;
//
// std::map<RsGxsId,QImage>::const_iterator it = image_cache.find(id) ;
//
// if(it != image_cache.end())
// return it->second ;
//
// int S = 128 ;
// QImage pix(S,S,QImage::Format_RGB32) ;
//
// uint64_t n = reinterpret_cast<const uint64_t*>(id.toByteArray())[0] ;
//
// uint8_t a[8] ;
// for(int i=0;i<8;++i)
// {
// a[i] = n&0xff ;
// n >>= 8 ;
// }
// QColor val[16] = {
// QColor::fromRgb( 255, 110, 180),
// QColor::fromRgb( 238, 92, 66),
// QColor::fromRgb( 255, 127, 36),
// QColor::fromRgb( 255, 193, 193),
// QColor::fromRgb( 127, 255, 212),
// QColor::fromRgb( 0, 255, 255),
// QColor::fromRgb( 224, 255, 255),
// QColor::fromRgb( 199, 21, 133),
// QColor::fromRgb( 50, 205, 50),
// QColor::fromRgb( 107, 142, 35),
// QColor::fromRgb( 30, 144, 255),
// QColor::fromRgb( 95, 158, 160),
// QColor::fromRgb( 143, 188, 143),
// QColor::fromRgb( 233, 150, 122),
// QColor::fromRgb( 151, 255, 255),
// QColor::fromRgb( 162, 205, 90),
// };
//
// int c1 = (a[0]^a[1]) & 0xf ;
// int c2 = (a[1]^a[2]) & 0xf ;
// int c3 = (a[2]^a[3]) & 0xf ;
// int c4 = (a[3]^a[4]) & 0xf ;
//
// for(int i=0;i<S/2;++i)
// for(int j=0;j<S/2;++j)
// {
// float res1 = 0.0f ;
// float res2 = 0.0f ;
// float f = 1.70;
//
// for(int k1=0;k1<4;++k1)
// for(int k2=0;k2<4;++k2)
// {
// res1 += cos( (2*M_PI*i/(float)S) * k1 * f) * (a[k1 ] & 0xf) + sin( (2*M_PI*j/(float)S) * k2 * f) * (a[k2 ] >> 4) + sin( (2*M_PI*i/(float)S) * k1 * f) * cos( (2*M_PI*j/(float)S) * k2 * f) * (a[k1+k2] >> 4) ;
// res2 += cos( (2*M_PI*i/(float)S) * k2 * f) * (a[k1+2] & 0xf) + sin( (2*M_PI*j/(float)S) * k1 * f) * (a[k2+1] >> 4) + sin( (2*M_PI*i/(float)S) * k2 * f) * cos( (2*M_PI*j/(float)S) * k1 * f) * (a[k1^k2] >> 4) ;
// }
//
// uint32_t q = 0 ;
// if(res1 >= 0.0f) q += val[c1].rgb() ; else q += val[c2].rgb() ;
// if(res2 >= 0.0f) q += val[c3].rgb() ; else q += val[c4].rgb() ;
//
// pix.setPixel( i, j, q) ;
// pix.setPixel( S-1-i, j, q) ;
// pix.setPixel( S-1-i, S-1-j, q) ;
// pix.setPixel( i, S-1-j, q) ;
// }
//
// image_cache[id] = pix.scaled(128,128,Qt::KeepAspectRatio,Qt::SmoothTransformation) ;
//
// return image_cache[id] ;
//}
/** /**
* @brief GxsIdDetails::makeIdentIcon * @brief GxsIdDetails::makeIdentIcon
* @param id: RsGxsId to compute * @param id: RsGxsId to compute
@ -457,52 +390,150 @@ static bool findTagIcon(int tag_class, int /*tag_type*/, QIcon &icon)
* Bring the source code from this adaptation: * Bring the source code from this adaptation:
* http://francisshanahan.com/identicon5/test.html * http://francisshanahan.com/identicon5/test.html
*/ */
const QImage& GxsIdDetails::makeDefaultIcon(const RsGxsId& id) const QPixmap GxsIdDetails::makeDefaultIcon(const RsGxsId& id, AvatarSize size)
{ {
checkCleanImagesCache();
// We use a cache for images. QImage has its own smart pointer system, but it does not prevent // We use a cache for images. QImage has its own smart pointer system, but it does not prevent
// the same image to be allocated many times. We do this using a cache. The cache is also cleaned-up // the same image to be allocated many times. We do this using a cache. The cache is also cleaned-up
// on a regular time basis so as to get rid of unused images. // on a regular time basis so as to get rid of unused images.
time_t now = time(NULL); time_t now = time(NULL);
// now look for the icon
QMutexLocker lock(&mIconCacheMutex);
auto& it = mDefaultIconCache[id];
if(it[(int)size].second.width() > 0)
{
it[(int)size].first = now;
return it[(int)size].second;
}
int S =0;
switch(size)
{
case SMALL: S = 16*3 ; break;
default:
case MEDIUM: S = 32*3 ; break;
case ORIGINAL:
case LARGE: S = 64*3 ; break;
}
QPixmap image = drawIdentIcon(QString::fromStdString(id.toStdString()),S,true);
it[(int)size] = std::make_pair(now,image);
return image;
}
void GxsIdDetails::checkCleanImagesCache()
{
time_t now = time(NULL);
// cleanup the cache every 10 mins // cleanup the cache every 10 mins
if(mLastIconCacheCleaning + DELAY_BETWEEN_ICON_CACHE_CLEANING < now) if(mLastIconCacheCleaning + DELAY_BETWEEN_ICON_CACHE_CLEANING < now)
{ {
std::cerr << "(II) Cleaning the icons cache." << std::endl; std::cerr << "(II) Cleaning the icons cache." << std::endl;
int nb_deleted = 0; int nb_deleted = 0;
uint32_t size_deleted = 0;
uint32_t total_size = 0;
QMutexLocker lock(&mIconCacheMutex);
for(auto it(mDefaultIconCache.begin());it!=mDefaultIconCache.end();) for(auto it(mDefaultIconCache.begin());it!=mDefaultIconCache.end();)
if(it->second.first + ICON_CACHE_STORAGE_TIME < now && it->second.second.isDetached()) {
{ bool all_empty = true ;
for(int i=0;i<4;++i)
if(it->second[i].first + ICON_CACHE_STORAGE_TIME < now && it->second[i].second.isDetached())
{
int s = it->second[i].second.width()*it->second[i].second.height()*4;
std::cerr << "Deleting pixmap " << it->first << " size " << i << " " << s << " bytes." << std::endl;
it->second[i].second = QPixmap();
it = mDefaultIconCache.erase(it);
++nb_deleted;
size_deleted += s;
}
else
{
all_empty = false;
total_size += it->second[i].second.width()*it->second[i].second.height()*4;
}
if(all_empty)
it = mDefaultIconCache.erase(it); it = mDefaultIconCache.erase(it);
++nb_deleted;
}
else else
++it; ++it;
}
mLastIconCacheCleaning = now; mLastIconCacheCleaning = now;
std::cerr << "(II) Removed " << nb_deleted << " unused icons. Cache contains " << mDefaultIconCache.size() << " icons"<< std::endl; std::cerr << "(II) Removed " << nb_deleted << " (" << size_deleted << " bytes) unused icons. Cache contains " << mDefaultIconCache.size() << " icons (" << total_size << " bytes)"<< std::endl;
} }
}
bool GxsIdDetails::loadPixmapFromData(const unsigned char *data,size_t data_len,QPixmap& pixmap, AvatarSize size)
{
// The trick below converts the data into an Id that can be read in the image cache. Because this method is mainly dedicated to loading
// avatars, we could also use the GxsId as id, but the avatar may change in time, so we actually need to make the id from the data itself.
assert(Sha1CheckSum::SIZE_IN_BYTES >= RsGxsId::SIZE_IN_BYTES);
Sha1CheckSum chksum = RsDirUtil::sha1sum(data,data_len);
RsGxsId id(chksum.toByteArray());
// We use a cache for images. QImage has its own smart pointer system, but it does not prevent
// the same image to be allocated many times. We do this using a cache. The cache is also cleaned-up
// on a regular time basis so as to get rid of unused images.
checkCleanImagesCache();
// now look for the icon // now look for the icon
auto it = mDefaultIconCache.find(id); QMutexLocker lock(&mIconCacheMutex);
if(it != mDefaultIconCache.end()) time_t now = time(NULL);
auto& it = mDefaultIconCache[id];
if(it[(int)size].second.width() > 0)
{ {
it->second.first = now; it[(int)size].first = now;
return it->second.second; pixmap = it[(int)size].second;
return true;
} }
QImage image = drawIdentIcon(QString::fromStdString(id.toStdString()),64*3, true); if(! pixmap.loadFromData(data,data_len))
return false;
mDefaultIconCache[id] = std::make_pair(now,image); // This resize is here just to prevent someone to explicitely add a huge blank image to screw up the UI
it = mDefaultIconCache.find(id);
return it->second.second; int wanted_S=0;
switch(size)
{
case ORIGINAL: wanted_S = 0 ;break;
case SMALL: wanted_S = 32 ;break;
default:
case MEDIUM: wanted_S = 64 ;break;
case LARGE: wanted_S = 128 ;break;
}
if(wanted_S > 0)
pixmap = pixmap.scaled(wanted_S,wanted_S,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
mDefaultIconCache[id][(int)size] = std::make_pair(now,pixmap);
#ifdef DEBUG
std::cerr << "Allocated new icon " << id << " size " << (int)size << std::endl;
#endif
return true;
} }
/** /**
* @brief GxsIdDetails::getSprite * @brief GxsIdDetails::getSprite
* @param shapeType: type of shape (0 to 15) * @param shapeType: type of shape (0 to 15)
@ -820,7 +851,7 @@ void GxsIdDetails::drawRotatedPolygon( QPixmap *pixmap,
* @param rotate: If the shapes could be rotated * @param rotate: If the shapes could be rotated
* @return QImage of computed hash * @return QImage of computed hash
*/ */
QImage GxsIdDetails::drawIdentIcon( QString hash, quint16 width, bool rotate) QPixmap GxsIdDetails::drawIdentIcon( QString hash, quint16 width, bool rotate)
{ {
bool ok; bool ok;
quint8 csh = hash.mid(0, 1).toInt(&ok,16);// Corner sprite shape quint8 csh = hash.mid(0, 1).toInt(&ok,16);// Corner sprite shape
@ -881,7 +912,7 @@ QImage GxsIdDetails::drawIdentIcon( QString hash, quint16 width, bool rotate)
} }
drawRotatedPolygon(&pixmap, center, size, size, 0, 0, size, fillCenter); drawRotatedPolygon(&pixmap, center, size, size, 0, 0, size, fillCenter);
return pixmap.toImage(); return pixmap;
} }
//static bool CreateIdIcon(const RsGxsId &id, QIcon &idIcon) //static bool CreateIdIcon(const RsGxsId &id, QIcon &idIcon)
@ -1089,11 +1120,11 @@ void GxsIdDetails::getIcons(const RsIdentityDetails &details, QList<QIcon> &icon
if(icon_types & ICON_TYPE_AVATAR) if(icon_types & ICON_TYPE_AVATAR)
{ {
if(details.mAvatar.mSize == 0 || !pix.loadFromData(details.mAvatar.mData, details.mAvatar.mSize, "PNG")) if(details.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(details.mAvatar.mData, details.mAvatar.mSize, pix))
#if QT_VERSION < 0x040700 #if QT_VERSION < 0x040700
pix = QPixmap::fromImage(makeDefaultIcon(details.mId)); pix = makeDefaultIcon(details.mId);
#else #else
pix.convertFromImage(makeDefaultIcon(details.mId)); pix = makeDefaultIcon(details.mId);
#endif #endif

View File

@ -74,6 +74,13 @@ public:
GxsIdDetails(); GxsIdDetails();
virtual ~GxsIdDetails(); virtual ~GxsIdDetails();
enum AvatarSize {
SMALL = 0x00,
MEDIUM = 0x01,
LARGE = 0x02,
ORIGINAL= 0x03
};
static void initialize(); static void initialize();
static void cleanup(); static void cleanup();
@ -102,8 +109,11 @@ public:
static void GenerateCombinedPixmap(QPixmap &pixmap, const QList<QIcon> &icons, int iconSize); static void GenerateCombinedPixmap(QPixmap &pixmap, const QList<QIcon> &icons, int iconSize);
//static QImage makeDefaultIcon(const RsGxsId& id); // These two methods use a cache so as to minimize the memory impact of avatars.
static const QImage& makeDefaultIcon(const RsGxsId& id);
static const QPixmap makeDefaultIcon(const RsGxsId& id, AvatarSize size = MEDIUM);
static bool loadPixmapFromData(const unsigned char *data, size_t data_len, QPixmap& pix, AvatarSize size = MEDIUM);
static void checkCleanImagesCache();
/* Processing */ /* Processing */
static void enableProcess(bool enable); static void enableProcess(bool enable);
@ -127,7 +137,7 @@ private:
quint16 x, quint16 y, quint16 x, quint16 y,
qreal shapeangle, qreal angle, qreal shapeangle, qreal angle,
quint16 size, QColor fillColor); quint16 size, QColor fillColor);
static QImage drawIdentIcon(QString hash, quint16 width, bool rotate); static QPixmap drawIdentIcon(QString hash, quint16 width, bool rotate);
private slots: private slots:
void objectDestroyed(QObject *object); void objectDestroyed(QObject *object);
@ -159,14 +169,15 @@ protected:
QMap<QObject*,CallbackData>::iterator mPendingDataIterator; QMap<QObject*,CallbackData>::iterator mPendingDataIterator;
static uint32_t mImagesAllocated; static uint32_t mImagesAllocated;
static std::map<RsGxsId,std::pair<time_t,QImage> > mDefaultIconCache; static std::map<RsGxsId,std::pair<time_t,QPixmap>[4] > mDefaultIconCache;
static time_t mLastIconCacheCleaning; static time_t mLastIconCacheCleaning;
int mCheckTimerId; int mCheckTimerId;
int mProcessDisableCount; int mProcessDisableCount;
/* Thread safe */ /* Thread safe */
QMutex mMutex; static QMutex mMutex;
static QMutex mIconCacheMutex;
}; };
#endif #endif

View File

@ -154,25 +154,21 @@ QVariant GxsIdRSTreeWidgetItem::data(int column, int role) const
if (role == Qt::ToolTipRole) if (role == Qt::ToolTipRole)
{ {
QString t = RSTreeWidgetItem::data(column, role).toString(); QString t = RSTreeWidgetItem::data(column, role).toString();
QImage pix; QPixmap pix;
if(mId.isNull()) return RSTreeWidgetItem::data(column, role); if(mId.isNull())
else if( rsReputations->overallReputationLevel(mId) == return RSTreeWidgetItem::data(column, role);
RsReputationLevel::LOCALLY_NEGATIVE ) else if( rsReputations->overallReputationLevel(mId) == RsReputationLevel::LOCALLY_NEGATIVE )
pix = QImage(BANNED_IMAGE); pix = QPixmap(BANNED_IMAGE);
else if ( mAvatar.mSize == 0 || else if ( mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(mAvatar.mData, mAvatar.mSize, pix,GxsIdDetails::LARGE) )
!pix.loadFromData(mAvatar.mData, mAvatar.mSize, "PNG") ) pix = GxsIdDetails::makeDefaultIcon(mId,GxsIdDetails::LARGE);
pix = GxsIdDetails::makeDefaultIcon(mId);
int S = QFontMetricsF(font(column)).height(); int S = QFontMetricsF(font(column)).height();
QString embeddedImage; QString embeddedImage;
if ( RsHtml::makeEmbeddedImage(
pix.scaled(QSize(4*S,4*S), Qt::KeepAspectRatio, if ( RsHtml::makeEmbeddedImage( pix.scaled(QSize(4*S,4*S), Qt::KeepAspectRatio, Qt::SmoothTransformation ).toImage(), embeddedImage, 8*S * 8*S ) )
Qt::SmoothTransformation ), t = "<table><tr><td>" + embeddedImage + "</td><td>" + t + "</td></table>";
embeddedImage, 8*S * 8*S ) )
t = "<table><tr><td>" + embeddedImage + "</td><td>" + t
+ "</td></table>";
return t; return t;
} }

View File

@ -26,6 +26,7 @@
#include <QMimeData> #include <QMimeData>
#include "CreateGxsChannelMsg.h" #include "CreateGxsChannelMsg.h"
#include "gui/gxs/GxsIdDetails.h"
#include "gui/feeds/SubFileItem.h" #include "gui/feeds/SubFileItem.h"
#include "gui/RetroShareLink.h" #include "gui/RetroShareLink.h"
#include "util/HandleRichText.h" #include "util/HandleRichText.h"
@ -771,7 +772,7 @@ void CreateGxsChannelMsg::loadChannelPostInfo(const uint32_t &token)
for(std::list<RsGxsFile>::const_iterator it(post.mFiles.begin());it!=post.mFiles.end();++it) for(std::list<RsGxsFile>::const_iterator it(post.mFiles.begin());it!=post.mFiles.end();++it)
addAttachment(it->mHash,it->mName,it->mSize,true,RsPeerId(),true); addAttachment(it->mHash,it->mName,it->mSize,true,RsPeerId(),true);
picture.loadFromData(post.mThumbnail.mData,post.mThumbnail.mSize,"PNG"); GxsIdDetails::loadPixmapFromData(post.mThumbnail.mData,post.mThumbnail.mSize,picture,GxsIdDetails::ORIGINAL);
thumbnail_label->setPixmap(picture); thumbnail_label->setPixmap(picture);
} }

View File

@ -326,7 +326,7 @@ void GxsChannelDialog::loadGroupSummaryToken(const uint32_t &token, std::list<Rs
if (group.mImage.mData != NULL) { if (group.mImage.mData != NULL) {
QPixmap image; QPixmap image;
image.loadFromData(group.mImage.mData, group.mImage.mSize, "PNG"); GxsIdDetails::loadPixmapFromData(group.mImage.mData, group.mImage.mSize, image,GxsIdDetails::ORIGINAL);
channelData->mIcon[group.mMeta.mGroupId] = image; channelData->mIcon[group.mMeta.mGroupId] = image;
} }

View File

@ -20,6 +20,7 @@
#include <QBuffer> #include <QBuffer>
#include "gui/gxs/GxsIdDetails.h"
#include "GxsChannelGroupDialog.h" #include "GxsChannelGroupDialog.h"
#include <retroshare/rsgxschannels.h> #include <retroshare/rsgxschannels.h>
@ -179,7 +180,8 @@ bool GxsChannelGroupDialog::service_loadGroup(uint32_t token, Mode /*mode*/, RsG
if (group.mImage.mData) { if (group.mImage.mData) {
QPixmap pixmap; QPixmap pixmap;
if (pixmap.loadFromData(group.mImage.mData, group.mImage.mSize, "PNG")) {
if (GxsIdDetails::loadPixmapFromData(group.mImage.mData, group.mImage.mSize,pixmap,GxsIdDetails::ORIGINAL)) {
setLogo(pixmap); setLogo(pixmap);
} }
} }

View File

@ -26,6 +26,7 @@
#include "GxsChannelPostsWidget.h" #include "GxsChannelPostsWidget.h"
#include "ui_GxsChannelPostsWidget.h" #include "ui_GxsChannelPostsWidget.h"
#include "gui/feeds/GxsChannelPostItem.h" #include "gui/feeds/GxsChannelPostItem.h"
#include "gui/gxs/GxsIdDetails.h"
#include "gui/gxschannels/CreateGxsChannelMsg.h" #include "gui/gxschannels/CreateGxsChannelMsg.h"
#include "gui/common/UIStateHelper.h" #include "gui/common/UIStateHelper.h"
#include "gui/settings/rsharesettings.h" #include "gui/settings/rsharesettings.h"
@ -238,7 +239,7 @@ void GxsChannelPostsWidget::insertChannelDetails(const RsGxsChannelGroup &group)
/* IMAGE */ /* IMAGE */
QPixmap chanImage; QPixmap chanImage;
if (group.mImage.mData != NULL) { if (group.mImage.mData != NULL) {
chanImage.loadFromData(group.mImage.mData, group.mImage.mSize, "PNG"); GxsIdDetails::loadPixmapFromData(group.mImage.mData, group.mImage.mSize, chanImage,GxsIdDetails::ORIGINAL);
} else { } else {
chanImage = QPixmap(CHAN_DEFAULT_IMAGE); chanImage = QPixmap(CHAN_DEFAULT_IMAGE);
} }

View File

@ -18,23 +18,27 @@
* * * *
*******************************************************************************/ *******************************************************************************/
#ifdef UNUSED_CODE
#include <gui/gxs/GxsIdDetails.h>
#include <util/PixmapMerging.h> #include <util/PixmapMerging.h>
#include <QPixmap> #include <QPixmap>
#include <QPainter> #include <QPainter>
QPixmap PixmapMerging::merge(const std::string & foregroundPixmapData, const std::string & backgroundPixmapFilename) { QPixmap PixmapMerging::merge(const std::string & foregroundPixmapData, const std::string & backgroundPixmapFilename)
QImage foregroundImage; {
foregroundImage.loadFromData((uchar *) foregroundPixmapData.c_str(), foregroundPixmapData.size()); QPixmap foregroundImage;
GxsIdDetails::loadPixmapFromData((uchar *) foregroundPixmapData.c_str(), foregroundPixmapData.size(),foregroundImage);
QPixmap backgroundPixmap = QPixmap(QString::fromStdString(backgroundPixmapFilename)); QPixmap backgroundPixmap = QPixmap(QString::fromStdString(backgroundPixmapFilename));
if (!foregroundImage.isNull()) { if (!foregroundImage.isNull()) {
QPainter painter(&backgroundPixmap); QPainter painter(&backgroundPixmap);
painter.drawImage(0, 0, painter.drawPixmap(0, 0, foregroundImage.scaled(backgroundPixmap.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
foregroundImage.scaled(backgroundPixmap.size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
painter.end(); painter.end();
} }
return backgroundPixmap; return backgroundPixmap;
} }
#endif

View File

@ -21,6 +21,7 @@
#ifndef PIXMAPMERGING_H #ifndef PIXMAPMERGING_H
#define PIXMAPMERGING_H #define PIXMAPMERGING_H
#ifdef UNUSED_CODE
#include <util/rsqtutildll.h> #include <util/rsqtutildll.h>
#include <util/NonCopyable.h> #include <util/NonCopyable.h>
@ -49,4 +50,6 @@ public:
RSQTUTIL_API static QPixmap merge(const std::string & foregroundPixmapData, const std::string & backgroundPixmapFilename); RSQTUTIL_API static QPixmap merge(const std::string & foregroundPixmapData, const std::string & backgroundPixmapFilename);
}; };
#endif
#endif //PIXMAPMERGING_H #endif //PIXMAPMERGING_H