mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-11-29 11:56:37 -05:00
merged upstream/master
This commit is contained in:
commit
6419b03a2a
131 changed files with 6081 additions and 1473 deletions
|
|
@ -41,11 +41,11 @@ void AvatarDefs::getOwnAvatar(QPixmap &avatar, const QString& defaultImage)
|
|||
}
|
||||
|
||||
/* load image */
|
||||
avatar.loadFromData(data, size, "PNG") ;
|
||||
GxsIdDetails::loadPixmapFromData(data, size, avatar,GxsIdDetails::ORIGINAL) ;
|
||||
|
||||
free(data);
|
||||
}
|
||||
void AvatarDefs::getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, const QString& defaultImage)
|
||||
bool AvatarDefs::getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, const QString& defaultImage)
|
||||
{
|
||||
unsigned char *data = NULL;
|
||||
int size = 0;
|
||||
|
|
@ -54,15 +54,16 @@ void AvatarDefs::getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, cons
|
|||
rsMsgs->getAvatarData(RsPeerId(sslId), data, size);
|
||||
if (size == 0) {
|
||||
avatar = QPixmap(defaultImage);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* load image */
|
||||
avatar.loadFromData(data, size, "PNG") ;
|
||||
GxsIdDetails::loadPixmapFromData(data, size, avatar, GxsIdDetails::LARGE) ;
|
||||
|
||||
free(data);
|
||||
return true;
|
||||
}
|
||||
void AvatarDefs::getAvatarFromGxsId(const RsGxsId& gxsId, QPixmap &avatar, const QString& defaultImage)
|
||||
bool AvatarDefs::getAvatarFromGxsId(const RsGxsId& gxsId, QPixmap &avatar, const QString& defaultImage)
|
||||
{
|
||||
//int size = 0;
|
||||
|
||||
|
|
@ -72,16 +73,18 @@ void AvatarDefs::getAvatarFromGxsId(const RsGxsId& gxsId, QPixmap &avatar, const
|
|||
if(!rsIdentity->getIdDetails(gxsId, details))
|
||||
{
|
||||
avatar = QPixmap(defaultImage);
|
||||
return ;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* load image */
|
||||
|
||||
if(details.mAvatar.mSize == 0 || !avatar.loadFromData(details.mAvatar.mData, details.mAvatar.mSize, "PNG"))
|
||||
avatar = QPixmap::fromImage(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);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void AvatarDefs::getAvatarFromGpgId(const RsPgpId& gpgId, QPixmap &avatar, const QString& defaultImage)
|
||||
bool AvatarDefs::getAvatarFromGpgId(const RsPgpId& gpgId, QPixmap &avatar, const QString& defaultImage)
|
||||
{
|
||||
unsigned char *data = NULL;
|
||||
int size = 0;
|
||||
|
|
@ -105,11 +108,13 @@ void AvatarDefs::getAvatarFromGpgId(const RsPgpId& gpgId, QPixmap &avatar, const
|
|||
|
||||
if (size == 0) {
|
||||
avatar = QPixmap(defaultImage);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* load image */
|
||||
avatar.loadFromData(data, size, "PNG") ;
|
||||
GxsIdDetails::loadPixmapFromData(data, size, avatar);
|
||||
|
||||
free(data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ class AvatarDefs
|
|||
public:
|
||||
static void getOwnAvatar(QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
||||
|
||||
static void getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
||||
static void getAvatarFromGpgId(const RsPgpId & gpgId, QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
||||
static void getAvatarFromGxsId(const RsGxsId & gxsId, QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
||||
static bool getAvatarFromSslId(const RsPeerId& sslId, QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
||||
static bool getAvatarFromGpgId(const RsPgpId & gpgId, QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
||||
static bool getAvatarFromGxsId(const RsGxsId & gxsId, QPixmap &avatar, const QString& defaultImage = AVATAR_DEFAULT_IMAGE);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ AvatarDialog::AvatarDialog(QWidget *parent) :
|
|||
updateInterface();
|
||||
}
|
||||
|
||||
const int AvatarDialog::RS_AVATAR_DEFAULT_IMAGE_W = 64;
|
||||
const int AvatarDialog::RS_AVATAR_DEFAULT_IMAGE_H = 64;
|
||||
|
||||
AvatarDialog::~AvatarDialog()
|
||||
{
|
||||
delete(ui);
|
||||
|
|
@ -52,7 +55,7 @@ AvatarDialog::~AvatarDialog()
|
|||
|
||||
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())
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@ class AvatarDialog : public QDialog
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static const int RS_AVATAR_DEFAULT_IMAGE_W ;
|
||||
static const int RS_AVATAR_DEFAULT_IMAGE_H ;
|
||||
|
||||
AvatarDialog(QWidget *parent = 0);
|
||||
~AvatarDialog();
|
||||
|
||||
|
|
|
|||
|
|
@ -18,12 +18,15 @@
|
|||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#include <QBuffer>
|
||||
|
||||
#include <rshare.h>
|
||||
#include <retroshare/rsstatus.h>
|
||||
#include <retroshare/rspeers.h>
|
||||
#include <retroshare/rsmsgs.h>
|
||||
|
||||
#include "gui/notifyqt.h"
|
||||
#include "util/misc.h"
|
||||
#include "gui/common/AvatarDefs.h"
|
||||
#include "gui/common/AvatarDialog.h"
|
||||
|
||||
|
|
@ -85,19 +88,33 @@ void AvatarWidget::mouseReleaseEvent(QMouseEvent */*event*/)
|
|||
if (!mFlag.isOwnId) {
|
||||
return;
|
||||
}
|
||||
QPixmap img = misc::getOpenThumbnailedPicture(this, tr("Choose avatar"), AvatarDialog::RS_AVATAR_DEFAULT_IMAGE_W,AvatarDialog::RS_AVATAR_DEFAULT_IMAGE_H);
|
||||
|
||||
AvatarDialog dialog(this);
|
||||
if (img.isNull())
|
||||
return;
|
||||
|
||||
QPixmap avatar;
|
||||
AvatarDefs::getOwnAvatar(avatar, "");
|
||||
setPixmap(img);
|
||||
|
||||
dialog.setAvatar(avatar);
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
QByteArray newAvatar;
|
||||
dialog.getAvatar(newAvatar);
|
||||
QByteArray data;
|
||||
QBuffer buffer(&data);
|
||||
|
||||
rsMsgs->setOwnAvatarData((unsigned char *)(newAvatar.data()), newAvatar.size()) ; // last char 0 included.
|
||||
}
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
img.save(&buffer, "PNG"); // writes image into a in PNG format
|
||||
|
||||
rsMsgs->setOwnAvatarData((unsigned char *)(data.data()), data.size()) ; // last char 0 included.
|
||||
|
||||
// AvatarDialog dialog(this);
|
||||
//
|
||||
// QPixmap avatar;
|
||||
// AvatarDefs::getOwnAvatar(avatar, "");
|
||||
//
|
||||
// dialog.setAvatar(avatar);
|
||||
// if (dialog.exec() == QDialog::Accepted) {
|
||||
// QByteArray newAvatar;
|
||||
// dialog.getAvatar(newAvatar);
|
||||
//
|
||||
// rsMsgs->setOwnAvatarData((unsigned char *)(newAvatar.data()), newAvatar.size()) ; // last char 0 included.
|
||||
// }
|
||||
}
|
||||
|
||||
void AvatarWidget::setFrameType(FrameType type)
|
||||
|
|
|
|||
|
|
@ -21,23 +21,40 @@
|
|||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QGridLayout>
|
||||
#include <QHash>
|
||||
#include <QIcon>
|
||||
#include <QPushButton>
|
||||
#include <QTabWidget>
|
||||
#include <QWidget>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
|
||||
#include "Emoticons.h"
|
||||
#include "util/HandleRichText.h"
|
||||
#include "retroshare/rsinit.h"
|
||||
|
||||
#define ICONNAME "groupicon.png"
|
||||
|
||||
static QHash<QString, QPair<QVector<QString>, QHash<QString, QString> > > Smileys;
|
||||
static QVector<QString> grpOrdered;
|
||||
static QVector<QString > StickerGroups;
|
||||
static QStringList filters;
|
||||
static QHash<QString, QString> tooltipcache;
|
||||
|
||||
void Emoticons::load()
|
||||
{
|
||||
loadSmiley();
|
||||
filters << "*.png" << "*.jpg" << "*.gif";
|
||||
loadSticker(QString::fromStdString(RsAccounts::ConfigDirectory()) + "/stickers"); //under .retroshare, shared between users
|
||||
loadSticker(QString::fromStdString(RsAccounts::AccountDirectory()) + "/stickers"); //under account, unique for user
|
||||
loadSticker(QString::fromStdString(RsAccounts::systemDataDirectory()) + "/stickers"); //exe's folder, shipped with RS
|
||||
}
|
||||
|
||||
void Emoticons::loadSmiley()
|
||||
{
|
||||
QString sm_AllLines;
|
||||
bool internalFiles = true;
|
||||
|
|
@ -267,3 +284,184 @@ void Emoticons::showSmileyWidget(QWidget *parent, QWidget *button, const char *s
|
|||
smWidget->move(x, y) ;
|
||||
smWidget->show() ;
|
||||
}
|
||||
|
||||
void Emoticons::loadSticker(QString foldername)
|
||||
{
|
||||
QDir dir(foldername);
|
||||
if(!dir.exists()) return;
|
||||
|
||||
//If it contains at a least one png then add it as a group
|
||||
QStringList files = dir.entryList(filters, QDir::Files);
|
||||
if(files.count() > 0)
|
||||
StickerGroups.append(foldername);
|
||||
|
||||
//Check subfolders
|
||||
QFileInfoList subfolders = dir.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot);
|
||||
for(int i = 0; i<subfolders.length(); i++)
|
||||
loadSticker(subfolders[i].filePath());
|
||||
}
|
||||
|
||||
void Emoticons::showStickerWidget(QWidget *parent, QWidget *button, const char *slotAddMethod, bool above)
|
||||
{
|
||||
QWidget *smWidget = new QWidget(parent, Qt::Popup) ;
|
||||
smWidget->setAttribute(Qt::WA_DeleteOnClose) ;
|
||||
smWidget->setWindowTitle("Stickers") ;
|
||||
|
||||
if(StickerGroups.count() == 0) {
|
||||
QMessageBox::warning(parent, "Stickers", "No stickers installed");
|
||||
return;
|
||||
}
|
||||
bool bOnlyOneGroup = (StickerGroups.count() == 1);
|
||||
|
||||
QTabWidget *smTab = nullptr;
|
||||
if (! bOnlyOneGroup)
|
||||
{
|
||||
smTab = new QTabWidget(smWidget);
|
||||
QGridLayout *smGLayout = new QGridLayout(smWidget);
|
||||
smGLayout->setContentsMargins(0,0,0,0);
|
||||
smGLayout->addWidget(smTab);
|
||||
}
|
||||
|
||||
const int buttonWidth = QFontMetricsF(smWidget->font()).height()*5;
|
||||
const int buttonHeight = QFontMetricsF(smWidget->font()).height()*5;
|
||||
int maxRowCount = 0;
|
||||
int maxCountPerLine = 0;
|
||||
|
||||
QVectorIterator<QString> grp(StickerGroups);
|
||||
while(grp.hasNext())
|
||||
{
|
||||
QDir groupDir = QDir(grp.next());
|
||||
QString groupName = groupDir.dirName();
|
||||
groupDir.setNameFilters(filters);
|
||||
|
||||
QWidget *tabGrpWidget = nullptr;
|
||||
if (! bOnlyOneGroup)
|
||||
{
|
||||
//Lazy load tooltips for the current tab
|
||||
QObject::connect(smTab, &QTabWidget::currentChanged, [=](int index){
|
||||
QWidget* current = smTab->widget(index);
|
||||
loadToolTips(current);
|
||||
});
|
||||
|
||||
tabGrpWidget = new QWidget(smTab);
|
||||
|
||||
// (Cyril) Never use an absolute size. It needs to be scaled to the actual font size on the screen.
|
||||
//
|
||||
QFontMetricsF fm(parent->font()) ;
|
||||
smTab->setIconSize(QSize(28*fm.height()/14.0,28*fm.height()/14.0));
|
||||
smTab->setMinimumWidth(400);
|
||||
smTab->setTabPosition(QTabWidget::South);
|
||||
smTab->setStyleSheet("QTabBar::tab { height: 44px; width: 44px; }");
|
||||
|
||||
int index;
|
||||
if (groupDir.exists(ICONNAME)) //use groupicon.png if exists, else the first png as a group icon
|
||||
index = smTab->addTab( tabGrpWidget, QIcon(groupDir.absoluteFilePath(ICONNAME)), "");
|
||||
else
|
||||
index = smTab->addTab( tabGrpWidget, QIcon(groupDir.entryInfoList(QDir::Files)[0].canonicalFilePath()), "");
|
||||
smTab->setTabToolTip(index, groupName);
|
||||
} else {
|
||||
tabGrpWidget = smWidget;
|
||||
}
|
||||
|
||||
QGridLayout *tabGLayout = new QGridLayout(tabGrpWidget);
|
||||
tabGLayout->setContentsMargins(0,0,0,0);
|
||||
tabGLayout->setSpacing(0);
|
||||
|
||||
QFileInfoList group = groupDir.entryInfoList(QDir::Files, QDir::Name);
|
||||
int rowCount = (int)sqrt((double)group.size());
|
||||
int countPerLine = (group.size()/rowCount) + ((group.size() % rowCount) ? 1 : 0);
|
||||
maxRowCount = qMax(maxRowCount, rowCount);
|
||||
maxCountPerLine = qMax(maxCountPerLine, countPerLine);
|
||||
|
||||
int lin = 0;
|
||||
int col = 0;
|
||||
for(int i = 0; i < group.length(); ++i)
|
||||
{
|
||||
QFileInfo fi = group[i];
|
||||
if(fi.fileName().compare(ICONNAME, Qt::CaseInsensitive) == 0)
|
||||
continue;
|
||||
QPushButton *button = new QPushButton("", tabGrpWidget);
|
||||
button->setIconSize(QSize(buttonWidth, buttonHeight));
|
||||
button->setFixedSize(QSize(buttonWidth, buttonHeight));
|
||||
button->setIcon(QPixmap(fi.absoluteFilePath()));
|
||||
button->setToolTip(fi.fileName());
|
||||
button->setStatusTip(fi.absoluteFilePath());
|
||||
button->setStyleSheet("QPushButton:hover {border: 3px solid #0099cc; border-radius: 3px;}");
|
||||
button->setFlat(true);
|
||||
tabGLayout->addWidget(button,col,lin);
|
||||
++lin;
|
||||
if(lin >= countPerLine)
|
||||
{
|
||||
lin = 0;
|
||||
++col;
|
||||
}
|
||||
QObject::connect(button, SIGNAL(clicked()), parent, slotAddMethod);
|
||||
QObject::connect(button, SIGNAL(clicked()), smWidget, SLOT(close()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Load tooltips for the first page
|
||||
QWidget * firstpage;
|
||||
if(bOnlyOneGroup) {
|
||||
firstpage = smWidget;
|
||||
} else {
|
||||
firstpage = smTab->currentWidget();
|
||||
}
|
||||
loadToolTips(firstpage);
|
||||
|
||||
//Get left up pos of button
|
||||
QPoint butTopLeft = button->mapToGlobal(QPoint(0,0));
|
||||
//Get widget's size
|
||||
QSize sizeWidget = smWidget->sizeHint();
|
||||
//Get screen's size
|
||||
QSize sizeScreen = QApplication::desktop()->size();
|
||||
|
||||
//Calculate left distance to screen start
|
||||
int distToScreenLeft = butTopLeft.x();
|
||||
//Calculate right distance to screen end
|
||||
int distToRightScreen = sizeScreen.width() - (butTopLeft.x() + button->width());
|
||||
|
||||
//Calculate left position
|
||||
int x;
|
||||
if (distToScreenLeft >= distToRightScreen) //More distance in left than right in screen
|
||||
x = butTopLeft.x() - sizeWidget.width(); //Place widget on left of button
|
||||
else
|
||||
x = butTopLeft.x() + button->width(); //Place widget on right of button
|
||||
|
||||
//Calculate top position
|
||||
int y;
|
||||
if (above) //Widget must be above the button
|
||||
y = butTopLeft.y() + button->height() - sizeWidget.height();
|
||||
else
|
||||
y = butTopLeft.y() + button->height()/2 - sizeWidget.height()/2; //Centered on button height
|
||||
|
||||
if (y + sizeWidget.height() > sizeScreen.height()) //Widget will be too low
|
||||
y = sizeScreen.height() - sizeWidget.height(); //Place widget bottom at screen bottom
|
||||
|
||||
if (y < 0) //Widget will be too high
|
||||
y = 0; //Place widget top at screen top
|
||||
|
||||
smWidget->move(x, y);
|
||||
smWidget->show();
|
||||
}
|
||||
|
||||
void Emoticons::loadToolTips(QWidget *container)
|
||||
{
|
||||
QList<QPushButton *> children = container->findChildren<QPushButton *>();
|
||||
for(int i = 0; i < children.length(); ++i) {
|
||||
if(!children[i]->toolTip().contains('<')) {
|
||||
if(tooltipcache.contains(children[i]->statusTip())) {
|
||||
children[i]->setToolTip(tooltipcache[children[i]->statusTip()]);
|
||||
} else {
|
||||
QString tooltip;
|
||||
if(RsHtml::makeEmbeddedImage(children[i]->statusTip(), tooltip, 300*300)) {
|
||||
tooltipcache.insert(children[i]->statusTip(), tooltip);
|
||||
children[i]->setToolTip(tooltip);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,10 +28,14 @@ class Emoticons
|
|||
{
|
||||
public:
|
||||
static void load();
|
||||
static void loadSmiley();
|
||||
static void loadSticker(QString foldername);
|
||||
|
||||
static void showSmileyWidget(QWidget *parent, QWidget *button, const char *slotAddMethod, bool above);
|
||||
static void showStickerWidget(QWidget *parent, QWidget *button, const char *slotAddMethod, bool above);
|
||||
|
||||
// static void formatText(QString &text);
|
||||
private:
|
||||
static void loadToolTips(QWidget *container);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -126,8 +126,7 @@ FriendList::FriendList(QWidget *parent) :
|
|||
#ifdef RS_DIRECT_CHAT
|
||||
connect(ui->peerTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(chatfriend(QTreeWidgetItem *)));
|
||||
#else
|
||||
connect( ui->peerTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)),
|
||||
this, SLOT(expandItem(QTreeWidgetItem *)) );
|
||||
connect( ui->peerTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this, SLOT(expandItem(QTreeWidgetItem *)) );
|
||||
#endif
|
||||
|
||||
connect(NotifyQt::getInstance(), SIGNAL(groupsChanged(int)), this, SLOT(groupsChanged()));
|
||||
|
|
@ -553,275 +552,6 @@ static void getNameWidget(QTreeWidget *treeWidget, QTreeWidgetItem *item, Elided
|
|||
}
|
||||
}
|
||||
|
||||
struct PgpItemInfo
|
||||
{
|
||||
PgpItemInfo() : gpg_connected(false),gpg_online(false),gpg_hasPrivateChat(false),bestPeerState(0),bestRSState(0) {}
|
||||
|
||||
bool gpg_connected ;
|
||||
bool gpg_online ;
|
||||
bool gpg_hasPrivateChat ;
|
||||
int bestPeerState ;
|
||||
unsigned int bestRSState ;
|
||||
QString bestCustomStateString;// for gpg item
|
||||
std::list<RsPeerId> sslContacts;
|
||||
QDateTime bestLastContact;
|
||||
QString bestIP;
|
||||
QPixmap bestAvatar;
|
||||
};
|
||||
|
||||
void FriendList::manageProfileLocations(QTreeWidgetItem *gpgItem,const RsPgpId& gpg_id,PgpItemInfo& info)
|
||||
{
|
||||
std::vector<RsPeerId> privateChatIds;
|
||||
ChatUserNotify::getPeersWithWaitingChat(privateChatIds);
|
||||
|
||||
int columnCount = ui->peerTreeWidget->columnCount();
|
||||
|
||||
for (auto sslIt ( info.sslContacts.begin()); sslIt != info.sslContacts.end(); ++sslIt)
|
||||
{
|
||||
QTreeWidgetItem *sslItem = NULL;
|
||||
RsPeerId sslId = *sslIt;
|
||||
|
||||
// find the corresponding sslItem child item of the gpg item
|
||||
bool newChild = true;
|
||||
int childCount = gpgItem->childCount();
|
||||
for (int childIndex = 0; childIndex < childCount; ++childIndex) {
|
||||
// we assume, that only ssl items are child of the gpg item, so we don't need to test the type
|
||||
if (getRsId(gpgItem->child(childIndex)) == sslId.toStdString()) {
|
||||
sslItem = gpgItem->child(childIndex);
|
||||
newChild = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RsPeerDetails sslDetail;
|
||||
if (!rsPeers->getPeerDetails(sslId, sslDetail) || !rsPeers->isFriend(sslId)) {
|
||||
#ifdef FRIENDS_DEBUG
|
||||
std::cerr << "Removing widget from the view : id : " << sslId << std::endl;
|
||||
#endif
|
||||
// child has disappeared, remove it from the gpg_item
|
||||
if (sslItem) {
|
||||
gpgItem->removeChild(sslItem);
|
||||
delete(sslItem);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (newChild) {
|
||||
sslItem = new RSTreeWidgetItem(mCompareRole, TYPE_SSL); //set type to 1 for custom popup menu
|
||||
|
||||
#ifdef FRIENDS_DEBUG
|
||||
std::cerr << "FriendList::insertPeers() inserting sslItem." << std::endl;
|
||||
#endif
|
||||
|
||||
/* Add ssl child to the list. Add here, because for setHidden the item must be added */
|
||||
gpgItem->addChild(sslItem);
|
||||
|
||||
/* Sort data */
|
||||
for (int i = 0; i < columnCount; ++i) {
|
||||
sslItem->setData(i, ROLE_SORT_GROUP, 2);
|
||||
sslItem->setData(i, ROLE_SORT_STANDARD_GROUP, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* not displayed, used to find back the item */
|
||||
QString strID = QString::fromStdString(sslDetail.id.toStdString());
|
||||
sslItem->setData(COLUMN_DATA, ROLE_ID, strID);
|
||||
sslItem->setText(COLUMN_ID, strID);
|
||||
sslItem->setData(COLUMN_ID, ROLE_SORT_NAME, strID);
|
||||
sslItem->setData(COLUMN_ID, ROLE_FILTER, strID);
|
||||
|
||||
/* Custom state string */
|
||||
QString customStateString;
|
||||
if (sslDetail.state & RS_PEER_STATE_CONNECTED) {
|
||||
customStateString = QString::fromUtf8(rsMsgs->getCustomStateString(sslDetail.id).c_str());
|
||||
}
|
||||
|
||||
QPixmap sslAvatar;
|
||||
AvatarDefs::getAvatarFromSslId(RsPeerId(sslDetail.id.toStdString()), sslAvatar);
|
||||
|
||||
/* last contact */
|
||||
QDateTime sslLastContact = QDateTime::fromTime_t(sslDetail.lastConnect);
|
||||
sslItem->setData(COLUMN_LAST_CONTACT, Qt::DisplayRole, QVariant(sslLastContact));
|
||||
sslItem->setData(COLUMN_LAST_CONTACT, ROLE_SORT_NAME, QVariant(sslLastContact));
|
||||
if (sslLastContact > info.bestLastContact) {
|
||||
info.bestLastContact = sslLastContact;
|
||||
}
|
||||
|
||||
/* IP */
|
||||
QString sslIP = (sslDetail.state & RS_PEER_STATE_CONNECTED) ? StatusDefs::connectStateIpString(sslDetail) : QString("---");
|
||||
sslItem->setText(COLUMN_IP, sslIP);
|
||||
sslItem->setData(COLUMN_IP, ROLE_SORT_NAME, sslIP);
|
||||
|
||||
/* change color and icon */
|
||||
QPixmap sslOverlayIcon;
|
||||
QFont sslFont;
|
||||
QColor sslColor;
|
||||
int peerState = 0;
|
||||
QString connectStateString;
|
||||
if (sslDetail.state & RS_PEER_STATE_CONNECTED)
|
||||
{
|
||||
// get the status info for this ssl id
|
||||
int rsState = 0;
|
||||
|
||||
StatusInfo status_info ;
|
||||
rsStatus->getStatus(sslDetail.id,status_info);
|
||||
|
||||
rsState = status_info.status;
|
||||
switch (rsState) {
|
||||
case RS_STATUS_INACTIVE:
|
||||
peerState = PEER_STATE_INACTIVE;
|
||||
break;
|
||||
|
||||
case RS_STATUS_ONLINE:
|
||||
peerState = PEER_STATE_ONLINE;
|
||||
break;
|
||||
|
||||
case RS_STATUS_AWAY:
|
||||
peerState = PEER_STATE_AWAY;
|
||||
break;
|
||||
|
||||
case RS_STATUS_BUSY:
|
||||
peerState = PEER_STATE_BUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
/* find the best ssl contact for the gpg item */
|
||||
if (info.bestPeerState == 0 || peerState < info.bestPeerState) {
|
||||
/* first ssl contact or higher state */
|
||||
info.bestPeerState = peerState;
|
||||
info.bestRSState = rsState;
|
||||
info.bestCustomStateString = customStateString;
|
||||
info.bestIP = sslIP;
|
||||
if (!sslAvatar.isNull()) {
|
||||
info.bestAvatar = sslAvatar;
|
||||
}
|
||||
} else if (peerState == info.bestPeerState) {
|
||||
/* equal state */
|
||||
if (info.bestCustomStateString.isEmpty() && !customStateString.isEmpty()) {
|
||||
/* when customStateString is shown in name item, use sslId with customStateString.
|
||||
second with a custom state string ... use second */
|
||||
info.bestPeerState = peerState;
|
||||
info.bestRSState = rsState;
|
||||
info.bestCustomStateString = customStateString;
|
||||
}
|
||||
if (info.bestAvatar.isNull() && !sslAvatar.isNull()) {
|
||||
/* Use available avatar */
|
||||
info.bestAvatar = sslAvatar;
|
||||
}
|
||||
}
|
||||
|
||||
sslItem->setHidden(false);
|
||||
info.gpg_connected = true;
|
||||
|
||||
sslOverlayIcon = QPixmap(StatusDefs::imageStatus(info.bestRSState));
|
||||
|
||||
connectStateString = StatusDefs::name(rsState);
|
||||
|
||||
if (rsState == 0) {
|
||||
sslFont.setBold(true);
|
||||
sslColor = mTextColorStatus[RS_STATUS_ONLINE];
|
||||
} else {
|
||||
sslFont = StatusDefs::font(rsState);
|
||||
sslColor = mTextColorStatus[rsState];
|
||||
}
|
||||
} else if (sslDetail.state & RS_PEER_STATE_ONLINE) {
|
||||
sslItem->setHidden(mHideUnconnected);
|
||||
info.gpg_online = true;
|
||||
peerState = PEER_STATE_AVAILABLE;
|
||||
|
||||
if (sslDetail.connectState) {
|
||||
sslOverlayIcon = QPixmap(":/images/connect_creating.png");
|
||||
} else {
|
||||
sslOverlayIcon = QPixmap(StatusDefs::imageStatus(RS_STATUS_ONLINE));
|
||||
}
|
||||
|
||||
connectStateString = StatusDefs::name(RS_STATUS_ONLINE);
|
||||
|
||||
sslFont.setBold(true);
|
||||
sslColor = mTextColorStatus[RS_STATUS_ONLINE];
|
||||
} else {
|
||||
peerState = PEER_STATE_OFFLINE;
|
||||
sslItem->setHidden(mHideUnconnected);
|
||||
if (sslDetail.connectState) {
|
||||
sslOverlayIcon = QPixmap(":/images/connect_creating.png");
|
||||
} else {
|
||||
sslOverlayIcon = QPixmap(StatusDefs::imageStatus(RS_STATUS_OFFLINE));
|
||||
}
|
||||
|
||||
connectStateString = StatusDefs::connectStateWithoutTransportTypeString(sslDetail);
|
||||
|
||||
sslFont.setBold(false);
|
||||
sslColor = mTextColorStatus[RS_STATUS_OFFLINE];
|
||||
}
|
||||
|
||||
/* Location */
|
||||
QString sslName = QString::fromUtf8(sslDetail.location.c_str());
|
||||
QString sslText;
|
||||
|
||||
if (mShowState) {
|
||||
if (!connectStateString.isEmpty()) {
|
||||
sslText = connectStateString;
|
||||
if (!customStateString.isEmpty()) {
|
||||
sslText += " [" + customStateString + "]";
|
||||
}
|
||||
} else {
|
||||
if (!customStateString.isEmpty()) {
|
||||
sslText = customStateString;
|
||||
}
|
||||
}
|
||||
|
||||
sslItem->setToolTip(COLUMN_NAME, "");
|
||||
} else {
|
||||
if (!customStateString.isEmpty()) {
|
||||
sslText = customStateString;
|
||||
}
|
||||
|
||||
/* Show the state as tooltip */
|
||||
sslItem->setToolTip(COLUMN_NAME, connectStateString);
|
||||
}
|
||||
|
||||
/* Create or get ssl label */
|
||||
ElidedLabel *sslNameLabel = NULL;
|
||||
ElidedLabel *sslTextLabel = NULL;
|
||||
|
||||
getNameWidget(ui->peerTreeWidget, sslItem, sslNameLabel, sslTextLabel);
|
||||
|
||||
if (sslNameLabel) {
|
||||
sslNameLabel->setText(sslName);
|
||||
sslNameLabel->setFont(sslFont);
|
||||
|
||||
QPalette palette = sslNameLabel->palette();
|
||||
palette.setColor(sslNameLabel->foregroundRole(), sslColor);
|
||||
|
||||
sslNameLabel->setPalette(palette);
|
||||
}
|
||||
if (sslTextLabel) {
|
||||
sslTextLabel->setText(sslText);
|
||||
sslTextLabel->setVisible(!sslText.isEmpty());
|
||||
}
|
||||
|
||||
// Filter
|
||||
sslItem->setData(COLUMN_NAME, ROLE_FILTER, sslName);
|
||||
|
||||
if (std::find(privateChatIds.begin(), privateChatIds.end(), sslDetail.id) != privateChatIds.end()) {
|
||||
// private chat is available
|
||||
sslOverlayIcon = QPixmap(":/images/chat.png");
|
||||
info.gpg_hasPrivateChat = true;
|
||||
}
|
||||
sslItem->setIcon(COLUMN_NAME, createAvatar(sslAvatar, sslOverlayIcon));
|
||||
|
||||
/* Sort data */
|
||||
sslItem->setData(COLUMN_NAME, ROLE_SORT_NAME, sslName);
|
||||
|
||||
for (int i = 0; i < columnCount; ++i) {
|
||||
sslItem->setData(i, ROLE_SORT_STATE, peerState);
|
||||
|
||||
sslItem->setTextColor(i, sslColor);
|
||||
sslItem->setFont(i, sslFont);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of peers from the RsIface.
|
||||
* Adds all friend gpg ids, with their nodes as children to the peerTreeWidget.
|
||||
|
|
@ -839,8 +569,8 @@ void FriendList::insertPeers()
|
|||
|
||||
int columnCount = ui->peerTreeWidget->columnCount();
|
||||
|
||||
//std::list<StatusInfo> statusInfo;
|
||||
//rsStatus->getStatusList(statusInfo);
|
||||
std::list<StatusInfo> statusInfo;
|
||||
rsStatus->getStatusList(statusInfo);
|
||||
|
||||
if (!rsPeers) {
|
||||
/* not ready yet! */
|
||||
|
|
@ -849,6 +579,9 @@ void FriendList::insertPeers()
|
|||
}
|
||||
|
||||
// get peers with waiting incoming chats
|
||||
std::vector<RsPeerId> privateChatIds;
|
||||
ChatUserNotify::getPeersWithWaitingChat(privateChatIds);
|
||||
|
||||
// get existing groups
|
||||
std::list<RsGroupInfo> groupInfoList;
|
||||
std::list<RsGroupInfo>::iterator groupIt;
|
||||
|
|
@ -858,8 +591,7 @@ void FriendList::insertPeers()
|
|||
std::list<RsPgpId>::iterator gpgIt;
|
||||
rsPeers->getGPGAcceptedList(gpgFriends);
|
||||
|
||||
// add own gpg id, if we have more than on node (ssl client)
|
||||
|
||||
//add own gpg id, if we have more than on node (ssl client)
|
||||
std::list<RsPeerId> ownSslContacts;
|
||||
RsPgpId ownId = rsPeers->getGPGOwnId();
|
||||
rsPeers->getAssociatedSSLIds(ownId, ownSslContacts);
|
||||
|
|
@ -867,24 +599,6 @@ void FriendList::insertPeers()
|
|||
gpgFriends.push_back(ownId);
|
||||
}
|
||||
|
||||
// Also add SSL peers which PGP key is not available yet.
|
||||
|
||||
std::list<RsPeerId> ssl_friends ;
|
||||
rsPeers->getFriendList(ssl_friends);
|
||||
std::map<RsPgpId,std::list<RsPeerDetails> > pgp_friends_without_validation;
|
||||
|
||||
std::cerr << "List of accepted ssl peers: " << std::endl;
|
||||
for(auto it(ssl_friends.begin());it!=ssl_friends.end();++it)
|
||||
{
|
||||
RsPeerDetails pd;
|
||||
if(rsPeers->getPeerDetails(*it,pd) && pd.skip_signature_validation)
|
||||
{
|
||||
std::cerr << " adding " << *it << " - " << pd.gpg_id << std::endl;
|
||||
gpgFriends.push_back(pd.gpg_id);
|
||||
pgp_friends_without_validation[pd.gpg_id].push_back(pd);
|
||||
}
|
||||
}
|
||||
|
||||
/* get a link to the table */
|
||||
QTreeWidget *peerTreeWidget = ui->peerTreeWidget;
|
||||
|
||||
|
|
@ -1086,8 +800,7 @@ void FriendList::insertPeers()
|
|||
}
|
||||
|
||||
RsPeerDetails detail;
|
||||
if (pgp_friends_without_validation.find(gpgId) == pgp_friends_without_validation.end() &&
|
||||
(!rsPeers->getGPGDetails(gpgId, detail) || !detail.accept_connection) && detail.gpg_id != ownId) {
|
||||
if ((!rsPeers->getGPGDetails(gpgId, detail) || !detail.accept_connection) && detail.gpg_id != ownId) {
|
||||
// don't accept anymore connection, remove from the view
|
||||
if (gpgItem) {
|
||||
if (groupItem) {
|
||||
|
|
@ -1096,13 +809,10 @@ void FriendList::insertPeers()
|
|||
delete (peerTreeWidget->takeTopLevelItem(peerTreeWidget->indexOfTopLevelItem(gpgItem)));
|
||||
}
|
||||
}
|
||||
|
||||
// We still want to add the item if it is unvalidated, in which case getGPGDetails returns false.
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (gpgItem == NULL)
|
||||
{
|
||||
if (gpgItem == NULL) {
|
||||
// create gpg item and add it to tree
|
||||
gpgItem = new RSTreeWidgetItem(mCompareRole, TYPE_GPG); //set type to 0 for custom popup menu
|
||||
|
||||
|
|
@ -1117,7 +827,7 @@ void FriendList::insertPeers()
|
|||
gpgItem->setTextAlignment(COLUMN_NAME, Qt::AlignLeft | Qt::AlignVCenter);
|
||||
|
||||
/* not displayed, used to find back the item */
|
||||
QString strID = QString::fromStdString(gpgId.toStdString());
|
||||
QString strID = QString::fromStdString(detail.gpg_id.toStdString());
|
||||
gpgItem->setData(COLUMN_DATA, ROLE_ID, strID);
|
||||
gpgItem->setText(COLUMN_ID, strID);
|
||||
gpgItem->setData(COLUMN_ID, ROLE_SORT_NAME, strID);
|
||||
|
|
@ -1147,22 +857,263 @@ void FriendList::insertPeers()
|
|||
}
|
||||
|
||||
// update the childs (ssl certs)
|
||||
bool gpg_connected = false;
|
||||
bool gpg_online = false;
|
||||
bool gpg_hasPrivateChat = false;
|
||||
int bestPeerState = 0; // for gpg item
|
||||
unsigned int bestRSState = 0; // for gpg item
|
||||
QString bestCustomStateString;// for gpg item
|
||||
std::list<RsPeerId> sslContacts;
|
||||
QDateTime bestLastContact;
|
||||
QString bestIP;
|
||||
QPixmap bestAvatar;
|
||||
|
||||
PgpItemInfo info;
|
||||
rsPeers->getAssociatedSSLIds(detail.gpg_id, sslContacts);
|
||||
for (std::list<RsPeerId>::iterator sslIt = sslContacts.begin(); sslIt != sslContacts.end(); ++sslIt) {
|
||||
QTreeWidgetItem *sslItem = NULL;
|
||||
RsPeerId sslId = *sslIt;
|
||||
|
||||
auto itt = pgp_friends_without_validation.find(gpgId);
|
||||
if(itt != pgp_friends_without_validation.end())
|
||||
{
|
||||
info.sslContacts.clear();
|
||||
for(auto itt2(itt->second.begin());itt2!=itt->second.end();++itt2)
|
||||
info.sslContacts.push_back(itt2->id);
|
||||
// find the corresponding sslItem child item of the gpg item
|
||||
bool newChild = true;
|
||||
childCount = gpgItem->childCount();
|
||||
for (int childIndex = 0; childIndex < childCount; ++childIndex) {
|
||||
// we assume, that only ssl items are child of the gpg item, so we don't need to test the type
|
||||
if (getRsId(gpgItem->child(childIndex)) == sslId.toStdString()) {
|
||||
sslItem = gpgItem->child(childIndex);
|
||||
newChild = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
detail.name = gpgId.toStdString() + tr(" (Unverified yet)").toStdString();
|
||||
RsPeerDetails sslDetail;
|
||||
if (!rsPeers->getPeerDetails(sslId, sslDetail) || !rsPeers->isFriend(sslId)) {
|
||||
#ifdef FRIENDS_DEBUG
|
||||
std::cerr << "Removing widget from the view : id : " << sslId << std::endl;
|
||||
#endif
|
||||
// child has disappeared, remove it from the gpg_item
|
||||
if (sslItem) {
|
||||
gpgItem->removeChild(sslItem);
|
||||
delete(sslItem);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (newChild) {
|
||||
sslItem = new RSTreeWidgetItem(mCompareRole, TYPE_SSL); //set type to 1 for custom popup menu
|
||||
|
||||
#ifdef FRIENDS_DEBUG
|
||||
std::cerr << "FriendList::insertPeers() inserting sslItem." << std::endl;
|
||||
#endif
|
||||
|
||||
/* Add ssl child to the list. Add here, because for setHidden the item must be added */
|
||||
gpgItem->addChild(sslItem);
|
||||
|
||||
/* Sort data */
|
||||
for (int i = 0; i < columnCount; ++i) {
|
||||
sslItem->setData(i, ROLE_SORT_GROUP, 2);
|
||||
sslItem->setData(i, ROLE_SORT_STANDARD_GROUP, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* not displayed, used to find back the item */
|
||||
QString strID = QString::fromStdString(sslDetail.id.toStdString());
|
||||
sslItem->setData(COLUMN_DATA, ROLE_ID, strID);
|
||||
sslItem->setText(COLUMN_ID, strID);
|
||||
sslItem->setData(COLUMN_ID, ROLE_SORT_NAME, strID);
|
||||
sslItem->setData(COLUMN_ID, ROLE_FILTER, strID);
|
||||
|
||||
/* Custom state string */
|
||||
QString customStateString;
|
||||
if (sslDetail.state & RS_PEER_STATE_CONNECTED) {
|
||||
customStateString = QString::fromUtf8(rsMsgs->getCustomStateString(sslDetail.id).c_str());
|
||||
}
|
||||
|
||||
QPixmap sslAvatar;
|
||||
AvatarDefs::getAvatarFromSslId(RsPeerId(sslDetail.id.toStdString()), sslAvatar);
|
||||
|
||||
/* last contact */
|
||||
QDateTime sslLastContact = QDateTime::fromTime_t(sslDetail.lastConnect);
|
||||
sslItem->setData(COLUMN_LAST_CONTACT, Qt::DisplayRole, QVariant(sslLastContact));
|
||||
sslItem->setData(COLUMN_LAST_CONTACT, ROLE_SORT_NAME, QVariant(sslLastContact));
|
||||
if (sslLastContact > bestLastContact) {
|
||||
bestLastContact = sslLastContact;
|
||||
}
|
||||
|
||||
/* IP */
|
||||
QString sslIP = (sslDetail.state & RS_PEER_STATE_CONNECTED) ? StatusDefs::connectStateIpString(sslDetail) : QString("---");
|
||||
sslItem->setText(COLUMN_IP, sslIP);
|
||||
sslItem->setData(COLUMN_IP, ROLE_SORT_NAME, sslIP);
|
||||
|
||||
/* change color and icon */
|
||||
QPixmap sslOverlayIcon;
|
||||
QFont sslFont;
|
||||
QColor sslColor;
|
||||
int peerState = 0;
|
||||
QString connectStateString;
|
||||
if (sslDetail.state & RS_PEER_STATE_CONNECTED) {
|
||||
// get the status info for this ssl id
|
||||
int rsState = 0;
|
||||
std::list<StatusInfo>::iterator it;
|
||||
for (it = statusInfo.begin(); it != statusInfo.end(); ++it) {
|
||||
if (it->id == sslId) {
|
||||
rsState = it->status;
|
||||
switch (rsState) {
|
||||
case RS_STATUS_INACTIVE:
|
||||
peerState = PEER_STATE_INACTIVE;
|
||||
break;
|
||||
|
||||
case RS_STATUS_ONLINE:
|
||||
peerState = PEER_STATE_ONLINE;
|
||||
break;
|
||||
|
||||
case RS_STATUS_AWAY:
|
||||
peerState = PEER_STATE_AWAY;
|
||||
break;
|
||||
|
||||
case RS_STATUS_BUSY:
|
||||
peerState = PEER_STATE_BUSY;
|
||||
break;
|
||||
}
|
||||
|
||||
/* find the best ssl contact for the gpg item */
|
||||
if (bestPeerState == 0 || peerState < bestPeerState) {
|
||||
/* first ssl contact or higher state */
|
||||
bestPeerState = peerState;
|
||||
bestRSState = rsState;
|
||||
bestCustomStateString = customStateString;
|
||||
bestIP = sslIP;
|
||||
if (!sslAvatar.isNull()) {
|
||||
bestAvatar = sslAvatar;
|
||||
}
|
||||
} else if (peerState == bestPeerState) {
|
||||
/* equal state */
|
||||
if (bestCustomStateString.isEmpty() && !customStateString.isEmpty()) {
|
||||
/* when customStateString is shown in name item, use sslId with customStateString.
|
||||
second with a custom state string ... use second */
|
||||
bestPeerState = peerState;
|
||||
bestRSState = rsState;
|
||||
bestCustomStateString = customStateString;
|
||||
}
|
||||
if (bestAvatar.isNull() && !sslAvatar.isNull()) {
|
||||
/* Use available avatar */
|
||||
bestAvatar = sslAvatar;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sslItem->setHidden(false);
|
||||
gpg_connected = true;
|
||||
|
||||
sslOverlayIcon = QPixmap(StatusDefs::imageStatus(bestRSState));
|
||||
|
||||
connectStateString = StatusDefs::name(rsState);
|
||||
|
||||
if (rsState == 0) {
|
||||
sslFont.setBold(true);
|
||||
sslColor = mTextColorStatus[RS_STATUS_ONLINE];
|
||||
|
||||
} else {
|
||||
sslFont = StatusDefs::font(rsState);
|
||||
sslColor = mTextColorStatus[rsState];
|
||||
}
|
||||
} else if (sslDetail.state & RS_PEER_STATE_ONLINE) {
|
||||
sslItem->setHidden(mHideUnconnected);
|
||||
gpg_online = true;
|
||||
peerState = PEER_STATE_AVAILABLE;
|
||||
|
||||
if (sslDetail.connectState) {
|
||||
sslOverlayIcon = QPixmap(":/images/connect_creating.png");
|
||||
} else {
|
||||
sslOverlayIcon = QPixmap(StatusDefs::imageStatus(RS_STATUS_ONLINE));
|
||||
}
|
||||
|
||||
connectStateString = StatusDefs::name(RS_STATUS_ONLINE);
|
||||
|
||||
sslFont.setBold(true);
|
||||
sslColor = mTextColorStatus[RS_STATUS_ONLINE];
|
||||
} else {
|
||||
peerState = PEER_STATE_OFFLINE;
|
||||
sslItem->setHidden(mHideUnconnected);
|
||||
if (sslDetail.connectState) {
|
||||
sslOverlayIcon = QPixmap(":/images/connect_creating.png");
|
||||
} else {
|
||||
sslOverlayIcon = QPixmap(StatusDefs::imageStatus(RS_STATUS_OFFLINE));
|
||||
}
|
||||
|
||||
connectStateString = StatusDefs::connectStateWithoutTransportTypeString(sslDetail);
|
||||
|
||||
sslFont.setBold(false);
|
||||
sslColor = mTextColorStatus[RS_STATUS_OFFLINE];
|
||||
}
|
||||
|
||||
/* Location */
|
||||
QString sslName = QString::fromUtf8(sslDetail.location.c_str());
|
||||
QString sslText;
|
||||
|
||||
if (mShowState) {
|
||||
if (!connectStateString.isEmpty()) {
|
||||
sslText = connectStateString;
|
||||
if (!customStateString.isEmpty()) {
|
||||
sslText += " [" + customStateString + "]";
|
||||
}
|
||||
} else {
|
||||
if (!customStateString.isEmpty()) {
|
||||
sslText = customStateString;
|
||||
}
|
||||
}
|
||||
|
||||
sslItem->setToolTip(COLUMN_NAME, "");
|
||||
} else {
|
||||
if (!customStateString.isEmpty()) {
|
||||
sslText = customStateString;
|
||||
}
|
||||
|
||||
/* Show the state as tooltip */
|
||||
sslItem->setToolTip(COLUMN_NAME, connectStateString);
|
||||
}
|
||||
|
||||
/* Create or get ssl label */
|
||||
ElidedLabel *sslNameLabel = NULL;
|
||||
ElidedLabel *sslTextLabel = NULL;
|
||||
|
||||
getNameWidget(ui->peerTreeWidget, sslItem, sslNameLabel, sslTextLabel);
|
||||
|
||||
if (sslNameLabel) {
|
||||
sslNameLabel->setText(sslName);
|
||||
sslNameLabel->setFont(sslFont);
|
||||
|
||||
QPalette palette = sslNameLabel->palette();
|
||||
palette.setColor(sslNameLabel->foregroundRole(), sslColor);
|
||||
|
||||
sslNameLabel->setPalette(palette);
|
||||
}
|
||||
if (sslTextLabel) {
|
||||
sslTextLabel->setText(sslText);
|
||||
sslTextLabel->setVisible(!sslText.isEmpty());
|
||||
}
|
||||
|
||||
// Filter
|
||||
sslItem->setData(COLUMN_NAME, ROLE_FILTER, sslName);
|
||||
|
||||
if (std::find(privateChatIds.begin(), privateChatIds.end(), sslDetail.id) != privateChatIds.end()) {
|
||||
// private chat is available
|
||||
sslOverlayIcon = QPixmap(":/images/chat.png");
|
||||
gpg_hasPrivateChat = true;
|
||||
}
|
||||
sslItem->setIcon(COLUMN_NAME, createAvatar(sslAvatar, sslOverlayIcon));
|
||||
|
||||
/* Sort data */
|
||||
sslItem->setData(COLUMN_NAME, ROLE_SORT_NAME, sslName);
|
||||
|
||||
for (int i = 0; i < columnCount; ++i) {
|
||||
sslItem->setData(i, ROLE_SORT_STATE, peerState);
|
||||
|
||||
sslItem->setTextColor(i, sslColor);
|
||||
sslItem->setFont(i, sslFont);
|
||||
}
|
||||
}
|
||||
else
|
||||
rsPeers->getAssociatedSSLIds(gpgId, info.sslContacts);
|
||||
|
||||
manageProfileLocations(gpgItem,gpgId,info);
|
||||
|
||||
QString gpgName = QString::fromUtf8(detail.name.c_str());
|
||||
QString gpgText;
|
||||
|
|
@ -1172,38 +1123,38 @@ void FriendList::insertPeers()
|
|||
bool showInfoAtGpgItem = !gpgItem->isExpanded();
|
||||
|
||||
QPixmap gpgOverlayIcon;
|
||||
if (info.gpg_connected) {
|
||||
if (gpg_connected) {
|
||||
gpgItem->setHidden(false);
|
||||
|
||||
++onlineCount;
|
||||
|
||||
if (info.bestPeerState == 0) {
|
||||
if (bestPeerState == 0) {
|
||||
// show as online
|
||||
info.bestPeerState = PEER_STATE_ONLINE;
|
||||
info.bestRSState = RS_STATUS_ONLINE;
|
||||
bestPeerState = PEER_STATE_ONLINE;
|
||||
bestRSState = RS_STATUS_ONLINE;
|
||||
}
|
||||
|
||||
gpgColor = mTextColorStatus[info.bestRSState];
|
||||
gpgFont = StatusDefs::font(info.bestRSState);
|
||||
gpgColor = mTextColorStatus[bestRSState];
|
||||
gpgFont = StatusDefs::font(bestRSState);
|
||||
|
||||
if (showInfoAtGpgItem) {
|
||||
gpgOverlayIcon = QPixmap(StatusDefs::imageStatus(info.bestRSState));
|
||||
gpgOverlayIcon = QPixmap(StatusDefs::imageStatus(bestRSState));
|
||||
|
||||
if (mShowState) {
|
||||
gpgText = StatusDefs::name(info.bestRSState);
|
||||
if (!info.bestCustomStateString.isEmpty()) {
|
||||
gpgText += " [" + info.bestCustomStateString + "]";
|
||||
gpgText = StatusDefs::name(bestRSState);
|
||||
if (!bestCustomStateString.isEmpty()) {
|
||||
gpgText += " [" + bestCustomStateString + "]";
|
||||
}
|
||||
} else {
|
||||
if (!info.bestCustomStateString.isEmpty()) {
|
||||
gpgText = info.bestCustomStateString;
|
||||
if (!bestCustomStateString.isEmpty()) {
|
||||
gpgText = bestCustomStateString;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (info.gpg_online) {
|
||||
} else if (gpg_online) {
|
||||
gpgItem->setHidden(mHideUnconnected);
|
||||
++onlineCount;
|
||||
info.bestPeerState = PEER_STATE_AVAILABLE;
|
||||
bestPeerState = PEER_STATE_AVAILABLE;
|
||||
|
||||
gpgFont.setBold(true);
|
||||
gpgColor = mTextColorStatus[RS_STATUS_ONLINE];
|
||||
|
|
@ -1216,7 +1167,7 @@ void FriendList::insertPeers()
|
|||
gpgOverlayIcon = QPixmap(IMAGE_AVAILABLE);
|
||||
}
|
||||
} else {
|
||||
info.bestPeerState = PEER_STATE_OFFLINE;
|
||||
bestPeerState = PEER_STATE_OFFLINE;
|
||||
gpgItem->setHidden(mHideUnconnected);
|
||||
|
||||
gpgFont = StatusDefs::font(RS_STATUS_OFFLINE);
|
||||
|
|
@ -1231,11 +1182,11 @@ void FriendList::insertPeers()
|
|||
}
|
||||
}
|
||||
|
||||
if (info.gpg_hasPrivateChat) {
|
||||
if (gpg_hasPrivateChat) {
|
||||
gpgOverlayIcon = QPixmap(":/images/chat.png");
|
||||
}
|
||||
|
||||
gpgItem->setIcon(COLUMN_NAME, createAvatar(info.bestAvatar.isNull() ? QPixmap(AVATAR_DEFAULT_IMAGE) : info.bestAvatar, gpgOverlayIcon));
|
||||
gpgItem->setIcon(COLUMN_NAME, createAvatar(bestAvatar.isNull() ? QPixmap(AVATAR_DEFAULT_IMAGE) : bestAvatar, gpgOverlayIcon));
|
||||
|
||||
/* Create or get gpg label */
|
||||
ElidedLabel *gpgNameLabel = NULL;
|
||||
|
|
@ -1260,16 +1211,16 @@ void FriendList::insertPeers()
|
|||
// Filter
|
||||
gpgItem->setData(COLUMN_NAME, ROLE_FILTER, gpgName);
|
||||
|
||||
gpgItem->setData(COLUMN_LAST_CONTACT, Qt::DisplayRole, showInfoAtGpgItem ? QVariant(info.bestLastContact) : "");
|
||||
gpgItem->setData(COLUMN_LAST_CONTACT, ROLE_SORT_NAME, QVariant(info.bestLastContact));
|
||||
gpgItem->setText(COLUMN_IP, showInfoAtGpgItem ? info.bestIP : "");
|
||||
gpgItem->setData(COLUMN_IP, ROLE_SORT_NAME, info.bestIP);
|
||||
gpgItem->setData(COLUMN_LAST_CONTACT, Qt::DisplayRole, showInfoAtGpgItem ? QVariant(bestLastContact) : "");
|
||||
gpgItem->setData(COLUMN_LAST_CONTACT, ROLE_SORT_NAME, QVariant(bestLastContact));
|
||||
gpgItem->setText(COLUMN_IP, showInfoAtGpgItem ? bestIP : "");
|
||||
gpgItem->setData(COLUMN_IP, ROLE_SORT_NAME, bestIP);
|
||||
|
||||
/* Sort data */
|
||||
gpgItem->setData(COLUMN_NAME, ROLE_SORT_NAME, gpgName);
|
||||
|
||||
for (int i = 0; i < columnCount; ++i) {
|
||||
gpgItem->setData(i, ROLE_SORT_STATE, info.bestPeerState);
|
||||
gpgItem->setData(i, ROLE_SORT_STATE, bestPeerState);
|
||||
|
||||
gpgItem->setTextColor(i, gpgColor);
|
||||
gpgItem->setFont(i, gpgFont);
|
||||
|
|
@ -2014,7 +1965,7 @@ bool FriendList::exportFriendlist(QString &fileName)
|
|||
/**
|
||||
* @brief helper function to show a message box
|
||||
*/
|
||||
void showXMLParsingError()
|
||||
static void showXMLParsingError()
|
||||
{
|
||||
// show error to user
|
||||
QMessageBox mbox;
|
||||
|
|
|
|||
1220
retroshare-gui/src/gui/common/FriendListModel.cpp
Normal file
1220
retroshare-gui/src/gui/common/FriendListModel.cpp
Normal file
File diff suppressed because it is too large
Load diff
235
retroshare-gui/src/gui/common/FriendListModel.h
Normal file
235
retroshare-gui/src/gui/common/FriendListModel.h
Normal file
|
|
@ -0,0 +1,235 @@
|
|||
/*******************************************************************************
|
||||
* retroshare-gui/src/gui/msgs/RsFriendListModel.h *
|
||||
* *
|
||||
* Copyright 2019 by Cyril Soler <csoler@users.sourceforge.net> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Affero General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Affero General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Affero General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QModelIndex>
|
||||
#include <QColor>
|
||||
|
||||
#include "retroshare/rsstatus.h"
|
||||
#include "retroshare/rsmsgs.h"
|
||||
#include "retroshare/rspeers.h"
|
||||
|
||||
typedef uint32_t ForumModelIndex;
|
||||
|
||||
// This class is the item model used by Qt to display the information
|
||||
|
||||
class RsFriendListModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RsFriendListModel(QObject *parent = NULL);
|
||||
~RsFriendListModel(){}
|
||||
|
||||
class RsNodeDetails: public RsPeerDetails {};// in the near future, there will be a specific class for Profile/Node details in replacement of RsPeerDetails
|
||||
class RsProfileDetails: public RsPeerDetails {};
|
||||
|
||||
struct HierarchicalGroupInformation
|
||||
{
|
||||
RsGroupInfo group_info;
|
||||
std::vector<uint32_t> child_profile_indices; // index in the array of hierarchical profiles
|
||||
};
|
||||
struct HierarchicalProfileInformation
|
||||
{
|
||||
RsProfileDetails profile_info;
|
||||
std::vector<uint32_t> child_node_indices; // indices of nodes in the array of nodes.
|
||||
};
|
||||
struct HierarchicalNodeInformation
|
||||
{
|
||||
HierarchicalNodeInformation() : last_update_ts(0) {}
|
||||
|
||||
rstime_t last_update_ts;
|
||||
RsNodeDetails node_info;
|
||||
};
|
||||
|
||||
enum Columns {
|
||||
COLUMN_THREAD_NAME = 0x00,
|
||||
COLUMN_THREAD_LAST_CONTACT = 0x01,
|
||||
COLUMN_THREAD_IP = 0x02,
|
||||
COLUMN_THREAD_ID = 0x03,
|
||||
COLUMN_THREAD_NB_COLUMNS = 0x04
|
||||
};
|
||||
|
||||
enum Roles{ SortRole = Qt::UserRole+1,
|
||||
StatusRole = Qt::UserRole+2,
|
||||
UnreadRole = Qt::UserRole+3,
|
||||
FilterRole = Qt::UserRole+4,
|
||||
OnlineRole = Qt::UserRole+5,
|
||||
TypeRole = Qt::UserRole+6
|
||||
};
|
||||
|
||||
enum FilterType{ FILTER_TYPE_NONE = 0x00,
|
||||
FILTER_TYPE_ID = 0x01,
|
||||
FILTER_TYPE_NAME = 0x02
|
||||
};
|
||||
|
||||
enum EntryType{ ENTRY_TYPE_UNKNOWN = 0x00,
|
||||
ENTRY_TYPE_GROUP = 0x01,
|
||||
ENTRY_TYPE_PROFILE = 0x02,
|
||||
ENTRY_TYPE_NODE = 0x03
|
||||
};
|
||||
|
||||
// This structure encodes the position of a node in the hierarchy. The type tells which of the index fields are valid.
|
||||
|
||||
struct EntryIndex
|
||||
{
|
||||
public:
|
||||
EntryIndex();
|
||||
|
||||
EntryType type; // type of the entry (group,profile,location)
|
||||
|
||||
// Indices w.r.t. parent. The set of indices entirely determines the position of the entry in the hierarchy.
|
||||
// An index of 0xff means "undefined"
|
||||
|
||||
uint16_t group_index; // index of the group in mGroups tab
|
||||
uint16_t profile_index; // index of the child profile in its own group if group_index < 0xff, or in the mProfiles tab otherwise.
|
||||
uint16_t node_index; // index of the child node in its own profile
|
||||
|
||||
EntryIndex parent() const;
|
||||
EntryIndex child(int row,const std::vector<EntryIndex>& top_level) const;
|
||||
uint32_t parentRow(uint32_t nb_groups) const;
|
||||
};
|
||||
|
||||
QModelIndex root() const{ return createIndex(0,0,(void*)NULL) ;}
|
||||
QModelIndex getIndexOfGroup(const RsNodeGroupId& mid) const;
|
||||
|
||||
static const QString FilterString ;
|
||||
|
||||
// This method will asynchroneously update the data
|
||||
|
||||
void setDisplayGroups(bool b);
|
||||
bool getDisplayGroups() const { return mDisplayGroups; }
|
||||
|
||||
void setDisplayStatusString(bool b);
|
||||
bool getDisplayStatusString() const { return mDisplayStatusString; }
|
||||
|
||||
EntryType getType(const QModelIndex&) const;
|
||||
|
||||
bool getGroupData (const QModelIndex&,RsGroupInfo &) const;
|
||||
bool getProfileData(const QModelIndex&,RsProfileDetails&) const;
|
||||
bool getNodeData (const QModelIndex&,RsNodeDetails &) const;
|
||||
|
||||
void setFilter(FilterType filter_type, const QStringList& strings) ;
|
||||
|
||||
void expandItem(const QModelIndex&) ;
|
||||
void collapseItem(const QModelIndex&) ;
|
||||
|
||||
// Overloaded methods from QAbstractItemModel
|
||||
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
QModelIndex index(int row, int column, const QModelIndex & parent = QModelIndex()) const override;
|
||||
QModelIndex parent(const QModelIndex& child) const override;
|
||||
Qt::ItemFlags flags(const QModelIndex& index) const override;
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
void clear() ;
|
||||
|
||||
/* Color definitions (for standard see qss.default) */
|
||||
QColor mTextColorGroup;
|
||||
QColor mTextColorStatus[RS_STATUS_COUNT];
|
||||
|
||||
private:
|
||||
const HierarchicalGroupInformation *getGroupInfo (const EntryIndex&) const;
|
||||
const HierarchicalProfileInformation *getProfileInfo(const EntryIndex&)const;
|
||||
const HierarchicalNodeInformation *getNodeInfo(const EntryIndex&) const;
|
||||
|
||||
bool isProfileExpanded(const EntryIndex& e) const;
|
||||
void checkNode(HierarchicalNodeInformation& node);
|
||||
bool getPeerOnlineStatus(const EntryIndex& e) const;
|
||||
std::map<RsPgpId,uint32_t>::const_iterator checkProfileIndex(const RsPgpId& pgp_id,
|
||||
std::map<RsPgpId,uint32_t>& pgp_indices,
|
||||
std::vector<HierarchicalProfileInformation>& mProfiles,
|
||||
bool create);
|
||||
|
||||
QVariant sizeHintRole (const EntryIndex& e, int col) const;
|
||||
QVariant displayRole (const EntryIndex& e, int col) const;
|
||||
QVariant decorationRole(const EntryIndex& e, int col) const;
|
||||
QVariant toolTipRole (const EntryIndex& e, int col) const;
|
||||
QVariant statusRole (const EntryIndex& e, int col) const;
|
||||
QVariant sortRole (const EntryIndex& e, int col) const;
|
||||
QVariant fontRole (const EntryIndex& e, int col) const;
|
||||
QVariant textColorRole (const EntryIndex& e, int col) const;
|
||||
QVariant onlineRole (const EntryIndex& e, int col) const;
|
||||
QVariant filterRole (const EntryIndex& e, int col) const;
|
||||
|
||||
/*!
|
||||
* \brief debug_dump
|
||||
* Dumps the hierarchy of posts in the terminal, to allow checking whether the internal representation is correct.
|
||||
*/
|
||||
|
||||
public slots:
|
||||
void checkInternalData(bool force);
|
||||
void debug_dump() const;
|
||||
|
||||
signals:
|
||||
void dataLoaded(); // emitted after the messages have been set. Can be used to updated the UI.
|
||||
void friendListChanged(); // emitted after the messages have been set. Can be used to updated the UI.
|
||||
void dataAboutToLoad();
|
||||
|
||||
private:
|
||||
void updateInternalData();
|
||||
bool passesFilter(const EntryIndex &e, int column) const;
|
||||
|
||||
void preMods() ;
|
||||
void postMods() ;
|
||||
|
||||
void *getParentRef(void *ref,int& row) const;
|
||||
void *getChildRef(void *ref,int row) const;
|
||||
int getChildrenCount(void *ref) const;
|
||||
|
||||
template<uint8_t> static bool convertIndexToInternalId(const EntryIndex& e,quintptr& ref);
|
||||
template<uint8_t> static bool convertInternalIdToIndex(quintptr ref, EntryIndex& e);
|
||||
|
||||
uint32_t updateFilterStatus(ForumModelIndex i,int column,const QStringList& strings);
|
||||
|
||||
QStringList mFilterStrings;
|
||||
FilterType mFilterType;
|
||||
|
||||
bool mDisplayGroups ;
|
||||
bool mDisplayStatusString ;
|
||||
rstime_t mLastInternalDataUpdate;
|
||||
rstime_t mLastNodeUpdate;;
|
||||
|
||||
// The 3 vectors below store thehierarchical information for groups, profiles and locations,
|
||||
// meaning which is the child/parent of which. The actual group/profile/node data are also stored in the
|
||||
// structure.
|
||||
|
||||
mutable std::vector<HierarchicalGroupInformation> mGroups;
|
||||
mutable std::vector<HierarchicalProfileInformation> mProfiles;
|
||||
mutable std::vector<HierarchicalNodeInformation> mLocations;
|
||||
|
||||
// The top level list contains all nodes to display, which type depends on the option to display groups or not.
|
||||
// Idices in the list may be profile indices or group indices. In the former case the profile child index refers to
|
||||
// the inde in the mProfiles tab, whereas in the the later case, the child index refers to the index of the profile in the
|
||||
// group it belows to.
|
||||
|
||||
std::vector<EntryIndex> mTopLevel;
|
||||
|
||||
// keeps track of expanded/collapsed items, so as to only show icon for collapsed profiles
|
||||
|
||||
std::set<std::string> mExpandedProfiles;
|
||||
};
|
||||
|
||||
1511
retroshare-gui/src/gui/common/NewFriendList.cpp
Normal file
1511
retroshare-gui/src/gui/common/NewFriendList.cpp
Normal file
File diff suppressed because it is too large
Load diff
158
retroshare-gui/src/gui/common/NewFriendList.h
Normal file
158
retroshare-gui/src/gui/common/NewFriendList.h
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
/*******************************************************************************
|
||||
* gui/common/NewFriendList.h *
|
||||
* *
|
||||
* Copyright (C) 2011, Retroshare Team <retroshare.project@gmail.com> *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Affero General Public License as *
|
||||
* published by the Free Software Foundation, either version 3 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Affero General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Affero General Public License *
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QTreeView>
|
||||
|
||||
#include "FriendListModel.h"
|
||||
#include "RsAutoUpdatePage.h"
|
||||
#include "retroshare/rsstatus.h"
|
||||
|
||||
namespace Ui {
|
||||
class NewFriendList;
|
||||
}
|
||||
|
||||
class RSTreeWidgetItemCompareRole;
|
||||
class QTreeWidgetItem;
|
||||
class QToolButton;
|
||||
class FriendListSortFilterProxyModel;
|
||||
|
||||
class NewFriendList: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor textColorGroup READ textColorGroup WRITE setTextColorGroup)
|
||||
Q_PROPERTY(QColor textColorStatusOffline READ textColorStatusOffline WRITE setTextColorStatusOffline)
|
||||
Q_PROPERTY(QColor textColorStatusAway READ textColorStatusAway WRITE setTextColorStatusAway)
|
||||
Q_PROPERTY(QColor textColorStatusBusy READ textColorStatusBusy WRITE setTextColorStatusBusy)
|
||||
Q_PROPERTY(QColor textColorStatusOnline READ textColorStatusOnline WRITE setTextColorStatusOnline)
|
||||
Q_PROPERTY(QColor textColorStatusInactive READ textColorStatusInactive WRITE setTextColorStatusInactive)
|
||||
|
||||
public:
|
||||
explicit NewFriendList(QWidget *parent = 0);
|
||||
~NewFriendList();
|
||||
|
||||
// Add a tool button to the tool area
|
||||
void addToolButton(QToolButton *toolButton);
|
||||
void processSettings(bool load);
|
||||
void setColumnVisible(int col,bool visible);
|
||||
bool isColumnVisible(int col) const;
|
||||
|
||||
std::string getSelectedGroupId() const;
|
||||
|
||||
//void updateDisplay() override;
|
||||
|
||||
QColor textColorGroup() const { return mModel->mTextColorGroup; }
|
||||
QColor textColorStatusOffline() const { return mModel->mTextColorStatus[RS_STATUS_OFFLINE ]; }
|
||||
QColor textColorStatusAway() const { return mModel->mTextColorStatus[RS_STATUS_AWAY ]; }
|
||||
QColor textColorStatusBusy() const { return mModel->mTextColorStatus[RS_STATUS_BUSY ]; }
|
||||
QColor textColorStatusOnline() const { return mModel->mTextColorStatus[RS_STATUS_ONLINE ]; }
|
||||
QColor textColorStatusInactive() const { return mModel->mTextColorStatus[RS_STATUS_INACTIVE]; }
|
||||
|
||||
void setTextColorGroup(QColor color) { mModel->mTextColorGroup = color; }
|
||||
void setTextColorStatusOffline(QColor color) { mModel->mTextColorStatus[RS_STATUS_OFFLINE ] = color; }
|
||||
void setTextColorStatusAway(QColor color) { mModel->mTextColorStatus[RS_STATUS_AWAY ] = color; }
|
||||
void setTextColorStatusBusy(QColor color) { mModel->mTextColorStatus[RS_STATUS_BUSY ] = color; }
|
||||
void setTextColorStatusOnline(QColor color) { mModel->mTextColorStatus[RS_STATUS_ONLINE ] = color; }
|
||||
void setTextColorStatusInactive(QColor color) { mModel->mTextColorStatus[RS_STATUS_INACTIVE] = color; }
|
||||
|
||||
public slots:
|
||||
void filterItems(const QString &text);
|
||||
void toggleSortByState(bool sort);
|
||||
void forceUpdateDisplay();
|
||||
|
||||
void toggleColumnVisible();
|
||||
void setShowGroups(bool show);
|
||||
void setShowUnconnected(bool hidden);
|
||||
void setShowState(bool show);
|
||||
void headerContextMenuRequested(QPoint);
|
||||
|
||||
private slots:
|
||||
void sortColumn(int col,Qt::SortOrder so);
|
||||
void itemExpanded(const QModelIndex&);
|
||||
void itemCollapsed(const QModelIndex&);
|
||||
|
||||
protected:
|
||||
void changeEvent(QEvent *e);
|
||||
|
||||
private:
|
||||
Ui::NewFriendList *ui;
|
||||
RsFriendListModel *mModel;
|
||||
QAction *mActionSortByState;
|
||||
|
||||
void expandGroup(const RsNodeGroupId& gid);
|
||||
void recursRestoreExpandedItems(const QModelIndex& index, const QString& parent_path, const std::set<QString>& exp, const std::set<QString> &sel);
|
||||
void recursSaveExpandedItems(const QModelIndex& index,const QString& parent_path,std::set<QString>& exp, std::set<QString>& sel);
|
||||
void saveExpandedPathsAndSelection(std::set<QString>& expanded_indexes, std::set<QString>& selected_indexes);
|
||||
void restoreExpandedPathsAndSelection(const std::set<QString>& expanded_indexes, const std::set<QString>& selected_indexes);
|
||||
|
||||
void checkInternalData(bool force);
|
||||
|
||||
QModelIndex getCurrentSourceIndex() const;
|
||||
|
||||
bool getCurrentNode(RsFriendListModel::RsNodeDetails& prof) const;
|
||||
bool getCurrentGroup(RsGroupInfo& prof) const;
|
||||
bool getCurrentProfile(RsFriendListModel::RsProfileDetails& prof) const;
|
||||
|
||||
// Settings for peer list display
|
||||
bool mShowState;
|
||||
|
||||
std::set<RsNodeGroupId> openGroups;
|
||||
std::set<RsPgpId> openPeers;
|
||||
|
||||
bool getOrCreateGroup(const std::string& name, uint flag, RsNodeGroupId& id);
|
||||
bool getGroupIdByName(const std::string& name, RsNodeGroupId& id);
|
||||
|
||||
bool importExportFriendlistFileDialog(QString &fileName, bool import);
|
||||
bool exportFriendlist(QString &fileName);
|
||||
bool importFriendlist(QString &fileName, bool &errorPeers, bool &errorGroups);
|
||||
|
||||
FriendListSortFilterProxyModel *mProxyModel ;
|
||||
private slots:
|
||||
void peerTreeWidgetCustomPopupMenu();
|
||||
void pastePerson();
|
||||
void connectNode();
|
||||
void configureNode();
|
||||
void configureProfile();
|
||||
void chatNode();
|
||||
void copyFullCertificate();
|
||||
void addFriend();
|
||||
void msgNode();
|
||||
void msgGroup();
|
||||
void msgProfile();
|
||||
void recommendNode();
|
||||
void removeNode();
|
||||
void removeProfile();
|
||||
void createNewGroup() ;
|
||||
|
||||
void addToGroup();
|
||||
void moveToGroup();
|
||||
void removeFromGroup();
|
||||
|
||||
void editGroup();
|
||||
void removeGroup();
|
||||
|
||||
void exportFriendlistClicked();
|
||||
void importFriendlistClicked();
|
||||
};
|
||||
132
retroshare-gui/src/gui/common/NewFriendList.ui
Normal file
132
retroshare-gui/src/gui/common/NewFriendList.ui
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NewFriendList</class>
|
||||
<widget class="QWidget" name="NewFriendList">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>475</width>
|
||||
<height>292</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="titleBarFrame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="LineEditClear" name="filterLineEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="peerTreeWidget">
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<action name="actionShowOfflineFriends">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Offline Friends</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show Offline Friends</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShowState">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Status</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show status</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShowGroups">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Groups</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show groups</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExportFriendlist">
|
||||
<property name="text">
|
||||
<string>export friendlist</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>export your friendlist including groups</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionImportFriendlist">
|
||||
<property name="text">
|
||||
<string>import friendlist</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>import your friendlist including groups</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LineEditClear</class>
|
||||
<extends>QLineEdit</extends>
|
||||
<header location="global">gui/common/LineEditClear.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -243,7 +243,7 @@ QString StatusDefs::connectStateWithoutTransportTypeString(RsPeerDetails &detail
|
|||
return stateString;
|
||||
}
|
||||
|
||||
QString StatusDefs::connectStateIpString(RsPeerDetails &details)
|
||||
QString StatusDefs::connectStateIpString(const RsPeerDetails &details)
|
||||
{
|
||||
QString stateString = QString("");
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public:
|
|||
static QString peerStateString(int peerState);
|
||||
static QString connectStateString(RsPeerDetails &details);
|
||||
static QString connectStateWithoutTransportTypeString(RsPeerDetails &details);
|
||||
static QString connectStateIpString(RsPeerDetails &details);
|
||||
static QString connectStateIpString(const RsPeerDetails &details);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue