From 35c760570498fb691581c5128ad065d7a43c816e Mon Sep 17 00:00:00 2001 From: thunder2 Date: Tue, 17 Jan 2012 20:36:36 +0000 Subject: [PATCH] Extracted a new widget ChatWidget for the basic chat handling from the PopupChatDialog and use it in ChatLobbyDialog too. Added an own ui for the ChatLobbyDialog. Saved settings of the ChatLobbyDialog. Changed parameters of RsStatus interface from "std::string" to "const std::string&" Fixed german language. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@4806 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- libretroshare/src/retroshare/rsstatus.h | 4 +- libretroshare/src/rsserver/p3status.cc | 4 +- libretroshare/src/rsserver/p3status.h | 4 +- libretroshare/src/services/p3chatservice.cc | 5 +- libretroshare/src/services/p3statusservice.cc | 2 +- libretroshare/src/services/p3statusservice.h | 2 +- retroshare-gui/src/RetroShare.pro | 6 + retroshare-gui/src/gui/ChatLobbyWidget.cpp | 10 +- retroshare-gui/src/gui/ChatLobbyWidget.ui | 6 +- retroshare-gui/src/gui/FriendsDialog.cpp | 14 +- retroshare-gui/src/gui/MainWindow.cpp | 10 +- retroshare-gui/src/gui/NewsFeed.cpp | 4 +- retroshare-gui/src/gui/chat/ChatDialog.cpp | 351 ++++++ retroshare-gui/src/gui/chat/ChatDialog.h | 87 ++ .../src/gui/chat/ChatLobbyDialog.cpp | 172 +-- retroshare-gui/src/gui/chat/ChatLobbyDialog.h | 58 +- .../src/gui/chat/ChatLobbyDialog.ui | 182 +++ retroshare-gui/src/gui/chat/ChatTabWidget.cpp | 57 +- retroshare-gui/src/gui/chat/ChatTabWidget.h | 36 +- retroshare-gui/src/gui/chat/ChatWidget.cpp | 689 +++++++++++ retroshare-gui/src/gui/chat/ChatWidget.h | 143 +++ retroshare-gui/src/gui/chat/ChatWidget.ui | 794 ++++++++++++ .../src/gui/chat/CreateLobbyDialog.cpp | 189 ++- .../src/gui/chat/CreateLobbyDialog.h | 43 +- .../src/gui/chat/CreateLobbyDialog.ui | 10 +- .../src/gui/chat/PopupChatDialog.cpp | 1084 ++--------------- retroshare-gui/src/gui/chat/PopupChatDialog.h | 163 +-- .../src/gui/chat/PopupChatDialog.ui | 735 +---------- .../src/gui/chat/PopupChatWindow.cpp | 455 ++++--- retroshare-gui/src/gui/chat/PopupChatWindow.h | 65 +- retroshare-gui/src/gui/common/FriendList.cpp | 11 +- retroshare-gui/src/gui/common/HashBox.cpp | 2 +- .../src/gui/settings/RsharePeerSettings.cpp | 88 +- .../src/gui/settings/RsharePeerSettings.h | 7 +- .../src/gui/toaster/OnlineToaster.cpp | 4 +- retroshare-gui/src/lang/retroshare_de.qm | Bin 329625 -> 339167 bytes retroshare-gui/src/lang/retroshare_de.ts | 772 ++++++++++-- retroshare-gui/src/main.cpp | 4 +- 38 files changed, 3720 insertions(+), 2552 deletions(-) create mode 100644 retroshare-gui/src/gui/chat/ChatDialog.cpp create mode 100644 retroshare-gui/src/gui/chat/ChatDialog.h create mode 100644 retroshare-gui/src/gui/chat/ChatLobbyDialog.ui create mode 100644 retroshare-gui/src/gui/chat/ChatWidget.cpp create mode 100644 retroshare-gui/src/gui/chat/ChatWidget.h create mode 100644 retroshare-gui/src/gui/chat/ChatWidget.ui diff --git a/libretroshare/src/retroshare/rsstatus.h b/libretroshare/src/retroshare/rsstatus.h index 1ab703e52..6ebb9f469 100644 --- a/libretroshare/src/retroshare/rsstatus.h +++ b/libretroshare/src/retroshare/rsstatus.h @@ -88,7 +88,7 @@ class RsStatus * This retrieves the status info one peer * @param statusInfo is populated with client's peer's status */ - virtual bool getStatus(std::string &id, StatusInfo &statusInfo) = 0; + virtual bool getStatus(const std::string &id, StatusInfo &statusInfo) = 0; /** * send the client's status to his/her peers @@ -96,7 +96,7 @@ class RsStatus * @param status the status of the peers * @return will return false if status info does not belong to client */ - virtual bool sendStatus(std::string id, uint32_t status) = 0; + virtual bool sendStatus(const std::string &id, uint32_t status) = 0; }; diff --git a/libretroshare/src/rsserver/p3status.cc b/libretroshare/src/rsserver/p3status.cc index 150854c2c..7ec0d285a 100644 --- a/libretroshare/src/rsserver/p3status.cc +++ b/libretroshare/src/rsserver/p3status.cc @@ -47,12 +47,12 @@ bool p3Status::getStatusList(std::list& statusInfo){ return mStatusSrv->getStatusList(statusInfo); } -bool p3Status::getStatus(std::string &id, StatusInfo &statusInfo) +bool p3Status::getStatus(const std::string &id, StatusInfo &statusInfo) { return mStatusSrv->getStatus(id, statusInfo); } -bool p3Status::sendStatus(std::string id, uint32_t status){ +bool p3Status::sendStatus(const std::string &id, uint32_t status){ return mStatusSrv->sendStatus(id, status); } diff --git a/libretroshare/src/rsserver/p3status.h b/libretroshare/src/rsserver/p3status.h index 3a65e44a4..53584fa3f 100644 --- a/libretroshare/src/rsserver/p3status.h +++ b/libretroshare/src/rsserver/p3status.h @@ -45,8 +45,8 @@ public: virtual bool getOwnStatus(StatusInfo& statusInfo); virtual bool getStatusList(std::list& statusInfo); - virtual bool getStatus(std::string &id, StatusInfo &statusInfo); - virtual bool sendStatus(std::string id, uint32_t status); + virtual bool getStatus(const std::string &id, StatusInfo &statusInfo); + virtual bool sendStatus(const std::string &id, uint32_t status); private: diff --git a/libretroshare/src/services/p3chatservice.cc b/libretroshare/src/services/p3chatservice.cc index 49ea858e0..6c388875a 100644 --- a/libretroshare/src/services/p3chatservice.cc +++ b/libretroshare/src/services/p3chatservice.cc @@ -366,8 +366,9 @@ bool p3ChatService::isLobbyId(const std::string& id,ChatLobbyId& lobby_id) lobby_id = it->second ; return true ; } - else - return false ; + + lobby_id = 0; + return false ; } bool p3ChatService::sendPrivateChat(const std::string &id, const std::wstring &msg) diff --git a/libretroshare/src/services/p3statusservice.cc b/libretroshare/src/services/p3statusservice.cc index ae3419f46..85526efde 100644 --- a/libretroshare/src/services/p3statusservice.cc +++ b/libretroshare/src/services/p3statusservice.cc @@ -106,7 +106,7 @@ bool p3StatusService::getStatusList(std::list& statusInfo) return true; } -bool p3StatusService::getStatus(std::string &id, StatusInfo &statusInfo) +bool p3StatusService::getStatus(const std::string &id, StatusInfo &statusInfo) { #ifdef STATUS_DEBUG std::cerr << "p3StatusService::getStatus() " << std::endl; diff --git a/libretroshare/src/services/p3statusservice.h b/libretroshare/src/services/p3statusservice.h index d0605e2d6..0512bec7c 100644 --- a/libretroshare/src/services/p3statusservice.h +++ b/libretroshare/src/services/p3statusservice.h @@ -65,7 +65,7 @@ virtual void statusChange(const std::list &plist); */ virtual bool getOwnStatus(StatusInfo& statusInfo); virtual bool getStatusList(std::list& statusInfo); -virtual bool getStatus(std::string &id, StatusInfo &statusInfo); +virtual bool getStatus(const std::string &id, StatusInfo &statusInfo); /* id = "", status is sent to all online peers */ virtual bool sendStatus(const std::string &id, uint32_t status); diff --git a/retroshare-gui/src/RetroShare.pro b/retroshare-gui/src/RetroShare.pro index ec53c551e..6fd1186b5 100644 --- a/retroshare-gui/src/RetroShare.pro +++ b/retroshare-gui/src/RetroShare.pro @@ -271,6 +271,8 @@ HEADERS += rshare.h \ gui/chat/PopupChatWindow.h \ gui/chat/PopupChatDialog.h \ gui/chat/ChatTabWidget.h \ + gui/chat/ChatWidget.h \ + gui/chat/ChatDialog.h \ gui/ChatLobbyWidget.h \ gui/chat/ChatLobbyDialog.h \ gui/chat/CreateLobbyDialog.h \ @@ -413,6 +415,8 @@ FORMS += gui/StartDialog.ui \ gui/chat/PopupChatWindow.ui \ gui/chat/PopupChatDialog.ui \ gui/chat/ChatTabWidget.ui \ + gui/chat/ChatWidget.ui \ + gui/chat/ChatLobbyDialog.ui \ gui/chat/CreateLobbyDialog.ui \ gui/ChatLobbyWidget.ui \ gui/connect/ConfCertDialog.ui \ @@ -540,6 +544,8 @@ SOURCES += main.cpp \ gui/chat/PopupChatWindow.cpp \ gui/chat/PopupChatDialog.cpp \ gui/chat/ChatTabWidget.cpp \ + gui/chat/ChatWidget.cpp \ + gui/chat/ChatDialog.cpp \ gui/ChatLobbyWidget.cpp \ gui/chat/ChatLobbyDialog.cpp \ gui/chat/CreateLobbyDialog.cpp \ diff --git a/retroshare-gui/src/gui/ChatLobbyWidget.cpp b/retroshare-gui/src/gui/ChatLobbyWidget.cpp index 0329b827e..39065e4a4 100644 --- a/retroshare-gui/src/gui/ChatLobbyWidget.cpp +++ b/retroshare-gui/src/gui/ChatLobbyWidget.cpp @@ -295,7 +295,7 @@ void ChatLobbyWidget::subscribeItem() if (rsMsgs->joinPublicChatLobby(id)) { std::string vpeer_id; if (rsMsgs->getVirtualPeerId(id, vpeer_id)) { - PopupChatDialog::chatFriend(vpeer_id) ; + ChatDialog::chatFriend(vpeer_id) ; } } } @@ -311,7 +311,7 @@ void ChatLobbyWidget::unsubscribeItem() std::string vpeer_id; if (rsMsgs->getVirtualPeerId(id, vpeer_id)) { - PopupChatDialog::closeChat(vpeer_id); + ChatDialog::closeChat(vpeer_id); } rsMsgs->unsubscribeChatLobby(id); @@ -339,7 +339,7 @@ void ChatLobbyWidget::displayChatLobbyEvent(qulonglong lobby_id, int event_type, std::string vpid; if (rsMsgs->getVirtualPeerId(lobby_id, vpid)) { - if (ChatLobbyDialog *cld = dynamic_cast(PopupChatDialog::getExistingInstance(vpid))) { + if (ChatLobbyDialog *cld = dynamic_cast(ChatDialog::getExistingChat(vpid))) { cld->displayLobbyEvent(event_type, nickname, str); } } @@ -351,14 +351,14 @@ void ChatLobbyWidget::readChatLobbyInvites() rsMsgs->getPendingChatLobbyInvites(invites); for(std::list::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)) { + if (QMessageBox::Ok == QMessageBox::question(this, 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); + ChatDialog::chatFriend(vpid); } else { std::cerr << "No lobby known with id 0x" << std::hex << (*it).lobby_id << std::dec << std::endl; } diff --git a/retroshare-gui/src/gui/ChatLobbyWidget.ui b/retroshare-gui/src/gui/ChatLobbyWidget.ui index 0a89e3c7e..52c350d31 100644 --- a/retroshare-gui/src/gui/ChatLobbyWidget.ui +++ b/retroshare-gui/src/gui/ChatLobbyWidget.ui @@ -89,11 +89,7 @@ p, li { white-space: pre-wrap; } Qt::NoFocus - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Create new chat lobby</span></p></body></html> + Create new chat lobby QPushButton::menu-indicator { diff --git a/retroshare-gui/src/gui/FriendsDialog.cpp b/retroshare-gui/src/gui/FriendsDialog.cpp index a49ed2433..1387a8799 100644 --- a/retroshare-gui/src/gui/FriendsDialog.cpp +++ b/retroshare-gui/src/gui/FriendsDialog.cpp @@ -37,9 +37,9 @@ #include #include "channels/CreateChannel.h" -#include "chat/PopupChatDialog.h" #include "common/Emoticons.h" #include "common/vmessagebox.h" +#include "chat/ChatDialog.h" #include "connect/ConfCertDialog.h" #include "connect/ConnectFriendWizard.h" #include "forums/CreateForum.h" @@ -320,15 +320,7 @@ void FriendsDialog::updateStatusString(const QString& peer_id, const QString& st void FriendsDialog::updatePeerStatusString(const QString& peer_id,const QString& status_string,bool is_private_chat) { - if(is_private_chat) - { - PopupChatDialog *pcd = PopupChatDialog::getExistingInstance(peer_id.toStdString()); - if (pcd) { - pcd->updateStatusString(peer_id, status_string); - } - } - else - { + if (!is_private_chat) { #ifdef FRIENDS_DEBUG std::cerr << "Updating public chat msg from peer " << rsPeers->getPeerName(peer_id.toStdString()) << ": " << status_string.toStdString() << std::endl ; #endif @@ -842,4 +834,4 @@ void FriendsDialog::createChatLobby() { std::list friends; CreateLobbyDialog(friends).exec(); -} \ No newline at end of file +} diff --git a/retroshare-gui/src/gui/MainWindow.cpp b/retroshare-gui/src/gui/MainWindow.cpp index 7e1cb1482..583550e3e 100644 --- a/retroshare-gui/src/gui/MainWindow.cpp +++ b/retroshare-gui/src/gui/MainWindow.cpp @@ -54,7 +54,7 @@ #include "ChannelFeed.h" #include "bwgraph/bwgraph.h" #include "help/browser/helpbrowser.h" -#include "chat/PopupChatDialog.h" +#include "chat/ChatDialog.h" #include "RetroShareLink.h" #ifdef UNFINISHED @@ -889,7 +889,7 @@ void MainWindow::updateStatus() void MainWindow::privateChatChanged(int list, int type) { /* first process the chat messages */ - PopupChatDialog::privateChatChanged(list, type); + ChatDialog::chatChanged(list, type); if (list == NOTIFY_LIST_PRIVATE_INCOMING_CHAT) { /* than count the chat messages */ @@ -1257,13 +1257,13 @@ void MainWindow::trayIconChannelsClicked(QSystemTrayIcon::ActivationReason e) void MainWindow::trayIconChatClicked(QSystemTrayIcon::ActivationReason e) { if(e == QSystemTrayIcon::Trigger || e == QSystemTrayIcon::DoubleClick) { - PopupChatDialog *pcd = NULL; + ChatDialog *chatDialog = NULL; std::list ids; if (rsMsgs->getPrivateChatQueueIds(true, ids) && ids.size()) { - pcd = PopupChatDialog::getPrivateChat(ids.front(), RS_CHAT_OPEN | RS_CHAT_FOCUS); + chatDialog = ChatDialog::getChat(ids.front(), RS_CHAT_OPEN | RS_CHAT_FOCUS); } - if (pcd == NULL) { + if (chatDialog == NULL) { showWindow(MainWindow::Friends); } } diff --git a/retroshare-gui/src/gui/NewsFeed.cpp b/retroshare-gui/src/gui/NewsFeed.cpp index b746b5f5a..be642f313 100644 --- a/retroshare-gui/src/gui/NewsFeed.cpp +++ b/retroshare-gui/src/gui/NewsFeed.cpp @@ -44,7 +44,7 @@ #include "feeds/SecurityItem.h" #include "settings/rsharesettings.h" -#include "chat/PopupChatDialog.h" +#include "chat/ChatDialog.h" const uint32_t NEWSFEED_PEERLIST = 0x0001; const uint32_t NEWSFEED_FORUMNEWLIST = 0x0002; @@ -548,7 +548,7 @@ void NewsFeed::openChat(std::string peerId) std::cerr << std::endl; #endif - PopupChatDialog::chatFriend(peerId); + ChatDialog::chatFriend(peerId); } void NewsFeed::itemDestroyed(QObject *item) diff --git a/retroshare-gui/src/gui/chat/ChatDialog.cpp b/retroshare-gui/src/gui/chat/ChatDialog.cpp new file mode 100644 index 000000000..3483633f6 --- /dev/null +++ b/retroshare-gui/src/gui/chat/ChatDialog.cpp @@ -0,0 +1,351 @@ +/**************************************************************** + * + * 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 "ChatDialog.h" +#include "gui/common/PeerDefs.h" +#include "PopupChatDialog.h" +#include "ChatLobbyDialog.h" +#include "PopupChatWindow.h" +#include "gui/settings/rsharesettings.h" +#include "gui/msgs/MessageComposer.h" + +#include +#include +#include + +static std::map chatDialogs; + +ChatDialog::ChatDialog(QWidget *parent, Qt::WFlags flags) : + QWidget(parent, flags) +{ +} + +ChatDialog::~ChatDialog() +{ + emit dialogClose(this); + + std::map::iterator it; + if (chatDialogs.end() != (it = chatDialogs.find(getPeerId()))) { + chatDialogs.erase(it); + } +} + +void ChatDialog::init(const std::string &peerId, const QString &peerName) +{ + this->peerId = peerId; + + ChatWidget *cw = getChatWidget(); + if (cw) { + cw->init(peerId, peerName); + + 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; + if (rsMsgs->isLobbyId(peerId, lobby_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 { + RsPeerDetails sslDetails; + if (rsPeers->getPeerDetails(peerId, sslDetails)) { + 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) { + 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; + } + + ChatLobbyId lid; + if (rsMsgs->isLobbyId(peerId, lid)) { + getChat(peerId, RS_CHAT_OPEN | RS_CHAT_FOCUS); + return; + } + + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(peerId, detail)) + return; + + std::string firstId; + + if (detail.isOnlyGPGdetail) { + //let's get the ssl child details, and open all the chat boxes + std::list sslIds; + rsPeers->getAssociatedSSLIds(detail.gpg_id, sslIds); + for (std::list::iterator it = sslIds.begin(); it != sslIds.end(); it++) { + if (firstId.empty()) { + firstId = *it; + } + + RsPeerDetails sslDetails; + if (rsPeers->getPeerDetails(*it, sslDetails)) { + if (sslDetails.state & RS_PEER_STATE_CONNECTED) { + getChat(*it, RS_CHAT_OPEN | RS_CHAT_FOCUS); + return; + } + } + } + } else { + if (detail.state & RS_PEER_STATE_CONNECTED) { + getChat(peerId, RS_CHAT_OPEN | RS_CHAT_FOCUS); + return; + } + firstId = peerId; + } + + /* info dialog */ + QMessageBox mb(QMessageBox::Question, tr("Friend not Online"), tr("Your Friend is offline \nDo you want to send them a Message instead"), QMessageBox::Yes | QMessageBox::No); + mb.setWindowIcon(QIcon(":/images/rstray3.png")); + if (mb.exec() == QMessageBox::Yes) { + MessageComposer::msgFriend(peerId, false); + } else { + if (firstId.empty() == false) { + getChat(firstId, 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; +} + +int ChatDialog::getPeerStatus() +{ + ChatWidget *cw = getChatWidget(); + if (cw) { + return cw->getPeerStatus(); + } + + return 0; +} + +QString ChatDialog::getTitle() +{ + ChatWidget *cw = getChatWidget(); + if (cw) { + return cw->getPeerName(); + } + + 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); +} diff --git a/retroshare-gui/src/gui/chat/ChatDialog.h b/retroshare-gui/src/gui/chat/ChatDialog.h new file mode 100644 index 000000000..aac39eaf7 --- /dev/null +++ b/retroshare-gui/src/gui/chat/ChatDialog.h @@ -0,0 +1,87 @@ +/**************************************************************** + * + * 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. + ****************************************************************/ + +#ifndef CHATDIALOG_H +#define CHATDIALOG_H + +#include +#include + +class ChatWidget; +class RSStyle; + +class ChatDialog : public QWidget +{ + Q_OBJECT + +public: + static ChatDialog *getExistingChat(const std::string &peerId); + static ChatDialog *getChat(const std::string &peerId, uint chatflags); + static void cleanupChat(); + static void chatFriend(const std::string &peerId); + static void closeChat(const std::string &peerId); + static void chatChanged(int list, int type); + + virtual bool canClose() { return true; } + virtual void showDialog(uint chatflags) {} + + virtual ChatWidget *getChatWidget() = 0; + virtual bool hasPeerStatus() = 0; + + void addToParent(QWidget *newParent); + void removeFromParent(QWidget *oldParent); + + std::string getPeerId() { return peerId; } + QString getTitle(); + bool hasNewMessages(); + bool isTyping(); + + bool setStyle(); + const RSStyle *getStyle(); + + void insertChatMsgs(); + int getPeerStatus(); + + void focusDialog(); + +signals: + void dialogClose(ChatDialog *dialog); + void infoChanged(ChatDialog *dialog); + void newMessage(ChatDialog *dialog); + +private slots: + void chatInfoChanged(ChatWidget*); + void chatNewMessage(ChatWidget*); + +protected: + explicit ChatDialog(QWidget *parent = 0, Qt::WFlags flags = 0); + virtual ~ChatDialog(); + + virtual void init(const std::string &peerId, const QString &peerName); + virtual void onChatChanged(int list, int type) {} + + virtual void addIncomingChatMsg(const ChatInfo& info) = 0; + + std::string peerId; +}; + +#endif // CHATDIALOG_H diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp b/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp index fcfc52be9..1c0a7484a 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.cpp @@ -21,52 +21,43 @@ ****************************************************************/ #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util/misc.h" -#include "rshare.h" - -#include -#include -#include - -#include -#include #include "ChatLobbyDialog.h" #include "gui/ChatLobbyWidget.h" +#include "gui/settings/rsharesettings.h" +#include "gui/settings/RsharePeerSettings.h" + +#include + +#include /** Default constructor */ -ChatLobbyDialog::ChatLobbyDialog(const std::string& dialog_id, const ChatLobbyId& lid, const QString &name, QWidget *parent, Qt::WFlags flags) - : PopupChatDialog(dialog_id, name, parent, flags), lobby_id(lid) +ChatLobbyDialog::ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent, Qt::WFlags flags) + : ChatDialog(parent, flags), lobbyId(lid) { - // remove the avatar widget. Replace it with a friends list. - ui.avatarWidget->hide(); - ui.ownAvatarWidget->hide(); - PopupChatDialog::updateStatus(QString::fromStdString(getPeerId()),RS_STATUS_ONLINE); + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); - // hide history buttons - ui.actionClearOfflineMessages->setVisible(false); - ui.actionDelete_Chat_History->setVisible(false); - ui.actionMessageHistory->setVisible(false); + connect(ui.participantsFrameButton, SIGNAL(toggled(bool)), this, SLOT(showParticipantsFrame(bool))); +} - ui.avatarFrameButton->setToolTip(tr("Hide participants")); +void ChatLobbyDialog::init(const std::string &peerId, const QString &peerName) +{ + ChatDialog::init(peerId, peerName); - ui.avatarframe->layout()->addWidget(new QLabel(tr("Participants:"))); - friendsListWidget = new QListWidget; - ui.avatarframe->layout()->addWidget(friendsListWidget); - ui.avatarframe->layout()->addItem(new QSpacerItem(12, 335, QSizePolicy::Minimum, QSizePolicy::Expanding)); + lastUpdateListTime = 0; + + /* Hide or show the participants frames */ + showParticipantsFrame(PeerSettings->getShowParticipantsFrame(peerId)); + + // add to window + ChatTabWidget *tabWidget = ChatLobbyWidget::getTabWidget(); + if (tabWidget) { + tabWidget->addDialog(this); + } + + // load settings + processSettings(true); } /** Destructor. */ @@ -76,25 +67,35 @@ ChatLobbyDialog::~ChatLobbyDialog() // check that the lobby still exists. ChatLobbyId lid; - if (rsMsgs->isLobbyId(getPeerId(),lid)) { - rsMsgs->unsubscribeChatLobby(lobby_id); + if (rsMsgs->isLobbyId(getPeerId(), lid)) { + rsMsgs->unsubscribeChatLobby(lobbyId); } + + // save settings + processSettings(false); } -bool ChatLobbyDialog::addToParent() +ChatWidget *ChatLobbyDialog::getChatWidget() { - ChatTabWidget *tabWidget = ChatLobbyWidget::getTabWidget(); - if (tabWidget) { - tabWidget->addDialog(this); - return true; + return ui.chatWidget; +} + +void ChatLobbyDialog::processSettings(bool load) +{ + Settings->beginGroup(QString("ChatLobbyDialog")); + + if (load) { + // load settings + } else { + // save settings } - return false; + Settings->endGroup(); } void ChatLobbyDialog::setNickName(const QString& nick) { - rsMsgs->setNickNameForChatLobby(lobby_id, nick.toUtf8().constData()); + rsMsgs->setNickNameForChatLobby(lobbyId, nick.toUtf8().constData()); } void ChatLobbyDialog::addIncomingChatMsg(const ChatInfo& info) @@ -104,70 +105,89 @@ void ChatLobbyDialog::addIncomingChatMsg(const ChatInfo& info) QString message = QString::fromStdWString(info.msg); QString name = QString::fromUtf8(info.peer_nickname.c_str()); - addChatMsg(true, name, sendTime, recvTime, message, TYPE_NORMAL); + ui.chatWidget->addChatMsg(true, name, sendTime, recvTime, message, ChatWidget::TYPE_NORMAL); // also update peer list. - static time_t last = 0 ; - time_t now = time(NULL) ; + time_t now = time(NULL); - if (now > last) { - last = now; - updateFriendsList(); + if (now > lastUpdateListTime) { + lastUpdateListTime = now; + updateParticipantsList(); } } -void ChatLobbyDialog::updateFriendsList() +void ChatLobbyDialog::updateParticipantsList() { - friendsListWidget->clear(); + ui.participantsList->clear(); std::list linfos; rsMsgs->getChatLobbyList(linfos); std::list::const_iterator it(linfos.begin()); - for (; it!=linfos.end() && (*it).lobby_id != lobby_id; ++it); + for (; it!=linfos.end() && (*it).lobby_id != lobbyId; ++it); if (it != linfos.end()) { for (std::map::const_iterator it2((*it).nick_names.begin()); it2 != (*it).nick_names.end(); ++it2) { - friendsListWidget->addItem(QString::fromUtf8((it2->first).c_str())); + ui.participantsList->addItem(QString::fromUtf8((it2->first).c_str())); } } } void ChatLobbyDialog::displayLobbyEvent(int event_type, const QString& nickname, const QString& str) { - switch(event_type) - { - case RS_CHAT_LOBBY_EVENT_PEER_LEFT: - addChatMsg(true, tr("Lobby management"), QDateTime::currentDateTime(), QDateTime::currentDateTime(), tr("%1 has left the lobby.").arg(str), TYPE_NORMAL); - break; - case RS_CHAT_LOBBY_EVENT_PEER_JOINED: - addChatMsg(true, tr("Lobby management"), QDateTime::currentDateTime(), QDateTime::currentDateTime(), tr("%1 joined the lobby.").arg(str), TYPE_NORMAL); - break; - case RS_CHAT_LOBBY_EVENT_PEER_STATUS: - updateStatusString(nickname,str); - break; - default: - std::cerr << "ChatLobbyDialog::displayLobbyEvent() Unhandled lobby event type " << event_type << std::endl; + switch (event_type) { + case RS_CHAT_LOBBY_EVENT_PEER_LEFT: + ui.chatWidget->addChatMsg(true, tr("Lobby management"), QDateTime::currentDateTime(), QDateTime::currentDateTime(), tr("%1 has left the lobby.").arg(str), ChatWidget::TYPE_NORMAL); + break; + case RS_CHAT_LOBBY_EVENT_PEER_JOINED: + ui.chatWidget->addChatMsg(true, tr("Lobby management"), QDateTime::currentDateTime(), QDateTime::currentDateTime(), tr("%1 joined the lobby.").arg(str), ChatWidget::TYPE_NORMAL); + break; + case RS_CHAT_LOBBY_EVENT_PEER_STATUS: + ui.chatWidget->updateStatusString(nickname + " %1", str); + break; + default: + std::cerr << "ChatLobbyDialog::displayLobbyEvent() Unhandled lobby event type " << event_type << std::endl; } } -QString ChatLobbyDialog::makeStatusString(const QString& peer_id, const QString& status_string) const -{ - return QString::fromUtf8(peer_id.toStdString().c_str()) + " " + tr(status_string.toAscii()); -} - bool ChatLobbyDialog::canClose() { // check that the lobby still exists. ChatLobbyId lid; - if (!rsMsgs->isLobbyId(getPeerId(),lid)) { + if (!rsMsgs->isLobbyId(getPeerId(), lid)) { return true; } - if (QMessageBox::Yes == QMessageBox::question(NULL, tr("Unsubscribe to lobby?"), tr("Do you want to unsubscribe to this chat lobby?"), QMessageBox::Yes | QMessageBox::No)) { + if (QMessageBox::Yes == QMessageBox::question(this, tr("Unsubscribe to lobby"), tr("Do you want to unsubscribe to this chat lobby?"), QMessageBox::Yes | QMessageBox::No)) { return true; } return false; } + +void ChatLobbyDialog::showDialog(uint chatflags) +{ + if (chatflags & RS_CHAT_FOCUS) { + ChatTabWidget *tabWidget = ChatLobbyWidget::getTabWidget(); + if (tabWidget) { + tabWidget->setCurrentWidget(this); + } + } +} + +void ChatLobbyDialog::showParticipantsFrame(bool show) +{ + ui.participantsFrame->setVisible(show); + ui.participantsFrameButton->setChecked(show); + + if (show) { + ui.participantsFrameButton->setToolTip(tr("Hide Participants")); + ui.participantsFrameButton->setIcon(QIcon(":images/hide_toolbox_frame.png")); + } else { + ui.participantsFrameButton->setToolTip(tr("Show Participants")); + ui.participantsFrameButton->setIcon(QIcon(":images/show_toolbox_frame.png")); + } + + PeerSettings->setShowParticipantsFrame(getPeerId(), show); +} diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.h b/retroshare-gui/src/gui/chat/ChatLobbyDialog.h index 04f0f707b..61036986d 100644 --- a/retroshare-gui/src/gui/chat/ChatLobbyDialog.h +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.h @@ -23,59 +23,49 @@ #ifndef _CHATLOBBYDIALOG_H #define _CHATLOBBYDIALOG_H -#include "ui_PopupChatDialog.h" +#include "ui_ChatLobbyDialog.h" +#include "ChatDialog.h" -class QAction; -class QTextEdit; -class QTextCharFormat; -class AttachFileItem; -class ChatInfo; -class QListWidget ; - -#include -#include "ChatStyle.h" -#include "gui/style/RSStyle.h" -#include "PopupChatDialog.h" - -class ChatLobbyDialog: public PopupChatDialog +class ChatLobbyDialog: public ChatDialog { Q_OBJECT -public: - void displayLobbyEvent(int event_type,const QString& nickname,const QString& str) ; + friend class ChatDialog; + +public: + void displayLobbyEvent(int event_type, const QString& nickname, const QString& str); - // The following methods are differentfrom those of the parent: - // - virtual bool hasPeerStatus() { return false; } virtual bool canClose(); + virtual void showDialog(uint chatflags); + virtual ChatWidget *getChatWidget(); + virtual bool hasPeerStatus() { return false; } + +private slots: + void showParticipantsFrame(bool show); protected: /** Default constructor */ - ChatLobbyDialog(const std::string& id,const ChatLobbyId& lid, const QString &name, QWidget *parent = 0, Qt::WFlags flags = 0); + ChatLobbyDialog(const ChatLobbyId& lid, QWidget *parent = 0, Qt::WFlags flags = 0); /** Default destructor */ virtual ~ChatLobbyDialog(); -// virtual void addChatMsg(bool incoming, const QString &name, const QDateTime &sendTime, const QDateTime &recvTime, const QString &message, enumChatType chatType); -// virtual void sendChat(); + void processSettings(bool load); - friend class PopupChatDialog ; - - // The following methods are differentfrom those of the parent: - // - virtual bool addToParent(); - virtual bool isChatLobby() { return true; } - virtual void addIncomingChatMsg(const ChatInfo& info) ; // - virtual QString makeStatusString(const QString& peer_id,const QString& status_string) const ; + virtual void init(const std::string &peerId, const QString &peerName); + virtual void addIncomingChatMsg(const ChatInfo& info); protected slots: - void setNickName(const QString&) ; + void setNickName(const QString&); private: - void updateFriendsList() ; + void updateParticipantsList(); - ChatLobbyId lobby_id ; - QListWidget *friendsListWidget ; + ChatLobbyId lobbyId; + time_t lastUpdateListTime; + + /** Qt Designer generated object */ + Ui::ChatLobbyDialog ui; }; #endif diff --git a/retroshare-gui/src/gui/chat/ChatLobbyDialog.ui b/retroshare-gui/src/gui/chat/ChatLobbyDialog.ui new file mode 100644 index 000000000..3717ac34f --- /dev/null +++ b/retroshare-gui/src/gui/chat/ChatLobbyDialog.ui @@ -0,0 +1,182 @@ + + + ChatLobbyDialog + + + Qt::NonModal + + + + 0 + 0 + 531 + 451 + + + + MainWindow + + + + + + + 0 + + + + + 0 + + + 5 + + + 0 + + + 0 + + + 1 + + + + + + 0 + 0 + + + + + 14 + 16777215 + + + + QFrame#frame{border: transparent} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + + + + 14 + 31 + + + + + 14 + 31 + + + + + + + + 16 + 31 + + + + true + + + + + + + Qt::Vertical + + + + 12 + 335 + + + + + + + + + + + + 132 + 16777215 + + + + border: transparent; + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 3 + + + 9 + + + 3 + + + 9 + + + + + QListWidget{ + border: 1px solid #B8B6B1; + border-radius: 6px; + background: white; +} + + + + + + + + + + + 0 + 0 + + + + + + + + + + + ChatWidget + QWidget +
gui/chat/ChatWidget.h
+ 1 +
+
+ + +
diff --git a/retroshare-gui/src/gui/chat/ChatTabWidget.cpp b/retroshare-gui/src/gui/chat/ChatTabWidget.cpp index 19f144c08..00fc8db6f 100644 --- a/retroshare-gui/src/gui/chat/ChatTabWidget.cpp +++ b/retroshare-gui/src/gui/chat/ChatTabWidget.cpp @@ -1,6 +1,28 @@ +/**************************************************************** + * + * 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 "ChatTabWidget.h" #include "ui_ChatTabWidget.h" -#include "PopupChatDialog.h" +#include "ChatDialog.h" #include "gui/common/StatusDefs.h" #define IMAGE_WINDOW ":/images/rstray3.png" @@ -22,28 +44,30 @@ ChatTabWidget::~ChatTabWidget() delete ui; } -void ChatTabWidget::addDialog(PopupChatDialog *dialog) +void ChatTabWidget::addDialog(ChatDialog *dialog) { addTab(dialog, dialog->getTitle()); + dialog->addToParent(this); - QObject::connect(dialog, SIGNAL(infoChanged(PopupChatDialog*)), this, SLOT(tabInfoChanged(PopupChatDialog*))); + QObject::connect(dialog, SIGNAL(infoChanged(ChatDialog*)), this, SLOT(tabInfoChanged(ChatDialog*))); tabInfoChanged(dialog); } -void ChatTabWidget::removeDialog(PopupChatDialog *dialog) +void ChatTabWidget::removeDialog(ChatDialog *dialog) { - QObject::disconnect(dialog, SIGNAL(infoChanged(PopupChatDialog*)), this, SLOT(tabInfoChanged(PopupChatDialog*))); + QObject::disconnect(dialog, SIGNAL(infoChanged(ChatDialog*)), this, SLOT(tabInfoChanged(ChatDialog*))); int tab = indexOf(dialog); if (tab >= 0) { + dialog->removeFromParent(this); removeTab(tab); } } void ChatTabWidget::tabClose(int tab) { - PopupChatDialog *dialog = dynamic_cast(widget(tab)); + ChatDialog *dialog = dynamic_cast(widget(tab)); if (dialog) { if (dialog->canClose()) { @@ -54,15 +78,14 @@ void ChatTabWidget::tabClose(int tab) void ChatTabWidget::tabChanged(int tab) { - PopupChatDialog *dialog = dynamic_cast(widget(tab)); + ChatDialog *dialog = dynamic_cast(widget(tab)); if (dialog) { - dialog->activate(); emit tabChanged(dialog); } } -void ChatTabWidget::tabInfoChanged(PopupChatDialog *dialog) +void ChatTabWidget::tabInfoChanged(ChatDialog *dialog) { int tab = indexOf(dialog); if (tab >= 0) { @@ -85,15 +108,15 @@ void ChatTabWidget::getInfo(bool &isTyping, bool &hasNewMessage, QIcon *icon) isTyping = false; hasNewMessage = false; - PopupChatDialog *pcd; + ChatDialog *cd; int tabCount = count(); for (int i = 0; i < tabCount; i++) { - pcd = dynamic_cast(widget(i)); - if (pcd) { - if (pcd->isTyping()) { + cd = dynamic_cast(widget(i)); + if (cd) { + if (cd->isTyping()) { isTyping = true; } - if (pcd->hasNewMessages()) { + if (cd->hasNewMessages()) { hasNewMessage = true; } } @@ -105,9 +128,9 @@ void ChatTabWidget::getInfo(bool &isTyping, bool &hasNewMessage, QIcon *icon) } else if (hasNewMessage) { *icon = QIcon(IMAGE_CHAT); } else { - pcd = dynamic_cast(currentWidget()); - if (pcd && pcd->hasPeerStatus()) { - *icon = QIcon(StatusDefs::imageIM(pcd->getPeerStatus())); + cd = dynamic_cast(currentWidget()); + if (cd && cd->hasPeerStatus()) { + *icon = QIcon(StatusDefs::imageIM(cd->getPeerStatus())); } else { *icon = QIcon(); } diff --git a/retroshare-gui/src/gui/chat/ChatTabWidget.h b/retroshare-gui/src/gui/chat/ChatTabWidget.h index 52a82c9ca..cf2a438e5 100644 --- a/retroshare-gui/src/gui/chat/ChatTabWidget.h +++ b/retroshare-gui/src/gui/chat/ChatTabWidget.h @@ -1,3 +1,25 @@ +/**************************************************************** + * + * 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. + ****************************************************************/ + #ifndef CHATTABWIDGET_H #define CHATTABWIDGET_H @@ -7,7 +29,7 @@ namespace Ui { class ChatTabWidget; } -class PopupChatDialog; +class ChatDialog; class ChatTabWidget : public QTabWidget { @@ -17,19 +39,19 @@ public: explicit ChatTabWidget(QWidget *parent = 0); ~ChatTabWidget(); - void addDialog(PopupChatDialog *dialog); - void removeDialog(PopupChatDialog *dialog); + void addDialog(ChatDialog *dialog); + void removeDialog(ChatDialog *dialog); void getInfo(bool &isTyping, bool &hasNewMessage, QIcon *icon); signals: - void tabChanged(PopupChatDialog *dialog); + void tabChanged(ChatDialog *dialog); void infoChanged(); private slots: - void tabClose(int tab); - void tabChanged(int tab); - void tabInfoChanged(PopupChatDialog *dialog); + void tabClose(int tab); + void tabChanged(int tab); + void tabInfoChanged(ChatDialog *dialog); private: Ui::ChatTabWidget *ui; diff --git a/retroshare-gui/src/gui/chat/ChatWidget.cpp b/retroshare-gui/src/gui/chat/ChatWidget.cpp new file mode 100644 index 000000000..13fe9537f --- /dev/null +++ b/retroshare-gui/src/gui/chat/ChatWidget.cpp @@ -0,0 +1,689 @@ +/**************************************************************** + * + * 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 +#include +#include +#include +#include +#include + +#include "ChatWidget.h" +#include "ui_ChatWidget.h" +#include "gui/notifyqt.h" +#include "gui/RetroShareLink.h" +#include "gui/settings/rsharesettings.h" +#include "gui/settings/RsharePeerSettings.h" +#include "gui/im_history/ImHistoryBrowser.h" +#include "HandleRichText.h" +#include "gui/common/StatusDefs.h" +#include "gui/common/FilesDefs.h" +#include "gui/common/Emoticons.h" +#include "util/misc.h" + +#include +#include +#include + +#include + +/***** + * #define CHAT_DEBUG 1 + *****/ + +// play sound when recv a message +void playsound() +{ + Settings->beginGroup("Sound"); + Settings->beginGroup("SoundFilePath"); + QString OnlineSound = Settings->value("NewChatMessage","").toString(); + Settings->endGroup(); + Settings->beginGroup("Enable"); + bool flag = Settings->value("NewChatMessage",false).toBool(); + Settings->endGroup(); + Settings->endGroup(); + + if (!OnlineSound.isEmpty() && flag) { + if (QSound::isAvailable()) { + QSound::play(OnlineSound); + } + } +} + +ChatWidget::ChatWidget(QWidget *parent) : + QWidget(parent), ui(new Ui::ChatWidget) +{ + ui->setupUi(this); + + newMessages = false; + typing = false; + peerStatus = 0; + isChatLobby = false; + + lastStatusSendTime = 0 ; + chatStyle.setStyleFromSettings(ChatStyle::TYPE_PRIVATE); + + connect(ui->sendButton, SIGNAL(clicked()), this, SLOT(sendChat())); + connect(ui->addFileButton, SIGNAL(clicked()), this , SLOT(addExtraFile())); + + connect(ui->textboldButton, SIGNAL(clicked()), this, SLOT(setFont())); + connect(ui->textunderlineButton, SIGNAL(clicked()), this, SLOT(setFont())); + connect(ui->textitalicButton, SIGNAL(clicked()), this, SLOT(setFont())); + connect(ui->attachPictureButton, SIGNAL(clicked()), this, SLOT(addExtraPicture())); + connect(ui->fontButton, SIGNAL(clicked()), this, SLOT(getFont())); + connect(ui->colorButton, SIGNAL(clicked()), this, SLOT(setColor())); + connect(ui->emoteiconButton, SIGNAL(clicked()), this, SLOT(smileyWidget())); + connect(ui->actionSaveChatHistory, SIGNAL(triggered()), this, SLOT(fileSaveAs())); + connect(ui->actionClearChatHistory, SIGNAL(triggered()), this, SLOT(clearChatHistory())); + connect(ui->actionDeleteChatHistory, SIGNAL(triggered()), this, SLOT(deleteChatHistory())); + connect(ui->actionMessageHistory, SIGNAL(triggered()), this, SLOT(messageHistory())); + + connect(ui->hashBox, SIGNAL(fileHashingFinished(QList)), this, SLOT(fileHashingFinished(QList))); + + connect(NotifyQt::getInstance(), SIGNAL(peerStatusChanged(const QString&, int)), this, SLOT(updateStatus(const QString&, int))); + connect(NotifyQt::getInstance(), SIGNAL(peerHasNewCustomStateString(const QString&, const QString&)), this, SLOT(updatePeersCustomStateString(const QString&, const QString&))); + + connect(ui->chattextEdit, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenu(QPoint))); + + ui->infoframe->setVisible(false); + ui->statusmessagelabel->hide(); + + ui->textboldButton->setIcon(QIcon(QString(":/images/edit-bold.png"))); + ui->textunderlineButton->setIcon(QIcon(QString(":/images/edit-underline.png"))); + ui->textitalicButton->setIcon(QIcon(QString(":/images/edit-italic.png"))); + ui->fontButton->setIcon(QIcon(QString(":/images/fonts.png"))); + ui->emoteiconButton->setIcon(QIcon(QString(":/images/emoticons/kopete/kopete020.png"))); + + ui->textboldButton->setCheckable(true); + ui->textunderlineButton->setCheckable(true); + ui->textitalicButton->setCheckable(true); + + setAcceptDrops(true); + ui->chattextEdit->setAcceptDrops(false); + ui->hashBox->setDropWidget(this); + ui->hashBox->setAutoHide(true); + + QMenu *toolmenu = new QMenu(); + toolmenu->addAction(ui->actionClearChatHistory); + toolmenu->addAction(ui->actionDeleteChatHistory); + toolmenu->addAction(ui->actionSaveChatHistory); + toolmenu->addAction(ui->actionMessageHistory); + ui->pushtoolsButton->setMenu(toolmenu); + + ui->chattextEdit->installEventFilter(this); + +#ifdef RS_RELEASE_VERSION + ui->attachPictureButton->setVisible(false); +#endif + + resetStatusBar(); +} + +ChatWidget::~ChatWidget() +{ + processSettings(false); + + delete ui; +} + +void ChatWidget::init(const std::string &peerId, const QString &peerName) +{ + this->peerId = peerId; + this->peerName = peerName; + + ui->friendnamelabel->setText(peerName); + + ChatLobbyId lid; + if (rsMsgs->isLobbyId(peerId, lid)) { + isChatLobby = true; + } + + currentColor.setNamedColor(PeerSettings->getPrivateChatColor(peerId)); + currentFont.fromString(PeerSettings->getPrivateChatFont(peerId)); + + colorChanged(currentColor); + fontChanged(currentFont); + + // load style + PeerSettings->getStyle(peerId, "ChatWidget", style); + + if (!isChatLobby) { + // initialize first status + StatusInfo peerStatusInfo; + // No check of return value. Non existing status info is handled as offline. + rsStatus->getStatus(peerId, peerStatusInfo); + updateStatus(QString::fromStdString(peerId), peerStatusInfo.status); + + // initialize first custom state string + QString customStateString = QString::fromUtf8(rsMsgs->getCustomStateString(peerId).c_str()); + updatePeersCustomStateString(QString::fromStdString(peerId), customStateString); + } else { + // currently not possible + ui->actionDeleteChatHistory->setVisible(false); + ui->actionMessageHistory->setVisible(false); + } + + if (rsHistory->getEnable(false)) { + // get chat messages from history + std::list historyMsgs; + int messageCount = Settings->getPrivateChatHistoryCount(); + if (messageCount > 0) { + rsHistory->getMessages(peerId, historyMsgs, messageCount); + + std::list::iterator historyIt; + for (historyIt = historyMsgs.begin(); historyIt != historyMsgs.end(); historyIt++) { + addChatMsg(historyIt->incoming, QString::fromUtf8(historyIt->peerName.c_str()), QDateTime::fromTime_t(historyIt->sendTime), QDateTime::fromTime_t(historyIt->recvTime), QString::fromUtf8(historyIt->message.c_str()), TYPE_HISTORY); + } + } + } + + processSettings(true); +} + +void ChatWidget::processSettings(bool load) +{ + Settings->beginGroup(QString("ChatWidget")); + + if (load) { + // load settings + + // state of splitter + ui->chatsplitter->restoreState(Settings->value("ChatSplitter").toByteArray()); + } else { + // save settings + + // state of splitter + Settings->setValue("ChatSplitter", ui->chatsplitter->saveState()); + } + + Settings->endGroup(); +} + +bool ChatWidget::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == ui->chattextEdit) { + if (event->type() == QEvent::KeyPress) { + updateStatusTyping(); + + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent && (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return)) { + // Enter pressed + if (Settings->getChatSendMessageWithCtrlReturn()) { + if (keyEvent->modifiers() & Qt::ControlModifier) { + // send message with Ctrl+Enter + sendChat(); + return true; // eat event + } + } else { + if (keyEvent->modifiers() & Qt::ControlModifier) { + // insert return + ui->chattextEdit->textCursor().insertText("\n"); + } else { + // send message with Enter + sendChat(); + } + return true; // eat event + } + } + } + } else { + if (event->type() == QEvent::WindowActivate) { + if (isVisible() && (window() == NULL || window()->isActiveWindow())) { + newMessages = false; + emit infoChanged(this); + focusDialog(); + } + } + } + // pass the event on to the parent class + return QWidget::eventFilter(obj, event); +} + +void ChatWidget::addToolsAction(QAction *action) +{ + ui->pushtoolsButton->menu()->addAction(action); +} + +void ChatWidget::showEvent(QShowEvent */*event*/) +{ + newMessages = false; + emit infoChanged(this); + focusDialog(); +} + +void ChatWidget::resizeEvent(QResizeEvent */*event*/) +{ + // Workaround: now the scroll position is correct calculated + QScrollBar *scrollbar = ui->textBrowser->verticalScrollBar(); + scrollbar->setValue(scrollbar->maximum()); +} + +void ChatWidget::addToParent(QWidget *newParent) +{ + newParent->window()->installEventFilter(this); +} + +void ChatWidget::removeFromParent(QWidget *oldParent) +{ + oldParent->window()->removeEventFilter(this); +} + +void ChatWidget::focusDialog() +{ + ui->chattextEdit->setFocus(); +} + +void ChatWidget::addChatMsg(bool incoming, const QString &name, const QDateTime &sendTime, const QDateTime &recvTime, const QString &message, enumChatType chatType) +{ +#ifdef CHAT_DEBUG + std::cout << "ChatWidget::addChatMsg message : " << message.toStdString() << std::endl; +#endif + + unsigned int formatFlag = CHAT_FORMATMSG_EMBED_LINKS; + + // embed smileys ? + if (Settings->valueFromGroup(QString("Chat"), QString::fromUtf8("Emoteicons_PrivatChat"), true).toBool()) { + formatFlag |= CHAT_FORMATMSG_EMBED_SMILEYS; + } + + ChatStyle::enumFormatMessage type; + if (chatType == TYPE_OFFLINE) { + type = ChatStyle::FORMATMSG_OOUTGOING; + } else if (chatType == TYPE_HISTORY) { + type = incoming ? ChatStyle::FORMATMSG_HINCOMING : ChatStyle::FORMATMSG_HOUTGOING; + } else { + type = incoming ? ChatStyle::FORMATMSG_INCOMING : ChatStyle::FORMATMSG_OUTGOING; + } + + QString formatMsg = chatStyle.formatMessage(type, name, incoming ? sendTime : recvTime, message, formatFlag); + + ui->textBrowser->append(formatMsg); + + /* Scroll to the end */ + QScrollBar *scrollbar = ui->textBrowser->verticalScrollBar(); + scrollbar->setValue(scrollbar->maximum()); + + resetStatusBar(); + + if (incoming && chatType == TYPE_NORMAL) { + playsound(); + + emit newMessage(this); + + if (!isVisible() || (window() && (!window()->isActiveWindow() || window()->isMinimized()))) { + newMessages = true; + } + + emit infoChanged(this); + } +} + +void ChatWidget::pasteLink() +{ + std::cerr << "In paste link" << std::endl; + ui->chattextEdit->insertHtml(RSLinkClipboard::toHtml()); +} + +void ChatWidget::contextMenu(QPoint /*point*/) +{ + std::cerr << "In context menu" << std::endl; + + QMenu *contextMnu = ui->chattextEdit->createStandardContextMenu(); + + contextMnu->addSeparator(); + QAction *action = contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste RetroShare Link"), this, SLOT(pasteLink())); + action->setDisabled(RSLinkClipboard::empty()); + + contextMnu->exec(QCursor::pos()); + delete(contextMnu); +} + +void ChatWidget::resetStatusBar() +{ + ui->statusLabel->clear(); + ui->typingpixmapLabel->clear(); + + typing = false; + + emit infoChanged(this); +} + +void ChatWidget::updateStatusTyping() +{ + if (time(NULL) - lastStatusSendTime > 5) // limit 'peer is typing' packets to at most every 10 sec + { +#ifdef ONLY_FOR_LINGUIST + tr("is typing..."); +#endif + + rsMsgs->sendStatusString(peerId, "is typing..."); + lastStatusSendTime = time(NULL) ; + } +} + +void ChatWidget::sendChat() +{ + QTextEdit *chatWidget = ui->chattextEdit; + + if (chatWidget->toPlainText().isEmpty()) { + // nothing to send + return; + } + + QString text; + RsHtml::optimizeHtml(chatWidget, text); + std::wstring msg = text.toStdWString(); + + if (msg.empty()) { + // nothing to send + return; + } + + std::string ownId = rsPeers->getOwnId(); + +#ifdef CHAT_DEBUG + std::cout << "ChatWidget:sendChat " << std::endl; +#endif + + if (rsMsgs->sendPrivateChat(peerId, msg)) { + QDateTime currentTime = QDateTime::currentDateTime(); + addChatMsg(false, QString::fromUtf8(rsPeers->getPeerName(ownId).c_str()), currentTime, currentTime, QString::fromStdWString(msg), TYPE_NORMAL); + } + + chatWidget->clear(); + // workaround for Qt bug - http://bugreports.qt.nokia.com/browse/QTBUG-2533 + // QTextEdit::clear() does not reset the CharFormat if document contains hyperlinks that have been accessed. + chatWidget->setCurrentCharFormat(QTextCharFormat ()); + + setFont(); +} + +void ChatWidget::on_closeInfoFrameButton_clicked() +{ + ui->infoframe->setVisible(false); +} + +void ChatWidget::setColor() +{ + bool ok; + QRgb color = QColorDialog::getRgba(ui->chattextEdit->textColor().rgba(), &ok, window()); + if (ok) { + currentColor = QColor(color); + PeerSettings->setPrivateChatColor(peerId, currentColor.name()); + colorChanged(currentColor); + } + setFont(); +} + +void ChatWidget::colorChanged(const QColor &c) +{ + QPixmap pix(16, 16); + pix.fill(c); + ui->colorButton->setIcon(pix); +} + +void ChatWidget::getFont() +{ + bool ok; + QFont font = QFontDialog::getFont(&ok, currentFont, this); + if (ok) { + fontChanged(font); + } +} + +void ChatWidget::fontChanged(const QFont &font) +{ + currentFont = font; + + ui->textboldButton->setChecked(currentFont.bold()); + ui->textunderlineButton->setChecked(currentFont.underline()); + ui->textitalicButton->setChecked(currentFont.italic()); + + setFont(); +} + +void ChatWidget::setFont() +{ + currentFont.setBold(ui->textboldButton->isChecked()); + currentFont.setUnderline(ui->textunderlineButton->isChecked()); + currentFont.setItalic(ui->textitalicButton->isChecked()); + + ui->chattextEdit->setFont(currentFont); + ui->chattextEdit->setTextColor(currentColor); + + ui->chattextEdit->setFocus(); + + PeerSettings->setPrivateChatFont(peerId, currentFont.toString()); +} + +void ChatWidget::smileyWidget() +{ + Emoticons::showSmileyWidget(this, ui->emoteiconButton, SLOT(addSmiley()), true); +} + +void ChatWidget::addSmiley() +{ + ui->chattextEdit->textCursor().insertText(qobject_cast(sender())->toolTip().split("|").first()); +} + +void ChatWidget::clearChatHistory() +{ + ui->textBrowser->clear(); +} + +void ChatWidget::deleteChatHistory() +{ + if ((QMessageBox::question(this, "RetroShare", tr("Do you really want to physically delete the history?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)) == QMessageBox::Yes) { + clearChatHistory(); + rsHistory->clear(peerId); + } +} + +void ChatWidget::messageHistory() +{ + ImHistoryBrowser imBrowser(peerId, ui->chattextEdit, window()); + imBrowser.exec(); +} + +void ChatWidget::addExtraFile() +{ + QStringList files; + if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", files)) { + ui->hashBox->addAttachments(files/*, 0*/); + } +} + +void ChatWidget::addExtraPicture() +{ + // select a picture file + QString file; + if (misc::getOpenFileName(window(), RshareSettings::LASTDIR_IMAGES, tr("Load Picture File"), "Pictures (*.png *.xpm *.jpg)", file)) { + ui->hashBox->addAttachments(QStringList(file), HashedFile::Picture); + } +} + +void ChatWidget::fileHashingFinished(QList hashedFiles) +{ + std::cerr << "ChatWidget::fileHashingFinished() started." << std::endl; + + QString message; + + QList::iterator it; + for (it = hashedFiles.begin(); it != hashedFiles.end(); ++it) { + HashedFile& hashedFile = *it; + QString ext = QFileInfo(hashedFile.filename).suffix(); + + RetroShareLink link; + link.createFile(hashedFile.filename, hashedFile.size, QString::fromStdString(hashedFile.hash)); + + if (hashedFile.flag & HashedFile::Picture) { + message += QString("").arg(hashedFile.filepath); + message+="
"; + } else { + QString image = FilesDefs::getImageFromFilename(hashedFile.filename, false); + if (!image.isEmpty()) { + message += QString("").arg(image); + } + } + message += link.toHtmlSize(); + if (it != hashedFiles.end()) { + message += "
"; + } + } + +#ifdef CHAT_DEBUG + std::cerr << "ChatWidget::fileHashingFinished message : " << message.toStdString() << std::endl; +#endif + + /* convert to real html document */ + QTextBrowser textBrowser; + textBrowser.setHtml(message); + std::wstring msg = textBrowser.toHtml().toStdWString(); + + if (rsMsgs->sendPrivateChat(peerId, msg)) { + std::string ownId = rsPeers->getOwnId(); + QDateTime currentTime = QDateTime::currentDateTime(); + addChatMsg(false, QString::fromUtf8(rsPeers->getPeerName(ownId).c_str()), currentTime, currentTime, QString::fromStdWString(msg), TYPE_NORMAL); + } +} + +bool ChatWidget::fileSave() +{ + if (fileName.isEmpty()) + return fileSaveAs(); + + QFile file(fileName); + if (!file.open(QFile::WriteOnly)) + return false; + QTextStream ts(&file); + ts.setCodec(QTextCodec::codecForName("UTF-8")); + ts << ui->textBrowser->document()->toPlainText(); + ui->textBrowser->document()->setModified(false); + return true; +} + +bool ChatWidget::fileSaveAs() +{ + QString fn; + if (misc::getSaveFileName(window(), RshareSettings::LASTDIR_HISTORY, tr("Save as..."), tr("Text File (*.txt );;All Files (*)"), fn)) { + setCurrentFileName(fn); + return fileSave(); + } + + return false; +} + +void ChatWidget::setCurrentFileName(const QString &fileName) +{ + this->fileName = fileName; + ui->textBrowser->document()->setModified(false); + + setWindowModified(false); +} + +void ChatWidget::updateStatus(const QString &peer_id, int status) +{ + /* set font size for status */ + if (peer_id.toStdString() == peerId) { + // the peers status has changed + + switch (status) { + case RS_STATUS_OFFLINE: + ui->infoframe->setVisible(true); + ui->infolabel->setText(peerName + " " + tr("apears to be Offline.") +"\n" + tr("Messages you send will be delivered after Friend is again Online")); + break; + + case RS_STATUS_INACTIVE: + ui->infoframe->setVisible(true); + ui->infolabel->setText(peerName + " " + tr("is Idle and may not reply")); + break; + + case RS_STATUS_ONLINE: + ui->infoframe->setVisible(false); + break; + + case RS_STATUS_AWAY: + ui->infolabel->setText(peerName + " " + tr("is Away and may not reply")); + ui->infoframe->setVisible(true); + break; + + case RS_STATUS_BUSY: + ui->infolabel->setText(peerName + " " + tr("is Busy and may not reply")); + ui->infoframe->setVisible(true); + break; + } + + QString statusString("%1"); + ui->friendnamelabel->setText(peerName + " (" + statusString.arg(StatusDefs::name(status)) + ")") ; + + peerStatus = status; + + emit infoChanged(this); + + return; + } + + // ignore status change +} + +void ChatWidget::updatePeersCustomStateString(const QString& peer_id, const QString& status_string) +{ + std::string stdPeerId = peer_id.toStdString(); + QString status_text; + + if (stdPeerId == peerId) { + // the peers status string has changed + if (status_string.isEmpty()) { + ui->statusmessagelabel->hide(); + } else { + ui->statusmessagelabel->show(); + status_text = RsHtml::formatText(status_string, RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS); + ui->statusmessagelabel->setText(status_text); + } + } +} + +void ChatWidget::updateStatusString(const QString &statusMask, const QString &statusString) +{ + ui->statusLabel->setText(QString(statusMask).arg(tr(statusString.toAscii()))); // displays info for 5 secs. + ui->typingpixmapLabel->setPixmap(QPixmap(":images/typing.png") ); + + if (statusString == "is typing...") { + typing = true; + + emit infoChanged(this); + } + + QTimer::singleShot(5000, this, SLOT(resetStatusBar())) ; +} + +bool ChatWidget::setStyle() +{ + if (style.showDialog(window())) { + PeerSettings->setStyle(peerId, "PopupChatDialog", style); + return true; + } + + return false; +} diff --git a/retroshare-gui/src/gui/chat/ChatWidget.h b/retroshare-gui/src/gui/chat/ChatWidget.h new file mode 100644 index 000000000..f714d1998 --- /dev/null +++ b/retroshare-gui/src/gui/chat/ChatWidget.h @@ -0,0 +1,143 @@ +/**************************************************************** + * + * 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. + ****************************************************************/ + +#ifndef CHATWIDGET_H +#define CHATWIDGET_H + +#include + +#include "gui/common/HashBox.h" +#include "ChatStyle.h" +#include "gui/style/RSStyle.h" + +#include + +class QAction; +class QTextEdit; + +namespace Ui { +class ChatWidget; +} + +class ChatWidget : public QWidget +{ + Q_OBJECT + +public: + enum enumChatType { TYPE_NORMAL, TYPE_HISTORY, TYPE_OFFLINE }; + +public: + explicit ChatWidget(QWidget *parent = 0); + ~ChatWidget(); + + void init(const std::string &peerId, const QString &peerName); + + bool hasNewMessages() { return newMessages; } + bool isTyping() { return typing; } + + void focusDialog(); + void addToParent(QWidget *newParent); + void removeFromParent(QWidget *oldParent); + + void addChatMsg(bool incoming, const QString &name, const QDateTime &sendTime, const QDateTime &recvTime, const QString &message, enumChatType chatType); + void updateStatusString(const QString &statusMask, const QString &statusString); + + void addToolsAction(QAction *action); + + std::string getPeerId() { return peerId; } + QString getPeerName() { return peerName; } + int getPeerStatus() { return peerStatus; } + + bool setStyle(); + const RSStyle *getStyle() { return &style; } + +private slots: + void clearChatHistory(); + void deleteChatHistory(); + void messageHistory(); + +signals: + void infoChanged(ChatWidget*); + void newMessage(ChatWidget*); + +protected: + bool eventFilter(QObject *obj, QEvent *event); + virtual void showEvent(QShowEvent *event); + virtual void resizeEvent(QResizeEvent *event); + +private slots: + void pasteLink(); + void contextMenu(QPoint); + + void fileHashingFinished(QList hashedFiles); + + void smileyWidget(); + void addSmiley(); + + void resetStatusBar() ; + + void addExtraFile(); + void addExtraPicture(); + void on_closeInfoFrameButton_clicked(); + + void setColor(); + void getFont(); + void setFont(); + + void sendChat(); + + void updateStatus(const QString &peer_id, int status); + void updatePeersCustomStateString(const QString& peer_id, const QString& status_string) ; + + bool fileSave(); + bool fileSaveAs(); + +private: + void updateStatusTyping(); + void setCurrentFileName(const QString &fileName); + + void colorChanged(const QColor &c); + void fontChanged(const QFont &font); + void processSettings(bool load); + + std::string peerId; + QString peerName; + + QColor currentColor; + QFont currentFont; + + QString fileName; + + bool newMessages; + bool typing; + int peerStatus; + bool isChatLobby; + + time_t lastStatusSendTime; + + ChatStyle chatStyle; + RSStyle style; + + Ui::ChatWidget *ui; +}; + +#endif // CHATWIDGET_H diff --git a/retroshare-gui/src/gui/chat/ChatWidget.ui b/retroshare-gui/src/gui/chat/ChatWidget.ui new file mode 100644 index 000000000..85b983921 --- /dev/null +++ b/retroshare-gui/src/gui/chat/ChatWidget.ui @@ -0,0 +1,794 @@ + + + ChatWidget + + + + 0 + 0 + 535 + 428 + + + + + + + 0 + + + 5 + + + 0 + + + 0 + + + 1 + + + + + + 0 + 0 + + + + + 14 + 16777215 + + + + QFrame#frame{border: transparent} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + + + + + + QFrame#frame_2{border: transparent} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 2 + + + 3 + + + 3 + + + 3 + + + + + + 0 + 0 + + + + + Arial + 13 + 75 + true + true + + + + TextLabel + + + + + + + + Arial + 9 + + + + TextLabel + + + + + + + + + + QFrame#infoframe{border: 1px solid #DCDC41; +border-radius: 6px; +background: #FFFFD7; +background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, +stop:0 #FFFFD7, stop:1 #FFFFB2);} + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 6 + + + + + + 16 + 16 + + + + + + + :/images/info16.png + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + TextLabel + + + + + + + + 16 + 16 + + + + Qt::NoFocus + + + Close + + + QToolButton +{ + border-image: url(:/images/closenormal.png) +} + +QToolButton:hover +{ +border-image: url(:/images/closehover.png) +} + +QToolButton:pressed { +border-image: url(:/images/closepressed.png) +} + + + + + + true + + + + + + + + + + + 347 + 30 + + + + + 16777215 + 30 + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 1 + + + 6 + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + QPushButton::menu-indicator { +subcontrol-origin: padding; +subcontrol-position: bottom right; +} + +QPushButton::menu-indicator:pressed, QPushButton::menu-indicator:open { +position: relative; +top: 1px; left: 1px; /* shift the arrow by 2 px */ +} + +QPushButton:hover { +border: 1px solid #CCCCCC; +} + + + + + + + :/images/configure.png:/images/configure.png + + + + 22 + 22 + + + + true + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + Attach a Picture + + + + + + + :/images/add_image24.png:/images/add_image24.png + + + + 24 + 24 + + + + true + + + + + + + + 28 + 28 + + + + Qt::NoFocus + + + Add a File for your Friend + + + + + + + :/images/add-share24.png:/images/add-share24.png + + + + 24 + 24 + + + + true + + + + + + + Qt::Horizontal + + + + 190 + 25 + + + + + + + + Send + + + + + + + + 0 + 0 + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + + + + + 24 + 24 + + + + true + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + Bold + + + + + + + ../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup + + + false + + + true + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + Underline + + + + + + + ../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup + + + false + + + true + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + Italic + + + + + + + ../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup + + + false + + + true + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + Font + + + + + + + ../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup + + + false + + + true + + + + + + + + 28 + 28 + + + + + 28 + 28 + + + + Qt::NoFocus + + + Text Color + + + + + + true + + + + + + + + + + 1 + + + Qt::Vertical + + + 2 + + + false + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + QTextBrowser{border: 1px solid #B8B6B1; +border-radius: 6px; +background: white;} + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:8pt;"></p></body></html> + + + true + + + true + + + + + + + + + 0 + + + + + + + + 0 + + + 3 + + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + Qt::CustomContextMenu + + + QTextEdit{border: 1px solid #B8B6B1; +border-radius: 6px; +background: white;} + + + + + + + + 18 + 18 + + + + + 18 + 18 + + + + T + + + Qt::AlignCenter + + + + + + + + + + + true + + + + + + + + + Bold + + + + + Italic + + + + + Underline + + + + + Strike + + + + + + :/images/edit-clear-history.png:/images/edit-clear-history.png + + + Clear Chat History + + + + + true + + + Disable Emoticons + + + + + Save Chat History + + + Save Chat History + + + + + Browse Message History + + + Browse History + + + + + + :/images/edit-clear-history.png:/images/edit-clear-history.png + + + Delete Chat History + + + Deletes all stored and displayed chat history + + + + + + HashBox + QScrollArea +
gui/common/HashBox.h
+ 1 +
+
+ + + + +
diff --git a/retroshare-gui/src/gui/chat/CreateLobbyDialog.cpp b/retroshare-gui/src/gui/chat/CreateLobbyDialog.cpp index 9d03f3b5c..396f4cad0 100644 --- a/retroshare-gui/src/gui/chat/CreateLobbyDialog.cpp +++ b/retroshare-gui/src/gui/chat/CreateLobbyDialog.cpp @@ -28,56 +28,49 @@ #include #include "gui/common/PeerDefs.h" -#include "gui/chat/PopupChatDialog.h" +#include "ChatDialog.h" CreateLobbyDialog::CreateLobbyDialog(const std::list& peer_list,QWidget *parent, Qt::WFlags flags, std::string grpId, int grpType) : - QDialog(parent, flags), mGrpId(grpId), mGrpType(grpType) + QDialog(parent, flags), mGrpId(grpId), mGrpType(grpType) { ui = new Ui::CreateLobbyDialog() ; - ui->setupUi(this); + ui->setupUi(this); - std::string default_nick ; - rsMsgs->getDefaultNickNameForChatLobby(default_nick) ; + std::string default_nick ; + rsMsgs->getDefaultNickNameForChatLobby(default_nick) ; #if QT_VERSION >= 0x040700 - ui->lobbyName_LE->setPlaceholderText(tr("Put a sensible lobby name here")) ; - ui->nickName_LE->setPlaceholderText(tr("Your nickname for this lobby (Change default name in options->chat)")) ; + ui->lobbyName_LE->setPlaceholderText(tr("Put a sensible lobby name here")) ; + ui->nickName_LE->setPlaceholderText(tr("Your nickname for this lobby (Change default name in options->chat)")) ; #endif - ui->nickName_LE->setText(QString::fromStdString(default_nick)) ; + ui->nickName_LE->setText(QString::fromStdString(default_nick)) ; - connect( ui->shareButton, SIGNAL( clicked ( bool ) ), this, SLOT( createLobby( ) ) ); - connect( ui->cancelButton, SIGNAL( clicked ( bool ) ), this, SLOT( cancel( ) ) ); - connect( ui->lobbyName_LE, SIGNAL( textChanged ( QString ) ), this, SLOT( checkTextFields( ) ) ); - connect( ui->nickName_LE, SIGNAL( textChanged ( QString ) ), this, SLOT( checkTextFields( ) ) ); + connect( ui->shareButton, SIGNAL( clicked ( bool ) ), this, SLOT( createLobby( ) ) ); + connect( ui->cancelButton, SIGNAL( clicked ( bool ) ), this, SLOT( cancel( ) ) ); + connect( ui->lobbyName_LE, SIGNAL( textChanged ( QString ) ), this, SLOT( checkTextFields( ) ) ); + connect( ui->nickName_LE, SIGNAL( textChanged ( QString ) ), this, SLOT( checkTextFields( ) ) ); - connect(ui->keyShareList, SIGNAL(itemChanged( QTreeWidgetItem *, int ) ), - this, SLOT(togglePersonItem( QTreeWidgetItem *, int ) )); + connect(ui->keyShareList, SIGNAL(itemChanged( QTreeWidgetItem *, int ) ), this, SLOT(togglePersonItem( QTreeWidgetItem *, int ) )); - setShareList(peer_list); - checkTextFields() ; + setShareList(peer_list); + checkTextFields() ; } - CreateLobbyDialog::~CreateLobbyDialog() { - delete ui; -} - -void CreateLobbyDialog::closeEvent (QCloseEvent * event) -{ - QWidget::closeEvent(event); + delete ui; } void CreateLobbyDialog::changeEvent(QEvent *e) { - QDialog::changeEvent(e); - switch (e->type()) { - case QEvent::LanguageChange: - ui->retranslateUi(this); - break; - default: - break; - } + QDialog::changeEvent(e); + switch (e->type()) { + case QEvent::LanguageChange: + ui->retranslateUi(this); + break; + default: + break; + } } void CreateLobbyDialog::checkTextFields() @@ -87,105 +80,104 @@ void CreateLobbyDialog::checkTextFields() else ui->shareButton->setEnabled(true) ; } + void CreateLobbyDialog::createLobby() { - if(mShareList.empty()) - { - QMessageBox::warning(this, tr("RetroShare"),tr("Please select at least one peer"), - QMessageBox::Ok, QMessageBox::Ok); + if(mShareList.empty()) + { + QMessageBox::warning(this, "RetroShare", tr("Please select at least one friend"), QMessageBox::Ok, QMessageBox::Ok); + return; + } - return; - } + // create chat lobby !! + std::string lobby_name = ui->lobbyName_LE->text().toUtf8().constData() ; - // create chat lobby !! - std::string lobby_name = ui->lobbyName_LE->text().toUtf8().constData() ; + // add to group - // add to group + int lobby_privacy_type = (ui->security_CB->currentIndex() == 0)?RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC:RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE ; - int lobby_privacy_type = (ui->security_CB->currentIndex() == 0)?RS_CHAT_LOBBY_PRIVACY_LEVEL_PUBLIC:RS_CHAT_LOBBY_PRIVACY_LEVEL_PRIVATE ; + ChatLobbyId id = rsMsgs->createChatLobby(lobby_name, mShareList, lobby_privacy_type); - ChatLobbyId id = rsMsgs->createChatLobby(lobby_name, mShareList, lobby_privacy_type); + std::cerr << "gui: Created chat lobby " << std::hex << id << std::endl ; - std::cerr << "gui: Created chat lobby " << std::hex << id << std::endl ; + // set nick name ! - // set nick name ! + rsMsgs->setNickNameForChatLobby(id,ui->nickName_LE->text().toStdString()) ; - rsMsgs->setNickNameForChatLobby(id,ui->nickName_LE->text().toStdString()) ; + // open chat window !! + std::string vpid ; + + if(rsMsgs->getVirtualPeerId(id,vpid)) + ChatDialog::chatFriend(vpid) ; - // open chat window !! - std::string vpid ; - - if(rsMsgs->getVirtualPeerId(id,vpid)) - PopupChatDialog::chatFriend(vpid) ; - - close(); + close(); } void CreateLobbyDialog::cancel() { - close(); + close(); } void CreateLobbyDialog::setShareList(const std::list& friend_list) { - if (!rsPeers) - { - /* not ready yet! */ - return; - } + if (!rsPeers) + { + /* not ready yet! */ + return; + } - std::list peers; - std::list::iterator it; + std::list peers; + std::list::iterator it; - mShareList.clear() ; - rsPeers->getFriendList(peers); + mShareList.clear() ; + rsPeers->getFriendList(peers); - /* get a link to the table */ - QTreeWidget *shareWidget = ui->keyShareList; + /* get a link to the table */ + QTreeWidget *shareWidget = ui->keyShareList; - QList items; + QList items; - for(it = peers.begin(); it != peers.end(); it++) - { - RsPeerDetails detail; - if (!rsPeers->getPeerDetails(*it, detail)) - { - continue; /* BAD */ - } + for(it = peers.begin(); it != peers.end(); it++) + { + RsPeerDetails detail; + if (!rsPeers->getPeerDetails(*it, detail)) + { + continue; /* BAD */ + } - /* make a widget per friend */ - QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); + /* make a widget per friend */ + QTreeWidgetItem *item = new QTreeWidgetItem((QTreeWidget*)0); - item -> setText(0, PeerDefs::nameWithLocation(detail)); - if (detail.state & RS_PEER_STATE_CONNECTED) { - item -> setTextColor(0,(Qt::darkBlue)); - } - item -> setSizeHint(0, QSize( 17,17 ) ); - item -> setText(1, QString::fromStdString(detail.id)); - item -> setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + item -> setText(0, PeerDefs::nameWithLocation(detail)); + if (detail.state & RS_PEER_STATE_CONNECTED) { + item -> setTextColor(0,(Qt::darkBlue)); + } + item -> setSizeHint(0, QSize( 17,17 ) ); + item -> setText(1, QString::fromStdString(detail.id)); + item -> setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); - item -> setCheckState(0, Qt::Unchecked); + item -> setCheckState(0, Qt::Unchecked); - for(std::list::const_iterator it2(friend_list.begin());it2!=friend_list.end();++it2) - if(*it == *it2) - { - item -> setCheckState(0, Qt::Checked); - mShareList.push_back(*it) ; - break ; - } + for(std::list::const_iterator it2(friend_list.begin());it2!=friend_list.end();++it2) + if(*it == *it2) + { + item -> setCheckState(0, Qt::Checked); + mShareList.push_back(*it) ; + break ; + } - /* add to the list */ - items.append(item); - } + /* add to the list */ + items.append(item); + } - /* remove old items */ - shareWidget->clear(); - shareWidget->setColumnCount(1); + /* remove old items */ + shareWidget->clear(); + shareWidget->setColumnCount(1); - /* add the items in! */ - shareWidget->insertTopLevelItems(0, items); + /* add the items in! */ + shareWidget->insertTopLevelItems(0, items); - shareWidget->update(); /* update display */ + shareWidget->update(); /* update display */ } void CreateLobbyDialog::togglePersonItem( QTreeWidgetItem *item, int /*col*/ ) @@ -206,4 +198,3 @@ void CreateLobbyDialog::togglePersonItem( QTreeWidgetItem *item, int /*col*/ ) return; } - diff --git a/retroshare-gui/src/gui/chat/CreateLobbyDialog.h b/retroshare-gui/src/gui/chat/CreateLobbyDialog.h index f2ffaf948..743168354 100644 --- a/retroshare-gui/src/gui/chat/CreateLobbyDialog.h +++ b/retroshare-gui/src/gui/chat/CreateLobbyDialog.h @@ -1,41 +1,36 @@ -#ifndef SHAREKEY_H -#define SHAREKEY_H +#ifndef CREATELOBBYDIALOG_H +#define CREATELOBBYDIALOG_H #include #include "ui_CreateLobbyDialog.h" class CreateLobbyDialog : public QDialog { - Q_OBJECT + Q_OBJECT public: - /* - *@param chanId The channel id to send request for - */ - CreateLobbyDialog(const std::list& friends_list,QWidget *parent = 0, Qt::WFlags flags = 0, std::string grpId = "", int grpType = 0); - ~CreateLobbyDialog(); + /* + *@param chanId The channel id to send request for + */ + CreateLobbyDialog(const std::list& friends_list,QWidget *parent = 0, Qt::WFlags flags = 0, std::string grpId = "", int grpType = 0); + ~CreateLobbyDialog(); protected: - void changeEvent(QEvent *e); - void closeEvent (QCloseEvent * event); + void changeEvent(QEvent *e); private: + void setShareList(const std::list&); - void setShareList(const std::list&); + Ui::CreateLobbyDialog *ui; - Ui::CreateLobbyDialog *ui; - - std::string mGrpId; - std::list mShareList; - int mGrpType; + std::string mGrpId; + std::list mShareList; + int mGrpType; private slots: - - void createLobby(); - void checkTextFields(); - void cancel(); - void togglePersonItem(QTreeWidgetItem* item, int col); - - + void createLobby(); + void checkTextFields(); + void cancel(); + void togglePersonItem(QTreeWidgetItem* item, int col); }; -#endif // SHAREKEY_H +#endif // CREATELOBBYDIALOG_H diff --git a/retroshare-gui/src/gui/chat/CreateLobbyDialog.ui b/retroshare-gui/src/gui/chat/CreateLobbyDialog.ui index 7478967a6..f2a11fee0 100644 --- a/retroshare-gui/src/gui/chat/CreateLobbyDialog.ui +++ b/retroshare-gui/src/gui/chat/CreateLobbyDialog.ui @@ -174,11 +174,7 @@ p, li { white-space: pre-wrap; } - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Select the Friends with which you want to group chat.</span></p></body></html> + Select the Friends with which you want to group chat. @@ -211,9 +207,6 @@ p, li { white-space: pre-wrap; } 0
- - check peers you would like to share private publish key with - false @@ -351,7 +344,6 @@ p, li { white-space: pre-wrap; } - diff --git a/retroshare-gui/src/gui/chat/PopupChatDialog.cpp b/retroshare-gui/src/gui/chat/PopupChatDialog.cpp index a030d5d3e..ace3632a9 100644 --- a/retroshare-gui/src/gui/chat/PopupChatDialog.cpp +++ b/retroshare-gui/src/gui/chat/PopupChatDialog.cpp @@ -20,749 +20,181 @@ * Boston, MA 02110-1301, USA. ****************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "PopupChatDialog.h" -#include "ChatLobbyDialog.h" #include "PopupChatWindow.h" -#include "gui/RetroShareLink.h" -#include "util/misc.h" -#include "rshare.h" -#include -#include -#include -#include #include "gui/settings/rsharesettings.h" #include "gui/settings/RsharePeerSettings.h" #include "gui/notifyqt.h" -#include "../RsAutoUpdatePage.h" -#include "gui/common/StatusDefs.h" -#include "gui/common/AvatarDefs.h" -#include "gui/common/Emoticons.h" -#include "gui/common/PeerDefs.h" -#include "gui/common/FilesDefs.h" -#include "gui/im_history/ImHistoryBrowser.h" -#include "gui/msgs/MessageComposer.h" -#include +#include +#include + #include #define appDir QApplication::applicationDirPath() #define WINDOW(This) dynamic_cast(This->window()) -/***** - * #define CHAT_DEBUG 1 - *****/ - -static std::map chatDialogs; - -// play sound when recv a message -void playsound() -{ - Settings->beginGroup("Sound"); - Settings->beginGroup("SoundFilePath"); - QString OnlineSound = Settings->value("NewChatMessage","").toString(); - Settings->endGroup(); - Settings->beginGroup("Enable"); - bool flag = Settings->value("NewChatMessage",false).toBool(); - Settings->endGroup(); - Settings->endGroup(); - - if (!OnlineSound.isEmpty() && flag) { - if (QSound::isAvailable()) { - QSound::play(OnlineSound); - } - } -} - /** Default constructor */ -PopupChatDialog::PopupChatDialog(const std::string &id, const QString &name, QWidget *parent, Qt::WFlags flags) - : QWidget(parent, flags), dialogId(id), dialogName(name), - lastChatTime(0), lastChatName("") +PopupChatDialog::PopupChatDialog(QWidget *parent, Qt::WFlags flags) + : ChatDialog(parent, flags) { - /* Invoke Qt Designer generated QObject setup routine */ - ui.setupUi(this); + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); - newMessages = false; - typing = false; - manualDelete = false; - peerStatus = 0; + manualDelete = false; - last_status_send_time = 0 ; - chatStyle.setStyleFromSettings(ChatStyle::TYPE_PRIVATE); - - /* Hide or show the frames */ - showAvatarFrame(PeerSettings->getShowAvatarFrame(dialogId)); - ui.infoframe->setVisible(false); - ui.statusmessagelabel->hide(); - - connect(ui.avatarFrameButton, SIGNAL(toggled(bool)), this, SLOT(showAvatarFrame(bool))); - - connect(ui.sendButton, SIGNAL(clicked( ) ), this, SLOT(sendChat( ) )); - connect(ui.addFileButton, SIGNAL(clicked() ), this , SLOT(addExtraFile())); - - connect(ui.textboldButton, SIGNAL(clicked()), this, SLOT(setFont())); - connect(ui.textunderlineButton, SIGNAL(clicked()), this, SLOT(setFont())); - connect(ui.textitalicButton, SIGNAL(clicked()), this, SLOT(setFont())); - connect(ui.attachPictureButton, SIGNAL(clicked()), this, SLOT(addExtraPicture())); - connect(ui.fontButton, SIGNAL(clicked()), this, SLOT(getFont())); - connect(ui.colorButton, SIGNAL(clicked()), this, SLOT(setColor())); - connect(ui.emoteiconButton, SIGNAL(clicked()), this, SLOT(smileyWidget())); - connect(ui.actionSave_Chat_History, SIGNAL(triggered()), this, SLOT(fileSaveAs())); - connect(ui.actionClearOfflineMessages, SIGNAL(triggered()), this, SLOT(clearOfflineMessages())); - - connect(ui.hashBox, SIGNAL(fileHashingFinished(QList)), this, SLOT(fileHashingFinished(QList))); - - connect(NotifyQt::getInstance(), SIGNAL(peerStatusChanged(const QString&, int)), this, SLOT(updateStatus_slot(const QString&, int))); - connect(NotifyQt::getInstance(), SIGNAL(peerHasNewCustomStateString(const QString&, const QString&)), this, SLOT(updatePeersCustomStateString(const QString&, const QString&))); - - connect(ui.chattextEdit,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(contextMenu(QPoint))); - - ui.avatarWidget->setFrameType(AvatarWidget::STATUS_FRAME); - ui.avatarWidget->setId(dialogId, false); - - ui.ownAvatarWidget->setFrameType(AvatarWidget::STATUS_FRAME); - ui.ownAvatarWidget->setOwnId(); - - // Create the status bar - resetStatusBar(); - - ui.textboldButton->setIcon(QIcon(QString(":/images/edit-bold.png"))); - ui.textunderlineButton->setIcon(QIcon(QString(":/images/edit-underline.png"))); - ui.textitalicButton->setIcon(QIcon(QString(":/images/edit-italic.png"))); - ui.fontButton->setIcon(QIcon(QString(":/images/fonts.png"))); - ui.emoteiconButton->setIcon(QIcon(QString(":/images/emoticons/kopete/kopete020.png"))); - - ui.textboldButton->setCheckable(true); - ui.textunderlineButton->setCheckable(true); - ui.textitalicButton->setCheckable(true); - - setAcceptDrops(true); - ui.chattextEdit->setAcceptDrops(false); - ui.hashBox->setDropWidget(this); - ui.hashBox->setAutoHide(true); - - QMenu *toolmenu = new QMenu(); - toolmenu->addAction(ui.actionClear_Chat_History); - toolmenu->addAction(ui.actionDelete_Chat_History); - toolmenu->addAction(ui.actionSave_Chat_History); - toolmenu->addAction(ui.actionClearOfflineMessages); - toolmenu->addAction(ui.actionMessageHistory); - //toolmenu->addAction(ui.action_Disable_Emoticons); - ui.pushtoolsButton->setMenu(toolmenu); - - ui.chattextEdit->installEventFilter(this); - -#ifdef RS_RELEASE_VERSION - ui.attachPictureButton->setVisible(false); -#endif + connect(ui.avatarFrameButton, SIGNAL(toggled(bool)), this, SLOT(showAvatarFrame(bool))); + connect(ui.actionClearOfflineMessages, SIGNAL(triggered()), this, SLOT(clearOfflineMessages())); + connect(NotifyQt::getInstance(), SIGNAL(chatStatusChanged(const QString&, const QString&, bool)), this, SLOT(chatStatusChanged(const QString&, const QString&, bool))); } -void PopupChatDialog::init() +void PopupChatDialog::init(const std::string &peerId, const QString &peerName) { - if (!isChatLobby()) { - mCurrentColor.setNamedColor(PeerSettings->getPrivateChatColor(dialogId)); - mCurrentFont.fromString(PeerSettings->getPrivateChatFont(dialogId)); + ChatDialog::init(peerId, peerName); - // load settings - processSettings(true); + /* Hide or show the avatar frames */ + showAvatarFrame(PeerSettings->getShowAvatarFrame(peerId)); - // load style - PeerSettings->getStyle(dialogId, "PopupChatDialog", style); + ui.avatarWidget->setFrameType(AvatarWidget::STATUS_FRAME); + ui.avatarWidget->setId(peerId, false); - // initialize first status - StatusInfo peerStatusInfo; - // No check of return value. Non existing status info is handled as offline. - rsStatus->getStatus(dialogId, peerStatusInfo); - updateStatus(QString::fromStdString(dialogId), peerStatusInfo.status); + ui.ownAvatarWidget->setFrameType(AvatarWidget::STATUS_FRAME); + ui.ownAvatarWidget->setOwnId(); - // initialize first custom state string - QString customStateString = QString::fromUtf8(rsMsgs->getCustomStateString(dialogId).c_str()); - updatePeersCustomStateString(QString::fromStdString(dialogId), customStateString); + ui.chatWidget->addToolsAction(ui.actionClearOfflineMessages); - if (rsHistory->getEnable(false)) { - // get chat messages from history - std::list historyMsgs; - int messageCount = Settings->getPrivateChatHistoryCount(); - if (messageCount > 0) { - rsHistory->getMessages(dialogId, historyMsgs, messageCount); + // add offline chat messages + onChatChanged(NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_ADD); - std::list::iterator historyIt; - for (historyIt = historyMsgs.begin(); historyIt != historyMsgs.end(); historyIt++) { - addChatMsg(historyIt->incoming, QString::fromUtf8(historyIt->peerName.c_str()), QDateTime::fromTime_t(historyIt->sendTime), QDateTime::fromTime_t(historyIt->recvTime), QString::fromUtf8(historyIt->message.c_str()), TYPE_HISTORY); - } - } - } - // add offline chat messages - onPrivateChatChanged(NOTIFY_LIST_PRIVATE_OUTGOING_CHAT, NOTIFY_TYPE_ADD); - } + // add to window + PopupChatWindow *window = PopupChatWindow::getWindow(false); + if (window) { + window->addDialog(this); + } - colorChanged(mCurrentColor); - fontChanged(mCurrentFont); + // load settings + processSettings(true); } /** Destructor. */ PopupChatDialog::~PopupChatDialog() { - // save settings - processSettings(false); - - emit dialogClose(this); - - std::map::iterator it; - if (chatDialogs.end() != (it = chatDialogs.find(dialogId))) { - chatDialogs.erase(it); - } + // save settings + processSettings(false); } -void PopupChatDialog::processSettings(bool bLoad) +ChatWidget *PopupChatDialog::getChatWidget() { - Settings->beginGroup(QString("ChatDialog")); - - if (bLoad) { - // load settings - - // state of splitter - ui.chatsplitter->restoreState(Settings->value("ChatSplitter").toByteArray()); - } else { - // save settings - - // state of splitter - Settings->setValue("ChatSplitter", ui.chatsplitter->saveState()); - } - - Settings->endGroup(); + return ui.chatWidget; } -/*static*/ PopupChatDialog *PopupChatDialog::getExistingInstance(const std::string &id) +void PopupChatDialog::processSettings(bool load) { - std::map::iterator it; - if (chatDialogs.end() != (it = chatDialogs.find(id))) { - /* exists already */ - return it->second; - } + Settings->beginGroup(QString("PopupChatDialog")); - return NULL; + if (load) { + // load settings + } else { + // save settings + } + + Settings->endGroup(); } -/*static*/ PopupChatDialog *PopupChatDialog::getPrivateChat(const std::string &id, uint chatflags) +void PopupChatDialog::showDialog(uint chatflags) { - /* see if it already exists */ - PopupChatDialog *popupchatdialog = getExistingInstance(id); - - if (popupchatdialog == NULL) { - ChatLobbyId lobby_id; - if (rsMsgs->isLobbyId(id, lobby_id)) { - chatflags = RS_CHAT_OPEN; // use own flags - } - - if (chatflags & RS_CHAT_OPEN) { - RsPeerDetails sslDetails; - - if (rsPeers->getPeerDetails(id, sslDetails)) { - popupchatdialog = new PopupChatDialog(id, PeerDefs::nameWithLocation(sslDetails)); - popupchatdialog->init(); - chatDialogs[id] = popupchatdialog; - - popupchatdialog->addToParent(); - } else 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) { - popupchatdialog = new ChatLobbyDialog(id, lobby_id, QString::fromUtf8((*it).lobby_name.c_str())); - popupchatdialog->init(); - chatDialogs[id] = popupchatdialog; - - popupchatdialog->addToParent(); - } - } - } - } - } - - if (popupchatdialog == NULL) { - return NULL; - } - - popupchatdialog->insertChatMsgs(); - - PopupChatWindow *window = WINDOW(popupchatdialog); - if (window) { - window->showDialog(popupchatdialog, chatflags); - } - - return popupchatdialog; -} - -/*static*/ void PopupChatDialog::cleanupChat() -{ - PopupChatWindow::cleanup(); - - /* PopupChatDialog 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 PopupChatDialog::privateChatChanged(int list, int type) -{ - if (list == NOTIFY_LIST_PRIVATE_INCOMING_CHAT && type == NOTIFY_TYPE_ADD) { - std::list ids; - if (rsMsgs->getPrivateChatQueueIds(true, ids)) { - uint chatflags = Settings->getChatFlags(); - - std::list::iterator id; - for (id = ids.begin(); id != ids.end(); id++) { - PopupChatDialog *pcd = getPrivateChat(*id, chatflags); - - if (pcd) { - pcd->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->onPrivateChatChanged(list, type); - } - } -} - -bool PopupChatDialog::addToParent() -{ - PopupChatWindow *window = PopupChatWindow::getWindow(false); - if (window) { - window->addDialog(this); - return true; - } - - return false; -} - -/*static*/ void PopupChatDialog::closeChat(const std::string& id) -{ - PopupChatDialog *popupchatdialog = getExistingInstance(id); - - if (popupchatdialog) { - delete(popupchatdialog); - } -} - -/*static*/ void PopupChatDialog::chatFriend(const std::string &id) -{ - if (id.empty()){ - return; - } - std::cerr<<" popup dialog chat friend 1"<isLobbyId(id, lid)) { - getPrivateChat(id, RS_CHAT_OPEN | RS_CHAT_FOCUS); - return; - } - - RsPeerDetails detail; - if (!rsPeers->getPeerDetails(id, detail)) - return; - - std::string firstId; - - if (detail.isOnlyGPGdetail) { - //let's get the ssl child details, and open all the chat boxes - std::list sslIds; - rsPeers->getAssociatedSSLIds(detail.gpg_id, sslIds); - for (std::list::iterator it = sslIds.begin(); it != sslIds.end(); it++) { - if (firstId.empty()) { - firstId = *it; - } - - RsPeerDetails sslDetails; - if (rsPeers->getPeerDetails(*it, sslDetails)) { - if (sslDetails.state & RS_PEER_STATE_CONNECTED) { - getPrivateChat(*it, RS_CHAT_OPEN | RS_CHAT_FOCUS); - return; - } - } - } - } else { - if (detail.state & RS_PEER_STATE_CONNECTED) { - getPrivateChat(id, RS_CHAT_OPEN | RS_CHAT_FOCUS); - return; - } - firstId = id; - } - - /* info dialog */ - QMessageBox mb(QMessageBox::Question, tr("Friend not Online"), tr("Your Friend is offline \nDo you want to send them a Message instead"), QMessageBox::Yes | QMessageBox::No); - mb.setWindowIcon(QIcon(":/images/rstray3.png")); - if (mb.exec() == QMessageBox::Yes) { - MessageComposer::msgFriend(id, false); - } else { - if (firstId.empty() == false) { - getPrivateChat(firstId, RS_CHAT_OPEN | RS_CHAT_FOCUS); - } - } -} - -void PopupChatDialog::focusDialog() -{ - ui.chattextEdit->setFocus(); -} - -void PopupChatDialog::pasteLink() -{ - std::cerr << "In paste link" << std::endl ; - ui.chattextEdit->insertHtml(RSLinkClipboard::toHtml()) ; -} - -void PopupChatDialog::contextMenu( QPoint /*point*/ ) -{ - std::cerr << "In context menu" << std::endl ; - - QMenu *contextMnu = ui.chattextEdit->createStandardContextMenu(); - - contextMnu->addSeparator(); - QAction *action = contextMnu->addAction(QIcon(":/images/pasterslink.png"), tr("Paste RetroShare Link"), this, SLOT(pasteLink())); - action->setDisabled(RSLinkClipboard::empty()); - - contextMnu->exec(QCursor::pos()); - delete(contextMnu); -} - -void PopupChatDialog::resetStatusBar() -{ - ui.statusLabel->clear(); - ui.typingpixmapLabel->clear(); - - typing = false; - - emit infoChanged(this); -} - -void PopupChatDialog::updateStatusTyping() -{ - if (time(NULL) - last_status_send_time > 5) // limit 'peer is typing' packets to at most every 10 sec - { -#ifdef ONLY_FOR_LINGUIST - tr("is typing..."); -#endif - - rsMsgs->sendStatusString(dialogId, "is typing..."); - last_status_send_time = time(NULL) ; - } -} - -QString PopupChatDialog::makeStatusString(const QString& peer_id,const QString& status_string) const -{ - return QString::fromUtf8(rsPeers->getPeerName(peer_id.toStdString()).c_str()) + " " + tr(status_string.toAscii()); + PopupChatWindow *window = WINDOW(this); + if (window) { + window->showDialog(this, chatflags); + } } // Called by libretroshare through notifyQt to display the peer's status // -void PopupChatDialog::updateStatusString(const QString& peer_id, const QString& status_string) +void PopupChatDialog::chatStatusChanged(const QString &peerId, const QString& statusString, bool isPrivateChat) { - QString status = makeStatusString(peer_id, status_string) ; - ui.statusLabel->setText(status); // displays info for 5 secs. - ui.typingpixmapLabel->setPixmap(QPixmap(":images/typing.png") ); - - if (status_string == "is typing...") { - typing = true; - - emit infoChanged(this); - } - - QTimer::singleShot(5000,this,SLOT(resetStatusBar())) ; -} - -void PopupChatDialog::resizeEvent(QResizeEvent */*event*/) -{ - // Workaround: now the scroll position is correct calculated - QScrollBar *scrollbar = ui.textBrowser->verticalScrollBar(); - scrollbar->setValue(scrollbar->maximum()); -} - -void PopupChatDialog::showEvent(QShowEvent */*event*/) -{ - newMessages = false; - emit infoChanged(this); - focusDialog(); -} - -void PopupChatDialog::activate() -{ - PopupChatWindow *window = WINDOW(this); - if (window) { - if (window->isActiveWindow()) { - newMessages = false; - emit infoChanged(this); - focusDialog(); - } - } else { - newMessages = false; - emit infoChanged(this); - focusDialog(); - } -} - -void PopupChatDialog::onPrivateChatChanged(int list, int type) -{ - if (list == NOTIFY_LIST_PRIVATE_OUTGOING_CHAT) { - switch (type) { - case NOTIFY_TYPE_ADD: - { - if (!isChatLobby()) { - std::list savedOfflineChatNew; - - QString name = QString::fromUtf8(rsPeers->getPeerName(rsPeers->getOwnId()).c_str()); - - std::list offlineChat; - if (rsMsgs->getPrivateChatQueueCount(false) && rsMsgs->getPrivateChatQueue(false, dialogId, offlineChat)) { - ui.actionClearOfflineMessages->setEnabled(true); - - std::list::iterator it; - for(it = offlineChat.begin(); it != offlineChat.end(); it++) { - /* are they public? */ - if ((it->chatflags & RS_CHAT_PRIVATE) == 0) { - /* this should not happen */ - continue; - } - - savedOfflineChatNew.push_back(*it); - - if (std::find(savedOfflineChat.begin(), savedOfflineChat.end(), *it) != savedOfflineChat.end()) { - continue; - } - - QDateTime sendTime = QDateTime::fromTime_t(it->sendTime); - QDateTime recvTime = QDateTime::fromTime_t(it->recvTime); - QString message = QString::fromStdWString(it->msg); - - addChatMsg(false, name, sendTime, recvTime, message, TYPE_OFFLINE); - } - } - - savedOfflineChat = savedOfflineChatNew; - } - } - break; - case NOTIFY_TYPE_DEL: - { - if (!isChatLobby()) { - if (manualDelete == false) { - QString name = QString::fromUtf8(rsPeers->getPeerName(rsPeers->getOwnId()).c_str()); - - // now show saved offline chat messages as sent - std::list::iterator it; - for(it = savedOfflineChat.begin(); it != savedOfflineChat.end(); ++it) { - QDateTime sendTime = QDateTime::fromTime_t(it->sendTime); - QDateTime recvTime = QDateTime::fromTime_t(it->recvTime); - QString message = QString::fromStdWString(it->msg); - - addChatMsg(false, name, sendTime, recvTime, message, TYPE_NORMAL); - } - } - - savedOfflineChat.clear(); - } - } - break; - } - - ui.actionClearOfflineMessages->setEnabled(!savedOfflineChat.empty()); - } + if (isPrivateChat && this->peerId == peerId.toStdString()) { + ui.chatWidget->updateStatusString(QString::fromUtf8(rsPeers->getPeerName(this->peerId).c_str()) + " %1", statusString); + } } void PopupChatDialog::addIncomingChatMsg(const ChatInfo& info) { - QDateTime sendTime = QDateTime::fromTime_t(info.sendTime); - QDateTime recvTime = QDateTime::fromTime_t(info.recvTime); - QString message = QString::fromStdWString(info.msg); - QString name = QString::fromUtf8(rsPeers->getPeerName(info.rsid).c_str()) ; + ChatWidget *cw = getChatWidget(); + if (cw) { + QDateTime sendTime = QDateTime::fromTime_t(info.sendTime); + QDateTime recvTime = QDateTime::fromTime_t(info.recvTime); + QString message = QString::fromStdWString(info.msg); + QString name = QString::fromUtf8(rsPeers->getPeerName(info.rsid).c_str()) ; - addChatMsg(true, name, sendTime, recvTime, message, TYPE_NORMAL); + cw->addChatMsg(true, name, sendTime, recvTime, message, ChatWidget::TYPE_NORMAL); + } } -void PopupChatDialog::insertChatMsgs() +void PopupChatDialog::onChatChanged(int list, int type) { - std::list newchat; - if (!rsMsgs->getPrivateChatQueue(true, dialogId, newchat)) - { -#ifdef PEERS_DEBUG - std::cerr << "no chat for " << dialogId << " available." << std::endl ; -#endif - return; - } + if (list == NOTIFY_LIST_PRIVATE_OUTGOING_CHAT) { + switch (type) { + case NOTIFY_TYPE_ADD: + { + std::list savedOfflineChatNew; - 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; - } + QString name = QString::fromUtf8(rsPeers->getPeerName(rsPeers->getOwnId()).c_str()); - addIncomingChatMsg(*it) ; - } + std::list offlineChat; + if (rsMsgs->getPrivateChatQueueCount(false) && rsMsgs->getPrivateChatQueue(false, peerId, offlineChat)) { + ui.actionClearOfflineMessages->setEnabled(true); - rsMsgs->clearPrivateChatQueue(true, dialogId); + std::list::iterator it; + for(it = offlineChat.begin(); it != offlineChat.end(); it++) { + /* are they public? */ + if ((it->chatflags & RS_CHAT_PRIVATE) == 0) { + /* this should not happen */ + continue; + } - playsound(); + savedOfflineChatNew.push_back(*it); - emit newMessage(this); + if (std::find(savedOfflineChat.begin(), savedOfflineChat.end(), *it) != savedOfflineChat.end()) { + continue; + } - PopupChatWindow *window = WINDOW(this); - if (isVisible() == false || (window && window->isActiveWindow() == false)) { - newMessages = true; - } + QDateTime sendTime = QDateTime::fromTime_t(it->sendTime); + QDateTime recvTime = QDateTime::fromTime_t(it->recvTime); + QString message = QString::fromStdWString(it->msg); - emit infoChanged(this); -} + ui.chatWidget->addChatMsg(false, name, sendTime, recvTime, message, ChatWidget::TYPE_OFFLINE); + } + } -void PopupChatDialog::addChatMsg(bool incoming, const QString &name, const QDateTime &sendTime, const QDateTime &recvTime, const QString &message, enumChatType chatType) -{ -#ifdef CHAT_DEBUG - std::cout << "PopupChatDialog:addChatMsg message : " << message.toStdString() << std::endl; -#endif + savedOfflineChat = savedOfflineChatNew; + } + break; + case NOTIFY_TYPE_DEL: + { + if (manualDelete == false) { + QString name = QString::fromUtf8(rsPeers->getPeerName(rsPeers->getOwnId()).c_str()); - unsigned int formatFlag = CHAT_FORMATMSG_EMBED_LINKS; + // now show saved offline chat messages as sent + std::list::iterator it; + for(it = savedOfflineChat.begin(); it != savedOfflineChat.end(); ++it) { + QDateTime sendTime = QDateTime::fromTime_t(it->sendTime); + QDateTime recvTime = QDateTime::fromTime_t(it->recvTime); + QString message = QString::fromStdWString(it->msg); - // embed smileys ? - if (Settings->valueFromGroup(QString("Chat"), QString::fromUtf8("Emoteicons_PrivatChat"), true).toBool()) { - formatFlag |= CHAT_FORMATMSG_EMBED_SMILEYS; - } + ui.chatWidget->addChatMsg(false, name, sendTime, recvTime, message, ChatWidget::TYPE_NORMAL); + } + } - ChatStyle::enumFormatMessage type; - if (chatType == TYPE_OFFLINE) { - type = ChatStyle::FORMATMSG_OOUTGOING; - } else if (chatType == TYPE_HISTORY) { - type = incoming ? ChatStyle::FORMATMSG_HINCOMING : ChatStyle::FORMATMSG_HOUTGOING; - } else { - type = incoming ? ChatStyle::FORMATMSG_INCOMING : ChatStyle::FORMATMSG_OUTGOING; - } + savedOfflineChat.clear(); + } + break; + } - QString formatMsg = chatStyle.formatMessage(type, name, incoming ? sendTime : recvTime, message, formatFlag); - - ui.textBrowser->append(formatMsg); - - /* Scroll to the end */ - QScrollBar *scrollbar = ui.textBrowser->verticalScrollBar(); - scrollbar->setValue(scrollbar->maximum()); - - resetStatusBar(); -} - -bool PopupChatDialog::eventFilter(QObject *obj, QEvent *event) -{ - if (obj == ui.chattextEdit) { - if (event->type() == QEvent::KeyPress) { - updateStatusTyping() ; - - QKeyEvent *keyEvent = static_cast(event); - if (keyEvent && (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return)) { - // Enter pressed - if (Settings->getChatSendMessageWithCtrlReturn()) { - if (keyEvent->modifiers() & Qt::ControlModifier) { - // send message with Ctrl+Enter - sendChat(); - return true; // eat event - } - } else { - if (keyEvent->modifiers() & Qt::ControlModifier) { - // insert return - ui.chattextEdit->textCursor().insertText("\n"); - } else { - // send message with Enter - sendChat(); - } - return true; // eat event - } - } - } - } - // pass the event on to the parent class - return QWidget::eventFilter(obj, event); -} - -void PopupChatDialog::sendChat() -{ - QTextEdit *chatWidget = ui.chattextEdit; - - if (chatWidget->toPlainText().isEmpty()) { - // nothing to send - return; - } - - QString text; - RsHtml::optimizeHtml(chatWidget, text); - std::wstring msg = text.toStdWString(); - - if (msg.empty()) { - // nothing to send - return; - } - - std::string ownId; - - { - rsiface->lockData(); /* Lock Interface */ - const RsConfig &conf = rsiface->getConfig(); - - ownId = conf.ownId; - - rsiface->unlockData(); /* Unlock Interface */ - } - -#ifdef CHAT_DEBUG - std::cout << "PopupChatDialog:sendChat " << std::endl; -#endif - - if (sendPrivateChat(msg)) - { - QDateTime currentTime = QDateTime::currentDateTime(); - addChatMsg(false, QString::fromUtf8(rsPeers->getPeerName(ownId).c_str()), currentTime, currentTime, QString::fromStdWString(msg), TYPE_NORMAL); - } - - chatWidget->clear(); - // workaround for Qt bug - http://bugreports.qt.nokia.com/browse/QTBUG-2533 - // QTextEdit::clear() does not reset the CharFormat if document contains hyperlinks that have been accessed. - chatWidget->setCurrentCharFormat(QTextCharFormat ()); - - setFont(); -} - -bool PopupChatDialog::sendPrivateChat(const std::wstring& msg) -{ - return rsMsgs->sendPrivateChat(dialogId, msg) ; + ui.actionClearOfflineMessages->setEnabled(!savedOfflineChat.empty()); + } } /** @@ -770,297 +202,23 @@ bool PopupChatDialog::sendPrivateChat(const std::wstring& msg) */ void PopupChatDialog::showAvatarFrame(bool show) { - if (show) { - ui.avatarframe->setVisible(true); - ui.avatarFrameButton->setChecked(true); - ui.avatarFrameButton->setToolTip(tr("Hide Avatar")); - ui.avatarFrameButton->setIcon(QIcon(":images/hide_toolbox_frame.png")); - } else { - ui.avatarframe->setVisible(false); - ui.avatarFrameButton->setChecked(false); - ui.avatarFrameButton->setToolTip(tr("Show Avatar")); - ui.avatarFrameButton->setIcon(QIcon(":images/show_toolbox_frame.png")); - } + ui.avatarframe->setVisible(show); + ui.avatarFrameButton->setChecked(show); - PeerSettings->setShowAvatarFrame(dialogId, show); -} + if (show) { + ui.avatarFrameButton->setToolTip(tr("Hide Avatar")); + ui.avatarFrameButton->setIcon(QIcon(":images/hide_toolbox_frame.png")); + } else { + ui.avatarFrameButton->setToolTip(tr("Show Avatar")); + ui.avatarFrameButton->setIcon(QIcon(":images/show_toolbox_frame.png")); + } -void PopupChatDialog::on_closeInfoFrameButton_clicked() -{ - ui.infoframe->setVisible(false); -} - -void PopupChatDialog::setColor() -{ - bool ok; - QRgb color = QColorDialog::getRgba(ui.chattextEdit->textColor().rgba(), &ok, window()); - if (ok) { - mCurrentColor = QColor(color); - PeerSettings->setPrivateChatColor(dialogId, mCurrentColor.name()); - colorChanged(mCurrentColor); - } - setFont(); -} - -void PopupChatDialog::colorChanged(const QColor &c) -{ - QPixmap pix(16, 16); - pix.fill(c); - ui.colorButton->setIcon(pix); -} - -void PopupChatDialog::getFont() -{ - bool ok; - QFont font = QFontDialog::getFont(&ok, mCurrentFont, this); - if (ok) { - fontChanged(font); - } -} - -void PopupChatDialog::fontChanged(const QFont &font) -{ - mCurrentFont = font; - - ui.textboldButton->setChecked(mCurrentFont.bold()); - ui.textunderlineButton->setChecked(mCurrentFont.underline()); - ui.textitalicButton->setChecked(mCurrentFont.italic()); - - setFont(); -} - -void PopupChatDialog::setFont() -{ - mCurrentFont.setBold(ui.textboldButton->isChecked()); - mCurrentFont.setUnderline(ui.textunderlineButton->isChecked()); - mCurrentFont.setItalic(ui.textitalicButton->isChecked()); - - ui.chattextEdit->setFont(mCurrentFont); - ui.chattextEdit->setTextColor(mCurrentColor); - - ui.chattextEdit->setFocus(); - - PeerSettings->setPrivateChatFont(dialogId, mCurrentFont.toString()); -} - -//============================================================================ - -void PopupChatDialog::smileyWidget() -{ - Emoticons::showSmileyWidget(this, ui.emoteiconButton, SLOT(addSmiley()), true); -} - -//============================================================================ - -void PopupChatDialog::addSmiley() -{ - ui.chattextEdit->textCursor().insertText(qobject_cast(sender())->toolTip().split("|").first()); -} - -//============================================================================ - -void PopupChatDialog::on_actionClear_Chat_History_triggered() -{ - ui.textBrowser->clear(); -} - -void PopupChatDialog::on_actionDelete_Chat_History_triggered() -{ - if ((QMessageBox::question(this, "RetroShare", tr("Do you really want to physically delete the history?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)) == QMessageBox::Yes) { - on_actionClear_Chat_History_triggered(); - rsHistory->clear(dialogId); - } -} - -void PopupChatDialog::addExtraFile() -{ - QStringList files; - if (misc::getOpenFileNames(this, RshareSettings::LASTDIR_EXTRAFILE, tr("Add Extra File"), "", files)) { - ui.hashBox->addAttachments(files/*, 0*/); - } -} - -void PopupChatDialog::addExtraPicture() -{ - // select a picture file - QString file; - if (misc::getOpenFileName(window(), RshareSettings::LASTDIR_IMAGES, tr("Load Picture File"), "Pictures (*.png *.xpm *.jpg)", file)) { - ui.hashBox->addAttachments(QStringList(file), HashedFile::Picture); - } -} - -void PopupChatDialog::fileHashingFinished(QList hashedFiles) -{ - std::cerr << "PopupChatDialog::fileHashingFinished() started." << std::endl; - - QString message; - - QList::iterator it; - for (it = hashedFiles.begin(); it != hashedFiles.end(); ++it) { - HashedFile& hashedFile = *it; - QString ext = QFileInfo(hashedFile.filename).suffix(); - - RetroShareLink link; - link.createFile(hashedFile.filename, hashedFile.size, QString::fromStdString(hashedFile.hash)); - - if (hashedFile.flag & HashedFile::Picture) { - message += QString("").arg(hashedFile.filepath); - message+="
"; - } else { - QString image = FilesDefs::getImageFromFilename(hashedFile.filename, false); - if (!image.isEmpty()) { - message += QString("").arg(image); - } - } - message += link.toHtmlSize(); - if (it != hashedFiles.end()) { - message += "
"; - } - } - -#ifdef CHAT_DEBUG - std::cerr << "PopupChatDialog::fileHashingFinished message : " << message.toStdString() << std::endl; -#endif - - /* convert to real html document */ - QTextBrowser textBrowser; - textBrowser.setHtml(message); - std::wstring msg = textBrowser.toHtml().toStdWString(); - - if (rsMsgs->sendPrivateChat(dialogId, msg)) { - std::string ownId = rsPeers->getOwnId(); - QDateTime currentTime = QDateTime::currentDateTime(); - addChatMsg(false, QString::fromUtf8(rsPeers->getPeerName(ownId).c_str()), currentTime, currentTime, QString::fromStdWString(msg), TYPE_NORMAL); - } -} - -bool PopupChatDialog::fileSave() -{ - if (fileName.isEmpty()) - return fileSaveAs(); - - QFile file(fileName); - if (!file.open(QFile::WriteOnly)) - return false; - QTextStream ts(&file); - ts.setCodec(QTextCodec::codecForName("UTF-8")); - ts << ui.textBrowser->document()->toPlainText(); - ui.textBrowser->document()->setModified(false); - return true; -} - -bool PopupChatDialog::fileSaveAs() -{ - QString fn; - if (misc::getSaveFileName(window(), RshareSettings::LASTDIR_HISTORY, tr("Save as..."), tr("Text File (*.txt );;All Files (*)"), fn)) { - setCurrentFileName(fn); - return fileSave(); - } - - return false; -} - -void PopupChatDialog::setCurrentFileName(const QString &fileName) -{ - this->fileName = fileName; - ui.textBrowser->document()->setModified(false); - - setWindowModified(false); + PeerSettings->setShowAvatarFrame(getPeerId(), show); } void PopupChatDialog::clearOfflineMessages() { - manualDelete = true; - rsMsgs->clearPrivateChatQueue(false, dialogId); - manualDelete = false; -} - -void PopupChatDialog::updateStatus_slot(const QString &peer_id, int status) -{ - updateStatus(peer_id, status); -} - -void PopupChatDialog::updateStatus(const QString &peer_id, int status) -{ - std::string stdPeerId = peer_id.toStdString(); - - /* set font size for status */ - if (stdPeerId == dialogId) { - // the peers status has changed - - switch (status) { - case RS_STATUS_OFFLINE: - ui.infoframe->setVisible(true); - ui.infolabel->setText(dialogName + " " + tr("apears to be Offline.") +"\n" + tr("Messages you send will be delivered after Friend is again Online")); - break; - - case RS_STATUS_INACTIVE: - ui.infoframe->setVisible(true); - ui.infolabel->setText(dialogName + " " + tr("is Idle and may not reply")); - break; - - case RS_STATUS_ONLINE: - ui.infoframe->setVisible(false); - break; - - case RS_STATUS_AWAY: - ui.infolabel->setText(dialogName + " " + tr("is Away and may not reply")); - ui.infoframe->setVisible(true); - break; - - case RS_STATUS_BUSY: - ui.infolabel->setText(dialogName + " " + tr("is Busy and may not reply")); - ui.infoframe->setVisible(true); - break; - } - - QString statusString("%1"); - ui.friendnamelabel->setText(dialogName + " (" + statusString.arg(StatusDefs::name(status)) + ")") ; - - peerStatus = status; - - emit infoChanged(this); - - return; - } - - // ignore status change -} - -void PopupChatDialog::updatePeersCustomStateString(const QString& peer_id, const QString& status_string) -{ - std::string stdPeerId = peer_id.toStdString(); - QString status_text; - - if (stdPeerId == dialogId) { - // the peers status string has changed - if (status_string.isEmpty()) { - ui.statusmessagelabel->hide(); - } else { - ui.statusmessagelabel->show(); - status_text = RsHtml::formatText(status_string, RSHTML_FORMATTEXT_EMBED_SMILEYS | RSHTML_FORMATTEXT_EMBED_LINKS); - ui.statusmessagelabel->setText(status_text); - } - } -} - -void PopupChatDialog::on_actionMessageHistory_triggered() -{ - ImHistoryBrowser imBrowser(dialogId, ui.chattextEdit, window()); - imBrowser.exec(); -} - -bool PopupChatDialog::setStyle() -{ - if (style.showDialog(window())) { - PeerSettings->setStyle(dialogId, "PopupChatDialog", style); - return true; - } - - return false; -} - -const RSStyle &PopupChatDialog::getStyle() -{ - return style; + manualDelete = true; + rsMsgs->clearPrivateChatQueue(false, peerId); + manualDelete = false; } diff --git a/retroshare-gui/src/gui/chat/PopupChatDialog.h b/retroshare-gui/src/gui/chat/PopupChatDialog.h index 3e9cb8dce..579829eeb 100644 --- a/retroshare-gui/src/gui/chat/PopupChatDialog.h +++ b/retroshare-gui/src/gui/chat/PopupChatDialog.h @@ -24,151 +24,44 @@ #define _POPUPCHATDIALOG_H #include "ui_PopupChatDialog.h" - -class QAction; -class QTextEdit; -class QTextCharFormat; -class ChatInfo; +#include "ChatDialog.h" #include -#include "ChatStyle.h" -#include "gui/style/RSStyle.h" -class PopupChatDialog : public QWidget +class PopupChatDialog : public ChatDialog { - Q_OBJECT + Q_OBJECT -public: - enum enumChatType { TYPE_NORMAL, TYPE_HISTORY, TYPE_OFFLINE }; - -public: - static PopupChatDialog *getExistingInstance(const std::string &id); - static PopupChatDialog *getPrivateChat(const std::string &id, uint chatflags); - static void cleanupChat(); - static void chatFriend(const std::string &id); - static void closeChat(const std::string &id); - static void privateChatChanged(int list, int type); - - void init(); - - void updateStatusString(const QString& peer_id, const QString& statusString); - std::string getPeerId() { return dialogId; } - QString getTitle() { return dialogName; } - bool hasNewMessages() { return newMessages; } - bool isTyping() { return typing; } - int getPeerStatus() { return peerStatus; } - void focusDialog(); - void activate(); - bool setStyle(); - const RSStyle &getStyle(); - virtual void updateStatus(const QString &peer_id, int status); - - // derived in ChatLobbyDialog. - // - virtual bool hasPeerStatus() { return true; } - virtual bool canClose() { return true; } - -signals: - void dialogClose(PopupChatDialog *dialog); - void infoChanged(PopupChatDialog *dialog); - void newMessage(PopupChatDialog *dialog); - -public slots: - void updateStatus_slot(const QString &peer_id, int status); - -protected: - /** Default constructor */ - PopupChatDialog(const std::string &id, const QString &name, QWidget *parent = 0, Qt::WFlags flags = 0); - /** Default destructor */ - ~PopupChatDialog(); - - virtual void resizeEvent(QResizeEvent *event); - virtual void showEvent(QShowEvent *event); - - bool eventFilter(QObject *obj, QEvent *ev); - - void insertChatMsgs(); - void addChatMsg(bool incoming, const QString &name, const QDateTime &sendTime, const QDateTime &recvTime, const QString &message, enumChatType chatType); - - // derived in ChatLobbyDialog. - // - virtual bool addToParent(); - virtual bool isChatLobby() { return false; } // TODO: spilt into a good base class - virtual void addIncomingChatMsg(const ChatInfo& info); - virtual QString makeStatusString(const QString& peer_id, const QString& status_string) const; + friend class ChatDialog; private slots: - void pasteLink() ; - void contextMenu(QPoint) ; - - void fileHashingFinished(QList hashedFiles); - - void smileyWidget(); - void addSmiley(); - - void resetStatusBar() ; - void updateStatusTyping() ; - - void on_actionMessageHistory_triggered(); - void addExtraFile(); - void addExtraPicture(); - void showAvatarFrame(bool show); - void on_closeInfoFrameButton_clicked(); - - void setColor(); - void getFont(); - void setFont(); - - void sendChat(); - - void updatePeersCustomStateString(const QString& peer_id, const QString& status_string) ; - - void on_actionClear_Chat_History_triggered(); - void on_actionDelete_Chat_History_triggered(); - - bool fileSave(); - bool fileSaveAs(); - void clearOfflineMessages(); - -private: - void setCurrentFileName(const QString &fileName); - - void colorChanged(const QColor &c); - void fontChanged(const QFont &font); - void processSettings(bool bLoad); - - void onPrivateChatChanged(int list, int type); - - QAction *actionTextBold; - QAction *actionTextUnderline; - QAction *actionTextItalic; - - std::string dialogId; - QString dialogName; - unsigned int lastChatTime; - std::string lastChatName; - - time_t last_status_send_time ; - QColor mCurrentColor; - QFont mCurrentFont; - - std::list savedOfflineChat; - QString wholeChat; - QString fileName; - - bool newMessages; - bool typing; - int peerStatus; - ChatStyle chatStyle; - bool manualDelete; - - RSStyle style; + void showAvatarFrame(bool show); + void clearOfflineMessages(); + void chatStatusChanged(const QString &peerId, const QString &statusString, bool isPrivateChat); protected: - virtual bool sendPrivateChat(const std::wstring& msg) ; // can be derived to send chat to e.g. a chat lobby + /** Default constructor */ + PopupChatDialog(QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + virtual ~PopupChatDialog(); - /** Qt Designer generated object */ - Ui::PopupChatDialog ui; + virtual void init(const std::string &peerId, const QString &peerName); + virtual void showDialog(uint chatflags); + virtual ChatWidget *getChatWidget(); + virtual bool hasPeerStatus() { return true; } + + void processSettings(bool load); + +protected: + virtual void addIncomingChatMsg(const ChatInfo& info); + virtual void onChatChanged(int list, int type); + +private: + bool manualDelete; + std::list savedOfflineChat; + + /** Qt Designer generated object */ + Ui::PopupChatDialog ui; }; #endif diff --git a/retroshare-gui/src/gui/chat/PopupChatDialog.ui b/retroshare-gui/src/gui/chat/PopupChatDialog.ui index c26ace544..d94268db9 100644 --- a/retroshare-gui/src/gui/chat/PopupChatDialog.ui +++ b/retroshare-gui/src/gui/chat/PopupChatDialog.ui @@ -40,7 +40,7 @@ 1 - + @@ -111,7 +111,7 @@ - + @@ -189,731 +189,24 @@ - - - - QFrame#frame_2{border: transparent} - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 2 - - - 3 - - - 3 - - - 3 - - - - - - 0 - 0 - - - - - Arial - 13 - 75 - true - true - - - - TextLabel - - - - - - - - Arial - 9 - - - - TextLabel - - - - - - - - - - QFrame#infoframe{border: 1px solid #DCDC41; -border-radius: 6px; -background: #FFFFD7; -background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, -stop:0 #FFFFD7, stop:1 #FFFFB2);} - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 6 - - - - - - 16 - 16 - - - - - - - :/images/info16.png - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - TextLabel - - - - - - - - 16 - 16 - - - - Qt::NoFocus - - - Close - - - QToolButton -{ - border-image: url(:/images/closenormal.png) -} - -QToolButton:hover -{ -border-image: url(:/images/closehover.png) -} - -QToolButton:pressed { -border-image: url(:/images/closepressed.png) -} - - - - - - true - - - - - - - - - - - 347 - 30 - - - - - 16777215 - 30 - - - - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - 1 - - - 6 - - - - - - 28 - 28 - - - - - 28 - 28 - - - - Qt::NoFocus - - - QPushButton::menu-indicator { -subcontrol-origin: padding; -subcontrol-position: bottom right; -} - -QPushButton::menu-indicator:pressed, QPushButton::menu-indicator:open { -position: relative; -top: 1px; left: 1px; /* shift the arrow by 2 px */ -} - -QPushButton:hover { -border: 1px solid #CCCCCC; -} - - - - - - - :/images/configure.png:/images/configure.png - - - - 22 - 22 - - - - true - - - - - - - - 28 - 28 - - - - - 28 - 28 - - - - Qt::NoFocus - - - Attach a Picture - - - - - - - :/images/add_image24.png:/images/add_image24.png - - - - 24 - 24 - - - - true - - - - - - - - 28 - 28 - - - - Qt::NoFocus - - - Add a File for your Friend - - - - - - - :/images/add-share24.png:/images/add-share24.png - - - - 24 - 24 - - - - true - - - - - - - Qt::Horizontal - - - - 190 - 25 - - - - - - - - Send - - - - - - - - 0 - 0 - - - - - 28 - 28 - - - - - 28 - 28 - - - - Qt::NoFocus - - - - - - - 24 - 24 - - - - true - - - - - - - - 28 - 28 - - - - - 28 - 28 - - - - Qt::NoFocus - - - Bold - - - - - - - ../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup - - - false - - - true - - - - - - - - 28 - 28 - - - - - 28 - 28 - - - - Qt::NoFocus - - - Underline - - - - - - - ../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup - - - false - - - true - - - - - - - - 28 - 28 - - - - - 28 - 28 - - - - Qt::NoFocus - - - Italic - - - - - - - ../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup - - - false - - - true - - - - - - - - 28 - 28 - - - - - 28 - 28 - - - - Qt::NoFocus - - - Font - - - - - - - ../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup../../../../../../../Dokumente und Einstellungen/Linux/.designer/backup - - - false - - - true - - - - - - - - 28 - 28 - - - - - 28 - 28 - - - - Qt::NoFocus - - - Text Color - - - - - - true - - - - - - - - - - 1 - - - Qt::Vertical - - - 2 - - - false - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - QTextBrowser{border: 1px solid #B8B6B1; -border-radius: 6px; -background: white;} - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"></p></body></html> - - - true - - - true - - - - - - - - - 0 - - - - - - - - 0 - - - 3 - - - - - - - - 0 - 0 - - - - - 0 - 30 - - - - Qt::CustomContextMenu - - - QTextEdit{border: 1px solid #B8B6B1; -border-radius: 6px; -background: white;} - - - - - - - - 18 - 18 - - - - - 18 - 18 - - - - T - - - Qt::AlignCenter - - - - - - - - - - - true + + + + + 0 + 0 + - - - Bold - - - - - Italic - - - - - Underline - - - - - Strike - - - - - - :/images/edit-clear-history.png:/images/edit-clear-history.png - - - Clear Chat History - - - - - true - - - Disable Emoticons - - - - - Save Chat History - - - Save Chat History - - Clear offline messages - - - Browse Message History - - - Browse History - - - - - - :/images/edit-clear-history.png:/images/edit-clear-history.png - - - Delete Chat History - - - Deletes all stored and displayed chat history - - @@ -923,14 +216,12 @@ background: white;} 1 - HashBox - QScrollArea -
gui/common/HashBox.h
+ ChatWidget + QWidget +
gui/chat/ChatWidget.h
1
- - - + diff --git a/retroshare-gui/src/gui/chat/PopupChatWindow.cpp b/retroshare-gui/src/gui/chat/PopupChatWindow.cpp index 30477c91e..ed63ce55c 100644 --- a/retroshare-gui/src/gui/chat/PopupChatWindow.cpp +++ b/retroshare-gui/src/gui/chat/PopupChatWindow.cpp @@ -16,14 +16,14 @@ * * 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, + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. ****************************************************************/ #include #include "PopupChatWindow.h" -#include "PopupChatDialog.h" +#include "ChatDialog.h" #include "gui/settings/rsharesettings.h" #include "gui/settings/RsharePeerSettings.h" #include "gui/common/StatusDefs.h" @@ -41,334 +41,331 @@ static PopupChatWindow *instance = NULL; /*static*/ PopupChatWindow *PopupChatWindow::getWindow(bool needSingleWindow) { - if (needSingleWindow == false && (Settings->getChatFlags() & RS_CHAT_TABBED_WINDOW)) { - if (instance == NULL) { - instance = new PopupChatWindow(true); - } + if (needSingleWindow == false && (Settings->getChatFlags() & RS_CHAT_TABBED_WINDOW)) { + if (instance == NULL) { + instance = new PopupChatWindow(true); + } - return instance; - } + return instance; + } - return new PopupChatWindow(false); + return new PopupChatWindow(false); } /*static*/ void PopupChatWindow::cleanup() { - if (instance) { - delete(instance); - instance = NULL; - } + if (instance) { + delete(instance); + instance = NULL; + } } /** Default constructor */ PopupChatWindow::PopupChatWindow(bool tabbed, QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags) { - /* Invoke Qt Designer generated QObject setup routine */ - ui.setupUi(this); + /* Invoke Qt Designer generated QObject setup routine */ + ui.setupUi(this); - tabbedWindow = tabbed; - firstShow = true; - chatDialog = NULL; + tabbedWindow = tabbed; + firstShow = true; + chatDialog = NULL; - ui.tabWidget->setVisible(tabbedWindow); + ui.tabWidget->setVisible(tabbedWindow); - if (Settings->getChatFlags() & RS_CHAT_TABBED_WINDOW) { - ui.actionDockTab->setVisible(tabbedWindow == false); - ui.actionUndockTab->setVisible(tabbedWindow); - } else { - ui.actionDockTab->setVisible(false); - ui.actionUndockTab->setVisible(false); - } + if (Settings->getChatFlags() & RS_CHAT_TABBED_WINDOW) { + ui.actionDockTab->setVisible(tabbedWindow == false); + ui.actionUndockTab->setVisible(tabbedWindow); + } else { + ui.actionDockTab->setVisible(false); + ui.actionUndockTab->setVisible(false); + } - setAttribute(Qt::WA_DeleteOnClose, true); + setAttribute(Qt::WA_DeleteOnClose, true); - connect(ui.actionAvatar, SIGNAL(triggered()),this, SLOT(getAvatar())); - connect(ui.actionColor, SIGNAL(triggered()), this, SLOT(setStyle())); - connect(ui.actionDockTab, SIGNAL(triggered()), this, SLOT(dockTab())); - connect(ui.actionUndockTab, SIGNAL(triggered()), this, SLOT(undockTab())); - connect(ui.actionSetOnTop, SIGNAL(toggled(bool)), this, SLOT(setOnTop())); + connect(ui.actionAvatar, SIGNAL(triggered()),this, SLOT(getAvatar())); + connect(ui.actionColor, SIGNAL(triggered()), this, SLOT(setStyle())); + connect(ui.actionDockTab, SIGNAL(triggered()), this, SLOT(dockTab())); + connect(ui.actionUndockTab, SIGNAL(triggered()), this, SLOT(undockTab())); + connect(ui.actionSetOnTop, SIGNAL(toggled(bool)), this, SLOT(setOnTop())); - connect(ui.tabWidget, SIGNAL(tabChanged(PopupChatDialog*)), this, SLOT(tabChanged(PopupChatDialog*))); + connect(ui.tabWidget, SIGNAL(tabChanged(ChatDialog*)), this, SLOT(tabChanged(ChatDialog*))); - if (tabbedWindow) { - /* signal toggled is called */ - ui.actionSetOnTop->setChecked(Settings->valueFromGroup("ChatWindow", "OnTop", false).toBool()); - } + if (tabbedWindow) { + /* signal toggled is called */ + ui.actionSetOnTop->setChecked(Settings->valueFromGroup("ChatWindow", "OnTop", false).toBool()); + } - setWindowIcon(QIcon(IMAGE_WINDOW)); + setWindowIcon(QIcon(IMAGE_WINDOW)); } /** Destructor. */ PopupChatWindow::~PopupChatWindow() { - saveSettings(); + saveSettings(); - if (this == instance) { - instance = NULL; - } + if (this == instance) { + instance = NULL; + } } void PopupChatWindow::saveSettings() { - if (tabbedWindow) { - Settings->saveWidgetInformation(this); + if (tabbedWindow) { + Settings->saveWidgetInformation(this); - Settings->setValueToGroup("ChatWindow", "OnTop", ui.actionSetOnTop->isChecked()); - } else { - if (!peerId.empty()) { - PeerSettings->saveWidgetInformation(peerId, this); - PeerSettings->setPrivateChatOnTop(peerId, ui.actionSetOnTop->isChecked()); - } - } + Settings->setValueToGroup("ChatWindow", "OnTop", ui.actionSetOnTop->isChecked()); + } else { + if (!peerId.empty()) { + PeerSettings->saveWidgetInformation(peerId, this); + PeerSettings->setPrivateChatOnTop(peerId, ui.actionSetOnTop->isChecked()); + } + } } void PopupChatWindow::showEvent(QShowEvent */*event*/) { - if (firstShow) { - firstShow = false; + if (firstShow) { + firstShow = false; - if (tabbedWindow) { - Settings->loadWidgetInformation(this); - } else { - this->move(qrand()%100, qrand()%100); //avoid to stack multiple popup chat windows on the same position - PeerSettings->loadWidgetInformation(peerId, this); - } - } + if (tabbedWindow) { + Settings->loadWidgetInformation(this); + } else { + this->move(qrand()%100, qrand()%100); //avoid to stack multiple popup chat windows on the same position + PeerSettings->loadWidgetInformation(peerId, this); + } + } } -PopupChatDialog *PopupChatWindow::getCurrentDialog() +ChatDialog *PopupChatWindow::getCurrentDialog() { - if (tabbedWindow) { - return dynamic_cast(ui.tabWidget->currentWidget()); - } + if (tabbedWindow) { + return dynamic_cast(ui.tabWidget->currentWidget()); + } - return chatDialog; + return chatDialog; } -void PopupChatWindow::changeEvent(QEvent *event) +void PopupChatWindow::addDialog(ChatDialog *dialog) { - if (event->type() == QEvent::ActivationChange) { - PopupChatDialog *pcd = getCurrentDialog(); - if (pcd) { - pcd->activate(); - } - } + if (tabbedWindow) { + ui.tabWidget->addDialog(dialog); + } else { + ui.horizontalLayout->addWidget(dialog); + dialog->addToParent(this); + ui.horizontalLayout->setContentsMargins(0, 0, 0, 0); + peerId = dialog->getPeerId(); + chatDialog = dialog; + calculateStyle(dialog); + + /* signal toggled is called */ + ui.actionSetOnTop->setChecked(PeerSettings->getPrivateChatOnTop(peerId)); + } + + QObject::connect(dialog, SIGNAL(infoChanged(ChatDialog*)), this, SLOT(tabInfoChanged(ChatDialog*))); + QObject::connect(dialog, SIGNAL(newMessage(ChatDialog*)), this, SLOT(tabNewMessage(ChatDialog*))); + QObject::connect(dialog, SIGNAL(dialogClose(ChatDialog*)), this, SLOT(dialogClose(ChatDialog*))); } -void PopupChatWindow::addDialog(PopupChatDialog *dialog) +void PopupChatWindow::removeDialog(ChatDialog *dialog) { - if (tabbedWindow) { - ui.tabWidget->addDialog(dialog); - } else { - ui.horizontalLayout->addWidget(dialog); - ui.horizontalLayout->setContentsMargins(0, 0, 0, 0); - peerId = dialog->getPeerId(); - chatDialog = dialog; - calculateStyle(dialog); + QObject::disconnect(dialog, SIGNAL(infoChanged(ChatDialog*)), this, SLOT(tabInfoChanged(ChatDialog*))); + QObject::disconnect(dialog, SIGNAL(newMessage(ChatDialog*)), this, SLOT(tabNewMessage(ChatDialog*))); + QObject::disconnect(dialog, SIGNAL(dialogClose(ChatDialog*)), this, SLOT(dialogClose(ChatDialog*))); - /* signal toggled is called */ - ui.actionSetOnTop->setChecked(PeerSettings->getPrivateChatOnTop(peerId)); - } + if (tabbedWindow) { + ui.tabWidget->removeDialog(dialog); - QObject::connect(dialog, SIGNAL(infoChanged(PopupChatDialog*)), this, SLOT(tabInfoChanged(PopupChatDialog*))); - QObject::connect(dialog, SIGNAL(newMessage(PopupChatDialog*)), this, SLOT(tabNewMessage(PopupChatDialog*))); - QObject::connect(dialog, SIGNAL(dialogClose(PopupChatDialog*)), this, SLOT(dialogClose(PopupChatDialog*))); + if (ui.tabWidget->count() == 0) { + deleteLater(); + } + } else { + if (chatDialog == dialog) { + saveSettings(); + dialog->removeFromParent(this); + ui.horizontalLayout->removeWidget(dialog); + chatDialog = NULL; + peerId.erase(); + deleteLater(); + } + } } -void PopupChatWindow::removeDialog(PopupChatDialog *dialog) +void PopupChatWindow::showDialog(ChatDialog *dialog, uint chatflags) { - QObject::disconnect(dialog, SIGNAL(infoChanged(PopupChatDialog*)), this, SLOT(tabInfoChanged(PopupChatDialog*))); - QObject::disconnect(dialog, SIGNAL(newMessage(PopupChatDialog*)), this, SLOT(tabNewMessage(PopupChatDialog*))); - QObject::disconnect(dialog, SIGNAL(dialogClose(PopupChatDialog*)), this, SLOT(dialogClose(PopupChatDialog*))); - - if (tabbedWindow) { - ui.tabWidget->removeDialog(dialog); - - if (ui.tabWidget->count() == 0) { - deleteLater(); - } - } else { - if (chatDialog == dialog) { - saveSettings(); - ui.horizontalLayout->removeWidget(dialog); - chatDialog = NULL; - peerId.erase(); - deleteLater(); - } - } + if (chatflags & RS_CHAT_FOCUS) { + if (tabbedWindow) { + ui.tabWidget->setCurrentWidget(dialog); + } + show(); + activateWindow(); + setWindowState((windowState() & (~Qt::WindowMinimized)) | Qt::WindowActive); + raise(); + dialog->focusDialog(); + } else { + if (isVisible() == false) { + showMinimized(); + } + alertDialog(dialog); + } } -void PopupChatWindow::showDialog(PopupChatDialog *dialog, uint chatflags) +void PopupChatWindow::alertDialog(ChatDialog */*dialog*/) { - if (chatflags & RS_CHAT_FOCUS) { - if (tabbedWindow) { - ui.tabWidget->setCurrentWidget(dialog); - } - show(); - activateWindow(); - setWindowState((windowState() & (~Qt::WindowMinimized)) | Qt::WindowActive); - raise(); - dialog->focusDialog(); - } else { - if (isVisible() == false) { - showMinimized(); - } - alertDialog(dialog); - } + QApplication::alert(this); } -void PopupChatWindow::alertDialog(PopupChatDialog */*dialog*/) +void PopupChatWindow::calculateTitle(ChatDialog *dialog) { - QApplication::alert(this); -} + bool hasNewMessages = false; + ChatDialog *cd; -void PopupChatWindow::calculateTitle(PopupChatDialog *dialog) -{ - bool hasNewMessages = false; - PopupChatDialog *pcd; + /* is typing */ + bool isTyping = false; + if (ui.tabWidget->isVisible()) { + ui.tabWidget->getInfo(isTyping, hasNewMessages, NULL); + } else { + if (dialog) { + isTyping = dialog->isTyping(); + hasNewMessages = dialog->hasNewMessages(); + } + } - /* is typing */ - bool isTyping = false; - if (ui.tabWidget->isVisible()) { - ui.tabWidget->getInfo(isTyping, hasNewMessages, NULL); - } else { - if (dialog) { - isTyping = dialog->isTyping(); - hasNewMessages = dialog->hasNewMessages(); - } - } + if (ui.tabWidget->isVisible()) { + cd = dynamic_cast(ui.tabWidget->currentWidget()); + } else { + cd = dialog; + } - if (ui.tabWidget->isVisible()) { - pcd = dynamic_cast(ui.tabWidget->currentWidget()); - } else { - pcd = dialog; - } + QIcon icon; + if (isTyping) { + icon = QIcon(IMAGE_TYPING); + } else if (hasNewMessages) { + icon = QIcon(IMAGE_CHAT); + } else { + if (cd && cd->hasPeerStatus()) { + icon = QIcon(StatusDefs::imageIM(cd->getPeerStatus())); + } else { + icon = QIcon(IMAGE_WINDOW); + } + } - QIcon icon; - if (isTyping) { - icon = QIcon(IMAGE_TYPING); - } else if (hasNewMessages) { - icon = QIcon(IMAGE_CHAT); - } else { - if (pcd && pcd->hasPeerStatus()) { - icon = QIcon(StatusDefs::imageIM(pcd->getPeerStatus())); - } else { - icon = QIcon(IMAGE_WINDOW); - } - } + setWindowIcon(icon); - setWindowIcon(icon); - - if (pcd) { - setWindowTitle(pcd->getTitle() + " (" + StatusDefs::name(pcd->getPeerStatus()) + ")"); - } else { - setWindowTitle(tr("RetroShare")); - } + if (cd) { + QString title = cd->getTitle(); + if (cd->hasPeerStatus()) { + title += " (" + StatusDefs::name(cd->getPeerStatus()) + ")"; + } + setWindowTitle(title); + } else { + setWindowTitle("RetroShare"); + } } void PopupChatWindow::getAvatar() { - QByteArray ba; - if (misc::getOpenAvatarPicture(this, ba)) { - std::cerr << "Avatar image size = " << ba.size() << std::endl ; + QByteArray ba; + if (misc::getOpenAvatarPicture(this, ba)) { + std::cerr << "Avatar image size = " << ba.size() << std::endl ; - rsMsgs->setOwnAvatarData((unsigned char *)(ba.data()), ba.size()); // last char 0 included. - } + rsMsgs->setOwnAvatarData((unsigned char *)(ba.data()), ba.size()); // last char 0 included. + } } -void PopupChatWindow::dialogClose(PopupChatDialog *dialog) +void PopupChatWindow::dialogClose(ChatDialog *dialog) { - removeDialog(dialog); + removeDialog(dialog); } -void PopupChatWindow::tabChanged(PopupChatDialog *dialog) +void PopupChatWindow::tabChanged(ChatDialog *dialog) { - calculateStyle(dialog); - calculateTitle(dialog); + calculateStyle(dialog); + calculateTitle(dialog); } -void PopupChatWindow::tabInfoChanged(PopupChatDialog *dialog) +void PopupChatWindow::tabInfoChanged(ChatDialog *dialog) { - calculateTitle(dialog); + calculateTitle(dialog); } -void PopupChatWindow::tabNewMessage(PopupChatDialog *dialog) +void PopupChatWindow::tabNewMessage(ChatDialog *dialog) { - alertDialog(dialog); + alertDialog(dialog); } void PopupChatWindow::dockTab() { - if ((Settings->getChatFlags() & RS_CHAT_TABBED_WINDOW) && chatDialog) { - PopupChatWindow *pcw = getWindow(false); - if (pcw) { - PopupChatDialog *pcd = chatDialog; - removeDialog(pcd); - pcw->addDialog(pcd); - pcw->show(); - pcw->calculateTitle(pcd); - } - } + if ((Settings->getChatFlags() & RS_CHAT_TABBED_WINDOW) && chatDialog) { + PopupChatWindow *pcw = getWindow(false); + if (pcw) { + ChatDialog *pcd = chatDialog; + removeDialog(pcd); + pcw->addDialog(pcd); + pcw->show(); + pcw->calculateTitle(pcd); + } + } } void PopupChatWindow::undockTab() { - PopupChatDialog *pcd = dynamic_cast(ui.tabWidget->currentWidget()); + ChatDialog *cd = dynamic_cast(ui.tabWidget->currentWidget()); - if (pcd) { - PopupChatWindow *pcw = getWindow(true); - if (pcw) { - removeDialog(pcd); - pcw->addDialog(pcd); - pcd->show(); - pcw->show(); - pcw->calculateTitle(pcd); - } - } + if (cd) { + PopupChatWindow *pcw = getWindow(true); + if (pcw) { + removeDialog(cd); + pcw->addDialog(cd); + cd->show(); + pcw->show(); + pcw->calculateTitle(cd); + } + } } void PopupChatWindow::setStyle() { - PopupChatDialog *pcd = getCurrentDialog(); + ChatDialog *cd = getCurrentDialog(); - if (pcd && pcd->setStyle()) { - calculateStyle(pcd); - } + if (cd && cd->setStyle()) { + calculateStyle(cd); + } } void PopupChatWindow::setOnTop() { - Qt::WindowFlags flags = windowFlags(); - if (ui.actionSetOnTop->isChecked()) { - flags |= Qt::WindowStaysOnTopHint; - } else { - flags &= ~Qt::WindowStaysOnTopHint; - } - setWindowFlags(flags); + Qt::WindowFlags flags = windowFlags(); + if (ui.actionSetOnTop->isChecked()) { + flags |= Qt::WindowStaysOnTopHint; + } else { + flags &= ~Qt::WindowStaysOnTopHint; + } + setWindowFlags(flags); - /* Show window again */ - show(); + /* Show window again */ + show(); } -void PopupChatWindow::calculateStyle(PopupChatDialog *dialog) +void PopupChatWindow::calculateStyle(ChatDialog *dialog) { - QString toolSheet; - QString statusSheet; - QString widgetSheet; + QString toolSheet; + QString statusSheet; + QString widgetSheet; - if (dialog) { - const RSStyle &style = dialog->getStyle(); + if (dialog) { + const RSStyle *style = dialog->getStyle(); + if (style) { + QString styleSheet = style->getStyleSheet(); - QString styleSheet = style.getStyleSheet(); + if (styleSheet.isEmpty() == false) { + toolSheet = QString("QToolBar{%1}").arg(styleSheet); + statusSheet = QString(".QStatusBar{%1}").arg(styleSheet); + widgetSheet = QString(".QWidget{%1}").arg(styleSheet); + } + } + } - if (styleSheet.isEmpty() == false) { - toolSheet = QString("QToolBar{%1}").arg(styleSheet); - statusSheet = QString(".QStatusBar{%1}").arg(styleSheet); - widgetSheet = QString(".QWidget{%1}").arg(styleSheet); - } - } - - ui.chattoolBar->setStyleSheet(toolSheet); - ui.chatstatusbar->setStyleSheet(statusSheet); - ui.chatcentralwidget->setStyleSheet(widgetSheet); + ui.chattoolBar->setStyleSheet(toolSheet); + ui.chatstatusbar->setStyleSheet(statusSheet); + ui.chatcentralwidget->setStyleSheet(widgetSheet); } diff --git a/retroshare-gui/src/gui/chat/PopupChatWindow.h b/retroshare-gui/src/gui/chat/PopupChatWindow.h index 4846b7525..5c50784dd 100644 --- a/retroshare-gui/src/gui/chat/PopupChatWindow.h +++ b/retroshare-gui/src/gui/chat/PopupChatWindow.h @@ -26,55 +26,54 @@ #include #include "ui_PopupChatWindow.h" -class PopupChatDialog; +class ChatDialog; class PopupChatWindow : public QMainWindow { - Q_OBJECT + Q_OBJECT public: - static PopupChatWindow *getWindow(bool needSingleWindow); - static void cleanup(); + static PopupChatWindow *getWindow(bool needSingleWindow); + static void cleanup(); public: - void addDialog(PopupChatDialog *dialog); - void removeDialog(PopupChatDialog *dialog); - void showDialog(PopupChatDialog *dialog, uint chatflags); - void alertDialog(PopupChatDialog *dialog); - void calculateTitle(PopupChatDialog *dialog); + void addDialog(ChatDialog *dialog); + void removeDialog(ChatDialog *dialog); + void showDialog(ChatDialog *dialog, uint chatflags); + void alertDialog(ChatDialog *dialog); + void calculateTitle(ChatDialog *dialog); protected: - /** Default constructor */ - PopupChatWindow(bool tabbed, QWidget *parent = 0, Qt::WFlags flags = 0); - /** Default destructor */ - ~PopupChatWindow(); + /** Default constructor */ + PopupChatWindow(bool tabbed, QWidget *parent = 0, Qt::WFlags flags = 0); + /** Default destructor */ + ~PopupChatWindow(); - virtual void showEvent(QShowEvent *event); - virtual void changeEvent(QEvent *event); + virtual void showEvent(QShowEvent *event); private slots: - void getAvatar(); - void tabChanged(PopupChatDialog *dialog); - void tabInfoChanged(PopupChatDialog *dialog); - void tabNewMessage(PopupChatDialog *dialog); - void dialogClose(PopupChatDialog *dialog); - void dockTab(); - void undockTab(); - void setStyle(); - void setOnTop(); + void getAvatar(); + void tabChanged(ChatDialog *dialog); + void tabInfoChanged(ChatDialog *dialog); + void tabNewMessage(ChatDialog *dialog); + void dialogClose(ChatDialog *dialog); + void dockTab(); + void undockTab(); + void setStyle(); + void setOnTop(); private: - bool tabbedWindow; - bool firstShow; - std::string peerId; - PopupChatDialog *chatDialog; + bool tabbedWindow; + bool firstShow; + std::string peerId; + ChatDialog *chatDialog; - PopupChatDialog *getCurrentDialog(); - void saveSettings(); - void calculateStyle(PopupChatDialog *dialog); + ChatDialog *getCurrentDialog(); + void saveSettings(); + void calculateStyle(ChatDialog *dialog); - /** Qt Designer generated object */ - Ui::PopupChatWindow ui; + /** Qt Designer generated object */ + Ui::PopupChatWindow ui; }; #endif diff --git a/retroshare-gui/src/gui/common/FriendList.cpp b/retroshare-gui/src/gui/common/FriendList.cpp index 028e24108..308f172f3 100644 --- a/retroshare-gui/src/gui/common/FriendList.cpp +++ b/retroshare-gui/src/gui/common/FriendList.cpp @@ -25,12 +25,13 @@ #include #include #include +#include #include "retroshare/rspeers.h" #include "retroshare/rsstatus.h" #include "GroupDefs.h" -#include "gui/chat/PopupChatDialog.h" +#include "gui/chat/ChatDialog.h" #include "gui/chat/CreateLobbyDialog.h" #include "gui/common/AvatarDefs.h" #include "gui/connect/ConfCertDialog.h" @@ -1209,7 +1210,7 @@ void FriendList::chatfriend(QTreeWidgetItem *pPeer) } std::string id = getRsId(pPeer); - PopupChatDialog::chatFriend(id); + ChatDialog::chatFriend(id); } void FriendList::addFriend() @@ -1416,7 +1417,7 @@ void FriendList::showLobby() std::string vpeer_id ; if(rsMsgs->getVirtualPeerId( ChatLobbyId(QString::fromStdString(lobby_id).toULongLong() ),vpeer_id)) - PopupChatDialog::chatFriend(vpeer_id) ; + ChatDialog::chatFriend(vpeer_id) ; } void FriendList::unsubscribeToLobby() { @@ -1433,7 +1434,7 @@ void FriendList::unsubscribeToLobby() // we should also close existing windows. - PopupChatDialog::closeChat(vpeer_id) ; + ChatDialog::closeChat(vpeer_id) ; } @@ -1462,7 +1463,7 @@ void FriendList::inviteToLobby() std::string vpeer_id ; if(rsMsgs->getVirtualPeerId( ChatLobbyId(QString::fromStdString(lobby_id).toULongLong() ),vpeer_id) ) - PopupChatDialog::chatFriend(vpeer_id) ; + ChatDialog::chatFriend(vpeer_id) ; } void FriendList::createchatlobby() diff --git a/retroshare-gui/src/gui/common/HashBox.cpp b/retroshare-gui/src/gui/common/HashBox.cpp index db1c2b334..38dea4bd6 100644 --- a/retroshare-gui/src/gui/common/HashBox.cpp +++ b/retroshare-gui/src/gui/common/HashBox.cpp @@ -153,7 +153,7 @@ bool HashBox::eventFilter(QObject* object, QEvent* event) void HashBox::addAttachments(const QStringList& files, HashedFile::Flags flag) { /* add a AttachFileItem to the attachment section */ - std::cerr << "PopupChatDialog::addExtraFile() hashing file." << std::endl; + std::cerr << "HashBox::addExtraFile() hashing file." << std::endl; if (files.isEmpty()) { return; diff --git a/retroshare-gui/src/gui/settings/RsharePeerSettings.cpp b/retroshare-gui/src/gui/settings/RsharePeerSettings.cpp index 95ed45666..9f16249d1 100644 --- a/retroshare-gui/src/gui/settings/RsharePeerSettings.cpp +++ b/retroshare-gui/src/gui/settings/RsharePeerSettings.cpp @@ -29,6 +29,7 @@ #include #include +#include #include "RsharePeerSettings.h" #include "gui/style/RSStyle.h" @@ -36,7 +37,7 @@ /** The file in which all settings of he peers will read and written. */ #define SETTINGS_FILE (QString::fromUtf8(RsInit::RsProfileConfigDirectory().c_str()) + "/RSPeers.conf") -/* clean dead gpg id's after these days */ +/* clean dead id's after these days */ #define DAYS_TO_CLEAN 7 /* Group for general data */ @@ -56,10 +57,10 @@ RsharePeerSettings *PeerSettings = NULL; RsharePeerSettings::RsharePeerSettings() : QSettings(SETTINGS_FILE, QSettings::IniFormat) { - cleanDeadGpgIds(); + cleanDeadIds(); } -void RsharePeerSettings::cleanDeadGpgIds() +void RsharePeerSettings::cleanDeadIds() { beginGroup(GROUP_GENERAL); QDateTime lastClean = value("lastClean").toDateTime(); @@ -75,6 +76,10 @@ void RsharePeerSettings::cleanDeadGpgIds() continue; } + ChatLobbyId lid; + if (rsMsgs->isLobbyId((*group).toStdString(), lid)) { + continue; + } if (rsPeers->isGPGAccepted((*group).toStdString()) == false) { remove(*group); } @@ -86,22 +91,27 @@ void RsharePeerSettings::cleanDeadGpgIds() } } -bool RsharePeerSettings::getGpgIdOfSslId(const std::string &sslId, std::string &gpgId) - +bool RsharePeerSettings::getSettingsIdOfPeerId(const std::string &peerId, std::string &settingsId) { - std::map::iterator it = m_SslToGpg.find(sslId); + ChatLobbyId lid; + if (rsMsgs->isLobbyId(peerId, lid)) { + settingsId = peerId; + return true; + } + + std::map::iterator it = m_SslToGpg.find(peerId); if (it != m_SslToGpg.end()) { - gpgId = it->second; + settingsId = it->second; return true; } RsPeerDetails details; - if (rsPeers->getPeerDetails(sslId, details) == false) { + if (rsPeers->getPeerDetails(peerId, details) == false) { return false; } - gpgId = details.gpg_id; - m_SslToGpg[sslId] = gpgId; + settingsId = details.gpg_id; + m_SslToGpg[peerId] = settingsId; return true; } @@ -111,13 +121,13 @@ QVariant RsharePeerSettings::get(const std::string &peerId, const QString &key, { QVariant result; - std::string gpgId; - if (getGpgIdOfSslId(peerId, gpgId) == false) { - /* gpg id not found */ + std::string settingsId; + if (getSettingsIdOfPeerId(peerId, settingsId) == false) { + /* settings id not found */ return result; } - beginGroup(QString::fromStdString(gpgId)); + beginGroup(QString::fromStdString(settingsId)); result = value(key, defaultValue); endGroup(); @@ -127,13 +137,13 @@ QVariant RsharePeerSettings::get(const std::string &peerId, const QString &key, /* set value of peer */ void RsharePeerSettings::set(const std::string &peerId, const QString &key, const QVariant &value) { - std::string gpgId; - if (getGpgIdOfSslId(peerId, gpgId) == false) { - /* gpg id not found */ + std::string settingsId; + if (getSettingsIdOfPeerId(peerId, settingsId) == false) { + /* settings id not found */ return; } - beginGroup(QString::fromStdString(gpgId)); + beginGroup(QString::fromStdString(settingsId)); setValue(key, value); endGroup(); } @@ -170,13 +180,13 @@ void RsharePeerSettings::setPrivateChatOnTop(const std::string &peerId, bool val void RsharePeerSettings::saveWidgetInformation(const std::string &peerId, QWidget *widget) { - std::string gpgId; - if (getGpgIdOfSslId(peerId, gpgId) == false) { - /* gpg id not found */ + std::string settingsId; + if (getSettingsIdOfPeerId(peerId, settingsId) == false) { + /* settings id not found */ return; } - beginGroup(QString::fromStdString(gpgId)); + beginGroup(QString::fromStdString(settingsId)); beginGroup("widgetInformation"); beginGroup(widget->objectName()); @@ -190,13 +200,13 @@ void RsharePeerSettings::saveWidgetInformation(const std::string &peerId, QWidge void RsharePeerSettings::loadWidgetInformation(const std::string &peerId, QWidget *widget) { - std::string gpgId; - if (getGpgIdOfSslId(peerId, gpgId) == false) { - /* gpg id not found */ + std::string settingsId; + if (getSettingsIdOfPeerId(peerId, settingsId) == false) { + /* settings id not found */ return; } - beginGroup(QString::fromStdString(gpgId)); + beginGroup(QString::fromStdString(settingsId)); beginGroup("widgetInformation"); beginGroup(widget->objectName()); @@ -218,15 +228,25 @@ void RsharePeerSettings::setShowAvatarFrame(const std::string &peerId, bool valu return set(peerId, "ShowAvatarFrame", value); } +bool RsharePeerSettings::getShowParticipantsFrame(const std::string &peerId) +{ + return get(peerId, "ShowParticipantsFrame", true).toBool(); +} + +void RsharePeerSettings::setShowParticipantsFrame(const std::string &peerId, bool value) +{ + return set(peerId, "ShowParticipantsFrame", value); +} + void RsharePeerSettings::getStyle(const std::string &peerId, const QString &name, RSStyle &style) { - std::string gpgId; - if (getGpgIdOfSslId(peerId, gpgId) == false) { - /* gpg id not found */ + std::string settingsId; + if (getSettingsIdOfPeerId(peerId, settingsId) == false) { + /* settings id not found */ return; } - beginGroup(QString::fromStdString(gpgId)); + beginGroup(QString::fromStdString(settingsId)); beginGroup("style"); beginGroup(name); @@ -239,13 +259,13 @@ void RsharePeerSettings::getStyle(const std::string &peerId, const QString &name void RsharePeerSettings::setStyle(const std::string &peerId, const QString &name, RSStyle &style) { - std::string gpgId; - if (getGpgIdOfSslId(peerId, gpgId) == false) { - /* gpg id not found */ + std::string settingsId; + if (getSettingsIdOfPeerId(peerId, settingsId) == false) { + /* settings id not found */ return; } - beginGroup(QString::fromStdString(gpgId)); + beginGroup(QString::fromStdString(settingsId)); beginGroup("style"); beginGroup(name); diff --git a/retroshare-gui/src/gui/settings/RsharePeerSettings.h b/retroshare-gui/src/gui/settings/RsharePeerSettings.h index 74ff3c28c..ab411d562 100644 --- a/retroshare-gui/src/gui/settings/RsharePeerSettings.h +++ b/retroshare-gui/src/gui/settings/RsharePeerSettings.h @@ -48,6 +48,9 @@ public: bool getShowAvatarFrame(const std::string &peerId); void setShowAvatarFrame(const std::string &peerId, bool value); + bool getShowParticipantsFrame(const std::string &peerId); + void setShowParticipantsFrame(const std::string &peerId, bool value); + void getStyle(const std::string &peerId, const QString &name, RSStyle &style); void setStyle(const std::string &peerId, const QString &name, RSStyle &style); @@ -55,8 +58,8 @@ protected: /** Default constructor. */ RsharePeerSettings(); - bool getGpgIdOfSslId(const std::string &sslId, std::string &gpgId); - void cleanDeadGpgIds(); + bool getSettingsIdOfPeerId(const std::string &peerId, std::string &settingsId); + void cleanDeadIds(); /* get value of peer */ QVariant get(const std::string &peerId, const QString &key, const QVariant &defaultValue = QVariant()); diff --git a/retroshare-gui/src/gui/toaster/OnlineToaster.cpp b/retroshare-gui/src/gui/toaster/OnlineToaster.cpp index 75a45838c..c97cf4755 100644 --- a/retroshare-gui/src/gui/toaster/OnlineToaster.cpp +++ b/retroshare-gui/src/gui/toaster/OnlineToaster.cpp @@ -21,7 +21,7 @@ #include "OnlineToaster.h" #include "gui/settings/rsharesettings.h" -#include "gui/chat/PopupChatDialog.h" +#include "gui/chat/ChatDialog.h" #include "util/WidgetBackgroundImage.h" #include "gui/common/AvatarDefs.h" @@ -50,7 +50,7 @@ OnlineToaster::OnlineToaster(const std::string &peerId, const QString &name) : Q void OnlineToaster::chatButtonSlot() { - PopupChatDialog::chatFriend(peerId); + ChatDialog::chatFriend(peerId); hide(); } diff --git a/retroshare-gui/src/lang/retroshare_de.qm b/retroshare-gui/src/lang/retroshare_de.qm index 75d554c8c2b5c63a6e94c92372e86214e9bb5e0b..b132617b09ebbd26fd7deeb79cbf2b3b5ac413e6 100644 GIT binary patch delta 22131 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 T@ZvulkIMW(*_!!-7;XQ5;)90E delta 18055 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 diff --git a/retroshare-gui/src/lang/retroshare_de.ts b/retroshare-gui/src/lang/retroshare_de.ts index 5508d8078..22d2c0c46 100644 --- a/retroshare-gui/src/lang/retroshare_de.ts +++ b/retroshare-gui/src/lang/retroshare_de.ts @@ -968,17 +968,15 @@ p, li { white-space: pre-wrap; } Anzeige - Set all to read - Alle als gelesen markieren + Alle als gelesen markieren - Enable Auto-download - Aktiviere Auto-Download + Aktiviere Auto-Download - + Create Channel Kanal erstellen @@ -998,7 +996,13 @@ p, li { white-space: pre-wrap; } Abonnieren - + + + Set all as read + Alle als gelesen markieren + + + Unsubcribe To Channel Kanal abbestellen @@ -1023,8 +1027,8 @@ p, li { white-space: pre-wrap; } Andere Kanäle - - + + Post to Channel Kanalbeitrag erstellen @@ -1059,26 +1063,142 @@ p, li { white-space: pre-wrap; } Kopiere RetroShare Link - + No Channel Selected Keinen Kanal gewählt - + Disable Auto-Download Deaktiviere Auto-Download - + + + Enable Auto-Download Aktiviere Auto-Download - + Edit Channel Details Kanal-Details bearbeiten + + ChatDialog + + + Friend not Online + Freund ist nicht online + + + + Your Friend is offline +Do you want to send them a Message instead + Dein Freund ist Offline. Möchtest du ihm stattdessen eine Nachricht senden + + + + ChatLobbyDialog + + + + Lobby management + Lobby Verwaltung + + + + %1 has left the lobby. + %1 hat die Lobby verlassen. + + + + %1 joined the lobby. + %1 hat die Lobby betreten. + + + + Do you want to unsubscribe to this chat lobby? + Möchtest du diese Lobby abbestellen? + + + + Unsubscribe to lobby + Lobby abbestellen + + + + Hide Participants + Telnehmer ausblenden + + + + Show Participants + Teilnehmer zeigen + + + + ChatLobbyWidget + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Chat lobbies</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Arial'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Chat Lobbies</span></p></body></html> + + + + Create new chat lobby + Neue Chat Lobby erstellen + + + + Name + Name + + + + Count + Anzahl + + + + Private Lobbies + Private Lobbies + + + + Public Lobbies + Öffentliche Lobbies + + + + Create chat lobby + Erstelle Chat Lobby + + + + Unsubscribe + Abbestellen + + + + Subscribe + Abonnieren + + + + Invitation to chat lobby + Einladung zur Chat Lobby + + ChatMsgItem @@ -1131,12 +1251,17 @@ p, li { white-space: pre-wrap; } Chat Einstellungen - + Enable Emoticons Privat Chat Emoticons für privaten Chat - + + Default nickname for chat lobbies: + Default-Spitzname für Chat Lobbies: + + + Chat Font Chat Schriftart @@ -1151,7 +1276,7 @@ p, li { white-space: pre-wrap; } Chat Schriftart: - + Enable Emoticons Group Chat Emoticons für Gruppenchat @@ -1160,7 +1285,7 @@ p, li { white-space: pre-wrap; } Chat History - + Load number of messages (0 = off) Lade Anzahl von Nachrichten (0 = aus) @@ -1192,7 +1317,7 @@ p, li { white-space: pre-wrap; } Privater Chat - + General Allgemein @@ -1201,7 +1326,7 @@ p, li { white-space: pre-wrap; } Chat Verlauf für Gruppenchat - + Send message with Ctrl+Return Sende Nachricht mit Strg+Enter @@ -1210,7 +1335,7 @@ p, li { white-space: pre-wrap; } Chat Verlauf für privaten Chat - + Enable Aktiviert @@ -1248,7 +1373,7 @@ p, li { white-space: pre-wrap; } Verlauf - + Incoming message in history Eingehehende Nachricht aus dem Verlauf @@ -1291,6 +1416,162 @@ p, li { white-space: pre-wrap; } Standard Stil für den Verlauf + + ChatWidget + + Form + Formular + + + + Close + Schliessen + + + + Attach a Picture + Bild anhängen + + + + Add a File for your Friend + Füge eine Datei für deinen Freund hinzu + + + + Send + Senden + + + + + Bold + Fett + + + + + Underline + Unterstrichen + + + + + Italic + Kursiv + + + + Font + Schriftart + + + + Text Color + Textfarbe + + + + Strike + Durchgestrichen + + + + Clear Chat History + Nachrichtenverlauf leeren + + + + Disable Emoticons + Deaktiviere Emoticons + + + + + Save Chat History + Nachrichtenverlauf speichern + + + + Browse Message History + Nachrichtenverlauf anzeigen + + + + Browse History + Nachrichtenverlauf + + + + Delete Chat History + Nachrichtenverlauf löschen + + + + Deletes all stored and displayed chat history + Löscht den gespeicherten und angezeigten Chat Verlauf + + + + Paste RetroShare Link + RetroShare Link einfügen + + + + is typing... + tippt... + + + + Do you really want to physically delete the history? + Möchtest du wirklich den Nachrichtenverlauf physisch löschen? + + + + Add Extra File + + + + + Load Picture File + Lade Bilddatei + + + + Save as... + Speichern unter... + + + + Text File (*.txt );;All Files (*) + Text Datei (*.txt );;Alle Dateien (*) + + + + apears to be Offline. + ist Offline. + + + + Messages you send will be delivered after Friend is again Online + Nachrichten, die Du versendest gehen bei diesem Freund erst wieder ein wenn er Online ist + + + + is Idle and may not reply + antwortet möglicherweise nicht, da der Status auf "Untätig" gesetzt wurde + + + + is Away and may not reply + antwortet möglicherweise nicht, da der Status auf "Abwesend" gesetzt wurde + + + + is Busy and may not reply + antwortet möglicherweise nicht, da der Status auf "Beschäftigt" gesetzt wurde + + ConclusionPage @@ -2563,6 +2844,121 @@ p, li { white-space: pre-wrap; } <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; font-style:normal;"><p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:400; color:#ffffff;">Gruppe ändern</span></p></body></html> + + CreateLobbyDialog + + + Create Chat Lobby + Erstelle Chat Lobby + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; color:#ffffff;">Create Chat Lobby</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:18pt; font-weight:600; color:#ffffff;">Neue Chat Lobby</span></p></body></html> + + + + Lobby name: + Lobby Name: + + + + Your nick name: + Dein Spitzname: + + + + Security policy: + Sicherheitsrichtlinie: + + + + Public (Visible by friends) + Öffentlich (für Freunde sichtbar) + + + + Private (Works on invitation only) + Privat (nur private Einladung) + + + + Select the Friends with which you want to group chat. + Wähle die Freunde mit denen du chatten möchtest. + + + Check peers you would like to chat with + Wähle die Nachbarn, mit denen du chatten möchtest + + + check peers you would like to share private publish key with + Wähle die Nachbarn, an die du den privaten Schlüssel verteilen möchtest + + + + Invited friends + Freunde einladen + + + + Contacts: + Kontakte: + + + + Create + Erstellen + + + + Cancel + Abbrechen + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">A chat lobby is a decentralized and anonymous chat group. All participants receive all messages. Once the lobby is created you can invite other friends from the Friends tab.</span></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:12pt;">Eine Chat Lobby ist ein dezentralisierter und anonymer Chat. Alle Teilnehmer erhalten alle Nachrichten. Wenn du eine Lobby erstellst, kannst du andere Freunde in der Freundesliste einladen.</span></p></body></html> + + + + Put a sensible lobby name here + Gib einen Lobbynamen ein + + + + Your nickname for this lobby (Change default name in options->chat) + Dein Spitzname für diese Lobby (Ändere den Defaultnamen in den Optionen->Chat) + + + + Please select at least one friend + Bitte wähle mindestens einen Freund + + + RetroShare + RetroShare + + + Please select at least one peer + Bitte wähle mindestens einen Nachbarn + + CryptoPage @@ -4300,7 +4696,7 @@ p, li { white-space: pre-wrap; } Zeige Gruppen - + Group Gruppe @@ -4335,12 +4731,42 @@ p, li { white-space: pre-wrap; } Gruppe entfernen - + + Create chat lobby + Erstelle Chat Lobby + + + Chat Chat + Chat lobbies + Chat Lobbies + + + + create new + Erstellen + + + + Invite this friend + Lade diesen Freund ein + + + + Show + Zeigen + + + + Unsubscribe + Abbestellen + + + Message Friend Freund anschreiben @@ -4427,7 +4853,17 @@ p, li { white-space: pre-wrap; } Möchtest du diesen Freund entfernen? - + + Unsubscribe to lobby + Lobby abbestellen + + + + You are about to unsubscribe a chat lobby<br>You can only re-enter if your friends invite you again. + Du bestellst die Lobby ab.<br>Du kannst nur wieder teilnehmen, wenn deine Freunde dich wieder einladen. + + + Sort by Sortiere nach @@ -4597,6 +5033,12 @@ p, li { white-space: pre-wrap; } Save Chat History Nachrichtenverlauf speichern + + + + Create new Chat lobby + Neue Chat Lobby erstellen + Hide Offline Friends Verstecke offline Freunde @@ -4618,7 +5060,7 @@ p, li { white-space: pre-wrap; } Status ausblenden - + Add a new Group Neue Gruppe hinzufügen @@ -4646,7 +5088,12 @@ p, li { white-space: pre-wrap; } Löscht den gespeicherten und angezeigten Chat Verlauf - + + Chat lobbies + Chat Lobbies + + + Profile Profil @@ -4661,7 +5108,7 @@ p, li { white-space: pre-wrap; } Willkommen bei RetroShare's Gruppenchat. - + me ich @@ -4780,7 +5227,7 @@ p, li { white-space: pre-wrap; } tippt... - + New group chat Neuer Gruppenchat @@ -8464,7 +8911,7 @@ p, li { white-space: pre-wrap; } Bitte geben Sie das Passwort ein um folgenden GPG Schlüssel freizuschalten: - + Examining shared files... Prüfe freigegebene Dateien... @@ -8919,22 +9366,31 @@ p, li { white-space: pre-wrap; } Formular - + Status: Status: - + File hash: Datei Prüfsumme: - + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><a href="more"><span style=" text-decoration: underline; color:#0000ff;">more...</span></a></p></body></html> + + + + File name: Dateiname: - + Launch configuration panel, if provided by the plugin Starte Einstellungen, wenn vom Plugin unterstützt @@ -8944,7 +9400,7 @@ p, li { white-space: pre-wrap; } Einstellung - + Add the plugin into the white list of accepted plugins. This will be effective after you restart RetroShare, since plugins need to be loaded at startup. Fügt das Plugin als vertrauenswürdig hinzu. Das wirkt sich nach dem Neustart von RetroShare aus, da die Plugins beim Start geladen werden. @@ -8980,7 +9436,7 @@ p, li { white-space: pre-wrap; } Geladene Plugins - + Authorize all plugins Erlaube alle Plugins @@ -9041,111 +9497,91 @@ p, li { white-space: pre-wrap; } PopupChatDialog - + Hide Avatar Avatar verstecken - + Show Avatar Avatar zeigen - Do you really want to physically delete the history? - Möchtest du wirklich den Nachrichtenverlauf physisch löschen? + Möchtest du wirklich den Nachrichtenverlauf physisch löschen? - Load Picture File - Lade Bilddatei + Lade Bilddatei File not found or file name not accepted. Datei nicht gefunden oder Dateiname nicht akzeptiert. - Messages you send will be delivered after Friend is again Online - Nachrichten, die Du versendest gehen bei diesem Freund erst wieder ein wenn er Online ist + Nachrichten, die Du versendest gehen bei diesem Freund erst wieder ein wenn er Online ist - - Bold - Fett + Fett - - Underline - Unterstrichen + Unterstrichen - - Italic - Kursiv + Kursiv - Text Color - Textfarbe + Textfarbe - + Clear offline messages Entferne offline Nachrichten - Browse Message History - Nachrichtenverlauf anzeigen + Nachrichtenverlauf anzeigen - Browse History - Nachrichtenverlauf + Nachrichtenverlauf - Clear Chat History - Nachrichtenverlauf leeren + Nachrichtenverlauf leeren - Font - Schriftart + Schriftart - Delete Chat History - Nachrichtenverlauf löschen + Nachrichtenverlauf löschen - Deletes all stored and displayed chat history - Löscht den gespeicherten und angezeigten Chat Verlauf + Löscht den gespeicherten und angezeigten Chat Verlauf - Send - Senden + Senden - Disable Emoticons - Deaktiviere Emoticons + Deaktiviere Emoticons - Strike - Durchgestrichen + Durchgestrichen - Add Extra File - Zusätzlich eine Datei hinzufügen + Zusätzlich eine Datei hinzufügen Drop file error. @@ -9156,76 +9592,61 @@ p, li { white-space: pre-wrap; } Ordner können nicht für Drag'n'Drop genutzt werden. Nur Dateien werden akzeptiert. - Add a File for your Friend - Füge eine Datei für deinen Freund hinzu + Füge eine Datei für deinen Freund hinzu - - Save Chat History - Nachrichtenverlauf speichern + Nachrichtenverlauf speichern - Save as... - Speichern unter... + Speichern unter... - Text File (*.txt );;All Files (*) - Text Datei (*.txt );;Alle Dateien (*) + Text Datei (*.txt );;Alle Dateien (*) - Your Friend is offline Do you want to send them a Message instead - Dein Freund ist Offline. Möchtest du ihm stattdessen eine Nachricht senden + Dein Freund ist Offline. Möchtest du ihm stattdessen eine Nachricht senden - Attach a Picture - Bild anhängen + Bild anhängen - is Idle and may not reply - antwortet möglicherweise nicht, da der Status auf "Untätig" gesetzt wurde + antwortet möglicherweise nicht, da der Status auf "Untätig" gesetzt wurde - is Away and may not reply - antwortet möglicherweise nicht, da der Status auf "Abwesend" gesetzt wurde + antwortet möglicherweise nicht, da der Status auf "Abwesend" gesetzt wurde - is Busy and may not reply - antwortet möglicherweise nicht, da der Status auf "Beschäftigt" gesetzt wurde + antwortet möglicherweise nicht, da der Status auf "Beschäftigt" gesetzt wurde - apears to be Offline. - ist Offline. + ist Offline. - Paste RetroShare Link - RetroShare Link einfügen + RetroShare Link einfügen - is typing... - tippt... + tippt... - Close - Schliessen + Schliessen - Friend not Online - Freund ist nicht online + Freund ist nicht online @@ -9265,9 +9686,8 @@ Do you want to send them a Message instead Immer im Vordergrund - RetroShare - RetroShare + RetroShare @@ -9711,18 +10131,18 @@ p, li { white-space: pre-wrap; } QObject - + RetroShare RetroShare - + Inititialize failed. Wrong or missing installation of gpg. Initialisierung fehlgeschlagen. GPG fehlt oder es ist eine falsche Version installiert. - + An unexpected error occured. Please report 'RsInit::InitRetroShare unexpected return code %1'. Ein unerwarteter Fehler ist aufgetreten. Bitte melde 'RsInit::InitRetroShare unexpected return code %1'. @@ -10410,7 +10830,7 @@ p, li { white-space: pre-wrap; } RSettingsWin - + General Allgemein @@ -10429,6 +10849,11 @@ p, li { white-space: pre-wrap; } Transfer Übertragung + + + Relay + + Notify @@ -10498,6 +10923,93 @@ p, li { white-space: pre-wrap; } <strong>Hoch:</strong> + + RelayPage + + + Enable Relay Connections + + + + + Use Relay Servers + + + + + Relay options + + + + + Number + + + + + Bandwidth per link + + + + + Total Bandwidth + + + + + Friends + Freunde + + + + + + x + + + + + + + kB/s + + + + + Friends of Friends + + + + + General + Allgemein + + + + Total: + Gesamt: + + + + Relay Server Setup + + + + + Add Server + + + + + Server Dht Key + + + + + Remove Server + + + RetroshareDirModel @@ -10760,22 +11272,22 @@ p, li { white-space: pre-wrap; } - + Copy RetroShare Link Kopiere RetroShare Link - + Send RetroShare Link Sende RetroShare Link - + Search again Erneut suchen - + Remove Entfernen @@ -10785,7 +11297,7 @@ p, li { white-space: pre-wrap; } Alle entfernen - + Folder Ordner @@ -10846,7 +11358,7 @@ p, li { white-space: pre-wrap; } Such ID - + Download Notice Download @@ -11297,6 +11809,11 @@ Es hilft auch, wenn Sie sich hinter einer Firewall/VPN befinden. Transfer Übertragung + + + Relays + + Plugins @@ -11328,7 +11845,7 @@ Es hilft auch, wenn Sie sich hinter einer Firewall/VPN befinden. OK - + General Allgemein @@ -11338,7 +11855,7 @@ Es hilft auch, wenn Sie sich hinter einer Firewall/VPN befinden. Server - + Directories Ordner @@ -12768,13 +13285,28 @@ p, li { white-space: pre-wrap; } Maximum simultaneous downloads: + + + Slots reserved for non-cache transfers: + + Default chunk strategy: Standard Block Strategie: - + + You can use this to force RetroShare to download your files rather +than cache files for as many slots as requested. Setting that number +to be equal to the queue size above will always prioritize your files +over cache. + +It is however recommended to leave at least a few slots for cache files. + + + + Streaming Streaming @@ -12797,12 +13329,12 @@ p, li { white-space: pre-wrap; } - + Safety disk space limit : Sicherheitsgrenze Festplattenspeicher: - + MB diff --git a/retroshare-gui/src/main.cpp b/retroshare-gui/src/main.cpp index 397419923..7665ce414 100644 --- a/retroshare-gui/src/main.cpp +++ b/retroshare-gui/src/main.cpp @@ -31,7 +31,7 @@ #include "gui/MessagesDialog.h" #include "gui/SharedFilesDialog.h" #include "gui/NetworkDialog.h" -#include "gui/chat/PopupChatDialog.h" +#include "gui/chat/ChatDialog.h" #include "gui/QuickStartWizard.h" #endif // MINIMAL_RSGUI #include "gui/MessengerWindow.h" @@ -318,7 +318,7 @@ int main(int argc, char *argv[]) } /* cleanup */ - PopupChatDialog::cleanupChat(); + ChatDialog::cleanupChat(); #endif // MINIMAL_RSGUI rsicontrol->rsGlobalShutDown();