Automated merge up from viewer-development

master
Loren Shih 2010-10-20 12:18:33 -04:00
commit 7687653871
704 changed files with 15873 additions and 6554 deletions

View File

@ -1,3 +1,4 @@
bb38ff1a763738609e1b3cada6d15fa61e5e84b9 2.1.1-release
003dd9461bfa479049afcc34545ab3431b147c7c v2start
08398e650c222336bb2b6de0cd3bba944aef11b4 2-1rn1
0962101bfa7df0643a6e625786025fe7f8a6dc97 2-1-beta-2
@ -26,3 +27,9 @@ d40ac9dd949cba6dab1cc386da6a2027690c2519 alpha-5
d6781e22543acd7e21b967209f3c6e7003d380e3 fork to viewer-2-0
c6e6324f5be1401f077ad18a4a0f6b46451c2f7b last_sprint
7076e22f9f43f479a4ea75eac447a36364bead5a beta_2.1.3
7076e22f9f43f479a4ea75eac447a36364bead5a 2.2.0-beta1
9822eb3e25f7fe0c28ffd8aba45c507caa383cbc 2.2.0-beta2
b0cd7e150009809a0b5b0a9d5785cd4bb230413a 2.2.0-beta3
00a831292231faad7e44c69f76cb96f175b8dfad 2.2.0-beta4
98e0d6df638429fd2f0476667504bd5a6b298def 2.3.0-beta1
1415e6538d54fd5d568ee88343424d57c6803c2c 2.2.0-release

View File

@ -39,8 +39,9 @@ snowstorm_viewer-development.email = viewer-development-builds@lists.secondlife.
# ========================================
# Viewer Beta
# ========================================
viewer-beta.viewer_channel = "Second Life Beta"
viewer-beta.login_channel = "Second Life Beta"
viewer-beta.viewer_channel = "Second Life Beta Viewer"
viewer-beta.login_channel = "Second Life Beta Viewer"
viewer-beta.build_debug_release_separately = true
viewer-beta.build_viewer_update_version_manager = true
# ========================================
@ -48,6 +49,7 @@ viewer-beta.build_viewer_update_version_manager = true
# ========================================
viewer-release.viewer_channel = "Second Life Release"
viewer-release.login_channel = "Second Life Release"
viewer-release.build_debug_release_separately = true
viewer-release.build_viewer_update_version_manager = true
# ========================================
@ -117,6 +119,26 @@ gooey.login_channel = "Second Life Alpha"
gooey.viewer_grid = agni
gooey.build_viewer_update_version_manager = false
# ========================================
# Display Names project
# ========================================
#viewer-identity-evolution.email = leyla@lindenlab.com
viewer-identity.build_Debug = false
viewer-identity.build_RelWithDebInfo = false
viewer-identity.build_viewer = true
viewer-identity.build_server = false
viewer-identity.build_server_tests = false
viewer-identity.build_Linux = true
viewer-identity.build_hg_bundle = true
viewer-identity.bulld_docs = true
viewer-identity.viewer_channel = "Second Life Project Viewer"
viewer-identity.login_channel = "Second Life Project Viewer"
viewer-identity.viewer_grid = aditi
viewer-identity.build_viewer_update_version_manager = false
# ========================================
# palange
# ========================================

View File

@ -59,7 +59,7 @@ pre_build()
-t $variant \
-G "$cmake_generator" \
configure \
-DGRID:STRING="$viewer_grid"\
-DGRID:STRING="$viewer_grid" \
-DVIEWER_CHANNEL:STRING="$viewer_channel" \
-DVIEWER_LOGIN_CHANNEL:STRING="$login_channel" \
-DINSTALL_PROPRIETARY:BOOL=ON \
@ -115,11 +115,15 @@ then
if [ -x "$top/../buildscripts/hg/bin/build.sh" ]
then
exec "$top/../buildscripts/hg/bin/build.sh" "$top"
elif [ -r "$top/README" ]
then
cat "$top/README"
exit 1
else
cat <<EOF
This script, if called in a development environment, requires that the branch
independent build script repository be checked out next to this repository.
This repository is located at http://hg.lindenlab.com/parabuild/buildscripts
This repository is located at http://hg.secondlife.com/buildscripts
EOF
exit 1
fi

View File

@ -62,6 +62,7 @@ Alejandro Rosenthal
VWR-1184
Aleric Inglewood
SNOW-522
SNOW-756
SNOW-764
VWR-10001
VWR-10759
@ -549,14 +550,18 @@ Ringo Tuxing
Robin Cornelius
SNOW-108
SNOW-204
SNOW-287
SNOW-484
SNOW-504
SNOW-506
SNOW-507
SNOW-511
SNOW-512
SNOW-514
SNOW-520
SNOW-585
SNOW-599
SNOW-747
VWR-2488
VWR-9557
VWR-11128
@ -658,12 +663,16 @@ Techwolf Lupindo
SNOW-592
SNOW-649
SNOW-650
SNOW-651
SNOW-654
SNOW-687
SNOW-680
SNOW-681
SNOW-685
SNOW-690
SNOW-746
VWR-12385
VWR-20893
tenebrous pau
VWR-247
Tharax Ferraris

View File

@ -370,6 +370,14 @@
</map>
<!-- Server to client -->
<key>DisplayNameUpdate</key>
<map>
<key>flavor</key>
<string>llsd</string>
<key>trusted-sender</key>
<boolean>true</boolean>
</map>
<key>ParcelVoiceInfo</key>
<map>
<key>flavor</key>
@ -426,6 +434,14 @@
<boolean>true</boolean>
</map>
<key>SetDisplayNameReply</key>
<map>
<key>flavor</key>
<string>llsd</string>
<key>trusted-sender</key>
<boolean>true</boolean>
</map>
<key>DirLandReply</key>
<map>
<key>flavor</key>

View File

@ -123,6 +123,8 @@ if (SERVER)
endif (WINDOWS)
endif (SERVER)
# Define after the custom viewer and server targets are created so individual
# apps can add themselves as dependencies
add_subdirectory(${INTEGRATION_TESTS_PREFIX}integration_tests)
if (LL_TESTS)
# Define after the custom viewer and server targets are created so
# individual apps can add themselves as dependencies
add_subdirectory(${INTEGRATION_TESTS_PREFIX}integration_tests)
endif (LL_TESTS)

View File

@ -26,6 +26,7 @@ set(cmake_SOURCE_FILES
FindBerkeleyDB.cmake
FindCARes.cmake
FindELFIO.cmake
FindFMOD.cmake
FindGooglePerfTools.cmake
FindMono.cmake
FindMT.cmake

View File

@ -59,9 +59,10 @@ if(WINDOWS)
set(release_files ${release_files} libtcmalloc_minimal.dll)
endif(USE_GOOGLE_PERFTOOLS)
if (FMOD_SDK_DIR)
set(fmod_files fmod.dll)
endif (FMOD_SDK_DIR)
if (FMOD)
set(debug_files ${debug_files} fmod.dll)
set(release_files ${release_files} fmod.dll)
endif (FMOD)
#*******************************
# LLKDU
@ -243,9 +244,9 @@ elseif(LINUX)
libssl.so.0.9.7
)
if (FMOD_SDK_DIR)
set(fmod_files "libfmod-3.75.so")
endif (FMOD_SDK_DIR)
if (FMOD)
set(release_files ${release_files} "libfmod-3.75.so")
endif (FMOD)
#*******************************
# LLKDU
@ -339,30 +340,6 @@ copy_if_different(
)
set(third_party_targets ${third_party_targets} ${out_targets})
if (FMOD_SDK_DIR)
copy_if_different(
${FMOD_SDK_DIR}
"${CMAKE_CURRENT_BINARY_DIR}/Debug"
out_targets
${fmod_files}
)
set(all_targets ${all_targets} ${out_targets})
copy_if_different(
${FMOD_SDK_DIR}
"${CMAKE_CURRENT_BINARY_DIR}/Release"
out_targets
${fmod_files}
)
set(all_targets ${all_targets} ${out_targets})
copy_if_different(
${FMOD_SDK_DIR}
"${CMAKE_CURRENT_BINARY_DIR}/RelWithDbgInfo"
out_targets
${fmod_files}
)
set(all_targets ${all_targets} ${out_targets})
endif (FMOD_SDK_DIR)
#*******************************
# LLKDU
set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu")

View File

@ -1,64 +1,24 @@
# -*- cmake -*-
include(Linking)
if(INSTALL_PROPRIETARY)
include(Prebuilt)
use_prebuilt_binary(fmod)
endif(INSTALL_PROPRIETARY)
find_library(FMOD_LIBRARY_RELEASE
NAMES fmod fmodvc fmod-3.75
PATHS
${ARCH_PREBUILT_DIRS_RELEASE}
)
find_library(FMOD_LIBRARY_DEBUG
NAMES fmod fmodvc fmod-3.75
PATHS
${ARCH_PREBUILT_DIRS_DEBUG}
)
if (FMOD_LIBRARY_RELEASE AND FMOD_LIBRARY_DEBUG)
set(FMOD_LIBRARY
debug ${FMOD_LIBRARY_DEBUG}
optimized ${FMOD_LIBRARY_RELEASE})
elseif (FMOD_LIBRARY_RELEASE)
set(FMOD_LIBRARY ${FMOD_LIBRARY_RELEASE})
endif (FMOD_LIBRARY_RELEASE AND FMOD_LIBRARY_DEBUG)
if (NOT FMOD_LIBRARY)
set(FMOD_SDK_DIR CACHE PATH "Path to the FMOD SDK.")
if (FMOD_SDK_DIR)
find_library(FMOD_LIBRARY
NAMES fmodvc fmod-3.75 fmod
PATHS
${FMOD_SDK_DIR}/api/lib
${FMOD_SDK_DIR}/api
${FMOD_SDK_DIR}/lib
${FMOD_SDK_DIR}
)
endif (FMOD_SDK_DIR)
endif (NOT FMOD_LIBRARY)
find_path(FMOD_INCLUDE_DIR fmod.h
${LIBS_PREBUILT_DIR}/include
${FMOD_SDK_DIR}/api/inc
${FMOD_SDK_DIR}/inc
${FMOD_SDK_DIR}
)
if (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
set(FMOD ON CACHE BOOL "Use closed source FMOD sound library.")
else (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
set(FMOD_LIBRARY "")
set(FMOD_INCLUDE_DIR "")
if (FMOD)
message(STATUS "No support for FMOD audio (need to set FMOD_SDK_DIR?)")
endif (FMOD)
set(FMOD OFF CACHE BOOL "Use closed source FMOD sound library.")
endif (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
set(FMOD ON CACHE BOOL "Use FMOD sound library.")
if (FMOD)
message(STATUS "Building with FMOD audio support")
if (STANDALONE)
set(FMOD_FIND_REQUIRED ON)
include(FindFMOD)
else (STANDALONE)
include(Prebuilt)
use_prebuilt_binary(fmod)
if (WINDOWS)
set(FMOD_LIBRARY fmod)
elseif (DARWIN)
set(FMOD_LIBRARY fmod)
elseif (LINUX)
set(FMOD_LIBRARY fmod-3.75)
endif (WINDOWS)
SET(FMOD_LIBRARIES ${FMOD_LIBRARY})
set(FMOD_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include)
endif (STANDALONE)
endif (FMOD)

View File

@ -0,0 +1,44 @@
# -*- cmake -*-
# - Find FMOD
# Find the FMOD includes and library
# This module defines
# FMOD_INCLUDE_DIR, where to find fmod.h and fmod_errors.h
# FMOD_LIBRARIES, the libraries needed to use FMOD.
# FMOD, If false, do not try to use FMOD.
# also defined, but not for general use are
# FMOD_LIBRARY, where to find the FMOD library.
FIND_PATH(FMOD_INCLUDE_DIR fmod.h PATH_SUFFIXES fmod)
SET(FMOD_NAMES ${FMOD_NAMES} fmod fmodvc fmod-3.75)
FIND_LIBRARY(FMOD_LIBRARY
NAMES ${FMOD_NAMES}
PATH_SUFFIXES fmod
)
IF (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
SET(FMOD_LIBRARIES ${FMOD_LIBRARY})
SET(FMOD_FOUND "YES")
ELSE (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
SET(FMOD_FOUND "NO")
ENDIF (FMOD_LIBRARY AND FMOD_INCLUDE_DIR)
IF (FMOD_FOUND)
IF (NOT FMOD_FIND_QUIETLY)
MESSAGE(STATUS "Found FMOD: ${FMOD_LIBRARIES}")
ENDIF (NOT FMOD_FIND_QUIETLY)
ELSE (FMOD_FOUND)
IF (FMOD_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find FMOD library")
ENDIF (FMOD_FIND_REQUIRED)
ENDIF (FMOD_FOUND)
# Deprecated declarations.
SET (NATIVE_FMOD_INCLUDE_PATH ${FMOD_INCLUDE_DIR} )
GET_FILENAME_COMPONENT (NATIVE_FMOD_LIB_PATH ${FMOD_LIBRARY} PATH)
MARK_AS_ADVANCED(
FMOD_LIBRARY
FMOD_INCLUDE_DIR
)

View File

@ -0,0 +1,40 @@
# -*- cmake -*-
# - Find Google BreakPad
# Find the Google BreakPad includes and library
# This module defines
# BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR, where to find exception_handler.h, etc.
# BREAKPAD_EXCEPTION_HANDLER_LIBRARIES, the libraries needed to use Google BreakPad.
# BREAKPAD_EXCEPTION_HANDLER_FOUND, If false, do not try to use Google BreakPad.
# also defined, but not for general use are
# BREAKPAD_EXCEPTION_HANDLER_LIBRARY, where to find the Google BreakPad library.
FIND_PATH(BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR google_breakpad/exception_handler.h)
SET(BREAKPAD_EXCEPTION_HANDLER_NAMES ${BREAKPAD_EXCEPTION_HANDLER_NAMES} breakpad_client)
FIND_LIBRARY(BREAKPAD_EXCEPTION_HANDLER_LIBRARY
NAMES ${BREAKPAD_EXCEPTION_HANDLER_NAMES}
)
IF (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR)
SET(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES ${BREAKPAD_EXCEPTION_HANDLER_LIBRARY})
SET(BREAKPAD_EXCEPTION_HANDLER_FOUND "YES")
ELSE (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR)
SET(BREAKPAD_EXCEPTION_HANDLER_FOUND "NO")
ENDIF (BREAKPAD_EXCEPTION_HANDLER_LIBRARY AND BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR)
IF (BREAKPAD_EXCEPTION_HANDLER_FOUND)
IF (NOT BREAKPAD_EXCEPTION_HANDLER_FIND_QUIETLY)
MESSAGE(STATUS "Found Google BreakPad: ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES}")
ENDIF (NOT BREAKPAD_EXCEPTION_HANDLER_FIND_QUIETLY)
ELSE (BREAKPAD_EXCEPTION_HANDLER_FOUND)
IF (BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED)
MESSAGE(FATAL_ERROR "Could not find Google BreakPad library")
ENDIF (BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED)
ENDIF (BREAKPAD_EXCEPTION_HANDLER_FOUND)
MARK_AS_ADVANCED(
BREAKPAD_EXCEPTION_HANDLER_LIBRARY
BREAKPAD_EXCEPTION_HANDLER_INCLUDE_DIR
)

View File

@ -2,8 +2,8 @@
include(Prebuilt)
if (STANDALONE)
MESSAGE(FATAL_ERROR "*TODO standalone support for google breakad is unimplemented")
# *TODO - implement this include(FindGoogleBreakpad)
set(BREAKPAD_EXCEPTION_HANDLER_FIND_REQUIRED ON)
include(FindGoogleBreakpad)
else (STANDALONE)
use_prebuilt_binary(google_breakpad)
if (DARWIN)

View File

@ -256,6 +256,10 @@ MACRO(SET_TEST_PATH LISTVAR)
set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources ${SHARED_LIB_STAGING_DIR}/Release/Resources /usr/lib)
ELSE(WINDOWS)
# Linux uses a single staging directory anyway.
set(${LISTVAR} ${SHARED_LIB_STAGING_DIR} /usr/lib)
IF (STANDALONE)
set(${LISTVAR} ${CMAKE_BINARY_DIR}/llcommon /usr/lib /usr/local/lib)
ELSE (STANDALONE)
set(${LISTVAR} ${SHARED_LIB_STAGING_DIR} /usr/lib)
ENDIF (STANDALONE)
ENDIF(WINDOWS)
ENDMACRO(SET_TEST_PATH)

View File

@ -1,28 +1,28 @@
# -*- cmake -*-
include(Prebuilt)
if (STANDALONE)
include(FindPkgConfig)
pkg_check_modules(PULSEAUDIO REQUIRED libpulse-mainloop-glib)
elseif (LINUX)
use_prebuilt_binary(pulseaudio)
set(PULSEAUDIO_FOUND ON FORCE BOOL)
set(PULSEAUDIO_INCLUDE_DIRS
${LIBS_PREBUILT_DIR}/include
)
# We don't need to explicitly link against pulseaudio itself, because
# the viewer probes for the system's copy at runtime.
set(PULSEAUDIO_LIBRARIES
# none needed!
)
endif (STANDALONE)
if (PULSEAUDIO_FOUND)
set(PULSEAUDIO ON CACHE BOOL "Build with PulseAudio support, if available.")
endif (PULSEAUDIO_FOUND)
set(PULSEAUDIO ON CACHE BOOL "Build with PulseAudio support, if available.")
if (PULSEAUDIO)
add_definitions(-DLL_PULSEAUDIO_ENABLED=1)
if (STANDALONE)
include(FindPkgConfig)
pkg_check_modules(PULSEAUDIO libpulse)
elseif (LINUX)
use_prebuilt_binary(pulseaudio)
set(PULSEAUDIO_FOUND ON FORCE BOOL)
set(PULSEAUDIO_INCLUDE_DIRS
${LIBS_PREBUILT_DIR}/include
)
# We don't need to explicitly link against pulseaudio itself, because
# the viewer probes for the system's copy at runtime.
set(PULSEAUDIO_LIBRARIES
# none needed!
)
endif (STANDALONE)
endif (PULSEAUDIO)
if (PULSEAUDIO_FOUND)
add_definitions(-DLL_PULSEAUDIO_ENABLED=1)
endif (PULSEAUDIO_FOUND)

View File

@ -24,7 +24,7 @@ myprog somearg otherarg
$LicenseInfo:firstyear=2009&license=viewerlgpl$
Second Life Viewer Source Code
Copyright (C) 2010, Linden Research, Inc.
Copyright (C) 2009-2010, Linden Research, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public

View File

@ -4,7 +4,7 @@
$LicenseInfo:firstyear=2006&license=viewerlgpl$
Second Life Viewer Source Code
Copyright (C) 2010, Linden Research, Inc.
Copyright (C) 2006-2010, Linden Research, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public

View File

@ -33,6 +33,7 @@ set(llcommon_SOURCE_FILES
llapp.cpp
llapr.cpp
llassettype.cpp
llavatarname.cpp
llbase32.cpp
llbase64.cpp
llcommon.cpp
@ -115,6 +116,7 @@ set(llcommon_HEADER_FILES
llallocator.h
llallocator_heap_profile.h
llagentconstants.h
llavatarname.h
llapp.h
llapr.h
llassettype.h
@ -252,8 +254,15 @@ set_source_files_properties(${llcommon_HEADER_FILES}
list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})
if(LLCOMMON_LINK_SHARED)
add_library (llcommon SHARED ${llcommon_SOURCE_FILES})
ll_stage_sharedlib(llcommon)
add_library (llcommon SHARED ${llcommon_SOURCE_FILES})
if(NOT WORD_SIZE EQUAL 32)
if(WINDOWS)
add_definitions(/FIXED:NO)
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif(WINDOWS)
endif(NOT WORD_SIZE EQUAL 32)
ll_stage_sharedlib(llcommon)
else(LLCOMMON_LINK_SHARED)
add_library (llcommon ${llcommon_SOURCE_FILES})
endif(LLCOMMON_LINK_SHARED)

View File

@ -0,0 +1,113 @@
/**
* @file llavatarname.cpp
* @brief Represents name-related data for an avatar, such as the
* username/SLID ("bobsmith123" or "james.linden") and the display
* name ("James Cook")
*
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llavatarname.h"
#include "lldate.h"
#include "llsd.h"
// Store these in pre-built std::strings to avoid memory allocations in
// LLSD map lookups
static const std::string USERNAME("username");
static const std::string DISPLAY_NAME("display_name");
static const std::string LEGACY_FIRST_NAME("legacy_first_name");
static const std::string LEGACY_LAST_NAME("legacy_last_name");
static const std::string IS_DISPLAY_NAME_DEFAULT("is_display_name_default");
static const std::string DISPLAY_NAME_EXPIRES("display_name_expires");
static const std::string DISPLAY_NAME_NEXT_UPDATE("display_name_next_update");
LLAvatarName::LLAvatarName()
: mUsername(),
mDisplayName(),
mLegacyFirstName(),
mLegacyLastName(),
mIsDisplayNameDefault(false),
mIsDummy(false),
mExpires(F64_MAX),
mNextUpdate(0.0)
{ }
bool LLAvatarName::operator<(const LLAvatarName& rhs) const
{
if (mUsername == rhs.mUsername)
return mDisplayName < rhs.mDisplayName;
else
return mUsername < rhs.mUsername;
}
LLSD LLAvatarName::asLLSD() const
{
LLSD sd;
sd[USERNAME] = mUsername;
sd[DISPLAY_NAME] = mDisplayName;
sd[LEGACY_FIRST_NAME] = mLegacyFirstName;
sd[LEGACY_LAST_NAME] = mLegacyLastName;
sd[IS_DISPLAY_NAME_DEFAULT] = mIsDisplayNameDefault;
sd[DISPLAY_NAME_EXPIRES] = LLDate(mExpires);
sd[DISPLAY_NAME_NEXT_UPDATE] = LLDate(mNextUpdate);
return sd;
}
void LLAvatarName::fromLLSD(const LLSD& sd)
{
mUsername = sd[USERNAME].asString();
mDisplayName = sd[DISPLAY_NAME].asString();
mLegacyFirstName = sd[LEGACY_FIRST_NAME].asString();
mLegacyLastName = sd[LEGACY_LAST_NAME].asString();
mIsDisplayNameDefault = sd[IS_DISPLAY_NAME_DEFAULT].asBoolean();
LLDate expires = sd[DISPLAY_NAME_EXPIRES];
mExpires = expires.secondsSinceEpoch();
LLDate next_update = sd[DISPLAY_NAME_NEXT_UPDATE];
mNextUpdate = next_update.secondsSinceEpoch();
}
std::string LLAvatarName::getCompleteName() const
{
std::string name;
if (!mUsername.empty())
{
name = mDisplayName + " (" + mUsername + ")";
}
else
{
// ...display names are off, legacy name is in mDisplayName
name = mDisplayName;
}
return name;
}
std::string LLAvatarName::getLegacyName() const
{
std::string name;
name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() );
name = mLegacyFirstName;
name += " ";
name += mLegacyLastName;
return name;
}

View File

@ -0,0 +1,95 @@
/**
* @file llavatarname.h
* @brief Represents name-related data for an avatar, such as the
* username/SLID ("bobsmith123" or "james.linden") and the display
* name ("James Cook")
*
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LLAVATARNAME_H
#define LLAVATARNAME_H
#include <string>
class LLSD;
class LL_COMMON_API LLAvatarName
{
public:
LLAvatarName();
bool operator<(const LLAvatarName& rhs) const;
LLSD asLLSD() const;
void fromLLSD(const LLSD& sd);
// For normal names, returns "James Linden (james.linden)"
// When display names are disabled returns just "James Linden"
std::string getCompleteName() const;
// Returns "James Linden" or "bobsmith123 Resident" for backwards
// compatibility with systems like voice and muting
// *TODO: Eliminate this in favor of username only
std::string getLegacyName() const;
// "bobsmith123" or "james.linden", US-ASCII only
std::string mUsername;
// "Jose' Sanchez" or "James Linden", UTF-8 encoded Unicode
// Contains data whether or not user has explicitly set
// a display name; may duplicate their username.
std::string mDisplayName;
// For "James Linden", "James"
// For "bobsmith123", "bobsmith123"
// Used to communicate with legacy systems like voice and muting which
// rely on old-style names.
// *TODO: Eliminate this in favor of username only
std::string mLegacyFirstName;
// For "James Linden", "Linden"
// For "bobsmith123", "Resident"
// see above for rationale
std::string mLegacyLastName;
// If true, both display name and SLID were generated from
// a legacy first and last name, like "James Linden (james.linden)"
bool mIsDisplayNameDefault;
// Under error conditions, we may insert "dummy" records with
// names like "???" into caches as placeholders. These can be
// shown in UI, but are not serialized.
bool mIsDummy;
// Names can change, so need to keep track of when name was
// last checked.
// Unix time-from-epoch seconds for efficiency
F64 mExpires;
// You can only change your name every N hours, so record
// when the next update is allowed
// Unix time-from-epoch seconds
F64 mNextUpdate;
};
#endif

View File

@ -28,7 +28,6 @@
#ifndef LL_LLCHAT_H
#define LL_LLCHAT_H
#include "llstring.h"
#include "lluuid.h"
#include "v3math.h"
@ -71,7 +70,7 @@ typedef enum e_chat_style
class LLChat
{
public:
LLChat(const std::string& text = LLStringUtil::null)
LLChat(const std::string& text = std::string())
: mText(text),
mFromName(),
mFromID(),

View File

@ -731,14 +731,17 @@ void LLStringOps::setupDatetimeInfo (bool daylight)
nowT = time (NULL);
tmpT = localtime (&nowT);
localT = mktime (tmpT);
tmpT = gmtime (&nowT);
gmtT = mktime (tmpT);
tmpT = localtime (&nowT);
localT = mktime (tmpT);
sLocalTimeOffset = (long) (gmtT - localT);
if (tmpT->tm_isdst)
{
sLocalTimeOffset -= 60 * 60; // 1 hour
}
sPacificDaylightTime = daylight;
sPacificTimeOffset = (sPacificDaylightTime? 7 : 8 ) * 60 * 60;

View File

@ -52,7 +52,6 @@ enum LLRoleChangeType
//
// KNOWN HOLES: use these for any single bit powers you need
// bit 0x1 << 41
// bit 0x1 << 46
// bit 0x1 << 49 and above
@ -103,6 +102,8 @@ const U64 GP_LAND_ALLOW_FLY = 0x1 << 24; // Bypass Fly Restriction
const U64 GP_LAND_ALLOW_CREATE = 0x1 << 25; // Bypass Create/Edit Objects Restriction
const U64 GP_LAND_ALLOW_LANDMARK = 0x1 << 26; // Bypass Landmark Restriction
const U64 GP_LAND_ALLOW_SET_HOME = 0x1 << 28; // Bypass Set Home Point Restriction
const U64 GP_LAND_ALLOW_HOLD_EVENT = 0x1LL << 41; // Allowed to hold events on group-owned land
// Parcel Access
const U64 GP_LAND_MANAGE_ALLOWED = 0x1 << 29; // Manage Allowed List

View File

@ -108,6 +108,9 @@ std::string build_transfer_message_to_source(
std::ostringstream ostr;
if(dest_id.isNull())
{
// *NOTE: Do not change these strings! The viewer matches
// them in llviewermessage.cpp to perform localization.
// If you need to make changes, add a new, localizable message. JC
ostr << "You paid L$" << amount;
switch(transaction_type)
{
@ -154,6 +157,9 @@ std::string build_transfer_message_to_destination(
return description;
}
std::ostringstream ostr;
// *NOTE: Do not change these strings! The viewer matches
// them in llviewermessage.cpp to perform localization.
// If you need to make changes, add a new, localizable message. JC
ostr << source_name << " paid you L$" << amount;
append_reason(ostr, transaction_type, description);
ostr << ".";

View File

@ -25,6 +25,7 @@ set(llmessage_SOURCE_FILES
llares.cpp
llareslistener.cpp
llassetstorage.cpp
llavatarnamecache.cpp
llblowfishcipher.cpp
llbuffer.cpp
llbufferstream.cpp
@ -110,6 +111,7 @@ set(llmessage_HEADER_FILES
llares.h
llareslistener.h
llassetstorage.h
llavatarnamecache.h
llblowfishcipher.h
llbuffer.h
llbufferstream.h
@ -248,6 +250,7 @@ if (LL_TESTS)
"${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py"
)
LL_ADD_INTEGRATION_TEST(llavatarnamecache "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}")

View File

@ -0,0 +1,822 @@
/**
* @file llavatarnamecache.cpp
* @brief Provides lookup of avatar SLIDs ("bobsmith123") and display names
* ("James Cook") from avatar UUIDs.
*
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llavatarnamecache.h"
#include "llcachename.h" // we wrap this system
#include "llframetimer.h"
#include "llhttpclient.h"
#include "llsd.h"
#include "llsdserialize.h"
#include <boost/tokenizer.hpp>
#include <map>
#include <set>
namespace LLAvatarNameCache
{
use_display_name_signal_t mUseDisplayNamesSignal;
// Manual override for display names - can disable even if the region
// supports it.
bool sUseDisplayNames = true;
// Cache starts in a paused state until we can determine if the
// current region supports display names.
bool sRunning = false;
// Base lookup URL for name service.
// On simulator, loaded from indra.xml
// On viewer, usually a simulator capability (at People API team's request)
// Includes the trailing slash, like "http://pdp60.lindenlab.com:8000/agents/"
std::string sNameLookupURL;
// accumulated agent IDs for next query against service
typedef std::set<LLUUID> ask_queue_t;
ask_queue_t sAskQueue;
// agent IDs that have been requested, but with no reply
// maps agent ID to frame time request was made
typedef std::map<LLUUID, F64> pending_queue_t;
pending_queue_t sPendingQueue;
// Callbacks to fire when we received a name.
// May have multiple callbacks for a single ID, which are
// represented as multiple slots bound to the signal.
// Avoid copying signals via pointers.
typedef std::map<LLUUID, callback_signal_t*> signal_map_t;
signal_map_t sSignalMap;
// names we know about
typedef std::map<LLUUID, LLAvatarName> cache_t;
cache_t sCache;
// Send bulk lookup requests a few times a second at most
// only need per-frame timing resolution
LLFrameTimer sRequestTimer;
// Periodically clean out expired entries from the cache
//LLFrameTimer sEraseExpiredTimer;
//-----------------------------------------------------------------------
// Internal methods
//-----------------------------------------------------------------------
// Handle name response off network.
// Optionally skip adding to cache, used when this is a fallback to the
// legacy name system.
void processName(const LLUUID& agent_id,
const LLAvatarName& av_name,
bool add_to_cache);
void requestNamesViaCapability();
// Legacy name system callback
void legacyNameCallback(const LLUUID& agent_id,
const std::string& full_name,
bool is_group);
void requestNamesViaLegacy();
// Fill in an LLAvatarName with the legacy name data
void buildLegacyName(const std::string& full_name,
LLAvatarName* av_name);
// Do a single callback to a given slot
void fireSignal(const LLUUID& agent_id,
const callback_slot_t& slot,
const LLAvatarName& av_name);
// Is a request in-flight over the network?
bool isRequestPending(const LLUUID& agent_id);
// Erase expired names from cache
void eraseExpired();
bool expirationFromCacheControl(LLSD headers, F64 *expires);
}
/* Sample response:
<?xml version="1.0"?>
<llsd>
<map>
<key>agents</key>
<array>
<map>
<key>display_name_next_update</key>
<date>2010-04-16T21:34:02+00:00Z</date>
<key>display_name_expires</key>
<date>2010-04-16T21:32:26.142178+00:00Z</date>
<key>display_name</key>
<string>MickBot390 LLQABot</string>
<key>sl_id</key>
<string>mickbot390.llqabot</string>
<key>id</key>
<string>0012809d-7d2d-4c24-9609-af1230a37715</string>
<key>is_display_name_default</key>
<boolean>false</boolean>
</map>
<map>
<key>display_name_next_update</key>
<date>2010-04-16T21:34:02+00:00Z</date>
<key>display_name_expires</key>
<date>2010-04-16T21:32:26.142178+00:00Z</date>
<key>display_name</key>
<string>Bjork Gudmundsdottir</string>
<key>sl_id</key>
<string>sardonyx.linden</string>
<key>id</key>
<string>3941037e-78ab-45f0-b421-bd6e77c1804d</string>
<key>is_display_name_default</key>
<boolean>true</boolean>
</map>
</array>
</map>
</llsd>
*/
class LLAvatarNameResponder : public LLHTTPClient::Responder
{
private:
// need to store agent ids that are part of this request in case of
// an error, so we can flag them as unavailable
std::vector<LLUUID> mAgentIDs;
// Need the headers to look up Expires: and Retry-After:
LLSD mHeaders;
public:
LLAvatarNameResponder(const std::vector<LLUUID>& agent_ids)
: mAgentIDs(agent_ids),
mHeaders()
{ }
/*virtual*/ void completedHeader(U32 status, const std::string& reason,
const LLSD& headers)
{
mHeaders = headers;
}
/*virtual*/ void result(const LLSD& content)
{
// Pull expiration out of headers if available
F64 expires = LLAvatarNameCache::nameExpirationFromHeaders(mHeaders);
LLSD agents = content["agents"];
LLSD::array_const_iterator it = agents.beginArray();
for ( ; it != agents.endArray(); ++it)
{
const LLSD& row = *it;
LLUUID agent_id = row["id"].asUUID();
LLAvatarName av_name;
av_name.fromLLSD(row);
// Use expiration time from header
av_name.mExpires = expires;
// Some avatars don't have explicit display names set
if (av_name.mDisplayName.empty())
{
av_name.mDisplayName = av_name.mUsername;
}
// cache it and fire signals
LLAvatarNameCache::processName(agent_id, av_name, true);
}
// Same logic as error response case
LLSD unresolved_agents = content["bad_ids"];
if (unresolved_agents.size() > 0)
{
const std::string DUMMY_NAME("\?\?\?");
LLAvatarName av_name;
av_name.mUsername = DUMMY_NAME;
av_name.mDisplayName = DUMMY_NAME;
av_name.mIsDisplayNameDefault = false;
av_name.mIsDummy = true;
av_name.mExpires = expires;
it = unresolved_agents.beginArray();
for ( ; it != unresolved_agents.endArray(); ++it)
{
const LLUUID& agent_id = *it;
// cache it and fire signals
LLAvatarNameCache::processName(agent_id, av_name, true);
}
}
}
/*virtual*/ void error(U32 status, const std::string& reason)
{
// We're going to construct a dummy record and cache it for a while,
// either briefly for a 503 Service Unavailable, or longer for other
// errors.
F64 retry_timestamp = errorRetryTimestamp(status);
// *NOTE: "??" starts trigraphs in C/C++, escape the question marks.
const std::string DUMMY_NAME("\?\?\?");
LLAvatarName av_name;
av_name.mUsername = DUMMY_NAME;
av_name.mDisplayName = DUMMY_NAME;
av_name.mIsDisplayNameDefault = false;
av_name.mIsDummy = true;
av_name.mExpires = retry_timestamp;
// Add dummy records for all agent IDs in this request
std::vector<LLUUID>::const_iterator it = mAgentIDs.begin();
for ( ; it != mAgentIDs.end(); ++it)
{
const LLUUID& agent_id = *it;
// cache it and fire signals
LLAvatarNameCache::processName(agent_id, av_name, true);
}
}
// Return time to retry a request that generated an error, based on
// error type and headers. Return value is seconds-since-epoch.
F64 errorRetryTimestamp(S32 status)
{
F64 now = LLFrameTimer::getTotalSeconds();
// Retry-After takes priority
LLSD retry_after = mHeaders["retry-after"];
if (retry_after.isDefined())
{
// We only support the delta-seconds type
S32 delta_seconds = retry_after.asInteger();
if (delta_seconds > 0)
{
// ...valid delta-seconds
return now + F64(delta_seconds);
}
}
// If no Retry-After, look for Cache-Control max-age
F64 expires = 0.0;
if (LLAvatarNameCache::expirationFromCacheControl(mHeaders, &expires))
{
return expires;
}
// No information in header, make a guess
if (status == 503)
{
// ...service unavailable, retry soon
const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min
return now + SERVICE_UNAVAILABLE_DELAY;
}
else
{
// ...other unexpected error
const F64 DEFAULT_DELAY = 3600.0; // 1 hour
return now + DEFAULT_DELAY;
}
}
};
void LLAvatarNameCache::processName(const LLUUID& agent_id,
const LLAvatarName& av_name,
bool add_to_cache)
{
if (add_to_cache)
{
sCache[agent_id] = av_name;
}
sPendingQueue.erase(agent_id);
// signal everyone waiting on this name
signal_map_t::iterator sig_it = sSignalMap.find(agent_id);
if (sig_it != sSignalMap.end())
{
callback_signal_t* signal = sig_it->second;
(*signal)(agent_id, av_name);
sSignalMap.erase(agent_id);
delete signal;
signal = NULL;
}
}
void LLAvatarNameCache::requestNamesViaCapability()
{
F64 now = LLFrameTimer::getTotalSeconds();
// URL format is like:
// http://pdp60.lindenlab.com:8000/agents/?ids=3941037e-78ab-45f0-b421-bd6e77c1804d&ids=0012809d-7d2d-4c24-9609-af1230a37715&ids=0019aaba-24af-4f0a-aa72-6457953cf7f0
//
// Apache can handle URLs of 4096 chars, but let's be conservative
const U32 NAME_URL_MAX = 4096;
const U32 NAME_URL_SEND_THRESHOLD = 3000;
std::string url;
url.reserve(NAME_URL_MAX);
std::vector<LLUUID> agent_ids;
agent_ids.reserve(128);
ask_queue_t::const_iterator it = sAskQueue.begin();
for ( ; it != sAskQueue.end(); ++it)
{
const LLUUID& agent_id = *it;
if (url.empty())
{
// ...starting new request
url += sNameLookupURL;
url += "?ids=";
}
else
{
// ...continuing existing request
url += "&ids=";
}
url += agent_id.asString();
agent_ids.push_back(agent_id);
// mark request as pending
sPendingQueue[agent_id] = now;
if (url.size() > NAME_URL_SEND_THRESHOLD)
{
//llinfos << "requestNames " << url << llendl;
LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids));
url.clear();
agent_ids.clear();
}
}
if (!url.empty())
{
//llinfos << "requestNames " << url << llendl;
LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids));
url.clear();
agent_ids.clear();
}
// We've moved all asks to the pending request queue
sAskQueue.clear();
}
void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id,
const std::string& full_name,
bool is_group)
{
// Construct a dummy record for this name. By convention, SLID is blank
// Never expires, but not written to disk, so lasts until end of session.
LLAvatarName av_name;
buildLegacyName(full_name, &av_name);
// Don't add to cache, the data already exists in the legacy name system
// cache and we don't want or need duplicate storage, because keeping the
// two copies in sync is complex.
processName(agent_id, av_name, false);
}
void LLAvatarNameCache::requestNamesViaLegacy()
{
F64 now = LLFrameTimer::getTotalSeconds();
std::string full_name;
ask_queue_t::const_iterator it = sAskQueue.begin();
for (; it != sAskQueue.end(); ++it)
{
const LLUUID& agent_id = *it;
// Mark as pending first, just in case the callback is immediately
// invoked below. This should never happen in practice.
sPendingQueue[agent_id] = now;
gCacheName->get(agent_id, false, // legacy compatibility
boost::bind(&LLAvatarNameCache::legacyNameCallback,
_1, _2, _3));
}
// We've either answered immediately or moved all asks to the
// pending queue
sAskQueue.clear();
}
void LLAvatarNameCache::initClass(bool running)
{
sRunning = running;
}
void LLAvatarNameCache::cleanupClass()
{
}
void LLAvatarNameCache::importFile(std::istream& istr)
{
LLSD data;
S32 parse_count = LLSDSerialize::fromXMLDocument(data, istr);
if (parse_count < 1) return;
// by convention LLSD storage is a map
// we only store one entry in the map
LLSD agents = data["agents"];
LLUUID agent_id;
LLAvatarName av_name;
LLSD::map_const_iterator it = agents.beginMap();
for ( ; it != agents.endMap(); ++it)
{
agent_id.set(it->first);
av_name.fromLLSD( it->second );
sCache[agent_id] = av_name;
}
// entries may have expired since we last ran the viewer, just
// clean them out now
eraseExpired();
llinfos << "loaded " << sCache.size() << llendl;
}
void LLAvatarNameCache::exportFile(std::ostream& ostr)
{
LLSD agents;
cache_t::const_iterator it = sCache.begin();
for ( ; it != sCache.end(); ++it)
{
const LLUUID& agent_id = it->first;
const LLAvatarName& av_name = it->second;
if (!av_name.mIsDummy)
{
// key must be a string
agents[agent_id.asString()] = av_name.asLLSD();
}
}
LLSD data;
data["agents"] = agents;
LLSDSerialize::toPrettyXML(data, ostr);
}
void LLAvatarNameCache::setNameLookupURL(const std::string& name_lookup_url)
{
sNameLookupURL = name_lookup_url;
}
bool LLAvatarNameCache::hasNameLookupURL()
{
return !sNameLookupURL.empty();
}
void LLAvatarNameCache::idle()
{
// By convention, start running at first idle() call
sRunning = true;
// *TODO: Possibly re-enabled this based on People API load measurements
// 100 ms is the threshold for "user speed" operations, so we can
// stall for about that long to batch up requests.
//const F32 SECS_BETWEEN_REQUESTS = 0.1f;
//if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS))
//{
// return;
//}
// Must be large relative to above
// No longer deleting expired entries, just re-requesting in the get
// this way first synchronous get call on an expired entry won't return
// legacy name. LF
//const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds
//if (sEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT))
//{
// eraseExpired();
//}
if (sAskQueue.empty())
{
return;
}
if (useDisplayNames())
{
requestNamesViaCapability();
}
else
{
// ...fall back to legacy name cache system
requestNamesViaLegacy();
}
}
bool LLAvatarNameCache::isRequestPending(const LLUUID& agent_id)
{
const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0;
F64 now = LLFrameTimer::getTotalSeconds();
F64 expire_time = now - PENDING_TIMEOUT_SECS;
pending_queue_t::const_iterator it = sPendingQueue.find(agent_id);
if (it != sPendingQueue.end())
{
bool request_expired = (it->second < expire_time);
return !request_expired;
}
return false;
}
void LLAvatarNameCache::eraseExpired()
{
F64 now = LLFrameTimer::getTotalSeconds();
cache_t::iterator it = sCache.begin();
while (it != sCache.end())
{
cache_t::iterator cur = it;
++it;
const LLAvatarName& av_name = cur->second;
if (av_name.mExpires < now)
{
sCache.erase(cur);
}
}
}
void LLAvatarNameCache::buildLegacyName(const std::string& full_name,
LLAvatarName* av_name)
{
llassert(av_name);
av_name->mUsername = "";
av_name->mDisplayName = full_name;
av_name->mIsDisplayNameDefault = true;
av_name->mIsDummy = true;
av_name->mExpires = F64_MAX;
}
// fills in av_name if it has it in the cache, even if expired (can check expiry time)
// returns bool specifying if av_name was filled, false otherwise
bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
{
if (sRunning)
{
// ...only do immediate lookups when cache is running
if (useDisplayNames())
{
// ...use display names cache
std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
if (it != sCache.end())
{
*av_name = it->second;
// re-request name if entry is expired
if (av_name->mExpires < LLFrameTimer::getTotalSeconds())
{
if (!isRequestPending(agent_id))
{
sAskQueue.insert(agent_id);
}
}
return true;
}
}
else
{
// ...use legacy names cache
std::string full_name;
if (gCacheName->getFullName(agent_id, full_name))
{
buildLegacyName(full_name, av_name);
return true;
}
}
}
if (!isRequestPending(agent_id))
{
sAskQueue.insert(agent_id);
}
return false;
}
void LLAvatarNameCache::fireSignal(const LLUUID& agent_id,
const callback_slot_t& slot,
const LLAvatarName& av_name)
{
callback_signal_t signal;
signal.connect(slot);
signal(agent_id, av_name);
}
void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot)
{
if (sRunning)
{
// ...only do immediate lookups when cache is running
if (useDisplayNames())
{
// ...use new cache
std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
if (it != sCache.end())
{
const LLAvatarName& av_name = it->second;
if (av_name.mExpires > LLFrameTimer::getTotalSeconds())
{
// ...name already exists in cache, fire callback now
fireSignal(agent_id, slot, av_name);
return;
}
}
}
else
{
// ...use old name system
std::string full_name;
if (gCacheName->getFullName(agent_id, full_name))
{
LLAvatarName av_name;
buildLegacyName(full_name, &av_name);
fireSignal(agent_id, slot, av_name);
return;
}
}
}
// schedule a request
if (!isRequestPending(agent_id))
{
sAskQueue.insert(agent_id);
}
// always store additional callback, even if request is pending
signal_map_t::iterator sig_it = sSignalMap.find(agent_id);
if (sig_it == sSignalMap.end())
{
// ...new callback for this id
callback_signal_t* signal = new callback_signal_t();
signal->connect(slot);
sSignalMap[agent_id] = signal;
}
else
{
// ...existing callback, bind additional slot
callback_signal_t* signal = sig_it->second;
signal->connect(slot);
}
}
void LLAvatarNameCache::setUseDisplayNames(bool use)
{
if (use != sUseDisplayNames)
{
sUseDisplayNames = use;
// flush our cache
sCache.clear();
mUseDisplayNamesSignal();
}
}
bool LLAvatarNameCache::useDisplayNames()
{
// Must be both manually set on and able to look up names.
return sUseDisplayNames && !sNameLookupURL.empty();
}
void LLAvatarNameCache::erase(const LLUUID& agent_id)
{
sCache.erase(agent_id);
}
void LLAvatarNameCache::fetch(const LLUUID& agent_id)
{
// re-request, even if request is already pending
sAskQueue.insert(agent_id);
}
void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_name)
{
// *TODO: update timestamp if zero?
sCache[agent_id] = av_name;
}
F64 LLAvatarNameCache::nameExpirationFromHeaders(LLSD headers)
{
F64 expires = 0.0;
if (expirationFromCacheControl(headers, &expires))
{
return expires;
}
else
{
// With no expiration info, default to an hour
const F64 DEFAULT_EXPIRES = 60.0 * 60.0;
F64 now = LLFrameTimer::getTotalSeconds();
return now + DEFAULT_EXPIRES;
}
}
bool LLAvatarNameCache::expirationFromCacheControl(LLSD headers, F64 *expires)
{
// Allow the header to override the default
LLSD cache_control_header = headers["cache-control"];
if (cache_control_header.isDefined())
{
S32 max_age = 0;
std::string cache_control = cache_control_header.asString();
if (max_age_from_cache_control(cache_control, &max_age))
{
F64 now = LLFrameTimer::getTotalSeconds();
*expires = now + (F64)max_age;
return true;
}
}
return false;
}
void LLAvatarNameCache::addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb)
{
mUseDisplayNamesSignal.connect(cb);
}
static const std::string MAX_AGE("max-age");
static const boost::char_separator<char> EQUALS_SEPARATOR("=");
static const boost::char_separator<char> COMMA_SEPARATOR(",");
bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age)
{
// Split the string on "," to get a list of directives
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
tokenizer directives(cache_control, COMMA_SEPARATOR);
tokenizer::iterator token_it = directives.begin();
for ( ; token_it != directives.end(); ++token_it)
{
// Tokens may have leading or trailing whitespace
std::string token = *token_it;
LLStringUtil::trim(token);
if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0)
{
// ...this token starts with max-age, so let's chop it up by "="
tokenizer subtokens(token, EQUALS_SEPARATOR);
tokenizer::iterator subtoken_it = subtokens.begin();
// Must have a token
if (subtoken_it == subtokens.end()) return false;
std::string subtoken = *subtoken_it;
// Must exactly equal "max-age"
LLStringUtil::trim(subtoken);
if (subtoken != MAX_AGE) return false;
// Must have another token
++subtoken_it;
if (subtoken_it == subtokens.end()) return false;
subtoken = *subtoken_it;
// Must be a valid integer
// *NOTE: atoi() returns 0 for invalid values, so we have to
// check the string first.
// *TODO: Do servers ever send "0000" for zero? We don't handle it
LLStringUtil::trim(subtoken);
if (subtoken == "0")
{
*max_age = 0;
return true;
}
S32 val = atoi( subtoken.c_str() );
if (val > 0 && val < S32_MAX)
{
*max_age = val;
return true;
}
return false;
}
}
return false;
}

View File

@ -0,0 +1,103 @@
/**
* @file llavatarnamecache.h
* @brief Provides lookup of avatar SLIDs ("bobsmith123") and display names
* ("James Cook") from avatar UUIDs.
*
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#ifndef LLAVATARNAMECACHE_H
#define LLAVATARNAMECACHE_H
#include "llavatarname.h" // for convenience
#include <boost/signals2.hpp>
class LLSD;
class LLUUID;
namespace LLAvatarNameCache
{
typedef boost::signals2::signal<void (void)> use_display_name_signal_t;
// Until the cache is set running, immediate lookups will fail and
// async lookups will be queued. This allows us to block requests
// until we know if the first region supports display names.
void initClass(bool running);
void cleanupClass();
void importFile(std::istream& istr);
void exportFile(std::ostream& ostr);
// On the viewer, usually a simulator capabilitity
// If empty, name cache will fall back to using legacy name
// lookup system
void setNameLookupURL(const std::string& name_lookup_url);
// Do we have a valid lookup URL, hence are we trying to use the
// new display name lookup system?
bool hasNameLookupURL();
// Periodically makes a batch request for display names not already in
// cache. Call once per frame.
void idle();
// If name is in cache, returns true and fills in provided LLAvatarName
// otherwise returns false
bool get(const LLUUID& agent_id, LLAvatarName *av_name);
// Callback types for get() below
typedef boost::signals2::signal<
void (const LLUUID& agent_id, const LLAvatarName& av_name)>
callback_signal_t;
typedef callback_signal_t::slot_type callback_slot_t;
// Fetches name information and calls callback.
// If name information is in cache, callback will be called immediately.
void get(const LLUUID& agent_id, callback_slot_t slot);
// Allow display names to be explicitly disabled for testing.
void setUseDisplayNames(bool use);
bool useDisplayNames();
void erase(const LLUUID& agent_id);
// Force a re-fetch of the most recent data, but keep the current
// data in cache
void fetch(const LLUUID& agent_id);
void insert(const LLUUID& agent_id, const LLAvatarName& av_name);
// Compute name expiration time from HTTP Cache-Control header,
// or return default value, in seconds from epoch.
F64 nameExpirationFromHeaders(LLSD headers);
void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb);
}
// Parse a cache-control header to get the max-age delta-seconds.
// Returns true if header has max-age param and it parses correctly.
// Exported here to ease unit testing.
bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age);
#endif

View File

@ -69,6 +69,8 @@ public:
public:
bool mIsGroup;
U32 mCreateTime; // unix time_t
// IDEVO TODO collapse names to one field, which will eliminate
// many string compares on "Resident"
std::string mFirstName;
std::string mLastName;
std::string mGroupName;
@ -214,7 +216,9 @@ public:
Impl(LLMessageSystem* msg);
~Impl();
BOOL getName(const LLUUID& id, std::string& first, std::string& last);
boost::signals2::connection addPending(const LLUUID& id, const LLCacheNameCallback& callback);
void addPending(const LLUUID& id, const LLHost& host);
@ -300,89 +304,10 @@ boost::signals2::connection LLCacheName::addObserver(const LLCacheNameCallback&
return impl.mSignal.connect(callback);
}
void LLCacheName::importFile(LLFILE* fp)
{
S32 count = 0;
const S32 BUFFER_SIZE = 1024;
char buffer[BUFFER_SIZE]; /*Flawfinder: ignore*/
// *NOTE: These buffer sizes are hardcoded into sscanf() below
char id_string[MAX_STRING]; /*Flawfinder: ignore*/
char firstname[MAX_STRING]; /*Flawfinder: ignore*/
char lastname[MAX_STRING]; /*Flawfinder: ignore*/
U32 create_time;
// This is OK if the first line is actually a name. We just don't load it.
char* valid = fgets(buffer, BUFFER_SIZE, fp);
if (!valid) return;
// *NOTE: This buffer size is hardcoded into sscanf() below
char version_string[BUFFER_SIZE]; /*Flawfinder: ignore*/
S32 version = 0;
S32 match = sscanf( /* Flawfinder: ignore */
buffer,
"%1023s %d",
version_string, &version);
if ( match != 2
|| strcmp(version_string, "version")
|| version != CN_FILE_VERSION)
{
llwarns << "Ignoring old cache name file format" << llendl;
return;
}
// We'll expire entries more than a week old
U32 now = (U32)time(NULL);
const U32 SECS_PER_DAY = 60 * 60 * 24;
U32 delete_before_time = now - (7 * SECS_PER_DAY);
while(!feof(fp))
{
valid = fgets(buffer, BUFFER_SIZE, fp);
if (!valid) break;
match = sscanf( /* Flawfinder: ignore */
buffer,
"%254s %u %254s %254s",
id_string,
&create_time,
firstname,
lastname);
if (4 != match) continue;
LLUUID id(id_string);
if (id.isNull()) continue;
// undo trivial XOR
S32 i;
for (i = 0; i < UUID_BYTES; i++)
{
id.mData[i] ^= 0x33;
}
// Don't load entries that are more than a week old
if (create_time < delete_before_time) continue;
LLCacheNameEntry* entry = new LLCacheNameEntry();
entry->mIsGroup = false;
entry->mCreateTime = create_time;
entry->mFirstName = firstname;
entry->mLastName = lastname;
impl.mCache[id] = entry;
std::string fullname = entry->mFirstName + " " + entry->mLastName;
impl.mReverseCache[fullname] = id;
count++;
}
llinfos << "LLCacheName loaded " << count << " names" << llendl;
}
bool LLCacheName::importFile(std::istream& istr)
{
LLSD data;
if(LLSDSerialize::fromXML(data, istr) < 1)
if(LLSDSerialize::fromXMLDocument(data, istr) < 1)
return false;
// We'll expire entries more than a week old
@ -408,7 +333,7 @@ bool LLCacheName::importFile(std::istream& istr)
entry->mFirstName = agent[FIRST].asString();
entry->mLastName = agent[LAST].asString();
impl.mCache[id] = entry;
std::string fullname = entry->mFirstName + " " + entry->mLastName;
std::string fullname = buildFullName(entry->mFirstName, entry->mLastName);
impl.mReverseCache[fullname] = id;
++count;
@ -457,6 +382,7 @@ void LLCacheName::exportFile(std::ostream& ostr)
// store it
LLUUID id = iter->first;
std::string id_str = id.asString();
// IDEVO TODO: Should we store SLIDs with last name "Resident" or not?
if(!entry->mFirstName.empty() && !entry->mLastName.empty())
{
data[AGENTS][id_str][FIRST] = entry->mFirstName;
@ -474,7 +400,7 @@ void LLCacheName::exportFile(std::ostream& ostr)
}
BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& last)
BOOL LLCacheName::Impl::getName(const LLUUID& id, std::string& first, std::string& last)
{
if(id.isNull())
{
@ -483,7 +409,7 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
return TRUE;
}
LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id );
LLCacheNameEntry* entry = get_ptr_in_map(mCache, id );
if (entry)
{
first = entry->mFirstName;
@ -494,16 +420,17 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las
{
first = sCacheName["waiting"];
last.clear();
if (!impl.isRequestPending(id))
if (!isRequestPending(id))
{
impl.mAskNameQueue.insert(id);
mAskNameQueue.insert(id);
}
return FALSE;
}
}
// static
void LLCacheName::LocalizeCacheName(std::string key, std::string value)
void LLCacheName::localizeCacheName(std::string key, std::string value)
{
if (key!="" && value!= "" )
sCacheName[key]=value;
@ -514,11 +441,13 @@ void LLCacheName::LocalizeCacheName(std::string key, std::string value)
BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname)
{
std::string first_name, last_name;
BOOL res = getName(id, first_name, last_name);
fullname = first_name + " " + last_name;
BOOL res = impl.getName(id, first_name, last_name);
fullname = buildFullName(first_name, last_name);
return res;
}
BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
{
if(id.isNull())
@ -555,13 +484,13 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
BOOL LLCacheName::getUUID(const std::string& first, const std::string& last, LLUUID& id)
{
std::string fullname = first + " " + last;
return getUUID(fullname, id);
std::string full_name = buildFullName(first, last);
return getUUID(full_name, id);
}
BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
BOOL LLCacheName::getUUID(const std::string& full_name, LLUUID& id)
{
ReverseCache::iterator iter = impl.mReverseCache.find(fullname);
ReverseCache::iterator iter = impl.mReverseCache.find(full_name);
if (iter != impl.mReverseCache.end())
{
id = iter->second;
@ -573,6 +502,55 @@ BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
}
}
//static
std::string LLCacheName::buildFullName(const std::string& first, const std::string& last)
{
std::string fullname = first;
if (!last.empty()
&& last != "Resident")
{
fullname += ' ';
fullname += last;
}
return fullname;
}
//static
std::string LLCacheName::cleanFullName(const std::string& full_name)
{
return full_name.substr(0, full_name.find(" Resident"));
}
//static
std::string LLCacheName::buildUsername(const std::string& full_name)
{
// rare, but handle hard-coded error names returned from server
if (full_name == "(\?\?\?) (\?\?\?)")
{
return "(\?\?\?)";
}
std::string::size_type index = full_name.find(' ');
if (index != std::string::npos)
{
std::string username;
username = full_name.substr(0, index);
std::string lastname = full_name.substr(index+1);
if (lastname != "Resident")
{
username = username + "." + lastname;
}
LLStringUtil::toLower(username);
return username;
}
// if the input wasn't a correctly formatted legacy name just return it unchanged
return full_name;
}
// This is a little bit kludgy. LLCacheNameCallback is a slot instead of a function pointer.
// The reason it is a slot is so that the legacy get() function below can bind an old callback
// and pass it as a slot. The reason it isn't a boost::function is so that trackable behavior
@ -580,7 +558,7 @@ BOOL LLCacheName::getUUID(const std::string& fullname, LLUUID& id)
// we call it immediately. -Steve
// NOTE: Even though passing first and last name is a bit of extra overhead, it eliminates the
// potential need for any parsing should any code need to handle first and last name independently.
boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback)
boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback)
{
boost::signals2::connection res;
@ -588,7 +566,7 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
{
LLCacheNameSignal signal;
signal.connect(callback);
signal(id, sCacheName["nobody"], "", is_group);
signal(id, sCacheName["nobody"], is_group);
return res;
}
@ -600,11 +578,13 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
// id found in map therefore we can call the callback immediately.
if (entry->mIsGroup)
{
signal(id, entry->mGroupName, "", entry->mIsGroup);
signal(id, entry->mGroupName, entry->mIsGroup);
}
else
{
signal(id, entry->mFirstName, entry->mLastName, entry->mIsGroup);
std::string fullname =
buildFullName(entry->mFirstName, entry->mLastName);
signal(id, fullname, entry->mIsGroup);
}
}
else
@ -626,9 +606,15 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, co
return res;
}
boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data)
boost::signals2::connection LLCacheName::getGroup(const LLUUID& group_id,
const LLCacheNameCallback& callback)
{
return get(id, is_group, boost::bind(callback, _1, _2, _3, _4, user_data));
return get(group_id, true, callback);
}
boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, old_callback_t callback, void* user_data)
{
return get(id, is_group, boost::bind(callback, _1, _2, _3, user_data));
}
void LLCacheName::processPending()
@ -700,7 +686,7 @@ void LLCacheName::dump()
{
llinfos
<< iter->first << " = "
<< entry->mFirstName << " " << entry->mLastName
<< buildFullName(entry->mFirstName, entry->mLastName)
<< " @ " << entry->mCreateTime
<< llendl;
}
@ -719,12 +705,24 @@ void LLCacheName::dumpStats()
<< llendl;
}
void LLCacheName::clear()
{
for_each(impl.mCache.begin(), impl.mCache.end(), DeletePairedPointer());
impl.mCache.clear();
}
//static
std::string LLCacheName::getDefaultName()
{
return sCacheName["waiting"];
}
//static
std::string LLCacheName::getDefaultLastName()
{
return "Resident";
}
void LLCacheName::Impl::processPendingAsks()
{
LLMemType mt_ppa(LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS);
@ -746,11 +744,13 @@ void LLCacheName::Impl::processPendingReplies()
if (!entry->mIsGroup)
{
(reply->mSignal)(reply->mID, entry->mFirstName, entry->mLastName, FALSE);
std::string fullname =
LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
(reply->mSignal)(reply->mID, fullname, false);
}
else
{
(reply->mSignal)(reply->mID, entry->mGroupName, "", TRUE);
(reply->mSignal)(reply->mID, entry->mGroupName, true);
}
}
@ -921,13 +921,27 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)
if (!isGroup)
{
mSignal(id, entry->mFirstName, entry->mLastName, FALSE);
std::string fullname = entry->mFirstName + " " + entry->mLastName;
mReverseCache[fullname] = id;
// NOTE: Very occasionally the server sends down a full name
// in the first name field with an empty last name, for example,
// first = "Ladanie1 Resident", last = "".
// I cannot reproduce this, nor can I find a bug in the server code.
// Ensure "Resident" does not appear via cleanFullName, because
// buildFullName only checks last name. JC
std::string full_name;
if (entry->mLastName.empty())
{
full_name = cleanFullName(entry->mFirstName);
}
else
{
full_name = LLCacheName::buildFullName(entry->mFirstName, entry->mLastName);
}
mSignal(id, full_name, false);
mReverseCache[full_name] = id;
}
else
{
mSignal(id, entry->mGroupName, "", TRUE);
mSignal(id, entry->mGroupName, true);
mReverseCache[entry->mGroupName] = id;
}
}
@ -956,4 +970,3 @@ void LLCacheName::Impl::handleUUIDGroupNameReply(LLMessageSystem* msg, void** us
{
((LLCacheName::Impl*)userData)->processUUIDReply(msg, true);
}

View File

@ -36,13 +36,12 @@ class LLUUID;
typedef boost::signals2::signal<void (const LLUUID& id,
const std::string& first_name,
const std::string& last_name,
BOOL is_group)> LLCacheNameSignal;
const std::string& name,
bool is_group)> LLCacheNameSignal;
typedef LLCacheNameSignal::slot_type LLCacheNameCallback;
// Old callback with user data for compatability
typedef void (*old_callback_t)(const LLUUID&, const std::string&, const std::string&, BOOL, void*);
typedef void (*old_callback_t)(const LLUUID&, const std::string&, bool, void*);
// Here's the theory:
// If you request a name that isn't in the cache, it returns "waiting"
@ -65,24 +64,31 @@ public:
boost::signals2::connection addObserver(const LLCacheNameCallback& callback);
// janky old format. Remove after a while. Phoenix. 2008-01-30
void importFile(LLFILE* fp);
// storing cache on disk; for viewer, in name.cache
bool importFile(std::istream& istr);
void exportFile(std::ostream& ostr);
// If available, copies the first and last name into the strings provided.
// first must be at least DB_FIRST_NAME_BUF_SIZE characters.
// last must be at least DB_LAST_NAME_BUF_SIZE characters.
// If available, copies name ("bobsmith123" or "James Linden") into string
// If not available, copies the string "waiting".
// Returns TRUE iff available.
BOOL getName(const LLUUID& id, std::string& first, std::string& last);
BOOL getFullName(const LLUUID& id, std::string& fullname);
BOOL getFullName(const LLUUID& id, std::string& full_name);
// Reverse lookup of UUID from name
BOOL getUUID(const std::string& first, const std::string& last, LLUUID& id);
BOOL getUUID(const std::string& fullname, LLUUID& id);
// IDEVO Temporary code
// Clean up new-style "bobsmith123 Resident" names to "bobsmith123" for display
static std::string buildFullName(const std::string& first, const std::string& last);
// Clean up legacy "bobsmith123 Resident" to "bobsmith123"
// If name does not contain "Resident" returns it unchanged.
static std::string cleanFullName(const std::string& full_name);
// Converts a standard legacy name to a username
// "bobsmith123 Resident" -> "bobsmith"
// "Random Linden" -> "random.linden"
static std::string buildUsername(const std::string& name);
// If available, this method copies the group name into the string
// provided. The caller must allocate at least
@ -94,10 +100,15 @@ public:
// If the data is currently available, may call the callback immediatly
// otherwise, will request the data, and will call the callback when
// available. There is no garuntee the callback will ever be called.
boost::signals2::connection get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback);
boost::signals2::connection get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback);
// Convenience method for looking up a group name, so you can
// tell the difference between avatar lookup and group lookup
// in global searches
boost::signals2::connection getGroup(const LLUUID& group_id, const LLCacheNameCallback& callback);
// LEGACY
boost::signals2::connection get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data);
boost::signals2::connection get(const LLUUID& id, bool is_group, old_callback_t callback, void* user_data);
// This method needs to be called from time to time to send out
// requests.
void processPending();
@ -108,9 +119,15 @@ public:
// Debugging
void dump(); // Dumps the contents of the cache
void dumpStats(); // Dumps the sizes of the cache and associated queues.
void clear(); // Deletes all entries from the cache
static std::string getDefaultName();
static void LocalizeCacheName(std::string key, std::string value);
// Returns "Resident", the default last name for SLID-based accounts
// that have no last name.
static std::string getDefaultLastName();
static void localizeCacheName(std::string key, std::string value);
static std::map<std::string, std::string> sCacheName;
private:

View File

@ -55,7 +55,7 @@ public:
LLMeanCollisionData(LLMeanCollisionData *mcd)
: mVictim(mcd->mVictim), mPerp(mcd->mPerp), mTime(mcd->mTime), mType(mcd->mType), mMag(mcd->mMag),
mFirstName(mcd->mFirstName), mLastName(mcd->mLastName)
mFullName(mcd->mFullName)
{
}
@ -89,8 +89,7 @@ public:
time_t mTime;
EMeanCollisionType mType;
F32 mMag;
std::string mFirstName;
std::string mLastName;
std::string mFullName;
};

View File

