Simplified usage of GxsIdDetails and removed some QTimer.

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@7714 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
thunder2 2014-11-27 00:55:48 +00:00
parent 705598b0b4
commit f692116207
11 changed files with 558 additions and 477 deletions

View File

@ -100,6 +100,8 @@ void GxsForumMsgItem::setup()
ui->titleLabel->setText(tr("Loading"));
ui->subjectLabel->clear();
ui->timestamplabel->clear();
ui->parentNameLabel->clear();
ui->nameLabel->clear();
/* general ones */
connect(ui->expandButton, SIGNAL(clicked()), this, SLOT(toggle()));
@ -294,6 +296,8 @@ void GxsForumMsgItem::fill()
}
}
ui->nameLabel->setId(mMessage.mMeta.mAuthorId);
// ui->avatar->setId(msg.srcId, true);
// if (rsPeers->getPeerName(msg.srcId) != "") {
@ -323,6 +327,8 @@ void GxsForumMsgItem::fill()
ui->parentSubLabel->setText(linkParent.toHtml());
ui->parentMsgLabel->setText(RsHtml().formatText(NULL, QString::fromUtf8(mParentMessage.mMsg.c_str()), RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS));
ui->parentNameLabel->setId(mParentMessage.mMeta.mAuthorId);
// if (rsPeers->getPeerName(msgParent.srcId) !="")
// {
// RetroShareLink linkMessage;

View File

@ -336,7 +336,7 @@
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="nameLabel">
<widget class="GxsIdLabel" name="nameLabel">
<property name="font">
<font>
<weight>75</weight>
@ -461,7 +461,7 @@
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="parentNameLabel">
<widget class="GxsIdLabel" name="parentNameLabel">
<property name="font">
<font>
<weight>75</weight>
@ -604,6 +604,11 @@
<header>gui/common/AvatarWidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>GxsIdLabel</class>
<extends>QLabel</extends>
<header>gui/gxs/GxsIdLabel.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="../images.qrc"/>

View File

