diff --git a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp index 7bf571b07..47e2da3fc 100644 --- a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp +++ b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.cpp @@ -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; diff --git a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.ui b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.ui index 30f3b3a82..5562d340f 100644 --- a/retroshare-gui/src/gui/feeds/GxsForumMsgItem.ui +++ b/retroshare-gui/src/gui/feeds/GxsForumMsgItem.ui @@ -336,7 +336,7 @@ - + 75 @@ -461,7 +461,7 @@ - + 75 @@ -604,6 +604,11 @@
gui/common/AvatarWidget.h
1 + + GxsIdLabel + QLabel +
gui/gxs/GxsIdLabel.h
+
diff --git a/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp b/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp index 84f2a7d9f..4fafda71d 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdChooser.cpp @@ -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 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(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 ids; //rsIdentity->getOwnIds(ids); @@ -245,17 +213,7 @@ void GxsIdChooser::loadPrivateIds(uint32_t token) for(std::list::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 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) { diff --git a/retroshare-gui/src/gui/gxs/GxsIdChooser.h b/retroshare-gui/src/gui/gxs/GxsIdChooser.h index 8d416992d..b92d04129 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdChooser.h +++ b/retroshare-gui/src/gui/gxs/GxsIdChooser.h @@ -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 mPendingId; - QTimer *mTimer; - unsigned int mTimerCount; - TokenQueue *mIdQueue; RsGxsUpdateBroadcastBase *mBase; }; diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp index 867ee9c91..57a3310fb 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.cpp @@ -21,6 +21,11 @@ * */ +#include +#include +#include +#include + #include #include "GxsIdDetails.h" @@ -28,9 +33,6 @@ #include #include -#include -#include - /* 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::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::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::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 image_cache ; + static std::map image_cache ; - std::map::const_iterator it = image_cache.find(id) ; + std::map::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(id.toByteArray())[0] ; + uint64_t n = reinterpret_cast(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> 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> 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> 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 &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> 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 &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::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::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 &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::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 &icons) +bool GxsIdDetails::GenerateCombinedIcon(QIcon &outIcon, const QList &icons) { int count = icons.size(); QPixmap image(IconSize * count, IconSize); QPainter painter(&image); painter.fillRect(0, 0, IconSize * count, IconSize, Qt::transparent); - std::list::iterator it; + QList::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; } - diff --git a/retroshare-gui/src/gui/gxs/GxsIdDetails.h b/retroshare-gui/src/gui/gxs/GxsIdDetails.h index f1b2d7cbc..81666510b 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdDetails.h +++ b/retroshare-gui/src/gui/gxs/GxsIdDetails.h @@ -24,21 +24,96 @@ #ifndef _GXS_ID_DETAILS_H #define _GXS_ID_DETAILS_H +#include +#include +#include #include #include + #include -#include -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 &icons,QString& comment); +typedef void (*GxsIdDetailsCallbackFunction)(GxsIdDetailsType type, const RsIdentityDetails &details, QObject *object, const QVariant &data); - bool GenerateCombinedIcon(QIcon &outIcon, std::list &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 &icons, QString& comment); + + static QString getName(const RsIdentityDetails &details); + static QString getComment(const RsIdentityDetails &details); + static void getIcons(const RsIdentityDetails &details, QList &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 &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 mPendingData; + int mCheckTimerId; + + /* Thread safe */ + QMutex mMutex; +}; #endif diff --git a/retroshare-gui/src/gui/gxs/GxsIdLabel.cpp b/retroshare-gui/src/gui/gxs/GxsIdLabel.cpp index ee94909b0..cefd478ec 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdLabel.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdLabel.cpp @@ -24,34 +24,42 @@ #include "GxsIdLabel.h" #include "GxsIdDetails.h" -#include - -#include - -#include - /** 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(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 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(); - } -} - diff --git a/retroshare-gui/src/gui/gxs/GxsIdLabel.h b/retroshare-gui/src/gui/gxs/GxsIdLabel.h index 95b9ea9af..12a0376c9 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdLabel.h +++ b/retroshare-gui/src/gui/gxs/GxsIdLabel.h @@ -21,17 +21,15 @@ * */ - #ifndef _GXS_ID_LABEL_H #define _GXS_ID_LABEL_H -#include #include #include 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 - diff --git a/retroshare-gui/src/gui/gxs/GxsIdTreeWidget.cpp b/retroshare-gui/src/gui/gxs/GxsIdTreeWidget.cpp index 7728e6a23..38fc03bf3 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdTreeWidget.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdTreeWidget.cpp @@ -36,7 +36,7 @@ static void paintGxsId( QPainter * painter, { QString desc; QString comment; - std::list icons; + QList 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::iterator it; + QList::iterator it; const int IconSize = 15; int i = 0; for(it = icons.begin(); it != icons.end(); ++it, ++i) diff --git a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp index 2f8fad8a5..52998d836 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp +++ b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.cpp @@ -24,23 +24,15 @@ #include "GxsIdTreeWidgetItem.h" #include "GxsIdDetails.h" -#include "rshare.h" - -#include - -#include - -#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(object); + if (!item) { + return; + } + + QString toolTip; + QList 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 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 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 diff --git a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h index 652b2a852..4f9221645 100644 --- a/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h +++ b/retroshare-gui/src/gui/gxs/GxsIdTreeWidgetItem.h @@ -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