mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-05-03 06:35:08 -04:00
Chat lobby:
- added new notifier to p3ChatService GUI: - list all public and private chat lobbies - added subscribe/unsubscribe - added new basic widget ChatTabWidget and use it in PopupChatWindow and ChatLobbyDialog - added a tabbed dialog for every subscribed chat lobby git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@4782 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
parent
fc949ce5d0
commit
6c626e180f
21 changed files with 934 additions and 420 deletions
|
@ -1,97 +1,377 @@
|
|||
#include <QTableWidget>
|
||||
#include <retroshare/rsmsgs.h>
|
||||
#include <QTreeWidget>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include "ChatLobbyWidget.h"
|
||||
#include "chat/CreateLobbyDialog.h"
|
||||
#include "common/RSTreeWidgetItem.h"
|
||||
#include "notifyqt.h"
|
||||
#include "chat/ChatLobbyDialog.h"
|
||||
|
||||
#define COL_LOBBY_NAME 0
|
||||
#define COL_LOBBY_ID 1
|
||||
#define COL_LOBBY_TYPE 2
|
||||
#define COL_LOBBY_STATE 3
|
||||
#define COL_LOBBY_COUNT 4
|
||||
#include "retroshare/rsmsgs.h"
|
||||
#include "retroshare/rspeers.h"
|
||||
#include "retroshare/rsnotify.h"
|
||||
|
||||
#define COLUMN_NAME 0
|
||||
#define COLUMN_USER_COUNT 1
|
||||
#define COLUMN_COUNT 2
|
||||
|
||||
#define COLUMN_DATA 0
|
||||
#define ROLE_SORT Qt::UserRole
|
||||
#define ROLE_ID Qt::UserRole + 1
|
||||
#define ROLE_SUBSCRIBED Qt::UserRole + 2
|
||||
|
||||
#define TYPE_FOLDER 0
|
||||
#define TYPE_LOBBY 1
|
||||
|
||||
#define IMAGE_CREATE ""
|
||||
#define IMAGE_PUBLIC ""
|
||||
#define IMAGE_PRIVATE ""
|
||||
#define IMAGE_SUBSCRIBE ""
|
||||
#define IMAGE_UNSUBSCRIBE ""
|
||||
|
||||
static ChatLobbyWidget *instance = NULL;
|
||||
|
||||
ChatLobbyWidget::ChatLobbyWidget(QWidget *parent, Qt::WFlags flags)
|
||||
: RsAutoUpdatePage(5000,parent)
|
||||
{
|
||||
setupUi(this) ;
|
||||
|
||||
QObject::connect(this,SIGNAL(cellDoubleClicked(int,int)),this,SLOT(doubleClickCell(int,int))) ;
|
||||
setupUi(this);
|
||||
|
||||
_lobby_table_TW->setColumnHidden(1,true) ;
|
||||
updateDisplay() ;
|
||||
if (instance == NULL) {
|
||||
instance = this;
|
||||
}
|
||||
|
||||
QObject::connect(NotifyQt::getInstance(), SIGNAL(lobbyListChanged()), SLOT(lobbyChanged()));
|
||||
QObject::connect(NotifyQt::getInstance(), SIGNAL(chatLobbyEvent(qulonglong,int,const QString&,const QString&)), this, SLOT(displayChatLobbyEvent(qulonglong,int,const QString&,const QString&)));
|
||||
QObject::connect(NotifyQt::getInstance(), SIGNAL(chatLobbyInviteReceived()), this, SLOT(readChatLobbyInvites()));
|
||||
|
||||
QObject::connect(lobbyTreeWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(lobbyTreeWidgetCostumPopupMenu()));
|
||||
QObject::connect(lobbyTreeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(itemDoubleClicked(QTreeWidgetItem*,int)));
|
||||
QObject::connect(lobbyTabWidget, SIGNAL(infoChanged()), this, SLOT(tabInfoChanged()));
|
||||
|
||||
compareRole = new RSTreeWidgetItemCompareRole;
|
||||
compareRole->setRole(COLUMN_NAME, ROLE_SORT);
|
||||
|
||||
lobbyTreeWidget->setColumnCount(COLUMN_COUNT);
|
||||
lobbyTreeWidget->sortItems(COLUMN_NAME, Qt::AscendingOrder);
|
||||
|
||||
QTreeWidgetItem *headerItem = lobbyTreeWidget->headerItem();
|
||||
headerItem->setText(COLUMN_NAME, tr("Name"));
|
||||
headerItem->setText(COLUMN_USER_COUNT, tr("Count"));
|
||||
headerItem->setTextAlignment(COLUMN_NAME, Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
headerItem->setTextAlignment(COLUMN_USER_COUNT, Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
|
||||
QHeaderView *header = lobbyTreeWidget->header();
|
||||
header->setResizeMode(COLUMN_NAME, QHeaderView::Interactive);
|
||||
header->setResizeMode(COLUMN_USER_COUNT, QHeaderView::Stretch);
|
||||
|
||||
lobbyTreeWidget->setColumnWidth(COLUMN_NAME, 200);
|
||||
lobbyTreeWidget->setColumnWidth(COLUMN_USER_COUNT, 50);
|
||||
|
||||
privateLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER);
|
||||
privateLobbyItem->setText(COLUMN_NAME, tr("Private Lobbies"));
|
||||
privateLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "1");
|
||||
lobbyTreeWidget->insertTopLevelItem(0, privateLobbyItem);
|
||||
|
||||
publicLobbyItem = new RSTreeWidgetItem(compareRole, TYPE_FOLDER);
|
||||
publicLobbyItem->setText(COLUMN_NAME, tr("Public Lobbies"));
|
||||
publicLobbyItem->setData(COLUMN_NAME, ROLE_SORT, "2");
|
||||
lobbyTreeWidget->insertTopLevelItem(1, publicLobbyItem);
|
||||
|
||||
lobbyTreeWidget->expandAll();
|
||||
|
||||
lobbyChanged();
|
||||
}
|
||||
|
||||
ChatLobbyWidget::~ChatLobbyWidget()
|
||||
{
|
||||
if (this == instance) {
|
||||
instance = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ ChatTabWidget *ChatLobbyWidget::getTabWidget()
|
||||
{
|
||||
return instance ? instance->lobbyTabWidget : NULL;
|
||||
}
|
||||
|
||||
void ChatLobbyWidget::lobbyTreeWidgetCostumPopupMenu()
|
||||
{
|
||||
QMenu contextMnu(this);
|
||||
|
||||
contextMnu.addAction(QIcon(IMAGE_CREATE), tr("Create chat lobby"), this, SLOT(createChatLobby()));
|
||||
|
||||
QTreeWidgetItem *item = lobbyTreeWidget->currentItem();
|
||||
if (item && item->type() == TYPE_LOBBY) {
|
||||
if (item->data(COLUMN_DATA, ROLE_SUBSCRIBED).toBool()) {
|
||||
contextMnu.addAction(QIcon(IMAGE_UNSUBSCRIBE), tr("Unsubscribe"), this, SLOT(unsubscribeItem()));
|
||||
} else {
|
||||
contextMnu.addAction(QIcon(IMAGE_SUBSCRIBE), tr("Subscribe"), this, SLOT(subscribeItem()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contextMnu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void ChatLobbyWidget::lobbyChanged()
|
||||
{
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
static void updateItem(QTreeWidgetItem *item, ChatLobbyId id, const std::string &name, int count, bool subscribed)
|
||||
{
|
||||
item->setText(COLUMN_NAME, QString::fromUtf8(name.c_str()));
|
||||
item->setData(COLUMN_NAME, ROLE_SORT, QString::fromUtf8(name.c_str()));
|
||||
|
||||
item->setText(COLUMN_USER_COUNT, QString::number(count));
|
||||
|
||||
item->setData(COLUMN_DATA, ROLE_ID, id);
|
||||
item->setData(COLUMN_DATA, ROLE_SUBSCRIBED, subscribed);
|
||||
|
||||
for (int column = 0; column < COLUMN_COUNT; ++column) {
|
||||
item->setTextColor(column, subscribed ? QColor() : QColor(Qt::gray));
|
||||
}
|
||||
}
|
||||
|
||||
void ChatLobbyWidget::updateDisplay()
|
||||
{
|
||||
std::cerr << "updating chat lobby display!" << std::endl;
|
||||
std::vector<PublicChatLobbyRecord> public_lobbies ;
|
||||
rsMsgs->getListOfNearbyChatLobbies(public_lobbies) ;
|
||||
std::vector<PublicChatLobbyRecord> publicLobbies;
|
||||
rsMsgs->getListOfNearbyChatLobbies(publicLobbies);
|
||||
|
||||
std::list<ChatLobbyInfo> linfos ;
|
||||
rsMsgs->getChatLobbyList(linfos) ;
|
||||
std::list<ChatLobbyInfo> lobbies;
|
||||
rsMsgs->getChatLobbyList(lobbies);
|
||||
|
||||
std::cerr << "got " << public_lobbies.size() << " public lobbies, and " << linfos.size() << " private lobbies." << std::endl;
|
||||
std::cerr << "got " << publicLobbies.size() << " public lobbies, and " << lobbies.size() << " private lobbies." << std::endl;
|
||||
|
||||
// now, do a nice display of public lobbies.
|
||||
// now, do a nice display of lobbies
|
||||
|
||||
_lobby_table_TW->clear() ;
|
||||
int n=0 ;
|
||||
std::string vpid;
|
||||
uint32_t i;
|
||||
uint32_t size = publicLobbies.size();
|
||||
std::list<ChatLobbyInfo>::const_iterator lobbyIt;
|
||||
|
||||
QList<QTreeWidgetItem*> list ;
|
||||
std::string vpid ;
|
||||
for(uint32_t i=0;i<public_lobbies.size();++i,++n)
|
||||
if(!rsMsgs->getVirtualPeerId(public_lobbies[i].lobby_id,vpid)) // only display unsubscribed lobbies
|
||||
{
|
||||
std::cerr << "adding " << public_lobbies[i].lobby_name << " #" << std::hex << public_lobbies[i].lobby_id << std::dec << " public " << public_lobbies[i].total_number_of_peers << " peers." << std::endl;
|
||||
// remove not existing public lobbies
|
||||
int childCount = publicLobbyItem->childCount();
|
||||
int childIndex = 0;
|
||||
while (childIndex < childCount) {
|
||||
QTreeWidgetItem *itemLoop = publicLobbyItem->child(childIndex);
|
||||
if (itemLoop->type() == TYPE_LOBBY) {
|
||||
// check for public lobby
|
||||
for (i = 0; i < size; ++i) {
|
||||
if (itemLoop->data(COLUMN_DATA, ROLE_ID).toULongLong() == publicLobbies[i].lobby_id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QStringList strl ;
|
||||
if (i >= size) {
|
||||
// check for private lobby with public level
|
||||
for (lobbyIt = lobbies.begin(); lobbyIt != lobbies.end(); ++lobbyIt) {
|
||||
if (lobbyIt->lobby_privacy_level == RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC &&
|
||||
itemLoop->data(COLUMN_DATA, ROLE_ID).toULongLong() == lobbyIt->lobby_id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
strl.push_back(QString::fromUtf8(public_lobbies[i].lobby_name.c_str())) ;
|
||||
strl.push_back(QString::number(public_lobbies[i].lobby_id,16)) ;
|
||||
strl.push_back(tr("Public")) ;
|
||||
strl.push_back(QString::number(public_lobbies[i].total_number_of_peers)) ;
|
||||
strl.push_back("") ;
|
||||
if (lobbyIt == lobbies.end()) {
|
||||
delete(publicLobbyItem->takeChild(publicLobbyItem->indexOfChild(itemLoop)));
|
||||
childCount = publicLobbyItem->childCount();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
childIndex++;
|
||||
}
|
||||
|
||||
list.push_back(new QTreeWidgetItem(strl)) ;
|
||||
for (i = 0; i < size; ++i) {
|
||||
const PublicChatLobbyRecord &lobby = publicLobbies[i];
|
||||
|
||||
std::cerr << "adding " << lobby.lobby_name << " #" << std::hex << lobby.lobby_id << std::dec << " public " << lobby.total_number_of_peers << " peers." << std::endl;
|
||||
|
||||
QTreeWidgetItem *item = NULL;
|
||||
|
||||
// search existing item
|
||||
childCount = publicLobbyItem->childCount();
|
||||
for (childIndex = 0; childIndex < childCount; childIndex++) {
|
||||
QTreeWidgetItem *itemLoop = publicLobbyItem->child(childIndex);
|
||||
if (itemLoop->type() == TYPE_LOBBY && itemLoop->data(COLUMN_DATA, ROLE_ID).toULongLong() == lobby.lobby_id) {
|
||||
item = itemLoop;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for(std::list<ChatLobbyInfo>::const_iterator it(linfos.begin());it!=linfos.end();++it,++n)
|
||||
{
|
||||
std::cerr << "adding " << (*it).lobby_name << " #" << std::hex << (*it).lobby_id << std::dec << " private " << (*it).nick_names.size() << " peers." << std::endl;
|
||||
if (item == NULL) {
|
||||
item = new RSTreeWidgetItem(compareRole, TYPE_LOBBY);
|
||||
publicLobbyItem->addChild(item);
|
||||
}
|
||||
|
||||
QStringList strl ;
|
||||
strl.push_back(QString::fromUtf8((*it).lobby_name.c_str())) ;
|
||||
strl.push_back(QString::number((*it).lobby_id,16)) ;
|
||||
item->setIcon(COLUMN_NAME, QIcon(IMAGE_PUBLIC));
|
||||
|
||||
if( (*it).lobby_privacy_level == RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC)
|
||||
strl.push_back(tr("Public")) ;
|
||||
else
|
||||
strl.push_back(tr("Private")) ;
|
||||
bool subscribed = false;
|
||||
if (rsMsgs->getVirtualPeerId(lobby.lobby_id, vpid)) {
|
||||
subscribed = true;
|
||||
}
|
||||
|
||||
strl.push_back(QString::number((*it).nick_names.size())) ;
|
||||
strl.push_back(tr("subscribed")) ;
|
||||
|
||||
list.push_back(new QTreeWidgetItem(strl)) ;
|
||||
updateItem(item, lobby.lobby_id, lobby.lobby_name, lobby.total_number_of_peers, subscribed);
|
||||
}
|
||||
|
||||
// remove not existing private lobbies
|
||||
childCount = privateLobbyItem->childCount();
|
||||
childIndex = 0;
|
||||
while (childIndex < childCount) {
|
||||
QTreeWidgetItem *itemLoop = privateLobbyItem->child(childIndex);
|
||||
if (itemLoop->type() == TYPE_LOBBY) {
|
||||
for (lobbyIt = lobbies.begin(); lobbyIt != lobbies.end(); ++lobbyIt) {
|
||||
if (lobbyIt->lobby_privacy_level == RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE &&
|
||||
itemLoop->data(COLUMN_DATA, ROLE_ID).toULongLong() == lobbyIt->lobby_id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lobbyIt == lobbies.end()) {
|
||||
delete(privateLobbyItem->takeChild(privateLobbyItem->indexOfChild(itemLoop)));
|
||||
childCount = privateLobbyItem->childCount();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
childIndex++;
|
||||
}
|
||||
|
||||
for (lobbyIt = lobbies.begin(); lobbyIt != lobbies.end(); ++lobbyIt) {
|
||||
const ChatLobbyInfo &lobby = *lobbyIt;
|
||||
|
||||
std::cerr << "adding " << lobby.lobby_name << " #" << std::hex << lobby.lobby_id << std::dec << " private " << lobby.nick_names.size() << " peers." << std::endl;
|
||||
|
||||
QTreeWidgetItem *itemParent;
|
||||
if (lobby.lobby_privacy_level == RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC) {
|
||||
itemParent = publicLobbyItem;
|
||||
} else {
|
||||
itemParent = privateLobbyItem;
|
||||
}
|
||||
|
||||
QTreeWidgetItem *item = NULL;
|
||||
|
||||
// search existing item
|
||||
childCount = itemParent->childCount();
|
||||
for (childIndex = 0; childIndex < childCount; childIndex++) {
|
||||
QTreeWidgetItem *itemLoop = itemParent->child(childIndex);
|
||||
if (itemLoop->type() == TYPE_LOBBY && itemLoop->data(COLUMN_DATA, ROLE_ID).toULongLong() == lobby.lobby_id) {
|
||||
item = itemLoop;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (item == NULL) {
|
||||
item = new RSTreeWidgetItem(compareRole, TYPE_LOBBY);
|
||||
itemParent->addChild(item);
|
||||
}
|
||||
|
||||
if (lobby.lobby_privacy_level == RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC) {
|
||||
item->setIcon(COLUMN_NAME, QIcon(IMAGE_PUBLIC));
|
||||
} else {
|
||||
item->setIcon(COLUMN_NAME, QIcon(IMAGE_PRIVATE));
|
||||
}
|
||||
|
||||
updateItem(item, lobby.lobby_id, lobby.lobby_name, lobby.nick_names.size(), true);
|
||||
}
|
||||
|
||||
_lobby_table_TW->addTopLevelItems(list) ;
|
||||
}
|
||||
|
||||
void ChatLobbyWidget::doubleClickCell(int row,int col)
|
||||
void ChatLobbyWidget::createChatLobby()
|
||||
{
|
||||
// Each lobby can be joined directly, by calling
|
||||
std::list<std::string> friends;
|
||||
CreateLobbyDialog(friends).exec();
|
||||
}
|
||||
|
||||
void ChatLobbyWidget::subscribeItem()
|
||||
{
|
||||
QTreeWidgetItem *item = lobbyTreeWidget->currentItem();
|
||||
if (item == NULL && item->type() != TYPE_LOBBY) {
|
||||
return;
|
||||
}
|
||||
|
||||
ChatLobbyId id = item->data(COLUMN_DATA, ROLE_ID).toULongLong();
|
||||
if (rsMsgs->joinPublicChatLobby(id)) {
|
||||
std::string vpeer_id;
|
||||
if (rsMsgs->getVirtualPeerId(id, vpeer_id)) {
|
||||
PopupChatDialog::chatFriend(vpeer_id) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChatLobbyWidget::unsubscribeItem()
|
||||
{
|
||||
QTreeWidgetItem *item = lobbyTreeWidget->currentItem();
|
||||
if (item == NULL && item->type() != TYPE_LOBBY) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ChatLobbyId id = item->data(COLUMN_DATA, ROLE_ID).toULongLong();
|
||||
|
||||
std::string vpeer_id;
|
||||
if (rsMsgs->getVirtualPeerId(id, vpeer_id)) {
|
||||
PopupChatDialog::closeChat(vpeer_id);
|
||||
}
|
||||
|
||||
rsMsgs->unsubscribeChatLobby(id);
|
||||
}
|
||||
|
||||
void ChatLobbyWidget::itemDoubleClicked(QTreeWidgetItem *item, int column)
|
||||
{
|
||||
// Each lobby can be joined directly, by calling
|
||||
// rsMsgs->joinPublicLobby(chatLobbyId) ;
|
||||
|
||||
// e.g. fill a list of public lobbies
|
||||
|
||||
|
||||
// also maintain a list of active chat lobbies. Each active (subscribed) lobby has a lobby tab in the gui.
|
||||
// Each tab knows its lobby id and its virtual peer id (the one to send private chat messages to)
|
||||
//
|
||||
// One possibility is to convert ChatLobbyDialog to be used at a chat lobby tab.
|
||||
|
||||
|
||||
// then the lobby can be accessed using the virtual peer id through
|
||||
// rsMsgs->getVirtualPeerId(ChatLobbyId,std::string& virtual_peer_id)
|
||||
// rsMsgs->getVirtualPeerId(ChatLobbyId,std::string& virtual_peer_id)
|
||||
}
|
||||
|
||||
void ChatLobbyWidget::displayChatLobbyEvent(qulonglong lobby_id, int event_type, const QString& nickname, const QString& str)
|
||||
{
|
||||
std::cerr << "Received displayChatLobbyEvent()!" << std::endl;
|
||||
|
||||
std::string vpid;
|
||||
if (rsMsgs->getVirtualPeerId(lobby_id, vpid)) {
|
||||
if (ChatLobbyDialog *cld = dynamic_cast<ChatLobbyDialog*>(PopupChatDialog::getExistingInstance(vpid))) {
|
||||
cld->displayLobbyEvent(event_type, nickname, str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChatLobbyWidget::readChatLobbyInvites()
|
||||
{
|
||||
std::list<ChatLobbyInvite> invites;
|
||||
rsMsgs->getPendingChatLobbyInvites(invites);
|
||||
|
||||
for(std::list<ChatLobbyInvite>::const_iterator it(invites.begin());it!=invites.end();++it) {
|
||||
if (QMessageBox::Ok == QMessageBox::question(NULL, tr("Invitation to chat lobby"), QString::fromUtf8(rsPeers->getPeerName((*it).peer_id).c_str()) + QString(" invites you to chat lobby named ") + QString::fromUtf8((*it).lobby_name.c_str()), QMessageBox::Ok, QMessageBox::Ignore)) {
|
||||
std::cerr << "Accepting invite to lobby " << (*it).lobby_name << std::endl;
|
||||
|
||||
rsMsgs->acceptLobbyInvite((*it).lobby_id);
|
||||
|
||||
std::string vpid;
|
||||
if(rsMsgs->getVirtualPeerId((*it).lobby_id,vpid )) {
|
||||
PopupChatDialog::chatFriend(vpid);
|
||||
} else {
|
||||
std::cerr << "No lobby known with id 0x" << std::hex << (*it).lobby_id << std::dec << std::endl;
|
||||
}
|
||||
} else {
|
||||
rsMsgs->denyLobbyInvite((*it).lobby_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ChatLobbyWidget::tabInfoChanged()
|
||||
{
|
||||
emit infoChanged();
|
||||
}
|
||||
|
||||
void ChatLobbyWidget::getInfo(bool &isTyping, bool &hasNewMessage, QIcon *icon)
|
||||
{
|
||||
lobbyTabWidget->getInfo(isTyping, hasNewMessage, icon);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue