Merge pull request from birarda/remove-xmpp

remove xmpp chat from interface
This commit is contained in:
Clément Brisset 2015-03-03 15:27:38 -08:00
commit 6cefa0d3fb
17 changed files with 40 additions and 1051 deletions

View file

@ -14,12 +14,10 @@
* [gverb](https://github.com/highfidelity/gverb)
* [Soxr](http://sourceforge.net/projects/soxr/) ~> 0.1.1
The following external projects are optional dependencies. You can indicate to CMake that you would like to include them by passing -DGET_$NAME=1 when running a clean CMake build. For example, to get CMake to download and compile QXmpp you would pass -DGET_QXMPP=1.
The following external projects are optional dependencies. You can indicate to CMake that you would like to include them by passing -DGET_$NAME=1 when running a clean CMake build. For example, to get CMake to download and compile SDL2 you would pass -DGET_SDL2=1.
* [SDL2](https://www.libsdl.org/download-2.0.php) ~> 2.0.3
* Enables game controller support in Interface
* [QXmpp](https://github.com/qxmpp-project/qxmpp) ~> 0.7.6
* Enables text chat support in Interface
The above dependencies will be downloaded, built, linked and included automatically by CMake where we require them. The CMakeLists files that handle grabbing each of the following external dependencies can be found in the [cmake/externals folder](cmake/externals). The resulting downloads, source files and binaries will be placed in the `build-ext` directory in each of the subfolders for each external project.

View file

@ -164,7 +164,6 @@ if (WIN32)
endif ()
option(GET_SDL2 "Get SDL2 library automatically as external project" 0)
option(GET_QXMPP "GET Qxmpp library automatically as external project" 0)
if (WIN32)
add_paths_to_fixup_libs("${QT_DIR}/bin")

View file

@ -1,13 +0,0 @@
diff --git a/qxmpp-0.7.6/src/src.pro b/qxmpp-0.7.6-patch/src/src.pro
index 954738c..8404c8c 100644
--- a/qxmpp-0.7.6/src/src.pro
+++ b/qxmpp-0.7.6-patch/src/src.pro
@@ -4,7 +4,7 @@ QT -= gui
TEMPLATE = lib
-CONFIG += $$QXMPP_LIBRARY_TYPE
+CONFIG += $$QXMPP_LIBRARY_TYPE c++11
DEFINES += QXMPP_BUILD
DEFINES += $$QXMPP_INTERNAL_DEFINES
INCLUDEPATH += $$QXMPP_INCLUDEPATH $$QXMPP_INTERNAL_INCLUDES

View file

@ -1,45 +0,0 @@
#
# FindQxmpp.cmake
#
# Try to find the qxmpp library
#
# You can provide a QXMPP_ROOT_DIR which contains lib and include directories
#
# Once done this will define
#
# QXMPP_FOUND - system found qxmpp
# QXMPP_INCLUDE_DIRS - the qxmpp include directory
# QXMPP_LIBRARIES - Link this to use qxmpp
#
# Created on 3/10/2014 by Stephen Birarda
# Copyright 2014 High Fidelity, Inc.
#
# Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
#
include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
hifi_library_search_hints("qxmpp")
find_path(QXMPP_INCLUDE_DIRS qxmpp/QXmppClient.h PATH_SUFFIXES include HINTS ${QXMPP_SEARCH_DIRS})
find_library(QXMPP_LIBRARY_RELEASE NAMES qxmpp PATH_SUFFIXES lib HINTS ${QXMPP_SEARCH_DIRS})
find_library(QXMPP_LIBRARY_DEBUG NAMES qxmpp_d PATH_SUFFIXES lib HINTS ${QXMPP_SEARCH_DIRS})
if (WIN32)
find_path(QXMPP_DLL_PATH NAMES qxmpp.dll PATH_SUFFIXES lib HINTS ${QXMPP_SEARCH_DIRS})
endif ()
find_package(Qt5 COMPONENTS Xml REQUIRED)
include(SelectLibraryConfigurations)
select_library_configurations(QXMPP)
set(QXMPP_LIBRARIES "${QXMPP_LIBRARY}" Qt5::Xml)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(QXmpp DEFAULT_MSG QXMPP_INCLUDE_DIRS QXMPP_LIBRARIES QXMPP_LIBRARY)
if (QXMPP_DLL_PATH)
add_paths_to_fixup_libs(${QXMPP_DLL_PATH})
endif ()

View file

@ -1,57 +0,0 @@
//
// globalServicesExample.js
// examples
//
// Created by Thijs Wenker on 9/12/14.
// Copyright 2014 High Fidelity, Inc.
//
// Example usage of the GlobalServices object. You could use it to make your own chatbox.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
function onConnected() {
if (GlobalServices.onlineUsers.length > 0) {
sendMessageForm()
return;
}
Script.setTimeout(function() { sendMessageForm(); }, 5000);
}
function onDisconnected(reason) {
switch(reason) {
case "logout":
Window.alert("logged out!");
break;
}
}
function onOnlineUsersChanged(users) {
print(users);
}
function onIncommingMessage(user, message) {
print(user + ": " + message);
if (message === "hello") {
GlobalServices.chat("hello, @" + user + "!");
}
}
function sendMessageForm() {
var form =
[
{ label: "To:", options: ["(noone)"].concat(GlobalServices.onlineUsers) },
{ label: "Message:", value: "Enter message here" }
];
if (Window.form("Send message on public chat", form)) {
GlobalServices.chat(form[0].value == "(noone)" ? form[1].value : "@" + form[0].value + ", " + form[1].value);
}
}
GlobalServices.connected.connect(onConnected);
GlobalServices.disconnected.connect(onDisconnected);
GlobalServices.onlineUsersChanged.connect(onOnlineUsersChanged);
GlobalServices.incomingMessage.connect(onIncommingMessage);

View file

@ -1,27 +0,0 @@
//
// loadScriptFromMessage.js
// examples
//
// Created by Thijs Wenker on 9/15/14.
// Copyright 2014 High Fidelity, Inc.
//
// Filters script links out of incomming messages and prompts you to run the script.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
//Javascript link RegEX
const JS_LINK_REGEX = /https?:\/\/[^ ]+\.js/i;
function onIncomingMessage(user, message) {
var script_link = JS_LINK_REGEX.exec(message);
if (script_link == null) {
return;
}
if (Window.confirm("@" + user + " sent the following script:\n" + script_link + "\nwould you like to run it?")) {
Script.load(script_link);
}
}
GlobalServices.incomingMessage.connect(onIncomingMessage);

View file

@ -14,32 +14,28 @@
// This script generates notifications created via a number of ways, such as:
// keystroke:
//
// "q" returns number of users currently online (for debug purposes)
// CTRL/s for snapshot.
// CTRL/m for mic mute and unmute.
// System generated notifications:
// Displays users online at startup.
// If Screen is resized.
// Triggers notification if @MyUserName is mentioned in chat.
// Announces existing user logging out.
// Announces new user logging in.
// If mic is muted for any reason.
//
// To add a new System notification type:
//
// 1. Set the Event Connector at the bottom of the script.
// example:
// GlobalServices.incomingMessage.connect(onIncomingMessage);
// AudioDevice.muteToggled.connect(onMuteStateChanged);
//
// 2. Create a new function to produce a text string, do not include new line returns.
// example:
// function onIncomingMessage(user, message) {
// //do stuff here;
// var text = "This is a notification";
// var wrappedText = wordWrap(text);
// createNotification(wrappedText, NotificationType.SNAPSHOT);
// function onMuteStateChanged() {
// var muteState,
// muteString;
//
// muteState = AudioDevice.getMuted() ? "muted" : "unmuted";
// muteString = "Microphone is now " + muteState;
// createNotification(muteString, NotificationType.MUTE_TOGGLE);
// }
//
// This new function must call wordWrap(text) if the length of message is longer than 42 chars or unknown.
@ -54,11 +50,12 @@
// 2. Declare a text string.
// 3. Call createNotifications(text, NotificationType) parsing the text.
// example:
// var welcome;
// if (key.text == "q") { //queries number of users online
// var welcome = "There are " + GlobalServices.onlineUsers.length + " users online now.";
// createNotification(welcome, NotificationType.USERS_ONLINE);
// }
// if (key.text === "s") {
// if (ctrlIsPressed === true) {
// noteString = "Snapshot taken.";
// createNotification(noteString, NotificationType.SNAPSHOT);
// }
// }
Script.include("./libraries/globals.js");
Script.include("./libraries/soundArray.js");
@ -81,8 +78,6 @@ var frame = 0;
var ourWidth = Window.innerWidth;
var ourHeight = Window.innerHeight;
var text = "placeholder";
var last_users = GlobalServices.onlineUsers;
var users = [];
var ctrlIsPressed = false;
var ready = true;
var MENU_NAME = 'Tools > Notifications';
@ -93,19 +88,11 @@ var PLAY_NOTIFICATION_SOUNDS_TYPE_SETTING_PRE = "play_notification_sounds_type_"
var NotificationType = {
UNKNOWN: 0,
USER_JOINS: 1,
USER_LEAVES: 2,
MUTE_TOGGLE: 3,
CHAT_MENTION: 4,
USERS_ONLINE: 5,
SNAPSHOT: 6,
WINDOW_RESIZE: 7,
MUTE_TOGGLE: 1,
SNAPSHOT: 2,
WINDOW_RESIZE: 3,
properties: [
{ text: "User Join" },
{ text: "User Leave" },
{ text: "Mute Toggle" },
{ text: "Chat Mention" },
{ text: "Users Online" },
{ text: "Snapshot" },
{ text: "Window Resize" }
],
@ -476,15 +463,9 @@ var STARTUP_TIMEOUT = 500, // ms
startingUp = true,
startupTimer = null;
// This reports the number of users online at startup
function reportUsers() {
createNotification("Welcome! There are " + GlobalServices.onlineUsers.length + " users online now.", NotificationType.USERS_ONLINE);
}
function finishStartup() {
startingUp = false;
Script.clearTimeout(startupTimer);
reportUsers();
}
function isStartingUp() {
@ -498,42 +479,6 @@ function isStartingUp() {
return startingUp;
}
// Triggers notification if a user logs on or off
function onOnlineUsersChanged(users) {
var i;
if (!isStartingUp()) { // Skip user notifications at startup.
for (i = 0; i < users.length; i += 1) {
if (last_users.indexOf(users[i]) === -1.0) {
createNotification(users[i] + " has joined", NotificationType.USER_JOINS);
}
}
for (i = 0; i < last_users.length; i += 1) {
if (users.indexOf(last_users[i]) === -1.0) {
createNotification(last_users[i] + " has left", NotificationType.USER_LEAVES);
}
}
}
last_users = users;
}
// Triggers notification if @MyUserName is mentioned in chat and returns the message to the notification.
function onIncomingMessage(user, message) {
var myMessage,
alertMe,
thisAlert;
myMessage = message;
alertMe = "@" + GlobalServices.myUsername;
thisAlert = user + ": " + myMessage;
if (myMessage.indexOf(alertMe) > -1.0) {
CreateNotification(wordWrap(thisAlert), NotificationType.CHAT_MENTION);
}
}
// Triggers mic mute notification
function onMuteStateChanged() {
var muteState,
@ -573,20 +518,12 @@ function keyReleaseEvent(key) {
// Triggers notification on specific key driven events
function keyPressEvent(key) {
var numUsers,
welcome,
noteString;
var noteString;
if (key.key === 16777249) {
ctrlIsPressed = true;
}
if (key.text === "q") { //queries number of users online
numUsers = GlobalServices.onlineUsers.length;
welcome = "There are " + numUsers + " users online now.";
createNotification(welcome, NotificationType.USERS_ONLINE);
}
if (key.text === "s") {
if (ctrlIsPressed === true) {
noteString = "Snapshot taken.";
@ -641,8 +578,6 @@ function menuItemEvent(menuItem) {
AudioDevice.muteToggled.connect(onMuteStateChanged);
Controller.keyPressEvent.connect(keyPressEvent);
Controller.mousePressEvent.connect(mousePressEvent);
GlobalServices.onlineUsersChanged.connect(onOnlineUsersChanged);
GlobalServices.incomingMessage.connect(onIncomingMessage);
Controller.keyReleaseEvent.connect(keyReleaseEvent);
Script.update.connect(update);
Script.scriptEnding.connect(scriptEnding);

View file

@ -2,7 +2,7 @@ set(TARGET_NAME interface)
project(${TARGET_NAME})
# set a default root dir for each of our optional externals if it was not passed
set(OPTIONAL_EXTERNALS "Faceshift" "LibOVR" "Sixense" "LeapMotion" "RtMidi" "Qxmpp" "SDL2" "RSSDK")
set(OPTIONAL_EXTERNALS "Faceshift" "LibOVR" "Sixense" "LeapMotion" "RtMidi" "SDL2" "RSSDK")
foreach(EXTERNAL ${OPTIONAL_EXTERNALS})
string(TOUPPER ${EXTERNAL} ${EXTERNAL}_UPPERCASE)
if (NOT ${${EXTERNAL}_UPPERCASE}_ROOT_DIR)
@ -119,7 +119,7 @@ link_hifi_libraries(shared octree environment gpu model fbx metavoxels networkin
audio audio-client animation script-engine physics
render-utils entities-renderer)
add_dependency_external_projects(sdl2 qxmpp)
add_dependency_external_projects(sdl2)
# perform standard include and linking for found externals
foreach(EXTERNAL ${OPTIONAL_EXTERNALS})
@ -175,16 +175,6 @@ if (RTMIDI_FOUND AND NOT DISABLE_RTMIDI AND APPLE)
target_link_libraries(${TARGET_NAME} ${CoreMIDI})
endif ()
if (QXMPP_FOUND AND NOT DISABLE_QXMPP AND WIN32)
if (NOT QXMPP_DLL_PATH)
# if we have no QXmpp DLL path, assume we're linking a static QXmpp on windows
add_definitions(-DQXMPP_STATIC)
else ()
# otherwise assume we are linking a dynamic QXmpp
add_definitions(-DQXMPP_SHARED)
endif ()
endif ()
# include headers for interface and InterfaceConfig.
include_directories("${PROJECT_SOURCE_DIR}/src" "${PROJECT_BINARY_DIR}/includes")

View file

@ -20,7 +20,6 @@
#include <PathUtils.h>
#include <SettingHandle.h>
#include <UserActivityLogger.h>
#include <XmppClient.h>
#include "Application.h"
#include "AccountManager.h"
@ -162,12 +161,9 @@ Menu::Menu() {
SLOT(setEnabled(bool)));
connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool)));
#endif
#ifdef HAVE_QXMPP
addActionToQMenuAndActionHash(toolsMenu, MenuOption::Chat, Qt::Key_Backslash,
dialogsManager.data(), SLOT(showChat()));
dialogsManager->setupChat();
#endif
dialogsManager.data(), SLOT(showIRCLink()));
addActionToQMenuAndActionHash(toolsMenu,
MenuOption::ToolWindow,

View file

@ -1,85 +0,0 @@
//
// XmppClient.cpp
// interface/src
//
// Created by Dimitar Dobrev on 10/3/14.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <AccountManager.h>
#include "XmppClient.h"
const QString DEFAULT_XMPP_SERVER = "chat.highfidelity.io";
const QString DEFAULT_CHAT_ROOM = "public@public-chat.highfidelity.io";
#ifdef HAVE_QXMPP
XmppClient::XmppClient() :
_xmppClient(),
_xmppMUCManager()
{
AccountManager& accountManager = AccountManager::getInstance();
connect(&accountManager, SIGNAL(profileChanged()), this, SLOT(connectToServer()));
connect(&accountManager, SIGNAL(logoutComplete()), this, SLOT(disconnectFromServer()));
}
#else
XmppClient::XmppClient() {
}
#endif
XmppClient& XmppClient::getInstance() {
static XmppClient sharedInstance;
return sharedInstance;
}
void XmppClient::xmppConnected() {
#ifdef HAVE_QXMPP
_publicChatRoom = _xmppMUCManager.addRoom(DEFAULT_CHAT_ROOM);
_publicChatRoom->setNickName(AccountManager::getInstance().getAccountInfo().getUsername());
_publicChatRoom->join();
emit joinedPublicChatRoom();
#endif
}
#ifdef HAVE_QXMPP
void XmppClient::xmppError(QXmppClient::Error error) {
qDebug() << "Error connnecting to XMPP for user "
<< AccountManager::getInstance().getAccountInfo().getUsername() << ": " << error;
}
#endif
void XmppClient::connectToServer() {
#ifdef HAVE_QXMPP
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.getAccountInfo().getUsername();
const QString& password = accountManager.getAccountInfo().getXMPPPassword();
_xmppClient.connectToServer(user + "@" + DEFAULT_XMPP_SERVER, password);
#endif
}
void XmppClient::disconnectFromServer() {
#ifdef HAVE_QXMPP
if (_xmppClient.isConnected()) {
_xmppClient.disconnectFromServer();
}
#endif
}
XmppClient::XmppClient(const XmppClient& other) {
Q_UNUSED(other);
}
void XmppClient::operator =(XmppClient const& other) {
Q_UNUSED(other);
}

View file

@ -1,57 +0,0 @@
//
// XmppClient.h
// interface/src
//
// Created by Dimitar Dobrev on 10/3/14.
// Copyright 2013 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_XmppClient_h
#define hifi_XmppClient_h
#include <QObject>
#ifdef HAVE_QXMPP
#include <qxmpp/QXmppClient.h>
#include <qxmpp/QXmppMucManager.h>
#endif
/// Generalized threaded processor for handling received inbound packets.
class XmppClient : public QObject {
Q_OBJECT
public:
static XmppClient& getInstance();
#ifdef HAVE_QXMPP
QXmppClient& getXMPPClient() { return _xmppClient; }
const QXmppMucRoom* getPublicChatRoom() const { return _publicChatRoom; }
#endif
signals:
void joinedPublicChatRoom();
private slots:
void xmppConnected();
#ifdef HAVE_QXMPP
void xmppError(QXmppClient::Error error);
#endif
void connectToServer();
void disconnectFromServer();
private:
XmppClient();
XmppClient(XmppClient const& other); // not implemented
void operator=(XmppClient const& other); // not implemented
#ifdef HAVE_QXMPP
QXmppClient _xmppClient;
QXmppMucManager _xmppMUCManager;
QXmppMucRoom* _publicChatRoom;
#endif
};
#endif // hifi_XmppClient_h

View file

@ -12,7 +12,6 @@
#include "AccountManager.h"
#include "Application.h"
#include "ResourceCache.h"
#include "XmppClient.h"
#include "GlobalServicesScriptingInterface.h"
@ -20,13 +19,6 @@ GlobalServicesScriptingInterface::GlobalServicesScriptingInterface() {
AccountManager& accountManager = AccountManager::getInstance();
connect(&accountManager, &AccountManager::usernameChanged, this, &GlobalServicesScriptingInterface::myUsernameChanged);
connect(&accountManager, &AccountManager::logoutComplete, this, &GlobalServicesScriptingInterface::loggedOut);
#ifdef HAVE_QXMPP
const XmppClient& xmppClient = XmppClient::getInstance();
connect(&xmppClient, &XmppClient::joinedPublicChatRoom, this, &GlobalServicesScriptingInterface::connected);
connect(&xmppClient, &XmppClient::joinedPublicChatRoom, this, &GlobalServicesScriptingInterface::onConnected);
const QXmppClient& qxmppClient = XmppClient::getInstance().getXMPPClient();
connect(&qxmppClient, &QXmppClient::messageReceived, this, &GlobalServicesScriptingInterface::messageReceived);
#endif // HAVE_QXMPP
_downloading = false;
connect(Application::getInstance(), &Application::renderingInWorldInterface,
@ -37,30 +29,6 @@ GlobalServicesScriptingInterface::~GlobalServicesScriptingInterface() {
AccountManager& accountManager = AccountManager::getInstance();
disconnect(&accountManager, &AccountManager::usernameChanged, this, &GlobalServicesScriptingInterface::myUsernameChanged);
disconnect(&accountManager, &AccountManager::logoutComplete, this, &GlobalServicesScriptingInterface::loggedOut);
#ifdef HAVE_QXMPP
const XmppClient& xmppClient = XmppClient::getInstance();
disconnect(&xmppClient, &XmppClient::joinedPublicChatRoom, this, &GlobalServicesScriptingInterface::connected);
disconnect(&xmppClient, &XmppClient::joinedPublicChatRoom, this, &GlobalServicesScriptingInterface::onConnected);
const QXmppClient& qxmppClient = XmppClient::getInstance().getXMPPClient();
disconnect(&qxmppClient, &QXmppClient::messageReceived, this, &GlobalServicesScriptingInterface::messageReceived);
const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom();
disconnect(publicChatRoom, &QXmppMucRoom::participantsChanged,
this, &GlobalServicesScriptingInterface::participantsChanged);
#endif // HAVE_QXMPP
}
void GlobalServicesScriptingInterface::onConnected() {
#ifdef HAVE_QXMPP
const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom();
connect(publicChatRoom, &QXmppMucRoom::participantsChanged,
this, &GlobalServicesScriptingInterface::participantsChanged, Qt::UniqueConnection);
#endif // HAVE_QXMPP
}
void GlobalServicesScriptingInterface::participantsChanged() {
#ifdef HAVE_QXMPP
emit GlobalServicesScriptingInterface::onlineUsersChanged(this->getOnlineUsers());
#endif // HAVE_QXMPP
}
GlobalServicesScriptingInterface* GlobalServicesScriptingInterface::getInstance() {
@ -68,62 +36,14 @@ GlobalServicesScriptingInterface* GlobalServicesScriptingInterface::getInstance(
return &sharedInstance;
}
bool GlobalServicesScriptingInterface::isConnected() {
#ifdef HAVE_QXMPP
return XmppClient::getInstance().getXMPPClient().isConnected();
#else
return false;
#endif // HAVE_QXMPP
}
QScriptValue GlobalServicesScriptingInterface::chat(const QString& message) {
#ifdef HAVE_QXMPP
if (XmppClient::getInstance().getXMPPClient().isConnected()) {
const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom();
QXmppMessage messageObject;
messageObject.setTo(publicChatRoom->jid());
messageObject.setType(QXmppMessage::GroupChat);
messageObject.setBody(message);
return XmppClient::getInstance().getXMPPClient().sendPacket(messageObject);
}
#endif // HAVE_QXMPP
return false;
}
QString GlobalServicesScriptingInterface::getMyUsername() {
return AccountManager::getInstance().getAccountInfo().getUsername();
}
QStringList GlobalServicesScriptingInterface::getOnlineUsers() {
#ifdef HAVE_QXMPP
if (XmppClient::getInstance().getXMPPClient().isConnected()) {
QStringList usernames;
const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom();
foreach(const QString& participant, XmppClient::getInstance().getPublicChatRoom()->participants()) {
usernames.append(participant.right(participant.count() - 1 - publicChatRoom->jid().count()));
}
return usernames;
}
#endif // HAVE_QXMPP
return QStringList();
}
void GlobalServicesScriptingInterface::loggedOut() {
emit GlobalServicesScriptingInterface::disconnected(QString("logout"));
}
#ifdef HAVE_QXMPP
void GlobalServicesScriptingInterface::messageReceived(const QXmppMessage& message) {
if (message.type() != QXmppMessage::GroupChat) {
return;
}
const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom();
QString username = message.from().right(message.from().count() - 1 - publicChatRoom->jid().count());
emit GlobalServicesScriptingInterface::incomingMessage(username, message.body());
}
#endif // HAVE_QXMPP
DownloadInfoResult::DownloadInfoResult() :
downloading(QList<float>()),
pending(0.0f)

View file

@ -19,13 +19,6 @@
#include <QString>
#include <QStringList>
#ifdef HAVE_QXMPP
#include <qxmpp/QXmppClient.h>
#include <qxmpp/QXmppMessage.h>
#endif // HAVE_QXMPP
class DownloadInfoResult {
public:
DownloadInfoResult();
@ -41,30 +34,20 @@ void DownloadInfoResultFromScriptValue(const QScriptValue& object, DownloadInfoR
class GlobalServicesScriptingInterface : public QObject {
Q_OBJECT
Q_PROPERTY(bool isConnected READ isConnected)
Q_PROPERTY(QString myUsername READ getMyUsername)
Q_PROPERTY(QStringList onlineUsers READ getOnlineUsers)
GlobalServicesScriptingInterface();
~GlobalServicesScriptingInterface();
public:
static GlobalServicesScriptingInterface* getInstance();
bool isConnected();
QString getMyUsername();
QStringList getOnlineUsers();
public slots:
QScriptValue chat(const QString& message);
DownloadInfoResult getDownloadInfo();
void updateDownloadInfo();
private slots:
void loggedOut();
void onConnected();
void participantsChanged();
#ifdef HAVE_QXMPP
void messageReceived(const QXmppMessage& message);
#endif // HAVE_QXMPP
void checkDownloadInfo();
signals:

View file

@ -1,420 +0,0 @@
//
// ChatWindow.cpp
// interface/src/ui
//
// Created by Dimitar Dobrev on 3/6/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QGridLayout>
#include <QFrame>
#include <QLayoutItem>
#include <QPalette>
#include <QScrollBar>
#include <QSizePolicy>
#include <QTimer>
#include "qtimespan.h"
#include <AddressManager.h>
#include <AccountManager.h>
#include <PathUtils.h>
#include "Application.h"
#include "ChatMessageArea.h"
#include "FlowLayout.h"
#include "MainWindow.h"
#include "UIUtil.h"
#include "XmppClient.h"
#include "ui_chatWindow.h"
#include "ChatWindow.h"
const int NUM_MESSAGES_TO_TIME_STAMP = 20;
const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?)|(?:hifi))://\\S+)");
const QRegularExpression regexHifiLinks("([#@]\\S+)");
const QString mentionSoundsPath("/mention-sounds/");
const QString mentionRegex("@(\\b%1\\b)");
ChatWindow::ChatWindow(QWidget* parent) :
QWidget(parent, Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint |
Qt::WindowCloseButtonHint),
_ui(new Ui::ChatWindow),
_numMessagesAfterLastTimeStamp(0),
_mousePressed(false),
_mouseStartPosition(),
_trayIcon(parent),
_effectPlayer(),
_usernameMentionTimestamp("MentionTimestamp", QDateTime())
{
setAttribute(Qt::WA_DeleteOnClose, false);
_ui->setupUi(this);
FlowLayout* flowLayout = new FlowLayout(0, 4, 4);
_ui->usersWidget->setLayout(flowLayout);
_ui->messagePlainTextEdit->installEventFilter(this);
_ui->messagePlainTextEdit->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
QTextCursor cursor(_ui->messagePlainTextEdit->textCursor());
cursor.movePosition(QTextCursor::Start);
QTextBlockFormat format = cursor.blockFormat();
format.setLineHeight(130, QTextBlockFormat::ProportionalHeight);
cursor.setBlockFormat(format);
_ui->messagePlainTextEdit->setTextCursor(cursor);
if (!AccountManager::getInstance().isLoggedIn()) {
_ui->connectingToXMPPLabel->setText(tr("You must be logged in to chat with others."));
}
#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->usersArea->hide();
_ui->messagesScrollArea->hide();
_ui->messagePlainTextEdit->hide();
connect(&XmppClient::getInstance(), SIGNAL(joinedPublicChatRoom()), this, SLOT(connected()));
}
connect(&xmppClient, SIGNAL(messageReceived(QXmppMessage)), this, SLOT(messageReceived(QXmppMessage)));
connect(&_trayIcon, SIGNAL(messageClicked()), this, SLOT(notificationClicked()));
#endif // HAVE_QXMPP
QDir mentionSoundsDir(PathUtils::resourcesPath() + mentionSoundsPath);
_mentionSounds = mentionSoundsDir.entryList(QDir::Files);
_trayIcon.setIcon(QIcon( PathUtils::resourcesPath() + "/images/hifi-logo.svg"));
}
ChatWindow::~ChatWindow() {
#ifdef HAVE_QXMPP
const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient();
disconnect(&xmppClient, SIGNAL(joinedPublicChatRoom()), 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 // HAVE_QXMPP
delete _ui;
}
void ChatWindow::keyPressEvent(QKeyEvent* event) {
if (event->key() == Qt::Key_Escape) {
Application::getInstance()->getWindow()->activateWindow();
hide();
} else {
QWidget::keyPressEvent(event);
}
}
void ChatWindow::showEvent(QShowEvent* event) {
QWidget::showEvent(event);
if (!event->spontaneous()) {
_ui->messagePlainTextEdit->setFocus();
}
QRect parentGeometry = Application::getInstance()->getDesirableApplicationGeometry();
int titleBarHeight = UIUtil::getWindowTitleBarHeight(this);
int menuBarHeight = Menu::getInstance()->geometry().height();
int topMargin = titleBarHeight + menuBarHeight;
setGeometry(parentGeometry.topRight().x() - size().width() + 1, parentGeometry.topRight().y() + topMargin,
size().width(), parentWidget()->height() - topMargin);
Application::processEvents();
scrollToBottom();
#ifdef HAVE_QXMPP
const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient();
if (xmppClient.isConnected()) {
participantsChanged();
}
#endif // HAVE_QXMPP
}
bool ChatWindow::eventFilter(QObject* sender, QEvent* event) {
if (sender == _ui->messagePlainTextEdit) {
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 // HAVE_QXMPP
QTextCursor cursor = _ui->messagePlainTextEdit->textCursor();
cursor.select(QTextCursor::Document);
cursor.removeSelectedText();
}
return true;
}
} else if (event->type() == QEvent::MouseButtonRelease) {
QVariant userVar = sender->property("user");
if (userVar.isValid()) {
DependencyManager::get<AddressManager>()->goToUser(userVar.toString());
return true;
}
}
return QWidget::eventFilter(sender, event);
}
void ChatWindow::addTimeStamp() {
QTimeSpan timePassed = QDateTime::currentDateTime() - _lastMessageStamp;
int times[] = { timePassed.daysPart(), timePassed.hoursPart(), timePassed.minutesPart() };
QString strings[] = { tr("%n day(s)", 0, times[0]), tr("%n hour(s)", 0, times[1]), tr("%n minute(s)", 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: #333333;"
"background-color: white;"
"font-size: 14px;"
"padding: 4px;");
timeLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
timeLabel->setAlignment(Qt::AlignLeft);
bool atBottom = isNearBottom();
_ui->messagesVBoxLayout->addWidget(timeLabel);
_ui->messagesVBoxLayout->parentWidget()->updateGeometry();
Application::processEvents();
_numMessagesAfterLastTimeStamp = 0;
if (atBottom) {
scrollToBottom();
}
}
}
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->usersArea->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 // HAVE_QXMPP
startTimerForTimeStamps();
}
void ChatWindow::timeout() {
if (_numMessagesAfterLastTimeStamp >= NUM_MESSAGES_TO_TIME_STAMP) {
addTimeStamp();
}
}
#ifdef HAVE_QXMPP
void ChatWindow::notificationClicked() {
if (parentWidget()->isMinimized()) {
parentWidget()->showNormal();
}
if (isHidden()) {
show();
}
// find last mention
int messageCount = _ui->messagesVBoxLayout->count();
for (unsigned int i = messageCount; i > 0; i--) {
ChatMessageArea* area = (ChatMessageArea*)_ui->messagesVBoxLayout->itemAt(i - 1)->widget();
QRegularExpression usernameMention(mentionRegex.arg(AccountManager::getInstance().getAccountInfo().getUsername()));
if (area->toPlainText().contains(usernameMention)) {
int top = area->geometry().top();
int height = area->geometry().height();
QScrollBar* verticalScrollBar = _ui->messagesScrollArea->verticalScrollBar();
verticalScrollBar->setSliderPosition(top - verticalScrollBar->size().height() + height);
return;
}
}
Application::processEvents();
scrollToBottom();
}
QString ChatWindow::getParticipantName(const QString& participant) {
const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom();
return participant.right(participant.count() - 1 - publicChatRoom->jid().count());
}
void ChatWindow::error(QXmppClient::Error error) {
_ui->connectingToXMPPLabel->setText(QString::number(error));
}
void ChatWindow::participantsChanged() {
bool atBottom = isNearBottom();
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) {
QString participantName = getParticipantName(participant);
QLabel* userLabel = new QLabel();
userLabel->setText(participantName);
userLabel->setStyleSheet("background-color: palette(light);"
"border-radius: 5px;"
"color: #267077;"
"padding-top: 3px;"
"padding-right: 2px;"
"padding-bottom: 2px;"
"padding-left: 2px;"
"border: 1px solid palette(shadow);"
"font-size: 14px;"
"font-weight: bold");
userLabel->setProperty("user", participantName);
userLabel->setCursor(Qt::PointingHandCursor);
userLabel->installEventFilter(this);
_ui->usersWidget->layout()->addWidget(userLabel);
}
Application::processEvents();
if (atBottom) {
scrollToBottom();
}
}
void ChatWindow::messageReceived(const QXmppMessage& message) {
if (message.type() != QXmppMessage::GroupChat) {
return;
}
// Update background if this is a message from the current user
bool fromSelf = getParticipantName(message.from()) == AccountManager::getInstance().getAccountInfo().getUsername();
// Create message area
ChatMessageArea* messageArea = new ChatMessageArea(true);
messageArea->setWordWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
messageArea->setTextInteractionFlags(Qt::TextBrowserInteraction);
messageArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
messageArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
messageArea->setReadOnly(true);
messageArea->setStyleSheet("QTextBrowser{ padding-bottom: 2px;"
"padding-left: 2px;"
"padding-top: 2px;"
"padding-right: 20px;"
"margin: 0px;"
"color: #333333;"
"font-size: 14px;"
"background-color: rgba(0, 0, 0, 0%);"
"border: 0; }"
"QMenu{ border: 2px outset gray; }");
QString userLabel = getParticipantName(message.from());
if (fromSelf) {
userLabel = "<b style=\"color: #4a6f91\">" + userLabel + ": </b>";
messageArea->setStyleSheet(messageArea->styleSheet() + "background-color: #e1e8ea");
} else {
userLabel = "<b>" + userLabel + ": </b>";
}
messageArea->document()->setDefaultStyleSheet("a { text-decoration: none; font-weight: bold; color: #267077;}");
QString messageText = message.body().toHtmlEscaped();
messageText = messageText.replace(regexLinks, "<a href=\"\\1\">\\1</a>");
messageText = messageText.replace(regexHifiLinks, "<a href=\"hifi://\\1\">\\1</a>");
messageArea->setHtml(userLabel + messageText);
bool atBottom = isNearBottom();
_ui->messagesVBoxLayout->addWidget(messageArea);
_ui->messagesVBoxLayout->parentWidget()->updateGeometry();
Application::processEvents();
if (atBottom || fromSelf) {
scrollToBottom();
}
++_numMessagesAfterLastTimeStamp;
if (message.stamp().isValid()) {
_lastMessageStamp = message.stamp().toLocalTime();
} else {
_lastMessageStamp = QDateTime::currentDateTime();
}
QRegularExpression usernameMention(mentionRegex.arg(AccountManager::getInstance().getAccountInfo().getUsername()));
if (message.body().contains(usernameMention)) {
// Don't show messages already seen in icon tray at start-up.
bool showMessage = _usernameMentionTimestamp.get() < _lastMessageStamp;
if (showMessage) {
_usernameMentionTimestamp.set(_lastMessageStamp);
}
if (isHidden() && showMessage) {
if (_effectPlayer.state() != QMediaPlayer::PlayingState) {
// get random sound
QFileInfo inf = QFileInfo(PathUtils::resourcesPath() +
mentionSoundsPath +
_mentionSounds.at(rand() % _mentionSounds.size()));
_effectPlayer.setMedia(QUrl::fromLocalFile(inf.absoluteFilePath()));
_effectPlayer.play();
}
_trayIcon.show();
_trayIcon.showMessage(windowTitle(), message.body());
}
}
}
#endif // HAVE_QXMPP
bool ChatWindow::isNearBottom() {
QScrollBar* verticalScrollBar = _ui->messagesScrollArea->verticalScrollBar();
return verticalScrollBar->value() >= verticalScrollBar->maximum() - Ui::AUTO_SCROLL_THRESHOLD;
}
// Scroll chat message area to bottom.
void ChatWindow::scrollToBottom() {
QScrollBar* verticalScrollBar = _ui->messagesScrollArea->verticalScrollBar();
verticalScrollBar->setValue(verticalScrollBar->maximum());
}
bool ChatWindow::event(QEvent* event) {
if (event->type() == QEvent::WindowActivate) {
_ui->messagePlainTextEdit->setFocus();
}
return QWidget::event(event);
}

View file

@ -1,88 +0,0 @@
//
// ChatWindow.h
// interface/src/ui
//
// Created by Dimitar Dobrev on 3/6/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_ChatWindow_h
#define hifi_ChatWindow_h
#include <QDateTime>
#include <QDockWidget>
#include <QMediaPlayer>
#include <QSystemTrayIcon>
#include <QTimer>
#include <Application.h>
#include <SettingHandle.h>
#include "FramelessDialog.h"
#ifdef HAVE_QXMPP
#include <qxmpp/QXmppClient.h>
#include <qxmpp/QXmppMessage.h>
#endif
namespace Ui {
// Maximum amount the chat can be scrolled up in order to auto scroll.
const int AUTO_SCROLL_THRESHOLD = 20;
class ChatWindow;
}
class ChatWindow : public QWidget {
Q_OBJECT
public:
ChatWindow(QWidget* parent);
~ChatWindow();
protected:
bool eventFilter(QObject* sender, QEvent* event);
virtual void keyPressEvent(QKeyEvent *event);
virtual void showEvent(QShowEvent* event);
virtual bool event(QEvent* event);
private:
#ifdef HAVE_QXMPP
QString getParticipantName(const QString& participant);
#endif
void startTimerForTimeStamps();
void addTimeStamp();
bool isNearBottom();
void scrollToBottom();
Ui::ChatWindow* _ui;
int _numMessagesAfterLastTimeStamp;
QDateTime _lastMessageStamp;
bool _mousePressed;
QPoint _mouseStartPosition;
QSystemTrayIcon _trayIcon;
QStringList _mentionSounds;
QMediaPlayer _effectPlayer;
Setting::Handle<QDateTime> _usernameMentionTimestamp;
private slots:
void connected();
void timeout();
#ifdef HAVE_QXMPP
void error(QXmppClient::Error error);
void participantsChanged();
void messageReceived(const QXmppMessage& message);
void notificationClicked();
#endif
};
#endif // hifi_ChatWindow_h

View file

@ -9,17 +9,17 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QMessageBox>
#include <AccountManager.h>
#include <MainWindow.h>
#include <PathUtils.h>
#include <XmppClient.h>
#include "AddressBarDialog.h"
#include "AnimationsDialog.h"
#include "AttachmentsDialog.h"
#include "BandwidthDialog.h"
#include "CachesSizeDialog.h"
#include "ChatWindow.h"
#include "HMDToolsDialog.h"
#include "LodToolsDialog.h"
#include "LoginDialog.h"
@ -163,53 +163,16 @@ void DialogsManager::showScriptEditor() {
_scriptEditor->raise();
}
void DialogsManager::setupChat() {
#ifdef HAVE_QXMPP
const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient();
connect(&xmppClient, &QXmppClient::connected, this, &DialogsManager::toggleChat);
connect(&xmppClient, &QXmppClient::disconnected, this, &DialogsManager::toggleChat);
QDir::setCurrent(PathUtils::resourcesPath());
// init chat window to listen chat
maybeCreateDialog(_chatWindow);
#endif
}
void DialogsManager::showChat() {
if (AccountManager::getInstance().isLoggedIn()) {
maybeCreateDialog(_chatWindow);
if (_chatWindow->isHidden()) {
_chatWindow->show();
}
_chatWindow->raise();
_chatWindow->activateWindow();
_chatWindow->setFocus();
} else {
qApp->getTrayIcon()->showMessage("Interface",
"You need to login to be able to chat with others on this domain.");
void DialogsManager::showIRCLink() {
if (!_ircInfoBox) {
_ircInfoBox = new QMessageBox(QMessageBox::NoIcon,
"High Fidelity IRC",
"High Fidelity has an IRC channel on irc.freenode.net at #highfidelity.<br/><br/>Web chat is available at <a href='http://webchat.freenode.net/?channels=highfidelity&uio=d4'>http://webchat.freenode.net/?channels=highfidelity&uio=d4</a>",
QMessageBox::Ok);
_ircInfoBox->setTextFormat(Qt::RichText);
_ircInfoBox->setAttribute(Qt::WA_DeleteOnClose);
_ircInfoBox->show();
}
}
void DialogsManager::toggleChat() {
#ifdef HAVE_QXMPP
QAction* chatAction = Menu::getInstance()->getActionForOption(MenuOption::Login);
Q_CHECK_PTR(chatAction);
chatAction->setEnabled(XmppClient::getInstance().getXMPPClient().isConnected());
if (!chatAction->isEnabled() && _chatWindow && AccountManager::getInstance().isLoggedIn()) {
if (_chatWindow->isHidden()) {
_chatWindow->show();
_chatWindow->raise();
_chatWindow->activateWindow();
_chatWindow->setFocus();
} else {
_chatWindow->hide();
}
}
#endif
_ircInfoBox->raise();
}

View file

@ -25,7 +25,6 @@ class AddressBarDialog;
class AnimationsDialog;
class AttachmentsDialog;
class CachesSizeDialog;
class ChatWindow;
class BandwidthDialog;
class LodToolsDialog;
class LoginDialog;
@ -34,6 +33,7 @@ class MetavoxelNetworkSimulator;
class OctreeStatsDialog;
class PreferencesDialog;
class ScriptEditorWindow;
class QMessageBox;
class DialogsManager : public QObject, public Dependency {
Q_OBJECT
@ -45,8 +45,6 @@ public:
QPointer<LodToolsDialog> getLodToolsDialog() const { return _lodToolsDialog; }
QPointer<OctreeStatsDialog> getOctreeStatsDialog() const { return _octreeStatsDialog; }
void setupChat();
public slots:
void toggleAddressBar();
void toggleLoginDialog();
@ -62,12 +60,11 @@ public slots:
void showMetavoxelEditor();
void showMetavoxelNetworkSimulator();
void showScriptEditor();
void showChat();
void showIRCLink();
private slots:
void toggleToolWindow();
void hmdToolsClosed();
void toggleChat();
private:
DialogsManager() {}
@ -91,7 +88,7 @@ private:
QPointer<AttachmentsDialog> _attachmentsDialog;
QPointer<BandwidthDialog> _bandwidthDialog;
QPointer<CachesSizeDialog> _cachesSizeDialog;
QPointer<ChatWindow> _chatWindow;
QPointer<QMessageBox> _ircInfoBox;
QPointer<HMDToolsDialog> _hmdToolsDialog;
QPointer<LodToolsDialog> _lodToolsDialog;
QPointer<LoginDialog> _loginDialog;