/**************************************************************** * * 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 #include #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 #include #include #include static std::map chatDialogs; ChatDialog::ChatDialog(QWidget *parent, Qt::WFlags flags) : QWidget(parent, flags) { setAttribute(Qt::WA_DeleteOnClose, true); } ChatDialog::~ChatDialog() { std::map::iterator it; if (chatDialogs.end() != (it = chatDialogs.find(getPeerId()))) { chatDialogs.erase(it); } } void ChatDialog::closeEvent(QCloseEvent *event) { if (!canClose()) { event->ignore(); return; } emit dialogClose(this); } void ChatDialog::init(const std::string &peerId, const QString &title) { this->peerId = peerId; ChatWidget *cw = getChatWidget(); if (cw) { cw->init(peerId, title); connect(cw, SIGNAL(infoChanged(ChatWidget*)), this, SLOT(chatInfoChanged(ChatWidget*))); connect(cw, SIGNAL(newMessage(ChatWidget*)), this, SLOT(chatNewMessage(ChatWidget*))); } } /*static*/ ChatDialog *ChatDialog::getExistingChat(const std::string &peerId) { std::map::iterator it; if (chatDialogs.end() != (it = chatDialogs.find(peerId))) { /* exists already */ return it->second; } return NULL; } /*static*/ ChatDialog *ChatDialog::getChat(const std::string &peerId, uint chatflags) { /* see if it already exists */ ChatDialog *cd = getExistingChat(peerId); if (cd == NULL) { ChatLobbyId lobby_id = 0; if (rsMsgs->isLobbyId(peerId, lobby_id)) { chatflags = RS_CHAT_OPEN | RS_CHAT_FOCUS; // use own flags } uint32_t distant_peer_status ; std::string distant_chat_pgp_id ; if(rsMsgs->getDistantChatStatus(peerId,distant_peer_status,distant_chat_pgp_id)) chatflags = RS_CHAT_OPEN | RS_CHAT_FOCUS; // use own flags if (chatflags & RS_CHAT_OPEN) { if (lobby_id) { std::list linfos; rsMsgs->getChatLobbyList(linfos); for (std::list::const_iterator it(linfos.begin()); it != linfos.end(); ++it) { if ((*it).lobby_id == lobby_id) { cd = new ChatLobbyDialog(lobby_id); chatDialogs[peerId] = cd; cd->init(peerId, QString::fromUtf8((*it).lobby_name.c_str())); } } } else if(distant_peer_status > 0) { cd = new PopupDistantChatDialog(); chatDialogs[peerId] = cd; std::string peer_name = rsPeers->getGPGName(distant_chat_pgp_id) ; cd->init(peerId, tr("Talking to ")+QString::fromStdString(peer_name)+" (PGP id="+QString::fromStdString(distant_chat_pgp_id)+")") ; } else { RsPeerDetails sslDetails; if (rsPeers->getPeerDetails(peerId, sslDetails)) { for(int i=0;inbPlugins();++i) if(rsPlugins->plugin(i) != NULL && (cd = rsPlugins->plugin(i)->qt_allocate_new_popup_chat_dialog()) != NULL) break ; if(cd == NULL) cd = new PopupChatDialog(); chatDialogs[peerId] = cd; cd->init(peerId, PeerDefs::nameWithLocation(sslDetails)); } } } } if (cd == NULL) { return NULL; } cd->insertChatMsgs(); cd->showDialog(chatflags); return cd; } /*static*/ void ChatDialog::cleanupChat() { PopupChatWindow::cleanup(); /* ChatDialog destuctor removes the entry from the map */ std::list list; std::map::iterator it; for (it = chatDialogs.begin(); it != chatDialogs.end(); it++) { if (it->second) { list.push_back(it->second); } } chatDialogs.clear(); std::list::iterator it1; for (it1 = list.begin(); it1 != list.end(); it1++) { delete (*it1); } } /*static*/ void ChatDialog::chatChanged(int list, int type) { if (list == NOTIFY_LIST_PRIVATE_INCOMING_CHAT && type == NOTIFY_TYPE_ADD) { // play sound when recv a message soundManager->play(SOUND_NEW_CHAT_MESSAGE); std::list ids; if (rsMsgs->getPrivateChatQueueIds(true, ids)) { uint chatflags = Settings->getChatFlags(); std::list::iterator id; for (id = ids.begin(); id != ids.end(); id++) { ChatDialog *cd = getChat(*id, chatflags); if (cd) { cd->insertChatMsgs(); } } } } /* now notify all open priavate chat windows */ std::map::iterator it; for (it = chatDialogs.begin (); it != chatDialogs.end(); it++) { if (it->second) { it->second->onChatChanged(list, type); } } } /*static*/ void ChatDialog::closeChat(const std::string& peerId) { ChatDialog *chatDialog = getExistingChat(peerId); if (chatDialog) { delete(chatDialog); } } /*static*/ void ChatDialog::chatFriend(const std::string &peerId) { if (peerId.empty()){ return; } std::string distant_chat_pgp_id ; uint32_t distant_peer_status ; if(rsMsgs->getDistantChatStatus(peerId,distant_peer_status,distant_chat_pgp_id)) { getChat(peerId,RS_CHAT_OPEN | RS_CHAT_FOCUS); // use own flags return ; } ChatLobbyId lid; if (rsMsgs->isLobbyId(peerId, lid)) { getChat(peerId, RS_CHAT_OPEN | RS_CHAT_FOCUS); return; } RsPeerDetails detail; if (!rsPeers->getPeerDetails(peerId, detail)) return; if (detail.isOnlyGPGdetail) { std::list onlineIds; //let's get the ssl child details std::list sslIds; rsPeers->getAssociatedSSLIds(detail.gpg_id, sslIds); if (sslIds.size() == 1) { // chat with the one ssl id (online or offline) getChat(sslIds.front(), RS_CHAT_OPEN | RS_CHAT_FOCUS); return; } // more than one ssl ids available, check for online for (std::list::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 getChat(onlineIds.front(), RS_CHAT_OPEN | RS_CHAT_FOCUS); return; } // more than one ssl ids online or all offline QMessageBox mb(QMessageBox::Warning, "RetroShare", tr("Your friend has more than one locations.\nPlease choose one of it to chat with."), QMessageBox::Ok); mb.setWindowIcon(QIcon(":/images/rstray3.png")); mb.exec(); } else { getChat(peerId, RS_CHAT_OPEN | RS_CHAT_FOCUS); } } 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; } void ChatDialog::setPeerStatus(uint32_t status) { ChatWidget *cw = getChatWidget(); if (cw) cw->updateStatus(QString::fromStdString(getPeerId()), 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); } void ChatDialog::insertChatMsgs() { std::string peerId = getPeerId(); std::list newchat; if (!rsMsgs->getPrivateChatQueue(true, peerId, newchat)) { return; } std::list::iterator it; for(it = newchat.begin(); it != newchat.end(); it++) { /* are they public? */ if ((it->chatflags & RS_CHAT_PRIVATE) == 0) { /* this should not happen */ continue; } addIncomingChatMsg(*it); } rsMsgs->clearPrivateChatQueue(true, peerId); }