@ -0,0 +1,102 @@
/**
* @file llavatarnamecache_test.cpp
* @author James Cook
* @brief LLAvatarNameCache test cases.
*
* $LicenseInfo:firstyear=2010&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../llavatarnamecache.h"
#include "../test/lltut.h"
namespace tut
{
struct avatarnamecache_data
{
};
typedef test_group<avatarnamecache_data> avatarnamecache_test;
typedef avatarnamecache_test::object avatarnamecache_object;
tut::avatarnamecache_test avatarnamecache_testcase("LLAvatarNameCache");
template<> template<>
void avatarnamecache_object::test<1>()
{
bool valid = false;
S32 max_age = 0;
valid = max_age_from_cache_control("max-age=3600", &max_age);
ensure("typical input valid", valid);
ensure_equals("typical input parsed", max_age, 3600);
valid = max_age_from_cache_control(
" max-age=600 , no-cache,private=\"stuff\" ", &max_age);
ensure("complex input valid", valid);
ensure_equals("complex input parsed", max_age, 600);
valid = max_age_from_cache_control(
"no-cache, max-age = 123 ", &max_age);
ensure("complex input 2 valid", valid);
ensure_equals("complex input 2 parsed", max_age, 123);
}
template<> template<>
void avatarnamecache_object::test<2>()
{
bool valid = false;
S32 max_age = -1;
valid = max_age_from_cache_control("", &max_age);
ensure("empty input returns invalid", !valid);
ensure_equals("empty input doesn't change val", max_age, -1);
valid = max_age_from_cache_control("no-cache", &max_age);
ensure("no max-age field returns invalid", !valid);
valid = max_age_from_cache_control("max", &max_age);
ensure("just 'max' returns invalid", !valid);
valid = max_age_from_cache_control("max-age", &max_age);
ensure("partial max-age is invalid", !valid);
valid = max_age_from_cache_control("max-age=", &max_age);
ensure("longer partial max-age is invalid", !valid);
valid = max_age_from_cache_control("max-age=FOO", &max_age);
ensure("invalid integer max-age is invalid", !valid);
valid = max_age_from_cache_control("max-age 234", &max_age);
ensure("space separated max-age is invalid", !valid);
valid = max_age_from_cache_control("max-age=0", &max_age);
ensure("zero max-age is valid", valid);
// *TODO: Handle "0000" as zero
//valid = max_age_from_cache_control("max-age=0000", &max_age);
//ensure("multi-zero max-age is valid", valid);
valid = max_age_from_cache_control("max-age=-123", &max_age);
ensure("less than zero max-age is invalid", !valid);
}
}

View File

@ -51,6 +51,14 @@ set(llplugin_HEADER_FILES
set_source_files_properties(${llplugin_HEADER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE)
if(NOT WORD_SIZE EQUAL 32)
if(WINDOWS)
add_definitions(/FIXED:NO)
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif(WINDOWS)
endif(NOT WORD_SIZE EQUAL 32)
list(APPEND llplugin_SOURCE_FILES ${llplugin_HEADER_FILES})
add_library (llplugin ${llplugin_SOURCE_FILES})

View File

@ -79,4 +79,6 @@ if (DARWIN)
)
endif (DARWIN)
ll_deploy_sharedlibs_command(SLPlugin)
if (LL_TESTS)
ll_deploy_sharedlibs_command(SLPlugin)
endif (LL_TESTS)

View File

@ -281,7 +281,7 @@ int main(int argc, char **argv)
}
// Check for a change in this process's frontmost window.
if(ActiveNonFloatingWindow() != front_window)
if(GetFrontWindowOfClass(kAllWindowClasses, true) != front_window)
{
ProcessSerialNumber self = { 0, kCurrentProcess };
ProcessSerialNumber parent = { 0, kNoProcess };
@ -307,7 +307,7 @@ int main(int argc, char **argv)
}
}
if((ActiveNonFloatingWindow() != NULL) && (front_window == NULL))
if((GetFrontWindowOfClass(kAllWindowClasses, true) != NULL) && (front_window == NULL))
{
// Opening the first window
@ -319,7 +319,7 @@ int main(int argc, char **argv)
if(layer_group)
{
SetWindowGroup(ActiveNonFloatingWindow(), layer_group);
SetWindowGroup(GetFrontWindowOfClass(kAllWindowClasses, true), layer_group);
}
if(parent_is_front_process)
@ -328,9 +328,9 @@ int main(int argc, char **argv)
(void) SetFrontProcess( &self );
}
ActivateWindow(ActiveNonFloatingWindow(), true);
ActivateWindow(GetFrontWindowOfClass(kAllWindowClasses, true), true);
}
else if((ActiveNonFloatingWindow() == NULL) && (front_window != NULL))
else if((GetFrontWindowOfClass(kAllWindowClasses, true) == NULL) && (front_window != NULL))
{
// Closing the last window
@ -350,7 +350,7 @@ int main(int argc, char **argv)
window_hack_state = 2;
}
front_window = ActiveNonFloatingWindow();
front_window = GetFrontWindowOfClass(kAllWindowClasses, true);
}
}

View File

@ -141,6 +141,7 @@ LLAccordionCtrlTab::LLAccordionCtrlTabHeader::LLAccordionCtrlTabHeader(
textboxParams.use_ellipses = true;
textboxParams.bg_visible = false;
textboxParams.mouse_opaque = false;
textboxParams.parse_urls = false;
mHeaderTextbox = LLUICtrlFactory::create<LLTextBox>(textboxParams);
addChild(mHeaderTextbox);
}
@ -735,6 +736,12 @@ S32 LLAccordionCtrlTab::notifyParent(const LLSD& info)
return 1;
}
if (!getDisplayChildren())
{
// Don't pass scrolling event further if our contents are invisible (STORM-298).
return 1;
}
}
return LLUICtrl::notifyParent(info);

View File

@ -499,7 +499,7 @@ void LLButton::onMouseEnter(S32 x, S32 y, MASK mask)
if (isInEnabledChain())
mNeedsHighlight = TRUE;
}
}
void LLButton::onMouseLeave(S32 x, S32 y, MASK mask)
{

View File

@ -52,8 +52,6 @@
#include "lltooltip.h"
// Globals
S32 LLCOMBOBOX_HEIGHT = 0;
S32 LLCOMBOBOX_WIDTH = 0;
S32 MAX_COMBO_WIDTH = 500;
static LLDefaultChildRegistry::Register<LLComboBox> register_combo_box("combo_box");
@ -486,7 +484,7 @@ void LLComboBox::createLineEditor(const LLComboBox::Params& p)
LLLineEditor::Params params = p.combo_editor;
params.rect(text_entry_rect);
params.default_text(LLStringUtil::null);
params.max_length_bytes(mMaxChars);
params.max_length.bytes(mMaxChars);
params.commit_callback.function(boost::bind(&LLComboBox::onTextCommit, this, _2));
params.keystroke_callback(boost::bind(&LLComboBox::onTextEntry, this, _1));
params.commit_on_focus_lost(false);
@ -705,10 +703,10 @@ void LLComboBox::onItemSelected(const LLSD& data)
setLabel(getSelectedItemLabel());
if (mAllowTextEntry)
{
gFocusMgr.setKeyboardFocus(mTextEntry);
mTextEntry->selectAll();
}
{
gFocusMgr.setKeyboardFocus(mTextEntry);
mTextEntry->selectAll();
}
}
// hiding the list reasserts the old value stored in the text editor/dropdown button
hideList();

View File

@ -43,9 +43,6 @@
class LLFontGL;
class LLViewBorder;
extern S32 LLCOMBOBOX_HEIGHT;
extern S32 LLCOMBOBOX_WIDTH;
class LLComboBox
: public LLUICtrl, public LLCtrlListInterface
{
@ -224,8 +221,8 @@ private:
commit_callback_t mPrearrangeCallback;
commit_callback_t mTextEntryCallback;
commit_callback_t mSelectionCallback;
boost::signals2::connection mTopLostSignalConnection;
S32 mLastSelectedIndex;
boost::signals2::connection mTopLostSignalConnection;
S32 mLastSelectedIndex;
};
// A combo box with icons for the list of items.

View File

@ -232,7 +232,8 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
mTornOff(false),
mHasBeenDraggedWhileMinimized(FALSE),
mPreviousMinimizedBottom(0),
mPreviousMinimizedLeft(0)
mPreviousMinimizedLeft(0),
mMinimizeSignal(NULL)
// mNotificationContext(NULL)
{
mHandle.bind(this);
@ -494,6 +495,8 @@ LLFloater::~LLFloater()
setVisible(false); // We're not visible if we're destroyed
storeVisibilityControl();
storeDockStateControl();
delete mMinimizeSignal;
}
void LLFloater::storeRectControl()
@ -998,6 +1001,11 @@ void LLFloater::setMinimized(BOOL minimize)
if (minimize == mMinimized) return;
if(mMinimizeSignal)
{
(*mMinimizeSignal)(this, LLSD(minimize));
}
if (minimize)
{
// minimized flag should be turned on before release focus
@ -2811,6 +2819,12 @@ void LLFloater::initFromParams(const LLFloater::Params& p)
}
}
boost::signals2::connection LLFloater::setMinimizeCallback( const commit_signal_t::slot_type& cb )
{
if (!mMinimizeSignal) mMinimizeSignal = new commit_signal_t();
return mMinimizeSignal->connect(cb);
}
LLFastTimer::DeclareTimer POST_BUILD("Floater Post Build");
bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node)

View File

@ -143,6 +143,8 @@ public:
static void setupParamsForExport(Params& p, LLView* parent);
bool buildFromFile(const std::string &filename, LLXMLNodePtr output_node = NULL);
boost::signals2::connection setMinimizeCallback( const commit_signal_t::slot_type& cb );
void initFromParams(const LLFloater::Params& p);
bool initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node = NULL);
@ -348,6 +350,8 @@ public:
// Public so external views or floaters can watch for this floater closing
commit_signal_t mCloseSignal;
commit_signal_t* mMinimizeSignal;
protected:
std::string mRectControl;
std::string mVisibilityControl;

View File

@ -78,7 +78,7 @@ template class LLLineEditor* LLView::getChild<class LLLineEditor>(
//
LLLineEditor::Params::Params()
: max_length_bytes("max_length", 254),
: max_length(""),
keystroke_callback("keystroke_callback"),
prevalidate_callback("prevalidate_callback"),
background_image("background_image"),
@ -108,7 +108,8 @@ LLLineEditor::Params::Params()
LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
: LLUICtrl(p),
mMaxLengthBytes(p.max_length_bytes),
mMaxLengthBytes(p.max_length.bytes),
mMaxLengthChars(p.max_length.chars),
mCursorPos( 0 ),
mScrollHPos( 0 ),
mTextPadLeft(p.text_pad_left),
@ -313,6 +314,12 @@ void LLLineEditor::setMaxTextLength(S32 max_text_length)
mMaxLengthBytes = max_len;
}
void LLLineEditor::setMaxTextChars(S32 max_text_chars)
{
S32 max_chars = llmax(0, max_text_chars);
mMaxLengthChars = max_chars;
}
void LLLineEditor::getTextPadding(S32 *left, S32 *right)
{
*left = mTextPadLeft;
@ -358,6 +365,16 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)
}
mText.assign(truncated_utf8);
if (mMaxLengthChars)
{
LLWString truncated_wstring = utf8str_to_wstring(truncated_utf8);
if (truncated_wstring.size() > (U32)mMaxLengthChars)
{
truncated_wstring = truncated_wstring.substr(0, mMaxLengthChars);
}
mText.assign(wstring_to_utf8str(truncated_wstring));
}
if (all_selected)
{
// ...keep whole thing selected
@ -802,6 +819,7 @@ void LLLineEditor::addChar(const llwchar uni_char)
}
S32 cur_bytes = mText.getString().size();
S32 new_bytes = wchar_utf8_length(new_c);
BOOL allow_char = TRUE;
@ -811,6 +829,14 @@ void LLLineEditor::addChar(const llwchar uni_char)
{
allow_char = FALSE;
}
else if (mMaxLengthChars)
{
S32 wide_chars = mText.getWString().size();
if ((wide_chars + 1) > mMaxLengthChars)
{
allow_char = FALSE;
}
}
if (allow_char)
{
@ -1111,7 +1137,19 @@ void LLLineEditor::pasteHelper(bool is_primary)
clean_string = clean_string.substr(0, wchars_that_fit);
LLUI::reportBadKeystroke();
}
if (mMaxLengthChars)
{
U32 available_chars = mMaxLengthChars - mText.getWString().size();
if (available_chars < clean_string.size())
{
clean_string = clean_string.substr(0, available_chars);
}
LLUI::reportBadKeystroke();
}
mText.insert(getCursor(), clean_string);
setCursor( getCursor() + (S32)clean_string.length() );
deselect();

View File

@ -59,11 +59,19 @@ public:
typedef boost::function<void (LLLineEditor* caller)> keystroke_callback_t;
struct MaxLength : public LLInitParam::Choice<MaxLength>
{
Alternative<S32> bytes, chars;
MaxLength() : bytes("max_length_bytes", 254),
chars("max_length_chars", 0)
{}
};
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
Optional<std::string> default_text;
Optional<S32> max_length_bytes;
Optional<MaxLength> max_length;
Optional<keystroke_callback_t> keystroke_callback;
Optional<LLTextValidate::validate_func_t, LLTextValidate::ValidateTextNamedFuncs> prevalidate_callback;
@ -214,6 +222,7 @@ public:
void setKeystrokeCallback(callback_t callback, void* user_data);
void setMaxTextLength(S32 max_text_length);
void setMaxTextChars(S32 max_text_chars);
// Manipulate left and right padding for text
void getTextPadding(S32 *left, S32 *right);
void setTextPadding(S32 left, S32 right);
@ -277,6 +286,7 @@ protected:
LLViewBorder* mBorder;
const LLFontGL* mGLFont;
S32 mMaxLengthBytes; // Max length of the UTF8 string in bytes
S32 mMaxLengthChars; // Maximum number of characters in the string
S32 mCursorPos; // I-beam is just after the mCursorPos-th character.
S32 mScrollHPos; // Horizontal offset from the start of mText. Used for scrolling.
LLFrameTimer mScrollTimer;

View File

@ -1848,89 +1848,104 @@ BOOL LLMenuGL::isOpen()
}
}
void LLMenuGL::scrollItemsUp()
bool LLMenuGL::scrollItems(EScrollingDirection direction)
{
// Slowing down the items scrolling when arrow button is held
// Slowing down items scrolling when arrow button is held
if (mScrollItemsTimer.hasExpired() && NULL != mFirstVisibleItem)
{
mScrollItemsTimer.setTimerExpirySec(.033f);
}
else
{
return;
return false;
}
item_list_t::iterator cur_item_iter;
item_list_t::iterator prev_item_iter;
for (cur_item_iter = mItems.begin(), prev_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++)
switch (direction)
{
if( (*cur_item_iter) == mFirstVisibleItem)
case SD_UP:
{
item_list_t::iterator cur_item_iter;
item_list_t::iterator prev_item_iter;
for (cur_item_iter = mItems.begin(), prev_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++)
{
break;
if( (*cur_item_iter) == mFirstVisibleItem)
{
break;
}
if ((*cur_item_iter)->getVisible())
{
prev_item_iter = cur_item_iter;
}
}
if ((*cur_item_iter)->getVisible())
if ((*prev_item_iter)->getVisible())
{
prev_item_iter = cur_item_iter;
mFirstVisibleItem = *prev_item_iter;
}
break;
}
if ((*prev_item_iter)->getVisible())
case SD_DOWN:
{
mFirstVisibleItem = *prev_item_iter;
}
mNeedsArrange = TRUE;
arrangeAndClear();
}
void LLMenuGL::scrollItemsDown()
{
// Slowing down the items scrolling when arrow button is held
if (mScrollItemsTimer.hasExpired())
{
mScrollItemsTimer.setTimerExpirySec(.033f);
}
else
{
return;
}
if (NULL == mFirstVisibleItem)
{
mFirstVisibleItem = *mItems.begin();
}
item_list_t::iterator cur_item_iter;
for (cur_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++)
{
if( (*cur_item_iter) == mFirstVisibleItem)
if (NULL == mFirstVisibleItem)
{
break;
mFirstVisibleItem = *mItems.begin();
}
}
item_list_t::iterator next_item_iter;
item_list_t::iterator cur_item_iter;
if (cur_item_iter != mItems.end())
{
for (next_item_iter = ++cur_item_iter; next_item_iter != mItems.end(); next_item_iter++)
for (cur_item_iter = mItems.begin(); cur_item_iter != mItems.end(); cur_item_iter++)
{
if( (*next_item_iter)->getVisible())
if( (*cur_item_iter) == mFirstVisibleItem)
{
break;
}
}
if (next_item_iter != mItems.end() &&
(*next_item_iter)->getVisible())
item_list_t::iterator next_item_iter;
if (cur_item_iter != mItems.end())
{
mFirstVisibleItem = *next_item_iter;
for (next_item_iter = ++cur_item_iter; next_item_iter != mItems.end(); next_item_iter++)
{
if( (*next_item_iter)->getVisible())
{
break;
}
}
if (next_item_iter != mItems.end() &&
(*next_item_iter)->getVisible())
{
mFirstVisibleItem = *next_item_iter;
}
}
break;
}
case SD_BEGIN:
{
mFirstVisibleItem = *mItems.begin();
break;
}
case SD_END:
{
item_list_t::reverse_iterator first_visible_item_iter = mItems.rend();
// Advance by mMaxScrollableItems back from the end of the list
// to make the last item visible.
std::advance(first_visible_item_iter, mMaxScrollableItems);
mFirstVisibleItem = *first_visible_item_iter;
break;
}
default:
llwarns << "Unknown scrolling direction: " << direction << llendl;
}
mNeedsArrange = TRUE;
arrangeAndClear();
return true;
}
// rearrange the child rects so they fit the shape of the menu.
@ -2162,7 +2177,7 @@ void LLMenuGL::arrange( void )
LLMenuScrollItem::Params item_params;
item_params.name(ARROW_UP);
item_params.arrow_type(LLMenuScrollItem::ARROW_UP);
item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItemsUp, this));
item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItems, this, SD_UP));
mArrowUpItem = LLUICtrlFactory::create<LLMenuScrollItem>(item_params);
LLUICtrl::addChild(mArrowUpItem);
@ -2173,7 +2188,7 @@ void LLMenuGL::arrange( void )
LLMenuScrollItem::Params item_params;
item_params.name(ARROW_DOWN);
item_params.arrow_type(LLMenuScrollItem::ARROW_DOWN);
item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItemsDown, this));
item_params.scroll_callback.function(boost::bind(&LLMenuGL::scrollItems, this, SD_DOWN));
mArrowDownItem = LLUICtrlFactory::create<LLMenuScrollItem>(item_params);
LLUICtrl::addChild(mArrowDownItem);
@ -2603,14 +2618,8 @@ LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disa
((LLFloater*)getParent())->setFocus(TRUE);
}
item_list_t::iterator cur_item_iter;
for (cur_item_iter = mItems.begin(); cur_item_iter != mItems.end(); ++cur_item_iter)
{
if( (*cur_item_iter) == cur_item)
{
break;
}
}
// Current item position in the items list
item_list_t::iterator cur_item_iter = std::find(mItems.begin(), mItems.end(), cur_item);
item_list_t::iterator next_item_iter;
if (cur_item_iter == mItems.end())
@ -2621,9 +2630,37 @@ LLMenuItemGL* LLMenuGL::highlightNextItem(LLMenuItemGL* cur_item, BOOL skip_disa
{
next_item_iter = cur_item_iter;
next_item_iter++;
// First visible item position in the items list
item_list_t::iterator first_visible_item_iter = std::find(mItems.begin(), mItems.end(), mFirstVisibleItem);
if (next_item_iter == mItems.end())
{
next_item_iter = mItems.begin();
// If current item is the last in the list, the menu is scrolled to the beginning
// and the first item is highlighted.
if (mScrollable && !scrollItems(SD_BEGIN))
{
return NULL;
}
}
// If current item is the last visible, the menu is scrolled one item down
// and the next item is highlighted.
else if (mScrollable &&
(U32)std::abs(std::distance(first_visible_item_iter, next_item_iter)) >= mMaxScrollableItems)
{
// Call highlightNextItem() recursively only if the menu was successfully scrolled down.
// If scroll timer hasn't expired yet the menu won't be scrolled and calling
// highlightNextItem() will result in an endless recursion.
if (scrollItems(SD_DOWN))
{
return highlightNextItem(cur_item, skip_disabled);
}
else
{
return NULL;
}
}
}
@ -2681,14 +2718,8 @@ LLMenuItemGL* LLMenuGL::highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disa
((LLFloater*)getParent())->setFocus(TRUE);
}
item_list_t::reverse_iterator cur_item_iter;
for (cur_item_iter = mItems.rbegin(); cur_item_iter != mItems.rend(); ++cur_item_iter)
{
if( (*cur_item_iter) == cur_item)
{
break;
}
}
// Current item reverse position from the end of the list
item_list_t::reverse_iterator cur_item_iter = std::find(mItems.rbegin(), mItems.rend(), cur_item);
item_list_t::reverse_iterator prev_item_iter;
if (cur_item_iter == mItems.rend())
@ -2699,9 +2730,37 @@ LLMenuItemGL* LLMenuGL::highlightPrevItem(LLMenuItemGL* cur_item, BOOL skip_disa
{
prev_item_iter = cur_item_iter;
prev_item_iter++;
// First visible item reverse position in the items list
item_list_t::reverse_iterator first_visible_item_iter = std::find(mItems.rbegin(), mItems.rend(), mFirstVisibleItem);
if (prev_item_iter == mItems.rend())
{
prev_item_iter = mItems.rbegin();
// If current item is the first in the list, the menu is scrolled to the end
// and the last item is highlighted.
if (mScrollable && !scrollItems(SD_END))
{
return NULL;
}
}
// If current item is the first visible, the menu is scrolled one item up
// and the previous item is highlighted.
else if (mScrollable &&
std::distance(first_visible_item_iter, cur_item_iter) <= 0)
{
// Call highlightNextItem() only if the menu was successfully scrolled up.
// If scroll timer hasn't expired yet the menu won't be scrolled and calling
// highlightNextItem() will result in an endless recursion.
if (scrollItems(SD_UP))
{
return highlightPrevItem(cur_item, skip_disabled);
}
else
{
return NULL;
}
}
}
@ -2872,12 +2931,12 @@ BOOL LLMenuGL::handleScrollWheel( S32 x, S32 y, S32 clicks )
if( clicks > 0 )
{
while( clicks-- )
scrollItemsDown();
scrollItems(SD_DOWN);
}
else
{
while( clicks++ )
scrollItemsUp();
scrollItems(SD_UP);
}
return TRUE;

View File

@ -397,6 +397,15 @@ public:
static const std::string ARROW_UP;
static const std::string ARROW_DOWN;
// for scrollable menus
typedef enum e_scrolling_direction
{
SD_UP = 0,
SD_DOWN = 1,
SD_BEGIN = 2,
SD_END = 3
} EScrollingDirection;
protected:
LLMenuGL(const LLMenuGL::Params& p);
friend class LLUICtrlFactory;
@ -503,8 +512,7 @@ public:
S32 getShortcutPad() { return mShortcutPad; }
void scrollItemsUp();
void scrollItemsDown();
bool scrollItems(EScrollingDirection direction);
BOOL isScrollable() const { return mScrollable; }
static class LLMenuHolderGL* sMenuContainer;

View File

@ -130,7 +130,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const LLMultiSliderCtrl::Params& p)
params.name("MultiSliderCtrl Editor");
params.rect(text_rect);
params.font(p.font);
params.max_length_bytes(MAX_STRING_LENGTH);
params.max_length.bytes(MAX_STRING_LENGTH);
params.commit_callback.function(LLMultiSliderCtrl::onEditorCommit);
params.prevalidate_callback(&LLTextValidate::validateFloat);
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);

View File

@ -29,7 +29,9 @@
#include "llnotifications.h"
#include "llnotificationtemplate.h"
#include "llavatarnamecache.h"
#include "llinstantmessage.h"
#include "llcachename.h"
#include "llxmlnode.h"
#include "lluictrl.h"
#include "lluictrlfactory.h"
@ -79,7 +81,9 @@ LLNotificationForm::FormButton::FormButton()
LLNotificationForm::FormInput::FormInput()
: type("type"),
width("width", 0)
max_length_chars("max_length_chars"),
width("width", 0),
value("value")
{}
LLNotificationForm::FormElement::FormElement()
@ -1060,12 +1064,12 @@ std::string LLNotificationChannel::summarize()
// LLNotifications implementation
// ---
LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFilters::includeEverything,
LLNotificationComparators::orderByUUID()),
mIgnoreAllNotifications(false)
LLNotificationComparators::orderByUUID()),
mIgnoreAllNotifications(false)
{
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));
mListener.reset(new LLNotificationsListener(*this));
mListener.reset(new LLNotificationsListener(*this));
}
@ -1552,17 +1556,50 @@ std::ostream& operator<<(std::ostream& s, const LLNotification& notification)
return s;
}
void LLPostponedNotification::onCachedNameReceived(const LLUUID& id, const std::string& first,
const std::string& last, bool is_group)
//static
void LLPostponedNotification::lookupName(LLPostponedNotification* thiz,
const LLUUID& id,
bool is_group)
{
mName = first + " " + last;
LLStringUtil::trim(mName);
if (mName.empty())
if (is_group)
{
llwarns << "Empty name received for Id: " << id << llendl;
mName = SYSTEM_FROM;
gCacheName->getGroup(id,
boost::bind(&LLPostponedNotification::onGroupNameCache,
thiz, _1, _2, _3));
}
else
{
LLAvatarNameCache::get(id,
boost::bind(&LLPostponedNotification::onAvatarNameCache,
thiz, _1, _2));
}
}
void LLPostponedNotification::onGroupNameCache(const LLUUID& id,
const std::string& full_name,
bool is_group)
{
finalizeName(full_name);
}
void LLPostponedNotification::onAvatarNameCache(const LLUUID& agent_id,
const LLAvatarName& av_name)
{
std::string name = av_name.getCompleteName();
// from PE merge - we should figure out if this is the right thing to do
if (name.empty())
{
llwarns << "Empty name received for Id: " << agent_id << llendl;
name = SYSTEM_FROM;
}
finalizeName(name);
}
void LLPostponedNotification::finalizeName(const std::string& name)
{
mName = name;
modifyNotificationParams();
LLNotifications::instance().add(mParams);
cleanup();

View File

@ -98,8 +98,8 @@
#include "llinitparam.h"
#include "llnotificationslistener.h"
#include "llnotificationptr.h"
#include "llcachename.h"
class LLAvatarName;
typedef enum e_notification_priority
{
NOTIFICATION_PRIORITY_UNSPECIFIED,
@ -194,7 +194,9 @@ public:
{
Mandatory<std::string> type;
Optional<S32> width;
Optional<S32> max_length_chars;
Optional<std::string> value;
FormInput();
};
@ -504,7 +506,7 @@ public:
std::string getLabel() const;
std::string getURL() const;
S32 getURLOption() const;
S32 getURLOpenExternally() const;
S32 getURLOpenExternally() const;
const LLNotificationFormPtr getForm();
@ -973,17 +975,20 @@ public:
{
// upcast T to the base type to restrict T derivation from LLPostponedNotification
LLPostponedNotification* thiz = new T();
thiz->mParams = params;
gCacheName->get(id, is_group, boost::bind(
&LLPostponedNotification::onCachedNameReceived, thiz, _1, _2,
_3, _4));
// Avoid header file dependency on llcachename.h
lookupName(thiz, id, is_group);
}
private:
void onCachedNameReceived(const LLUUID& id, const std::string& first,
const std::string& last, bool is_group);
static void lookupName(LLPostponedNotification* thiz, const LLUUID& id, bool is_group);
// only used for groups
void onGroupNameCache(const LLUUID& id, const std::string& full_name, bool is_group);
// only used for avatars
void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
// used for both group and avatar names
void finalizeName(const std::string& name);
void cleanup()
{

View File

@ -119,7 +119,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
{
params.font(p.font);
}
params.max_length_bytes(MAX_STRING_LENGTH);
params.max_length.bytes(MAX_STRING_LENGTH);
params.commit_callback.function((boost::bind(&LLSpinCtrl::onEditorCommit, this, _2)));
if( mPrecision>0 )//should accept float numbers

View File

@ -40,7 +40,8 @@ LLStyle::Params::Params()
selected_color("selected_color", LLColor4::black),
font("font", LLFontGL::getFontMonospace()),
image("image"),
link_href("href")
link_href("href"),
is_link("is_link")
{}
@ -51,6 +52,7 @@ LLStyle::LLStyle(const LLStyle::Params& p)
mSelectedColor(p.selected_color),
mFont(p.font()),
mLink(p.link_href),
mIsLink(p.is_link.isProvided() ? p.is_link : !p.link_href().empty()),
mDropShadow(p.drop_shadow),
mImagep(p.image())
{}
@ -73,7 +75,7 @@ void LLStyle::setLinkHREF(const std::string& href)
BOOL LLStyle::isLink() const
{
return mLink.size();
return mIsLink;
}
BOOL LLStyle::isVisible() const

View File

@ -46,6 +46,7 @@ public:
Optional<const LLFontGL*> font;
Optional<LLUIImage*> image;
Optional<std::string> link_href;
Optional<bool> is_link;
Params();
};
LLStyle(const Params& p = Params());
@ -106,6 +107,7 @@ private:
std::string mFontName;
const LLFontGL* mFont;
std::string mLink;
bool mIsLink;
LLUIImagePtr mImagep;
};

View File

@ -5,7 +5,7 @@
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
* Copyright (C) 2009-2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -475,8 +475,8 @@ void LLTextBase::drawCursor()
{
LLColor4 text_color;
const LLFontGL* fontp;
text_color = segmentp->getColor();
fontp = segmentp->getStyle()->getFont();
text_color = segmentp->getColor();
fontp = segmentp->getStyle()->getFont();
fontp->render(text, mCursorPos, cursor_rect,
LLColor4(1.f - text_color.mV[VRED], 1.f - text_color.mV[VGREEN], 1.f - text_color.mV[VBLUE], alpha),
LLFontGL::LEFT, mVAlign,
@ -1605,6 +1605,20 @@ std::string LLTextBase::getText() const
return getViewModel()->getValue().asString();
}
// IDEVO - icons can be UI image names or UUID sent from
// server with avatar display name
static LLUIImagePtr image_from_icon_name(const std::string& icon_name)
{
if (LLUUID::validate(icon_name))
{
return LLUI::getUIImageByID( LLUUID(icon_name) );
}
else
{
return LLUI::getUIImage(icon_name);
}
}
void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params)
{
LLStyle::Params style_params(input_params);
@ -1617,7 +1631,7 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
LLUrlMatch match;
std::string text = new_text;
while ( LLUrlRegistry::instance().findUrl(text, match,
boost::bind(&LLTextBase::replaceUrlLabel, this, _1, _2)) )
boost::bind(&LLTextBase::replaceUrl, this, _1, _2, _3)) )
{
LLTextUtil::processUrlMatch(&match,this);
@ -1625,11 +1639,8 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
start = match.getStart();
end = match.getEnd()+1;
LLStyle::Params link_params = style_params;
link_params.color = match.getColor();
link_params.readonly_color = match.getColor();
link_params.font.style("UNDERLINE");
link_params.link_href = match.getUrl();
LLStyle::Params link_params(style_params);
link_params.overwriteFrom(match.getStyle());
// output the text before the Url
if (start > 0)
@ -1646,26 +1657,20 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
std::string subtext=text.substr(0,start);
appendAndHighlightText(subtext, part, style_params);
}
// output the styled Url (unless we've been asked to suppress hyperlinking)
if (match.isLinkDisabled())
// output the styled Url
appendAndHighlightTextImpl(match.getLabel(), part, link_params, match.underlineOnHoverOnly());
// set the tooltip for the Url label
if (! match.getTooltip().empty())
{
appendAndHighlightText(match.getLabel(), part, style_params);
segment_set_t::iterator it = getSegIterContaining(getLength()-1);
if (it != mSegments.end())
{
LLTextSegmentPtr segment = *it;
segment->setToolTip(match.getTooltip());
}
}
else
{
appendAndHighlightText(match.getLabel(), part, link_params, match.underlineOnHoverOnly());
// set the tooltip for the Url label
if (! match.getTooltip().empty())
{
segment_set_t::iterator it = getSegIterContaining(getLength()-1);
if (it != mSegments.end())
{
LLTextSegmentPtr segment = *it;
segment->setToolTip(match.getTooltip());
}
}
}
// move on to the rest of the text after the Url
if (end < (S32)text.length())
{
@ -1850,8 +1855,9 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, S32 highlig
}
void LLTextBase::replaceUrlLabel(const std::string &url,
const std::string &label)
void LLTextBase::replaceUrl(const std::string &url,
const std::string &label,
const std::string &icon)
{
// get the full (wide) text for the editor so we can change it
LLWString text = getWText();
@ -1872,7 +1878,7 @@ void LLTextBase::replaceUrlLabel(const std::string &url,
seg->setEnd(seg_start + seg_length);
// if we find a link with our Url, then replace the label
if (style->isLink() && style->getLinkHREF() == url)
if (style->getLinkHREF() == url)
{
S32 start = seg->getStart();
S32 end = seg->getEnd();
@ -1881,6 +1887,21 @@ void LLTextBase::replaceUrlLabel(const std::string &url,
modified = true;
}
// Icon might be updated when more avatar or group info
// becomes available
if (style->isImage() && style->getLinkHREF() == url)
{
LLUIImagePtr image = image_from_icon_name( icon );
if (image)
{
LLStyle::Params icon_params;
icon_params.image = image;
LLStyleConstSP new_style(new LLStyle(icon_params));
seg->setStyle(new_style);
modified = true;
}
}
// work out the character offset for the next segment
seg_start = seg->getEnd();
}
@ -1978,8 +1999,8 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,
else if (hit_past_end_of_line && segmentp->getEnd() > line_iter->mDocIndexEnd - 1)
{
// segment wraps to next line, so just set doc pos to the end of the line
// segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd)
pos = llmin(getLength(), line_iter->mDocIndexEnd);
// segment wraps to next line, so just set doc pos to start of next line (represented by mDocIndexEnd)
pos = llmin(getLength(), line_iter->mDocIndexEnd);
break;
}
start_x += text_width;

View File

@ -493,7 +493,11 @@ protected:
// misc
void updateRects();
void needsScroll() { mScrollNeeded = TRUE; }
void replaceUrlLabel(const std::string &url, const std::string &label);
struct URLLabelCallback;
// Replace a URL with a new icon and label, for example, when
// avatar names are looked up.
void replaceUrl(const std::string &url, const std::string &label, const std::string& icon);
void appendTextImpl(const std::string &new_text, const LLStyle::Params& input_params = LLStyle::Params());
void appendAndHighlightTextImpl(const std::string &new_text, S32 highlight_part, const LLStyle::Params& style_params, bool underline_on_hover_only = false);

View File

@ -31,18 +31,19 @@
#include "llurlmatch.h"
#include "llurlregistry.h"
#include "llavatarnamecache.h"
#include "llcachename.h"
#include "lltrans.h"
#include "lluicolortable.h"
#define APP_HEADER_REGEX "((x-grid-location-info://[-\\w\\.]+/app)|(secondlife:///app))"
// Utility functions
std::string localize_slapp_label(const std::string& url, const std::string& full_name);
LLUrlEntryBase::LLUrlEntryBase() :
mColor(LLUIColorTable::instance().getColor("HTMLLinkColor")),
mDisabledLink(false)
{
}
LLUrlEntryBase::LLUrlEntryBase()
{}
LLUrlEntryBase::~LLUrlEntryBase()
{
@ -53,6 +54,22 @@ std::string LLUrlEntryBase::getUrl(const std::string &string) const
return escapeUrl(string);
}
//virtual
std::string LLUrlEntryBase::getIcon(const std::string &url)
{
return mIcon;
}
LLStyle::Params LLUrlEntryBase::getStyle() const
{
LLStyle::Params style_params;
style_params.color = LLUIColorTable::instance().getColor("HTMLLinkColor");
style_params.readonly_color = LLUIColorTable::instance().getColor("HTMLLinkColor");
style_params.font.style = "UNDERLINE";
return style_params;
}
std::string LLUrlEntryBase::getIDStringFromUrl(const std::string &url) const
{
// return the id from a SLURL in the format /app/{cmd}/{id}/about
@ -130,16 +147,20 @@ void LLUrlEntryBase::addObserver(const std::string &id,
mObservers.insert(std::pair<std::string, LLUrlEntryObserver>(id, observer));
}
}
void LLUrlEntryBase::callObservers(const std::string &id, const std::string &label)
// *NOTE: See also LLUrlEntryAgent::callObservers()
void LLUrlEntryBase::callObservers(const std::string &id,
const std::string &label,
const std::string &icon)
{
// notify all callbacks waiting on the given uuid
std::multimap<std::string, LLUrlEntryObserver>::iterator it;
for (it = mObservers.find(id); it != mObservers.end();)
typedef std::multimap<std::string, LLUrlEntryObserver>::iterator observer_it;
std::pair<observer_it, observer_it> matching_range = mObservers.equal_range(id);
for (observer_it it = matching_range.first; it != matching_range.second;)
{
// call the callback - give it the new label
LLUrlEntryObserver &observer = it->second;
(*observer.signal)(it->second.url, label);
(*observer.signal)(it->second.url, label, icon);
// then remove the signal - we only need to call it once
delete observer.signal;
mObservers.erase(it++);
@ -308,16 +329,35 @@ LLUrlEntryAgent::LLUrlEntryAgent()
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_agent.xml";
mIcon = "Generic_Person";
mColor = LLUIColorTable::instance().getColor("AgentLinkColor");
}
void LLUrlEntryAgent::onAgentNameReceived(const LLUUID& id,
const std::string& first,
const std::string& last,
BOOL is_group)
// virtual
void LLUrlEntryAgent::callObservers(const std::string &id,
const std::string &label,
const std::string &icon)
{
// notify all callbacks waiting on the given uuid
typedef std::multimap<std::string, LLUrlEntryObserver>::iterator observer_it;
std::pair<observer_it, observer_it> matching_range = mObservers.equal_range(id);
for (observer_it it = matching_range.first; it != matching_range.second;)
{
// call the callback - give it the new label
LLUrlEntryObserver &observer = it->second;
std::string final_label = localize_slapp_label(observer.url, label);
(*observer.signal)(observer.url, final_label, icon);
// then remove the signal - we only need to call it once
delete observer.signal;
mObservers.erase(it++);
}
}
void LLUrlEntryAgent::onAvatarNameCache(const LLUUID& id,
const LLAvatarName& av_name)
{
std::string label = av_name.getCompleteName();
// received the agent name from the server - tell our observers
callObservers(id.asString(), first + " " + last);
callObservers(id.asString(), label, mIcon);
}
LLUUID LLUrlEntryAgent::getID(const std::string &string) const
@ -330,6 +370,10 @@ std::string LLUrlEntryAgent::getTooltip(const std::string &string) const
// return a tooltip corresponding to the URL type instead of the generic one
std::string url = getUrl(string);
if (LLStringUtil::endsWith(url, "/inspect"))
{
return LLTrans::getString("TooltipAgentInspect");
}
if (LLStringUtil::endsWith(url, "/mute"))
{
return LLTrans::getString("TooltipAgentMute");
@ -379,50 +423,182 @@ std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCa
}
LLUUID agent_id(agent_id_string);
std::string full_name;
if (agent_id.isNull())
{
return LLTrans::getString("AvatarNameNobody");
}
else if (gCacheName->getFullName(agent_id, full_name))
LLAvatarName av_name;
if (LLAvatarNameCache::get(agent_id, &av_name))
{
// customize label string based on agent SLapp suffix
if (LLStringUtil::endsWith(url, "/mute"))
{
return LLTrans::getString("SLappAgentMute") + " " + full_name;
}
if (LLStringUtil::endsWith(url, "/unmute"))
{
return LLTrans::getString("SLappAgentUnmute") + " " + full_name;
}
if (LLStringUtil::endsWith(url, "/im"))
{
return LLTrans::getString("SLappAgentIM") + " " + full_name;
}
if (LLStringUtil::endsWith(url, "/pay"))
{
return LLTrans::getString("SLappAgentPay") + " " + full_name;
}
if (LLStringUtil::endsWith(url, "/offerteleport"))
{
return LLTrans::getString("SLappAgentOfferTeleport") + " " + full_name;
}
if (LLStringUtil::endsWith(url, "/requestfriend"))
{
return LLTrans::getString("SLappAgentRequestFriend") + " " + full_name;
}
return full_name;
std::string label = av_name.getCompleteName();
// handle suffixes like /mute or /offerteleport
label = localize_slapp_label(url, label);
return label;
}
else
{
gCacheName->get(agent_id, FALSE,
boost::bind(&LLUrlEntryAgent::onAgentNameReceived,
this, _1, _2, _3, _4));
LLAvatarNameCache::get(agent_id,
boost::bind(&LLUrlEntryAgent::onAvatarNameCache,
this, _1, _2));
addObserver(agent_id_string, url, cb);
return LLTrans::getString("LoadingData");
}
}
LLStyle::Params LLUrlEntryAgent::getStyle() const
{
LLStyle::Params style_params = LLUrlEntryBase::getStyle();
style_params.color = LLUIColorTable::instance().getColor("AgentLinkColor");
style_params.readonly_color = LLUIColorTable::instance().getColor("AgentLinkColor");
return style_params;
}
std::string localize_slapp_label(const std::string& url, const std::string& full_name)
{
// customize label string based on agent SLapp suffix
if (LLStringUtil::endsWith(url, "/mute"))
{
return LLTrans::getString("SLappAgentMute") + " " + full_name;
}
if (LLStringUtil::endsWith(url, "/unmute"))
{
return LLTrans::getString("SLappAgentUnmute") + " " + full_name;
}
if (LLStringUtil::endsWith(url, "/im"))
{
return LLTrans::getString("SLappAgentIM") + " " + full_name;
}
if (LLStringUtil::endsWith(url, "/pay"))
{
return LLTrans::getString("SLappAgentPay") + " " + full_name;
}
if (LLStringUtil::endsWith(url, "/offerteleport"))
{
return LLTrans::getString("SLappAgentOfferTeleport") + " " + full_name;
}
if (LLStringUtil::endsWith(url, "/requestfriend"))
{
return LLTrans::getString("SLappAgentRequestFriend") + " " + full_name;
}
return full_name;
}
std::string LLUrlEntryAgent::getIcon(const std::string &url)
{
// *NOTE: Could look up a badge here by calling getIDStringFromUrl()
// and looking up the badge for the agent.
return mIcon;
}
//
// LLUrlEntryAgentName describes a Second Life agent name Url, e.g.,
// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
//
LLUrlEntryAgentName::LLUrlEntryAgentName()
{}
void LLUrlEntryAgentName::onAvatarNameCache(const LLUUID& id,
const LLAvatarName& av_name)
{
std::string label = getName(av_name);
// received the agent name from the server - tell our observers
callObservers(id.asString(), label, mIcon);
}
std::string LLUrlEntryAgentName::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
if (!gCacheName)
{
// probably at the login screen, use short string for layout
return LLTrans::getString("LoadingData");
}
std::string agent_id_string = getIDStringFromUrl(url);
if (agent_id_string.empty())
{
// something went wrong, just give raw url
return unescapeUrl(url);
}
LLUUID agent_id(agent_id_string);
if (agent_id.isNull())
{
return LLTrans::getString("AvatarNameNobody");
}
LLAvatarName av_name;
if (LLAvatarNameCache::get(agent_id, &av_name))
{
return getName(av_name);
}
else
{
LLAvatarNameCache::get(agent_id,
boost::bind(&LLUrlEntryAgentCompleteName::onAvatarNameCache,
this, _1, _2));
addObserver(agent_id_string, url, cb);
return LLTrans::getString("LoadingData");
}
}
LLStyle::Params LLUrlEntryAgentName::getStyle() const
{
// don't override default colors
return LLStyle::Params().is_link(false);
}
//
// LLUrlEntryAgentCompleteName describes a Second Life agent complete name Url, e.g.,
// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
//
LLUrlEntryAgentCompleteName::LLUrlEntryAgentCompleteName()
{
mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/completename",
boost::regex::perl|boost::regex::icase);
}
std::string LLUrlEntryAgentCompleteName::getName(const LLAvatarName& avatar_name)
{
return avatar_name.getCompleteName();
}
//
// LLUrlEntryAgentDisplayName describes a Second Life agent display name Url, e.g.,
// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
//
LLUrlEntryAgentDisplayName::LLUrlEntryAgentDisplayName()
{
mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/displayname",
boost::regex::perl|boost::regex::icase);
}
std::string LLUrlEntryAgentDisplayName::getName(const LLAvatarName& avatar_name)
{
return avatar_name.mDisplayName;
}
//
// LLUrlEntryAgentUserName describes a Second Life agent user name Url, e.g.,
// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
// x-grid-location-info://lincoln.lindenlab.com/app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
//
LLUrlEntryAgentUserName::LLUrlEntryAgentUserName()
{
mPattern = boost::regex(APP_HEADER_REGEX "/agent/[\\da-f-]+/username",
boost::regex::perl|boost::regex::icase);
}
std::string LLUrlEntryAgentUserName::getName(const LLAvatarName& avatar_name)
{
return avatar_name.mUsername.empty() ? avatar_name.getLegacyName() : avatar_name.mUsername;
}
//
// LLUrlEntryGroup Describes a Second Life group Url, e.g.,
// secondlife:///app/group/00005ff3-4044-c79f-9de8-fb28ae0df991/about
@ -436,18 +612,16 @@ LLUrlEntryGroup::LLUrlEntryGroup()
mMenuName = "menu_url_group.xml";
mIcon = "Generic_Group";
mTooltip = LLTrans::getString("TooltipGroupUrl");
mColor = LLUIColorTable::instance().getColor("GroupLinkColor");
}
void LLUrlEntryGroup::onGroupNameReceived(const LLUUID& id,
const std::string& first,
const std::string& last,
BOOL is_group)
const std::string& name,
bool is_group)
{
// received the group name from the server - tell our observers
callObservers(id.asString(), first);
callObservers(id.asString(), name, mIcon);
}
LLUUID LLUrlEntryGroup::getID(const std::string &string) const
@ -483,14 +657,23 @@ std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCa
}
else
{
gCacheName->get(group_id, TRUE,
gCacheName->getGroup(group_id,
boost::bind(&LLUrlEntryGroup::onGroupNameReceived,
this, _1, _2, _3, _4));
this, _1, _2, _3));
addObserver(group_id_string, url, cb);
return LLTrans::getString("LoadingData");
}
}
LLStyle::Params LLUrlEntryGroup::getStyle() const
{
LLStyle::Params style_params = LLUrlEntryBase::getStyle();
style_params.color = LLUIColorTable::instance().getColor("GroupLinkColor");
style_params.readonly_color = LLUIColorTable::instance().getColor("GroupLinkColor");
return style_params;
}
//
// LLUrlEntryInventory Describes a Second Life inventory Url, e.g.,
// secondlife:///app/inventory/0e346d8b-4433-4d66-a6b0-fd37083abc4c/select
@ -791,7 +974,6 @@ LLUrlEntryNoLink::LLUrlEntryNoLink()
{
mPattern = boost::regex("<nolink>[^<]*</nolink>",
boost::regex::perl|boost::regex::icase);
mDisabledLink = true;
}
std::string LLUrlEntryNoLink::getUrl(const std::string &url) const
@ -805,6 +987,12 @@ std::string LLUrlEntryNoLink::getLabel(const std::string &url, const LLUrlLabelC
return getUrl(url);
}
LLStyle::Params LLUrlEntryNoLink::getStyle() const
{
return LLStyle::Params();
}
//
// LLUrlEntryIcon describes an icon with <icon>...</icon> tags
//
@ -812,7 +1000,6 @@ LLUrlEntryIcon::LLUrlEntryIcon()
{
mPattern = boost::regex("<icon\\s*>\\s*([^<]*)?\\s*</icon\\s*>",
boost::regex::perl|boost::regex::icase);
mDisabledLink = true;
}
std::string LLUrlEntryIcon::getUrl(const std::string &url) const

View File

@ -30,13 +30,17 @@
#include "lluuid.h"
#include "lluicolor.h"
#include "llstyle.h"
#include <boost/signals2.hpp>
#include <boost/regex.hpp>
#include <string>
#include <map>
class LLAvatarName;
typedef boost::signals2::signal<void (const std::string& url,
const std::string& label)> LLUrlLabelSignal;
const std::string& label,
const std::string& icon)> LLUrlLabelSignal;
typedef LLUrlLabelSignal::slot_type LLUrlLabelCallback;
///
@ -71,10 +75,10 @@ public:
virtual std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb) { return url; }
/// Return an icon that can be displayed next to Urls of this type
virtual std::string getIcon(const std::string &url) { return mIcon; }
virtual std::string getIcon(const std::string &url);
/// Return the color to render the displayed text
LLUIColor getColor() const { return mColor; }
/// Return the style to render the displayed text
virtual LLStyle::Params getStyle() const;
/// Given a matched Url, return a tooltip string for the hyperlink
virtual std::string getTooltip(const std::string &string) const { return mTooltip; }
@ -85,9 +89,6 @@ public:
/// Return the name of a SL location described by this Url, if any
virtual std::string getLocation(const std::string &url) const { return ""; }
/// is this a match for a URL that should not be hyperlinked?
bool isLinkDisabled() const { return mDisabledLink; }
/// Should this link text be underlined only when mouse is hovered over it?
virtual bool underlineOnHoverOnly(const std::string &string) const { return false; }
@ -100,7 +101,7 @@ protected:
std::string getLabelFromWikiLink(const std::string &url) const;
std::string getUrlFromWikiLink(const std::string &string) const;
void addObserver(const std::string &id, const std::string &url, const LLUrlLabelCallback &cb);
void callObservers(const std::string &id, const std::string &label);
virtual void callObservers(const std::string &id, const std::string &label, const std::string& icon);
typedef struct {
std::string url;
@ -111,9 +112,7 @@ protected:
std::string mIcon;
std::string mMenuName;
std::string mTooltip;
LLUIColor mColor;
std::multimap<std::string, LLUrlEntryObserver> mObservers;
bool mDisabledLink;
};
///
@ -162,18 +161,78 @@ public:
///
/// LLUrlEntryAgent Describes a Second Life agent Url, e.g.,
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about
///
class LLUrlEntryAgent : public LLUrlEntryBase
{
public:
LLUrlEntryAgent();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getIcon(const std::string &url);
/*virtual*/ std::string getTooltip(const std::string &string) const;
/*virtual*/ LLStyle::Params getStyle() const;
/*virtual*/ LLUUID getID(const std::string &string) const;
/*virtual*/ bool underlineOnHoverOnly(const std::string &string) const;
protected:
/*virtual*/ void callObservers(const std::string &id, const std::string &label, const std::string& icon);
private:
void onAgentNameReceived(const LLUUID& id, const std::string& first,
const std::string& last, BOOL is_group);
void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
};
///
/// LLUrlEntryAgentName Describes a Second Life agent name Url, e.g.,
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/(completename|displayname|username)
/// that displays various forms of user name
/// This is a base class for the various implementations of name display
class LLUrlEntryAgentName : public LLUrlEntryBase
{
public:
LLUrlEntryAgentName();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ LLStyle::Params getStyle() const;
protected:
// override this to pull out relevant name fields
virtual std::string getName(const LLAvatarName& avatar_name) = 0;
private:
void onAvatarNameCache(const LLUUID& id, const LLAvatarName& av_name);
};
///
/// LLUrlEntryAgentCompleteName Describes a Second Life agent name Url, e.g.,
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/completename
/// that displays the full display name + user name for an avatar
/// such as "James Linden (james.linden)"
class LLUrlEntryAgentCompleteName : public LLUrlEntryAgentName
{
public:
LLUrlEntryAgentCompleteName();
private:
/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
};
///
/// LLUrlEntryAgentDisplayName Describes a Second Life agent display name Url, e.g.,
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/displayname
/// that displays the just the display name for an avatar
/// such as "James Linden"
class LLUrlEntryAgentDisplayName : public LLUrlEntryAgentName
{
public:
LLUrlEntryAgentDisplayName();
private:
/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
};
///
/// LLUrlEntryAgentUserName Describes a Second Life agent username Url, e.g.,
/// secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/username
/// that displays the just the display name for an avatar
/// such as "james.linden"
class LLUrlEntryAgentUserName : public LLUrlEntryAgentName
{
public:
LLUrlEntryAgentUserName();
private:
/*virtual*/ std::string getName(const LLAvatarName& avatar_name);
};
///
@ -185,10 +244,10 @@ class LLUrlEntryGroup : public LLUrlEntryBase
public:
LLUrlEntryGroup();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ LLStyle::Params getStyle() const;
/*virtual*/ LLUUID getID(const std::string &string) const;
private:
void onGroupNameReceived(const LLUUID& id, const std::string& first,
const std::string& last, BOOL is_group);
void onGroupNameReceived(const LLUUID& id, const std::string& name, bool is_group);
};
///
@ -297,6 +356,7 @@ public:
LLUrlEntryNoLink();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getUrl(const std::string &string) const;
/*virtual*/ LLStyle::Params getStyle() const;
};
///

