added various sizes in icons cache so that we do not always allocate the largest sizes

This commit is contained in:
csoler 2019-06-04 11:49:26 +02:00
parent e66fb923fb
commit 94cbe65142
No known key found for this signature in database
GPG Key ID: 7BCA522266C0804C
18 changed files with 107 additions and 64 deletions

View File

@ -322,8 +322,8 @@ void ChatLobbyWidget::lobbyTreeWidgetCustomPopupMenu(QPoint)
QPixmap pixmap ;
if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap))
pixmap = GxsIdDetails::makeDefaultIcon(*it) ;
if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap, GxsIdDetails::SMALL))
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()));
action->setData(QString::fromStdString((*it).toStdString())) ;

View File

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

View File

@ -183,11 +183,11 @@ void IdDetailsDialog::insertIdDetails(uint32_t token)
QPixmap pixmap;
if(data.mImage.mSize > 0 && GxsIdDetails::loadPixmapFromData(data.mImage.mData, data.mImage.mSize, pixmap))
ui->avatarLabel->setPixmap(pixmap) ;
if(data.mImage.mSize > 0 && GxsIdDetails::loadPixmapFromData(data.mImage.mData, data.mImage.mSize, pixmap, GxsIdDetails::LARGE))
ui->avatarLabel->setPixmap(pixmap);
else
{
pixmap = 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
}

View File

@ -752,8 +752,8 @@ void IdDialog::loadCircleGroupMeta(const uint32_t &token)
QPixmap pixmap ;
if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap))
pixmap = GxsIdDetails::makeDefaultIcon(it->first) ;
if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap,GxsIdDetails::SMALL))
pixmap = GxsIdDetails::makeDefaultIcon(it->first,GxsIdDetails::SMALL) ;
if(has_id)
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 ;
if(data.mImage.mSize == 0 || !GxsIdDetails::loadPixmapFromData(data.mImage.mData, data.mImage.mSize, pixmap))
pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId)) ;
if(data.mImage.mSize == 0 || !GxsIdDetails::loadPixmapFromData(data.mImage.mData, data.mImage.mSize, pixmap,GxsIdDetails::SMALL))
pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId),GxsIdDetails::SMALL) ;
item->setIcon(RSID_COL_NICKNAME, QIcon(pixmap));
@ -1797,8 +1797,8 @@ void IdDialog::insertIdDetails(uint32_t token)
QPixmap pixmap ;
if(data.mImage.mSize == 0 || !GxsIdDetails::loadPixmapFromData(data.mImage.mData, data.mImage.mSize, pixmap))
pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId)) ;
if(data.mImage.mSize == 0 || !GxsIdDetails::loadPixmapFromData(data.mImage.mData, data.mImage.mSize, pixmap,GxsIdDetails::LARGE))
pixmap = GxsIdDetails::makeDefaultIcon(RsGxsId(data.mMeta.mGroupId),GxsIdDetails::LARGE) ;
#ifdef ID_DEBUG
std::cerr << "Setting header frame image : " << pixmap.width() << " x " << pixmap.height() << std::endl;
@ -2470,8 +2470,8 @@ void IdDialog::IdListCustomPopupMenu( QPoint )
QPixmap pixmap ;
if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap))
pixmap = GxsIdDetails::makeDefaultIcon(*it) ;
if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap,GxsIdDetails::SMALL))
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()));
action->setData(QString::fromStdString((*it).toStdString())) ;

View File

@ -258,7 +258,7 @@ void IdEditDialog::loadExistingId(uint32_t token)
QPixmap avatar;
if (mEditGroup.mImage.mSize > 0)
GxsIdDetails::loadPixmapFromData(mEditGroup.mImage.mData, mEditGroup.mImage.mSize, avatar);
GxsIdDetails::loadPixmapFromData(mEditGroup.mImage.mData, mEditGroup.mImage.mSize, avatar,GxsIdDetails::LARGE);
setAvatar(avatar);

View File

@ -467,8 +467,8 @@ void PeopleDialog::iw_AddButtonClickedExt()
QPixmap pixmap ;
if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap))
pixmap = GxsIdDetails::makeDefaultIcon(*it) ;
if(idd.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(idd.mAvatar.mData, idd.mAvatar.mSize, pixmap,GxsIdDetails::SMALL))
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()));
action->setData(QString::fromStdString((*it).toStdString()) + ";" + QString::fromStdString(dest->groupInfo().mMeta.mGroupId.toStdString())) ;

View File

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

View File