@ -56,8 +56,6 @@ GxsIdChooser::GxsIdChooser(QWidget *parent)
mDefaultId.clear() ;
mDefaultIdName.clear();
mTimer = NULL;
mTimerCount = 0;
/* Enable sort with own role */
QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this);
@ -120,64 +118,34 @@ void GxsIdChooser::loadIds(uint32_t chooserFlags, RsGxsId defId)
mFirstLoad = true;
}
bool GxsIdChooser::makeIdDesc(const RsGxsId &gxsId, QString &desc)
static void loadPrivateIdsCallback(GxsIdDetailsType type, const RsIdentityDetails &details, QObject *object, const QVariant &/*data*/)
{
std::list<QIcon> icons;
QString comment ;
if (!GxsIdDetails::MakeIdDesc(gxsId, false, desc, icons,comment)) {
if (mTimerCount > MAX_TRY) {
desc = QString("%1 ... [").arg(tr("Not found"));
desc += QString::fromStdString(gxsId.toStdString().substr(0,5));
desc += "...]";
}
return false;
}
return true;
}
void GxsIdChooser::addPrivateId(const RsGxsId &gxsId, bool replace)
{
QString str;
bool found = makeIdDesc(gxsId, str);
if (!found) {
/* Add to pending id's */
mPendingId.push_back(gxsId);
if (replace && mTimerCount <= MAX_TRY) {
/* Retry */
return;
}
}
QString id = QString::fromStdString(gxsId.toStdString());
if (replace) {
/* Find and replace text of exisiting item */
int index = findData(id);
if (index >= 0) {
setItemText(index, str);
setItemData(index, QString("%1_%2").arg(found ? "1" : "2").arg(str), ROLE_SORT);
setItemData(index, found ? TYPE_FOUND_ID : TYPE_UNKNOWN_ID, ROLE_TYPE);
model()->sort(0);
GxsIdChooser *chooser = dynamic_cast<GxsIdChooser*>(object);
if (!chooser) {
return;
}
//If not found create a new item.
}
}
/* Add new item */
addItem(str, id);
setItemData(count() - 1, QString("%1_%2").arg(found ? "1" : "2").arg(str), ROLE_SORT);
setItemData(count() - 1, found ? TYPE_FOUND_ID : TYPE_UNKNOWN_ID, ROLE_TYPE);
model()->sort(0);
QString text = GxsIdDetails::getNameForType(type, details);
QString id = QString::fromStdString(details.mId.toStdString());
/* Find and replace text of exisiting item */
int index = chooser->findData(id);
if (index >= 0) {
chooser->setItemText(index, text);
} else {
/* Add new item */
chooser->addItem(text, id);
index = chooser->count() - 1;
}
chooser->setItemData(index, QString("%1_%2").arg((type == GXS_ID_DETAILS_TYPE_DONE) ? "1" : "2").arg(text), ROLE_SORT);
chooser->setItemData(index, (type == GXS_ID_DETAILS_TYPE_DONE) ? TYPE_FOUND_ID : TYPE_UNKNOWN_ID, ROLE_TYPE);
chooser->model()->sort(0);
}
void GxsIdChooser::loadPrivateIds(uint32_t token)
{
mPendingId.clear();
if (mFirstLoad) { clear();}
mTimerCount = 0;
if (mTimer) {
delete(mTimer);
}
std::list<RsGxsId> ids;
//rsIdentity->getOwnIds(ids);
@ -245,17 +213,7 @@ void GxsIdChooser::loadPrivateIds(uint32_t token)
for(std::list<RsGxsId>::iterator it = ids.begin(); it != ids.end(); ++it) {
/* add to Chooser */
addPrivateId(*it, !mFirstLoad);
}
if (!mPendingId.empty()) {
/* Create and start timer to load pending id's */
mTimerCount = 0;
mTimer = new QTimer();
mTimer->setSingleShot(true);
mTimer->setInterval(500);
connect(mTimer, SIGNAL(timeout()), this, SLOT(timer()));
mTimer->start();
GxsIdDetails::process(*it, loadPrivateIdsCallback, this);
}
setDefaultItem();
@ -327,41 +285,6 @@ void GxsIdChooser::myCurrentIndexChanged(int index)
setToolTip("");
}
}
void GxsIdChooser::timer()
{
++mTimerCount;
QList<RsGxsId> pendingId = mPendingId;
mPendingId.clear();
/* Process pending id's */
while (!pendingId.empty()) {
RsGxsId id = pendingId.front();
pendingId.pop_front();
addPrivateId(id, true);
}
setDefaultItem();
if (mPendingId.empty()) {
/* All pending id's processed */
delete(mTimer);
mTimer = NULL;
mTimerCount = 0;
} else {//if (mPendingId.empty())
if (mTimerCount <= MAX_TRY) {
/* Restart timer */
mTimer->start();
} else {//if (mTimerCount <= MAX_TRY)
delete(mTimer);
mTimer = NULL;
mTimerCount = 0;
mPendingId.clear();
}
}
}
void GxsIdChooser::updateDisplay(bool complete)
{

View File

@ -72,14 +72,11 @@ protected:
private slots:
void fillDisplay(bool complete);
void timer();
void myCurrentIndexChanged(int index);
private:
void requestIdList() ;
void loadPrivateIds(uint32_t token);
void addPrivateId(const RsGxsId &gxsId, bool replace);
bool makeIdDesc(const RsGxsId &gxsId, QString &desc);
void insertIdList(uint32_t token);
void setDefaultItem();
@ -89,10 +86,6 @@ private:
bool mFirstLoad;
QPushButton* addNewCxsId;
QList<RsGxsId> mPendingId;
QTimer *mTimer;
unsigned int mTimerCount;
TokenQueue *mIdQueue;
RsGxsUpdateBroadcastBase *mBase;
};

View File