View File

@ -37,16 +37,15 @@ LLUrlMatch::LLUrlMatch() :
mIcon(""),
mMenuName(""),
mLocation(""),
mDisabledLink(false),
mUnderlineOnHoverOnly(false)
{
}
void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
const std::string &label, const std::string &tooltip,
const std::string &icon, const LLUIColor& color,
const std::string &icon, const LLStyle::Params& style,
const std::string &menu, const std::string &location,
bool disabled_link, const LLUUID& id, bool underline_on_hover_only)
const LLUUID& id, bool underline_on_hover_only)
{
mStart = start;
mEnd = end;
@ -54,10 +53,10 @@ void LLUrlMatch::setValues(U32 start, U32 end, const std::string &url,
mLabel = label;
mTooltip = tooltip;
mIcon = icon;
mColor = color;
mStyle = style;
mStyle.link_href = url;
mMenuName = menu;
mLocation = location;
mDisabledLink = disabled_link;
mID = id;
mUnderlineOnHoverOnly = underline_on_hover_only;
}

View File

@ -28,11 +28,11 @@
#ifndef LL_LLURLMATCH_H
#define LL_LLURLMATCH_H
#include "linden_common.h"
//#include "linden_common.h"
#include <string>
#include <vector>
#include "lluicolor.h"
#include "llstyle.h"
///
/// LLUrlMatch describes a single Url that was matched within a string by
@ -69,7 +69,7 @@ public:
std::string getIcon() const { return mIcon; }
/// Return the color to render the displayed text
LLUIColor getColor() const { return mColor; }
LLStyle::Params getStyle() const { return mStyle; }
/// Return the name of a XUI file containing the context menu items
std::string getMenuName() const { return mMenuName; }
@ -77,21 +77,17 @@ public:
/// return the SL location that this Url describes, or "" if none.
std::string getLocation() const { return mLocation; }
/// is this a match for a URL that should not be hyperlinked?
bool isLinkDisabled() const { return mDisabledLink; }
/// Should this link text be underlined only when mouse is hovered over it?
bool underlineOnHoverOnly() const { return mUnderlineOnHoverOnly; }
/// Change the contents of this match object (used by LLUrlRegistry)
void setValues(U32 start, U32 end, const std::string &url, const std::string &label,
const std::string &tooltip, const std::string &icon,
const LLUIColor& color, const std::string &menu,
const std::string &location, bool disabled_link
, const LLUUID& id, bool underline_on_hover_only = false );
const LLUUID& getID() const { return mID;}
const LLStyle::Params& style, const std::string &menu,
const std::string &location, const LLUUID& id,
bool underline_on_hover_only = false );
const LLUUID& getID() const { return mID; }
private:
U32 mStart;
U32 mEnd;
@ -101,10 +97,8 @@ private:
std::string mIcon;
std::string mMenuName;
std::string mLocation;
LLUUID mID;
LLUIColor mColor;
bool mDisabledLink;
LLStyle::Params mStyle;
bool mUnderlineOnHoverOnly;
};

View File

@ -31,18 +31,25 @@
#include <boost/regex.hpp>
// default dummy callback that ignores any label updates from the server
void LLUrlRegistryNullCallback(const std::string &url, const std::string &label)
void LLUrlRegistryNullCallback(const std::string &url, const std::string &label, const std::string& icon)
{
}
LLUrlRegistry::LLUrlRegistry()
{
mUrlEntry.reserve(20);
// Urls are matched in the order that they were registered
registerUrl(new LLUrlEntryNoLink());
registerUrl(new LLUrlEntryIcon());
registerUrl(new LLUrlEntrySLURL());
registerUrl(new LLUrlEntryHTTP());
registerUrl(new LLUrlEntryHTTPLabel());
registerUrl(new LLUrlEntryAgentCompleteName());
registerUrl(new LLUrlEntryAgentDisplayName());
registerUrl(new LLUrlEntryAgentUserName());
// LLUrlEntryAgent*Name must appear before LLUrlEntryAgent since
// LLUrlEntryAgent is a less specific (catchall for agent urls)
registerUrl(new LLUrlEntryAgent());
registerUrl(new LLUrlEntryGroup());
registerUrl(new LLUrlEntryParcel());
@ -71,10 +78,13 @@ LLUrlRegistry::~LLUrlRegistry()
}
}
void LLUrlRegistry::registerUrl(LLUrlEntryBase *url)
void LLUrlRegistry::registerUrl(LLUrlEntryBase *url, bool force_front)
{
if (url)
{
if (force_front) // IDEVO
mUrlEntry.insert(mUrlEntry.begin(), url);
else
mUrlEntry.push_back(url);
}
}
@ -174,10 +184,9 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
match_entry->getLabel(url, cb),
match_entry->getTooltip(url),
match_entry->getIcon(url),
match_entry->getColor(),
match_entry->getStyle(),
match_entry->getMenuName(),
match_entry->getLocation(url),
match_entry->isLinkDisabled(),
match_entry->getID(url),
match_entry->underlineOnHoverOnly(url));
return true;
@ -210,10 +219,9 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr
match.getLabel(),
match.getTooltip(),
match.getIcon(),
match.getColor(),
match.getStyle(),
match.getMenuName(),
match.getLocation(),
match.isLinkDisabled(),
match.getID(),
match.underlineOnHoverOnly());
return true;

View File

@ -37,7 +37,9 @@
#include <vector>
/// This default callback for findUrl() simply ignores any label updates
void LLUrlRegistryNullCallback(const std::string &url, const std::string &label);
void LLUrlRegistryNullCallback(const std::string &url,
const std::string &label,
const std::string &icon);
///
/// LLUrlRegistry is a singleton that contains a set of Url types that
@ -64,7 +66,9 @@ public:
~LLUrlRegistry();
/// add a new Url handler to the registry (will be freed on destruction)
void registerUrl(LLUrlEntryBase *url);
/// optionally force it to the front of the list, making it take
/// priority over other regular expression matches for URLs
void registerUrl(LLUrlEntryBase *url, bool force_front = false);
/// get the next Url in an input string, starting at a given character offset
/// your callback is invoked if the matched Url's label changes in the future

View File

@ -27,11 +27,28 @@
#include "llstring.h"
#include "llfile.h"
#include "llavatarnamecache.h"
#include "llcachename.h"
#include "lluuid.h"
#include <string>
// Stub for LLAvatarNameCache
bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
{
return false;
}
void LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot)
{
return;
}
bool LLAvatarNameCache::useDisplayNames()
{
return false;
}
//
// Stub implementation for LLCacheName
//
@ -47,7 +64,12 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)
return TRUE;
}
boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback)
boost::signals2::connection LLCacheName::get(const LLUUID& id, bool is_group, const LLCacheNameCallback& callback)
{
return boost::signals2::connection();
}
boost::signals2::connection LLCacheName::getGroup(const LLUUID& id, const LLCacheNameCallback& callback)
{
return boost::signals2::connection();
}
@ -67,3 +89,105 @@ std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::
{
return std::string();
}
//
// Stub implementation for LLStyle::Params::Params
//
LLStyle::Params::Params()
{
}
//
// Stub implementations for various LLInitParam classes
//
namespace LLInitParam
{
BaseBlock::BaseBlock() {}
BaseBlock::~BaseBlock() {}
Param::Param(BaseBlock* enclosing_block)
: mIsProvided(false)
{
const U8* my_addr = reinterpret_cast<const U8*>(this);
const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
mEnclosingBlockOffset = (U16)(my_addr - block_addr);
}
void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) {}
void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name){}
param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;}
void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
{
descriptor.mCurrentBlockPtr = this;
}
bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack){ return true; }
bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { return true; }
bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { return true; }
bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }
bool BaseBlock::validateBlock(bool emit_errors) const { return true; }
TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
: super_t(descriptor, name, value, func, min_count, max_count)
{}
void TypedParam<LLUIColor>::setValueFromBlock() const
{}
void TypedParam<LLUIColor>::setBlockFromValue()
{}
void TypeValues<LLUIColor>::declareValues()
{}
bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b)
{
return false;
}
TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
: super_t(descriptor, _name, value, func, min_count, max_count)
{}
void TypedParam<const LLFontGL*>::setValueFromBlock() const
{}
void TypedParam<const LLFontGL*>::setBlockFromValue()
{}
void TypeValues<LLFontGL::HAlign>::declareValues()
{}
void TypeValues<LLFontGL::VAlign>::declareValues()
{}
void TypeValues<LLFontGL::ShadowType>::declareValues()
{}
void TypedParam<LLUIImage*>::setValueFromBlock() const
{}
void TypedParam<LLUIImage*>::setBlockFromValue()
{}
bool ParamCompare<LLUIImage*, false>::equals(
LLUIImage* const &a,
LLUIImage* const &b)
{
return false;
}
bool ParamCompare<LLUIColor, false>::equals(const LLUIColor &a, const LLUIColor &b)
{
return false;
}
}
//static
LLFontGL* LLFontGL::getFontDefault()
{
return NULL;
}

View File