@ -164,7 +164,7 @@ bool PostedGroupDialog::service_loadGroup(uint32_t token, Mode /*mode*/, RsGroup
if (group.mGroupImage.mData) {
QPixmap pixmap;
if (GxsIdDetails::loadPixmapFromData(group.mGroupImage.mData, group.mGroupImage.mSize, pixmap))
if (GxsIdDetails::loadPixmapFromData(group.mGroupImage.mData, group.mGroupImage.mSize, pixmap,GxsIdDetails::ORIGINAL))
setLogo(pixmap);
} else {

View File

@ -256,7 +256,7 @@ void PostedItem::fill()
if(mPost.mImage.mData != NULL)
{
QPixmap pixmap;
GxsIdDetails::loadPixmapFromData(mPost.mImage.mData, mPost.mImage.mSize, pixmap);
GxsIdDetails::loadPixmapFromData(mPost.mImage.mData, mPost.mImage.mSize, pixmap,GxsIdDetails::ORIGINAL);
// Wiping data - as its been passed to thumbnail.
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 */
GxsIdDetails::loadPixmapFromData(data, size, avatar) ;
GxsIdDetails::loadPixmapFromData(data, size, avatar,GxsIdDetails::ORIGINAL) ;
free(data);
}
@ -58,7 +58,7 @@ void AvatarDefs::getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, cons
}
/* load image */
GxsIdDetails::loadPixmapFromData(data, size, avatar) ;
GxsIdDetails::loadPixmapFromData(data, size, avatar, GxsIdDetails::LARGE) ;
free(data);
}
@ -77,8 +77,8 @@ void AvatarDefs::getAvatarFromGxsId(const RsGxsId& gxsId, QPixmap &avatar, const
/* load image */
if(details.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(details.mAvatar.mData, details.mAvatar.mSize, avatar))
avatar = GxsIdDetails::makeDefaultIcon(gxsId);
if(details.mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(details.mAvatar.mData, details.mAvatar.mSize, avatar,GxsIdDetails::LARGE))
avatar = GxsIdDetails::makeDefaultIcon(gxsId,GxsIdDetails::LARGE);
}
void AvatarDefs::getAvatarFromGpgId(const RsPgpId& gpgId, QPixmap &avatar, const QString& defaultImage)

View File

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

View File

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

View File

@ -135,7 +135,7 @@ void GxsChannelGroupItem::fill()
if (mGroup.mImage.mData != NULL) {
QPixmap chanImage;
GxsIdDetails::loadPixmapFromData(mGroup.mImage.mData, mGroup.mImage.mSize, chanImage);
GxsIdDetails::loadPixmapFromData(mGroup.mImage.mData, mGroup.mImage.mSize, chanImage,GxsIdDetails::ORIGINAL);
ui->logoLabel->setPixmap(QPixmap(chanImage));
}

View File

@ -393,7 +393,7 @@ void GxsChannelPostItem::fill()
if(mPost.mThumbnail.mData != NULL)
{
QPixmap thumbnail;
GxsIdDetails::loadPixmapFromData(mPost.mThumbnail.mData, mPost.mThumbnail.mSize, thumbnail);
GxsIdDetails::loadPixmapFromData(mPost.mThumbnail.mData, mPost.mThumbnail.mSize, thumbnail,GxsIdDetails::ORIGINAL);
// Wiping data - as its been passed to thumbnail.
ui->logoLabel->setPixmap(thumbnail);
}

View File

