mirror of
https://github.com/overte-org/overte.git
synced 2025-04-22 06:44:17 +02:00
Merge pull request #4370 from birarda/remove-xmpp
remove xmpp chat from interface
This commit is contained in:
commit
6cefa0d3fb
17 changed files with 40 additions and 1051 deletions
4
BUILD.md
4
BUILD.md
|
@ -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.
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
13
cmake/externals/qxmpp/qxmpp.patch
vendored
13
cmake/externals/qxmpp/qxmpp.patch
vendored
|
@ -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
|
|
@ -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 ()
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue