/* # 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 (); _hash->insert(tabWidget->tabText(0), t); // already connected? QDBusPendingReply reply = _ifaceDBus->isConnected(); reply.waitForFinished(); if (reply.isValid() && reply.value() != "") { // get available nicknames if already connected QDBusPendingReply 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 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); }