@ -138,7 +138,7 @@ void PostedGroupItem::fill()
if (mGroup.mGroupImage.mData != NULL) {
QPixmap postedImage;
GxsIdDetails::loadPixmapFromData(mGroup.mGroupImage.mData, mGroup.mGroupImage.mSize, postedImage);
GxsIdDetails::loadPixmapFromData(mGroup.mGroupImage.mData, mGroup.mGroupImage.mSize, postedImage,GxsIdDetails::ORIGINAL);
ui->logoLabel->setPixmap(QPixmap(postedImage));
} else {
ui->logoLabel->setPixmap(QPixmap(":/images/posted_64.png"));

View File

@ -68,10 +68,10 @@
uint32_t GxsIdDetails::mImagesAllocated = 0;
time_t GxsIdDetails::mLastIconCacheCleaning = time(NULL);
std::map<RsGxsId,std::pair<time_t,QPixmap> > GxsIdDetails::mDefaultIconCache ;
std::map<RsGxsId,std::pair<time_t,QPixmap>[4] > GxsIdDetails::mDefaultIconCache ;
#define ICON_CACHE_STORAGE_TIME 600
#define DELAY_BETWEEN_ICON_CACHE_CLEANING 300
#define ICON_CACHE_STORAGE_TIME 60
#define DELAY_BETWEEN_ICON_CACHE_CLEANING 30
void ReputationItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
@ -459,7 +459,7 @@ static bool findTagIcon(int tag_class, int /*tag_type*/, QIcon &icon)
* Bring the source code from this adaptation:
* http://francisshanahan.com/identicon5/test.html
*/
const QPixmap GxsIdDetails::makeDefaultIcon(const RsGxsId& id)
const QPixmap GxsIdDetails::makeDefaultIcon(const RsGxsId& id, AvatarSize size)
{
checkCleanImagesCache();
@ -471,17 +471,28 @@ const QPixmap GxsIdDetails::makeDefaultIcon(const RsGxsId& id)
// now look for the icon
auto it = mDefaultIconCache.find(id);
auto& it = mDefaultIconCache[id];
if(it != mDefaultIconCache.end())
if(it[(int)size].second.width() > 0)
{
it->second.first = now;
return it->second.second;
it[(int)size].first = now;
return it[(int)size].second;
}
QPixmap image = drawIdentIcon(QString::fromStdString(id.toStdString()),64*3, true);
int S =0;
mDefaultIconCache[id] = std::make_pair(now,image);
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;
}
@ -498,13 +509,26 @@ void GxsIdDetails::checkCleanImagesCache()
int nb_deleted = 0;
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())
{
it->second[i].second = QPixmap();
std::cerr << "Deleting pixmap " << it->first << " size " << i << std::endl;
it = mDefaultIconCache.erase(it);
++nb_deleted;
}
else
all_empty = false;
if(all_empty)
it = mDefaultIconCache.erase(it);
++nb_deleted;
}
else
++it;
}
mLastIconCacheCleaning = now;
std::cerr << "(II) Removed " << nb_deleted << " unused icons. Cache contains " << mDefaultIconCache.size() << " icons"<< std::endl;
@ -512,7 +536,7 @@ void GxsIdDetails::checkCleanImagesCache()
}
bool GxsIdDetails::loadPixmapFromData(const unsigned char *data,size_t data_len,QPixmap& pixmap)
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.
@ -531,12 +555,12 @@ bool GxsIdDetails::loadPixmapFromData(const unsigned char *data,size_t data_len,
// now look for the icon
time_t now = time(NULL);
auto it = mDefaultIconCache.find(id);
auto& it = mDefaultIconCache[id];
if(it != mDefaultIconCache.end())
if(it[(int)size].second.width() > 0)
{
it->second.first = now;
pixmap = it->second.second;
it[(int)size].first = now;
pixmap = it[(int)size].second;
return true;
}
@ -546,11 +570,23 @@ bool GxsIdDetails::loadPixmapFromData(const unsigned char *data,size_t data_len,
// This resize is here just to prevent someone to explicitely add a huge blank image to screw up the UI
if(pixmap.width() != AvatarDialog::RS_AVATAR_IMAGE_W || pixmap.height() != AvatarDialog::RS_AVATAR_IMAGE_H)
pixmap = pixmap.scaled(AvatarDialog::RS_AVATAR_IMAGE_W,AvatarDialog::RS_AVATAR_IMAGE_H,Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
int wanted_S=0;
mDefaultIconCache[id] = std::make_pair(now,pixmap);
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);
std::cerr << "Allocated new icon " << id << " size " << (int)size << std::endl;
return true;
}
/**

View File

@ -74,6 +74,13 @@ public:
GxsIdDetails();
virtual ~GxsIdDetails();
enum AvatarSize {
SMALL = 0x00,
MEDIUM = 0x01,
LARGE = 0x02,
ORIGINAL= 0x03
};
static void initialize();
static void cleanup();
@ -104,8 +111,8 @@ public:
// These two methods use a cache so as to minimize the memory impact of avatars.
static const QPixmap makeDefaultIcon(const RsGxsId& id);
static bool loadPixmapFromData(const unsigned char *data,size_t data_len,QPixmap& pix);
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 */
@ -162,7 +169,7 @@ protected:
QMap<QObject*,CallbackData>::iterator mPendingDataIterator;
static uint32_t mImagesAllocated;
static std::map<RsGxsId,std::pair<time_t,QPixmap> > mDefaultIconCache;
static std::map<RsGxsId,std::pair<time_t,QPixmap>[4] > mDefaultIconCache;
static time_t mLastIconCacheCleaning;
int mCheckTimerId;

View File

@ -160,8 +160,8 @@ QVariant GxsIdRSTreeWidgetItem::data(int column, int role) const
return RSTreeWidgetItem::data(column, role);
else if( rsReputations->overallReputationLevel(mId) == RsReputationLevel::LOCALLY_NEGATIVE )
pix = QPixmap(BANNED_IMAGE);
else if ( mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(mAvatar.mData, mAvatar.mSize, pix) )
pix = GxsIdDetails::makeDefaultIcon(mId);
else if ( mAvatar.mSize == 0 || !GxsIdDetails::loadPixmapFromData(mAvatar.mData, mAvatar.mSize, pix,GxsIdDetails::LARGE) )
pix = GxsIdDetails::makeDefaultIcon(mId,GxsIdDetails::LARGE);
int S = QFontMetricsF(font(column)).height();