FriendList:

- Removed avatar column
- Removed state column
- Added combined avatar and status icon
- Added status icons in 64px
- Renamed "Hide state" to "Show state"
- Added sort by name and state

RSTreeWidget:
- Added version for load/save state
- Added method setColumnCustomizable
This commit is contained in:
thunder2 2015-08-08 20:27:19 +02:00
parent ec67ee0e00
commit 87f2e6da37
24 changed files with 619 additions and 596 deletions

View File

@ -142,9 +142,7 @@ QList<int> sizes;
// load settings
RsAutoUpdatePage::lockAllEvents();
ui.friendList->setColumnVisible(FriendList::COLUMN_STATE, false);
ui.friendList->setColumnVisible(FriendList::COLUMN_LAST_CONTACT, false);
ui.friendList->setColumnVisible(FriendList::COLUMN_AVATAR, true);
ui.friendList->setColumnVisible(FriendList::COLUMN_IP, false);
ui.friendList->setShowGroups(true);
processSettings(true);

View File

@ -142,13 +142,10 @@ MessengerWindow::MessengerWindow(QWidget* parent, Qt::WindowFlags flags)
// load settings
RsAutoUpdatePage::lockAllEvents();
ui.friendList->setColumnVisible(FriendList::COLUMN_STATE, false);
ui.friendList->setColumnVisible(FriendList::COLUMN_LAST_CONTACT, false);
ui.friendList->setColumnVisible(FriendList::COLUMN_AVATAR, true);
ui.friendList->setColumnVisible(FriendList::COLUMN_IP, false);
ui.friendList->setShowGroups(false);
processSettings(true);
ui.friendList->setBigName(true);
RsAutoUpdatePage::unlockAllEvents();
// add self nick

View File

