summaryrefslogblamecommitdiffstats
path: root/src/gui/clientChatDialog.cpp
blob: 163ac92292e9fc21cf2df9370c315c94c60420bd (plain) (tree)






























                                                                                








































































































































































































































































                                                                                 
/*
 # 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);
}