RetroShare/retroshare-gui/src/gui/chat/ChatLobbyUserNotify.cpp

328 lines
10 KiB
C++
Raw Normal View History

/****************************************************************
* RetroShare is distributed under the following license:
*
* Copyright (C) 2014 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 <QTime>
#include <QMenu>
#include "ChatLobbyUserNotify.h"
#include "gui/notifyqt.h"
#include "gui/MainWindow.h"
#include "gui/ChatLobbyWidget.h"
#include "gui/settings/rsharesettings.h"
#include "util/DateTime.h"
#include <retroshare/rsidentity.h>
ChatLobbyUserNotify::ChatLobbyUserNotify(QObject *parent) :
UserNotify(parent)
{
_name = tr("Chat Lobbies");
_group = "ChatLobby";
_bCheckForNickName = Settings->valueFromGroup(_group, "CheckForNickName", true).toBool();
_bCountUnRead = Settings->valueFromGroup(_group, "CountUnRead", true).toBool();
_bCountSpecificText = Settings->valueFromGroup(_group, "CountSpecificText").toBool();
_textToNotify = Settings->valueFromGroup(_group, "TextToNotify").toStringList();
}
bool ChatLobbyUserNotify::hasSetting(QString *name, QString *group)
{
if (name) *name = _name;
if (group) *group = _group;
return true;
}
void ChatLobbyUserNotify::setCheckForNickName(bool value)
{
if (_bCheckForNickName != value) {
_bCheckForNickName = value;
Settings->setValueToGroup(_group, "CheckForNickName", value);
}
}
void ChatLobbyUserNotify::setCountUnRead(bool value)
{
if (_bCountUnRead != value) {
_bCountUnRead = value;
Settings->setValueToGroup(_group, "CountUnRead", value);
}
}
void ChatLobbyUserNotify::setCountSpecificText(bool value)
{
if (_bCountSpecificText != value) {
_bCountSpecificText = value;
Settings->setValueToGroup(_group, "CountSpecificText", value);
}
}
void ChatLobbyUserNotify::setTextToNotify(QStringList value)
{
if (_textToNotify != value) {
_textToNotify = value;
Settings->setValueToGroup(_group, "TextToNotify", value);
}
}
void ChatLobbyUserNotify::setTextToNotify(QString value)
{
while(value.contains("\n\n")) value.replace("\n\n","\n");
QStringList list = value.split("\n");
setTextToNotify(list);
}
QIcon ChatLobbyUserNotify::getIcon()
{
return QIcon(":/images/chat_32.png");
}
QIcon ChatLobbyUserNotify::getMainIcon(bool hasNew)
{
return hasNew ? QIcon(":/images/chat_red24.png") : QIcon(":/images/chat_32.png");
}
unsigned int ChatLobbyUserNotify::getNewCount()
{
int iNum=0;
for (lobby_map::iterator itCL=_listMsg.begin(); itCL!=_listMsg.end(); ++itCL) {
iNum+=itCL->second.size();
if (itCL->second.size()==0) _listMsg.erase(itCL);
}
return iNum;
}
QString ChatLobbyUserNotify::getTrayMessage(bool plural)
{
return plural ? tr("You have %1 new messages") : tr("You have %1 new message");
}
QString ChatLobbyUserNotify::getNotifyMessage(bool plural)
{
return plural ? tr("%1 new messages") : tr("%1 new message");
}
void ChatLobbyUserNotify::iconClicked()
{
/// Tray icon Menu ///
QMenu* trayMenu = new QMenu(MainWindow::getInstance());
std::list<ChatLobbyId> lobbies;
rsMsgs->getChatLobbyList(lobbies);
bool doUpdate=false;
for (lobby_map::iterator itCL=_listMsg.begin(); itCL!=_listMsg.end();++itCL) {
/// Create a menu per lobby ///
bool bFound=false;
QString strLobbyName=tr("Unknown Lobby");
QIcon icoLobby=QIcon();
std::list<ChatLobbyId>::const_iterator lobbyIt;
for (lobbyIt = lobbies.begin(); lobbyIt != lobbies.end(); ++lobbyIt) {
ChatLobbyId clId = *lobbyIt;
if (clId==itCL->first) {
ChatLobbyInfo clInfo;
if (rsMsgs->getChatLobbyInfo(clId,clInfo))
strLobbyName=QString::fromUtf8(clInfo.lobby_name.c_str()) ;
icoLobby=(clInfo.lobby_flags & RS_CHAT_LOBBY_FLAGS_PUBLIC) ? QIcon(":/images/chat_red24.png") : QIcon(":/images/chat_x24.png");
bFound=true;
break;
}
}
if (bFound){
makeSubMenu(trayMenu, icoLobby, strLobbyName, itCL->first);
} else {
_listMsg.erase(itCL);
doUpdate=true;
}
}
if (notifyCombined()) {
QSystemTrayIcon* trayIcon=getTrayIcon();
if (trayIcon!=NULL) trayIcon->setContextMenu(trayMenu);
} else {
QAction* action=getNotifyIcon();
if (action!=NULL) {
action->setMenu(trayMenu);
}
}
QString strName=tr("Remove All");
QAction *pAction = new QAction( QIcon(), strName, trayMenu);
ActionTag actionTag={0x0, "", true};
pAction->setData(qVariantFromValue(actionTag));
connect(trayMenu, SIGNAL(triggered(QAction*)), this, SLOT(subMenuClicked(QAction*)));
connect(trayMenu, SIGNAL(hovered(QAction*)), this, SLOT(subMenuHovered(QAction*)));
trayMenu->addAction(pAction);
trayMenu->exec(QCursor::pos());
if (doUpdate) updateIcon();
}
void ChatLobbyUserNotify::makeSubMenu(QMenu* parentMenu, QIcon icoLobby, QString strLobbyName, ChatLobbyId id)
{
lobby_map::iterator itCL=_listMsg.find(id);
if (itCL==_listMsg.end()) return;
msg_map msgMap = itCL->second;
unsigned int msgCount=msgMap.size();
if(!parentMenu) parentMenu = new QMenu(MainWindow::getInstance());
QMenu *lobbyMenu = parentMenu->addMenu(icoLobby, strLobbyName);
connect(lobbyMenu, SIGNAL(triggered(QAction*)), this, SLOT(subMenuClicked(QAction*)));
connect(lobbyMenu, SIGNAL(hovered(QAction*)), this, SLOT(subMenuHovered(QAction*)));
lobbyMenu->setToolTip(getNotifyMessage(msgCount>1).arg(msgCount));
for (msg_map::iterator itMsg=msgMap.begin(); itMsg!=msgMap.end(); ++itMsg) {
/// initialize menu ///
QString strName=itMsg->first;
MsgData msgData=itMsg->second;
QTextDocument doc;
doc.setHtml(msgData.text);
strName.append(":").append(doc.toPlainText().left(30).replace(QString("\n"),QString(" ")));
QAction *pAction = new QAction( icoLobby, strName, lobbyMenu);
pAction->setToolTip(doc.toPlainText());
ActionTag actionTag={itCL->first, itMsg->first, false};
pAction->setData(qVariantFromValue(actionTag));
lobbyMenu->addAction(pAction);
}
QString strName=tr("Remove All");
QAction *pAction = new QAction( icoLobby, strName, lobbyMenu);
ActionTag actionTag={itCL->first, "", true};
pAction->setData(qVariantFromValue(actionTag));
lobbyMenu->addAction(pAction);
}
void ChatLobbyUserNotify::iconHovered()
{
iconClicked();
}
void ChatLobbyUserNotify::chatLobbyNewMessage(ChatLobbyId lobby_id, QDateTime time, QString senderName, QString msg)
{
bool bGetNickName = false;
if (_bCheckForNickName) {
RsGxsId gxs_id;
rsMsgs->getIdentityForChatLobby(lobby_id,gxs_id);
RsIdentityDetails details ;
rsIdentity->getIdDetails(gxs_id,details) ;
bGetNickName = checkWord(msg, QString::fromUtf8(details.mNickname.c_str()));
}
bool bFoundTextToNotify = false;
if(_bCountSpecificText)
for (QStringList::Iterator it = _textToNotify.begin(); it != _textToNotify.end(); ++it) {
bFoundTextToNotify |= checkWord(msg, (*it));
}
if ((bGetNickName || bFoundTextToNotify || _bCountUnRead)){
QString strAnchor = time.toString(Qt::ISODate);
strAnchor.append("_").append(senderName);
MsgData msgData;
msgData.text=msg;
msgData.unread=!(bGetNickName || bFoundTextToNotify);
_listMsg[lobby_id][strAnchor]=msgData;
emit countChanged(lobby_id, _listMsg[lobby_id].size());
updateIcon();
}
}
bool ChatLobbyUserNotify::checkWord(QString message, QString word)
{
bool bFound = false;
int nFound = -1;
if (((nFound=message.indexOf(word)) != -1)
&& (!word.isEmpty())) {
QString eow=" ~!@#$%^&*()_+{}|:\"<>?,./;'[]\\-="; // end of word
bool bFirstCharEOW = (nFound==0)?true:(eow.indexOf(message.at(nFound-1)) != -1);
bool bLastCharEOW = ((nFound+word.length()-1) < message.length())
?(eow.indexOf(message.at(nFound+word.length())) != -1)
:true;
bFound = (bFirstCharEOW && bLastCharEOW);
}
return bFound;
}
void ChatLobbyUserNotify::chatLobbyCleared(ChatLobbyId lobby_id, QString anchor, bool onlyUnread /*=false*/)
{
bool changed = anchor.isEmpty();
unsigned int count=0;
if (lobby_id==0) return;
lobby_map::iterator itCL=_listMsg.find(lobby_id);
if (itCL!=_listMsg.end()) {
if (!anchor.isEmpty()) {
msg_map::iterator itMsg=itCL->second.find(anchor);
if (itMsg!=itCL->second.end()) {
MsgData msgData = itMsg->second;
if(!onlyUnread || msgData.unread) {
itCL->second.erase(itMsg);
changed=true;
}
}
count = itCL->second.size();
}
if (count==0) _listMsg.erase(itCL);
}
if (changed) emit countChanged(lobby_id, count);
updateIcon();
}
void ChatLobbyUserNotify::subMenuClicked(QAction* action)
{
ActionTag actionTag=action->data().value<ActionTag>();
if(!actionTag.removeALL){
MainWindow::showWindow(MainWindow::ChatLobby);
ChatLobbyWidget *chatLobbyWidget = dynamic_cast<ChatLobbyWidget*>(MainWindow::getPage(MainWindow::ChatLobby));
if (chatLobbyWidget) chatLobbyWidget->showLobbyAnchor(actionTag.cli ,actionTag.timeStamp);
}
lobby_map::iterator itCL=_listMsg.find(actionTag.cli);
if (itCL!=_listMsg.end()) {
unsigned int count=0;
if(!actionTag.removeALL){
msg_map::iterator itMsg=itCL->second.find(actionTag.timeStamp);
if (itMsg!=itCL->second.end()) itCL->second.erase(itMsg);
count = itCL->second.size();
}
if (count==0) _listMsg.erase(itCL);
emit countChanged(actionTag.cli, count);
} else if(actionTag.cli==0x0){
for(itCL=_listMsg.begin();itCL!=_listMsg.end();++itCL){
emit countChanged(itCL->first, 0);
_listMsg.erase(itCL);
}
}
QMenu *lobbyMenu=dynamic_cast<QMenu*>(action->parent());
if (lobbyMenu) lobbyMenu->removeAction(action);
updateIcon();
}
void ChatLobbyUserNotify::subMenuHovered(QAction* action)
{
QMenu *lobbyMenu=dynamic_cast<QMenu*>(action->parent());
if (lobbyMenu) lobbyMenu->setToolTip(action->toolTip());
}