@ -30,6 +30,7 @@
#include "llurlentry_stub.cpp"
#include "lltut.h"
#include "../lluicolortable.h"
#include "../lluiimage.h"
#include <boost/regex.hpp>
@ -40,6 +41,26 @@ LLUIColor LLUIColorTable::getColor(const std::string& name, const LLColor4& defa
LLUIColor::LLUIColor() : mColorPtr(NULL) {}
LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
{
}
LLUIImage::~LLUIImage()
{
}
//virtual
S32 LLUIImage::getWidth() const
{
return 0;
}
//virtual
S32 LLUIImage::getHeight() const
{
return 0;
}
namespace tut
{
struct LLUrlEntryData

View File

@ -25,14 +25,135 @@
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "../llurlmatch.h"
#include "../lluiimage.h"
#include "lltut.h"
// link seam
// link seams
LLUIColor::LLUIColor()
: mColorPtr(NULL)
{}
LLStyle::Params::Params()
{
}
LLUIImage::LLUIImage(const std::string& name, LLPointer<LLTexture> image)
{
}
LLUIImage::~LLUIImage()
{
}
//virtual
S32 LLUIImage::getWidth() const
{
return 0;
}
//virtual
S32 LLUIImage::getHeight() const
{
return 0;
}
namespace LLInitParam
{
BaseBlock::BaseBlock() {}
BaseBlock::~BaseBlock() {}
void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided) {}
void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name){}
param_handle_t BaseBlock::getHandleFromParam(const Param* param) const {return 0;}
void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
{
descriptor.mCurrentBlockPtr = this;
}
Param::Param(BaseBlock* enclosing_block)
: mIsProvided(false)
{
const U8* my_addr = reinterpret_cast<const U8*>(this);
const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
mEnclosingBlockOffset = (U16)(my_addr - block_addr);
}
bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack){ return true; }
bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const { return true; }
bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const { return true; }
bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite) { return true; }
bool BaseBlock::validateBlock(bool emit_errors) const { return true; }
TypedParam<LLUIColor >::TypedParam(BlockDescriptor& descriptor, const char* name, const LLUIColor& value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
: super_t(descriptor, name, value, func, min_count, max_count)
{}
void TypedParam<LLUIColor>::setValueFromBlock() const
{}
void TypedParam<LLUIColor>::setBlockFromValue()
{}
void TypeValues<LLUIColor>::declareValues()
{}
bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b)
{
return false;
}
TypedParam<const LLFontGL*>::TypedParam(BlockDescriptor& descriptor, const char* _name, const LLFontGL*const value, ParamDescriptor::validation_func_t func, S32 min_count, S32 max_count)
: super_t(descriptor, _name, value, func, min_count, max_count)
{}
void TypedParam<const LLFontGL*>::setValueFromBlock() const
{}
void TypedParam<const LLFontGL*>::setBlockFromValue()
{}
void TypeValues<LLFontGL::HAlign>::declareValues()
{}
void TypeValues<LLFontGL::VAlign>::declareValues()
{}
void TypeValues<LLFontGL::ShadowType>::declareValues()
{}
void TypedParam<LLUIImage*>::setValueFromBlock() const
{}
void TypedParam<LLUIImage*>::setBlockFromValue()
{}
bool ParamCompare<LLUIImage*, false>::equals(
LLUIImage* const &a,
LLUIImage* const &b)
{
return false;
}
bool ParamCompare<LLUIColor, false>::equals(const LLUIColor &a, const LLUIColor &b)
{
return false;
}
}
//static
LLFontGL* LLFontGL::getFontDefault()
{
return NULL;
}
namespace tut
{
struct LLUrlMatchData
@ -59,7 +180,7 @@ namespace tut
LLUrlMatch match;
ensure("empty()", match.empty());
match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLUIColor(), "", "", false,LLUUID::null);
match.setValues(0, 1, "http://secondlife.com", "Second Life", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure("! empty()", ! match.empty());
}
@ -72,7 +193,7 @@ namespace tut
LLUrlMatch match;
ensure_equals("getStart() == 0", match.getStart(), 0);
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getStart() == 10", match.getStart(), 10);
}
@ -85,7 +206,7 @@ namespace tut
LLUrlMatch match;
ensure_equals("getEnd() == 0", match.getEnd(), 0);
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getEnd() == 20", match.getEnd(), 20);
}
@ -98,10 +219,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getUrl() == ''", match.getUrl(), "");
match.setValues(10, 20, "http://slurl.com/", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
match.setValues(10, 20, "http://slurl.com/", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getUrl() == 'http://slurl.com/'", match.getUrl(), "http://slurl.com/");
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getUrl() == '' (2)", match.getUrl(), "");
}
@ -114,10 +235,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getLabel() == ''", match.getLabel(), "");
match.setValues(10, 20, "", "Label", "", "", LLUIColor(), "", "", false,LLUUID::null);
match.setValues(10, 20, "", "Label", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getLabel() == 'Label'", match.getLabel(), "Label");
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getLabel() == '' (2)", match.getLabel(), "");
}
@ -130,10 +251,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getTooltip() == ''", match.getTooltip(), "");
match.setValues(10, 20, "", "", "Info", "", LLUIColor(), "", "", false,LLUUID::null);
match.setValues(10, 20, "", "", "Info", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getTooltip() == 'Info'", match.getTooltip(), "Info");
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getTooltip() == '' (2)", match.getTooltip(), "");
}
@ -146,10 +267,10 @@ namespace tut
LLUrlMatch match;
ensure_equals("getIcon() == ''", match.getIcon(), "");
match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "", "", false,LLUUID::null);
match.setValues(10, 20, "", "", "", "Icon", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getIcon() == 'Icon'", match.getIcon(), "Icon");
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure_equals("getIcon() == '' (2)", match.getIcon(), "");
}
@ -162,10 +283,10 @@ namespace tut
LLUrlMatch match;
ensure("getMenuName() empty", match.getMenuName().empty());
match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "", false,LLUUID::null);
match.setValues(10, 20, "", "", "", "Icon", LLStyle::Params(), "xui_file.xml", "", LLUUID::null);
ensure_equals("getMenuName() == \"xui_file.xml\"", match.getMenuName(), "xui_file.xml");
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure("getMenuName() empty (2)", match.getMenuName().empty());
}
@ -178,10 +299,10 @@ namespace tut
LLUrlMatch match;
ensure("getLocation() empty", match.getLocation().empty());
match.setValues(10, 20, "", "", "", "Icon", LLUIColor(), "xui_file.xml", "Paris", false,LLUUID::null);
match.setValues(10, 20, "", "", "", "Icon", LLStyle::Params(), "xui_file.xml", "Paris", LLUUID::null);
ensure_equals("getLocation() == \"Paris\"", match.getLocation(), "Paris");
match.setValues(10, 20, "", "", "", "", LLUIColor(), "", "", false,LLUUID::null);
match.setValues(10, 20, "", "", "", "", LLStyle::Params(), "", "", LLUUID::null);
ensure("getLocation() empty (2)", match.getLocation().empty());
}
}

View File

@ -29,7 +29,13 @@
#include "llxuiparser.h"
#include "llxmlnode.h"
#ifdef LL_STANDALONE
#include <expat.h>
#else
#include "expat/expat.h"
#endif
#include <fstream>
#include <boost/tokenizer.hpp>
//#include <boost/spirit/include/qi.hpp>

View File

@ -25,6 +25,14 @@ include_directories(
### media_plugin_base
if(NOT WORD_SIZE EQUAL 32)
if(WINDOWS)
add_definitions(/FIXED:NO)
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif(WINDOWS)
endif(NOT WORD_SIZE EQUAL 32)
set(media_plugin_base_SOURCE_FILES
media_plugin_base.cpp
)

View File

@ -29,6 +29,14 @@ include_directories(
### media_plugin_example
if(NOT WORD_SIZE EQUAL 32)
if(WINDOWS)
add_definitions(/FIXED:NO)
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif(WINDOWS)
endif(NOT WORD_SIZE EQUAL 32)
set(media_plugin_example_SOURCE_FILES
media_plugin_example.cpp
)

View File

@ -30,6 +30,14 @@ include_directories(
### media_plugin_gstreamer010
if(NOT WORD_SIZE EQUAL 32)
if(WINDOWS)
add_definitions(/FIXED:NO)
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif(WINDOWS)
endif(NOT WORD_SIZE EQUAL 32)
set(media_plugin_gstreamer010_SOURCE_FILES
media_plugin_gstreamer010.cpp
llmediaimplgstreamer_syms.cpp

View File

@ -32,6 +32,14 @@ include_directories(
### media_plugin_webkit
if(NOT WORD_SIZE EQUAL 32)
if(WINDOWS)
add_definitions(/FIXED:NO)
else(WINDOWS) # not windows therefore gcc LINUX and DARWIN
add_definitions(-fPIC)
endif(WINDOWS)
endif(NOT WORD_SIZE EQUAL 32)
set(media_plugin_webkit_SOURCE_FILES
media_plugin_webkit.cpp
)
@ -53,6 +61,8 @@ set(media_plugin_webkit_LINK_LIBRARIES
if (LINUX)
if (PULSEAUDIO_FOUND)
list(APPEND media_plugin_webkit_SOURCE_FILES linux_volume_catcher.cpp)
else (PULSEAUDIO_FOUND)
list(APPEND media_plugin_webkit_SOURCE_FILES dummy_volume_catcher.cpp)
endif (PULSEAUDIO_FOUND)
list(APPEND media_plugin_webkit_LINK_LIBRARIES
${UI_LIBRARIES} # for glib/GTK
@ -67,9 +77,6 @@ elseif (DARWIN)
)
elseif (WINDOWS)
list(APPEND media_plugin_webkit_SOURCE_FILES windows_volume_catcher.cpp)
else (LINUX)
# All other platforms use the dummy volume catcher for now.
list(APPEND media_plugin_webkit_SOURCE_FILES dummy_volume_catcher.cpp)
endif (LINUX)
set_source_files_properties(${media_plugin_webkit_HEADER_FILES}

View File

@ -146,7 +146,6 @@ set(viewer_SOURCE_FILES
lldriverparam.cpp
lldynamictexture.cpp
llemote.cpp
lleventinfo.cpp
lleventnotifier.cpp
lleventpoll.cpp
llexpandabletextbox.cpp
@ -175,6 +174,7 @@ set(viewer_SOURCE_FILES
llfloatercamera.cpp
llfloatercolorpicker.cpp
llfloaterdaycycle.cpp
llfloaterdisplayname.cpp
llfloaterenvsettings.cpp
llfloaterevent.cpp
llfloaterfonttest.cpp
@ -252,6 +252,7 @@ set(viewer_SOURCE_FILES
llhudeffecttrail.cpp
llhudicon.cpp
llhudmanager.cpp
llhudnametag.cpp
llhudobject.cpp
llhudrender.cpp
llhudtext.cpp
@ -497,6 +498,7 @@ set(viewer_SOURCE_FILES
llviewercontrol.cpp
llviewercontrollistener.cpp
llviewerdisplay.cpp
llviewerdisplayname.cpp
llviewerfloaterreg.cpp
llviewerfoldertype.cpp
llviewergenericmessage.cpp
@ -682,7 +684,6 @@ set(viewer_HEADER_FILES
lldriverparam.h
lldynamictexture.h
llemote.h
lleventinfo.h
lleventnotifier.h
lleventpoll.h
llexpandabletextbox.h
@ -711,6 +712,7 @@ set(viewer_HEADER_FILES
llfloatercamera.h
llfloatercolorpicker.h
llfloaterdaycycle.h
llfloaterdisplayname.h
llfloaterenvsettings.h
llfloaterevent.h
llfloaterfonttest.h
@ -788,6 +790,7 @@ set(viewer_HEADER_FILES
llhudeffecttrail.h
llhudicon.h
llhudmanager.h
llhudnametag.h
llhudobject.h
llhudrender.h
llhudtext.h
@ -1031,6 +1034,7 @@ set(viewer_HEADER_FILES
llviewercontrol.h
llviewercontrollistener.h
llviewerdisplay.h
llviewerdisplayname.h
llviewerfloaterreg.h
llviewerfoldertype.h
llviewergenericmessage.h
@ -1504,6 +1508,9 @@ if (WINDOWS)
${SHARED_LIB_STAGING_DIR}/Release/openjpeg.dll
${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/openjpeg.dll
${SHARED_LIB_STAGING_DIR}/Debug/openjpegd.dll
${SHARED_LIB_STAGING_DIR}/Release/fmod.dll
${SHARED_LIB_STAGING_DIR}/RelWithDebInfo/fmod.dll
${SHARED_LIB_STAGING_DIR}/Debug/fmod.dll
${SHARED_LIB_STAGING_DIR}/Release/msvcr80.dll
${SHARED_LIB_STAGING_DIR}/Release/msvcp80.dll
${SHARED_LIB_STAGING_DIR}/Release/Microsoft.VC80.CRT.manifest
@ -1525,7 +1532,6 @@ if (WINDOWS)
${CMAKE_CURRENT_SOURCE_DIR}/featuretable.txt
${CMAKE_CURRENT_SOURCE_DIR}/featuretable_xp.txt
${CMAKE_CURRENT_SOURCE_DIR}/dbghelp.dll
${CMAKE_CURRENT_SOURCE_DIR}/fmod.dll
${ARCH_PREBUILT_DIRS_RELEASE}/libeay32.dll
${ARCH_PREBUILT_DIRS_RELEASE}/qtcore4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/qtgui4.dll

View File

@ -24,6 +24,8 @@
<RenderTerrainLODFactor value="2"/>
<!--Default for now-->
<RenderTreeLODFactor value="0.5"/>
<!--Default for now-->
<RenderUseFBO value="1"/>
<!--Try Impostors-->
<RenderUseImpostors value="TRUE"/>
<!--Default for now-->

View File

@ -45,6 +45,17 @@
<key>Value</key>
<integer>1</integer>
</map>
<key>FirstDisplayName</key>
<map>
<key>Comment</key>
<string>Shows hint when edits profile for the first time</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>FirstReceiveLindens</key>
<map>
<key>Comment</key>

View File

@ -26,6 +26,8 @@
<RenderTerrainLODFactor value="1.0"/>
<!--Default for now-->
<RenderTreeLODFactor value="0.5"/>
<!--Default for now-->
<RenderUseFBO value="0"/>
<!--Try Impostors-->
<RenderUseImpostors value="TRUE"/>
<!--Default for now-->

View File

@ -24,6 +24,8 @@
<RenderTerrainLODFactor value="1.0"/>
<!--Default for now-->
<RenderTreeLODFactor value="0.5"/>
<!--Default for now-->
<RenderUseFBO value="0"/>
<!--Try Impostors-->
<RenderUseImpostors value="TRUE"/>
<!--Default for now-->

View File

@ -2908,6 +2908,17 @@
<key>Value</key>
<integer>175</integer>
</map>
<key>EventURL</key>
<map>
<key>Comment</key>
<string>URL for Event website, displayed in the event floater</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://events.secondlife.com/viewer/embed/event/</string>
</map>
<key>EveryoneCopy</key>
<map>
<key>Comment</key>
@ -5794,13 +5805,13 @@
<key>ToastGap</key>
<map>
<key>Comment</key>
<string>Gap between toasts on a screen</string>
<string>Gap between toasts on a screen (min. value is 5)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>5</integer>
<integer>7</integer>
</map>
<key>ToastButtonWidth</key>
<map>
@ -8118,7 +8129,7 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>RenderShowGroupTitleAll</key>
<key>NameTagShowGroupTitles</key>
<map>
<key>Comment</key>
<string>Show group titles in name labels</string>
@ -8127,6 +8138,39 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>NameTagShowDisplayNames</key>
<map>
<key>Comment</key>
<string>Show display names in name labels</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>NameTagShowFriends</key>
<map>
<key>Comment</key>
<string>Highlight the name tags of your friends</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>NameTagShowUsernames</key>
<map>
<key>Comment</key>
<string>Show usernames in avatar name tags</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>RenderInitError</key>
@ -11243,6 +11287,17 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>UseDisplayNames</key>
<map>
<key>Comment</key>
<string>Use new, changeable, unicode names</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>UseEnergy</key>
<map>
<key>Comment</key>

View File

@ -24,6 +24,8 @@
<RenderTerrainLODFactor value="2.0"/>
<!--Default for now-->
<RenderTreeLODFactor value="1.0"/>
<!--Default for now-->
<RenderUseFBO value="1"/>
<!--Try Impostors-->
<RenderUseImpostors value="TRUE"/>
<!--Default for now-->

View File

@ -62,6 +62,7 @@ RenderShadowDetail 1 2
RenderUseFBO 1 1
WatchdogDisabled 1 1
RenderUseStreamVBO 1 1
RenderUseFBO 1 1
//
// Low Graphics Settings
@ -90,7 +91,7 @@ SkyUseClassicClouds 1 0
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
RenderUseFBO 1 0
//
// Mid Graphics Settings
@ -117,7 +118,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
RenderUseFBO 1 0
//
// High Graphics Settings (purty)
@ -144,7 +145,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
RenderUseFBO 1 1
//
// Ultra graphics (REALLY PURTY!)
@ -171,7 +172,7 @@ WLSkyDetail 1 128
RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
RenderUseFBO 1 1
//
// Class Unknown Hardware (unknown)
@ -247,7 +248,8 @@ WindLightUseAtmosShaders 0 0
RenderDeferred 0 0
RenderDeferredSSAO 0 0
RenderShadowDetail 0 0
RenderUseFBO 1 0
//
// CPU based feature masks

View File

@ -60,6 +60,7 @@ RenderDeferred 1 0
RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
RenderUseFBO 1 1
//
// Low Graphics Settings
@ -88,7 +89,7 @@ SkyUseClassicClouds 1 0
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
RenderUseFBO 1 0
//
// Mid Graphics Settings
@ -115,7 +116,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
RenderUseFBO 1 0
//
// High Graphics Settings (purty)
@ -142,7 +143,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
RenderUseFBO 1 1
//
// Ultra graphics (REALLY PURTY!)
@ -169,7 +170,7 @@ WLSkyDetail 1 128
RenderDeferred 1 1
RenderDeferredSSAO 1 1
RenderShadowDetail 1 2
RenderUseFBO 1 1
//
// Class Unknown Hardware (unknown)
@ -244,6 +245,7 @@ WindLightUseAtmosShaders 0 0
RenderDeferred 0 0
RenderDeferredSSAO 0 0
RenderShadowDetail 0 0
RenderUseFBO 1 0
//

View File

@ -60,6 +60,7 @@ Disregard128DefaultDrawDistance 1 1
Disregard96DefaultDrawDistance 1 1
SkyUseClassicClouds 1 1
WatchdogDisabled 1 1
RenderUseFBO 1 1
//
// Low Graphics Settings
@ -87,6 +88,7 @@ VertexShaderEnable 1 0
WindLightUseAtmosShaders 1 0
WLSkyDetail 1 48
SkyUseClassicClouds 1 0
RenderUseFBO 1 0
//
// Mid Graphics Settings
@ -112,6 +114,7 @@ RenderWaterReflections 1 0
VertexShaderEnable 1 1
WindLightUseAtmosShaders 1 0
WLSkyDetail 1 48
RenderUseFBO 1 0
//
// High Graphics Settings (purty)
@ -137,6 +140,7 @@ RenderWaterReflections 1 0
VertexShaderEnable 1 1
WindLightUseAtmosShaders 1 1
WLSkyDetail 1 48
RenderUseFBO 1 1
//
// Ultra graphics (REALLY PURTY!)
@ -162,6 +166,7 @@ RenderWaterReflections 1 1
VertexShaderEnable 1 1
WindLightUseAtmosShaders 1 1
WLSkyDetail 1 128
RenderUseFBO 1 1
//
// Class Unknown Hardware (unknown)
@ -227,6 +232,7 @@ RenderUseImpostors 0 0
RenderVBOEnable 1 0
RenderWaterReflections 0 0
WindLightUseAtmosShaders 0 0
RenderUseFBO 1 0
//
// CPU based feature masks

View File

@ -38,6 +38,7 @@ RenderTextureMemoryMultiple 1 1.0
UseOcclusion 1 1
RenderCubeMap 1 1
WatchdogDisabled 1 1
RenderUseFBO 1 1
//
@ -52,6 +53,7 @@ RenderAvatarMode 1 0
RenderLighting 1 0
RenderObjectBump 1 0
RenderRippleWater 1 0
RenderUseFBO 1 0
//
// Class 1 Hardware
@ -65,6 +67,7 @@ RenderAvatarMode 1 0
RenderLighting 1 0
RenderObjectBump 1 0
RenderRippleWater 1 0
RenderUseFBO 1 0
//
// Class 2 Hardware (make it purty)
@ -76,6 +79,7 @@ RenderAvatarMode 1 1
RenderLighting 1 1
RenderObjectBump 1 1
RenderRippleWater 1 1
RenderUseFBO 1 1
//
// Class 3 Hardware (make it purty)
@ -87,6 +91,7 @@ RenderAvatarMode 1 1
RenderLighting 1 1
RenderObjectBump 1 1
RenderRippleWater 1 1
RenderUseFBO 1 1
//
// No Pixel Shaders available
@ -114,6 +119,7 @@ RenderParticleCount 1 1024
RenderTerrainDetail 1 0
RenderCubeMap 0 0
UseOcclusion 0 0
RenderUseFBO 1 0
list low

View File

@ -59,6 +59,7 @@ SkyUseClassicClouds 1 1
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
RenderUseFBO 1 1
WatchdogDisabled 1 1
RenderUseStreamVBO 1 1
@ -89,7 +90,7 @@ SkyUseClassicClouds 1 0
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
RenderUseFBO 1 0
//
// Mid Graphics Settings
@ -116,7 +117,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
RenderUseFBO 1 0
//
// High Graphics Settings (purty)
@ -143,7 +144,7 @@ WLSkyDetail 1 48
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
RenderUseFBO 1 1
//
// Ultra graphics (REALLY PURTY!)
@ -170,6 +171,7 @@ WLSkyDetail 1 128
RenderDeferred 1 0
RenderDeferredSSAO 1 0
RenderShadowDetail 1 0
RenderUseFBO 1 1
//
// Class Unknown Hardware (unknown)
@ -244,6 +246,7 @@ WindLightUseAtmosShaders 0 0
RenderDeferred 0 0
RenderDeferredSSAO 0 0
RenderShadowDetail 0 0
RenderUseFBO 1 0
//
// CPU based feature masks

View File

@ -39,29 +39,6 @@
#include "llvoavatarself.h"
#include "llslurl.h"
//static
void LLAgentUI::buildName(std::string& name)
{
name.clear();
if (isAgentAvatarValid())
{
LLNameValue *first_nv = gAgentAvatarp->getNVPair("FirstName");
LLNameValue *last_nv = gAgentAvatarp->getNVPair("LastName");
if (first_nv && last_nv)
{
name = first_nv->printData() + " " + last_nv->printData();
}
else
{
llwarns << "Agent is missing FirstName and/or LastName nv pair." << llendl;
}
}
else
{
name = gSavedSettings.getString("FirstName") + " " + gSavedSettings.getString("LastName");
}
}
//static
void LLAgentUI::buildFullname(std::string& name)
{

View File

@ -41,7 +41,6 @@ public:
LOCATION_FORMAT_FULL, // Parcel, Region (x, y, z) - Maturity
};
static void buildName(std::string& name);
static void buildFullname(std::string &name);
static void buildSLURL(LLSLURL& slurl, const bool escaped = true);

View File

@ -87,6 +87,7 @@
#include "llsecondlifeurls.h"
// Linden library includes
#include "llavatarnamecache.h"
#include "llimagej2c.h"
#include "llmemory.h"
#include "llprimitive.h"
@ -159,7 +160,6 @@
// Included so that constants/settings might be initialized
// in save_settings_to_globals()
#include "llbutton.h"
#include "llcombobox.h"
#include "llstatusbar.h"
#include "llsurface.h"
#include "llvosky.h"
@ -436,9 +436,6 @@ static void settings_to_globals()
MENU_BAR_HEIGHT = gSavedSettings.getS32("MenuBarHeight");
MENU_BAR_WIDTH = gSavedSettings.getS32("MenuBarWidth");
LLCOMBOBOX_HEIGHT = BTN_HEIGHT - 2;
LLCOMBOBOX_WIDTH = 128;
LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));
LLImageGL::sGlobalUseAnisotropic = gSavedSettings.getBOOL("RenderAnisotropic");
@ -1385,8 +1382,7 @@ bool LLAppViewer::cleanup()
LLPolyMesh::freeAllMeshes();
delete gCacheName;
gCacheName = NULL;
LLStartUp::cleanupNameCache();
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.
@ -3453,6 +3449,15 @@ void LLAppViewer::saveFinalSnapshot()
void LLAppViewer::loadNameCache()
{
// display names cache
std::string filename =
gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
llifstream name_cache_stream(filename);
if(name_cache_stream.is_open())
{
LLAvatarNameCache::importFile(name_cache_stream);
}
if (!gCacheName) return;
std::string name_cache;
@ -3462,19 +3467,19 @@ void LLAppViewer::loadNameCache()
{
if(gCacheName->importFile(cache_file)) return;
}
// Try to load from the legacy format. This should go away after a
// while. Phoenix 2008-01-30
LLFILE* name_cache_fp = LLFile::fopen(name_cache, "r"); // Flawfinder: ignore
if (name_cache_fp)
{
gCacheName->importFile(name_cache_fp);
fclose(name_cache_fp);
}
}
void LLAppViewer::saveNameCache()
{
{
// display names cache
std::string filename =
gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
llofstream name_cache_stream(filename);
if(name_cache_stream.is_open())
{
LLAvatarNameCache::exportFile(name_cache_stream);
}
if (!gCacheName) return;
std::string name_cache;
@ -3678,6 +3683,7 @@ void LLAppViewer::idle()
// NOTE: Starting at this point, we may still have pointers to "dead" objects
// floating throughout the various object lists.
//
idleNameCache();
idleNetwork();
@ -4015,6 +4021,60 @@ void LLAppViewer::sendLogoutRequest()
}
}
void LLAppViewer::idleNameCache()
{
// Neither old nor new name cache can function before agent has a region
LLViewerRegion* region = gAgent.getRegion();
if (!region) return;
// deal with any queued name requests and replies.
gCacheName->processPending();
// Can't run the new cache until we have the list of capabilities
// for the agent region, and can therefore decide whether to use
// display names or fall back to the old name system.
if (!region->capabilitiesReceived()) return;
// Agent may have moved to a different region, so need to update cap URL
// for name lookups. Can't do this in the cap grant code, as caps are
// granted to neighbor regions before the main agent gets there. Can't
// do it in the move-into-region code because cap not guaranteed to be
// granted yet, for example on teleport.
bool had_capability = LLAvatarNameCache::hasNameLookupURL();
std::string name_lookup_url;
name_lookup_url.reserve(128); // avoid a memory allocation below
name_lookup_url = region->getCapability("GetDisplayNames");
bool have_capability = !name_lookup_url.empty();
if (have_capability)
{
// we have support for display names, use it
U32 url_size = name_lookup_url.size();
// capabilities require URLs with slashes before query params:
// https://<host>:<port>/cap/<uuid>/?ids=<blah>
// but the caps are granted like:
// https://<host>:<port>/cap/<uuid>
if (url_size > 0 && name_lookup_url[url_size-1] != '/')
{
name_lookup_url += '/';
}
LLAvatarNameCache::setNameLookupURL(name_lookup_url);
}
else
{
// Display names not available on this region
LLAvatarNameCache::setNameLookupURL( std::string() );
}
// Error recovery - did we change state?
if (had_capability != have_capability)
{
// name tags are persistant on screen, so make sure they refresh
LLVOAvatar::invalidateNameTags();
}
LLAvatarNameCache::idle();
}
//
// Handle messages, and all message related stuff
//
@ -4045,8 +4105,6 @@ void LLAppViewer::idleNetwork()
{
LLFastTimer t(FTM_IDLE_NETWORK); // decode
// deal with any queued name requests and replies.
gCacheName->processPending();
LLTimer check_message_timer;
// Read all available packets from network
const S64 frame_count = gFrameCount; // U32->S64

View File

@ -204,6 +204,8 @@ private:
void idle();
void idleShutdown();
// update avatar SLID and display name caches
void idleNameCache();
void idleNetwork();
void sendLogoutRequest();

View File

@ -31,11 +31,11 @@
#include "boost/lambda/lambda.hpp" // for lambda::constant
#include "llavatarnamecache.h" // IDEVO
#include "llsd.h"
#include "lldarray.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "roles_constants.h" // for GP_MEMBER_INVITE
#include "llagent.h"
@ -49,6 +49,7 @@
#include "llfloaterpay.h"
#include "llfloaterworldmap.h"
#include "llgiveinventory.h"
#include "llinventorybridge.h"
#include "llinventorymodel.h" // for gInventory.findCategoryUUIDForType
#include "llinventorypanel.h"
#include "llimview.h" // for gIMMgr
@ -64,6 +65,7 @@
#include "llimfloater.h"
#include "lltrans.h"
#include "llcallingcard.h"
#include "llslurl.h" // IDEVO
// static
void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::string& name)
@ -75,26 +77,22 @@ void LLAvatarActions::requestFriendshipDialog(const LLUUID& id, const std::strin
}
LLSD args;
args["NAME"] = name;
args["NAME"] = LLSLURL("agent", id, "completename").getSLURLString();
LLSD payload;
payload["id"] = id;
payload["name"] = name;
// Look for server versions like: Second Life Server 1.24.4.95600
if (gLastVersionChannel.find(" 1.24.") != std::string::npos)
{
// Old and busted server version, doesn't support friend
// requests with messages.
LLNotificationsUtil::add("AddFriend", args, payload, &callbackAddFriend);
}
else
{
LLNotificationsUtil::add("AddFriendWithMessage", args, payload, &callbackAddFriendWithMessage);
}
// add friend to recent people list
LLRecentPeople::instance().add(id);
}
void on_avatar_name_friendship(const LLUUID& id, const LLAvatarName av_name)
{
LLAvatarActions::requestFriendshipDialog(id, av_name.getCompleteName());
}
// static
void LLAvatarActions::requestFriendshipDialog(const LLUUID& id)
{
@ -103,9 +101,7 @@ void LLAvatarActions::requestFriendshipDialog(const LLUUID& id)
return;
}
std::string full_name;
gCacheName->getFullName(id, full_name);
requestFriendshipDialog(id, full_name);
LLAvatarNameCache::get(id, boost::bind(&on_avatar_name_friendship, _1, _2));
}
// static
@ -130,11 +126,10 @@ void LLAvatarActions::removeFriendsDialog(const uuid_vec_t& ids)
if(ids.size() == 1)
{
LLUUID agent_id = ids[0];
std::string first, last;
if(gCacheName->getName(agent_id, first, last))
LLAvatarName av_name;
if(LLAvatarNameCache::get(agent_id, &av_name))
{
args["FIRST_NAME"] = first;
args["LAST_NAME"] = last;
args["NAME"] = av_name.mDisplayName;
}
msgType = "RemoveFromFriends";
@ -162,14 +157,6 @@ void LLAvatarActions::offerTeleport(const LLUUID& invitee)
if (invitee.isNull())
return;
//waiting until Name Cache gets updated with corresponding avatar name
std::string just_to_request_name;
if (!gCacheName->getFullName(invitee, just_to_request_name))
{
gCacheName->get(invitee, FALSE, boost::bind((void (*)(const LLUUID&)) &LLAvatarActions::offerTeleport, invitee));
return;
}
LLDynamicArray<LLUUID> ids;
ids.push_back(invitee);
offerTeleport(ids);
@ -184,25 +171,26 @@ void LLAvatarActions::offerTeleport(const uuid_vec_t& ids)
handle_lure(ids);
}
static void on_avatar_name_cache_start_im(const LLUUID& agent_id,
const LLAvatarName& av_name)
{
std::string name = av_name.getCompleteName();
LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id);
if (session_id != LLUUID::null)
{
LLIMFloater::show(session_id);
}
make_ui_sound("UISndStartIM");
}
// static
void LLAvatarActions::startIM(const LLUUID& id)
{
if (id.isNull())
return;
std::string name;
if (!gCacheName->getFullName(id, name))
{
gCacheName->get(id, FALSE, boost::bind(&LLAvatarActions::startIM, id));
return;
}
LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id);
if (session_id != LLUUID::null)
{
LLIMFloater::show(session_id);
}
make_ui_sound("UISndStartIM");
LLAvatarNameCache::get(id,
boost::bind(&on_avatar_name_cache_start_im, _1, _2));
}
// static
@ -218,6 +206,18 @@ void LLAvatarActions::endIM(const LLUUID& id)
}
}
static void on_avatar_name_cache_start_call(const LLUUID& agent_id,
const LLAvatarName& av_name)
{
std::string name = av_name.getCompleteName();
LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, agent_id, true);
if (session_id != LLUUID::null)
{
gIMMgr->startCall(session_id);
}
make_ui_sound("UISndStartIM");
}
// static
void LLAvatarActions::startCall(const LLUUID& id)
{
@ -225,15 +225,8 @@ void LLAvatarActions::startCall(const LLUUID& id)
{
return;
}
std::string name;
gCacheName->getFullName(id, name);
LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id, true);
if (session_id != LLUUID::null)
{
gIMMgr->startCall(session_id);
}
make_ui_sound("UISndStartIM");
LLAvatarNameCache::get(id,
boost::bind(&on_avatar_name_cache_start_call, _1, _2));
}
// static
@ -329,14 +322,14 @@ void LLAvatarActions::showProfile(const LLUUID& id)
// static
void LLAvatarActions::showOnMap(const LLUUID& id)
{
std::string name;
if (!gCacheName->getFullName(id, name))
LLAvatarName av_name;
if (!LLAvatarNameCache::get(id, &av_name))
{
gCacheName->get(id, FALSE, boost::bind(&LLAvatarActions::showOnMap, id));
LLAvatarNameCache::get(id, boost::bind(&LLAvatarActions::showOnMap, id));
return;
}
gFloaterWorldMap->trackAvatar(id, name);
gFloaterWorldMap->trackAvatar(id, av_name.mDisplayName);
LLFloaterReg::showInstance("world_map");
}
@ -443,17 +436,27 @@ namespace action_give_inventory
}
/**
* Checks My Inventory visibility.
* @return active inventory panel, or NULL if there's no such panel
*/
static bool is_give_inventory_acceptable()
static LLInventoryPanel* get_active_inventory_panel()
{
LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
if (!active_panel)
{
active_panel = get_outfit_editor_inventory_panel();
if (!active_panel) return false;
}
return active_panel;
}
/**
* Checks My Inventory visibility.
*/
static bool is_give_inventory_acceptable()
{
LLInventoryPanel* active_panel = get_active_inventory_panel();
if (!active_panel) return false;
// check selection in the panel
const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
if (inventory_selected_uuids.empty()) return false; // nothing selected
@ -486,14 +489,15 @@ namespace action_give_inventory
return acceptable;
}
static void build_residents_string(const std::vector<std::string>& avatar_names, std::string& residents_string)
static void build_residents_string(const std::vector<LLAvatarName> avatar_names, std::string& residents_string)
{
llassert(avatar_names.size() > 0);
const std::string& separator = LLTrans::getString("words_separator");
for (std::vector<std::string>::const_iterator it = avatar_names.begin(); ; )
for (std::vector<LLAvatarName>::const_iterator it = avatar_names.begin(); ; )
{
residents_string.append(*it);
LLAvatarName av_name = *it;
residents_string.append(av_name.mDisplayName);
if (++it == avatar_names.end())
{
break;
@ -530,7 +534,7 @@ namespace action_give_inventory
struct LLShareInfo : public LLSingleton<LLShareInfo>
{
std::vector<std::string> mAvatarNames;
std::vector<LLAvatarName> mAvatarNames;
uuid_vec_t mAvatarUuids;
};
@ -543,12 +547,8 @@ namespace action_give_inventory
return;
}
LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
if (!active_panel)
{
active_panel = get_outfit_editor_inventory_panel();
if (!active_panel) return;
}
LLInventoryPanel* active_panel = get_active_inventory_panel();
if (!active_panel) return;
const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
if (inventory_selected_uuids.empty())
@ -595,7 +595,7 @@ namespace action_give_inventory
}
else
{
LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id);
LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id);
shared = true;
}
}
@ -627,17 +627,12 @@ namespace action_give_inventory
* @param avatar_names - avatar names request to be sent.
* @param avatar_uuids - avatar names request to be sent.
*/
static void give_inventory(const std::vector<std::string>& avatar_names, const uuid_vec_t& avatar_uuids)
static void give_inventory(const uuid_vec_t& avatar_uuids, const std::vector<LLAvatarName> avatar_names)
{
llassert(avatar_names.size() == avatar_uuids.size());
LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
if (!active_panel)
{
active_panel = get_outfit_editor_inventory_panel();
if (!active_panel) return;
}
LLInventoryPanel* active_panel = get_active_inventory_panel();
if (!active_panel) return;
const uuid_set_t inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList();
if (inventory_selected_uuids.empty())
@ -672,12 +667,59 @@ void LLAvatarActions::shareWithAvatars()
LLNotificationsUtil::add("ShareNotification");
}
// static
bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NULL*/)
{
using namespace action_give_inventory;
if (!inv_panel)
{
LLInventoryPanel* active_panel = get_active_inventory_panel();
if (!active_panel) return false;
inv_panel = active_panel;
}
// check selection in the panel
LLFolderView* root_folder = inv_panel->getRootFolder();
const uuid_set_t inventory_selected_uuids = root_folder->getSelectionList();
if (inventory_selected_uuids.empty()) return false; // nothing selected
bool can_share = true;
uuid_set_t::const_iterator it = inventory_selected_uuids.begin();
const uuid_set_t::const_iterator it_end = inventory_selected_uuids.end();
for (; it != it_end; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
// any category can be offered.
if (inv_cat)
{
continue;
}
// check if inventory item can be given
LLFolderViewItem* item = root_folder->getItemByID(*it);
if (!item) return false;
LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getListener());
if (bridge && bridge->canShare())
{
continue;
}
// there are neither item nor category in inventory
can_share = false;
break;
}
return can_share;
}
// static
void LLAvatarActions::toggleBlock(const LLUUID& id)
{
std::string name;
gCacheName->getFullName(id, name);
gCacheName->getFullName(id, name); // needed for mute
LLMute mute(id, name, LLMute::AGENT);
if (LLMuteList::getInstance()->isMuted(mute.mID, mute.mName))
@ -865,23 +907,6 @@ bool LLAvatarActions::handleUnfreeze(const LLSD& notification, const LLSD& respo
}
return false;
}
// static
bool LLAvatarActions::callbackAddFriend(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (option == 0)
{
// Servers older than 1.25 require the text of the message to be the
// calling card folder ID for the offering user. JC
LLUUID calling_card_folder_id =
gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
std::string message = calling_card_folder_id.asString();
requestFriendship(notification["payload"]["id"].asUUID(),
notification["payload"]["name"].asString(),
message);
}
return false;
}
// static
void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message)
@ -899,7 +924,6 @@ void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::stri
LLSD payload;
payload["from_id"] = target_id;
payload["SESSION_NAME"] = target_name;
payload["SUPPRESS_TOAST"] = true;
LLNotificationsUtil::add("FriendshipOffered", args, payload);
}
@ -914,16 +938,16 @@ bool LLAvatarActions::isFriend(const LLUUID& id)
bool LLAvatarActions::isBlocked(const LLUUID& id)
{
std::string name;
gCacheName->getFullName(id, name);
gCacheName->getFullName(id, name); // needed for mute
return LLMuteList::getInstance()->isMuted(id, name);
}
// static
bool LLAvatarActions::canBlock(const LLUUID& id)
{
std::string firstname, lastname;
gCacheName->getName(id, firstname, lastname);
bool is_linden = !LLStringUtil::compareStrings(lastname, "Linden");
std::string full_name;
gCacheName->getFullName(id, full_name); // needed for mute
bool is_linden = (full_name.find("Linden") != std::string::npos);
bool is_self = id == gAgentID;
return !is_self && !is_linden;
}

View File

@ -34,6 +34,8 @@
#include <string>
#include <vector>
class LLInventoryPanel;
/**
* Friend-related actions (add, remove, offer teleport, etc)
*/
@ -183,8 +185,16 @@ public:
*/
static bool canOfferTeleport(const uuid_vec_t& ids);
/**
* Checks whether all items selected in the given inventory panel can be shared
*
* @param inv_panel Inventory panel to get selection from. If NULL, the active inventory panel is used.
*
* @return false if the selected items cannot be shared or the active inventory panel cannot be obtained
*/
static bool canShareSelectedItems(LLInventoryPanel* inv_panel = NULL);
private:
static bool callbackAddFriend(const LLSD& notification, const LLSD& response);
static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response);
static bool handleRemove(const LLSD& notification, const LLSD& response);
static bool handlePay(const LLSD& notification, const LLSD& response, LLUUID avatar_id);

View File

@ -28,17 +28,19 @@
#include "llavatariconctrl.h"
// viewer includes
#include "llagent.h"
#include "llavatarconstants.h"
#include "llcallingcard.h" // for LLAvatarTracker
#include "llavataractions.h"
#include "llmenugl.h"
#include "lluictrlfactory.h"
#include "llcachename.h"
#include "llagentdata.h"
#include "llimfloater.h"
// library includes
#include "llavatarnamecache.h"
#define MENU_ITEM_VIEW_PROFILE 0
#define MENU_ITEM_SEND_IM 1
@ -227,6 +229,9 @@ void LLAvatarIconCtrl::setValue(const LLSD& value)
// Check if cache already contains image_id for that avatar
if (!updateFromCache())
{
// *TODO: Consider getting avatar icon/badge directly from
// People API, rather than sending AvatarPropertyRequest
// messages. People API already hits the user table.
LLIconCtrl::setValue(mDefaultIconName);
app->addObserver(mAvatarId, this);
app->sendAvatarPropertiesRequest(mAvatarId);
@ -238,10 +243,9 @@ void LLAvatarIconCtrl::setValue(const LLSD& value)
LLIconCtrl::setValue(value);
}
if (gCacheName)
{
gCacheName->get(mAvatarId, FALSE, boost::bind(&LLAvatarIconCtrl::nameUpdatedCallback, this, _1, _2, _3, _4));
}
LLAvatarNameCache::get(mAvatarId,
boost::bind(&LLAvatarIconCtrl::onAvatarNameCache,
this, _1, _2));
}
bool LLAvatarIconCtrl::updateFromCache()
@ -284,24 +288,21 @@ void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type)
}
}
void LLAvatarIconCtrl::nameUpdatedCallback(
const LLUUID& id,
const std::string& first,
const std::string& last,
BOOL is_group)
void LLAvatarIconCtrl::onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
{
if (id == mAvatarId)
if (agent_id == mAvatarId)
{
mFirstName = first;
mLastName = last;
// Most avatar icon controls are next to a UI element that shows
// a display name, so only show username.
mFullName = av_name.mUsername;
if (mDrawTooltip)
{
setToolTip(mFirstName + " " + mLastName);
setToolTip(mFullName);
}
else
{
setToolTip(std::string(""));
setToolTip(std::string());
}
}
}

View File

