mirror of
https://github.com/RetroShare/RetroShare.git
synced 2024-10-01 02:35:48 -04:00
32ac7efb42
git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@5125 b45a01b8-16f6-495d-af2f-9b41ad6348cc
768 lines
21 KiB
C++
768 lines
21 KiB
C++
/****************************************************************
|
|
*
|
|
* RetroShare is distributed under the following license:
|
|
*
|
|
* Copyright (C) 2011, RetroShare Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
****************************************************************/
|
|
|
|
#include <QApplication>
|
|
#include <QMenu>
|
|
#include <QKeyEvent>
|
|
#include <QScrollBar>
|
|
#include <QColorDialog>
|
|
#include <QFontDialog>
|
|
#include <QMessageBox>
|
|
|
|
#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 <retroshare/rsstatus.h>
|
|
#include <retroshare/rspeers.h>
|
|
#include <retroshare/rshistory.h>
|
|
|
|
#include <time.h>
|
|
|
|
/*****
|
|
* #define CHAT_DEBUG 1
|
|
*****/
|
|
|
|
ChatWidget::ChatWidget(QWidget *parent) :
|
|
QWidget(parent), ui(new Ui::ChatWidget)
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
newMessages = false;
|
|
typing = false;
|
|
peerStatus = 0;
|
|
isChatLobby = false;
|
|
firstShow = true;
|
|
inChatCharFormatChanged = false;
|
|
|
|
lastStatusSendTime = 0 ;
|
|
|
|
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->colorButton, SIGNAL(clicked()), this, SLOT(chooseColor()));
|
|
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->actionChooseFont, SIGNAL(triggered()), this, SLOT(chooseFont()));
|
|
connect(ui->actionResetFont, SIGNAL(triggered()), this, SLOT(resetFont()));
|
|
|
|
connect(ui->hashBox, SIGNAL(fileHashingFinished(QList<HashedFile>)), this, SLOT(fileHashingFinished(QList<HashedFile>)));
|
|
|
|
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)));
|
|
// reset text and color after removing all characters from the QTextEdit and after calling QTextEdit::clear
|
|
connect(ui->chattextEdit, SIGNAL(currentCharFormatChanged(QTextCharFormat)), this, SLOT(chatCharFormatChanged()));
|
|
|
|
ui->infoframe->setVisible(false);
|
|
ui->statusmessagelabel->hide();
|
|
|
|
setAcceptDrops(true);
|
|
ui->chattextEdit->setAcceptDrops(false);
|
|
ui->hashBox->setDropWidget(this);
|
|
ui->hashBox->setAutoHide(true);
|
|
|
|
QMenu *menu = new QMenu();
|
|
menu->addAction(ui->actionChooseFont);
|
|
menu->addAction(ui->actionResetFont);
|
|
ui->fontButton->setMenu(menu);
|
|
|
|
menu = new QMenu();
|
|
menu->addAction(ui->actionClearChatHistory);
|
|
menu->addAction(ui->actionDeleteChatHistory);
|
|
menu->addAction(ui->actionSaveChatHistory);
|
|
menu->addAction(ui->actionMessageHistory);
|
|
ui->pushtoolsButton->setMenu(menu);
|
|
|
|
ui->chattextEdit->installEventFilter(this);
|
|
|
|
#ifdef RS_RELEASE_VERSION
|
|
ui->attachPictureButton->setVisible(false);
|
|
#endif
|
|
|
|
resetStatusBar();
|
|
}
|
|
|
|
ChatWidget::~ChatWidget()
|
|
{
|
|
processSettings(false);
|
|
|
|
delete ui;
|
|
}
|
|
|
|
void ChatWidget::addChatButton(QPushButton *button)
|
|
{
|
|
ui->chatButtonLayout->addWidget(button) ;
|
|
}
|
|
|
|
void ChatWidget::init(const std::string &peerId, const QString &title)
|
|
{
|
|
this->peerId = peerId;
|
|
this->title = title;
|
|
|
|
ui->titleLabel->setText(title);
|
|
|
|
std::string ownId = rsPeers->getOwnId();
|
|
setName(QString::fromUtf8(rsPeers->getPeerName(ownId).c_str()));
|
|
|
|
ChatLobbyId lid;
|
|
if (rsMsgs->isLobbyId(peerId, lid)) {
|
|
isChatLobby = true;
|
|
chatStyle.setStyleFromSettings(ChatStyle::TYPE_PUBLIC);
|
|
} else {
|
|
chatStyle.setStyleFromSettings(ChatStyle::TYPE_PRIVATE);
|
|
}
|
|
|
|
currentColor.setNamedColor(PeerSettings->getPrivateChatColor(peerId));
|
|
currentFont.fromString(PeerSettings->getPrivateChatFont(peerId));
|
|
|
|
colorChanged();
|
|
fontChanged();
|
|
setColorAndFont();
|
|
|
|
// 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);
|
|
|
|
updateTitle();
|
|
}
|
|
|
|
if (rsHistory->getEnable(false)) {
|
|
// get chat messages from history
|
|
std::list<HistoryMsg> historyMsgs;
|
|
int messageCount = Settings->getPrivateChatHistoryCount();
|
|
if (messageCount > 0) {
|
|
rsHistory->getMessages(peerId, historyMsgs, messageCount);
|
|
|
|
std::list<HistoryMsg>::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<QKeyEvent*>(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();
|
|
|
|
if (firstShow) {
|
|
// Workaround: now the scroll position is correct calculated
|
|
firstShow = false;
|
|
QScrollBar *scrollbar = ui->textBrowser->verticalScrollBar();
|
|
scrollbar->setValue(scrollbar->maximum());
|
|
}
|
|
}
|
|
|
|
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::setWelcomeMessage(QString &text)
|
|
{
|
|
ui->textBrowser->setText(text);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
if (chatType == TYPE_SYSTEM) {
|
|
formatFlag |= CHAT_FORMATMSG_SYSTEM;
|
|
}
|
|
|
|
QString formatMsg = chatStyle.formatMessage(type, name, incoming ? sendTime : recvTime, message, formatFlag);
|
|
|
|
ui->textBrowser->append(formatMsg);
|
|
|
|
resetStatusBar();
|
|
|
|
if (incoming && chatType == TYPE_NORMAL) {
|
|
emit newMessage(this);
|
|
|
|
if (!isActive()) {
|
|
newMessages = true;
|
|
}
|
|
|
|
emit infoChanged(this);
|
|
}
|
|
}
|
|
|
|
bool ChatWidget::isActive()
|
|
{
|
|
if (!isVisible() || (window() && (!window()->isActiveWindow() || window()->isMinimized()))) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void ChatWidget::pasteLink()
|
|
{
|
|
std::cerr << "In paste link" << std::endl;
|
|
ui->chattextEdit->insertHtml(RSLinkClipboard::toHtml());
|
|
}
|
|
|
|
void ChatWidget::pasteOwnCertificateLink()
|
|
{
|
|
std::cerr << "In paste own certificate link" << std::endl;
|
|
RetroShareLink link ;
|
|
std::string ownId = rsPeers->getOwnId() ;
|
|
|
|
if( link.createCertificate(ownId) ) {
|
|
ui->chattextEdit->insertHtml(link.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->addAction(QIcon(":/images/pasterslink.png"), tr("Paste own certificate link"), this, SLOT(pasteOwnCertificateLink()));
|
|
|
|
contextMnu->exec(QCursor::pos());
|
|
delete(contextMnu);
|
|
}
|
|
|
|
void ChatWidget::chatCharFormatChanged()
|
|
{
|
|
if (inChatCharFormatChanged) {
|
|
return;
|
|
}
|
|
|
|
inChatCharFormatChanged = true;
|
|
|
|
// Reset font and color before inserting a character if edit box is empty
|
|
// (color info disappears when the user deletes all text)
|
|
if (ui->chattextEdit->toPlainText().isEmpty()) {
|
|
setColorAndFont();
|
|
}
|
|
|
|
inChatCharFormatChanged = false;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
#ifdef CHAT_DEBUG
|
|
std::cout << "ChatWidget:sendChat " << std::endl;
|
|
#endif
|
|
|
|
if (rsMsgs->sendPrivateChat(peerId, msg)) {
|
|
QDateTime currentTime = QDateTime::currentDateTime();
|
|
addChatMsg(false, name, 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 ());
|
|
}
|
|
|
|
void ChatWidget::on_closeInfoFrameButton_clicked()
|
|
{
|
|
ui->infoframe->setVisible(false);
|
|
}
|
|
|
|
void ChatWidget::chooseColor()
|
|
{
|
|
bool ok;
|
|
QRgb color = QColorDialog::getRgba(ui->chattextEdit->textColor().rgba(), &ok, window());
|
|
if (ok) {
|
|
currentColor = QColor(color);
|
|
PeerSettings->setPrivateChatColor(peerId, currentColor.name());
|
|
colorChanged();
|
|
setColorAndFont();
|
|
}
|
|
}
|
|
|
|
void ChatWidget::colorChanged()
|
|
{
|
|
QPixmap pix(16, 16);
|
|
pix.fill(currentColor);
|
|
ui->colorButton->setIcon(pix);
|
|
}
|
|
|
|
void ChatWidget::chooseFont()
|
|
{
|
|
bool ok;
|
|
QFont font = QFontDialog::getFont(&ok, currentFont, this);
|
|
if (ok) {
|
|
currentFont = font;
|
|
fontChanged();
|
|
setFont();
|
|
}
|
|
}
|
|
|
|
void ChatWidget::resetFont()
|
|
{
|
|
currentFont.fromString(Settings->getChatScreenFont());
|
|
fontChanged();
|
|
setFont();
|
|
}
|
|
|
|
void ChatWidget::fontChanged()
|
|
{
|
|
ui->textboldButton->setChecked(currentFont.bold());
|
|
ui->textunderlineButton->setChecked(currentFont.underline());
|
|
ui->textitalicButton->setChecked(currentFont.italic());
|
|
}
|
|
|
|
void ChatWidget::setColorAndFont()
|
|
{
|
|
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();
|
|
}
|
|
|
|
void ChatWidget::setFont()
|
|
{
|
|
setColorAndFont();
|
|
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<QPushButton*>(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<HashedFile> hashedFiles)
|
|
{
|
|
std::cerr << "ChatWidget::fileHashingFinished() started." << std::endl;
|
|
|
|
QString message;
|
|
|
|
QList<HashedFile>::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("<img src=\"file:///%1\" width=\"100\" height=\"100\">").arg(hashedFile.filepath);
|
|
message+="<br>";
|
|
} else {
|
|
QString image = FilesDefs::getImageFromFilename(hashedFile.filename, false);
|
|
if (!image.isEmpty()) {
|
|
message += QString("<img src=\"%1\">").arg(image);
|
|
}
|
|
}
|
|
message += link.toHtmlSize();
|
|
if (it != hashedFiles.end()) {
|
|
message += "<BR>";
|
|
}
|
|
}
|
|
|
|
#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)) {
|
|
QDateTime currentTime = QDateTime::currentDateTime();
|
|
addChatMsg(false, name, 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)
|
|
{
|
|
if (isChatLobby) {
|
|
// updateTitle is used
|
|
return;
|
|
}
|
|
|
|
/* set font size for status */
|
|
if (peer_id.toStdString() == peerId) {
|
|
// the peers status has changed
|
|
|
|
QString peerName = QString::fromUtf8(rsPeers->getPeerName(peerId).c_str());
|
|
|
|
// is scrollbar at the end?
|
|
QScrollBar *scrollbar = ui->textBrowser->verticalScrollBar();
|
|
bool atEnd = (scrollbar->value() == scrollbar->maximum());
|
|
|
|
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("<span style=\"font-size:11pt; font-weight:500;""\">%1</span>");
|
|
ui->titleLabel->setText(peerName + " (" + statusString.arg(StatusDefs::name(status)) + ")") ;
|
|
|
|
peerStatus = status;
|
|
|
|
if (atEnd) {
|
|
// scroll to the end
|
|
scrollbar->setValue(scrollbar->maximum());
|
|
}
|
|
|
|
emit infoChanged(this);
|
|
emit statusChanged(status);
|
|
|
|
return;
|
|
}
|
|
|
|
// ignore status change
|
|
}
|
|
|
|
void ChatWidget::updateTitle()
|
|
{
|
|
if (!isChatLobby) {
|
|
// updateStatus is used
|
|
return;
|
|
}
|
|
|
|
ui->titleLabel->setText(name + "@" + title);
|
|
}
|
|
|
|
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())) ;
|
|
}
|
|
|
|
void ChatWidget::setName(const QString &name)
|
|
{
|
|
this->name = name;
|
|
updateTitle();
|
|
}
|
|
|
|
bool ChatWidget::setStyle()
|
|
{
|
|
if (style.showDialog(window())) {
|
|
PeerSettings->setStyle(peerId, "PopupChatDialog", style);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|