@ -26,6 +26,7 @@
#include <QTreeWidgetItem>
#include <QWidgetAction>
#include <QDateTime>
#include <QPainter>
#include "retroshare/rspeers.h"
@ -73,20 +74,18 @@
#define IMAGE_COLLAPSE ":/images/edit_remove24.png"
/* Images for Status icons */
#define IMAGE_AVAILABLE ":/images/user/identityavaiblecyan24.png"
#define IMAGE_CONNECT2 ":/images/reload24.png"
#define IMAGE_PASTELINK ":/images/pasterslink.png"
#define IMAGE_GROUP24 ":/images/user/group24.png"
#define COLUMN_DATA 0 // column for storing the userdata id
#define COLUMN_SORT COLUMN_NAME // column for sorting
#define COLUMN_AVATAR_WIDTH 42
#define ROLE_SORT Qt::UserRole
#define ROLE_ID Qt::UserRole + 1
#define ROLE_STANDARD Qt::UserRole + 2
// to store the best ssl id for pgp items
// the best id decides which avatar image we want to display at the pgpg item
#define ROLE_BEST_SSL Qt::UserRole + 3
#define ROLE_ID Qt::UserRole
#define ROLE_STANDARD Qt::UserRole + 1
#define ROLE_SORT_GROUP Qt::UserRole + 2
#define ROLE_SORT_STANDARD_GROUP Qt::UserRole + 3
#define ROLE_SORT_NAME Qt::UserRole + 4
#define ROLE_SORT_STATE Qt::UserRole + 5
#define TYPE_GPG 0
#define TYPE_SSL 1
@ -101,9 +100,6 @@
#define PEER_STATE_INACTIVE 5
#define PEER_STATE_OFFLINE 6
#define BuildStateSortString(bEnabled,sName,nState) bEnabled ? (QString ("%1").arg(nState) + " " + sName) : sName
/******
* #define FRIENDS_DEBUG 1
*****/
@ -111,10 +107,9 @@
FriendList::FriendList(QWidget *parent) :
RsAutoUpdatePage(1500, parent),
ui(new Ui::FriendList),
m_compareRole(new RSTreeWidgetItemCompareRole),
mBigName(false),
mCompareRole(new RSTreeWidgetItemCompareRole),
mShowGroups(true),
mHideState(true),
mShowState(false),
mHideUnconnected(false),
groupsHasChanged(false),
openGroups(NULL),
@ -122,37 +117,26 @@ FriendList::FriendList(QWidget *parent) :
{
ui->setupUi(this);
m_compareRole->setRole(COLUMN_NAME, ROLE_SORT);
m_compareRole->setRole(COLUMN_STATE, ROLE_SORT);
m_compareRole->setRole(COLUMN_LAST_CONTACT, ROLE_SORT);
m_compareRole->setRole(COLUMN_IP, ROLE_SORT);
m_compareRole->setRole(COLUMN_AVATAR, ROLE_STANDARD);
connect(ui->peerTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(peerTreeWidgetCustomPopupMenu()));
connect(ui->peerTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(chatfriend(QTreeWidgetItem *)));
connect(NotifyQt::getInstance(), SIGNAL(groupsChanged(int)), this, SLOT(groupsChanged()));
connect(NotifyQt::getInstance(), SIGNAL(friendsChanged()), this, SLOT(insertPeers()));
connect(NotifyQt::getInstance(), SIGNAL(peerHasNewAvatar(const QString&)), this, SLOT(updateAvatar(const QString&)));
connect(ui->actionHideOfflineFriends, SIGNAL(triggered(bool)), this, SLOT(setHideUnconnected(bool)));
connect(ui->actionHideState, SIGNAL(triggered(bool)), this, SLOT(setHideState(bool)));
connect(ui->actionShowState, SIGNAL(triggered(bool)), this, SLOT(setShowState(bool)));
connect(ui->actionShowGroups, SIGNAL(triggered(bool)), this, SLOT(setShowGroups(bool)));
connect(ui->actionSortByName, SIGNAL(triggered()), this, SLOT(setSortByName()));
connect(ui->actionSortByState, SIGNAL(triggered()), this, SLOT(setSortByState()));
connect(ui->filterLineEdit, SIGNAL(textChanged(QString)), this, SLOT(filterItems(QString)));
ui->filterLineEdit->setPlaceholderText(tr("Search")) ;
ui->filterLineEdit->showFilterIcon();
initializeHeader(false);
ui->peerTreeWidget->sortItems(COLUMN_NAME, Qt::AscendingOrder);
// set header text aligment
QTreeWidgetItem *headerItem = ui->peerTreeWidget->headerItem();
headerItem->setTextAlignment(COLUMN_NAME, Qt::AlignHCenter | Qt::AlignVCenter);
headerItem->setTextAlignment(COLUMN_STATE, Qt::AlignLeft | Qt::AlignVCenter);
headerItem->setTextAlignment(COLUMN_AVATAR, Qt::AlignLeft | Qt::AlignVCenter);
/* Set sort */
setSortMode(SORT_MODE_NAME);
// workaround for Qt bug, should be solved in next Qt release 4.7.0
// http://bugreports.qt.nokia.com/browse/QTBUG-8270
@ -160,9 +144,16 @@ FriendList::FriendList(QWidget *parent) :
connect(Shortcut, SIGNAL(activated()), this, SLOT(removefriend()));
/* Initialize tree */
ui->peerTreeWidget->setColumnCustomizable(true);
ui->peerTreeWidget->enableColumnCustomize(true);
ui->peerTreeWidget->setColumnCustomizable(COLUMN_NAME, false);
connect(ui->peerTreeWidget, SIGNAL(columnVisibleChanged(int,bool)), this, SLOT(peerTreeColumnVisibleChanged(int,bool)));
/* Set initial column width */
int fontWidth = QFontMetricsF(ui->peerTreeWidget->font()).width("W");
ui->peerTreeWidget->setColumnWidth(COLUMN_NAME, 22 * fontWidth);
ui->peerTreeWidget->setColumnWidth(COLUMN_LAST_CONTACT, 12 * fontWidth);
ui->peerTreeWidget->setColumnWidth(COLUMN_IP, 15 * fontWidth);
/* Initialize display menu */
createDisplayMenu();
}
@ -170,7 +161,7 @@ FriendList::FriendList(QWidget *parent) :
FriendList::~FriendList()
{
delete ui;
delete(m_compareRole);
delete(mCompareRole);
}
void FriendList::addToolButton(QToolButton *toolButton)
@ -190,6 +181,7 @@ void FriendList::addToolButton(QToolButton *toolButton)
void FriendList::processSettings(bool load)
{
// state of peer tree
ui->peerTreeWidget->setSettingsVersion(1);
ui->peerTreeWidget->processSettings(load);
if (load) {
@ -200,9 +192,12 @@ void FriendList::processSettings(bool load)
// states
setHideUnconnected(Settings->value("hideUnconnected", mHideUnconnected).toBool());
setHideState(Settings->value("hideState", mHideState).toBool());
setShowState(Settings->value("showState", mShowState).toBool());
setShowGroups(Settings->value("showGroups", mShowGroups).toBool());
// sort
setSortMode((SortMode) Settings->value("sortMode", SORT_MODE_NAME).toInt());
// open groups
int arrayIndex = Settings->beginReadArray("Groups");
for (int index = 0; index < arrayIndex; ++index) {
@ -210,18 +205,17 @@ void FriendList::processSettings(bool load)
addGroupToExpand(Settings->value("open").toString().toStdString());
}
Settings->endArray();
initializeHeader(true);
peerTreeColumnVisibleChanged(COLUMN_STATE, !ui->peerTreeWidget->isColumnHidden(COLUMN_STATE));
} else {
// save settings
// states
Settings->setValue("hideUnconnected", mHideUnconnected);
Settings->setValue("hideState", mHideState);
Settings->setValue("rootIsDecorated", ui->peerTreeWidget->rootIsDecorated());
Settings->setValue("showState", mShowState);
Settings->setValue("showGroups", mShowGroups);
// sort
Settings->setValue("sortMode", sortMode());
// open groups
Settings->beginWriteArray("Groups");
int arrayIndex = 0;
@ -248,22 +242,6 @@ void FriendList::changeEvent(QEvent *e)
}
}
void FriendList::initializeHeader(bool /*afterLoadSettings*/)
{
// set column size
QHeaderView *header = ui->peerTreeWidget->header();
QHeaderView_setSectionsMovable(header, true);
//QHeaderView_setSectionResizeModeColumn(header, COLUMN_NAME, QHeaderView::Stretch);
QHeaderView_setSectionResizeModeColumn(header, COLUMN_NAME, QHeaderView::Interactive);
QHeaderView_setSectionResizeModeColumn(header, COLUMN_STATE, QHeaderView::Interactive);
QHeaderView_setSectionResizeModeColumn(header, COLUMN_LAST_CONTACT, QHeaderView::Interactive);
QHeaderView_setSectionResizeModeColumn(header, COLUMN_IP, QHeaderView::Interactive);
QHeaderView_setSectionResizeModeColumn(header, COLUMN_AVATAR, QHeaderView::Fixed);
header->setStretchLastSection(false);
header->resizeSection(COLUMN_AVATAR, COLUMN_AVATAR_WIDTH);
}
/* Utility Fns */
inline std::string getRsId(QTreeWidgetItem *item)
{
@ -476,31 +454,21 @@ void FriendList::groupsChanged()
insertPeers();
}
void FriendList::updateAvatar(const QString& id)
static QIcon createAvatar(const QPixmap &avatar, const QPixmap &overlay)
{
if (ui->peerTreeWidget->isColumnHidden(COLUMN_AVATAR))
return;
QPixmap pixmap(avatar);
QTreeWidgetItemIterator it(ui->peerTreeWidget);
while (*it) {
// case ssl item
if ((*it)->type() == TYPE_SSL && id == (*it)->data(COLUMN_DATA, ROLE_ID).toString()) {
if ((*it)->parent() != NULL && (*it)->parent()->type() == TYPE_GPG) {
QPixmap avatar;
AvatarDefs::getAvatarFromSslId(RsPeerId(id.toStdString()), avatar);
QIcon avatar_icon(avatar);
(*it)->setIcon(COLUMN_AVATAR, avatar_icon);
}
}
// case pgp item
if ((*it)->type() == TYPE_GPG && id == (*it)->data(COLUMN_DATA, ROLE_BEST_SSL).toString()) {
QPixmap avatar;
AvatarDefs::getAvatarFromSslId(RsPeerId(id.toStdString()), avatar);
QIcon avatar_icon(avatar);
(*it)->setIcon(COLUMN_AVATAR, avatar_icon);
}
++it;
}
int x = avatar.width() / 2;
int y = avatar.height() / 2;
int w = avatar.width() / 2;
int h = avatar.height() / 2;
QPainter painter(&pixmap);
painter.drawPixmap(x, y, w, h, overlay);
QIcon icon;
icon.addPixmap(pixmap);
return icon;
}
/**
@ -518,8 +486,6 @@ void FriendList::insertPeers()
std::cerr << "FriendList::insertPeers() called." << std::endl;
#endif
bool isStatusColumnHidden = ui->peerTreeWidget->isColumnHidden(COLUMN_STATE);
bool isAvatarColumnHidden = ui->peerTreeWidget->isColumnHidden(COLUMN_AVATAR);
int columnCount = ui->peerTreeWidget->columnCount();
std::list<StatusInfo> statusInfo;
@ -662,13 +628,12 @@ void FriendList::insertPeers()
if (groupItem == NULL) {
// add group item
groupItem = new RSTreeWidgetItem(m_compareRole, TYPE_GROUP);
groupItem = new RSTreeWidgetItem(mCompareRole, TYPE_GROUP);
/* Add item to the list. Add here, because for setHidden the item must be added */
peerTreeWidget->addTopLevelItem(groupItem);
groupItem->setChildIndicatorPolicy(QTreeWidgetItem::DontShowIndicatorWhenChildless);
groupItem->setSizeHint(COLUMN_NAME, QSize(26, 26));
groupItem->setTextAlignment(COLUMN_NAME, Qt::AlignLeft | Qt::AlignVCenter);
groupItem->setIcon(COLUMN_NAME, QIcon(IMAGE_GROUP24));
groupItem->setForeground(COLUMN_NAME, QBrush(textColorGroup()));
@ -677,6 +642,10 @@ void FriendList::insertPeers()
groupItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(groupInfo->id));
groupItem->setData(COLUMN_DATA, ROLE_STANDARD, (groupInfo->flag & RS_GROUP_FLAG_STANDARD) ? true : false);
/* Sort data */
groupItem->setData(COLUMN_SORT, ROLE_SORT_GROUP, 1);
groupItem->setData(COLUMN_SORT, ROLE_SORT_STANDARD_GROUP, (groupInfo->flag & RS_GROUP_FLAG_STANDARD) ? 0 : 1);
groupItem->setData(COLUMN_SORT, ROLE_SORT_STATE, 0);
} else {
// remove all gpg items that are not more assigned
int childCount = groupItem->childCount();
@ -757,7 +726,7 @@ void FriendList::insertPeers()
if (gpgItem == NULL) {
// create gpg item and add it to tree
gpgItem = new RSTreeWidgetItem(m_compareRole, TYPE_GPG); //set type to 0 for custom popup menu
gpgItem = new RSTreeWidgetItem(mCompareRole, TYPE_GPG); //set type to 0 for custom popup menu
/* Add gpg item to the list. Add here, because for setHidden the item must be added */
if (groupItem) {
@ -771,17 +740,17 @@ void FriendList::insertPeers()
/* not displayed, used to find back the item */
gpgItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(detail.gpg_id.toStdString()));
}
if (mBigName && !mHideState && isStatusColumnHidden) {
gpgItem->setSizeHint(COLUMN_NAME, QSize(40, 40));
} else {
gpgItem->setSizeHint(COLUMN_NAME, QSize(26, 26));
/* Sort data */
gpgItem->setData(COLUMN_SORT, ROLE_SORT_GROUP, 2);
// show first the standard groups, than the user groups
gpgItem->setData(COLUMN_SORT, ROLE_SORT_STANDARD_GROUP, 1);
}
++availableCount;
QString gpgItemText = QString::fromUtf8(detail.name.c_str());
QString gpgName = QString::fromUtf8(detail.name.c_str());
QString gpgItemText = gpgName;
// remove items that are not friends anymore
int childCount = gpgItem->childCount();
@ -803,18 +772,18 @@ void FriendList::insertPeers()
bool gpg_hasPrivateChat = false;
int bestPeerState = 0; // for gpg item
unsigned int bestRSState = 0; // for gpg item
RsPeerId bestSslId; // for gpg item
QString bestCustomStateString;// for gpg item
std::list<RsPeerId> sslContacts;
QDateTime lastContact;
QString itemIP;
QDateTime bestLastContact;
QString bestIP;
QPixmap bestAvatar;
rsPeers->getAssociatedSSLIds(detail.gpg_id, sslContacts);
for (std::list<RsPeerId>::iterator sslIt = sslContacts.begin(); sslIt != sslContacts.end(); ++sslIt) {
QTreeWidgetItem *sslItem = NULL;
RsPeerId sslId = *sslIt;
//find the corresponding sslItem child item of the gpg item
// find the corresponding sslItem child item of the gpg item
bool newChild = true;
childCount = gpgItem->childCount();
for (int childIndex = 0; childIndex < childCount; ++childIndex) {
@ -831,15 +800,16 @@ void FriendList::insertPeers()
#ifdef FRIENDS_DEBUG
std::cerr << "Removing widget from the view : id : " << sslId << std::endl;
#endif
//child has disappeared, remove it from the gpg_item
// child has disappeared, remove it from the gpg_item
if (sslItem) {
gpgItem->removeChild(sslItem);
delete(sslItem);
}
continue;
}
if (newChild) {
sslItem = new RSTreeWidgetItem(m_compareRole, TYPE_SSL); //set type to 1 for custom popup menu
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;
@ -847,71 +817,47 @@ void FriendList::insertPeers()
/* Add ssl child to the list. Add here, because for setHidden the item must be added */
gpgItem->addChild(sslItem);
/* Sort data */
sslItem->setData(COLUMN_SORT, ROLE_SORT_GROUP, 2);
sslItem->setData(COLUMN_SORT, ROLE_SORT_STANDARD_GROUP, 1);
}
/* not displayed, used to find back the item */
sslItem->setData(COLUMN_DATA, ROLE_ID, QString::fromStdString(sslDetail.id.toStdString()));
if (!isAvatarColumnHidden)
updateAvatar(QString::fromStdString(sslDetail.id.toStdString()));
QString sText;
/* Custom state string */
QString customStateString;
if (sslDetail.state & RS_PEER_STATE_CONNECTED) {
customStateString = QString::fromUtf8(rsMsgs->getCustomStateString(sslDetail.id).c_str());
}
sText = QString::fromUtf8(sslDetail.location.c_str());
if (customStateString.isEmpty() == false) {
sText += " - " + customStateString;
}
QString connectStateString = StatusDefs::connectStateWithoutTransportTypeString(sslDetail);
if (!isStatusColumnHidden) {
sslItem->setText(COLUMN_STATE, connectStateString);
} else if (!mHideState && connectStateString.isEmpty() == false) {
sText += " [" + connectStateString + "]";
}
sslItem->setText( COLUMN_NAME, sText);
if (isStatusColumnHidden == true && mHideState == true) {
/* Show the state as tooltip */
sslItem->setToolTip(COLUMN_NAME, connectStateString);
} else {
sslItem->setToolTip(COLUMN_NAME, "");
}
// sort node
sslItem->setData(COLUMN_STATE, ROLE_SORT, sText);
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, sslLastContact);
if (sslLastContact > lastContact) {
lastContact = sslLastContact;
if (sslLastContact > bestLastContact) {
bestLastContact = sslLastContact;
}
/* IP */
QString sslItemIP = (sslDetail.state & RS_PEER_STATE_CONNECTED) ? StatusDefs::connectStateIpString(sslDetail) : QString("---");
sslItem->setData(COLUMN_IP, Qt::DisplayRole, QVariant(sslItemIP));
sslItem->setData(COLUMN_IP, ROLE_SORT, sslItemIP);
if (sslItemIP != itemIP) {
itemIP = sslItemIP;
}
QString sslIP = (sslDetail.state & RS_PEER_STATE_CONNECTED) ? StatusDefs::connectStateIpString(sslDetail) : QString("---");
sslItem->setText(COLUMN_IP, sslIP);
/* change color and icon */
QIcon sslIcon;
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 peerState = 0;
int rsState = 0;
std::list<StatusInfo>::iterator it;
for(it = statusInfo.begin(); it != statusInfo.end(); ++it) {
if(it->id == sslId){
for (it = statusInfo.begin(); it != statusInfo.end(); ++it) {
if (it->id == sslId) {
rsState = it->status;
switch (rsState) {
case RS_STATUS_INACTIVE:
@ -935,19 +881,25 @@ void FriendList::insertPeers()
if (bestPeerState == 0 || peerState < bestPeerState) {
/* first ssl contact or higher state */
bestPeerState = peerState;
bestSslId = sslId;
bestRSState = rsState;
bestCustomStateString = customStateString;
bestIP = sslIP;
if (!sslAvatar.isNull()) {
bestAvatar = sslAvatar;
}
} else if (peerState == bestPeerState) {
/* equal state */
if (mBigName && bestCustomStateString.isEmpty() && !customStateString.isEmpty()) {
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;
bestSslId = sslId;
bestRSState = rsState;
bestCustomStateString = customStateString;
}
if (bestAvatar.isNull() && !sslAvatar.isNull()) {
/* Use available avatar */
bestAvatar = sslAvatar;
}
}
break;
}
@ -956,7 +908,9 @@ void FriendList::insertPeers()
sslItem->setHidden(false);
gpg_connected = true;
sslIcon = QIcon(":/images/connect_established.png");
sslOverlayIcon = QPixmap(StatusDefs::imageStatus(bestRSState));
connectStateString = StatusDefs::name(rsState);
if (rsState == 0) {
sslFont.setBold(true);
@ -968,41 +922,78 @@ void FriendList::insertPeers()
} else if (sslDetail.state & RS_PEER_STATE_ONLINE) {
sslItem->setHidden(mHideUnconnected);
gpg_online = true;
peerState = PEER_STATE_AVAILABLE;
if (sslDetail.connectState) {
sslIcon = QIcon(":/images/connect_creating.png");
sslOverlayIcon = QPixmap(":/images/connect_creating.png");
} else {
sslIcon = QIcon(":/images/connect_no.png");
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) {
sslIcon = QIcon(":/images/connect_creating.png");
sslOverlayIcon = QPixmap(":/images/connect_creating.png");
} else {
sslIcon = QIcon(":/images/connect_no.png");
sslOverlayIcon = QPixmap(StatusDefs::imageStatus(RS_STATUS_OFFLINE));
}
connectStateString = StatusDefs::connectStateWithoutTransportTypeString(sslDetail);
sslFont.setBold(false);
sslColor = mTextColorStatus[RS_STATUS_OFFLINE];
}
/* Location */
QString sName = QString::fromUtf8(sslDetail.location.c_str());
QString sText = sName;
if (mShowState) {
if (!connectStateString.isEmpty()) {
sText += "\n" + connectStateString;
if (!customStateString.isEmpty()) {
sText += " [" + customStateString + "]";
}
} else {
if (!customStateString.isEmpty()) {
sText += "\n" + customStateString;
}
}
sslItem->setToolTip(COLUMN_NAME, "");
} else {
if (!customStateString.isEmpty()) {
sText += "\n" + customStateString;
}
/* Show the state as tooltip */
sslItem->setToolTip(COLUMN_NAME, connectStateString);
}
sslItem->setText(COLUMN_NAME, sText);
if (std::find(privateChatIds.begin(), privateChatIds.end(), sslDetail.id) != privateChatIds.end()) {
// private chat is available
sslIcon = QIcon(":/images/chat.png");
sslOverlayIcon = QPixmap(":/images/chat.png");
gpg_hasPrivateChat = true;
}
sslItem -> setIcon(COLUMN_NAME, sslIcon);
sslItem->setIcon(COLUMN_NAME, createAvatar(sslAvatar, sslOverlayIcon));
/* Sort data */
sslItem->setData(COLUMN_SORT, ROLE_SORT_NAME, sName);
sslItem->setData(COLUMN_SORT, ROLE_SORT_STATE, peerState);
for (int i = 0; i < columnCount; ++i) {
sslItem -> setTextColor(i, sslColor);
sslItem -> setFont(i, sslFont);
sslItem->setTextColor(i, sslColor);
sslItem->setFont(i, sslFont);
}
}
QIcon gpgIcon;
QPixmap gpgOverlayIcon;
if (gpg_connected) {
gpgItem->setHidden(false);
@ -1021,32 +1012,27 @@ void FriendList::insertPeers()
gpgItem->setFont(i, font);
}
gpgIcon = QIcon(StatusDefs::imageStatus(bestRSState));
gpgOverlayIcon = QPixmap(StatusDefs::imageStatus(bestRSState));
if (!isStatusColumnHidden) {
gpgItem->setText(COLUMN_STATE, StatusDefs::name(bestRSState));
}
if (isStatusColumnHidden && mBigName && !mHideState) {
if (bestCustomStateString.isEmpty()) {
if (mShowState) {
gpgItemText += "\n" + StatusDefs::name(bestRSState);
if (!bestCustomStateString.isEmpty()) {
gpgItemText += " [" + bestCustomStateString + "]";
}
} else {
if (!bestCustomStateString.isEmpty()) {
gpgItemText += "\n" + bestCustomStateString;
}
} else if (isStatusColumnHidden && !mHideState){
gpgItemText += " - " + StatusDefs::name(bestRSState);
}
} else if (gpg_online) {
if (!isStatusColumnHidden) {
gpgItem->setText(COLUMN_STATE, tr("Available"));
} else if (!mHideState && !mBigName) {
gpgItemText += " - " + tr("Available") ;
if (mShowState) {
gpgItemText += "\n" + tr("Available");
}
bestPeerState = PEER_STATE_AVAILABLE;
++onlineCount;
gpgItem->setHidden(mHideUnconnected);
gpgIcon = QIcon(IMAGE_AVAILABLE);
gpgOverlayIcon = QPixmap(IMAGE_AVAILABLE);
QFont font;
font.setBold(true);
@ -1056,15 +1042,13 @@ void FriendList::insertPeers()
gpgItem->setFont(i,font);
}
} else {
if (!isStatusColumnHidden) {
gpgItem->setText(COLUMN_STATE, StatusDefs::name(RS_STATUS_OFFLINE));
} else if (!mHideState && !mBigName) {
gpgItemText += " - " + StatusDefs::name(RS_STATUS_OFFLINE) ;
if (mShowState) {
gpgItemText += "\n" + StatusDefs::name(RS_STATUS_OFFLINE);
}
bestPeerState = PEER_STATE_OFFLINE;
gpgItem->setHidden(mHideUnconnected);
gpgIcon = QIcon(StatusDefs::imageStatus(RS_STATUS_OFFLINE));
gpgOverlayIcon = QPixmap(StatusDefs::imageStatus(RS_STATUS_OFFLINE));
QColor textColor = mTextColorStatus[RS_STATUS_OFFLINE];
QFont font = StatusDefs::font(RS_STATUS_OFFLINE);
@ -1075,26 +1059,18 @@ void FriendList::insertPeers()
}
if (gpg_hasPrivateChat) {
gpgIcon = QIcon(":/images/chat.png");
gpgOverlayIcon = QPixmap(":/images/chat.png");
}
if (!isAvatarColumnHidden){
QPixmap avatar;
AvatarDefs::getAvatarFromSslId(bestSslId, avatar);
QIcon avatar_icon(avatar);
gpgItem->setIcon(COLUMN_AVATAR, avatar_icon);
// tell the avatar callback which avatar must be filled in at this place
gpgItem->setData(COLUMN_DATA, ROLE_BEST_SSL, QString::fromStdString(bestSslId.toStdString()));
}
gpgItem->setIcon(COLUMN_NAME, createAvatar(bestAvatar.isNull() ? QPixmap(AVATAR_DEFAULT_IMAGE) : bestAvatar, gpgOverlayIcon));
gpgItem->setText(COLUMN_NAME, gpgItemText);
gpgItem->setData(COLUMN_NAME, ROLE_SORT, "2 " + gpgItemText);
gpgItem->setData(COLUMN_STATE, ROLE_SORT, "2 " + BuildStateSortString(true, gpgItemText, bestPeerState));
gpgItem->setIcon(COLUMN_NAME, gpgIcon);
gpgItem->setData(COLUMN_LAST_CONTACT, Qt::DisplayRole, QVariant(lastContact));
gpgItem->setData(COLUMN_LAST_CONTACT, ROLE_SORT, "2 " + lastContact.toString("yyyyMMdd_hhmmss"));
gpgItem->setData(COLUMN_IP, Qt::DisplayRole, QVariant());
gpgItem->setData(COLUMN_IP, ROLE_SORT, "2 " + itemIP);
gpgItem->setData(COLUMN_LAST_CONTACT, Qt::DisplayRole, QVariant(bestLastContact));
gpgItem->setText(COLUMN_IP, bestIP);
/* Sort data */
gpgItem->setData(COLUMN_SORT, ROLE_SORT_NAME, gpgName);
gpgItem->setData(COLUMN_SORT, ROLE_SORT_STATE, bestPeerState);
if (openPeers != NULL && openPeers->find(gpgId.toStdString()) != openPeers->end()) {
gpgItem->setExpanded(true);
@ -1109,8 +1085,9 @@ void FriendList::insertPeers()
groupItem->setHidden(false);
QString groupName = GroupDefs::name(*groupInfo);
groupItem->setText(COLUMN_NAME, QString("%1 (%2/%3)").arg(groupName).arg(onlineCount).arg(availableCount));
// show first the standard groups, than the user groups
groupItem->setData(COLUMN_NAME, ROLE_SORT, ((groupInfo->flag & RS_GROUP_FLAG_STANDARD) ? "0 " : "1 ") + groupName);
/* Sort data */
groupItem->setData(COLUMN_SORT, ROLE_SORT_NAME, groupName);
}
}
@ -1135,6 +1112,8 @@ void FriendList::insertPeers()
delete(openPeers);
openPeers = NULL;
}
ui->peerTreeWidget->sortItems(COLUMN_SORT, Qt::AscendingOrder);
}
/**
@ -1458,7 +1437,6 @@ void FriendList::connectfriend()
QTreeWidgetItem *item = c->child(childIndex);
if (item->type() == TYPE_SSL) {
rsPeers->connectAttempt(RsPeerId(getRsId(item)));
item->setIcon(COLUMN_NAME,(QIcon(IMAGE_CONNECT2)));
// Launch ProgressDialog, only if single SSL child.
if (childCount == 1)
@ -1470,7 +1448,6 @@ void FriendList::connectfriend()
} else {
//this is a SSL key
rsPeers->connectAttempt(RsPeerId(getRsId(c)));
c->setIcon(COLUMN_NAME,(QIcon(IMAGE_CONNECT2)));
// Launch ProgressDialog.
ConnectProgressDialog::showProgress(RsPeerId(getRsId(c)));
}
@ -1682,37 +1659,66 @@ void FriendList::setColumnVisible(Column column, bool visible)
peerTreeColumnVisibleChanged(column, visible);
}
void FriendList::sortByColumn(Column column, Qt::SortOrder sortOrder)
void FriendList::peerTreeColumnVisibleChanged(int /*column*/, bool visible)
{
ui->peerTreeWidget->sortByColumn(column, sortOrder);
}
void FriendList::peerTreeColumnVisibleChanged(int column, bool visible)
{
switch (column) {
case COLUMN_NAME:
case COLUMN_AVATAR:
case COLUMN_LAST_CONTACT:
case COLUMN_IP:
break;
case COLUMN_STATE:
ui->actionHideState->setEnabled(!visible);
break;
}
if (visible) {
insertPeers();
}
}
void FriendList::setHideState(bool hidden)
void FriendList::setShowState(bool show)
{
if (mHideState != hidden) {
mHideState = hidden;
if (mShowState != show) {
mShowState = show;
insertPeers();
}
}
void FriendList::setSortByName()
{
setSortMode(SORT_MODE_NAME);
}
void FriendList::setSortByState()
{
setSortMode(SORT_MODE_STATE);
}
void FriendList::setSortMode(SortMode sortMode)
{
// Add changes also in FriendList::sortMode
mCompareRole->setRole(COLUMN_SORT, ROLE_SORT_GROUP);
mCompareRole->addRole(COLUMN_SORT, ROLE_SORT_STANDARD_GROUP);
switch (sortMode) {
case SORT_MODE_STATE:
mCompareRole->addRole(COLUMN_SORT, ROLE_SORT_STATE);
mCompareRole->addRole(COLUMN_SORT, ROLE_SORT_NAME);
break;
default: // SORT_MODE_NAME
mCompareRole->addRole(COLUMN_SORT, ROLE_SORT_NAME);
mCompareRole->addRole(COLUMN_SORT, ROLE_SORT_STATE);
}
ui->peerTreeWidget->sortItems(COLUMN_SORT, Qt::AscendingOrder);
}
FriendList::SortMode FriendList::sortMode()
{
QList<int> roles;
mCompareRole->findRoles(COLUMN_SORT, roles);
if (roles.count() == 4) {
switch (roles.at(2)) {
case ROLE_SORT_NAME:
return SORT_MODE_NAME;
case ROLE_SORT_STATE:
return SORT_MODE_STATE;
}
}
return SORT_MODE_NAME;
}
void FriendList::setShowGroups(bool show)
{
if (mShowGroups != show) {
@ -1735,35 +1741,6 @@ void FriendList::setShowGroups(bool show)
}
}
/**
* If set to true, the customStateString will be shwon in all gpg peer items,
* not only in the ssl ids (used in MessengerWindow).
* These items will then be doublespaced.
*/
void FriendList::setBigName(bool bigName)
{
if (mBigName != bigName) {
mBigName = bigName;
// Change the size of the already existing items
QSize newSize;
if (mBigName) {
newSize.setHeight(40);
newSize.setWidth(40);
} else {
newSize.setHeight(26);
newSize.setWidth(26);
}
QTreeWidgetItemIterator it(ui->peerTreeWidget);
while (*it) {
if ((*it)->type() == TYPE_GPG) {
(*it)->setSizeHint(COLUMN_NAME, newSize);
}
++it;
}
}
}
/**
* Hides all items that don't contain text in the name column.
*/
@ -1802,8 +1779,16 @@ void FriendList::createDisplayMenu()
QMenu *displayMenu = new QMenu(this);
connect(displayMenu, SIGNAL(aboutToShow()), this, SLOT(updateMenu()));
QActionGroup *actionGroup = new QActionGroup(displayMenu);
QMenu *menu = displayMenu->addMenu(tr("Sort by"));
menu->addAction(ui->actionSortByName);
ui->actionSortByName->setActionGroup(actionGroup);
menu->addAction(ui->actionSortByState);
ui->actionSortByState->setActionGroup(actionGroup);
displayMenu->addAction(ui->actionHideOfflineFriends);
displayMenu->addAction(ui->actionHideState);
displayMenu->addAction(ui->actionShowState);
displayMenu->addAction(ui->actionShowGroups);
ui->displayButton->setMenu(displayMenu);
@ -1812,6 +1797,16 @@ void FriendList::createDisplayMenu()
void FriendList::updateMenu()
{
ui->actionHideOfflineFriends->setChecked(mHideUnconnected);
ui->actionHideState->setChecked(mHideState);
ui->actionShowState->setChecked(mShowState);
ui->actionShowGroups->setChecked(mShowGroups);
ui->actionSortByName->setChecked(true);
switch (sortMode()) {
case SORT_MODE_NAME:
ui->actionSortByName->setChecked(true);
break;
case SORT_MODE_STATE:
ui->actionSortByState->setChecked(true);
break;
}
}

View File

@ -52,10 +52,14 @@ public:
enum Column
{
COLUMN_NAME = 0,
COLUMN_AVATAR = 1,
COLUMN_STATE = 2,
COLUMN_LAST_CONTACT = 3,
COLUMN_IP = 4
COLUMN_LAST_CONTACT = 1,
COLUMN_IP = 2
};
enum SortMode
{
SORT_MODE_NAME = 1,
SORT_MODE_STATE = 2
};
public:
@ -74,7 +78,9 @@ public:
virtual void updateDisplay();
void setColumnVisible(Column column, bool visible);
void sortByColumn(Column column, Qt::SortOrder sortOrder);
void setSortMode(SortMode sortMode);
SortMode sortMode();
QColor textColorGroup() const { return mTextColorGroup; }
QColor textColorStatusOffline() const { return mTextColorStatus[RS_STATUS_OFFLINE]; }
@ -92,11 +98,12 @@ public:
public slots:
void filterItems(const QString &text);
void setSortByName();
void setSortByState();
void setBigName(bool bigName); // show customStateString in second line of the name cell
void setShowGroups(bool show);
void setHideUnconnected(bool hidden);
void setHideState(bool hidden);
void setShowState(bool show);
private slots:
void peerTreeColumnVisibleChanged(int column, bool visible);
@ -107,12 +114,11 @@ protected:
private:
Ui::FriendList *ui;
RSTreeWidgetItemCompareRole *m_compareRole;
RSTreeWidgetItemCompareRole *mCompareRole;
// Settings for peer list display
bool mBigName;
bool mShowGroups;
bool mHideState;
bool mShowState;
bool mHideUnconnected;
QString mFilterText;
@ -126,14 +132,12 @@ private:
QColor mTextColorStatus[RS_STATUS_COUNT];
QTreeWidgetItem *getCurrentPeer() const;
void initializeHeader(bool afterLoadSettings);
void getSslIdsFromItem(QTreeWidgetItem *item, std::list<RsPeerId> &sslIds);
private slots:
void groupsChanged();
void insertPeers();
void peerTreeWidgetCustomPopupMenu();
void updateAvatar(const QString &);
void updateMenu();
void pastePerson();

View File

@ -81,15 +81,6 @@
<height>38</height>
</size>
</property>
<property name="autoExpandDelay">
<number>1</number>
</property>
<property name="indentation">
<number>20</number>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="allColumnsShowFocus">
<bool>true</bool>
</property>
@ -97,7 +88,7 @@
<bool>false</bool>
</property>
<property name="columnCount">
<number>5</number>
<number>3</number>
</property>
<attribute name="headerStretchLastSection">
<bool>false</bool>
@ -106,15 +97,8 @@
<property name="text">
<string>Friend nodes</string>
</property>
</column>
<column>
<property name="text">
<string>Avatar</string>
</property>
</column>
<column>
<property name="text">
<string>Status</string>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</column>
<column>
@ -138,15 +122,37 @@
<string>Hide Offline Friends</string>
</property>
</action>
<action name="actionHideState">
<action name="actionSortByName">
<property name="checkable">
<bool>true</bool>
</property>
<property name="enabled">
<bool>false</bool>
<property name="text">
<string>Name</string>
</property>
<property name="toolTip">
<string>Sort by Name</string>
</property>
</action>
<action name="actionSortByState">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Hide State</string>
<string>State</string>
</property>
<property name="toolTip">
<string>Sort by State</string>
</property>
</action>
<action name="actionShowState">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Stow State</string>
</property>
<property name="toolTip">
<string>Show State</string>
</property>
</action>
<action name="actionShowGroups">

View File

@ -29,7 +29,8 @@
RSTreeWidget::RSTreeWidget(QWidget *parent) : QTreeWidget(parent)
{
mColumnCustomizable = false;
mEnableColumnCustomize = false;
mSettingsVersion = 0; // disabled
}
void RSTreeWidget::setPlaceholderText(const QString &text)
@ -117,32 +118,45 @@ bool RSTreeWidget::filterItem(QTreeWidgetItem *item, int filterColumn, const QSt
return (itemVisible || visibleChildCount);
}
void RSTreeWidget::setSettingsVersion(qint32 version)
{
mSettingsVersion = version;
}
void RSTreeWidget::processSettings(bool load)
{
if (load) {
// load settings
// Load settings
// state of tree widget
// State of tree widget
if (mSettingsVersion == 0 || Settings->value(QString("%1Version").arg(objectName())) == mSettingsVersion) {
// Compare version, because Qt can crash in restoreState after column changes
header()->restoreState(Settings->value(objectName()).toByteArray());
}
} else {
// save settings
// Save settings
// state of tree widget
Settings->setValue(objectName(), header()->saveState());
// Save version
if (mSettingsVersion) {
Settings->setValue(QString("%1Version").arg(objectName()), mSettingsVersion);
}
}
}
void RSTreeWidget::setColumnCustomizable(bool customizable)
void RSTreeWidget::enableColumnCustomize(bool customizable)
{
if (customizable == mColumnCustomizable) {
if (customizable == mEnableColumnCustomize) {
return;
}
mColumnCustomizable = customizable;
mEnableColumnCustomize = customizable;
QHeaderView *h = header();
if (mColumnCustomizable) {
if (mEnableColumnCustomize) {
h->setContextMenuPolicy(Qt::CustomContextMenu);
connect(h, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(headerContextMenuRequested(QPoint)));
} else {
@ -151,9 +165,14 @@ void RSTreeWidget::setColumnCustomizable(bool customizable)
}
}
void RSTreeWidget::setColumnCustomizable(int column, bool customizable)
{
mColumnCustomizable[column] = customizable;
}
void RSTreeWidget::headerContextMenuRequested(const QPoint &pos)
{
if (!mColumnCustomizable) {
if (!mEnableColumnCustomize) {
return;
}
@ -162,6 +181,10 @@ void RSTreeWidget::headerContextMenuRequested(const QPoint &pos)
QTreeWidgetItem *item = headerItem();
int columnCount = item->columnCount();
for (int column = 0; column < columnCount; ++column) {
QMap<int, bool>::const_iterator it = mColumnCustomizable.find(column);
if (it != mColumnCustomizable.end() && *it == false) {
continue;
}
QAction *action = contextMenu.addAction(QIcon(), item->text(column), this, SLOT(columnVisible()));
action->setCheckable(true);
action->setData(column);

View File

@ -37,9 +37,11 @@ public:
void filterItems(int filterColumn, const QString &text);
void setSettingsVersion(qint32 version);
void processSettings(bool load);
void setColumnCustomizable(bool customizable);
void enableColumnCustomize(bool customizable);
void setColumnCustomizable(int column, bool customizable);
signals:
void signalMouseMiddleButtonClicked(QTreeWidgetItem *item);
@ -58,7 +60,9 @@ protected:
private:
QString mPlaceholderText;
bool mColumnCustomizable;
bool mEnableColumnCustomize;
quint32 mSettingsVersion;
QMap<int, bool> mColumnCustomizable;
};
#endif

View File

@ -86,15 +86,15 @@ const char *StatusDefs::imageStatus(unsigned int status)
{
switch (status) {
case RS_STATUS_OFFLINE:
return ":/images/status/user-offline.png";
return ":/icons/user-offline_64.png";
case RS_STATUS_AWAY:
return ":/images/status/user-away.png";
return ":/icons/user-away_64.png";
case RS_STATUS_BUSY:
return ":/images/status/user-busy.png";
return ":/icons/user-busy_64.png";
case RS_STATUS_ONLINE:
return ":/images/status/user-online.png";
return ":/icons/user-online_64.png";
case RS_STATUS_INACTIVE:
return ":/images/status/user-away-extended.png";
return ":/icons/user-away-extended_64.png";
}
std::cerr << "StatusDefs::imageUser: Unknown status requested " << status;

View File

@ -55,5 +55,10 @@
<file>icons/tile_downloaded_48.png</file>
<file>icons/tile_downloading_48.png</file>
<file>icons/tile_inactive_48.png</file>
<file>icons/user-away_64.png</file>
<file>icons/user-away-extended_64.png</file>
<file>icons/user-busy_64.png</file>
<file>icons/user-offline_64.png</file>
<file>icons/user-online_64.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -60,10 +60,7 @@
<file>images/btn_green.png</file>
<file>images/btn_green_hover.png</file>
<file>images/btn_green_pressed.png</file>
<file>images/connect_established.png</file>
<file>images/connect_established_low.png</file>
<file>images/connect_creating.png</file>
<file>images/connect_no.png</file>
<file>images/dht16.png</file>
<file>images/dht32.png</file>
<file>images/edit-clear-history.png</file>
@ -424,7 +421,6 @@
<file>images/replymail-pressed.png</file>
<file>images/replymail24.png</file>
<file>images/replymailall24-hover.png</file>
<file>images/reload24.png</file>
<file>images/reset.png</file>
<file>images/resume.png</file>
<file>images/security-high-16.png</file>
@ -694,11 +690,6 @@
<file>images/tags/dev-translator.png</file>
<file>images/tags/dev-patcher.png</file>
<file>images/tags/developer.png</file>
<file>images/status/user-online.png</file>
<file>images/status/user-offline.png</file>
<file>images/status/user-busy.png</file>
<file>images/status/user-away-extended.png</file>
<file>images/status/user-away.png</file>
<file>images/circles/circles_32.png</file>
<file>images/circles/circles_64.png</file>
<file>images/newsfeed/news-feed-32.png</file>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 818 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 856 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB