From b35134e325aceb22adc6ec0836dc9e29057f38d2 Mon Sep 17 00:00:00 2001 From: Mohammed Nafees Date: Sat, 17 May 2014 20:38:43 +0530 Subject: [PATCH 1/3] Fix the chat widget's visibility when not logged in --- interface/src/Menu.cpp | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index bff08d5221..c79d4618e5 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -34,6 +34,7 @@ #include #include "Application.h" +#include "AccountManager.h" #include "Menu.h" #include "scripting/MenuScriptingInterface.h" #include "Util.h" @@ -193,10 +194,10 @@ Menu::Menu() : QAction::PreferencesRole); addActionToQMenuAndActionHash(editMenu, MenuOption::Attachments, 0, this, SLOT(editAttachments())); - + addDisabledActionAndSeparator(editMenu, "Physics"); QObject* avatar = appInstance->getAvatar(); - addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::ObeyEnvironmentalGravity, Qt::SHIFT | Qt::Key_G, false, + addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::ObeyEnvironmentalGravity, Qt::SHIFT | Qt::Key_G, false, avatar, SLOT(updateMotionBehaviorsFromMenu())); @@ -1013,24 +1014,24 @@ void Menu::multipleDestinationsDecision(const QJsonObject& userData, const QJson void Menu::muteEnvironment() { int headerSize = numBytesForPacketHeaderGivenPacketType(PacketTypeMuteEnvironment); int packetSize = headerSize + sizeof(glm::vec3) + sizeof(float); - + glm::vec3 position = Application::getInstance()->getAvatar()->getPosition(); - + char* packet = (char*)malloc(packetSize); populatePacketHeader(packet, PacketTypeMuteEnvironment); memcpy(packet + headerSize, &position, sizeof(glm::vec3)); memcpy(packet + headerSize + sizeof(glm::vec3), &MUTE_RADIUS, sizeof(float)); - + QByteArray mutePacket(packet, packetSize); - + // grab our audio mixer from the NodeList, if it exists SharedNodePointer audioMixer = NodeList::getInstance()->soloNodeOfType(NodeType::AudioMixer); - + if (audioMixer) { // send off this mute packet NodeList::getInstance()->writeDatagram(mutePacket, audioMixer); } - + free(packet); } @@ -1188,19 +1189,22 @@ void Menu::showScriptEditor() { } void Menu::showChat() { - QMainWindow* mainWindow = Application::getInstance()->getWindow(); - if (!_chatWindow) { - _chatWindow = new ChatWindow(mainWindow); - } - if (_chatWindow->isHidden()) { - _chatWindow->show(); + if (AccountManager::getInstance().isLoggedIn()) { + QMainWindow* mainWindow = Application::getInstance()->getWindow(); + if (!_chatWindow) { + _chatWindow = new ChatWindow(mainWindow); + } + + if (_chatWindow->isHidden()) { + _chatWindow->show(); + } } } void Menu::toggleChat() { #ifdef HAVE_QXMPP _chatAction->setEnabled(XmppClient::getInstance().getXMPPClient().isConnected()); - if (!_chatAction->isEnabled() && _chatWindow) { + if (!_chatAction->isEnabled() && _chatWindow && AccountManager::getInstance().isLoggedIn()) { if (_chatWindow->isHidden()) { _chatWindow->show(); } else { From ad49b5c2e15846ab4d5178e1cff88e81c8783beb Mon Sep 17 00:00:00 2001 From: Mohammed Nafees Date: Thu, 22 May 2014 16:53:07 +0530 Subject: [PATCH 2/3] Show OS notification when user is not logged in --- interface/src/Application.cpp | 109 +++++++++++++++++----------------- interface/src/Application.h | 6 +- interface/src/Menu.cpp | 3 + 3 files changed, 64 insertions(+), 54 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 17443b3cb0..79015185c6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -172,11 +172,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _previousScriptLocation(), _nodeBoundsDisplay(this), _runningScriptsWidget(new RunningScriptsWidget(_window)), - _runningScriptsWidgetWasVisible(false) + _runningScriptsWidgetWasVisible(false), + _trayIcon(new QSystemTrayIcon(_window)) { // init GnuTLS for DTLS with domain-servers DTLSClientSession::globalInit(); - + // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); @@ -238,10 +239,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(&nodeList->getDomainHandler(), SIGNAL(hostnameChanged(const QString&)), SLOT(domainChanged(const QString&))); connect(&nodeList->getDomainHandler(), SIGNAL(connectedToDomain(const QString&)), SLOT(connectedToDomain(const QString&))); - + // update our location every 5 seconds in the data-server, assuming that we are authenticated with one const float DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS = 5.0f * 1000.0f; - + QTimer* locationUpdateTimer = new QTimer(this); connect(locationUpdateTimer, &QTimer::timeout, this, &Application::updateLocationInServer); locationUpdateTimer->start(DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS); @@ -337,7 +338,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // when -url in command line, teleport to location urlGoTo(argc, constArgv); - + // For now we're going to set the PPS for outbound packets to be super high, this is // probably not the right long term solution. But for now, we're going to do this to // allow you to move a particle around in your hand @@ -364,27 +365,29 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // clear the scripts, and set out script to our default scripts clearScriptsBeforeRunning(); loadScript("http://public.highfidelity.io/scripts/defaultScripts.js"); - + QMutexLocker locker(&_settingsMutex); _settings->setValue("firstRun",QVariant(false)); } else { // do this as late as possible so that all required subsystems are inialized loadScripts(); - + QMutexLocker locker(&_settingsMutex); _previousScriptLocation = _settings->value("LastScriptLocation", QVariant("")).toString(); } - + connect(_window, &MainWindow::windowGeometryChanged, _runningScriptsWidget, &RunningScriptsWidget::setBoundary); - - //When -url in command line, teleport to location - urlGoTo(argc, constArgv); - + + //When -url in command line, teleport to location + urlGoTo(argc, constArgv); + // call the OAuthWebviewHandler static getter so that its instance lives in our thread OAuthWebViewHandler::getInstance(); // make sure the High Fidelity root CA is in our list of trusted certs OAuthWebViewHandler::addHighFidelityRootCAToSSLConfig(); + + _trayIcon->show(); } Application::~Application() { @@ -393,11 +396,11 @@ Application::~Application() { // make sure we don't call the idle timer any more delete idleTimer; - + _sharedVoxelSystem.changeTree(new VoxelTree); - + saveSettings(); - + delete _voxelImporter; // let the avatar mixer know we're out @@ -431,14 +434,14 @@ Application::~Application() { delete _glWidget; AccountManager::getInstance().destroy(); - + DTLSClientSession::globalDeinit(); } void Application::saveSettings() { Menu::getInstance()->saveSettings(); _rearMirrorTools->saveSettings(_settings); - + if (_voxelImporter) { _voxelImporter->saveSettings(_settings); } @@ -520,7 +523,7 @@ void Application::initializeGL() { _voxelHideShowThread.initialize(_enableProcessVoxelsThread); _particleEditSender.initialize(_enableProcessVoxelsThread); _modelEditSender.initialize(_enableProcessVoxelsThread); - + if (_enableProcessVoxelsThread) { qDebug("Voxel parsing thread created."); } @@ -585,7 +588,7 @@ void Application::paintGL() { _myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _myAvatar->getScale() * _scaleMirror); _myCamera.setTargetPosition(_myAvatar->getPosition() + glm::vec3(0, headHeight + (_raiseMirror * _myAvatar->getScale()), 0)); _myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); - + // if the head would intersect the near clip plane, we must push the camera out glm::vec3 relativePosition = glm::inverse(_myCamera.getTargetRotation()) * (eyePosition - _myCamera.getTargetPosition()); @@ -594,7 +597,7 @@ void Application::paintGL() { pushback = relativePosition.z + pushbackRadius - _myCamera.getDistance(); pushbackFocalLength = _myCamera.getDistance(); } - + // handle pushback, if any if (pushbackFocalLength > 0.0f) { const float PUSHBACK_DECAY = 0.5f; @@ -1279,7 +1282,7 @@ void Application::dropEvent(QDropEvent *event) { void Application::sendPingPackets() { QByteArray pingPacket = NodeList::getInstance()->constructPingPacket(); - controlledBroadcastToNodes(pingPacket, NodeSet() + controlledBroadcastToNodes(pingPacket, NodeSet() << NodeType::VoxelServer << NodeType::ParticleServer << NodeType::ModelServer << NodeType::AudioMixer << NodeType::AvatarMixer << NodeType::MetavoxelServer); @@ -1290,7 +1293,7 @@ void Application::timer() { if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) { sendPingPackets(); } - + float diffTime = (float)_timerStart.nsecsElapsed() / 1000000000.0f; _fps = (float)_frameCount / diffTime; @@ -1694,7 +1697,7 @@ void Application::init() { connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView())); connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors())); - + // set up our audio reflector _audioReflector.setMyAvatar(getAvatar()); _audioReflector.setVoxels(_voxels.getTree()); @@ -1703,7 +1706,7 @@ void Application::init() { connect(getAudio(), &Audio::processInboundAudio, &_audioReflector, &AudioReflector::processInboundAudio,Qt::DirectConnection); connect(getAudio(), &Audio::processLocalAudio, &_audioReflector, &AudioReflector::processLocalAudio,Qt::DirectConnection); - connect(getAudio(), &Audio::preProcessOriginalInboundAudio, &_audioReflector, + connect(getAudio(), &Audio::preProcessOriginalInboundAudio, &_audioReflector, &AudioReflector::preProcessOriginalInboundAudio,Qt::DirectConnection); // save settings when avatar changes @@ -1818,7 +1821,7 @@ void Application::updateMyAvatarLookAtPosition() { PerformanceWarning warn(showWarnings, "Application::updateMyAvatarLookAtPosition()"); FaceTracker* tracker = getActiveFaceTracker(); - + bool isLookingAtSomeone = false; glm::vec3 lookAtSpot; if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { @@ -1853,7 +1856,7 @@ void Application::updateMyAvatarLookAtPosition() { glm::distance(_mouseRayOrigin, _myAvatar->getHead()->calculateAverageEyePosition())); lookAtSpot = _mouseRayOrigin + _mouseRayDirection * qMax(minEyeDistance, distance); */ - + } // // Deflect the eyes a bit to match the detected Gaze from 3D camera if active @@ -1873,7 +1876,7 @@ void Application::updateMyAvatarLookAtPosition() { eyePitch * pitchSign * deflection, eyeYaw * deflection, 0.0f))) * glm::inverse(_myCamera.getRotation()) * (lookAtSpot - origin); } - + _myAvatar->getHead()->setLookAtPosition(lookAtSpot); } @@ -1925,7 +1928,7 @@ void Application::updateCamera(float deltaTime) { PerformanceWarning warn(showWarnings, "Application::updateCamera()"); if (!OculusManager::isConnected() && !TV3DManager::isConnected() && - Menu::getInstance()->isOptionChecked(MenuOption::OffAxisProjection)) { + Menu::getInstance()->isOptionChecked(MenuOption::OffAxisProjection)) { FaceTracker* tracker = getActiveFaceTracker(); if (tracker) { const float EYE_OFFSET_SCALE = 0.025f; @@ -2481,7 +2484,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) { // disable specular lighting for ground and voxels glMaterialfv(GL_FRONT, GL_SPECULAR, NO_SPECULAR_COLOR); - + // draw the audio reflector overlay _audioReflector.render(); @@ -2649,7 +2652,7 @@ void Application::displayOverlay() { const float LOG2_LOUDNESS_FLOOR = 11.f; float audioLevel = 0.f; float loudness = _audio.getLastInputLoudness() + 1.f; - + _trailingAudioLoudness = AUDIO_METER_AVERAGING * _trailingAudioLoudness + (1.f - AUDIO_METER_AVERAGING) * loudness; float log2loudness = log(_trailingAudioLoudness) / LOG2; @@ -2662,7 +2665,7 @@ void Application::displayOverlay() { audioLevel = AUDIO_METER_SCALE_WIDTH; } bool isClipping = ((_audio.getTimeSinceLastClip() > 0.f) && (_audio.getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)); - + if ((_audio.getTimeSinceLastClip() > 0.f) && (_audio.getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)) { const float MAX_MAGNITUDE = 0.7f; float magnitude = MAX_MAGNITUDE * (1 - _audio.getTimeSinceLastClip() / CLIPPING_INDICATOR_TIME); @@ -2768,7 +2771,7 @@ void Application::displayOverlay() { // give external parties a change to hook in emit renderingOverlay(); - + _overlays.render2D(); glPopMatrix(); @@ -2844,7 +2847,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { // save absolute translations glm::vec3 absoluteSkeletonTranslation = _myAvatar->getSkeletonModel().getTranslation(); glm::vec3 absoluteFaceTranslation = _myAvatar->getHead()->getFaceModel().getTranslation(); - + // get the eye positions relative to the neck and use them to set the face translation glm::vec3 leftEyePosition, rightEyePosition; _myAvatar->getHead()->getFaceModel().setTranslation(glm::vec3()); @@ -3110,7 +3113,7 @@ void Application::uploadModel(ModelType modelType) { thread->connect(uploader, SIGNAL(destroyed()), SLOT(quit())); thread->connect(thread, SIGNAL(finished()), SLOT(deleteLater())); uploader->connect(thread, SIGNAL(started()), SLOT(send())); - + thread->start(); } @@ -3127,28 +3130,28 @@ void Application::updateWindowTitle(){ } void Application::updateLocationInServer() { - + AccountManager& accountManager = AccountManager::getInstance(); - + if (accountManager.isLoggedIn()) { - + static QJsonObject lastLocationObject; - + // construct a QJsonObject given the user's current address information QJsonObject updatedLocationObject; - + QJsonObject addressObject; addressObject.insert("position", QString(createByteArray(_myAvatar->getPosition()))); addressObject.insert("orientation", QString(createByteArray(glm::degrees(safeEulerAngles(_myAvatar->getOrientation()))))); addressObject.insert("domain", NodeList::getInstance()->getDomainHandler().getHostname()); - + updatedLocationObject.insert("address", addressObject); - + if (updatedLocationObject != lastLocationObject) { - + accountManager.authenticatedRequest("/api/v1/users/address", QNetworkAccessManager::PutOperation, JSONCallbackParameters(), QJsonDocument(updatedLocationObject).toJson()); - + lastLocationObject = updatedLocationObject; } } @@ -3173,7 +3176,7 @@ void Application::domainChanged(const QString& domainHostname) { // reset the voxels renderer _voxels.killLocalVoxels(); - + // reset the auth URL for OAuth web view handler OAuthWebViewHandler::getInstance().clearLastAuthorizationURL(); } @@ -3394,7 +3397,7 @@ void Application::loadScripts() { loadScript(string); } } - + QMutexLocker locker(&_settingsMutex); _settings->endArray(); } @@ -3655,7 +3658,7 @@ void Application::parseVersionXml() { QObject* sender = QObject::sender(); QXmlStreamReader xml(qobject_cast(sender)); - + while (!xml.atEnd() && !xml.hasError()) { if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == operatingSystem) { while (!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == operatingSystem)) { @@ -3672,7 +3675,7 @@ void Application::parseVersionXml() { } xml.readNext(); } - + if (!shouldSkipVersion(latestVersion) && applicationVersion() != latestVersion) { new UpdateDialog(_glWidget, releaseNotes, latestVersion, downloadUrl); } @@ -3724,24 +3727,24 @@ void Application::urlGoTo(int argc, const char * constArgv[]) { } else if (urlParts.count() > 1) { // if url has 2 or more parts, the first one is domain name QString domain = urlParts[0]; - + // second part is either a destination coordinate or // a place name QString destination = urlParts[1]; - + // any third part is an avatar orientation. QString orientation = urlParts.count() > 2 ? urlParts[2] : QString(); - + Menu::goToDomain(domain); - + // goto either @user, #place, or x-xx,y-yy,z-zz // style co-ordinate. Menu::goTo(destination); - + if (!orientation.isEmpty()) { // location orientation Menu::goToOrientation(orientation); } - } + } } } diff --git a/interface/src/Application.h b/interface/src/Application.h index 5460093cbd..36076218b1 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -203,6 +204,7 @@ public: JoystickManager* getJoystickManager() { return &_joystickManager; } BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; } QUndoStack* getUndoStack() { return &_undoStack; } + QSystemTrayIcon* getTrayIcon() { return _trayIcon; } /// if you need to access the application settings, use lockSettings()/unlockSettings() QSettings* lockSettings() { _settingsMutex.lock(); return _settings; } @@ -466,7 +468,7 @@ private: glm::mat4 _untranslatedViewMatrix; glm::vec3 _viewMatrixTranslation; glm::mat4 _projectionMatrix; - + float _scaleMirror; float _rotateMirror; float _raiseMirror; @@ -553,6 +555,8 @@ private: RunningScriptsWidget* _runningScriptsWidget; QHash _scriptEnginesHash; bool _runningScriptsWidgetWasVisible; + + QSystemTrayIcon* _trayIcon; }; #endif // hifi_Application_h diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index c79d4618e5..8021816db9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -1198,6 +1199,8 @@ void Menu::showChat() { if (_chatWindow->isHidden()) { _chatWindow->show(); } + } else { + Application::getInstance()->getTrayIcon()->showMessage("Interface", "You need to login to be able to chat with others on this domain."); } } From c4b17963e2d78c2ce9c6002d7f76aa77392a1a38 Mon Sep 17 00:00:00 2001 From: Mohammed Nafees Date: Thu, 22 May 2014 16:55:24 +0530 Subject: [PATCH 3/3] Remove unnecessory header file inclusion in Menu.cpp --- interface/src/Menu.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 8021816db9..c40058f89b 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include