@ -21,6 +21,11 @@
*
*/
#include <QApplication>
#include <QThread>
#include <QTimerEvent>
#include <QMutexLocker>
#include <math.h>
#include "GxsIdDetails.h"
@ -28,9 +33,6 @@
#include <iostream>
#include <QPainter>
#include <QIcon>
#include <QObject>
/* Images for tag icons */
#define IMAGE_LOADING ":/images/folder-draft.png"
@ -44,6 +46,9 @@
#define IMAGE_DEV_PATCHER ":/images/tags/dev-patcher.png"
#define IMAGE_DEV_DEVELOPER ":/images/tags/developer.png"
#define TIMER_INTERVAL 1000
#define MAX_ATTEMPTS 10
static const int IconSize = 20;
const int kRecognTagClass_DEVELOPMENT = 1;
@ -54,8 +59,190 @@ const int kRecognTagType_Dev_Translator = 3;
const int kRecognTagType_Dev_Patcher = 4;
const int kRecognTagType_Dev_Developer = 5;
/* The global object */
GxsIdDetails *GxsIdDetails::mInstance = NULL;
static bool findTagIcon(int tag_class, int tag_type, QIcon &icon)
GxsIdDetails::GxsIdDetails()
: QObject()
{
mCheckTimerId = 0;
connect(this, SIGNAL(startTimerFromThread()), this, SLOT(doStartTimer()));
}
GxsIdDetails::~GxsIdDetails()
{
}
void GxsIdDetails::objectDestroyed(QObject *object)
{
if (!object) {
return;
}
QMutexLocker lock(&mMutex);
/* Object is about to be destroyed, remove it from pending list */
QList<CallbackData>::iterator dataIt;
for (dataIt = mPendingData.begin(); dataIt != mPendingData.end(); ) {
CallbackData &pendingData = *dataIt;
if (pendingData.mObject == object) {
dataIt = mPendingData.erase(dataIt);
continue;
}
++dataIt;
}
}
void GxsIdDetails::connectObject_locked(QObject *object, bool doConnect)
{
if (!object) {
return;
}
/* Search Object in pending list */
QList<CallbackData>::iterator dataIt;
for (dataIt = mPendingData.begin(); dataIt != mPendingData.end(); ++dataIt) {
if (dataIt->mObject == object) {
/* Object still/already in pending list */
return;
}
}
if (doConnect) {
connect(object, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
} else {
disconnect(object, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
}
}
void GxsIdDetails::timerEvent(QTimerEvent *event)
{
if (event->timerId() == mCheckTimerId) {
/* Stop timer */
killTimer(mCheckTimerId);
mCheckTimerId = 0;
if (rsIdentity) {
QMutexLocker lock(&mMutex);
if (!mPendingData.empty()) {
/* Check pending id's */
QList<CallbackData>::iterator dataIt;
for (dataIt = mPendingData.begin(); dataIt != mPendingData.end(); ) {
CallbackData &pendingData = *dataIt;
RsIdentityDetails details;
if (rsIdentity->getIdDetails(pendingData.mId, details)) {
/* Got details */
pendingData.mCallback(GXS_ID_DETAILS_TYPE_DONE, details, pendingData.mObject, pendingData.mData);
QObject *object = pendingData.mObject;
dataIt = mPendingData.erase(dataIt);
connectObject_locked(object, false);
continue;
}
if (++pendingData.mAttempt > MAX_ATTEMPTS) {
/* Max attempts reached, stop trying */
details.mId = pendingData.mId;
pendingData.mCallback(GXS_ID_DETAILS_TYPE_FAILED, details, pendingData.mObject, pendingData.mData);
QObject *object = pendingData.mObject;
dataIt = mPendingData.erase(dataIt);
connectObject_locked(object, false);
continue;
}
++dataIt;
}
}
}
QMutexLocker lock(&mMutex);
if (mPendingData.empty()) {
/* All done */
mInstance = NULL;
deleteLater();
} else {
/* Start timer */
doStartTimer();
}
}
QObject::timerEvent(event);
}
void GxsIdDetails::doStartTimer()
{
if (mCheckTimerId) {
/* Timer is running */
return;
}
mCheckTimerId = startTimer(TIMER_INTERVAL);
}
bool GxsIdDetails::process(const RsGxsId &id, GxsIdDetailsCallbackFunction callback, QObject *object, const QVariant &data)
{
if (!callback) {
return false;
}
RsIdentityDetails details;
if (id.isNull()) {
callback(GXS_ID_DETAILS_TYPE_EMPTY, details, object, data);
return true;
}
/* Try to get the information */
if (rsIdentity && rsIdentity->getIdDetails(id, details)) {
callback(GXS_ID_DETAILS_TYPE_DONE, details, object, data);
return true;
}
details.mId = id;
callback(GXS_ID_DETAILS_TYPE_LOADING, details, object, data);
/* Add id to the pending list */
if (!mInstance) {
mInstance = new GxsIdDetails;
mInstance->moveToThread(qApp->thread());
}
CallbackData pendingData;
pendingData.mId = id;
pendingData.mCallback = callback;
pendingData.mObject = object;
pendingData.mData = data;
{
QMutexLocker lock(&mInstance->mMutex);
/* Connect signal "destroy" */
mInstance->connectObject_locked(object, true);
mInstance->mPendingData.push_back(pendingData);
}
/* Start timer */
if (QThread::currentThread() == qApp->thread()) {
/* Start timer directly */
mInstance->doStartTimer();
} else {
/* Send signal to start timer in main thread */
emit mInstance->startTimerFromThread();
}
return true;
}
static bool findTagIcon(int tag_class, int /*tag_type*/, QIcon &icon)
{
switch(tag_class)
{
@ -72,158 +259,220 @@ static bool findTagIcon(int tag_class, int tag_type, QIcon &icon)
QImage GxsIdDetails::makeDefaultIcon(const RsGxsId& id)
{
static std::map<RsGxsId,QImage> image_cache ;
static std::map<RsGxsId,QImage> image_cache ;
std::map<RsGxsId,QImage>::const_iterator it = image_cache.find(id) ;
std::map<RsGxsId,QImage>::const_iterator it = image_cache.find(id) ;
if(it != image_cache.end())
return it->second ;
if(it != image_cache.end())
return it->second ;
int S = 128 ;
QImage pix(S,S,QImage::Format_RGB32) ;
int S = 128 ;
QImage pix(S,S,QImage::Format_RGB32) ;
uint64_t n = reinterpret_cast<const uint64_t*>(id.toByteArray())[0] ;
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(64,64,Qt::KeepAspectRatio,Qt::SmoothTransformation) ;
return image_cache[id] ;
}
static bool CreateIdIcon(const RsGxsId &id, QIcon &idIcon)
{
QPixmap image(IconSize, IconSize);
QPainter painter(&image);
painter.fillRect(0, 0, IconSize, IconSize, Qt::black);
int len = id.SIZE_IN_BYTES;
for(int i = 0; i<len; ++i)
uint8_t a[8] ;
for(int i=0;i<8;++i)
{
unsigned char hex = id.toByteArray()[i];
int x = hex & 0xf ;
int y = (hex & 0xf0) >> 4 ;
painter.fillRect(x, y, x+1, y+1, Qt::green);
a[i] = n&0xff ;
n >>= 8 ;
}
idIcon = QIcon(image);
return true;
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(64,64,Qt::KeepAspectRatio,Qt::SmoothTransformation) ;
return image_cache[id] ;
}
bool GxsIdDetails::MakeIdDesc(const RsGxsId &id, bool doIcons, QString &str, std::list<QIcon> &icons,QString& comment)
//static bool CreateIdIcon(const RsGxsId &id, QIcon &idIcon)
//{
// QPixmap image(IconSize, IconSize);
// QPainter painter(&image);
// painter.fillRect(0, 0, IconSize, IconSize, Qt::black);
// int len = id.SIZE_IN_BYTES;
// for(int i = 0; i<len; ++i)
// {
// unsigned char hex = id.toByteArray()[i];
// int x = hex & 0xf ;
// int y = (hex & 0xf0) >> 4 ;
// painter.fillRect(x, y, x+1, y+1, Qt::green);
// }
// idIcon = QIcon(image);
// return true;
//}
QString GxsIdDetails::getLoadingText(const RsGxsId &id)
{
return QString("%1... %2").arg(QApplication::translate("GxsIdDetails", "Loading"), QString::fromStdString(id.toStdString().substr(0, 5)));
}
QString GxsIdDetails::getFailedText(const RsGxsId &id)
{
return QString("%1 ...[%2]").arg(QApplication::translate("GxsIdDetails", "Not found"), QString::fromStdString(id.toStdString().substr(0, 5)));
}
QString GxsIdDetails::getEmptyIdText()
{
return QApplication::translate("GxsIdDetails", "No Signature");
}
QString GxsIdDetails::getNameForType(GxsIdDetailsType type, const RsIdentityDetails &details)
{
switch (type) {
case GXS_ID_DETAILS_TYPE_EMPTY:
return getEmptyIdText();
case GXS_ID_DETAILS_TYPE_LOADING:
return getLoadingText(details.mId);
case GXS_ID_DETAILS_TYPE_DONE:
return getName(details);
case GXS_ID_DETAILS_TYPE_FAILED:
return getFailedText(details.mId);
}
return "";
}
QIcon GxsIdDetails::getLoadingIcon(const RsGxsId &/*id*/)
{
return QIcon(IMAGE_LOADING);
}
bool GxsIdDetails::MakeIdDesc(const RsGxsId &id, bool doIcons, QString &str, QList<QIcon> &icons, QString& comment)
{
RsIdentityDetails details;
if (!rsIdentity->getIdDetails(id, details))
{
// std::cerr << "GxsIdTreeWidget::MakeIdDesc() FAILED TO GET ID " << id;
// std::cerr << "GxsIdTreeWidget::MakeIdDesc() FAILED TO GET ID " << id;
//std::cerr << std::endl;
str = QObject::tr("Loading... ") + QString::fromStdString(id.toStdString().substr(0,5));
str = getLoadingText(id);
if (!doIcons)
{
QIcon baseIcon = QIcon(IMAGE_LOADING);
icons.push_back(baseIcon);
icons.push_back(getLoadingIcon(id));
}
return false;
}
str = QString::fromUtf8(details.mNickname.c_str());
str = getName(details);
std::list<RsRecognTag>::iterator it;
for(it = details.mRecognTags.begin(); it != details.mRecognTags.end(); ++it)
comment += getComment(details);
if (doIcons)
getIcons(details, icons);
// Cyril: I disabled these three which I believe to have been put for testing purposes.
//
// icons.push_back(QIcon(IMAGE_ANON));
// icons.push_back(QIcon(IMAGE_ANON));
// icons.push_back(QIcon(IMAGE_ANON));
// std::cerr << "GxsIdTreeWidget::MakeIdDesc() ID Ok. Comment: " << comment.toStdString() ;
// std::cerr << std::endl;
return true;
}
QString GxsIdDetails::getName(const RsIdentityDetails &details)
{
QString name = QString::fromUtf8(details.mNickname.c_str());
std::list<RsRecognTag>::const_iterator it;
for (it = details.mRecognTags.begin(); it != details.mRecognTags.end(); ++it)
{
str += " (";
str += QString::number(it->tag_class);
str += ":";
str += QString::number(it->tag_type);
str += ")";
name += QString(" (%1 %2)").arg(it->tag_class).arg(it->tag_type);
}
comment += "Identity name: " + QString::fromUtf8(details.mNickname.c_str()) + "\n";
comment += "Identity Id : " + QString::fromStdString(id.toStdString()) + "\n";
return name;
}
QString GxsIdDetails::getComment(const RsIdentityDetails &details)
{
QString comment;
comment = QString("%1: %2\n%3: %4").arg(QApplication::translate("GxsIdDetails", "Identity name"),
QString::fromUtf8(details.mNickname.c_str()),
QApplication::translate("GxsIdDetails", "Identity Id"),
QString::fromStdString(details.mId.toStdString()));
if (details.mPgpLinked)
{
comment += "Authentication: signed by " ;
comment += QString("\n%1: %2 ").arg(QApplication::translate("GxsIdDetails", "Authentication"), QApplication::translate("GxsIdDetails", "signed by"));
if (details.mPgpKnown)
{
/* look up real name */
std::string authorName = rsPeers->getGPGName(details.mPgpId);
comment += QString::fromUtf8(authorName.c_str());
comment += " [";
comment += QString::fromStdString(details.mPgpId.toStdString()) ;
comment += "]";
comment += QString("%1 [%2]").arg(QString::fromUtf8(authorName.c_str()), QString::fromStdString(details.mPgpId.toStdString()));
}
else
comment += QObject::tr("unknown Key") ;
comment += QApplication::translate("GxsIdDetails", "unknown Key");
}
else
comment += "Authentication: anonymous" ;
comment += QString("\n%1: %2").arg(QApplication::translate("GxsIdDetails", "Authentication"), QApplication::translate("GxsIdDetails", "anonymous"));
if (!doIcons)
return true;
return comment;
}
QPixmap pix ;
pix.convertFromImage( makeDefaultIcon(id) );
QIcon idIcon( pix ) ;
//CreateIdIcon(id, idIcon);
void GxsIdDetails::getIcons(const RsIdentityDetails &details, QList<QIcon> &icons)
{
QPixmap pix ;
pix.convertFromImage(makeDefaultIcon(details.mId));
QIcon idIcon(pix);
//CreateIdIcon(id, idIcon);
icons.push_back(idIcon);
// ICON Logic.
@ -240,7 +489,8 @@ bool GxsIdDetails::MakeIdDesc(const RsGxsId &id, bool doIcons, QString &str, std
icons.push_back(baseIcon);
// Add In RecognTags Icons.
for(it = details.mRecognTags.begin(); it != details.mRecognTags.end(); ++it)
std::list<RsRecognTag>::const_iterator it;
for (it = details.mRecognTags.begin(); it != details.mRecognTags.end(); ++it)
{
QIcon tagIcon;
if (findTagIcon(it->tag_class, it->tag_type, tagIcon))
@ -248,34 +498,22 @@ bool GxsIdDetails::MakeIdDesc(const RsGxsId &id, bool doIcons, QString &str, std
icons.push_back(tagIcon);
}
}
// Cyril: I disabled these three which I believe to have been put for testing purposes.
//
// icons.push_back(QIcon(IMAGE_ANON));
// icons.push_back(QIcon(IMAGE_ANON));
// icons.push_back(QIcon(IMAGE_ANON));
// std::cerr << "GxsIdTreeWidget::MakeIdDesc() ID Ok. Comment: " << comment.toStdString() ;
// std::cerr << std::endl;
return true;
}
bool GxsIdDetails::GenerateCombinedIcon(QIcon &outIcon, std::list<QIcon> &icons)
bool GxsIdDetails::GenerateCombinedIcon(QIcon &outIcon, const QList<QIcon> &icons)
{
int count = icons.size();
QPixmap image(IconSize * count, IconSize);
QPainter painter(&image);
painter.fillRect(0, 0, IconSize * count, IconSize, Qt::transparent);
std::list<QIcon>::iterator it;
QList<QIcon>::const_iterator it;
int i = 0;
for(it = icons.begin(); it != icons.end(); ++it, ++i)
{
it->paint(&painter, IconSize * i, 0, IconSize, IconSize);
it->paint(&painter, IconSize * i, 0, IconSize, IconSize);
}
outIcon = QIcon(image);
return true;
}

View File

@ -24,21 +24,96 @@
#ifndef _GXS_ID_DETAILS_H
#define _GXS_ID_DETAILS_H
#include <QObject>
#include <QMutex>
#include <QVariant>
#include <QIcon>
#include <QString>
#include <retroshare/rsidentity.h>
#include <list>
namespace GxsIdDetails
class QLabel;
enum GxsIdDetailsType
{
GXS_ID_DETAILS_TYPE_EMPTY,
GXS_ID_DETAILS_TYPE_LOADING,
GXS_ID_DETAILS_TYPE_DONE,
GXS_ID_DETAILS_TYPE_FAILED
};
bool MakeIdDesc(const RsGxsId &id, bool doIcons,
QString &desc, std::list<QIcon> &icons,QString& comment);
typedef void (*GxsIdDetailsCallbackFunction)(GxsIdDetailsType type, const RsIdentityDetails &details, QObject *object, const QVariant &data);
bool GenerateCombinedIcon(QIcon &outIcon, std::list<QIcon> &icons);
class GxsIdDetails : public QObject
{
Q_OBJECT
QImage makeDefaultIcon(const RsGxsId& id);
public:
GxsIdDetails();
virtual ~GxsIdDetails();
} // namespace GxsIdDetails.
/* Information */
static bool MakeIdDesc(const RsGxsId &id, bool doIcons, QString &desc, QList<QIcon> &icons, QString& comment);
static QString getName(const RsIdentityDetails &details);
static QString getComment(const RsIdentityDetails &details);
static void getIcons(const RsIdentityDetails &details, QList<QIcon> &icons);
static QString getEmptyIdText();
static QString getLoadingText(const RsGxsId &id);
static QString getFailedText(const RsGxsId &id);
static QString getNameForType(GxsIdDetailsType type, const RsIdentityDetails &details);
static QIcon getLoadingIcon(const RsGxsId &id);
static bool GenerateCombinedIcon(QIcon &outIcon, const QList<QIcon> &icons);
static QImage makeDefaultIcon(const RsGxsId& id);
/* Processing */
static bool process(const RsGxsId &id, GxsIdDetailsCallbackFunction callback, QObject *object, const QVariant &data = QVariant());
signals:
void startTimerFromThread();
protected:
void connectObject_locked(QObject *object, bool doConnect);
/* Timer */
virtual void timerEvent(QTimerEvent *event);
private slots:
void objectDestroyed(QObject *object);
void doStartTimer();
protected:
class CallbackData
{
public:
CallbackData()
{
mAttempt = 0;
mCallback = 0;
mObject = NULL;
}
public:
int mAttempt;
RsGxsId mId;
GxsIdDetailsCallbackFunction mCallback;
QObject *mObject;
QVariant mData;
};
static GxsIdDetails *mInstance;
/* Pending data */
QList<CallbackData> mPendingData;
int mCheckTimerId;
/* Thread safe */
QMutex mMutex;
};
#endif

View File

@ -24,34 +24,42 @@
#include "GxsIdLabel.h"
#include "GxsIdDetails.h"
#include <algorithm>
#include <retroshare/rspeers.h>
#include <iostream>
/** Constructor */
GxsIdLabel::GxsIdLabel(QWidget *parent)
:QLabel(parent), mTimer(NULL), mCount(0)
: QLabel(parent)
{
mTimer = new QTimer(this);
mTimer->setSingleShot(true);
connect(mTimer, SIGNAL(timeout()), this, SLOT(loadId()));
}
return;
static void fillLabelCallback(GxsIdDetailsType type, const RsIdentityDetails &details, QObject *object, const QVariant &/*data*/)
{
QLabel *label = dynamic_cast<QLabel*>(object);
if (!label) {
return;
}
label->setText(GxsIdDetails::getNameForType(type, details));
QString toolTip;
switch (type) {
case GXS_ID_DETAILS_TYPE_EMPTY:
case GXS_ID_DETAILS_TYPE_LOADING:
case GXS_ID_DETAILS_TYPE_FAILED:
break;
case GXS_ID_DETAILS_TYPE_DONE:
toolTip = GxsIdDetails::getComment(details);
break;
}
label->setToolTip(toolTip);
}
void GxsIdLabel::setId(const RsGxsId &id)
{
mId = id;
if (mId.isNull())
{
setText("No Signature");
}
else
{
loadId();
}
GxsIdDetails::process(mId, fillLabelCallback, this);
}
bool GxsIdLabel::getId(RsGxsId &id)
@ -59,32 +67,3 @@ bool GxsIdLabel::getId(RsGxsId &id)
id = mId;
return true;
}
#define MAX_ATTEMPTS 3
void GxsIdLabel::loadId()
{
mCount++;
/* try and get details - if not there ... set callback */
QString desc;
QString comment ;
std::list<QIcon> icons;
bool loaded = GxsIdDetails::MakeIdDesc(mId, false, desc, icons,comment);
setText(desc);
setToolTip(comment);
if (loaded)
{
return;
}
if (mCount < MAX_ATTEMPTS)
{
/* timer event to try again */
mTimer->setInterval(mCount * 1000);
mTimer->start();
}
}

View File

@ -21,17 +21,15 @@
*
*/
#ifndef _GXS_ID_LABEL_H
#define _GXS_ID_LABEL_H
#include <QTimer>
#include <QLabel>
#include <retroshare/rsidentity.h>
class GxsIdLabel : public QLabel
{
Q_OBJECT
Q_OBJECT
public:
GxsIdLabel(QWidget *parent = NULL);
@ -39,15 +37,8 @@ public:
void setId(const RsGxsId &id);
bool getId(RsGxsId &id);
private slots:
void loadId();
private:
QTimer *mTimer;
RsGxsId mId;
int mCount;
};
#endif

View File

@ -36,7 +36,7 @@ static void paintGxsId( QPainter * painter,
{
QString desc;
QString comment;
std::list<QIcon> icons;
QList<QIcon> icons;
if (!GxsIdDetails::MakeIdDesc(id, true, desc, icons,comment))
{
/* flag for reloading */
@ -45,11 +45,9 @@ static void paintGxsId( QPainter * painter,
const QRect &rect = option.rect;
int x = rect.left();
int y = rect.top();
int height = rect.height();
int width = rect.width();
std::list<QIcon>::iterator it;
QList<QIcon>::iterator it;
const int IconSize = 15;
int i = 0;
for(it = icons.begin(); it != icons.end(); ++it, ++i)

View File

@ -24,23 +24,15 @@
#include "GxsIdTreeWidgetItem.h"
#include "GxsIdDetails.h"
#include "rshare.h"
#include <retroshare/rspeers.h>
#include <iostream>
#define MAX_ATTEMPTS 5
/** Constructor */
GxsIdRSTreeWidgetItem::GxsIdRSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, QTreeWidget *parent)
: QObject(NULL), RSTreeWidgetItem(compareRole, parent), mCount(0), mColumn(0)
: QObject(NULL), RSTreeWidgetItem(compareRole, parent), mColumn(0)
{
init();
}
GxsIdRSTreeWidgetItem::GxsIdRSTreeWidgetItem(const RSTreeWidgetItemCompareRole *compareRole, QTreeWidgetItem *parent)
: QObject(NULL), RSTreeWidgetItem(compareRole, parent), mCount(0), mColumn(0)
: QObject(NULL), RSTreeWidgetItem(compareRole, parent), mColumn(0)
{
init();
}
@ -49,6 +41,44 @@ void GxsIdRSTreeWidgetItem::init()
{
}
static void fillGxsIdRSTreeWidgetItemCallback(GxsIdDetailsType type, const RsIdentityDetails &details, QObject *object, const QVariant &/*data*/)
{
GxsIdRSTreeWidgetItem *item = dynamic_cast<GxsIdRSTreeWidgetItem*>(object);
if (!item) {
return;
}
QString toolTip;
QList<QIcon> icons;
switch (type) {
case GXS_ID_DETAILS_TYPE_EMPTY:
case GXS_ID_DETAILS_TYPE_FAILED:
break;
case GXS_ID_DETAILS_TYPE_LOADING:
icons.push_back(GxsIdDetails::getLoadingIcon(details.mId));
break;
case GXS_ID_DETAILS_TYPE_DONE:
toolTip = GxsIdDetails::getComment(details);
GxsIdDetails::getIcons(details, icons);
break;
}
int column = item->idColumn();
item->setText(column, GxsIdDetails::getNameForType(type, details));
item->setToolTip(column, toolTip);
item->setData(column, Qt::UserRole, QString::fromStdString(details.mId.toStdString()));
QIcon combinedIcon;
if (!icons.empty()) {
GxsIdDetails::GenerateCombinedIcon(combinedIcon, icons);
}
item->setIcon(column, combinedIcon);
}
void GxsIdRSTreeWidgetItem::setId(const RsGxsId &id, int column)
{
//std::cerr << " GxsIdRSTreeWidgetItem::setId(" << id << "," << column << ")";
@ -56,14 +86,8 @@ void GxsIdRSTreeWidgetItem::setId(const RsGxsId &id, int column)
mId = id;
mColumn = column;
if (mId.isNull())
{
setText(mColumn, "No Signature");
}
else
{
loadId();
}
GxsIdDetails::process(mId, fillGxsIdRSTreeWidgetItemCallback, this);
}
bool GxsIdRSTreeWidgetItem::getId(RsGxsId &id)
@ -71,127 +95,3 @@ bool GxsIdRSTreeWidgetItem::getId(RsGxsId &id)
id = mId;
return true;
}
void GxsIdRSTreeWidgetItem::loadId()
{
disconnect(rApp, SIGNAL(secondTick()), this, SLOT(loadId()));
//std::cerr << " GxsIdRSTreeWidgetItem::loadId() Id: " << mId << ", mCount: " << mCount;
//std::cerr << std::endl;
mCount++;
/* try and get details - if not there ... set callback */
QString desc;
QString comment ;
std::list<QIcon> icons;
bool loaded = GxsIdDetails::MakeIdDesc(mId, true, desc, icons,comment);
QIcon combinedIcon;
if (!icons.empty())
{
GxsIdDetails::GenerateCombinedIcon(combinedIcon, icons);
setIcon(mColumn, combinedIcon);
}
setToolTip(mColumn,comment) ;
setText(mColumn, desc);
setData(mColumn,Qt::UserRole, QString::fromStdString(mId.toStdString()));
if (loaded)
{
// std::cerr << " GxsIdRSTreeWidgetItem::loadId() Loaded Okay";
//std::cerr << std::endl;
return;
}
if (mCount < MAX_ATTEMPTS)
{
//std::cerr << " GxsIdRSTreeWidgetItem::loadId() Starting Timer for re-try";
//std::cerr << std::endl;
/* timer event to try again */
connect(rApp, SIGNAL(secondTick()), this, SLOT(loadId()));
}
}
#if 0
/** Constructor */
GxsIdTreeWidgetItem::GxsIdTreeWidgetItem(QTreeWidget *parent)
: QObject(NULL), QTreeWidgetItem(parent), mCount(0), mColumn(0)
{
init();
}
GxsIdTreeWidgetItem::GxsIdTreeWidgetItem(QTreeWidgetItem *parent)
: QObject(NULL), QTreeWidgetItem(parent), mCount(0), mColumn(0)
{
init();
}
void GxsIdTreeWidgetItem::init()
{
}
void GxsIdTreeWidgetItem::setId(const RsGxsId &id, int column)
{
std::cerr << " GxsIdTreeWidgetItem::setId(" << id << "," << column << ")";
std::cerr << std::endl;
mId = id;
mColumn = column;
if (mId.isNull())
{
setText(mColumn, "No Signature");
}
else
{
loadId();
}
}
bool GxsIdTreeWidgetItem::getId(RsGxsId &id)
{
id = mId;
return true;
}
void GxsIdTreeWidgetItem::loadId()
{
disconnect(rApp, SIGNAL(secondTick()), this, SLOT(loadId()));
std::cerr << " GxsIdTreeWidgetItem::loadId() Id: " << mId << ", mCount: " << mCount;
std::cerr << std::endl;
mCount++;
/* try and get details - if not there ... set callback */
QString desc;
QString comment;
std::list<QIcon> icons;
bool loaded = GxsIdDetails::MakeIdDesc(mId, true, desc, icons,comment);
QIcon combinedIcon;
if (!icons.empty())
{
GxsIdDetails::GenerateCombinedIcon(combinedIcon, icons);
setIcon(mColumn, combinedIcon);
}
setText(mColumn, desc);
setToolTip(mColumn, comment);
if (loaded)
{
std::cerr << " GxsIdTreeWidgetItem::loadId() Loaded Okay";
std::cerr << std::endl;
return;
}
if (mCount < MAX_ATTEMPTS)
{
std::cerr << " GxsIdTreeWidgetItem::loadId() Starting Timer for re-try";
std::cerr << std::endl;
/* timer event to try again */
connect(rApp, SIGNAL(secondTick()), this, SLOT(loadId()));
}
}
#endif

View File

@ -34,7 +34,6 @@
* The tick signal to fill the id cannot be processed when the thread is finished.
***/
class GxsIdRSTreeWidgetItem : public QObject, public RSTreeWidgetItem
{
Q_OBJECT
@ -46,39 +45,13 @@ public:
void setId(const RsGxsId &id, int column);
bool getId(RsGxsId &id);
private slots:
void loadId();
int idColumn() { return mColumn; }
private:
void init();
RsGxsId mId;
int mCount;
int mColumn;
};
#if 0
class GxsIdTreeWidgetItem : public QObject, public QTreeWidgetItem
{
Q_OBJECT
public:
GxsIdTreeWidgetItem(QTreeWidget *parent = NULL);
GxsIdTreeWidgetItem(QTreeWidgetItem *parent);
void setId(const RsGxsId &id, int column);
bool getId(RsGxsId &id);
private slots:
void loadId();
private:
void init();
RsGxsId mId;
int mCount;
int mColumn;
};
#endif
#endif