/*
# Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of
# Freiburg
#
# This program is free software distributed under the GPL version 2.
# See http://openslx.org/COPYING
#
# If you have any feedback please consult http://openslx.org/feedback and
# send your suggestions, praise, or complaints to feedback@openslx.org
#
# General information about OpenSLX can be found at http://openslx.org/
# -----------------------------------------------------------------------------
# clientChatDialog.cpp
# - graphical chat interface
# -----------------------------------------------------------------------------
*/
#include "clientChatDialog.h"
ClientChatDialog::ClientChatDialog(QWidget *parent) :
QDialog(parent)
{
_trayIcon = NULL;
_nickname = "";
setupUi(this);
setAcceptDrops(true);
connect(pushButton, SIGNAL(clicked()), this, SLOT(send()));
// connect to D-Bus and get interface
QDBusConnection dbus = QDBusConnection::sessionBus();
_ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this);
connect(_ifaceDBus, SIGNAL(chat_receive(QString, QString, QString)), this,
SLOT(receive(QString, QString, QString)));
// add first tab for public messages
tabWidget->clear();
QTextEdit *t = new QTextEdit();
t->setReadOnly(true);
tabWidget->addTab(t, "@all");
_hash = new QHash<QString, QTextEdit*> ();
_hash->insert(tabWidget->tabText(0), t);
// already connected?
QDBusPendingReply<QString> reply = _ifaceDBus->isConnected();
reply.waitForFinished();
if (reply.isValid() && reply.value() != "")
{
// get available nicknames if already connected
QDBusPendingReply<QStringList> reply1 = _ifaceDBus->chat_getNicknames();
reply1.waitForFinished();
QStringList nicknames = reply1.value();
if (reply1.isValid() && !nicknames.isEmpty())
listWidget->addItems(nicknames);
connected();
}
else
disconnected();
// setup menu
_menu = new QMenu();
_sendFileAction = new QAction(tr("&Send File..."), this);
_menu->addAction(_sendFileAction);
connect(listWidget, SIGNAL(doubleClicked(QModelIndex)), this,
SLOT(addTab(QModelIndex)));
connect(tabWidget, SIGNAL(tabCloseRequested(int)), this,
SLOT(removeTab(int)));
connect(tabWidget, SIGNAL(currentChanged(int)), this, SLOT(removeIcon(int)));
connect(listWidget, SIGNAL(customContextMenuRequested(QPoint)), this,
SLOT(showMenu(QPoint)));
connect(_sendFileAction, SIGNAL(triggered()), this,
SLOT(sendFile()));
connect(_ifaceDBus, SIGNAL(chat_client_add(QString)), this,
SLOT(addClient(QString)));
connect(_ifaceDBus, SIGNAL(chat_client_remove(QString)), this,
SLOT(removeClient(QString)));
connect(_ifaceDBus, SIGNAL(disconnected()), listWidget,
SLOT(clear()));
connect(_ifaceDBus, SIGNAL(connected(QString)), this,
SLOT(connected()));
connect(_ifaceDBus, SIGNAL(disconnected()), this,
SLOT(disconnected()));
lineEdit->setFocus();
}
ClientChatDialog::~ClientChatDialog()
{
}
////////////////////////////////////////////////////////////////////////////////
// Public
void ClientChatDialog::setTrayIcon(QSystemTrayIcon *trayIcon)
{
_trayIcon = trayIcon;
// FIXME: messageClicked() is always emitted, not only on chat msg
//connect(_trayIcon, SIGNAL(messageClicked()), this, SLOT(open()));
}
////////////////////////////////////////////////////////////////////////////////
// Protected
void ClientChatDialog::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasUrls())
event->accept();
}
void ClientChatDialog::dropEvent(QDropEvent *event)
{
event->accept();
sendFile(event->mimeData()->urls().first().toLocalFile());
}
////////////////////////////////////////////////////////////////////////////////
// Private
void ClientChatDialog::send()
{
QString msg = lineEdit->text();
if (msg != "")
{
QString nick_to = tabWidget->tabText(tabWidget->currentIndex());
_ifaceDBus->chat_send(nick_to, _nickname, msg);
lineEdit->clear();
lineEdit->setFocus();
qDebug("[%s] S %s -> %s : %s", metaObject()->className(),
qPrintable(_nickname), qPrintable(nick_to), qPrintable(msg));
}
}
void ClientChatDialog::receive(QString nick_from, QString nick_to, QString msg)
{
qDebug("[%s] R %s <- %s : %s", metaObject()->className(),
qPrintable(nick_to), qPrintable(nick_from), qPrintable(msg));
if (nick_to == tabWidget->tabText(0) || nick_from == _nickname)
printMsg(nick_from, msg, getTab(nick_to)); // public message or own msg
else
printMsg(nick_from, msg, getTab(nick_from)); // private message
}
void ClientChatDialog::addTab(QModelIndex i)
{
QString text = i.data().toString();
if (_hash->contains(text))
tabWidget->setCurrentWidget(_hash->value(text));
else
{
QTextEdit *t = new QTextEdit();
t->setReadOnly(true);
tabWidget->setCurrentIndex(tabWidget->addTab(t, text));
_hash->insert(text, t);
}
lineEdit->setFocus();
}
void ClientChatDialog::removeTab(int i)
{
if (i != 0)
{
_hash->remove(tabWidget->tabText(i));
tabWidget->removeTab(i);
lineEdit->setFocus();
}
}
void ClientChatDialog::addClient(QString nick)
{
listWidget->addItem(nick);
printEvent("-> " + nick + tr(" has joined the chat."));
}
void ClientChatDialog::removeClient(QString nick)
{
delete listWidget->findItems(nick, Qt::MatchExactly).first();
printEvent("<- " + nick + tr(" has left the chat."));
}
void ClientChatDialog::removeIcon(int i)
{
tabWidget->setTabIcon(i, QIcon());
}
void ClientChatDialog::showMenu(QPoint p)
{
_menu->popup(listWidget->mapToGlobal(p));
}
void ClientChatDialog::sendFile()
{
ClientFileSendDialog *d = new ClientFileSendDialog(this);
d->open(listWidget->currentItem()->text());
}
void ClientChatDialog::sendFile(QString filename)
{
if (tabWidget->currentIndex() == 0 || filename == "")
return;
// ask user
QString nick = tabWidget->tabText(tabWidget->currentIndex());
QMessageBox::StandardButton result = QMessageBox::question(0,
tr("PVS File Transfer"),
tr("Send file '") + filename + tr("' to ") + nick + "?",
QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
if (result != QMessageBox::Ok)
return;
ClientFileSendDialog *d = new ClientFileSendDialog(this);
d->open(nick, filename);
}
void ClientChatDialog::connected()
{
// get current users name from backend
QDBusPendingReply<QString> reply = _ifaceDBus->chat_getNickname();
reply.waitForFinished();
if (reply.isValid())
{
_nickname = reply.value();
pushButton->setEnabled(true);
printEvent("!!! " + tr("Connected."));
}
qDebug("[%s] Nickname: '%s'", metaObject()->className(),
qPrintable(_nickname));
}
void ClientChatDialog::disconnected()
{
pushButton->setEnabled(false);
printEvent("!!! " + tr("Disconnected."));
}
QTextEdit* ClientChatDialog::getTab(QString text)
{
if (!_hash->contains(text))
{
QTextEdit *t = new QTextEdit();
t->setReadOnly(true);
tabWidget->addTab(t, text);
_hash->insert(text, t);
}
lineEdit->setFocus();
return _hash->value(text);
}
void ClientChatDialog::printMsg(QString nick_from, QString msg, QTextEdit *t)
{
// move cursor at the end
t->moveCursor(QTextCursor::End);
// print time
t->setTextColor(QColor(0, 100, 0));
t->append("[" + QTime::currentTime().toString("hh:mm") + "] ");
// print nickname
t->setTextColor(QColor(0, 0, 255));
t->insertPlainText("<" + nick_from + "> ");
// print message
t->setTextColor(QColor(0, 0, 0));
t->insertPlainText(msg);
// show icon if not current tab
if (tabWidget->currentIndex() != tabWidget->indexOf(t))
tabWidget->setTabIcon(tabWidget->indexOf(t), QIcon(":chat_msg16.svg"));
// show balloon message if supported and chat-dialog is not visible
if (!isVisible() && _trayIcon && QSystemTrayIcon::supportsMessages())
_trayIcon->showMessage(tr("Message from <") + nick_from + ">", msg,
QSystemTrayIcon::Information, 20000);
}
void ClientChatDialog::printEvent(QString msg)
{
QTextEdit *t = _hash->value(tabWidget->tabText(0));
// move cursor at the end
t->moveCursor(QTextCursor::End);
t->setTextColor(QColor(150, 150, 150));
// print time
t->append("[" + QTime::currentTime().toString("hh:mm") + "] ");
// print message
t->insertPlainText(msg);
}