@ -31,6 +31,8 @@
#include "llavatarpropertiesprocessor.h"
#include "llviewermenu.h"
class LLAvatarName;
class LLAvatarIconIDCache: public LLSingleton<LLAvatarIconIDCache>
{
public:
@ -84,22 +86,16 @@ public:
// LLAvatarPropertiesProcessor observer trigger
virtual void processProperties(void* data, EAvatarProcessorType type);
void nameUpdatedCallback(
const LLUUID& id,
const std::string& first,
const std::string& last,
BOOL is_group);
void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
const LLUUID& getAvatarId() const { return mAvatarId; }
const std::string& getFirstName() const { return mFirstName; }
const std::string& getLastName() const { return mLastName; }
const std::string& getFullName() const { return mFullName; }
void setDrawTooltip(bool value) { mDrawTooltip = value;}
protected:
LLUUID mAvatarId;
std::string mFirstName;
std::string mLastName;
std::string mFullName;
bool mDrawTooltip;
std::string mDefaultIconName;

View File

@ -38,6 +38,7 @@
// newview
#include "llagentdata.h" // for comparator
#include "llavatariconctrl.h"
#include "llavatarnamecache.h"
#include "llcallingcard.h" // for LLAvatarTracker
#include "llcachename.h"
#include "lllistcontextmenu.h"
@ -131,6 +132,7 @@ LLAvatarList::LLAvatarList(const Params& p)
, mShowLastInteractionTime(p.show_last_interaction_time)
, mContextMenu(NULL)
, mDirty(true) // to force initial update
, mNeedUpdateNames(false)
, mLITUpdateTimer(NULL)
, mShowIcons(true)
, mShowInfoBtn(p.show_info_btn)
@ -149,8 +151,17 @@ LLAvatarList::LLAvatarList(const Params& p)
mLITUpdateTimer->setTimerExpirySec(0); // zero to force initial update
mLITUpdateTimer->start();
}
LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLAvatarList::handleDisplayNamesOptionChanged, this));
}
void LLAvatarList::handleDisplayNamesOptionChanged()
{
mNeedUpdateNames = true;
}
LLAvatarList::~LLAvatarList()
{
delete mLITUpdateTimer;
@ -170,6 +181,11 @@ void LLAvatarList::draw()
LLFlatListViewEx::draw();
if (mNeedUpdateNames)
{
updateAvatarNames();
}
if (mDirty)
refresh();
@ -233,7 +249,6 @@ void LLAvatarList::addAvalineItem(const LLUUID& item_id, const LLUUID& session_i
//////////////////////////////////////////////////////////////////////////
// PROTECTED SECTION
//////////////////////////////////////////////////////////////////////////
void LLAvatarList::refresh()
{
bool have_names = TRUE;
@ -252,12 +267,15 @@ void LLAvatarList::refresh()
// Handle added items.
unsigned nadded = 0;
const std::string waiting_str = LLTrans::getString("AvatarNameWaiting");
for (uuid_vec_t::const_iterator it=added.begin(); it != added.end(); it++)
{
std::string name;
const LLUUID& buddy_id = *it;
have_names &= (bool)gCacheName->getFullName(buddy_id, name);
if (!have_filter || findInsensitive(name, mNameFilter))
LLAvatarName av_name;
have_names &= LLAvatarNameCache::get(buddy_id, &av_name);
if (!have_filter || findInsensitive(av_name.mDisplayName, mNameFilter))
{
if (nadded >= ADD_LIMIT)
{
@ -266,7 +284,11 @@ void LLAvatarList::refresh()
}
else
{
addNewItem(buddy_id, name, LLAvatarTracker::instance().isBuddyOnline(buddy_id));
// *NOTE: If you change the UI to show a different string,
// be sure to change the filter code below.
addNewItem(buddy_id,
av_name.mDisplayName.empty() ? waiting_str : av_name.mDisplayName,
LLAvatarTracker::instance().isBuddyOnline(buddy_id));
modified = true;
nadded++;
}
@ -288,10 +310,10 @@ void LLAvatarList::refresh()
for (std::vector<LLSD>::const_iterator it=cur_values.begin(); it != cur_values.end(); it++)
{
std::string name;
const LLUUID& buddy_id = it->asUUID();
have_names &= (bool)gCacheName->getFullName(buddy_id, name);
if (!findInsensitive(name, mNameFilter))
LLAvatarName av_name;
have_names &= LLAvatarNameCache::get(buddy_id, &av_name);
if (!findInsensitive(av_name.mDisplayName, mNameFilter))
{
removeItemByUUID(buddy_id);
modified = true;
@ -337,20 +359,34 @@ void LLAvatarList::refresh()
onCommit();
}
void LLAvatarList::updateAvatarNames()
{
std::vector<LLPanel*> items;
getItems(items);
for( std::vector<LLPanel*>::const_iterator it = items.begin(); it != items.end(); it++)
{
LLAvatarListItem* item = static_cast<LLAvatarListItem*>(*it);
item->updateAvatarName();
}
mNeedUpdateNames = false;
}
bool LLAvatarList::filterHasMatches()
{
uuid_vec_t values = getIDs();
for (uuid_vec_t::const_iterator it=values.begin(); it != values.end(); it++)
{
std::string name;
const LLUUID& buddy_id = *it;
BOOL have_name = gCacheName->getFullName(buddy_id, name);
LLAvatarName av_name;
bool have_name = LLAvatarNameCache::get(buddy_id, &av_name);
// If name has not been loaded yet we consider it as a match.
// When the name will be loaded the filter will be applied again(in refresh()).
if (have_name && !findInsensitive(name, mNameFilter))
if (have_name && !findInsensitive(av_name.mDisplayName, mNameFilter))
{
continue;
}
@ -384,7 +420,7 @@ S32 LLAvatarList::notifyParent(const LLSD& info)
void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos)
{
LLAvatarListItem* item = new LLAvatarListItem();
item->setName(name);
// This sets the name as a side effect
item->setAvatarId(id, mSessionID, mIgnoreOnlineStatus);
item->setOnline(mIgnoreOnlineStatus ? true : is_online);
item->showLastInteractionTime(mShowLastInteractionTime);
@ -551,11 +587,13 @@ void LLAvalineListItem::setName(const std::string& name)
std::string hidden_name = LLTrans::getString("AvalineCaller", args);
LL_DEBUGS("Avaline") << "Avaline caller: " << uuid << ", name: " << hidden_name << LL_ENDL;
LLAvatarListItem::setName(hidden_name);
LLAvatarListItem::setAvatarName(hidden_name);
LLAvatarListItem::setAvatarToolTip(hidden_name);
}
else
{
const std::string& formatted_phone = LLTextUtil::formatPhoneNumber(name);
LLAvatarListItem::setName(formatted_phone);
LLAvatarListItem::setAvatarName(formatted_phone);
LLAvatarListItem::setAvatarToolTip(formatted_phone);
}
}

View File

@ -28,7 +28,6 @@
#define LL_LLAVATARLIST_H
#include "llflatlistview.h"
#include "llavatarlistitem.h"
class LLTimer;
@ -96,6 +95,7 @@ public:
virtual S32 notifyParent(const LLSD& info);
void addAvalineItem(const LLUUID& item_id, const LLUUID& session_id, const std::string& item_name);
void handleDisplayNamesOptionChanged();
protected:
void refresh();
@ -105,14 +105,17 @@ protected:
const uuid_vec_t& vnew,
uuid_vec_t& vadded,
uuid_vec_t& vremoved);
void updateLastInteractionTimes();
void updateLastInteractionTimes();
void rebuildNames();
void onItemDoubleClicked(LLUICtrl* ctrl, S32 x, S32 y, MASK mask);
void updateAvatarNames();
private:
bool mIgnoreOnlineStatus;
bool mShowLastInteractionTime;
bool mDirty;
bool mNeedUpdateNames;
bool mShowIcons;
bool mShowInfoBtn;
bool mShowProfileBtn;

View File

@ -35,6 +35,7 @@
#include "lltextutil.h"
#include "llagent.h"
#include "llavatarnamecache.h"
#include "llavatariconctrl.h"
#include "lloutputmonitorctrl.h"
@ -186,11 +187,16 @@ void LLAvatarListItem::setOnline(bool online)
setState(online ? IS_ONLINE : IS_OFFLINE);
}
void LLAvatarListItem::setName(const std::string& name)
void LLAvatarListItem::setAvatarName(const std::string& name)
{
setNameInternal(name, mHighlihtSubstring);
}
void LLAvatarListItem::setAvatarToolTip(const std::string& tooltip)
{
mAvatarName->setToolTip(tooltip);
}
void LLAvatarListItem::setHighlight(const std::string& highlight)
{
setNameInternal(mAvatarName->getText(), mHighlihtSubstring = highlight);
@ -249,7 +255,8 @@ void LLAvatarListItem::setAvatarId(const LLUUID& id, const LLUUID& session_id, b
mAvatarIcon->setValue(id);
// Set avatar name.
gCacheName->get(id, FALSE, boost::bind(&LLAvatarListItem::onNameCache, this, _2, _3));
LLAvatarNameCache::get(id,
boost::bind(&LLAvatarListItem::onAvatarNameCache, this, _2));
}
}
@ -335,23 +342,33 @@ const LLUUID& LLAvatarListItem::getAvatarId() const
return mAvatarId;
}
const std::string LLAvatarListItem::getAvatarName() const
std::string LLAvatarListItem::getAvatarName() const
{
return mAvatarName->getValue();
}
//== PRIVATE SECTION ==========================================================
std::string LLAvatarListItem::getAvatarToolTip() const
{
return mAvatarName->getToolTip();
}
void LLAvatarListItem::updateAvatarName()
{
LLAvatarNameCache::get(getAvatarId(),
boost::bind(&LLAvatarListItem::onAvatarNameCache, this, _2));
}
//== PRIVATE SECITON ==========================================================
void LLAvatarListItem::setNameInternal(const std::string& name, const std::string& highlight)
{
LLTextUtil::textboxSetHighlightedVal(mAvatarName, mAvatarNameStyle, name, highlight);
mAvatarName->setToolTip(name);
}
void LLAvatarListItem::onNameCache(const std::string& first_name, const std::string& last_name)
void LLAvatarListItem::onAvatarNameCache(const LLAvatarName& av_name)
{
std::string name = first_name + " " + last_name;
setName(name);
setAvatarName(av_name.mDisplayName);
setAvatarToolTip(av_name.mUsername);
//requesting the list to resort
notifyParent(LLSD().with("sort", LLSD()));

View File

@ -36,6 +36,7 @@
#include "llcallingcard.h" // for LLFriendObserver
class LLAvatarIconCtrl;
class LLAvatarName;
class LLIconCtrl;
class LLAvatarListItem : public LLPanel, public LLFriendObserver
@ -86,7 +87,9 @@ public:
virtual void changed(U32 mask); // from LLFriendObserver
void setOnline(bool online);
void setName(const std::string& name);
void updateAvatarName(); // re-query the name cache
void setAvatarName(const std::string& name);
void setAvatarToolTip(const std::string& tooltip);
void setHighlight(const std::string& highlight);
void setState(EItemState item_style);
void setAvatarId(const LLUUID& id, const LLUUID& session_id, bool ignore_status_changes = false, bool is_resident = true);
@ -100,7 +103,8 @@ public:
void setAvatarIconVisible(bool visible);
const LLUUID& getAvatarId() const;
const std::string getAvatarName() const;
std::string getAvatarName() const;
std::string getAvatarToolTip() const;
void onInfoBtnClick();
void onProfileBtnClick();
@ -154,7 +158,7 @@ private:
} EAvatarListItemChildIndex;
void setNameInternal(const std::string& name, const std::string& highlight);
void onNameCache(const std::string& first_name, const std::string& last_name);
void onAvatarNameCache(const LLAvatarName& av_name);
std::string formatSeconds(U32 secs);

View File

@ -770,7 +770,7 @@ void LLBottomTray::loadButtonsOrder()
}
// Nearbychat is not stored in order settings file, but it must be the first of the panels, so moving it
// manually here
mToolbarStack->movePanel(mNearbyChatBar, NULL, true);
mToolbarStack->movePanel(mChatBarContainer, NULL, true);
}
void LLBottomTray::onDraggableButtonMouseUp(LLUICtrl* ctrl, S32 x, S32 y)
@ -1026,7 +1026,7 @@ S32 LLBottomTray::processWidthDecreased(S32 delta_width)
processShrinkButtons(delta_width, buttons_freed_width);
}
// 3. Decreasing width of nearby chat.
const S32 chatbar_panel_min_width = get_panel_min_width(mToolbarStack, mNearbyChatBar);
const S32 chatbar_panel_min_width = get_panel_min_width(mToolbarStack, mChatBarContainer);
const S32 chatbar_panel_width = mChatBarContainer->getRect().getWidth();
if (still_should_be_processed && chatbar_panel_width > chatbar_panel_min_width)
{

View File

@ -27,13 +27,14 @@
#include "llviewerprecompiledheaders.h"
#include "llcallfloater.h"
#include "llnotificationsutil.h"
#include "lltrans.h"
#include "llcallfloater.h"
#include "llagent.h"
#include "llagentdata.h" // for gAgentID
#include "llavatarnamecache.h"
#include "llavatariconctrl.h"
#include "llavatarlist.h"
#include "llbottomtray.h"
@ -44,6 +45,7 @@
#include "llspeakers.h"
#include "lltextutil.h"
#include "lltransientfloatermgr.h"
#include "llviewerdisplayname.h"
#include "llviewerwindow.h"
#include "llvoicechannel.h"
#include "llviewerparcelmgr.h"
@ -77,7 +79,8 @@ public:
void setName(const std::string& name)
{
const std::string& formatted_phone = LLTextUtil::formatPhoneNumber(name);
LLAvatarListItem::setName(formatted_phone);
LLAvatarListItem::setAvatarName(formatted_phone);
LLAvatarListItem::setAvatarToolTip(formatted_phone);
}
void setSpeakerId(const LLUUID& id) { mSpeakingIndicator->setSpeakerId(id); }
@ -112,6 +115,11 @@ LLCallFloater::LLCallFloater(const LLSD& key)
// force docked state since this floater doesn't save it between recreations
setDocked(true);
// update the agent's name if display name setting change
LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLCallFloater::updateAgentModeratorState, this));
LLViewerDisplayName::addNameChangedCallback(boost::bind(&LLCallFloater::updateAgentModeratorState, this));
}
LLCallFloater::~LLCallFloater()
@ -368,9 +376,31 @@ void LLCallFloater::sOnCurrentChannelChanged(const LLUUID& /*session_id*/)
call_floater->connectToChannel(channel);
}
void LLCallFloater::onAvatarNameCache(const LLUUID& agent_id,
const LLAvatarName& av_name)
{
LLStringUtil::format_map_t args;
args["[NAME]"] = av_name.getCompleteName();
std::string title = getString("title_peer_2_peer", args);
setTitle(title);
}
void LLCallFloater::updateTitle()
{
LLVoiceChannel* voice_channel = LLVoiceChannel::getCurrentVoiceChannel();
if (mVoiceType == VC_PEER_TO_PEER)
{
LLUUID session_id = voice_channel->getSessionID();
LLIMModel::LLIMSession* im_session =
LLIMModel::getInstance()->findIMSession(session_id);
if (im_session)
{
LLAvatarNameCache::get(im_session->mOtherParticipantID,
boost::bind(&LLCallFloater::onAvatarNameCache,
this, _1, _2));
return;
}
}
std::string title;
switch (mVoiceType)
{
@ -415,9 +445,10 @@ void LLCallFloater::initAgentData()
{
mAgentPanel->getChild<LLUICtrl>("user_icon")->setValue(gAgentID);
std::string name;
gCacheName->getFullName(gAgentID, name);
mAgentPanel->getChild<LLUICtrl>("user_text")->setValue(name);
// Just use display name, because it's you
LLAvatarName av_name;
LLAvatarNameCache::get( gAgentID, &av_name );
mAgentPanel->getChild<LLUICtrl>("user_text")->setValue(av_name.mDisplayName);
mSpeakingIndicator = mAgentPanel->getChild<LLOutputMonitorCtrl>("speaking_indicator");
mSpeakingIndicator->setSpeakerId(gAgentID);
@ -435,12 +466,12 @@ void LLCallFloater::setModeratorMutedVoice(bool moderator_muted)
mSpeakingIndicator->setIsMuted(moderator_muted);
}
void LLCallFloater::updateAgentModeratorState()
void LLCallFloater::onModeratorNameCache(const LLAvatarName& av_name)
{
std::string name;
gCacheName->getFullName(gAgentID, name);
name = av_name.mDisplayName;
if(gAgent.isInGroup(mSpeakerManager->getSessionID()))
if(mSpeakerManager && gAgent.isInGroup(mSpeakerManager->getSessionID()))
{
// This method can be called when LLVoiceChannel.mState == STATE_NO_CHANNEL_INFO
// in this case there are not any speakers yet.
@ -458,6 +489,11 @@ void LLCallFloater::updateAgentModeratorState()
mAgentPanel->getChild<LLUICtrl>("user_text")->setValue(name);
}
void LLCallFloater::updateAgentModeratorState()
{
LLAvatarNameCache::get(gAgentID, boost::bind(&LLCallFloater::onModeratorNameCache, this, _2));
}
static void get_voice_participants_uuids(uuid_vec_t& speakers_uuids)
{
// Get a list of participants from VoiceClient

View File

@ -34,6 +34,7 @@
class LLAvatarList;
class LLAvatarListItem;
class LLAvatarName;
class LLNonAvatarCaller;
class LLOutputMonitorCtrl;
class LLParticipantList;
@ -116,11 +117,16 @@ private:
*/
void onAvatarListRefreshed();
/**
* Updates window title with an avatar name
*/
void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
void updateTitle();
void initAgentData();
void setModeratorMutedVoice(bool moderator_muted);
void updateAgentModeratorState();
void onModeratorNameCache(const LLAvatarName& av_name);
/**
* Sets initial participants voice states in avatar list (Invited, Joined, Has Left).

View File

@ -37,6 +37,7 @@
//#include <iterator>
#include "indra_constants.h"
#include "llavatarnamecache.h"
#include "llcachename.h"
#include "llstl.h"
#include "lltimer.h"
@ -44,6 +45,7 @@
#include "message.h"
#include "llagent.h"
#include "llavatarnamecache.h"
#include "llbutton.h"
#include "llinventoryobserver.h"
#include "llinventorymodel.h"
@ -90,8 +92,10 @@ const F32 OFFLINE_SECONDS = FIND_FREQUENCY + 8.0f;
// static
LLAvatarTracker LLAvatarTracker::sInstance;
static void on_avatar_name_cache_notify(const LLUUID& agent_id,
const LLAvatarName& av_name,
bool online,
LLSD payload);
///----------------------------------------------------------------------------
/// Class LLAvatarTracker
@ -244,7 +248,7 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
using namespace std;
U32 new_buddy_count = 0;
std::string first,last;
std::string full_name;
LLUUID agent_id;
for(buddy_map_t::const_iterator itr = buds.begin(); itr != buds.end(); ++itr)
{
@ -254,7 +258,8 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
{
++new_buddy_count;
mBuddyInfo[agent_id] = (*itr).second;
gCacheName->getName(agent_id, first, last);
// IDEVO: is this necessary? name is unused?
gCacheName->getFullName(agent_id, full_name);
addChangedMask(LLFriendObserver::ADD, agent_id);
lldebugs << "Added buddy " << agent_id
<< ", " << (mBuddyInfo[agent_id]->isOnline() ? "Online" : "Offline")
@ -627,12 +632,9 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg)
{
if((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)
{
std::string name;
LLSD args;
if(gCacheName->getFullName(agent_id, name))
{
args["NAME"] = name;
}
args["NAME"] = LLSLURL("agent", agent_id, "displayname").getSLURLString();
LLSD payload;
payload["from_id"] = agent_id;
if(LLRelationship::GRANT_MODIFY_OBJECTS & new_rights)
@ -674,8 +676,6 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
{
tracking_id = mTrackingData->mAvatarID;
}
BOOL notify = FALSE;
LLSD args;
LLSD payload;
for(S32 i = 0; i < count; ++i)
{
@ -685,17 +685,6 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
if(info)
{
setBuddyOnline(agent_id,online);
if(chat_notify)
{
std::string first, last;
if(gCacheName->getName(agent_id, first, last))
{
notify = TRUE;
args["FIRST"] = first;
args["LAST"] = last;
}
}
}
else
{
@ -711,29 +700,12 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
// *TODO: get actual inventory id
gInventory.addChangedMask(LLInventoryObserver::CALLING_CARD, LLUUID::null);
}
if(notify)
if(chat_notify)
{
// Popup a notify box with online status of this agent
LLNotificationPtr notification;
if (online)
{
notification =
LLNotificationsUtil::add("FriendOnline",
args,
payload.with("respond_on_mousedown", TRUE),
boost::bind(&LLAvatarActions::startIM, agent_id));
}
else
{
notification =
LLNotificationsUtil::add("FriendOffline", args, payload);
}
// If there's an open IM session with this agent, send a notification there too.
LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, agent_id);
std::string notify_msg = notification->getMessage();
LLIMModel::instance().proccessOnlineOfflineNotification(session_id, notify_msg);
// Look up the name of this agent for the notification
LLAvatarNameCache::get(agent_id,
boost::bind(&on_avatar_name_cache_notify,
_1, _2, online, payload));
}
mModifyMask |= LLFriendObserver::ONLINE;
@ -742,6 +714,37 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
}
}
static void on_avatar_name_cache_notify(const LLUUID& agent_id,
const LLAvatarName& av_name,
bool online,
LLSD payload)
{
// Popup a notify box with online status of this agent
// Use display name only because this user is your friend
LLSD args;
args["NAME"] = av_name.mDisplayName;
LLNotificationPtr notification;
if (online)
{
notification =
LLNotificationsUtil::add("FriendOnline",
args,
payload.with("respond_on_mousedown", TRUE),
boost::bind(&LLAvatarActions::startIM, agent_id));
}
else
{
notification =
LLNotificationsUtil::add("FriendOffline", args, payload);
}
// If there's an open IM session with this agent, send a notification there too.
LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, agent_id);
std::string notify_msg = notification->getMessage();
LLIMModel::instance().proccessOnlineOfflineNotification(session_id, notify_msg);
}
void LLAvatarTracker::formFriendship(const LLUUID& id)
{
if(id.notNull())
@ -862,10 +865,9 @@ bool LLCollectProxyBuddies::operator()(const LLUUID& buddy_id, LLRelationship* b
bool LLCollectMappableBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
{
gCacheName->getName(buddy_id, mFirst, mLast);
std::ostringstream fullname;
fullname << mFirst << " " << mLast;
buddy_map_t::value_type value(fullname.str(), buddy_id);
LLAvatarName av_name;
LLAvatarNameCache::get( buddy_id, &av_name);
buddy_map_t::value_type value(av_name.mDisplayName, buddy_id);
if(buddy->isOnline() && buddy->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION))
{
mMappable.insert(value);
@ -875,10 +877,8 @@ bool LLCollectMappableBuddies::operator()(const LLUUID& buddy_id, LLRelationship
bool LLCollectOnlineBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
{
gCacheName->getName(buddy_id, mFirst, mLast);
std::ostringstream fullname;
fullname << mFirst << " " << mLast;
buddy_map_t::value_type value(fullname.str(), buddy_id);
gCacheName->getFullName(buddy_id, mFullName);
buddy_map_t::value_type value(mFullName, buddy_id);
if(buddy->isOnline())
{
mOnline.insert(value);
@ -888,10 +888,10 @@ bool LLCollectOnlineBuddies::operator()(const LLUUID& buddy_id, LLRelationship*
bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id, LLRelationship* buddy)
{
gCacheName->getName(buddy_id, mFirst, mLast);
std::ostringstream fullname;
fullname << mFirst << " " << mLast;
buddy_map_t::value_type value(fullname.str(), buddy_id);
LLAvatarName av_name;
LLAvatarNameCache::get(buddy_id, &av_name);
mFullName = av_name.mDisplayName;
buddy_map_t::value_type value(mFullName, buddy_id);
if(buddy->isOnline())
{
mOnline.insert(value);
@ -902,5 +902,3 @@ bool LLCollectAllBuddies::operator()(const LLUUID& buddy_id, LLRelationship* bud
}
return true;
}

View File

@ -235,8 +235,7 @@ public:
virtual bool operator()(const LLUUID& buddy_id, LLRelationship* buddy);
typedef std::map<std::string, LLUUID, LLDictionaryLess> buddy_map_t;
buddy_map_t mMappable;
std::string mFirst;
std::string mLast;
std::string mFullName;
};
// collect dictionary sorted map of name -> agent_id for every online buddy
@ -248,8 +247,7 @@ public:
virtual bool operator()(const LLUUID& buddy_id, LLRelationship* buddy);
typedef std::map<std::string, LLUUID, LLDictionaryLess> buddy_map_t;
buddy_map_t mOnline;
std::string mFirst;
std::string mLast;
std::string mFullName;
};
// collect dictionary sorted map of name -> agent_id for every buddy,
@ -263,8 +261,7 @@ public:
typedef std::map<std::string, LLUUID, LLDictionaryLess> buddy_map_t;
buddy_map_t mOnline;
buddy_map_t mOffline;
std::string mFirst;
std::string mLast;
std::string mFullName;
};
#endif // LL_LLCALLINGCARD_H

View File

@ -26,10 +26,12 @@
#include "llviewerprecompiledheaders.h"
#include "llchathistory.h"
#include "llavatarnamecache.h"
#include "llinstantmessage.h"
#include "llimview.h"
#include "llchathistory.h"
#include "llcommandhandler.h"
#include "llpanel.h"
#include "lluictrlfactory.h"
@ -53,6 +55,7 @@
#include "llworld.h"
#include "lluiconstants.h"
#include "llviewercontrol.h"
#include "llsidetray.h"//for blocked objects panel
@ -98,6 +101,18 @@ LLObjectIMHandler gObjectIMHandler;
class LLChatHistoryHeader: public LLPanel
{
public:
LLChatHistoryHeader()
: LLPanel(),
mPopupMenuHandleAvatar(),
mPopupMenuHandleObject(),
mAvatarID(),
mSourceType(CHAT_SOURCE_UNKNOWN),
mFrom(),
mSessionID(),
mMinUserNameWidth(0),
mUserNameFont(NULL)
{}
static LLChatHistoryHeader* createInstance(const std::string& file_name)
{
LLChatHistoryHeader* pInstance = new LLChatHistoryHeader;
@ -240,7 +255,6 @@ public:
mAvatarID = chat.mFromID;
mSessionID = chat.mSessionID;
mSourceType = chat.mSourceType;
gCacheName->get(mAvatarID, FALSE, boost::bind(&LLChatHistoryHeader::nameUpdatedCallback, this, _1, _2, _3, _4));
//*TODO overly defensive thing, source type should be maintained out there
if((chat.mFromID.isNull() && chat.mFromName.empty()) || chat.mFromName == SYSTEM_FROM && chat.mFromID.isNull())
@ -248,22 +262,40 @@ public:
mSourceType = CHAT_SOURCE_SYSTEM;
}
LLTextBox* userName = getChild<LLTextBox>("user_name");
mUserNameFont = style_params.font();
LLTextBox* user_name = getChild<LLTextBox>("user_name");
user_name->setReadOnlyColor(style_params.readonly_color());
user_name->setColor(style_params.color());
userName->setReadOnlyColor(style_params.readonly_color());
userName->setColor(style_params.color());
userName->setValue(chat.mFromName);
mFrom = chat.mFromName;
if (chat.mFromName.empty() || CHAT_SOURCE_SYSTEM == mSourceType)
if (chat.mFromName.empty()
|| mSourceType == CHAT_SOURCE_SYSTEM
|| mAvatarID.isNull())
{
mFrom = LLTrans::getString("SECOND_LIFE");
userName->setValue(mFrom);
user_name->setValue(mFrom);
updateMinUserNameWidth();
}
else if (mSourceType == CHAT_SOURCE_AGENT
&& chat.mChatStyle != CHAT_STYLE_HISTORY)
{
// ...from a normal user, lookup the name and fill in later.
// *NOTE: Do not do this for chat history logs, otherwise the viewer
// will flood the People API with lookup requests on startup
// Start with blank so sample data from XUI XML doesn't
// flash on the screen
user_name->setValue( LLSD() );
LLAvatarNameCache::get(mAvatarID,
boost::bind(&LLChatHistoryHeader::onAvatarNameCache, this, _1, _2));
}
else {
// ...from an object, just use name as given
mFrom = chat.mFromName;
user_name->setValue(mFrom);
updateMinUserNameWidth();
}
mMinUserNameWidth = style_params.font()->getWidth(userName->getWText().c_str()) + PADDING;
setTimeField(chat);
LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
@ -317,12 +349,39 @@ public:
LLPanel::draw();
}
void nameUpdatedCallback(const LLUUID& id,const std::string& first,const std::string& last,BOOL is_group)
void updateMinUserNameWidth()
{
if (id != mAvatarID)
return;
mFrom = first + " " + last;
if (mUserNameFont)
{
LLTextBox* user_name = getChild<LLTextBox>("user_name");
const LLWString& text = user_name->getWText();
mMinUserNameWidth = mUserNameFont->getWidth(text.c_str()) + PADDING;
}
}
void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name)
{
mFrom = av_name.mDisplayName;
LLTextBox* user_name = getChild<LLTextBox>("user_name");
user_name->setValue( LLSD(av_name.mDisplayName ) );
user_name->setToolTip( av_name.mUsername );
if (gSavedSettings.getBOOL("NameTagShowUsernames") && LLAvatarNameCache::useDisplayNames())
{
LLStyle::Params style_params_name;
LLColor4 userNameColor = LLUIColorTable::instance().getColor("EmphasisColor");
style_params_name.color(userNameColor);
style_params_name.font.name("SansSerifSmall");
style_params_name.font.style("NORMAL");
style_params_name.readonly_color(userNameColor);
user_name->appendText(" - " + av_name.mUsername, FALSE, style_params_name);
}
setToolTip( av_name.mUsername );
// name might have changed, update width
updateMinUserNameWidth();
}
protected:
static const S32 PADDING = 20;
@ -449,6 +508,7 @@ protected:
LLUUID mSessionID;
S32 mMinUserNameWidth;
const LLFontGL* mUserNameFont;
};
LLUICtrl* LLChatHistoryHeader::sInfoCtrl = NULL;

View File

@ -169,7 +169,9 @@ void LLNearbyChatToastPanel::init(LLSD& notification)
{
std::string str_sender;
str_sender = fromName;
str_sender = "<nolink>"; // disable parsing URLs in object names (STORM-358)
str_sender += fromName;
str_sender += "</nolink>";
str_sender+=" ";

View File

@ -166,3 +166,23 @@ std::string LLDateUtil::ageFromDate(const std::string& date_string)
{
return ageFromDate(date_string, LLDate::now());
}
//std::string LLDateUtil::ageFromDateISO(const std::string& date_string,
// const LLDate& now)
//{
// S32 born_month, born_day, born_year;
// S32 matched = sscanf(date_string.c_str(), "%d-%d-%d",
// &born_year, &born_month, &born_day);
// if (matched != 3) return "???";
// date.fromYMDHMS(year, month, day);
// F64 secs_since_epoch = date.secondsSinceEpoch();
// // Correct for the fact that specified date is in Pacific time, == UTC - 8
// secs_since_epoch += 8.0 * 60.0 * 60.0;
// date.secondsSinceEpoch(secs_since_epoch);
// return ageFromDate(born_year, born_month, born_day, now);
//}
//
//std::string LLDateUtil::ageFromDateISO(const std::string& date_string)
//{
// return ageFromDateISO(date_string, LLDate::now());
//}

View File

@ -61,6 +61,14 @@ namespace LLDateUtil
// Calls the above with LLDate::now()
std::string ageFromDate(const std::string& date_string);
// As above, for YYYY-MM-DD dates
//std::string ageFromDateISO(const std::string& date_string, const LLDate& now);
// Calls the above with LLDate::now()
//std::string ageFromDateISO(const std::string& date_string);
//std::string ageFromDate(S32 born_year, S32 born_month, S32 born_day, const LLDate& now);
}
#endif

View File

@ -48,6 +48,7 @@ class LLCamera;
class LLDrawPool;
class LLDrawable;
class LLFace;
class LLFacePool;
class LLSpatialGroup;
class LLSpatialBridge;
class LLSpatialPartition;

View File

@ -1,98 +0,0 @@
/**
* @file lleventinfo.cpp
* @brief LLEventInfo class implementation
*
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "lleventinfo.h"
#include "lluuid.h"
#include "message.h"
LLEventInfo::cat_map LLEventInfo::sCategories;
void LLEventInfo::unpack(LLMessageSystem *msg)
{
U32 event_id;
msg->getU32("EventData", "EventID", event_id);
mID = event_id;
msg->getString("EventData", "Name", mName);
msg->getString("EventData", "Category", mCategoryStr);
msg->getString("EventData", "Date", mTimeStr);
U32 duration;
msg->getU32("EventData","Duration",duration);
mDuration = duration;
U32 date;
msg->getU32("EventData", "DateUTC", date);
mUnixTime = date;
msg->getString("EventData", "Desc", mDesc);
std::string buffer;
msg->getString("EventData", "Creator", buffer);
mRunByID = LLUUID(buffer);
U32 foo;
msg->getU32("EventData", "Cover", foo);
mHasCover = foo ? TRUE : FALSE;
if (mHasCover)
{
U32 cover;
msg->getU32("EventData", "Amount", cover);
mCover = cover;
}
msg->getString("EventData", "SimName", mSimName);
msg->getVector3d("EventData", "GlobalPos", mPosGlobal);
// Mature content
U32 event_flags;
msg->getU32("EventData", "EventFlags", event_flags);
mEventFlags = event_flags;
}
// static
void LLEventInfo::loadCategories(const LLSD& options)
{
for(LLSD::array_const_iterator resp_it = options.beginArray(),
end = options.endArray(); resp_it != end; ++resp_it)
{
LLSD name = (*resp_it)["category_name"];
if(name.isDefined())
{
LLSD id = (*resp_it)["category_id"];
if(id.isDefined())
{
LLEventInfo::sCategories[id.asInteger()] = name.asString();
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More