From 86643803cf0456996ed37114185dc5ca335c285d Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Mon, 10 Mar 2014 16:01:53 +0200 Subject: [PATCH] Moved the connection and configuration of XMPP to the log-in process. --- CMakeLists.txt | 6 --- cmake/modules/FindQxmpp.cmake | 4 +- interface/CMakeLists.txt | 1 + interface/interface_en.ts | 16 +++---- interface/src/Menu.cpp | 15 ++++++- interface/src/Menu.h | 2 + interface/src/XmppClient.cpp | 65 ++++++++++++++++++++++++++++ interface/src/XmppClient.h | 43 +++++++++++++++++++ interface/src/ui/ChatWindow.cpp | 74 ++++++++++++++++++-------------- interface/src/ui/ChatWindow.h | 6 +-- interface/src/ui/FlowLayout.cpp | 2 +- libraries/shared/CMakeLists.txt | 2 +- libraries/shared/src/qtimespan.h | 54 +++++++++++------------ 13 files changed, 208 insertions(+), 82 deletions(-) create mode 100644 interface/src/XmppClient.cpp create mode 100644 interface/src/XmppClient.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b3e1af23e8..33589ddb57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,12 +34,6 @@ if (APPLE) endif (DARWIN_VERSION GREATER 12) endif (APPLE) -set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/") - -find_package(qxmpp REQUIRED) -add_definitions(-DQXMPP_STATIC) -include_directories(SYSTEM ${QXMPP_INCLUDE_DIR}) - # targets not supported on windows if (NOT WIN32) add_subdirectory(animation-server) diff --git a/cmake/modules/FindQxmpp.cmake b/cmake/modules/FindQxmpp.cmake index f50212d63f..13ff1ed855 100644 --- a/cmake/modules/FindQxmpp.cmake +++ b/cmake/modules/FindQxmpp.cmake @@ -29,10 +29,10 @@ else () if (QXMPP_FOUND) if (NOT QXMPP_FIND_QUIETLY) message(STATUS "Found qxmpp: ${QXMPP_LIBRARY}") - endif (NOT QXMPP_FIND_QUIETLY) + endif () else () if (QXMPP_FIND_REQUIRED) message(FATAL_ERROR "Could not find qxmpp") - endif (SIXENSE_FIND_REQUIRED) + endif () endif () endif () \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 6ec0b6f679..2559c00207 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -182,6 +182,7 @@ target_link_libraries( ${TARGET_NAME} "${FACESHIFT_LIBRARIES}" "${ZLIB_LIBRARIES}" + "${QXMPP_LIBRARY}" Qt5::Core Qt5::Gui Qt5::Multimedia Qt5::Network Qt5::OpenGL Qt5::Script Qt5::Svg Qt5::WebKit Qt5::WebKitWidgets Qt5::Xml Qt5::UiTools ) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 8198d97a8f..e5461bc1c2 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -45,7 +45,7 @@ - + day %n day @@ -53,7 +53,7 @@ - + hour %n hour @@ -61,7 +61,7 @@ - + minute %n minute @@ -76,7 +76,7 @@ - + %1 online now: @@ -113,18 +113,18 @@ Menu - + Open .ini config file - - + + Text files (*.ini) - + Save .ini config file diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 60e93b0cea..2331a1bceb 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include "Application.h" @@ -161,7 +162,12 @@ Menu::Menu() : QMenu* toolsMenu = addMenu("Tools"); addActionToQMenuAndActionHash(toolsMenu, MenuOption::MetavoxelEditor, 0, this, SLOT(showMetavoxelEditor())); addActionToQMenuAndActionHash(toolsMenu, MenuOption::FstUploader, 0, Application::getInstance(), SLOT(uploadFST())); - addActionToQMenuAndActionHash(toolsMenu, MenuOption::Chat, 0, this, SLOT(showChat())); + + _chatAction = addActionToQMenuAndActionHash(toolsMenu, MenuOption::Chat, 0, this, SLOT(showChat())); + const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient(); + toggleChat(); + connect(&xmppClient, SIGNAL(connected()), this, SLOT(toggleChat())); + connect(&xmppClient, SIGNAL(disconnected()), this, SLOT(toggleChat())); QMenu* viewMenu = addMenu("View"); @@ -1039,6 +1045,13 @@ void Menu::showChat() { _chatWindow->raise(); } +void Menu::toggleChat() { + _chatAction->setEnabled(XmppClient::getInstance().getXMPPClient().isConnected()); + if (!_chatAction->isEnabled() && _chatWindow) { + _chatWindow->close(); + } +} + void Menu::audioMuteToggled() { QAction *muteAction = _actionHash.value(MenuOption::MuteAudio); muteAction->setChecked(Application::getInstance()->getAudio()->getMuted()); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index cd32a9c8df..380fe2d3b7 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -144,6 +144,7 @@ private slots: void runTests(); void showMetavoxelEditor(); void showChat(); + void toggleChat(); void audioMuteToggled(); private: @@ -204,6 +205,7 @@ private: quint64 _lastAdjust; SimpleMovingAverage _fpsAverage; QAction* _loginAction; + QAction* _chatAction; }; namespace MenuOption { diff --git a/interface/src/XmppClient.cpp b/interface/src/XmppClient.cpp new file mode 100644 index 0000000000..a3716c781e --- /dev/null +++ b/interface/src/XmppClient.cpp @@ -0,0 +1,65 @@ +// +// XmppClient.cpp +// interface +// +// Created by Dimitar Dobrev on 10/3/14 +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#include + +#include "XmppClient.h" + +const QString DEFAULT_XMPP_SERVER = "chat.highfidelity.io"; +const QString DEFAULT_CHAT_ROOM = "public@public-chat.highfidelity.io"; + +XmppClient::XmppClient() : + _xmppClient(), + _xmppMUCManager() { + AccountManager& accountManager = AccountManager::getInstance(); + connect(&accountManager, SIGNAL(accessTokenChanged()), this, SLOT(connectToServer())); + connect(&accountManager, SIGNAL(logoutComplete()), this, SLOT(disconnectFromServer())); +} + +XmppClient& XmppClient::getInstance() { + static XmppClient sharedInstance; + return sharedInstance; +} + +void XmppClient::xmppConnected() { + _publicChatRoom = _xmppMUCManager.addRoom(DEFAULT_CHAT_ROOM); + _publicChatRoom->setNickName(AccountManager::getInstance().getUsername()); + _publicChatRoom->join(); +} + +void XmppClient::xmppError(QXmppClient::Error error) { + qDebug() << "Error connnecting to XMPP for user " << AccountManager::getInstance().getUsername() << ": " << error; +} + +void XmppClient::connectToServer() { + disconnectFromServer(); + + if (_xmppClient.addExtension(&_xmppMUCManager)) { + connect(&_xmppClient, SIGNAL(connected()), this, SLOT(xmppConnected())); + connect(&_xmppClient, SIGNAL(error(QXmppClient::Error)), this, SLOT(xmppError(QXmppClient::Error))); + } + AccountManager& accountManager = AccountManager::getInstance(); + QString user = accountManager.getUsername(); + const QString& password = accountManager.getXMPPPassword(); + _xmppClient.connectToServer(user + "@" + DEFAULT_XMPP_SERVER, password); +} + +void XmppClient::disconnectFromServer() +{ + if (_xmppClient.isConnected()) { + _xmppClient.disconnectFromServer(); + } +} + +XmppClient::XmppClient(const XmppClient& other) { + Q_UNUSED(other); +} + +void XmppClient::operator =(XmppClient const& other) { + Q_UNUSED(other); +} diff --git a/interface/src/XmppClient.h b/interface/src/XmppClient.h new file mode 100644 index 0000000000..1ebe868424 --- /dev/null +++ b/interface/src/XmppClient.h @@ -0,0 +1,43 @@ +// +// XmppClient.h +// interface +// +// Created by Dimitar Dobrev on 10/3/14 +// Copyright (c) 2013 High Fidelity, Inc. All rights reserved. +// + +#ifndef __interface__XmppClient__ +#define __interface__XmppClient__ + +#include +#include +#include + +/// Generalized threaded processor for handling received inbound packets. +class XmppClient : public QObject { + Q_OBJECT + +public: + static XmppClient& getInstance(); + + QXmppClient& getXMPPClient() { return _xmppClient; } + const QXmppMucRoom* getPublicChatRoom() const { return _publicChatRoom; } + +private slots: + void xmppConnected(); + void xmppError(QXmppClient::Error error); + + void connectToServer(); + void disconnectFromServer(); + +private: + XmppClient(); + XmppClient(XmppClient const& other); // not implemented + void operator=(XmppClient const& other); // not implemented + + QXmppClient _xmppClient; + QXmppMucManager _xmppMUCManager; + QXmppMucRoom* _publicChatRoom; +}; + +#endif // __interface__XmppClient__ diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 4e4b869cda..7bcec5a2a9 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -16,17 +16,13 @@ #include #include "ChatWindow.h" -#include "ui_chatwindow.h" +#include "ui_chatWindow.h" #include "FlowLayout.h" #include "qtimespan.h" -#include -#include #include -#include +#include -const QString DEFAULT_SERVER = "chat.highfidelity.io"; -const QString DEFAULT_CHAT_ROOM = "public@public-chat.highfidelity.io"; const int NUM_MESSAGES_TO_TIME_STAMP = 20; const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?))://\\S+)"); @@ -42,25 +38,34 @@ ChatWindow::ChatWindow() : ui->messagePlainTextEdit->installEventFilter(this); - ui->numOnlineLabel->hide(); - ui->usersWidget->hide(); - ui->messagesScrollArea->hide(); - ui->messagePlainTextEdit->hide(); - setAttribute(Qt::WA_DeleteOnClose); - _xmppClient.addExtension(&_xmppMUCManager); - connect(&_xmppClient, SIGNAL(connected()), this, SLOT(connected())); - connect(&_xmppClient, SIGNAL(error(QXmppClient::Error)), this, SLOT(error(QXmppClient::Error))); - connect(&_xmppClient, SIGNAL(messageReceived(QXmppMessage)), this, SLOT(messageReceived(QXmppMessage))); - - AccountManager& accountManager = AccountManager::getInstance(); - QString user = accountManager.getUsername(); - const QString& password = accountManager.getXMPPPassword(); - _xmppClient.connectToServer(user + "@" + DEFAULT_SERVER, password); + 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->usersWidget->hide(); + ui->messagesScrollArea->hide(); + ui->messagePlainTextEdit->hide(); + connect(&xmppClient, SIGNAL(connected()), this, SLOT(connected())); + } + connect(&xmppClient, SIGNAL(messageReceived(QXmppMessage)), this, SLOT(messageReceived(QXmppMessage))); } ChatWindow::~ChatWindow() { + 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())); + delete ui; } @@ -75,7 +80,8 @@ bool ChatWindow::eventFilter(QObject* sender, QEvent* event) { (keyEvent->modifiers() & Qt::ShiftModifier) == 0) { QString message = ui->messagePlainTextEdit->document()->toPlainText(); if (!message.trimmed().isEmpty()) { - _xmppClient.sendMessage(_chatRoom->jid(), message); + const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); + XmppClient::getInstance().getXMPPClient().sendMessage(publicChatRoom->jid(), message); ui->messagePlainTextEdit->document()->clear(); } return true; @@ -84,7 +90,8 @@ bool ChatWindow::eventFilter(QObject* sender, QEvent* event) { } QString ChatWindow::getParticipantName(const QString& participant) { - return participant.right(participant.count() - 1 - _chatRoom->jid().count()); + const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); + return participant.right(participant.count() - 1 - publicChatRoom->jid().count()); } void ChatWindow::addTimeStamp() { @@ -107,22 +114,25 @@ void ChatWindow::addTimeStamp() { numMessagesAfterLastTimeStamp = 0; } -void ChatWindow::connected() { - _chatRoom = _xmppMUCManager.addRoom(DEFAULT_CHAT_ROOM); - connect(_chatRoom, SIGNAL(participantsChanged()), this, SLOT(participantsChanged())); - _chatRoom->setNickName(AccountManager::getInstance().getUsername()); - _chatRoom->join(); +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->usersWidget->show(); ui->messagesScrollArea->show(); ui->messagePlainTextEdit->show(); - QTimer* timer = new QTimer(this); - timer->setInterval(10 * 60 * 1000); - connect(timer, SIGNAL(timeout()), this, SLOT(timeout())); - timer->start(); + const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); + connect(publicChatRoom, SIGNAL(participantsChanged()), this, SLOT(participantsChanged())); + + startTimerForTimeStamps(); } void ChatWindow::timeout() { @@ -136,7 +146,7 @@ void ChatWindow::error(QXmppClient::Error error) { } void ChatWindow::participantsChanged() { - QStringList participants = _chatRoom->participants(); + QStringList participants = XmppClient::getInstance().getPublicChatRoom()->participants(); ui->numOnlineLabel->setText(tr("%1 online now:").arg(participants.count())); while (QLayoutItem* item = ui->usersWidget->layout()->takeAt(0)) { diff --git a/interface/src/ui/ChatWindow.h b/interface/src/ui/ChatWindow.h index afa1947268..16f8928d7e 100644 --- a/interface/src/ui/ChatWindow.h +++ b/interface/src/ui/ChatWindow.h @@ -16,7 +16,7 @@ #include #include -#include +#include namespace Ui { class ChatWindow; @@ -34,12 +34,10 @@ protected: private: QString getParticipantName(const QString& participant); + void startTimerForTimeStamps(); void addTimeStamp(); Ui::ChatWindow* ui; - QXmppClient _xmppClient; - QXmppMucManager _xmppMUCManager; - QXmppMucRoom* _chatRoom; int numMessagesAfterLastTimeStamp; QDateTime lastMessageStamp; diff --git a/interface/src/ui/FlowLayout.cpp b/interface/src/ui/FlowLayout.cpp index 5387d9499d..c24ad6ce01 100644 --- a/interface/src/ui/FlowLayout.cpp +++ b/interface/src/ui/FlowLayout.cpp @@ -40,7 +40,7 @@ #include -#include "flowlayout.h" +#include "FlowLayout.h" //! [1] FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing) : QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing) diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index 40473c924a..be18a3ba45 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -32,4 +32,4 @@ if (UNIX AND NOT APPLE) target_link_libraries(${TARGET_NAME} "${CMAKE_THREAD_LIBS_INIT}") endif (UNIX AND NOT APPLE) -target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets Qt5::Xml "${QXMPP_LIBRARY}") +target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets Qt5::Xml) diff --git a/libraries/shared/src/qtimespan.h b/libraries/shared/src/qtimespan.h index 03ed69abe3..83f9cdbec7 100644 --- a/libraries/shared/src/qtimespan.h +++ b/libraries/shared/src/qtimespan.h @@ -79,7 +79,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TimeSpanFormat) class QTimeSpanPrivate; -class Q_CORE_EXPORT QTimeSpan +class QTimeSpan { public: QTimeSpan(); @@ -247,8 +247,8 @@ public: private: #ifndef QT_NO_DATASTREAM - friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QTimeSpan &); - friend Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTimeSpan &); + friend QDataStream &operator<<(QDataStream &, const QTimeSpan &); + friend QDataStream &operator>>(QDataStream &, QTimeSpan &); #endif QSharedDataPointer d; @@ -258,40 +258,40 @@ Q_DECLARE_METATYPE(QTimeSpan); Q_DECLARE_METATYPE(Qt::TimeSpanUnit); //non-member operators -Q_CORE_EXPORT QTimeSpan operator+(const QTimeSpan &left, const QTimeSpan &right); -Q_CORE_EXPORT QTimeSpan operator-(const QTimeSpan &left, const QTimeSpan &right); -Q_CORE_EXPORT QTimeSpan operator*(const QTimeSpan &left, qreal right);//no problem -Q_CORE_EXPORT QTimeSpan operator*(const QTimeSpan &left, int right);//no problem +QTimeSpan operator+(const QTimeSpan &left, const QTimeSpan &right); +QTimeSpan operator-(const QTimeSpan &left, const QTimeSpan &right); +QTimeSpan operator*(const QTimeSpan &left, qreal right);//no problem +QTimeSpan operator*(const QTimeSpan &left, int right);//no problem inline QTimeSpan operator*(qreal left, const QTimeSpan &right) {return right * left;} // works inline QTimeSpan operator*(int left, const QTimeSpan &right) {return right * left;} // works -//Q_CORE_EXPORT QTimeSpan operator*(qreal left, const QTimeSpan &right) {return right * left;} //does not work -//Q_CORE_EXPORT QTimeSpan operator*(int left, const QTimeSpan &right) {return right * left;} //does not work -Q_CORE_EXPORT QTimeSpan operator/(const QTimeSpan &left, qreal right); -Q_CORE_EXPORT QTimeSpan operator/(const QTimeSpan &left, int right); -Q_CORE_EXPORT qreal operator/(const QTimeSpan &left, const QTimeSpan &right); -Q_CORE_EXPORT QTimeSpan operator-(const QTimeSpan &right); // Unary negation -Q_CORE_EXPORT QTimeSpan operator|(const QTimeSpan &left, const QTimeSpan &right); // Union -Q_CORE_EXPORT QTimeSpan operator&(const QTimeSpan &left, const QTimeSpan &right); // Intersection +//QTimeSpan operator*(qreal left, const QTimeSpan &right) {return right * left;} //does not work +//QTimeSpan operator*(int left, const QTimeSpan &right) {return right * left;} //does not work +QTimeSpan operator/(const QTimeSpan &left, qreal right); +QTimeSpan operator/(const QTimeSpan &left, int right); +qreal operator/(const QTimeSpan &left, const QTimeSpan &right); +QTimeSpan operator-(const QTimeSpan &right); // Unary negation +QTimeSpan operator|(const QTimeSpan &left, const QTimeSpan &right); // Union +QTimeSpan operator&(const QTimeSpan &left, const QTimeSpan &right); // Intersection // Operators that use QTimeSpan and other date/time classes -Q_CORE_EXPORT QTimeSpan operator-(const QDateTime &left, const QDateTime &right); -Q_CORE_EXPORT QTimeSpan operator-(const QDate &left, const QDate &right); -Q_CORE_EXPORT QTimeSpan operator-(const QTime &left, const QTime &right); -Q_CORE_EXPORT QDate operator+(const QDate &left, const QTimeSpan &right); -Q_CORE_EXPORT QDate operator-(const QDate &left, const QTimeSpan &right); -Q_CORE_EXPORT QTime operator+(const QTime &left, const QTimeSpan &right); -Q_CORE_EXPORT QTime operator-(const QTime &left, const QTimeSpan &right); -Q_CORE_EXPORT QDateTime operator+(const QDateTime &left, const QTimeSpan &right); -Q_CORE_EXPORT QDateTime operator-(const QDateTime &left, const QTimeSpan &right); +QTimeSpan operator-(const QDateTime &left, const QDateTime &right); +QTimeSpan operator-(const QDate &left, const QDate &right); +QTimeSpan operator-(const QTime &left, const QTime &right); +QDate operator+(const QDate &left, const QTimeSpan &right); +QDate operator-(const QDate &left, const QTimeSpan &right); +QTime operator+(const QTime &left, const QTimeSpan &right); +QTime operator-(const QTime &left, const QTimeSpan &right); +QDateTime operator+(const QDateTime &left, const QTimeSpan &right); +QDateTime operator-(const QDateTime &left, const QTimeSpan &right); #ifndef QT_NO_DATASTREAM -Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QTimeSpan &); -Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QTimeSpan &); +QDataStream &operator<<(QDataStream &, const QTimeSpan &); +QDataStream &operator>>(QDataStream &, QTimeSpan &); #endif // QT_NO_DATASTREAM #if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING) -Q_CORE_EXPORT QDebug operator<<(QDebug, const QTimeSpan &); +QDebug operator<<(QDebug, const QTimeSpan &); #endif QT_END_NAMESPACE