overte-HifiExperiments/interface/src/ui/ChatWindow.cpp
2014-03-13 14:07:21 +02:00

220 lines
7.6 KiB
C++

//
// ChatWindow.cpp
// interface
//
// Created by Dimitar Dobrev on 3/6/14.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
//
#include <QFormLayout>
#include <QFrame>
#include <QLayoutItem>
#include <QPalette>
#include <QScrollBar>
#include <QSizePolicy>
#include <QTextDocument>
#include <QTimer>
#include "Application.h"
#include "FlowLayout.h"
#include "qtimespan.h"
#include "ui_chatWindow.h"
#include "XmppClient.h"
#include "ChatWindow.h"
const int NUM_MESSAGES_TO_TIME_STAMP = 20;
const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?))://\\S+)");
ChatWindow::ChatWindow() :
QDialog(Application::getInstance()->getGLWidget(), Qt::CustomizeWindowHint),
ui(new Ui::ChatWindow),
numMessagesAfterLastTimeStamp(0)
{
ui->setupUi(this);
FlowLayout* flowLayout = new FlowLayout(0, 4, 4);
ui->usersWidget->setLayout(flowLayout);
ui->messagePlainTextEdit->installEventFilter(this);
setAttribute(Qt::WA_DeleteOnClose);
#ifdef HAVE_QXMPP
const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient();
if (xmppClient.isConnected()) {
participantsChanged();
const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom();
connect(publicChatRoom, SIGNAL(participantsChanged()), this, SLOT(participantsChanged()));
ui->connectingToXMPPLabel->hide();
startTimerForTimeStamps();
} else {
ui->numOnlineLabel->hide();
ui->closeButton->hide();
ui->usersWidget->hide();
ui->messagesScrollArea->hide();
ui->messagePlainTextEdit->hide();
connect(&xmppClient, SIGNAL(connected()), this, SLOT(connected()));
}
connect(&xmppClient, SIGNAL(messageReceived(QXmppMessage)), this, SLOT(messageReceived(QXmppMessage)));
#endif
}
ChatWindow::~ChatWindow() {
#ifdef HAVE_QXMPP
const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient();
disconnect(&xmppClient, SIGNAL(connected()), this, SLOT(connected()));
disconnect(&xmppClient, SIGNAL(messageReceived(QXmppMessage)), this, SLOT(messageReceived(QXmppMessage)));
const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom();
disconnect(publicChatRoom, SIGNAL(participantsChanged()), this, SLOT(participantsChanged()));
#endif
delete ui;
}
void ChatWindow::reject() {
hide();
}
bool ChatWindow::eventFilter(QObject* sender, QEvent* event) {
Q_UNUSED(sender);
if (event->type() != QEvent::KeyPress) {
return false;
}
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if ((keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) &&
(keyEvent->modifiers() & Qt::ShiftModifier) == 0) {
QString messageText = ui->messagePlainTextEdit->document()->toPlainText().trimmed();
if (!messageText.isEmpty()) {
#ifdef HAVE_QXMPP
const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom();
QXmppMessage message;
message.setTo(publicChatRoom->jid());
message.setType(QXmppMessage::GroupChat);
message.setBody(messageText);
XmppClient::getInstance().getXMPPClient().sendPacket(message);
#endif
ui->messagePlainTextEdit->document()->clear();
}
return true;
}
return false;
}
#ifdef HAVE_QXMPP
QString ChatWindow::getParticipantName(const QString& participant) {
const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom();
return participant.right(participant.count() - 1 - publicChatRoom->jid().count());
}
#endif
void ChatWindow::addTimeStamp() {
QTimeSpan timePassed = QDateTime::currentDateTime() - lastMessageStamp;
int times[] = { timePassed.daysPart(), timePassed.hoursPart(), timePassed.minutesPart() };
QString strings[] = { tr("day", 0, times[0]), tr("hour", 0, times[1]), tr("minute", 0, times[2]) };
QString timeString = "";
for (int i = 0; i < 3; i++) {
if (times[i] > 0) {
timeString += strings[i] + " ";
}
}
timeString.chop(1);
if (!timeString.isEmpty()) {
QLabel* timeLabel = new QLabel(timeString);
timeLabel->setStyleSheet("color: palette(shadow);"
"background-color: palette(highlight);"
"padding: 4px;");
timeLabel->setAlignment(Qt::AlignHCenter);
ui->messagesFormLayout->addRow(timeLabel);
numMessagesAfterLastTimeStamp = 0;
}
}
void ChatWindow::startTimerForTimeStamps() {
QTimer* timer = new QTimer(this);
timer->setInterval(10 * 60 * 1000);
connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
timer->start();
}
void ChatWindow::connected() {
ui->connectingToXMPPLabel->hide();
ui->numOnlineLabel->show();
ui->closeButton->show();
ui->usersWidget->show();
ui->messagesScrollArea->show();
ui->messagePlainTextEdit->show();
ui->messagePlainTextEdit->setFocus();
#ifdef HAVE_QXMPP
const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom();
connect(publicChatRoom, SIGNAL(participantsChanged()), this, SLOT(participantsChanged()));
#endif
startTimerForTimeStamps();
}
void ChatWindow::timeout() {
if (numMessagesAfterLastTimeStamp >= NUM_MESSAGES_TO_TIME_STAMP) {
addTimeStamp();
}
}
#ifdef HAVE_QXMPP
void ChatWindow::error(QXmppClient::Error error) {
ui->connectingToXMPPLabel->setText(QString::number(error));
}
void ChatWindow::participantsChanged() {
QStringList participants = XmppClient::getInstance().getPublicChatRoom()->participants();
ui->numOnlineLabel->setText(tr("%1 online now:").arg(participants.count()));
while (QLayoutItem* item = ui->usersWidget->layout()->takeAt(0)) {
delete item->widget();
delete item;
}
foreach (const QString& participant, participants) {
QLabel* userLabel = new QLabel(getParticipantName(participant));
userLabel->setStyleSheet("background-color: palette(light);"
"border-radius: 5px;"
"color: #267077;"
"padding: 2px;"
"border: 1px solid palette(shadow);"
"font-weight: bold");
ui->usersWidget->layout()->addWidget(userLabel);
}
}
void ChatWindow::messageReceived(const QXmppMessage& message) {
if (message.type() != QXmppMessage::GroupChat) {
return;
}
QLabel* userLabel = new QLabel(getParticipantName(message.from()));
userLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
userLabel->setStyleSheet("padding: 2px; font-weight: bold");
userLabel->setAlignment(Qt::AlignTop);
QLabel* messageLabel = new QLabel(message.body().replace(regexLinks, "<a href=\"\\1\">\\1</a>"));
messageLabel->setWordWrap(true);
messageLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
messageLabel->setOpenExternalLinks(true);
messageLabel->setStyleSheet("padding: 2px; margin-right: 20px");
messageLabel->setAlignment(Qt::AlignTop);
ui->messagesFormLayout->addRow(userLabel, messageLabel);
ui->messagesFormLayout->parentWidget()->updateGeometry();
Application::processEvents();
QScrollBar* verticalScrollBar = ui->messagesScrollArea->verticalScrollBar();
verticalScrollBar->setSliderPosition(verticalScrollBar->maximum());
messageLabel->updateGeometry();
++numMessagesAfterLastTimeStamp;
if (message.stamp().isValid()) {
lastMessageStamp = message.stamp().toLocalTime();
} else {
lastMessageStamp = QDateTime::currentDateTime();
}
}
#endif