mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-01-22 21:31:07 -05:00
403 lines
10 KiB
C++
403 lines
10 KiB
C++
/****************************************************************
|
|
*
|
|
* RetroShare is distributed under the following license:
|
|
*
|
|
* Copyright (C) 2011, RetroShare Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
****************************************************************/
|
|
|
|
#include <QMessageBox>
|
|
#include <QCloseEvent>
|
|
#include <QMenu>
|
|
#include <QWidgetAction>
|
|
|
|
#include "ChatDialog.h"
|
|
#include "gui/common/PeerDefs.h"
|
|
#include "PopupChatDialog.h"
|
|
#include "PopupDistantChatDialog.h"
|
|
#include "ChatLobbyDialog.h"
|
|
#include "PopupChatWindow.h"
|
|
#include "gui/settings/rsharesettings.h"
|
|
#include "gui/SoundManager.h"
|
|
|
|
#include <retroshare/rsiface.h>
|
|
#include <retroshare/rsnotify.h>
|
|
#include <retroshare/rspeers.h>
|
|
|
|
static std::map<ChatId, ChatDialog*> chatDialogsList;
|
|
|
|
ChatDialog::ChatDialog(QWidget *parent, Qt::WindowFlags flags) :
|
|
QWidget(parent, flags)
|
|
{
|
|
setAttribute(Qt::WA_DeleteOnClose, true);
|
|
}
|
|
|
|
ChatDialog::~ChatDialog()
|
|
{
|
|
std::map<ChatId, ChatDialog *>::iterator it;
|
|
if (chatDialogsList.end() != (it = chatDialogsList.find(mChatId))) {
|
|
chatDialogsList.erase(it);
|
|
}
|
|
}
|
|
|
|
void ChatDialog::closeEvent(QCloseEvent *event)
|
|
{
|
|
if (!canClose()) {
|
|
event->ignore();
|
|
return;
|
|
}
|
|
emit dialogClose(this);
|
|
}
|
|
|
|
void ChatDialog::init(const ChatId &id, const QString &title)
|
|
{
|
|
mChatId = id;
|
|
ChatWidget *cw = getChatWidget();
|
|
if (cw) {
|
|
cw->init(id, title);
|
|
|
|
connect(cw, SIGNAL(infoChanged(ChatWidget*)), this, SLOT(chatInfoChanged(ChatWidget*)));
|
|
connect(cw, SIGNAL(newMessage(ChatWidget*)), this, SLOT(chatNewMessage(ChatWidget*)));
|
|
}
|
|
}
|
|
|
|
/*static*/ ChatDialog* ChatDialog::getExistingChat(ChatId id)
|
|
{
|
|
std::map<ChatId, ChatDialog*>::iterator it;
|
|
if (chatDialogsList.end() != (it = chatDialogsList.find(id))) {
|
|
/* exists already */
|
|
return it->second;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*static*/ ChatDialog* ChatDialog::getChat(ChatId id, uint chatflags)
|
|
{
|
|
if(id.isBroadcast() || id.isNotSet())
|
|
return NULL; // broadcast is not handled by a chat dialog
|
|
|
|
/* see if it already exists */
|
|
ChatDialog *cd = getExistingChat(id);
|
|
|
|
if (cd == NULL) {
|
|
|
|
if(id.isDistantChatId())
|
|
chatflags = RS_CHAT_OPEN | RS_CHAT_FOCUS; // force open for distant chat
|
|
|
|
if (chatflags & RS_CHAT_OPEN) {
|
|
if (id.isLobbyId()) {
|
|
ChatLobbyDialog* cld = new ChatLobbyDialog(id.toLobbyId());
|
|
cld->init(ChatId(), "");
|
|
cd = cld;
|
|
}
|
|
else if(id.isDistantChatId())
|
|
{
|
|
PopupDistantChatDialog* pdcd = new PopupDistantChatDialog(id.toDistantChatId());
|
|
|
|
pdcd->init(id, "");
|
|
cd = pdcd;
|
|
}
|
|
else
|
|
{
|
|
RsPeerDetails sslDetails;
|
|
if (rsPeers->getPeerDetails(id.toPeerId(), sslDetails)) {
|
|
PopupChatDialog* pcd = new PopupChatDialog();
|
|
pcd->init(id, PeerDefs::nameWithLocation(sslDetails));
|
|
cd = pcd;
|
|
}
|
|
}
|
|
if(cd)
|
|
chatDialogsList[id] = cd;
|
|
}
|
|
}
|
|
|
|
if (cd == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
cd->showDialog(chatflags);
|
|
|
|
return cd;
|
|
}
|
|
|
|
/*static*/ void ChatDialog::cleanupChat()
|
|
{
|
|
PopupChatWindow::cleanup();
|
|
|
|
/* ChatDialog destuctor removes the entry from the map */
|
|
std::list<ChatDialog*> list;
|
|
|
|
std::map<ChatId, ChatDialog*>::iterator it;
|
|
for (it = chatDialogsList.begin(); it != chatDialogsList.end(); ++it) {
|
|
if (it->second) {
|
|
list.push_back(it->second);
|
|
}
|
|
}
|
|
|
|
chatDialogsList.clear();
|
|
|
|
std::list<ChatDialog*>::iterator it1;
|
|
for (it1 = list.begin(); it1 != list.end(); ++it1) {
|
|
delete (*it1);
|
|
}
|
|
}
|
|
|
|
/*static*/ void ChatDialog::closeChat(const ChatId &chat_id)
|
|
{
|
|
ChatDialog *chatDialog = getExistingChat(chat_id);
|
|
|
|
if (chatDialog) {
|
|
//delete chatDialog; // ChatDialog removes itself from the map
|
|
chatDialog->deleteLater();
|
|
}
|
|
}
|
|
|
|
/*static*/ void ChatDialog::chatMessageReceived(ChatMessage msg)
|
|
{
|
|
if(msg.chat_id.isBroadcast())
|
|
return; // broadcast is not handled by a chat dialog
|
|
|
|
if(msg.incoming && (msg.chat_id.isPeerId() || msg.chat_id.isDistantChatId()))
|
|
// play sound when recv a message
|
|
SoundManager::play(SOUND_NEW_CHAT_MESSAGE);
|
|
|
|
ChatDialog *cd = getChat(msg.chat_id, Settings->getChatFlags());
|
|
if(cd)
|
|
cd->addChatMsg(msg);
|
|
else
|
|
std::cerr << "ChatDialog::chatMessageReceived(): no ChatDialog for this message. Ignoring Message: " << msg.msg << std::endl;
|
|
}
|
|
|
|
/*static*/ void ChatDialog::chatFriend(const ChatId &peerId, const bool forceFocus)
|
|
{
|
|
getChat(peerId, forceFocus ? RS_CHAT_OPEN | RS_CHAT_FOCUS : RS_CHAT_OPEN);
|
|
|
|
// below is the old code witch does lots of error checking.
|
|
// because there are many different chat types, there are also different ways to check if the id is valid
|
|
// i think the chatservice should offer a method bool isChatAvailable(ChatId)
|
|
/*
|
|
if (peerId.isNull()){
|
|
return;
|
|
}
|
|
|
|
uint32_t distant_peer_status ;
|
|
|
|
if(rsMsgs->getDistantChatStatus(RsGxsId(peerId),distant_peer_status))
|
|
{
|
|
getChat(peerId, forceFocus ? RS_CHAT_OPEN | RS_CHAT_FOCUS : RS_CHAT_OPEN ); // use own flags
|
|
return ;
|
|
}
|
|
|
|
ChatLobbyId lid;
|
|
if (rsMsgs->isLobbyId(peerId, lid)) {
|
|
getChat(peerId, (forceFocus ? (RS_CHAT_OPEN | RS_CHAT_FOCUS) : RS_CHAT_OPEN));
|
|
}
|
|
|
|
RsPeerDetails detail;
|
|
if (!rsPeers->getPeerDetails(peerId, detail))
|
|
return;
|
|
|
|
if (detail.isOnlyGPGdetail) {
|
|
// Should not happen
|
|
//chatFriend(detail.gpg_id, forceFocus);
|
|
return;
|
|
}
|
|
|
|
getChat(peerId, forceFocus ? RS_CHAT_OPEN | RS_CHAT_FOCUS : RS_CHAT_OPEN);
|
|
*/
|
|
}
|
|
|
|
/*static*/ void ChatDialog::chatFriend(const RsPgpId &gpgId, const bool forceFocus)
|
|
{
|
|
if (gpgId.isNull()){
|
|
return;
|
|
}
|
|
|
|
RsPeerDetails detail;
|
|
if (!rsPeers->getGPGDetails(gpgId, detail))
|
|
return;
|
|
|
|
if (!detail.isOnlyGPGdetail) {
|
|
return;
|
|
}
|
|
|
|
//let's get the ssl child details
|
|
std::list<RsPeerId> sslIds;
|
|
rsPeers->getAssociatedSSLIds(detail.gpg_id, sslIds);
|
|
|
|
if (sslIds.size() == 1) {
|
|
// chat with the one ssl id (online or offline)
|
|
chatFriend(ChatId(sslIds.front()), forceFocus);
|
|
return;
|
|
}
|
|
|
|
// more than one ssl ids available, check for online
|
|
std::list<RsPeerId> onlineIds;
|
|
for (std::list<RsPeerId>::iterator it = sslIds.begin(); it != sslIds.end(); ++it) {
|
|
if (rsPeers->isOnline(*it)) {
|
|
onlineIds.push_back(*it);
|
|
}
|
|
}
|
|
|
|
if (onlineIds.size() == 1) {
|
|
// chat with the online ssl id
|
|
chatFriend(ChatId(onlineIds.front()), forceFocus);
|
|
return;
|
|
}
|
|
|
|
// show menu with online locations
|
|
QMenu menu;
|
|
QLabel* label = new QLabel("<strong>Select one of your friends locations to chat with</strong>");
|
|
QWidgetAction *widgetAction = new QWidgetAction(&menu);
|
|
widgetAction->setDefaultWidget(label);
|
|
menu.addAction(widgetAction);
|
|
QObject cleanupchildren;
|
|
for(std::list<RsPeerId>::iterator it = onlineIds.begin(); it != onlineIds.end(); ++it)
|
|
{
|
|
RsPeerDetails detail;
|
|
rsPeers->getPeerDetails(*it, detail);
|
|
menu.addAction(QString::fromUtf8(detail.location.c_str()), new ChatFriendMethod(&cleanupchildren, *it), SLOT(chatFriend()));
|
|
}
|
|
menu.exec(QCursor::pos());
|
|
}
|
|
|
|
void ChatDialog::addToParent(QWidget *newParent)
|
|
{
|
|
ChatWidget *cw = getChatWidget();
|
|
if (cw) {
|
|
cw->addToParent(newParent);
|
|
}
|
|
}
|
|
|
|
void ChatDialog::removeFromParent(QWidget *oldParent)
|
|
{
|
|
ChatWidget *cw = getChatWidget();
|
|
if (cw) {
|
|
cw->removeFromParent(oldParent);
|
|
}
|
|
}
|
|
|
|
bool ChatDialog::isTyping()
|
|
{
|
|
ChatWidget *cw = getChatWidget();
|
|
if (cw) {
|
|
return cw->isTyping();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ChatDialog::hasNewMessages()
|
|
{
|
|
ChatWidget *cw = getChatWidget();
|
|
if (cw) {
|
|
return cw->hasNewMessages();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
QString ChatDialog::getPeerName(const ChatId& id) const
|
|
{
|
|
if(id.isPeerId())
|
|
return QString::fromUtf8(rsPeers->getPeerName(id.toPeerId()).c_str()) ;
|
|
else
|
|
return "ChatDialog::getPeerName(): invalid id type passed (RsPeerId is required). This is a bug.";
|
|
}
|
|
|
|
QString ChatDialog::getOwnName() const
|
|
{
|
|
if(mChatId.isPeerId())
|
|
return QString::fromUtf8(rsPeers->getPeerName(rsPeers->getOwnId()).c_str());
|
|
else
|
|
return "ChatDialog::getOwnName(): invalid id type passed (RsPeerId is required). This is a bug.";
|
|
}
|
|
|
|
void ChatDialog::setPeerStatus(uint32_t status)
|
|
{
|
|
ChatWidget *cw = getChatWidget();
|
|
if (cw)
|
|
{
|
|
// convert to virtual peer id
|
|
// this is only required for private and distant chat,
|
|
// because lobby and broadcast does not have a status
|
|
RsPeerId vpid;
|
|
if(mChatId.isPeerId())
|
|
vpid = mChatId.toPeerId();
|
|
if(mChatId.isDistantChatId())
|
|
vpid = RsPeerId(mChatId.toDistantChatId());
|
|
cw->updateStatus(QString::fromStdString(vpid.toStdString()), status);
|
|
}
|
|
}
|
|
int ChatDialog::getPeerStatus()
|
|
{
|
|
ChatWidget *cw = getChatWidget();
|
|
if (cw) {
|
|
return cw->getPeerStatus();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
QString ChatDialog::getTitle()
|
|
{
|
|
ChatWidget *cw = getChatWidget();
|
|
if (cw) {
|
|
return cw->getTitle();
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
void ChatDialog::focusDialog()
|
|
{
|
|
ChatWidget *cw = getChatWidget();
|
|
if (cw) {
|
|
cw->focusDialog();
|
|
}
|
|
}
|
|
|
|
bool ChatDialog::setStyle()
|
|
{
|
|
ChatWidget *cw = getChatWidget();
|
|
if (cw) {
|
|
return cw->setStyle();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
const RSStyle *ChatDialog::getStyle()
|
|
{
|
|
ChatWidget *cw = getChatWidget();
|
|
if (cw) {
|
|
return cw->getStyle();
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void ChatDialog::chatInfoChanged(ChatWidget*)
|
|
{
|
|
emit infoChanged(this);
|
|
}
|
|
|
|
void ChatDialog::chatNewMessage(ChatWidget*)
|
|
{
|
|
emit newMessage(this);
|
|
}
|