diff options
71 files changed, 3769 insertions, 3002 deletions
@@ -42,3 +42,4 @@ dc6483491b4af559060bccaef8e9045a303212dd 2.4.0-beta1 3bc1f50a72e117f4d4ad8d555f0c785ea8cc201e 2.4.0-beta1 25bd6007e3d2fc15db9326ed4b18a24a5969a46a 2.4.0-beta2 1ed382c6a08ba3850b6ce9061bc551ddece0ea07 2.4.0-release +a82e5b1e22c7f90e3c7977d146b80588f004ed0d 2.5.0-start @@ -170,13 +170,7 @@ do mkdir -p "$build_dir" if pre_build "$variant" "$build_dir" >> "$build_log" 2>&1 then - if $build_link_parallel - then - begin_section BuildParallel - ( build "$variant" "$build_dir" > "$build_dir/build.log" 2>&1 ) & - build_processes="$build_processes $!" - end_section BuildParallel - elif $build_coverity + if $build_coverity then mkdir -p "$build_dir/cvbuild" coverity_config=`cygpath --windows "$coverity_dir/config/coverity_config.xml"` @@ -198,7 +192,6 @@ do begin_section CovAnalyze\ &&\ "$coverity_dir"/bin/cov-analyze\ - --cxx\ --security\ --concurrency\ --dir "$coverity_tmpdir"\ @@ -209,14 +202,14 @@ do begin_section CovCommit\ &&\ "$coverity_dir"/bin/cov-commit-defects\ - --product "$coverity_product"\ + --stream "$coverity_product"\ --dir "$coverity_tmpdir"\ - --remote "$coverity_server"\ + --host "$coverity_server"\ --strip-path "$coverity_root"\ --target "$branch/$arch"\ --version "$revision"\ --description "$repo: $variant $revision"\ - --user admin --password admin\ + --user admin --password coverity\ >> "$build_log" 2>&1\ || record_failure "Coverity Build Failed" # since any step could have failed, rely on the enclosing block to close any pending sub-blocks @@ -227,6 +220,12 @@ do then upload_item log "$build_dir"/cvbuild/build-log.txt text/plain fi + elif $build_link_parallel + then + begin_section BuildParallel + ( build "$variant" "$build_dir" > "$build_dir/build.log" 2>&1 ) & + build_processes="$build_processes $!" + end_section BuildParallel else begin_section "Build$variant" build "$variant" "$build_dir" >> "$build_log" 2>&1 diff --git a/doc/contributions.txt b/doc/contributions.txt index d7a5f73ac0..9266ae3c5b 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -219,6 +219,8 @@ Catherine Pfeffer Celierra Darling VWR-1274 VWR-6975 +Coaldust Numbers + VWR-1095 Cron Stardust VWR-10579 Cypren Christenson @@ -370,6 +372,7 @@ Jonathan Yap STORM-679 STORM-737 STORM-726 + STORM-812 VWR-17801 STORM-785 Kage Pixel diff --git a/indra/cmake/GetPrerequisites_2_8.cmake b/indra/cmake/GetPrerequisites_2_8.cmake index 5a24842c89..05ec1539ba 100644 --- a/indra/cmake/GetPrerequisites_2_8.cmake +++ b/indra/cmake/GetPrerequisites_2_8.cmake @@ -1,786 +1,786 @@ -# GetPrerequisites.cmake
-#
-# This script provides functions to list the .dll, .dylib or .so files that an
-# executable or shared library file depends on. (Its prerequisites.)
-#
-# It uses various tools to obtain the list of required shared library files:
-# dumpbin (Windows)
-# ldd (Linux/Unix)
-# otool (Mac OSX)
-#
-# The following functions are provided by this script:
-# gp_append_unique
-# is_file_executable
-# gp_item_default_embedded_path
-# (projects can override with gp_item_default_embedded_path_override)
-# gp_resolve_item
-# (projects can override with gp_resolve_item_override)
-# gp_resolved_file_type
-# gp_file_type
-# get_prerequisites
-# list_prerequisites
-# list_prerequisites_by_glob
-#
-# Requires CMake 2.6 or greater because it uses function, break, return and
-# PARENT_SCOPE.
-
-#=============================================================================
-# Copyright 2008-2009 Kitware, Inc.
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-# (To distributed this file outside of CMake, substitute the full
-# License text for the above reference.)
-
-# gp_append_unique list_var value
-#
-# Append value to the list variable ${list_var} only if the value is not
-# already in the list.
-#
-function(gp_append_unique list_var value)
- set(contains 0)
-
- foreach(item ${${list_var}})
- if("${item}" STREQUAL "${value}")
- set(contains 1)
- break()
- endif("${item}" STREQUAL "${value}")
- endforeach(item)
-
- if(NOT contains)
- set(${list_var} ${${list_var}} "${value}" PARENT_SCOPE)
- endif(NOT contains)
-endfunction(gp_append_unique)
-
-
-# is_file_executable file result_var
-#
-# Return 1 in ${result_var} if ${file} is a binary executable.
-#
-# Return 0 in ${result_var} otherwise.
-#
-function(is_file_executable file result_var)
- #
- # A file is not executable until proven otherwise:
- #
- set(${result_var} 0 PARENT_SCOPE)
-
- get_filename_component(file_full "${file}" ABSOLUTE)
- string(TOLOWER "${file_full}" file_full_lower)
-
- # If file name ends in .exe on Windows, *assume* executable:
- #
- if(WIN32)
- if("${file_full_lower}" MATCHES "\\.exe$")
- set(${result_var} 1 PARENT_SCOPE)
- return()
- endif("${file_full_lower}" MATCHES "\\.exe$")
-
- # A clause could be added here that uses output or return value of dumpbin
- # to determine ${result_var}. In 99%+? practical cases, the exe name
- # match will be sufficient...
- #
- endif(WIN32)
-
- # Use the information returned from the Unix shell command "file" to
- # determine if ${file_full} should be considered an executable file...
- #
- # If the file command's output contains "executable" and does *not* contain
- # "text" then it is likely an executable suitable for prerequisite analysis
- # via the get_prerequisites macro.
- #
- if(UNIX)
- if(NOT file_cmd)
- find_program(file_cmd "file")
- endif(NOT file_cmd)
-
- if(file_cmd)
- execute_process(COMMAND "${file_cmd}" "${file_full}"
- OUTPUT_VARIABLE file_ov
- OUTPUT_STRIP_TRAILING_WHITESPACE
- )
-
- # Replace the name of the file in the output with a placeholder token
- # (the string " _file_full_ ") so that just in case the path name of
- # the file contains the word "text" or "executable" we are not fooled
- # into thinking "the wrong thing" because the file name matches the
- # other 'file' command output we are looking for...
- #
- string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}")
- string(TOLOWER "${file_ov}" file_ov)
-
- #message(STATUS "file_ov='${file_ov}'")
- if("${file_ov}" MATCHES "executable")
- #message(STATUS "executable!")
- if("${file_ov}" MATCHES "text")
- #message(STATUS "but text, so *not* a binary executable!")
- else("${file_ov}" MATCHES "text")
- set(${result_var} 1 PARENT_SCOPE)
- return()
- endif("${file_ov}" MATCHES "text")
- endif("${file_ov}" MATCHES "executable")
- else(file_cmd)
- message(STATUS "warning: No 'file' command, skipping execute_process...")
- endif(file_cmd)
- endif(UNIX)
-endfunction(is_file_executable)
-
-
-# gp_item_default_embedded_path item default_embedded_path_var
-#
-# Return the path that others should refer to the item by when the item
-# is embedded inside a bundle.
-#
-# Override on a per-project basis by providing a project-specific
-# gp_item_default_embedded_path_override function.
-#
-function(gp_item_default_embedded_path item default_embedded_path_var)
-
- # On Windows and Linux, "embed" prerequisites in the same directory
- # as the executable by default:
- #
- set(path "@executable_path")
- set(overridden 0)
-
- # On the Mac, relative to the executable depending on the type
- # of the thing we are embedding:
- #
- if(APPLE)
- #
- # The assumption here is that all executables in the bundle will be
- # in same-level-directories inside the bundle. The parent directory
- # of an executable inside the bundle should be MacOS or a sibling of
- # MacOS and all embedded paths returned from here will begin with
- # "@executable_path/../" and will work from all executables in all
- # such same-level-directories inside the bundle.
- #
-
- # By default, embed things right next to the main bundle executable:
- #
- set(path "@executable_path/../../Contents/MacOS")
-
- # Embed .dylibs right next to the main bundle executable:
- #
- if(item MATCHES "\\.dylib$")
- set(path "@executable_path/../MacOS")
- set(overridden 1)
- endif(item MATCHES "\\.dylib$")
-
- # Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS):
- #
- if(NOT overridden)
- if(item MATCHES "[^/]+\\.framework/")
- set(path "@executable_path/../Frameworks")
- set(overridden 1)
- endif(item MATCHES "[^/]+\\.framework/")
- endif(NOT overridden)
- endif()
-
- # Provide a hook so that projects can override the default embedded location
- # of any given library by whatever logic they choose:
- #
- if(COMMAND gp_item_default_embedded_path_override)
- gp_item_default_embedded_path_override("${item}" path)
- endif(COMMAND gp_item_default_embedded_path_override)
-
- set(${default_embedded_path_var} "${path}" PARENT_SCOPE)
-endfunction(gp_item_default_embedded_path)
-
-
-# gp_resolve_item context item exepath dirs resolved_item_var
-#
-# Resolve an item into an existing full path file.
-#
-# Override on a per-project basis by providing a project-specific
-# gp_resolve_item_override function.
-#
-function(gp_resolve_item context item exepath dirs resolved_item_var)
- set(resolved 0)
- set(resolved_item "${item}")
-
- # Is it already resolved?
- #
- if(EXISTS "${resolved_item}")
- set(resolved 1)
- endif(EXISTS "${resolved_item}")
-
- if(NOT resolved)
- if(item MATCHES "@executable_path")
- #
- # @executable_path references are assumed relative to exepath
- #
- string(REPLACE "@executable_path" "${exepath}" ri "${item}")
- get_filename_component(ri "${ri}" ABSOLUTE)
-
- if(EXISTS "${ri}")
- #message(STATUS "info: embedded item exists (${ri})")
- set(resolved 1)
- set(resolved_item "${ri}")
- else(EXISTS "${ri}")
- message(STATUS "warning: embedded item does not exist '${ri}'")
- endif(EXISTS "${ri}")
- endif(item MATCHES "@executable_path")
- endif(NOT resolved)
-
- if(NOT resolved)
- if(item MATCHES "@loader_path")
- #
- # @loader_path references are assumed relative to the
- # PATH of the given "context" (presumably another library)
- #
- get_filename_component(contextpath "${context}" PATH)
- string(REPLACE "@loader_path" "${contextpath}" ri "${item}")
- get_filename_component(ri "${ri}" ABSOLUTE)
-
- if(EXISTS "${ri}")
- #message(STATUS "info: embedded item exists (${ri})")
- set(resolved 1)
- set(resolved_item "${ri}")
- else(EXISTS "${ri}")
- message(STATUS "warning: embedded item does not exist '${ri}'")
- endif(EXISTS "${ri}")
- endif(item MATCHES "@loader_path")
- endif(NOT resolved)
-
- if(NOT resolved)
- set(ri "ri-NOTFOUND")
- find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH)
- find_file(ri "${item}" ${exepath} ${dirs} /usr/lib)
- if(ri)
- #message(STATUS "info: 'find_file' in exepath/dirs (${ri})")
- set(resolved 1)
- set(resolved_item "${ri}")
- set(ri "ri-NOTFOUND")
- endif(ri)
- endif(NOT resolved)
-
- if(NOT resolved)
- if(item MATCHES "[^/]+\\.framework/")
- set(fw "fw-NOTFOUND")
- find_file(fw "${item}"
- "~/Library/Frameworks"
- "/Library/Frameworks"
- "/System/Library/Frameworks"
- )
- if(fw)
- #message(STATUS "info: 'find_file' found framework (${fw})")
- set(resolved 1)
- set(resolved_item "${fw}")
- set(fw "fw-NOTFOUND")
- endif(fw)
- endif(item MATCHES "[^/]+\\.framework/")
- endif(NOT resolved)
-
- # Using find_program on Windows will find dll files that are in the PATH.
- # (Converting simple file names into full path names if found.)
- #
- if(WIN32)
- if(NOT resolved)
- set(ri "ri-NOTFOUND")
- find_program(ri "${item}" PATHS "${exepath};${dirs}" NO_DEFAULT_PATH)
- find_program(ri "${item}" PATHS "${exepath};${dirs}")
- if(ri)
- #message(STATUS "info: 'find_program' in exepath/dirs (${ri})")
- set(resolved 1)
- set(resolved_item "${ri}")
- set(ri "ri-NOTFOUND")
- endif(ri)
- endif(NOT resolved)
- endif(WIN32)
-
- # Provide a hook so that projects can override item resolution
- # by whatever logic they choose:
- #
- if(COMMAND gp_resolve_item_override)
- gp_resolve_item_override("${context}" "${item}" "${exepath}" "${dirs}" resolved_item resolved)
- endif(COMMAND gp_resolve_item_override)
-
- if(NOT resolved)
- message(STATUS "
-warning: cannot resolve item '${item}'
-
- possible problems:
- need more directories?
- need to use InstallRequiredSystemLibraries?
- run in install tree instead of build tree?
-")
-# message(STATUS "
-#******************************************************************************
-#warning: cannot resolve item '${item}'
-#
-# possible problems:
-# need more directories?
-# need to use InstallRequiredSystemLibraries?
-# run in install tree instead of build tree?
-#
-# context='${context}'
-# item='${item}'
-# exepath='${exepath}'
-# dirs='${dirs}'
-# resolved_item_var='${resolved_item_var}'
-#******************************************************************************
-#")
- endif(NOT resolved)
-
- set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE)
-endfunction(gp_resolve_item)
-
-
-# gp_resolved_file_type original_file file exepath dirs type_var
-#
-# Return the type of ${file} with respect to ${original_file}. String
-# describing type of prerequisite is returned in variable named ${type_var}.
-#
-# Use ${exepath} and ${dirs} if necessary to resolve non-absolute ${file}
-# values -- but only for non-embedded items.
-#
-# Possible types are:
-# system
-# local
-# embedded
-# other
-#
-function(gp_resolved_file_type original_file file exepath dirs type_var)
- #message(STATUS "**")
-
- if(NOT IS_ABSOLUTE "${original_file}")
- message(STATUS "warning: gp_resolved_file_type expects absolute full path for first arg original_file")
- endif()
-
- set(is_embedded 0)
- set(is_local 0)
- set(is_system 0)
-
- set(resolved_file "${file}")
-
- if("${file}" MATCHES "^@(executable|loader)_path")
- set(is_embedded 1)
- endif()
-
- if(NOT is_embedded)
- if(NOT IS_ABSOLUTE "${file}")
- gp_resolve_item("${original_file}" "${file}" "${exepath}" "${dirs}" resolved_file)
- endif()
-
- string(TOLOWER "${original_file}" original_lower)
- string(TOLOWER "${resolved_file}" lower)
-
- if(UNIX)
- if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11R6/)")
- set(is_system 1)
- endif()
- endif()
-
- if(APPLE)
- if(resolved_file MATCHES "^(/System/Library/|/usr/lib/)")
- set(is_system 1)
- endif()
- endif()
-
- if(WIN32)
- string(TOLOWER "$ENV{SystemRoot}" sysroot)
- string(REGEX REPLACE "\\\\" "/" sysroot "${sysroot}")
-
- string(TOLOWER "$ENV{windir}" windir)
- string(REGEX REPLACE "\\\\" "/" windir "${windir}")
-
- if(lower MATCHES "^(${sysroot}/system|${windir}/system|${sysroot}/syswow|${windir}/syswow|(.*/)*msvc[^/]+dll)")
- set(is_system 1)
- endif()
- endif()
-
- if(NOT is_system)
- get_filename_component(original_path "${original_lower}" PATH)
- get_filename_component(path "${lower}" PATH)
- if("${original_path}" STREQUAL "${path}")
- set(is_local 1)
- endif()
- endif()
- endif()
-
- # Return type string based on computed booleans:
- #
- set(type "other")
-
- if(is_system)
- set(type "system")
- elseif(is_embedded)
- set(type "embedded")
- elseif(is_local)
- set(type "local")
- endif()
-
- #message(STATUS "gp_resolved_file_type: '${file}' '${resolved_file}'")
- #message(STATUS " type: '${type}'")
-
- if(NOT is_embedded)
- if(NOT IS_ABSOLUTE "${resolved_file}")
- if(lower MATCHES "^msvc[^/]+dll" AND is_system)
- message(STATUS "info: non-absolute msvc file '${file}' returning type '${type}'")
- else()
- message(STATUS "warning: gp_resolved_file_type non-absolute file '${file}' returning type '${type}' -- possibly incorrect")
- endif()
- endif()
- endif()
-
- set(${type_var} "${type}" PARENT_SCOPE)
-
- #message(STATUS "**")
-endfunction()
-
-
-# gp_file_type original_file file type_var
-#
-# Return the type of ${file} with respect to ${original_file}. String
-# describing type of prerequisite is returned in variable named ${type_var}.
-#
-# Possible types are:
-# system
-# local
-# embedded
-# other
-#
-function(gp_file_type original_file file type_var)
- if(NOT IS_ABSOLUTE "${original_file}")
- message(STATUS "warning: gp_file_type expects absolute full path for first arg original_file")
- endif()
-
- get_filename_component(exepath "${original_file}" PATH)
-
- set(type "")
- gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "" type)
-
- set(${type_var} "${type}" PARENT_SCOPE)
-endfunction(gp_file_type)
-
-
-# get_prerequisites target prerequisites_var exclude_system recurse dirs
-#
-# Get the list of shared library files required by ${target}. The list in
-# the variable named ${prerequisites_var} should be empty on first entry to
-# this function. On exit, ${prerequisites_var} will contain the list of
-# required shared library files.
-#
-# target is the full path to an executable file
-#
-# prerequisites_var is the name of a CMake variable to contain the results
-#
-# exclude_system is 0 or 1: 0 to include "system" prerequisites , 1 to
-# exclude them
-#
-# recurse is 0 or 1: 0 for direct prerequisites only, 1 for all prerequisites
-# recursively
-#
-# exepath is the path to the top level executable used for @executable_path
-# replacment on the Mac
-#
-# dirs is a list of paths where libraries might be found: these paths are
-# searched first when a target without any path info is given. Then standard
-# system locations are also searched: PATH, Framework locations, /usr/lib...
-#
-function(get_prerequisites target prerequisites_var exclude_system recurse exepath dirs)
- set(verbose 0)
- set(eol_char "E")
-
- if(NOT IS_ABSOLUTE "${target}")
- message("warning: target '${target}' is not absolute...")
- endif(NOT IS_ABSOLUTE "${target}")
-
- if(NOT EXISTS "${target}")
- message("warning: target '${target}' does not exist...")
- endif(NOT EXISTS "${target}")
-
- # <setup-gp_tool-vars>
- #
- # Try to choose the right tool by default. Caller can set gp_tool prior to
- # calling this function to force using a different tool.
- #
- if("${gp_tool}" STREQUAL "")
- set(gp_tool "ldd")
- if(APPLE)
- set(gp_tool "otool")
- endif(APPLE)
- if(WIN32)
- set(gp_tool "dumpbin")
- endif(WIN32)
- endif("${gp_tool}" STREQUAL "")
-
- set(gp_tool_known 0)
-
- if("${gp_tool}" STREQUAL "ldd")
- set(gp_cmd_args "")
- set(gp_regex "^[\t ]*[^\t ]+ => ([^\t ]+).*${eol_char}$")
- set(gp_regex_cmp_count 1)
- set(gp_tool_known 1)
- endif("${gp_tool}" STREQUAL "ldd")
-
- if("${gp_tool}" STREQUAL "otool")
- set(gp_cmd_args "-L")
- set(gp_regex "^\t([^\t]+) \\(compatibility version ([0-9]+.[0-9]+.[0-9]+), current version ([0-9]+.[0-9]+.[0-9]+)\\)${eol_char}$")
- set(gp_regex_cmp_count 3)
- set(gp_tool_known 1)
- endif("${gp_tool}" STREQUAL "otool")
-
- if("${gp_tool}" STREQUAL "dumpbin")
- set(gp_cmd_args "/dependents")
- set(gp_regex "^ ([^ ].*[Dd][Ll][Ll])${eol_char}$")
- set(gp_regex_cmp_count 1)
- set(gp_tool_known 1)
- set(ENV{VS_UNICODE_OUTPUT} "") # Block extra output from inside VS IDE.
- endif("${gp_tool}" STREQUAL "dumpbin")
-
- if(NOT gp_tool_known)
- message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...")
- message(STATUS "CMake function get_prerequisites needs more code to handle '${gp_tool}'")
- message(STATUS "Valid gp_tool values are dumpbin, ldd and otool.")
- return()
- endif(NOT gp_tool_known)
-
- set(gp_cmd_paths ${gp_cmd_paths}
- "C:/Program Files/Microsoft Visual Studio 9.0/VC/bin"
- "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin"
- "C:/Program Files/Microsoft Visual Studio 8/VC/BIN"
- "C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN"
- "C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN"
- "C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN"
- "/usr/local/bin"
- "/usr/bin"
- )
-
- find_program(gp_cmd ${gp_tool} PATHS ${gp_cmd_paths})
-
- if(NOT gp_cmd)
- message(STATUS "warning: could not find '${gp_tool}' - cannot analyze prerequisites...")
- return()
- endif(NOT gp_cmd)
-
- if("${gp_tool}" STREQUAL "dumpbin")
- # When running dumpbin, it also needs the "Common7/IDE" directory in the
- # PATH. It will already be in the PATH if being run from a Visual Studio
- # command prompt. Add it to the PATH here in case we are running from a
- # different command prompt.
- #
- get_filename_component(gp_cmd_dir "${gp_cmd}" PATH)
- get_filename_component(gp_cmd_dlls_dir "${gp_cmd_dir}/../../Common7/IDE" ABSOLUTE)
- if(EXISTS "${gp_cmd_dlls_dir}")
- # only add to the path if it is not already in the path
- if(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}")
- set(ENV{PATH} "$ENV{PATH};${gp_cmd_dlls_dir}")
- endif(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}")
- endif(EXISTS "${gp_cmd_dlls_dir}")
- endif("${gp_tool}" STREQUAL "dumpbin")
- #
- # </setup-gp_tool-vars>
-
- if("${gp_tool}" STREQUAL "ldd")
- set(old_ld_env "$ENV{LD_LIBRARY_PATH}")
- foreach(dir ${exepath} ${dirs})
- set(ENV{LD_LIBRARY_PATH} "${dir}:$ENV{LD_LIBRARY_PATH}")
- endforeach(dir)
- endif("${gp_tool}" STREQUAL "ldd")
-
-
- # Track new prerequisites at each new level of recursion. Start with an
- # empty list at each level:
- #
- set(unseen_prereqs)
-
- # Run gp_cmd on the target:
- #
- execute_process(
- COMMAND ${gp_cmd} ${gp_cmd_args} ${target}
- OUTPUT_VARIABLE gp_cmd_ov
- )
-
- if("${gp_tool}" STREQUAL "ldd")
- set(ENV{LD_LIBRARY_PATH} "${old_ld_env}")
- endif("${gp_tool}" STREQUAL "ldd")
-
- if(verbose)
- message(STATUS "<RawOutput cmd='${gp_cmd} ${gp_cmd_args} ${target}'>")
- message(STATUS "gp_cmd_ov='${gp_cmd_ov}'")
- message(STATUS "</RawOutput>")
- endif(verbose)
-
- get_filename_component(target_dir "${target}" PATH)
-
- # Convert to a list of lines:
- #
- string(REGEX REPLACE ";" "\\\\;" candidates "${gp_cmd_ov}")
- string(REGEX REPLACE "\n" "${eol_char};" candidates "${candidates}")
-
- # Analyze each line for file names that match the regular expression:
- #
- foreach(candidate ${candidates})
- if("${candidate}" MATCHES "${gp_regex}")
- # Extract information from each candidate:
- string(REGEX REPLACE "${gp_regex}" "\\1" raw_item "${candidate}")
-
- if(gp_regex_cmp_count GREATER 1)
- string(REGEX REPLACE "${gp_regex}" "\\2" raw_compat_version "${candidate}")
- string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" compat_major_version "${raw_compat_version}")
- string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" compat_minor_version "${raw_compat_version}")
- string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" compat_patch_version "${raw_compat_version}")
- endif(gp_regex_cmp_count GREATER 1)
-
- if(gp_regex_cmp_count GREATER 2)
- string(REGEX REPLACE "${gp_regex}" "\\3" raw_current_version "${candidate}")
- string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" current_major_version "${raw_current_version}")
- string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" current_minor_version "${raw_current_version}")
- string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" current_patch_version "${raw_current_version}")
- endif(gp_regex_cmp_count GREATER 2)
-
- # Use the raw_item as the list entries returned by this function. Use the
- # gp_resolve_item function to resolve it to an actual full path file if
- # necessary.
- #
- set(item "${raw_item}")
-
- # Add each item unless it is excluded:
- #
- set(add_item 1)
-
- if(${exclude_system})
- set(type "")
- gp_resolved_file_type("${target}" "${item}" "${exepath}" "${dirs}" type)
- if("${type}" STREQUAL "system")
- set(add_item 0)
- endif("${type}" STREQUAL "system")
- endif(${exclude_system})
-
- if(add_item)
- list(LENGTH ${prerequisites_var} list_length_before_append)
- gp_append_unique(${prerequisites_var} "${item}")
- list(LENGTH ${prerequisites_var} list_length_after_append)
-
- if(${recurse})
- # If item was really added, this is the first time we have seen it.
- # Add it to unseen_prereqs so that we can recursively add *its*
- # prerequisites...
- #
- # But first: resolve its name to an absolute full path name such
- # that the analysis tools can simply accept it as input.
- #
- if(NOT list_length_before_append EQUAL list_length_after_append)
- gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item)
- set(unseen_prereqs ${unseen_prereqs} "${resolved_item}")
- endif(NOT list_length_before_append EQUAL list_length_after_append)
- endif(${recurse})
- endif(add_item)
- else("${candidate}" MATCHES "${gp_regex}")
- if(verbose)
- message(STATUS "ignoring non-matching line: '${candidate}'")
- endif(verbose)
- endif("${candidate}" MATCHES "${gp_regex}")
- endforeach(candidate)
-
- list(LENGTH ${prerequisites_var} prerequisites_var_length)
- if(prerequisites_var_length GREATER 0)
- list(SORT ${prerequisites_var})
- endif(prerequisites_var_length GREATER 0)
- if(${recurse})
- set(more_inputs ${unseen_prereqs})
- foreach(input ${more_inputs})
- get_prerequisites("${input}" ${prerequisites_var} ${exclude_system} ${recurse} "${exepath}" "${dirs}")
- endforeach(input)
- endif(${recurse})
-
- set(${prerequisites_var} ${${prerequisites_var}} PARENT_SCOPE)
-endfunction(get_prerequisites)
-
-
-# list_prerequisites target all exclude_system verbose
-#
-# ARGV0 (target) is the full path to an executable file
-#
-# optional ARGV1 (all) is 0 or 1: 0 for direct prerequisites only,
-# 1 for all prerequisites recursively
-#
-# optional ARGV2 (exclude_system) is 0 or 1: 0 to include "system"
-# prerequisites , 1 to exclude them
-#
-# optional ARGV3 (verbose) is 0 or 1: 0 to print only full path
-# names of prerequisites, 1 to print extra information
-#
-function(list_prerequisites target)
- if("${ARGV1}" STREQUAL "")
- set(all 1)
- else("${ARGV1}" STREQUAL "")
- set(all "${ARGV1}")
- endif("${ARGV1}" STREQUAL "")
-
- if("${ARGV2}" STREQUAL "")
- set(exclude_system 0)
- else("${ARGV2}" STREQUAL "")
- set(exclude_system "${ARGV2}")
- endif("${ARGV2}" STREQUAL "")
-
- if("${ARGV3}" STREQUAL "")
- set(verbose 0)
- else("${ARGV3}" STREQUAL "")
- set(verbose "${ARGV3}")
- endif("${ARGV3}" STREQUAL "")
-
- set(count 0)
- set(count_str "")
- set(print_count "${verbose}")
- set(print_prerequisite_type "${verbose}")
- set(print_target "${verbose}")
- set(type_str "")
-
- get_filename_component(exepath "${target}" PATH)
-
- set(prereqs "")
- get_prerequisites("${target}" prereqs ${exclude_system} ${all} "${exepath}" "")
-
- if(print_target)
- message(STATUS "File '${target}' depends on:")
- endif(print_target)
-
- foreach(d ${prereqs})
- math(EXPR count "${count} + 1")
-
- if(print_count)
- set(count_str "${count}. ")
- endif(print_count)
-
- if(print_prerequisite_type)
- gp_file_type("${target}" "${d}" type)
- set(type_str " (${type})")
- endif(print_prerequisite_type)
-
- message(STATUS "${count_str}${d}${type_str}")
- endforeach(d)
-endfunction(list_prerequisites)
-
-
-# list_prerequisites_by_glob glob_arg glob_exp
-#
-# glob_arg is GLOB or GLOB_RECURSE
-#
-# glob_exp is a globbing expression used with "file(GLOB" to retrieve a list
-# of matching files. If a matching file is executable, its prerequisites are
-# listed.
-#
-# Any additional (optional) arguments provided are passed along as the
-# optional arguments to the list_prerequisites calls.
-#
-function(list_prerequisites_by_glob glob_arg glob_exp)
- message(STATUS "=============================================================================")
- message(STATUS "List prerequisites of executables matching ${glob_arg} '${glob_exp}'")
- message(STATUS "")
- file(${glob_arg} file_list ${glob_exp})
- foreach(f ${file_list})
- is_file_executable("${f}" is_f_executable)
- if(is_f_executable)
- message(STATUS "=============================================================================")
- list_prerequisites("${f}" ${ARGN})
- message(STATUS "")
- endif(is_f_executable)
- endforeach(f)
-endfunction(list_prerequisites_by_glob)
+# GetPrerequisites.cmake +# +# This script provides functions to list the .dll, .dylib or .so files that an +# executable or shared library file depends on. (Its prerequisites.) +# +# It uses various tools to obtain the list of required shared library files: +# dumpbin (Windows) +# ldd (Linux/Unix) +# otool (Mac OSX) +# +# The following functions are provided by this script: +# gp_append_unique +# is_file_executable +# gp_item_default_embedded_path +# (projects can override with gp_item_default_embedded_path_override) +# gp_resolve_item +# (projects can override with gp_resolve_item_override) +# gp_resolved_file_type +# gp_file_type +# get_prerequisites +# list_prerequisites +# list_prerequisites_by_glob +# +# Requires CMake 2.6 or greater because it uses function, break, return and +# PARENT_SCOPE. + +#============================================================================= +# Copyright 2008-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distributed this file outside of CMake, substitute the full +# License text for the above reference.) + +# gp_append_unique list_var value +# +# Append value to the list variable ${list_var} only if the value is not +# already in the list. +# +function(gp_append_unique list_var value) + set(contains 0) + + foreach(item ${${list_var}}) + if("${item}" STREQUAL "${value}") + set(contains 1) + break() + endif("${item}" STREQUAL "${value}") + endforeach(item) + + if(NOT contains) + set(${list_var} ${${list_var}} "${value}" PARENT_SCOPE) + endif(NOT contains) +endfunction(gp_append_unique) + + +# is_file_executable file result_var +# +# Return 1 in ${result_var} if ${file} is a binary executable. +# +# Return 0 in ${result_var} otherwise. +# +function(is_file_executable file result_var) + # + # A file is not executable until proven otherwise: + # + set(${result_var} 0 PARENT_SCOPE) + + get_filename_component(file_full "${file}" ABSOLUTE) + string(TOLOWER "${file_full}" file_full_lower) + + # If file name ends in .exe on Windows, *assume* executable: + # + if(WIN32) + if("${file_full_lower}" MATCHES "\\.exe$") + set(${result_var} 1 PARENT_SCOPE) + return() + endif("${file_full_lower}" MATCHES "\\.exe$") + + # A clause could be added here that uses output or return value of dumpbin + # to determine ${result_var}. In 99%+? practical cases, the exe name + # match will be sufficient... + # + endif(WIN32) + + # Use the information returned from the Unix shell command "file" to + # determine if ${file_full} should be considered an executable file... + # + # If the file command's output contains "executable" and does *not* contain + # "text" then it is likely an executable suitable for prerequisite analysis + # via the get_prerequisites macro. + # + if(UNIX) + if(NOT file_cmd) + find_program(file_cmd "file") + endif(NOT file_cmd) + + if(file_cmd) + execute_process(COMMAND "${file_cmd}" "${file_full}" + OUTPUT_VARIABLE file_ov + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + # Replace the name of the file in the output with a placeholder token + # (the string " _file_full_ ") so that just in case the path name of + # the file contains the word "text" or "executable" we are not fooled + # into thinking "the wrong thing" because the file name matches the + # other 'file' command output we are looking for... + # + string(REPLACE "${file_full}" " _file_full_ " file_ov "${file_ov}") + string(TOLOWER "${file_ov}" file_ov) + + #message(STATUS "file_ov='${file_ov}'") + if("${file_ov}" MATCHES "executable") + #message(STATUS "executable!") + if("${file_ov}" MATCHES "text") + #message(STATUS "but text, so *not* a binary executable!") + else("${file_ov}" MATCHES "text") + set(${result_var} 1 PARENT_SCOPE) + return() + endif("${file_ov}" MATCHES "text") + endif("${file_ov}" MATCHES "executable") + else(file_cmd) + message(STATUS "warning: No 'file' command, skipping execute_process...") + endif(file_cmd) + endif(UNIX) +endfunction(is_file_executable) + + +# gp_item_default_embedded_path item default_embedded_path_var +# +# Return the path that others should refer to the item by when the item +# is embedded inside a bundle. +# +# Override on a per-project basis by providing a project-specific +# gp_item_default_embedded_path_override function. +# +function(gp_item_default_embedded_path item default_embedded_path_var) + + # On Windows and Linux, "embed" prerequisites in the same directory + # as the executable by default: + # + set(path "@executable_path") + set(overridden 0) + + # On the Mac, relative to the executable depending on the type + # of the thing we are embedding: + # + if(APPLE) + # + # The assumption here is that all executables in the bundle will be + # in same-level-directories inside the bundle. The parent directory + # of an executable inside the bundle should be MacOS or a sibling of + # MacOS and all embedded paths returned from here will begin with + # "@executable_path/../" and will work from all executables in all + # such same-level-directories inside the bundle. + # + + # By default, embed things right next to the main bundle executable: + # + set(path "@executable_path/../../Contents/MacOS") + + # Embed .dylibs right next to the main bundle executable: + # + if(item MATCHES "\\.dylib$") + set(path "@executable_path/../MacOS") + set(overridden 1) + endif(item MATCHES "\\.dylib$") + + # Embed frameworks in the embedded "Frameworks" directory (sibling of MacOS): + # + if(NOT overridden) + if(item MATCHES "[^/]+\\.framework/") + set(path "@executable_path/../Frameworks") + set(overridden 1) + endif(item MATCHES "[^/]+\\.framework/") + endif(NOT overridden) + endif() + + # Provide a hook so that projects can override the default embedded location + # of any given library by whatever logic they choose: + # + if(COMMAND gp_item_default_embedded_path_override) + gp_item_default_embedded_path_override("${item}" path) + endif(COMMAND gp_item_default_embedded_path_override) + + set(${default_embedded_path_var} "${path}" PARENT_SCOPE) +endfunction(gp_item_default_embedded_path) + + +# gp_resolve_item context item exepath dirs resolved_item_var +# +# Resolve an item into an existing full path file. +# +# Override on a per-project basis by providing a project-specific +# gp_resolve_item_override function. +# +function(gp_resolve_item context item exepath dirs resolved_item_var) + set(resolved 0) + set(resolved_item "${item}") + + # Is it already resolved? + # + if(EXISTS "${resolved_item}") + set(resolved 1) + endif(EXISTS "${resolved_item}") + + if(NOT resolved) + if(item MATCHES "@executable_path") + # + # @executable_path references are assumed relative to exepath + # + string(REPLACE "@executable_path" "${exepath}" ri "${item}") + get_filename_component(ri "${ri}" ABSOLUTE) + + if(EXISTS "${ri}") + #message(STATUS "info: embedded item exists (${ri})") + set(resolved 1) + set(resolved_item "${ri}") + else(EXISTS "${ri}") + message(STATUS "warning: embedded item does not exist '${ri}'") + endif(EXISTS "${ri}") + endif(item MATCHES "@executable_path") + endif(NOT resolved) + + if(NOT resolved) + if(item MATCHES "@loader_path") + # + # @loader_path references are assumed relative to the + # PATH of the given "context" (presumably another library) + # + get_filename_component(contextpath "${context}" PATH) + string(REPLACE "@loader_path" "${contextpath}" ri "${item}") + get_filename_component(ri "${ri}" ABSOLUTE) + + if(EXISTS "${ri}") + #message(STATUS "info: embedded item exists (${ri})") + set(resolved 1) + set(resolved_item "${ri}") + else(EXISTS "${ri}") + message(STATUS "warning: embedded item does not exist '${ri}'") + endif(EXISTS "${ri}") + endif(item MATCHES "@loader_path") + endif(NOT resolved) + + if(NOT resolved) + set(ri "ri-NOTFOUND") + find_file(ri "${item}" ${exepath} ${dirs} NO_DEFAULT_PATH) + find_file(ri "${item}" ${exepath} ${dirs} /usr/lib) + if(ri) + #message(STATUS "info: 'find_file' in exepath/dirs (${ri})") + set(resolved 1) + set(resolved_item "${ri}") + set(ri "ri-NOTFOUND") + endif(ri) + endif(NOT resolved) + + if(NOT resolved) + if(item MATCHES "[^/]+\\.framework/") + set(fw "fw-NOTFOUND") + find_file(fw "${item}" + "~/Library/Frameworks" + "/Library/Frameworks" + "/System/Library/Frameworks" + ) + if(fw) + #message(STATUS "info: 'find_file' found framework (${fw})") + set(resolved 1) + set(resolved_item "${fw}") + set(fw "fw-NOTFOUND") + endif(fw) + endif(item MATCHES "[^/]+\\.framework/") + endif(NOT resolved) + + # Using find_program on Windows will find dll files that are in the PATH. + # (Converting simple file names into full path names if found.) + # + if(WIN32) + if(NOT resolved) + set(ri "ri-NOTFOUND") + find_program(ri "${item}" PATHS "${exepath};${dirs}" NO_DEFAULT_PATH) + find_program(ri "${item}" PATHS "${exepath};${dirs}") + if(ri) + #message(STATUS "info: 'find_program' in exepath/dirs (${ri})") + set(resolved 1) + set(resolved_item "${ri}") + set(ri "ri-NOTFOUND") + endif(ri) + endif(NOT resolved) + endif(WIN32) + + # Provide a hook so that projects can override item resolution + # by whatever logic they choose: + # + if(COMMAND gp_resolve_item_override) + gp_resolve_item_override("${context}" "${item}" "${exepath}" "${dirs}" resolved_item resolved) + endif(COMMAND gp_resolve_item_override) + + if(NOT resolved) + message(STATUS " +warning: cannot resolve item '${item}' + + possible problems: + need more directories? + need to use InstallRequiredSystemLibraries? + run in install tree instead of build tree? +") +# message(STATUS " +#****************************************************************************** +#warning: cannot resolve item '${item}' +# +# possible problems: +# need more directories? +# need to use InstallRequiredSystemLibraries? +# run in install tree instead of build tree? +# +# context='${context}' +# item='${item}' +# exepath='${exepath}' +# dirs='${dirs}' +# resolved_item_var='${resolved_item_var}' +#****************************************************************************** +#") + endif(NOT resolved) + + set(${resolved_item_var} "${resolved_item}" PARENT_SCOPE) +endfunction(gp_resolve_item) + + +# gp_resolved_file_type original_file file exepath dirs type_var +# +# Return the type of ${file} with respect to ${original_file}. String +# describing type of prerequisite is returned in variable named ${type_var}. +# +# Use ${exepath} and ${dirs} if necessary to resolve non-absolute ${file} +# values -- but only for non-embedded items. +# +# Possible types are: +# system +# local +# embedded +# other +# +function(gp_resolved_file_type original_file file exepath dirs type_var) + #message(STATUS "**") + + if(NOT IS_ABSOLUTE "${original_file}") + message(STATUS "warning: gp_resolved_file_type expects absolute full path for first arg original_file") + endif() + + set(is_embedded 0) + set(is_local 0) + set(is_system 0) + + set(resolved_file "${file}") + + if("${file}" MATCHES "^@(executable|loader)_path") + set(is_embedded 1) + endif() + + if(NOT is_embedded) + if(NOT IS_ABSOLUTE "${file}") + gp_resolve_item("${original_file}" "${file}" "${exepath}" "${dirs}" resolved_file) + endif() + + string(TOLOWER "${original_file}" original_lower) + string(TOLOWER "${resolved_file}" lower) + + if(UNIX) + if(resolved_file MATCHES "^(/lib/|/lib32/|/lib64/|/usr/lib/|/usr/lib32/|/usr/lib64/|/usr/X11R6/)") + set(is_system 1) + endif() + endif() + + if(APPLE) + if(resolved_file MATCHES "^(/System/Library/|/usr/lib/)") + set(is_system 1) + endif() + endif() + + if(WIN32) + string(TOLOWER "$ENV{SystemRoot}" sysroot) + string(REGEX REPLACE "\\\\" "/" sysroot "${sysroot}") + + string(TOLOWER "$ENV{windir}" windir) + string(REGEX REPLACE "\\\\" "/" windir "${windir}") + + if(lower MATCHES "^(${sysroot}/system|${windir}/system|${sysroot}/syswow|${windir}/syswow|(.*/)*msvc[^/]+dll)") + set(is_system 1) + endif() + endif() + + if(NOT is_system) + get_filename_component(original_path "${original_lower}" PATH) + get_filename_component(path "${lower}" PATH) + if("${original_path}" STREQUAL "${path}") + set(is_local 1) + endif() + endif() + endif() + + # Return type string based on computed booleans: + # + set(type "other") + + if(is_system) + set(type "system") + elseif(is_embedded) + set(type "embedded") + elseif(is_local) + set(type "local") + endif() + + #message(STATUS "gp_resolved_file_type: '${file}' '${resolved_file}'") + #message(STATUS " type: '${type}'") + + if(NOT is_embedded) + if(NOT IS_ABSOLUTE "${resolved_file}") + if(lower MATCHES "^msvc[^/]+dll" AND is_system) + message(STATUS "info: non-absolute msvc file '${file}' returning type '${type}'") + else() + message(STATUS "warning: gp_resolved_file_type non-absolute file '${file}' returning type '${type}' -- possibly incorrect") + endif() + endif() + endif() + + set(${type_var} "${type}" PARENT_SCOPE) + + #message(STATUS "**") +endfunction() + + +# gp_file_type original_file file type_var +# +# Return the type of ${file} with respect to ${original_file}. String +# describing type of prerequisite is returned in variable named ${type_var}. +# +# Possible types are: +# system +# local +# embedded +# other +# +function(gp_file_type original_file file type_var) + if(NOT IS_ABSOLUTE "${original_file}") + message(STATUS "warning: gp_file_type expects absolute full path for first arg original_file") + endif() + + get_filename_component(exepath "${original_file}" PATH) + + set(type "") + gp_resolved_file_type("${original_file}" "${file}" "${exepath}" "" type) + + set(${type_var} "${type}" PARENT_SCOPE) +endfunction(gp_file_type) + + +# get_prerequisites target prerequisites_var exclude_system recurse dirs +# +# Get the list of shared library files required by ${target}. The list in +# the variable named ${prerequisites_var} should be empty on first entry to +# this function. On exit, ${prerequisites_var} will contain the list of +# required shared library files. +# +# target is the full path to an executable file +# +# prerequisites_var is the name of a CMake variable to contain the results +# +# exclude_system is 0 or 1: 0 to include "system" prerequisites , 1 to +# exclude them +# +# recurse is 0 or 1: 0 for direct prerequisites only, 1 for all prerequisites +# recursively +# +# exepath is the path to the top level executable used for @executable_path +# replacment on the Mac +# +# dirs is a list of paths where libraries might be found: these paths are +# searched first when a target without any path info is given. Then standard +# system locations are also searched: PATH, Framework locations, /usr/lib... +# +function(get_prerequisites target prerequisites_var exclude_system recurse exepath dirs) + set(verbose 0) + set(eol_char "E") + + if(NOT IS_ABSOLUTE "${target}") + message("warning: target '${target}' is not absolute...") + endif(NOT IS_ABSOLUTE "${target}") + + if(NOT EXISTS "${target}") + message("warning: target '${target}' does not exist...") + endif(NOT EXISTS "${target}") + + # <setup-gp_tool-vars> + # + # Try to choose the right tool by default. Caller can set gp_tool prior to + # calling this function to force using a different tool. + # + if("${gp_tool}" STREQUAL "") + set(gp_tool "ldd") + if(APPLE) + set(gp_tool "otool") + endif(APPLE) + if(WIN32) + set(gp_tool "dumpbin") + endif(WIN32) + endif("${gp_tool}" STREQUAL "") + + set(gp_tool_known 0) + + if("${gp_tool}" STREQUAL "ldd") + set(gp_cmd_args "") + set(gp_regex "^[\t ]*[^\t ]+ => ([^\t ]+).*${eol_char}$") + set(gp_regex_cmp_count 1) + set(gp_tool_known 1) + endif("${gp_tool}" STREQUAL "ldd") + + if("${gp_tool}" STREQUAL "otool") + set(gp_cmd_args "-L") + set(gp_regex "^\t([^\t]+) \\(compatibility version ([0-9]+.[0-9]+.[0-9]+), current version ([0-9]+.[0-9]+.[0-9]+)\\)${eol_char}$") + set(gp_regex_cmp_count 3) + set(gp_tool_known 1) + endif("${gp_tool}" STREQUAL "otool") + + if("${gp_tool}" STREQUAL "dumpbin") + set(gp_cmd_args "/dependents") + set(gp_regex "^ ([^ ].*[Dd][Ll][Ll])${eol_char}$") + set(gp_regex_cmp_count 1) + set(gp_tool_known 1) + set(ENV{VS_UNICODE_OUTPUT} "") # Block extra output from inside VS IDE. + endif("${gp_tool}" STREQUAL "dumpbin") + + if(NOT gp_tool_known) + message(STATUS "warning: gp_tool='${gp_tool}' is an unknown tool...") + message(STATUS "CMake function get_prerequisites needs more code to handle '${gp_tool}'") + message(STATUS "Valid gp_tool values are dumpbin, ldd and otool.") + return() + endif(NOT gp_tool_known) + + set(gp_cmd_paths ${gp_cmd_paths} + "C:/Program Files/Microsoft Visual Studio 9.0/VC/bin" + "C:/Program Files (x86)/Microsoft Visual Studio 9.0/VC/bin" + "C:/Program Files/Microsoft Visual Studio 8/VC/BIN" + "C:/Program Files (x86)/Microsoft Visual Studio 8/VC/BIN" + "C:/Program Files/Microsoft Visual Studio .NET 2003/VC7/BIN" + "C:/Program Files (x86)/Microsoft Visual Studio .NET 2003/VC7/BIN" + "/usr/local/bin" + "/usr/bin" + ) + + find_program(gp_cmd ${gp_tool} PATHS ${gp_cmd_paths}) + + if(NOT gp_cmd) + message(STATUS "warning: could not find '${gp_tool}' - cannot analyze prerequisites...") + return() + endif(NOT gp_cmd) + + if("${gp_tool}" STREQUAL "dumpbin") + # When running dumpbin, it also needs the "Common7/IDE" directory in the + # PATH. It will already be in the PATH if being run from a Visual Studio + # command prompt. Add it to the PATH here in case we are running from a + # different command prompt. + # + get_filename_component(gp_cmd_dir "${gp_cmd}" PATH) + get_filename_component(gp_cmd_dlls_dir "${gp_cmd_dir}/../../Common7/IDE" ABSOLUTE) + if(EXISTS "${gp_cmd_dlls_dir}") + # only add to the path if it is not already in the path + if(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}") + set(ENV{PATH} "$ENV{PATH};${gp_cmd_dlls_dir}") + endif(NOT "$ENV{PATH}" MATCHES "${gp_cmd_dlls_dir}") + endif(EXISTS "${gp_cmd_dlls_dir}") + endif("${gp_tool}" STREQUAL "dumpbin") + # + # </setup-gp_tool-vars> + + if("${gp_tool}" STREQUAL "ldd") + set(old_ld_env "$ENV{LD_LIBRARY_PATH}") + foreach(dir ${exepath} ${dirs}) + set(ENV{LD_LIBRARY_PATH} "${dir}:$ENV{LD_LIBRARY_PATH}") + endforeach(dir) + endif("${gp_tool}" STREQUAL "ldd") + + + # Track new prerequisites at each new level of recursion. Start with an + # empty list at each level: + # + set(unseen_prereqs) + + # Run gp_cmd on the target: + # + execute_process( + COMMAND ${gp_cmd} ${gp_cmd_args} ${target} + OUTPUT_VARIABLE gp_cmd_ov + ) + + if("${gp_tool}" STREQUAL "ldd") + set(ENV{LD_LIBRARY_PATH} "${old_ld_env}") + endif("${gp_tool}" STREQUAL "ldd") + + if(verbose) + message(STATUS "<RawOutput cmd='${gp_cmd} ${gp_cmd_args} ${target}'>") + message(STATUS "gp_cmd_ov='${gp_cmd_ov}'") + message(STATUS "</RawOutput>") + endif(verbose) + + get_filename_component(target_dir "${target}" PATH) + + # Convert to a list of lines: + # + string(REGEX REPLACE ";" "\\\\;" candidates "${gp_cmd_ov}") + string(REGEX REPLACE "\n" "${eol_char};" candidates "${candidates}") + + # Analyze each line for file names that match the regular expression: + # + foreach(candidate ${candidates}) + if("${candidate}" MATCHES "${gp_regex}") + # Extract information from each candidate: + string(REGEX REPLACE "${gp_regex}" "\\1" raw_item "${candidate}") + + if(gp_regex_cmp_count GREATER 1) + string(REGEX REPLACE "${gp_regex}" "\\2" raw_compat_version "${candidate}") + string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" compat_major_version "${raw_compat_version}") + string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" compat_minor_version "${raw_compat_version}") + string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" compat_patch_version "${raw_compat_version}") + endif(gp_regex_cmp_count GREATER 1) + + if(gp_regex_cmp_count GREATER 2) + string(REGEX REPLACE "${gp_regex}" "\\3" raw_current_version "${candidate}") + string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\1" current_major_version "${raw_current_version}") + string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\2" current_minor_version "${raw_current_version}") + string(REGEX REPLACE "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$" "\\3" current_patch_version "${raw_current_version}") + endif(gp_regex_cmp_count GREATER 2) + + # Use the raw_item as the list entries returned by this function. Use the + # gp_resolve_item function to resolve it to an actual full path file if + # necessary. + # + set(item "${raw_item}") + + # Add each item unless it is excluded: + # + set(add_item 1) + + if(${exclude_system}) + set(type "") + gp_resolved_file_type("${target}" "${item}" "${exepath}" "${dirs}" type) + if("${type}" STREQUAL "system") + set(add_item 0) + endif("${type}" STREQUAL "system") + endif(${exclude_system}) + + if(add_item) + list(LENGTH ${prerequisites_var} list_length_before_append) + gp_append_unique(${prerequisites_var} "${item}") + list(LENGTH ${prerequisites_var} list_length_after_append) + + if(${recurse}) + # If item was really added, this is the first time we have seen it. + # Add it to unseen_prereqs so that we can recursively add *its* + # prerequisites... + # + # But first: resolve its name to an absolute full path name such + # that the analysis tools can simply accept it as input. + # + if(NOT list_length_before_append EQUAL list_length_after_append) + gp_resolve_item("${target}" "${item}" "${exepath}" "${dirs}" resolved_item) + set(unseen_prereqs ${unseen_prereqs} "${resolved_item}") + endif(NOT list_length_before_append EQUAL list_length_after_append) + endif(${recurse}) + endif(add_item) + else("${candidate}" MATCHES "${gp_regex}") + if(verbose) + message(STATUS "ignoring non-matching line: '${candidate}'") + endif(verbose) + endif("${candidate}" MATCHES "${gp_regex}") + endforeach(candidate) + + list(LENGTH ${prerequisites_var} prerequisites_var_length) + if(prerequisites_var_length GREATER 0) + list(SORT ${prerequisites_var}) + endif(prerequisites_var_length GREATER 0) + if(${recurse}) + set(more_inputs ${unseen_prereqs}) + foreach(input ${more_inputs}) + get_prerequisites("${input}" ${prerequisites_var} ${exclude_system} ${recurse} "${exepath}" "${dirs}") + endforeach(input) + endif(${recurse}) + + set(${prerequisites_var} ${${prerequisites_var}} PARENT_SCOPE) +endfunction(get_prerequisites) + + +# list_prerequisites target all exclude_system verbose +# +# ARGV0 (target) is the full path to an executable file +# +# optional ARGV1 (all) is 0 or 1: 0 for direct prerequisites only, +# 1 for all prerequisites recursively +# +# optional ARGV2 (exclude_system) is 0 or 1: 0 to include "system" +# prerequisites , 1 to exclude them +# +# optional ARGV3 (verbose) is 0 or 1: 0 to print only full path +# names of prerequisites, 1 to print extra information +# +function(list_prerequisites target) + if("${ARGV1}" STREQUAL "") + set(all 1) + else("${ARGV1}" STREQUAL "") + set(all "${ARGV1}") + endif("${ARGV1}" STREQUAL "") + + if("${ARGV2}" STREQUAL "") + set(exclude_system 0) + else("${ARGV2}" STREQUAL "") + set(exclude_system "${ARGV2}") + endif("${ARGV2}" STREQUAL "") + + if("${ARGV3}" STREQUAL "") + set(verbose 0) + else("${ARGV3}" STREQUAL "") + set(verbose "${ARGV3}") + endif("${ARGV3}" STREQUAL "") + + set(count 0) + set(count_str "") + set(print_count "${verbose}") + set(print_prerequisite_type "${verbose}") + set(print_target "${verbose}") + set(type_str "") + + get_filename_component(exepath "${target}" PATH) + + set(prereqs "") + get_prerequisites("${target}" prereqs ${exclude_system} ${all} "${exepath}" "") + + if(print_target) + message(STATUS "File '${target}' depends on:") + endif(print_target) + + foreach(d ${prereqs}) + math(EXPR count "${count} + 1") + + if(print_count) + set(count_str "${count}. ") + endif(print_count) + + if(print_prerequisite_type) + gp_file_type("${target}" "${d}" type) + set(type_str " (${type})") + endif(print_prerequisite_type) + + message(STATUS "${count_str}${d}${type_str}") + endforeach(d) +endfunction(list_prerequisites) + + +# list_prerequisites_by_glob glob_arg glob_exp +# +# glob_arg is GLOB or GLOB_RECURSE +# +# glob_exp is a globbing expression used with "file(GLOB" to retrieve a list +# of matching files. If a matching file is executable, its prerequisites are +# listed. +# +# Any additional (optional) arguments provided are passed along as the +# optional arguments to the list_prerequisites calls. +# +function(list_prerequisites_by_glob glob_arg glob_exp) + message(STATUS "=============================================================================") + message(STATUS "List prerequisites of executables matching ${glob_arg} '${glob_exp}'") + message(STATUS "") + file(${glob_arg} file_list ${glob_exp}) + foreach(f ${file_list}) + is_file_executable("${f}" is_f_executable) + if(is_f_executable) + message(STATUS "=============================================================================") + list_prerequisites("${f}" ${ARGN}) + message(STATUS "") + endif(is_f_executable) + endforeach(f) +endfunction(list_prerequisites_by_glob) diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake index 62b764bb30..05f0492234 100644 --- a/indra/cmake/LLAddBuildTest.cmake +++ b/indra/cmake/LLAddBuildTest.cmake @@ -1,276 +1,276 @@ -# -*- cmake -*-
-include(LLTestCommand)
-include(GoogleMock)
-
-MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
- # Given a project name and a list of sourcefiles (with optional properties on each),
- # add targets to build and run the tests specified.
- # ASSUMPTIONS:
- # * this macro is being executed in the project file that is passed in
- # * current working SOURCE dir is that project dir
- # * there is a subfolder tests/ with test code corresponding to the filenames passed in
- # * properties for each sourcefile passed in indicate what libs to link that file with (MAKE NO ASSUMPTIONS ASIDE FROM TUT)
- #
- # More info and examples at: https://wiki.secondlife.com/wiki/How_to_add_unit_tests_to_indra_code
- #
- # WARNING: do NOT modify this code without working with poppy -
- # there is another branch that will conflict heavily with any changes here.
-INCLUDE(GoogleMock)
-
-
- IF(LL_TEST_VERBOSE)
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}")
- ENDIF(LL_TEST_VERBOSE)
-
- # Start with the header and project-wide setup before making targets
- #project(UNITTEST_PROJECT_${project})
- # Setup includes, paths, etc
- SET(alltest_SOURCE_FILES
- ${CMAKE_SOURCE_DIR}/test/test.cpp
- ${CMAKE_SOURCE_DIR}/test/lltut.cpp
- )
- SET(alltest_DEP_TARGETS
- # needed by the test harness itself
- ${APRUTIL_LIBRARIES}
- ${APR_LIBRARIES}
- llcommon
- )
- IF(NOT "${project}" STREQUAL "llmath")
- # add llmath as a dep unless the tested module *is* llmath!
- LIST(APPEND alltest_DEP_TARGETS
- llmath
- )
- ENDIF(NOT "${project}" STREQUAL "llmath")
- SET(alltest_INCLUDE_DIRS
- ${LLMATH_INCLUDE_DIRS}
- ${LLCOMMON_INCLUDE_DIRS}
- ${LIBS_OPEN_DIR}/test
- ${GOOGLEMOCK_INCLUDE_DIRS}
- )
- SET(alltest_LIBRARIES
- ${GOOGLEMOCK_LIBRARIES}
- ${PTHREAD_LIBRARY}
- ${WINDOWS_LIBRARIES}
- )
- # Headers, for convenience in targets.
- SET(alltest_HEADER_FILES
- ${CMAKE_SOURCE_DIR}/test/test.h
- )
-
- # Use the default flags
- if (LINUX)
- SET(CMAKE_EXE_LINKER_FLAGS "")
- endif (LINUX)
-
- # start the source test executable definitions
- SET(${project}_TEST_OUTPUT "")
- FOREACH (source ${sources})
- STRING( REGEX REPLACE "(.*)\\.[^.]+$" "\\1" name ${source} )
- STRING( REGEX REPLACE ".*\\.([^.]+)$" "\\1" extension ${source} )
- IF(LL_TEST_VERBOSE)
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} individual source: ${source} (${name}.${extension})")
- ENDIF(LL_TEST_VERBOSE)
-
- #
- # Per-codefile additional / external source, header, and include dir property extraction
- #
- # Source
- GET_SOURCE_FILE_PROPERTY(${name}_test_additional_SOURCE_FILES ${source} LL_TEST_ADDITIONAL_SOURCE_FILES)
- IF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
- SET(${name}_test_additional_SOURCE_FILES "")
- ENDIF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
- SET(${name}_test_SOURCE_FILES ${source} tests/${name}_test.${extension} ${alltest_SOURCE_FILES} ${${name}_test_additional_SOURCE_FILES} )
- IF(LL_TEST_VERBOSE)
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}")
- ENDIF(LL_TEST_VERBOSE)
- # Headers
- GET_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES)
- IF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
- SET(${name}_test_additional_HEADER_FILES "")
- ENDIF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
- SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES})
- set_source_files_properties(${${name}_test_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)
- LIST(APPEND ${name}_test_SOURCE_FILES ${${name}_test_HEADER_FILES})
- IF(LL_TEST_VERBOSE)
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_HEADER_FILES ${${name}_test_HEADER_FILES}")
- ENDIF(LL_TEST_VERBOSE)
- # Include dirs
- GET_SOURCE_FILE_PROPERTY(${name}_test_additional_INCLUDE_DIRS ${source} LL_TEST_ADDITIONAL_INCLUDE_DIRS)
- IF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
- SET(${name}_test_additional_INCLUDE_DIRS "")
- ENDIF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
- INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${name}_test_additional_INCLUDE_DIRS )
- IF(LL_TEST_VERBOSE)
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}")
- ENDIF(LL_TEST_VERBOSE)
-
-
- # Setup target
- ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES})
- SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
-
- #
- # Per-codefile additional / external project dep and lib dep property extraction
- #
- # WARNING: it's REALLY IMPORTANT to not mix these. I guarantee it will not work in the future. + poppy 2009-04-19
- # Projects
- GET_SOURCE_FILE_PROPERTY(${name}_test_additional_PROJECTS ${source} LL_TEST_ADDITIONAL_PROJECTS)
- IF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
- SET(${name}_test_additional_PROJECTS "")
- ENDIF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
- # Libraries
- GET_SOURCE_FILE_PROPERTY(${name}_test_additional_LIBRARIES ${source} LL_TEST_ADDITIONAL_LIBRARIES)
- IF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
- SET(${name}_test_additional_LIBRARIES "")
- ENDIF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
- IF(LL_TEST_VERBOSE)
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_PROJECTS ${${name}_test_additional_PROJECTS}")
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_LIBRARIES ${${name}_test_additional_LIBRARIES}")
- ENDIF(LL_TEST_VERBOSE)
- # Add to project
- TARGET_LINK_LIBRARIES(PROJECT_${project}_TEST_${name} ${alltest_LIBRARIES} ${alltest_DEP_TARGETS} ${${name}_test_additional_PROJECTS} ${${name}_test_additional_LIBRARIES} )
- # Compile-time Definitions
- GET_SOURCE_FILE_PROPERTY(${name}_test_additional_CFLAGS ${source} LL_TEST_ADDITIONAL_CFLAGS)
- IF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND)
- SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES COMPILE_FLAGS ${${name}_test_additional_CFLAGS} )
- IF(LL_TEST_VERBOSE)
- MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_CFLAGS ${${name}_test_additional_CFLAGS}")
- ENDIF(LL_TEST_VERBOSE)
- ENDIF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND)
-
- #
- # Setup test targets
- #
- GET_TARGET_PROPERTY(TEST_EXE PROJECT_${project}_TEST_${name} LOCATION)
- SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/PROJECT_${project}_TEST_${name}_ok.txt)
- SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
-
- # daveh - what configuration does this use? Debug? it's cmake-time, not build time. + poppy 2009-04-19
- IF(LL_TEST_VERBOSE)
- MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_cmd = ${TEST_CMD}")
- ENDIF(LL_TEST_VERBOSE)
-
- SET_TEST_PATH(LD_LIBRARY_PATH)
- LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${TEST_CMD})
- IF(LL_TEST_VERBOSE)
- MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_script = ${TEST_SCRIPT_CMD}")
- ENDIF(LL_TEST_VERBOSE)
- # Add test
- ADD_CUSTOM_COMMAND(
- OUTPUT ${TEST_OUTPUT}
- COMMAND ${TEST_SCRIPT_CMD}
- DEPENDS PROJECT_${project}_TEST_${name}
- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- )
- # Why not add custom target and add POST_BUILD command?
- # Slightly less uncertain behavior
- # (OUTPUT commands run non-deterministically AFAIK) + poppy 2009-04-19
- # > I did not use a post build step as I could not make it notify of a
- # > failure after the first time you build and fail a test. - daveh 2009-04-20
- LIST(APPEND ${project}_TEST_OUTPUT ${TEST_OUTPUT})
- ENDFOREACH (source)
-
- # Add the test runner target per-project
- # (replaces old _test_ok targets all over the place)
- ADD_CUSTOM_TARGET(${project}_tests ALL DEPENDS ${${project}_TEST_OUTPUT})
- ADD_DEPENDENCIES(${project} ${project}_tests)
-ENDMACRO(LL_ADD_PROJECT_UNIT_TESTS)
-
-FUNCTION(LL_ADD_INTEGRATION_TEST
- testname
- additional_source_files
- library_dependencies
-# variable args
- )
- if(TEST_DEBUG)
- message(STATUS "Adding INTEGRATION_TEST_${testname} - debug output is on")
- endif(TEST_DEBUG)
-
- SET(source_files
- tests/${testname}_test.cpp
- ${CMAKE_SOURCE_DIR}/test/test.cpp
- ${CMAKE_SOURCE_DIR}/test/lltut.cpp
- ${additional_source_files}
- )
-
- SET(libraries
- ${library_dependencies}
- ${GOOGLEMOCK_LIBRARIES}
- ${PTHREAD_LIBRARY}
- )
-
- # Add test executable build target
- if(TEST_DEBUG)
- message(STATUS "ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})")
- endif(TEST_DEBUG)
- ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})
- SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
- if(STANDALONE)
- SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}")
- endif(STANDALONE)
-
- # Add link deps to the executable
- if(TEST_DEBUG)
- message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})")
- endif(TEST_DEBUG)
- TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})
-
- # Create the test running command
- SET(test_command ${ARGN})
- GET_TARGET_PROPERTY(TEST_EXE INTEGRATION_TEST_${testname} LOCATION)
- LIST(FIND test_command "{}" test_exe_pos)
- IF(test_exe_pos LESS 0)
- # The {} marker means "the full pathname of the test executable."
- # test_exe_pos -1 means we didn't find it -- so append the test executable
- # name to $ARGN, the variable part of the arg list. This is convenient
- # shorthand for both straightforward execution of the test program (empty
- # $ARGN) and for running a "wrapper" program of some kind accepting the
- # pathname of the test program as the last of its args. You need specify
- # {} only if the test program's pathname isn't the last argument in the
- # desired command line.
- LIST(APPEND test_command "${TEST_EXE}")
- ELSE (test_exe_pos LESS 0)
- # Found {} marker at test_exe_pos. Remove the {}...
- LIST(REMOVE_AT test_command test_exe_pos)
- # ...and replace it with the actual name of the test executable.
- LIST(INSERT test_command test_exe_pos "${TEST_EXE}")
- ENDIF (test_exe_pos LESS 0)
-
- SET_TEST_PATH(LD_LIBRARY_PATH)
- LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${test_command})
-
- if(TEST_DEBUG)
- message(STATUS "TEST_SCRIPT_CMD: ${TEST_SCRIPT_CMD}")
- endif(TEST_DEBUG)
-
- ADD_CUSTOM_COMMAND(
- TARGET INTEGRATION_TEST_${testname}
- POST_BUILD
- COMMAND ${TEST_SCRIPT_CMD}
- )
-
- # Use CTEST? Not sure how to yet...
- # ADD_TEST(INTEGRATION_TEST_RUNNER_${testname} ${TEST_SCRIPT_CMD})
-
-ENDFUNCTION(LL_ADD_INTEGRATION_TEST)
-
-MACRO(SET_TEST_PATH LISTVAR)
- IF(WINDOWS)
- # We typically build/package only Release variants of third-party
- # libraries, so append the Release staging dir in case the library being
- # sought doesn't have a debug variant.
- set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR} ${SHARED_LIB_STAGING_DIR}/Release)
- ELSEIF(DARWIN)
- # We typically build/package only Release variants of third-party
- # libraries, so append the Release staging dir in case the library being
- # sought doesn't have a debug variant.
- 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.
- 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)
+# -*- cmake -*- +include(LLTestCommand) +include(GoogleMock) + +MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources) + # Given a project name and a list of sourcefiles (with optional properties on each), + # add targets to build and run the tests specified. + # ASSUMPTIONS: + # * this macro is being executed in the project file that is passed in + # * current working SOURCE dir is that project dir + # * there is a subfolder tests/ with test code corresponding to the filenames passed in + # * properties for each sourcefile passed in indicate what libs to link that file with (MAKE NO ASSUMPTIONS ASIDE FROM TUT) + # + # More info and examples at: https://wiki.secondlife.com/wiki/How_to_add_unit_tests_to_indra_code + # + # WARNING: do NOT modify this code without working with poppy - + # there is another branch that will conflict heavily with any changes here. +INCLUDE(GoogleMock) + + + IF(LL_TEST_VERBOSE) + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}") + ENDIF(LL_TEST_VERBOSE) + + # Start with the header and project-wide setup before making targets + #project(UNITTEST_PROJECT_${project}) + # Setup includes, paths, etc + SET(alltest_SOURCE_FILES + ${CMAKE_SOURCE_DIR}/test/test.cpp + ${CMAKE_SOURCE_DIR}/test/lltut.cpp + ) + SET(alltest_DEP_TARGETS + # needed by the test harness itself + ${APRUTIL_LIBRARIES} + ${APR_LIBRARIES} + llcommon + ) + IF(NOT "${project}" STREQUAL "llmath") + # add llmath as a dep unless the tested module *is* llmath! + LIST(APPEND alltest_DEP_TARGETS + llmath + ) + ENDIF(NOT "${project}" STREQUAL "llmath") + SET(alltest_INCLUDE_DIRS + ${LLMATH_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LIBS_OPEN_DIR}/test + ${GOOGLEMOCK_INCLUDE_DIRS} + ) + SET(alltest_LIBRARIES + ${GOOGLEMOCK_LIBRARIES} + ${PTHREAD_LIBRARY} + ${WINDOWS_LIBRARIES} + ) + # Headers, for convenience in targets. + SET(alltest_HEADER_FILES + ${CMAKE_SOURCE_DIR}/test/test.h + ) + + # Use the default flags + if (LINUX) + SET(CMAKE_EXE_LINKER_FLAGS "") + endif (LINUX) + + # start the source test executable definitions + SET(${project}_TEST_OUTPUT "") + FOREACH (source ${sources}) + STRING( REGEX REPLACE "(.*)\\.[^.]+$" "\\1" name ${source} ) + STRING( REGEX REPLACE ".*\\.([^.]+)$" "\\1" extension ${source} ) + IF(LL_TEST_VERBOSE) + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} individual source: ${source} (${name}.${extension})") + ENDIF(LL_TEST_VERBOSE) + + # + # Per-codefile additional / external source, header, and include dir property extraction + # + # Source + GET_SOURCE_FILE_PROPERTY(${name}_test_additional_SOURCE_FILES ${source} LL_TEST_ADDITIONAL_SOURCE_FILES) + IF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND) + SET(${name}_test_additional_SOURCE_FILES "") + ENDIF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND) + SET(${name}_test_SOURCE_FILES ${source} tests/${name}_test.${extension} ${alltest_SOURCE_FILES} ${${name}_test_additional_SOURCE_FILES} ) + IF(LL_TEST_VERBOSE) + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}") + ENDIF(LL_TEST_VERBOSE) + # Headers + GET_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES) + IF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND) + SET(${name}_test_additional_HEADER_FILES "") + ENDIF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND) + SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES}) + set_source_files_properties(${${name}_test_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE) + LIST(APPEND ${name}_test_SOURCE_FILES ${${name}_test_HEADER_FILES}) + IF(LL_TEST_VERBOSE) + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_HEADER_FILES ${${name}_test_HEADER_FILES}") + ENDIF(LL_TEST_VERBOSE) + # Include dirs + GET_SOURCE_FILE_PROPERTY(${name}_test_additional_INCLUDE_DIRS ${source} LL_TEST_ADDITIONAL_INCLUDE_DIRS) + IF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND) + SET(${name}_test_additional_INCLUDE_DIRS "") + ENDIF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND) + INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${name}_test_additional_INCLUDE_DIRS ) + IF(LL_TEST_VERBOSE) + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}") + ENDIF(LL_TEST_VERBOSE) + + + # Setup target + ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES}) + SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}") + + # + # Per-codefile additional / external project dep and lib dep property extraction + # + # WARNING: it's REALLY IMPORTANT to not mix these. I guarantee it will not work in the future. + poppy 2009-04-19 + # Projects + GET_SOURCE_FILE_PROPERTY(${name}_test_additional_PROJECTS ${source} LL_TEST_ADDITIONAL_PROJECTS) + IF(${name}_test_additional_PROJECTS MATCHES NOTFOUND) + SET(${name}_test_additional_PROJECTS "") + ENDIF(${name}_test_additional_PROJECTS MATCHES NOTFOUND) + # Libraries + GET_SOURCE_FILE_PROPERTY(${name}_test_additional_LIBRARIES ${source} LL_TEST_ADDITIONAL_LIBRARIES) + IF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND) + SET(${name}_test_additional_LIBRARIES "") + ENDIF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND) + IF(LL_TEST_VERBOSE) + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_PROJECTS ${${name}_test_additional_PROJECTS}") + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_LIBRARIES ${${name}_test_additional_LIBRARIES}") + ENDIF(LL_TEST_VERBOSE) + # Add to project + TARGET_LINK_LIBRARIES(PROJECT_${project}_TEST_${name} ${alltest_LIBRARIES} ${alltest_DEP_TARGETS} ${${name}_test_additional_PROJECTS} ${${name}_test_additional_LIBRARIES} ) + # Compile-time Definitions + GET_SOURCE_FILE_PROPERTY(${name}_test_additional_CFLAGS ${source} LL_TEST_ADDITIONAL_CFLAGS) + IF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND) + SET_TARGET_PROPERTIES(PROJECT_${project}_TEST_${name} PROPERTIES COMPILE_FLAGS ${${name}_test_additional_CFLAGS} ) + IF(LL_TEST_VERBOSE) + MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_CFLAGS ${${name}_test_additional_CFLAGS}") + ENDIF(LL_TEST_VERBOSE) + ENDIF(NOT ${name}_test_additional_CFLAGS MATCHES NOTFOUND) + + # + # Setup test targets + # + GET_TARGET_PROPERTY(TEST_EXE PROJECT_${project}_TEST_${name} LOCATION) + SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/PROJECT_${project}_TEST_${name}_ok.txt) + SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR}) + + # daveh - what configuration does this use? Debug? it's cmake-time, not build time. + poppy 2009-04-19 + IF(LL_TEST_VERBOSE) + MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_cmd = ${TEST_CMD}") + ENDIF(LL_TEST_VERBOSE) + + SET_TEST_PATH(LD_LIBRARY_PATH) + LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${TEST_CMD}) + IF(LL_TEST_VERBOSE) + MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_script = ${TEST_SCRIPT_CMD}") + ENDIF(LL_TEST_VERBOSE) + # Add test + ADD_CUSTOM_COMMAND( + OUTPUT ${TEST_OUTPUT} + COMMAND ${TEST_SCRIPT_CMD} + DEPENDS PROJECT_${project}_TEST_${name} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + # Why not add custom target and add POST_BUILD command? + # Slightly less uncertain behavior + # (OUTPUT commands run non-deterministically AFAIK) + poppy 2009-04-19 + # > I did not use a post build step as I could not make it notify of a + # > failure after the first time you build and fail a test. - daveh 2009-04-20 + LIST(APPEND ${project}_TEST_OUTPUT ${TEST_OUTPUT}) + ENDFOREACH (source) + + # Add the test runner target per-project + # (replaces old _test_ok targets all over the place) + ADD_CUSTOM_TARGET(${project}_tests ALL DEPENDS ${${project}_TEST_OUTPUT}) + ADD_DEPENDENCIES(${project} ${project}_tests) +ENDMACRO(LL_ADD_PROJECT_UNIT_TESTS) + +FUNCTION(LL_ADD_INTEGRATION_TEST + testname + additional_source_files + library_dependencies +# variable args + ) + if(TEST_DEBUG) + message(STATUS "Adding INTEGRATION_TEST_${testname} - debug output is on") + endif(TEST_DEBUG) + + SET(source_files + tests/${testname}_test.cpp + ${CMAKE_SOURCE_DIR}/test/test.cpp + ${CMAKE_SOURCE_DIR}/test/lltut.cpp + ${additional_source_files} + ) + + SET(libraries + ${library_dependencies} + ${GOOGLEMOCK_LIBRARIES} + ${PTHREAD_LIBRARY} + ) + + # Add test executable build target + if(TEST_DEBUG) + message(STATUS "ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files})") + endif(TEST_DEBUG) + ADD_EXECUTABLE(INTEGRATION_TEST_${testname} ${source_files}) + SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}") + if(STANDALONE) + SET_TARGET_PROPERTIES(INTEGRATION_TEST_${testname} PROPERTIES COMPILE_FLAGS -I"${TUT_INCLUDE_DIR}") + endif(STANDALONE) + + # Add link deps to the executable + if(TEST_DEBUG) + message(STATUS "TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries})") + endif(TEST_DEBUG) + TARGET_LINK_LIBRARIES(INTEGRATION_TEST_${testname} ${libraries}) + + # Create the test running command + SET(test_command ${ARGN}) + GET_TARGET_PROPERTY(TEST_EXE INTEGRATION_TEST_${testname} LOCATION) + LIST(FIND test_command "{}" test_exe_pos) + IF(test_exe_pos LESS 0) + # The {} marker means "the full pathname of the test executable." + # test_exe_pos -1 means we didn't find it -- so append the test executable + # name to $ARGN, the variable part of the arg list. This is convenient + # shorthand for both straightforward execution of the test program (empty + # $ARGN) and for running a "wrapper" program of some kind accepting the + # pathname of the test program as the last of its args. You need specify + # {} only if the test program's pathname isn't the last argument in the + # desired command line. + LIST(APPEND test_command "${TEST_EXE}") + ELSE (test_exe_pos LESS 0) + # Found {} marker at test_exe_pos. Remove the {}... + LIST(REMOVE_AT test_command test_exe_pos) + # ...and replace it with the actual name of the test executable. + LIST(INSERT test_command test_exe_pos "${TEST_EXE}") + ENDIF (test_exe_pos LESS 0) + + SET_TEST_PATH(LD_LIBRARY_PATH) + LL_TEST_COMMAND(TEST_SCRIPT_CMD "${LD_LIBRARY_PATH}" ${test_command}) + + if(TEST_DEBUG) + message(STATUS "TEST_SCRIPT_CMD: ${TEST_SCRIPT_CMD}") + endif(TEST_DEBUG) + + ADD_CUSTOM_COMMAND( + TARGET INTEGRATION_TEST_${testname} + POST_BUILD + COMMAND ${TEST_SCRIPT_CMD} + ) + + # Use CTEST? Not sure how to yet... + # ADD_TEST(INTEGRATION_TEST_RUNNER_${testname} ${TEST_SCRIPT_CMD}) + +ENDFUNCTION(LL_ADD_INTEGRATION_TEST) + +MACRO(SET_TEST_PATH LISTVAR) + IF(WINDOWS) + # We typically build/package only Release variants of third-party + # libraries, so append the Release staging dir in case the library being + # sought doesn't have a debug variant. + set(${LISTVAR} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR} ${SHARED_LIB_STAGING_DIR}/Release) + ELSEIF(DARWIN) + # We typically build/package only Release variants of third-party + # libraries, so append the Release staging dir in case the library being + # sought doesn't have a debug variant. + 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. + 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) diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 356e0f4c0f..7d5afe92dc 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -28,7 +28,7 @@ #define LL_LLVERSIONVIEWER_H const S32 LL_VERSION_MAJOR = 2; -const S32 LL_VERSION_MINOR = 5; +const S32 LL_VERSION_MINOR = 6; const S32 LL_VERSION_PATCH = 0; const S32 LL_VERSION_BUILD = 0; diff --git a/indra/llmath/llbbox.cpp b/indra/llmath/llbbox.cpp index b46a6e03d2..3e2c05a6e6 100644 --- a/indra/llmath/llbbox.cpp +++ b/indra/llmath/llbbox.cpp @@ -89,6 +89,19 @@ void LLBBox::addBBoxAgent(const LLBBox& b) } } +LLBBox LLBBox::getAxisAligned() const +{ + // no rotation = axis aligned rotation + LLBBox aligned(mPosAgent, LLQuaternion(), LLVector3(), LLVector3()); + + // add the center point so that it's not empty + aligned.addPointAgent(mPosAgent); + + // add our BBox + aligned.addBBoxAgent(*this); + + return aligned; +} void LLBBox::expand( F32 delta ) { @@ -147,6 +160,15 @@ BOOL LLBBox::containsPointAgent(const LLVector3& p) const return containsPointLocal(point_local); } +LLVector3 LLBBox::getMinAgent() const +{ + return localToAgent(mMinLocal); +} + +LLVector3 LLBBox::getMaxAgent() const +{ + return localToAgent(mMaxLocal); +} /* LLBBox operator*(const LLBBox &a, const LLMatrix4 &b) diff --git a/indra/llmath/llbbox.h b/indra/llmath/llbbox.h index 5b911793f0..28e69b75e1 100644 --- a/indra/llmath/llbbox.h +++ b/indra/llmath/llbbox.h @@ -51,9 +51,11 @@ public: const LLVector3& getPositionAgent() const { return mPosAgent; } const LLQuaternion& getRotation() const { return mRotation; } + LLVector3 getMinAgent() const; const LLVector3& getMinLocal() const { return mMinLocal; } void setMinLocal( const LLVector3& min ) { mMinLocal = min; } + LLVector3 getMaxAgent() const; const LLVector3& getMaxLocal() const { return mMaxLocal; } void setMaxLocal( const LLVector3& max ) { mMaxLocal = max; } @@ -80,6 +82,8 @@ public: LLVector3 localToAgentBasis(const LLVector3& v) const; LLVector3 agentToLocalBasis(const LLVector3& v) const; + // Get the smallest possible axis aligned bbox that contains this bbox + LLBBox getAxisAligned() const; // friend LLBBox operator*(const LLBBox& a, const LLMatrix4& b); diff --git a/indra/llmessage/llregionflags.h b/indra/llmessage/llregionflags.h index b9b974ec4f..7b796a0fa8 100644 --- a/indra/llmessage/llregionflags.h +++ b/indra/llmessage/llregionflags.h @@ -42,9 +42,6 @@ const U32 REGION_FLAGS_RESET_HOME_ON_TELEPORT = (1 << 3); // Does the sun move? const U32 REGION_FLAGS_SUN_FIXED = (1 << 4); -// Tax free zone (no taxes on objects, land, etc.) -const U32 REGION_FLAGS_TAX_FREE = (1 << 5); - // Can't change the terrain heightfield, even on owned parcels, // but can plant trees and grass. const U32 REGION_FLAGS_BLOCK_TERRAFORM = (1 << 6); @@ -54,17 +51,12 @@ const U32 REGION_FLAGS_BLOCK_LAND_RESELL = (1 << 7); // All content wiped once per night const U32 REGION_FLAGS_SANDBOX = (1 << 8); -const U32 REGION_FLAGS_NULL_LAYER = (1 << 9); -// const U32 REGION_FLAGS_SKIP_AGENT_ACTION = (1 << 10); -const U32 REGION_FLAGS_HARD_ALLOW_LAND_TRANSFER = (1 << 10); // Region allows land reselling -// const U32 REGION_FLAGS_SKIP_UPDATE_INTEREST_LIST= (1 << 11); -const U32 REGION_FLAGS_HARD_ALLOW_POST_CLASSIFIED = (1 << 11); // Region allows posting of classified ads const U32 REGION_FLAGS_SKIP_COLLISIONS = (1 << 12); // Pin all non agent rigid bodies const U32 REGION_FLAGS_SKIP_SCRIPTS = (1 << 13); const U32 REGION_FLAGS_SKIP_PHYSICS = (1 << 14); // Skip all physics const U32 REGION_FLAGS_EXTERNALLY_VISIBLE = (1 << 15); -//const U32 REGION_FLAGS_MAINLAND_VISIBLE = (1 << 16); -const U32 REGION_FLAGS_PUBLIC_ALLOWED = (1 << 17); +const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT = (1 << 16); +const U32 REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT = (1 << 17); const U32 REGION_FLAGS_BLOCK_DWELL = (1 << 18); // Is flight allowed? @@ -81,18 +73,13 @@ const U32 REGION_FLAGS_ESTATE_SKIP_SCRIPTS = (1 << 21); const U32 REGION_FLAGS_RESTRICT_PUSHOBJECT = (1 << 22); const U32 REGION_FLAGS_DENY_ANONYMOUS = (1 << 23); -// const U32 REGION_FLAGS_DENY_IDENTIFIED = (1 << 24); -// const U32 REGION_FLAGS_DENY_TRANSACTED = (1 << 25); const U32 REGION_FLAGS_ALLOW_PARCEL_CHANGES = (1 << 26); -// const U32 REGION_FLAGS_ABUSE_EMAIL_TO_ESTATE_OWNER = (1 << 27); // We no longer support ELAR - const U32 REGION_FLAGS_ALLOW_VOICE = (1 << 28); const U32 REGION_FLAGS_BLOCK_PARCEL_SEARCH = (1 << 29); const U32 REGION_FLAGS_DENY_AGEUNVERIFIED = (1 << 30); -const U32 REGION_FLAGS_SKIP_MONO_SCRIPTS = (1 << 31); const U32 REGION_FLAGS_DEFAULT = REGION_FLAGS_ALLOW_LANDMARK | REGION_FLAGS_ALLOW_SET_HOME | @@ -105,7 +92,6 @@ const U32 REGION_FLAGS_PRELUDE_UNSET = REGION_FLAGS_ALLOW_LANDMARK | REGION_FLAGS_ALLOW_SET_HOME; const U32 REGION_FLAGS_ESTATE_MASK = REGION_FLAGS_EXTERNALLY_VISIBLE - | REGION_FLAGS_PUBLIC_ALLOWED | REGION_FLAGS_SUN_FIXED | REGION_FLAGS_DENY_ANONYMOUS | REGION_FLAGS_DENY_AGEUNVERIFIED; diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 6b06040b8a..8b6a73af56 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -94,6 +94,7 @@ LLComboBox::LLComboBox(const LLComboBox::Params& p) mMaxChars(p.max_chars), mPrearrangeCallback(p.prearrange_callback()), mTextEntryCallback(p.text_entry_callback()), + mTextChangedCallback(p.text_changed_callback()), mListPosition(p.list_position), mLastSelectedIndex(-1), mLabel(p.label) @@ -834,6 +835,10 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor) mList->deselectAllItems(); mLastSelectedIndex = -1; } + if (mTextChangedCallback != NULL) + { + (mTextChangedCallback)(line_editor, LLSD()); + } return; } @@ -878,6 +883,10 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor) // RN: presumably text entry updateSelection(); } + if (mTextChangedCallback != NULL) + { + (mTextChangedCallback)(line_editor, LLSD()); + } } void LLComboBox::updateSelection() diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index 5f0e4a6843..74d64269bd 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -73,7 +73,8 @@ public: allow_new_values; Optional<S32> max_chars; Optional<commit_callback_t> prearrange_callback, - text_entry_callback; + text_entry_callback, + text_changed_callback; Optional<EPreferredPosition, PreferredPositionValues> list_position; @@ -190,6 +191,7 @@ public: void setPrearrangeCallback( commit_callback_t cb ) { mPrearrangeCallback = cb; } void setTextEntryCallback( commit_callback_t cb ) { mTextEntryCallback = cb; } + void setTextChangedCallback( commit_callback_t cb ) { mTextChangedCallback = cb; } void setButtonVisible(BOOL visible); @@ -220,6 +222,7 @@ private: BOOL mTextEntryTentative; commit_callback_t mPrearrangeCallback; commit_callback_t mTextEntryCallback; + commit_callback_t mTextChangedCallback; commit_callback_t mSelectionCallback; boost::signals2::connection mTopLostSignalConnection; S32 mLastSelectedIndex; diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index d30697e178..c425782715 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -272,9 +272,6 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) initFromParams(p); - // chrome floaters don't take focus at all - setFocusRoot(!getIsChrome()); - initFloater(p); } @@ -2910,8 +2907,6 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str params.from_xui = true; applyXUILayout(params, parent); initFromParams(params); - // chrome floaters don't take focus at all - setFocusRoot(!getIsChrome()); initFloater(params); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index ce22a52460..a61c35abd2 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -405,6 +405,7 @@ set(viewer_SOURCE_FILES llsecapi.cpp llsechandler_basic.cpp llselectmgr.cpp + llshareavatarhandler.cpp llsidepanelappearance.cpp llsidepanelinventory.cpp llsidepanelinventorysubpanel.cpp @@ -546,6 +547,7 @@ set(viewer_SOURCE_FILES llvoclouds.cpp llvograss.cpp llvoground.cpp + llvoicecallhandler.cpp llvoicechannel.cpp llvoiceclient.cpp llvoicevisualizer.cpp @@ -1853,29 +1855,29 @@ if (PACKAGE) endif (LINUX) if(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) - if(CMAKE_CFG_INTDIR STREQUAL ".") + if(CMAKE_CFG_INTDIR STREQUAL ".") set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE}) - else(CMAKE_CFG_INTDIR STREQUAL ".") + else(CMAKE_CFG_INTDIR STREQUAL ".") # set LLBUILD_CONFIG to be a shell variable evaluated at build time # reflecting the configuration we are currently building. set(LLBUILD_CONFIG ${CMAKE_CFG_INTDIR}) - endif(CMAKE_CFG_INTDIR STREQUAL ".") - add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" - COMMAND "${PYTHON_EXECUTABLE}" - ARGS - "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" - "${LLBUILD_CONFIG}" - "${VIEWER_DIST_DIR}" - "${VIEWER_EXE_GLOBS}" - "${VIEWER_LIB_GLOB}" - "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/bin/dump_syms" - "${VIEWER_SYMBOL_FILE}" - DEPENDS generate_breakpad_symbols.py + endif(CMAKE_CFG_INTDIR STREQUAL ".") + add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" + COMMAND "${PYTHON_EXECUTABLE}" + ARGS + "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" + "${LLBUILD_CONFIG}" + "${VIEWER_DIST_DIR}" + "${VIEWER_EXE_GLOBS}" + "${VIEWER_LIB_GLOB}" + "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/bin/dump_syms" + "${VIEWER_SYMBOL_FILE}" + DEPENDS generate_breakpad_symbols.py VERBATIM) - add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}") - add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}") - add_dependencies(package generate_breakpad_symbols) + add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}") + add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}") + add_dependencies(package generate_breakpad_symbols) endif(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) endif (PACKAGE) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ea7ac6beda..ef6f8fd3ee 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -3932,6 +3932,17 @@ <key>Value</key> <string>http://search.secondlife.com/viewer/[CATEGORY]/?q=[QUERY]&p=[AUTH_TOKEN]&r=[MATURITY]&lang=[LANGUAGE]&g=[GODLIKE]&sid=[SESSION_ID]&rid=[REGION_ID]&pid=[PARCEL_ID]&channel=[CHANNEL]&version=[VERSION]&major=[VERSION_MAJOR]&minor=[VERSION_MINOR]&patch=[VERSION_PATCH]&build=[VERSION_BUILD]</string> </map> + <key>WebProfileURL</key> + <map> + <key>Comment</key> + <string>URL for Web Profiles</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>https://my.secondlife.com/[AGENT_NAME]</string> + </map> <key>HighResSnapshot</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 705c73cbf7..8efec1cff0 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -160,6 +160,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>ShowFavoritesOnLogin</key> + <map> + <key>Comment</key> + <string>Determines whether favorites of last logged in user will be saved on exit from viewer and shown on login screen</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <!-- End of back compatibility settings --> </map> </llsd> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index ea3c2eb312..77552663ab 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -218,7 +218,10 @@ LLAgent::LLAgent() : mFirstLogin(FALSE), mGenderChosen(FALSE), - mAppearanceSerialNum(0) + mAppearanceSerialNum(0), + + mMouselookModeInSignal(NULL), + mMouselookModeOutSignal(NULL) { for (U32 i = 0; i < TOTAL_CONTROLS; i++) { @@ -269,6 +272,9 @@ LLAgent::~LLAgent() { cleanup(); + delete mMouselookModeInSignal; + delete mMouselookModeOutSignal; + // *Note: this is where LLViewerCamera::getInstance() used to be deleted. } @@ -1735,6 +1741,11 @@ void LLAgent::endAnimationUpdateUI() LLFloaterCamera::onLeavingMouseLook(); + if (mMouselookModeOutSignal) + { + (*mMouselookModeOutSignal)(); + } + // Only pop if we have pushed... if (TRUE == mViewsPushed) { @@ -1840,6 +1851,11 @@ void LLAgent::endAnimationUpdateUI() mViewsPushed = TRUE; + if (mMouselookModeInSignal) + { + (*mMouselookModeInSignal)(); + } + // hide all floaters except the mini map #if 0 // Use this once all floaters are registered @@ -1899,7 +1915,6 @@ void LLAgent::endAnimationUpdateUI() } } } - } else if (gAgentCamera.getCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR) { @@ -1931,6 +1946,18 @@ void LLAgent::endAnimationUpdateUI() gAgentCamera.updateLastCamera(); } +boost::signals2::connection LLAgent::setMouselookModeInCallback( const camera_signal_t::slot_type& cb ) +{ + if (!mMouselookModeInSignal) mMouselookModeInSignal = new camera_signal_t(); + return mMouselookModeInSignal->connect(cb); +} + +boost::signals2::connection LLAgent::setMouselookModeOutCallback( const camera_signal_t::slot_type& cb ) +{ + if (!mMouselookModeOutSignal) mMouselookModeOutSignal = new camera_signal_t(); + return mMouselookModeOutSignal->connect(cb); +} + //----------------------------------------------------------------------------- // heardChat() //----------------------------------------------------------------------------- diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index aebebad96a..896408c0dd 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -39,6 +39,8 @@ #include "llvoavatardefines.h" #include "llslurl.h" +#include <boost/signals2.hpp> + extern const BOOL ANIMATE; extern const U8 AGENT_STATE_TYPING; // Typing indication extern const U8 AGENT_STATE_EDITING; // Set when agent has objects selected @@ -410,7 +412,13 @@ public: BOOL getCustomAnim() const { return mCustomAnim; } void setCustomAnim(BOOL anim) { mCustomAnim = anim; } + typedef boost::signals2::signal<void ()> camera_signal_t; + boost::signals2::connection setMouselookModeInCallback( const camera_signal_t::slot_type& cb ); + boost::signals2::connection setMouselookModeOutCallback( const camera_signal_t::slot_type& cb ); + private: + camera_signal_t* mMouselookModeInSignal; + camera_signal_t* mMouselookModeOutSignal; BOOL mCustomAnim; // Current animation is ANIM_AGENT_CUSTOMIZE ? LLAnimPauseRequest mPauseRequest; BOOL mViewsPushed; // Keep track of whether or not we have pushed views diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index f12bc16d4b..dd5bc74b2a 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -126,6 +126,7 @@ void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason) break; } LLUploadDialog::modalUploadFinished(); + LLFilePicker::instance().reset(); // unlock file picker when bulk upload fails } //virtual diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 066b4d8bc3..f3f0cde221 100644..100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -56,9 +56,11 @@ #include "llmutelist.h" #include "llnotificationsutil.h" // for LLNotificationsUtil #include "llpaneloutfitedit.h" +#include "llpanelprofile.h" #include "llrecentpeople.h" #include "llsidetray.h" #include "lltrans.h" +#include "llviewercontrol.h" #include "llviewerobjectlist.h" #include "llviewermessage.h" // for handle_lure #include "llviewerregion.h" @@ -306,6 +308,20 @@ void LLAvatarActions::showProfile(const LLUUID& id) params["id"] = id; params["open_tab_name"] = "panel_profile"; + // PROFILES: open in webkit window + std::string full_name; + if (gCacheName->getFullName(id,full_name)) + { + std::string agent_name = LLCacheName::buildUsername(full_name); + llinfos << "opening web profile for " << agent_name << llendl; + std::string url = getProfileURL(agent_name); + LLWeb::loadWebURLInternal(url); + } + else + { + llwarns << "no name info for agent id " << id << llendl; + } +#if 0 //Show own profile if(gAgent.getID() == id) { @@ -316,6 +332,7 @@ void LLAvatarActions::showProfile(const LLUUID& id) { LLSideTray::getInstance()->showPanel("panel_profile_view", params); } +#endif } } diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp index 360ba080ac..360ba080ac 100644..100755 --- a/indra/newview/llcommandhandler.cpp +++ b/indra/newview/llcommandhandler.cpp diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 0c0fdd5572..0b17d64eb0 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -607,6 +607,15 @@ void LLFavoritesBarCtrl::changed(U32 mask) } else { + LLInventoryModel::item_array_t items; + LLInventoryModel::cat_array_t cats; + LLIsType is_type(LLAssetType::AT_LANDMARK); + gInventory.collectDescendentsIf(mFavoriteFolderId, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + + for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) + { + (*i)->getSLURL(); + } updateButtons(); } } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 338b6555ff..8c9dfe435a 100644..100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -105,6 +105,7 @@ #include "llteleporthistorystorage.h" #include "lllogininstance.h" // to check if logged in yet +#include "llsdserialize.h" const F32 MAX_USER_FAR_CLIP = 512.f; const F32 MIN_USER_FAR_CLIP = 64.f; @@ -284,8 +285,10 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mGotPersonalInfo(false), mOriginalIMViaEmail(false), mLanguageChanged(false), - mDoubleClickActionDirty(false) + mDoubleClickActionDirty(false), + mFavoritesRecordMayExist(false) { + //Build Floater is now Called from LLFloaterReg::add("preferences", "floater_preferences.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterPreference>); static bool registered_dialog = false; @@ -322,16 +325,61 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key) mCommitCallbackRegistrar.add("Pref.getUIColor", boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2)); mCommitCallbackRegistrar.add("Pref.MaturitySettings", boost::bind(&LLFloaterPreference::onChangeMaturity, this)); mCommitCallbackRegistrar.add("Pref.BlockList", boost::bind(&LLFloaterPreference::onClickBlockList, this)); + + sSkin = gSavedSettings.getString("SkinCurrent"); + mCommitCallbackRegistrar.add("Pref.CommitDoubleClickChekbox", boost::bind(&LLFloaterPreference::onDoubleClickCheckBox, this, _1)); mCommitCallbackRegistrar.add("Pref.CommitRadioDoubleClick", boost::bind(&LLFloaterPreference::onDoubleClickRadio, this)); - sSkin = gSavedSettings.getString("SkinCurrent"); - gSavedSettings.getControl("NameTagShowUsernames")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2)); gSavedSettings.getControl("NameTagShowFriends")->getCommitSignal()->connect(boost::bind(&handleNameTagOptionChanged, _2)); gSavedSettings.getControl("UseDisplayNames")->getCommitSignal()->connect(boost::bind(&handleDisplayNamesOptionChanged, _2)); + + LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this ); +} + +void LLFloaterPreference::processProperties( void* pData, EAvatarProcessorType type ) +{ + if ( APT_PROPERTIES == type ) + { + const LLAvatarData* pAvatarData = static_cast<const LLAvatarData*>( pData ); + if( pAvatarData && gAgent.getID() == pAvatarData->avatar_id ) + { + storeAvatarProperties( pAvatarData ); + processProfileProperties( pAvatarData ); + } + } } +void LLFloaterPreference::storeAvatarProperties( const LLAvatarData* pAvatarData ) +{ + mAvatarProperties.avatar_id = gAgent.getID(); + mAvatarProperties.image_id = pAvatarData->image_id; + mAvatarProperties.fl_image_id = pAvatarData->fl_image_id; + mAvatarProperties.about_text = pAvatarData->about_text; + mAvatarProperties.fl_about_text = pAvatarData->fl_about_text; + mAvatarProperties.profile_url = pAvatarData->profile_url; + mAvatarProperties.flags = pAvatarData->flags; + mAvatarProperties.allow_publish = pAvatarData->flags & AVATAR_ALLOW_PUBLISH; +} + +void LLFloaterPreference::processProfileProperties(const LLAvatarData* pAvatarData ) +{ + getChild<LLUICtrl>("online_searchresults")->setValue( (bool)(pAvatarData->flags & AVATAR_ALLOW_PUBLISH) ); +} + +void LLFloaterPreference::saveAvatarProperties( void ) +{ + mAvatarProperties.allow_publish = getChild<LLUICtrl>("online_searchresults")->getValue(); + if ( mAvatarProperties.allow_publish ) + { + mAvatarProperties.flags |= AVATAR_ALLOW_PUBLISH; + } + + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate( &mAvatarProperties ); +} + + BOOL LLFloaterPreference::postBuild() { gSavedSettings.getControl("PlainTextChatHistory")->getSignal()->connect(boost::bind(&LLIMFloater::processChatHistoryStyleUpdate, _2)); @@ -415,6 +463,8 @@ void LLFloaterPreference::saveSettings() void LLFloaterPreference::apply() { + LLAvatarPropertiesProcessor::getInstance()->addObserver( gAgent.getID(), this ); + LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core"); if (sSkin != gSavedSettings.getString("SkinCurrent")) { @@ -486,11 +536,41 @@ void LLFloaterPreference::apply() } } + saveAvatarProperties(); + if (mDoubleClickActionDirty) { updateDoubleClickSettings(); mDoubleClickActionDirty = false; } + + if (mFavoritesRecordMayExist && !gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) + { + removeFavoritesRecordOfUser(); + } +} + +void LLFloaterPreference::removeFavoritesRecordOfUser() +{ + mFavoritesRecordMayExist = false; + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); + LLSD fav_llsd; + llifstream file; + file.open(filename); + if (!file.is_open()) return; + LLSDSerialize::fromXML(fav_llsd, file); + + LLAvatarName av_name; + LLAvatarNameCache::get( gAgentID, &av_name ); + if (fav_llsd.has(av_name.getLegacyName())) + { + fav_llsd.erase(av_name.getLegacyName()); + } + + llofstream out_file; + out_file.open(filename); + LLSDSerialize::toPrettyXML(fav_llsd, out_file); + } void LLFloaterPreference::cancel() @@ -527,6 +607,7 @@ void LLFloaterPreference::cancel() void LLFloaterPreference::onOpen(const LLSD& key) { + // this variable and if that follows it are used to properly handle busy mode response message static bool initialized = FALSE; // if user is logged in and we haven't initialized busy_response yet, do it @@ -553,7 +634,7 @@ void LLFloaterPreference::onOpen(const LLSD& key) (gAgent.isMature() || gAgent.isGodlike()); LLComboBox* maturity_combo = getChild<LLComboBox>("maturity_desired_combobox"); - + LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest( gAgent.getID() ); if (can_choose_maturity) { // if they're not adult or a god, they shouldn't see the adult selection, so delete it @@ -575,6 +656,11 @@ void LLFloaterPreference::onOpen(const LLSD& key) getChildView("maturity_desired_combobox")->setVisible( false); } + if (LLStartUp::getStartupState() == STATE_STARTED) + { + mFavoritesRecordMayExist = gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin"); + } + // Forget previous language changes. mLanguageChanged = false; @@ -1288,6 +1374,7 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im // getChild<LLUICtrl>("busy_response")->setValue(gSavedSettings.getString("BusyModeResponse2")); + getChildView("favorites_on_login_check")->setEnabled(TRUE); getChildView("log_nearby_chat")->setEnabled(TRUE); getChildView("log_instant_messages")->setEnabled(TRUE); getChildView("show_timestamps_check_im")->setEnabled(TRUE); @@ -1503,6 +1590,10 @@ BOOL LLPanelPreference::postBuild() { getChild<LLCheckBoxCtrl>("voice_call_friends_only_check")->setCommitCallback(boost::bind(&showFriendsOnlyWarning, _1, _2)); } + if (hasChild("favorites_on_login_check")) + { + getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setCommitCallback(boost::bind(&showFavoritesOnLoginWarning, _1, _2)); + } // Panel Advanced if (hasChild("modifier_combo")) @@ -1570,6 +1661,14 @@ void LLPanelPreference::showFriendsOnlyWarning(LLUICtrl* checkbox, const LLSD& v } } +void LLPanelPreference::showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value) +{ + if (checkbox && checkbox->getValue()) + { + LLNotificationsUtil::add("FavoritesOnLogin"); + } +} + void LLPanelPreference::cancel() { for (control_values_map_t::iterator iter = mSavedValues.begin(); diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 0f51189853..784033ae95 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -34,6 +34,7 @@ #define LL_LLFLOATERPREFERENCE_H #include "llfloater.h" +#include "llavatarpropertiesprocessor.h" class LLPanelPreference; class LLPanelLCD; @@ -55,7 +56,7 @@ typedef enum // Floater to control preferences (display, audio, bandwidth, general. -class LLFloaterPreference : public LLFloater +class LLFloaterPreference : public LLFloater, public LLAvatarPropertiesObserver { public: LLFloaterPreference(const LLSD& key); @@ -77,6 +78,11 @@ public: // translate user's busy response message according to current locale if message is default, otherwise do nothing static void initBusyResponse(); + void processProperties( void* pData, EAvatarProcessorType type ); + void processProfileProperties(const LLAvatarData* pAvatarData ); + void storeAvatarProperties( const LLAvatarData* pAvatarData ); + void saveAvatarProperties( void ); + protected: void onBtnOK(); void onBtnCancel(); @@ -153,6 +159,8 @@ public: void buildPopupLists(); static void refreshSkin(void* data); + // Remove record of current user's favorites from file on disk. + void removeFavoritesRecordOfUser(); private: static std::string sSkin; // set true if state of double-click action checkbox or radio-group was changed by user @@ -163,7 +171,11 @@ private: bool mLanguageChanged; bool mOriginalHideOnlineStatus; + // Record of current user's favorites may be stored in file on disk. + bool mFavoritesRecordMayExist; std::string mDirectoryVisibility; + + LLAvatarData mAvatarProperties; }; class LLPanelPreference : public LLPanel @@ -184,6 +196,8 @@ public: private: //for "Only friends and groups can call or IM me" static void showFriendsOnlyWarning(LLUICtrl*, const LLSD&); + //for "Show my Favorite Landmarks at Login" + static void showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value); typedef std::map<LLControlVariable*, LLSD> control_values_map_t; control_values_map_t mSavedValues; diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 51726112a0..058567492b 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -1,402 +1,402 @@ -/**
- * @file llfloaterwebcontent.cpp
- * @brief floater for displaying web content - e.g. profiles and search (eventually)
- *
- * $LicenseInfo:firstyear=2006&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 "llcombobox.h"
-#include "lliconctrl.h"
-#include "llfloaterreg.h"
-#include "lllayoutstack.h"
-#include "llpluginclassmedia.h"
-#include "llprogressbar.h"
-#include "lltextbox.h"
-#include "llurlhistory.h"
-#include "llviewercontrol.h"
-#include "llweb.h"
-#include "llwindow.h"
-
-#include "llfloaterwebcontent.h"
-
-LLFloaterWebContent::LLFloaterWebContent( const LLSD& key )
- : LLFloater( key )
-{
- mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this ));
- mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this ));
- mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this ));
- mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this ));
- mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this ));
- mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this ));
-}
-
-BOOL LLFloaterWebContent::postBuild()
-{
- // these are used in a bunch of places so cache them
- mWebBrowser = getChild< LLMediaCtrl >( "webbrowser" );
- mAddressCombo = getChild< LLComboBox >( "address" );
- mStatusBarText = getChild< LLTextBox >( "statusbartext" );
- mStatusBarProgress = getChild<LLProgressBar>("statusbarprogress" );
-
- // observe browser events
- mWebBrowser->addObserver( this );
-
- // these buttons are always enabled
- getChildView("reload")->setEnabled( true );
- getChildView("popexternal")->setEnabled( true );
-
- // cache image for secure browsing
- mSecureLockIcon = getChild< LLIconCtrl >("media_secure_lock_flag");
-
- // initialize the URL history using the system URL History manager
- initializeURLHistory();
-
- return TRUE;
-}
-
-void LLFloaterWebContent::initializeURLHistory()
-{
- // start with an empty list
- LLCtrlListInterface* url_list = childGetListInterface("address");
- if (url_list)
- {
- url_list->operateOnAll(LLCtrlListInterface::OP_DELETE);
- }
-
- // Get all of the entries in the "browser" collection
- LLSD browser_history = LLURLHistory::getURLHistory("browser");
- LLSD::array_iterator iter_history =
- browser_history.beginArray();
- LLSD::array_iterator end_history =
- browser_history.endArray();
- for(; iter_history != end_history; ++iter_history)
- {
- std::string url = (*iter_history).asString();
- if(! url.empty())
- url_list->addSimpleElement(url);
- }
-}
-
-//static
-void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid )
-{
- lldebugs << "url = " << url << ", target = " << target << ", uuid = " << uuid << llendl;
-
- std::string tag = target;
-
- if(target.empty() || target == "_blank")
- {
- if(!uuid.empty())
- {
- tag = uuid;
- }
- else
- {
- // create a unique tag for this instance
- LLUUID id;
- id.generate();
- tag = id.asString();
- }
- }
-
- S32 browser_window_limit = gSavedSettings.getS32("WebContentWindowLimit");
-
- if(LLFloaterReg::findInstance("web_content", tag) != NULL)
- {
- // There's already a web browser for this tag, so we won't be opening a new window.
- }
- else if(browser_window_limit != 0)
- {
- // showInstance will open a new window. Figure out how many web browsers are already open,
- // and close the least recently opened one if this will put us over the limit.
-
- LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList("web_content");
- lldebugs << "total instance count is " << instances.size() << llendl;
-
- for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++)
- {
- lldebugs << " " << (*iter)->getKey() << llendl;
- }
-
- if(instances.size() >= (size_t)browser_window_limit)
- {
- // Destroy the least recently opened instance
- (*instances.begin())->closeFloater();
- }
- }
-
- LLFloaterWebContent *browser = dynamic_cast<LLFloaterWebContent*> (LLFloaterReg::showInstance("web_content", tag));
- llassert(browser);
- if(browser)
- {
- browser->mUUID = uuid;
-
- // tell the browser instance to load the specified URL
- browser->open_media(url, target);
- LLViewerMedia::proxyWindowOpened(target, uuid);
- }
-}
-
-//static
-void LLFloaterWebContent::closeRequest(const std::string &uuid)
-{
- LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content");
- lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl;
- for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
- {
- LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter);
- lldebugs << " " << i->mUUID << llendl;
- if (i && i->mUUID == uuid)
- {
- i->closeFloater(false);
- return;
- }
- }
-}
-
-//static
-void LLFloaterWebContent::geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height)
-{
- LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content");
- lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl;
- for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
- {
- LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter);
- lldebugs << " " << i->mUUID << llendl;
- if (i && i->mUUID == uuid)
- {
- i->geometryChanged(x, y, width, height);
- return;
- }
- }
-}
-
-void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height)
-{
- // Make sure the layout of the browser control is updated, so this calculation is correct.
- LLLayoutStack::updateClass();
-
- // TODO: need to adjust size and constrain position to make sure floaters aren't moved outside the window view, etc.
- LLCoordWindow window_size;
- getWindow()->getSize(&window_size);
-
- // Adjust width and height for the size of the chrome on the web Browser window.
- width += getRect().getWidth() - mWebBrowser->getRect().getWidth();
- height += getRect().getHeight() - mWebBrowser->getRect().getHeight();
-
- LLRect geom;
- geom.setOriginAndSize(x, window_size.mY - (y + height), width, height);
-
- lldebugs << "geometry change: " << geom << llendl;
-
- handleReshape(geom,false);
-}
-
-void LLFloaterWebContent::open_media(const std::string& web_url, const std::string& target)
-{
- // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin.
- mWebBrowser->setHomePageUrl(web_url, "text/html");
- mWebBrowser->setTarget(target);
- mWebBrowser->navigateTo(web_url, "text/html");
- set_current_url(web_url);
-}
-
-//virtual
-void LLFloaterWebContent::onClose(bool app_quitting)
-{
- LLViewerMedia::proxyWindowClosed(mUUID);
- destroy();
-}
-
-// virtual
-void LLFloaterWebContent::draw()
-{
- // this is asychronous so we need to keep checking
- getChildView( "back" )->setEnabled( mWebBrowser->canNavigateBack() );
- getChildView( "forward" )->setEnabled( mWebBrowser->canNavigateForward() );
-
- LLFloater::draw();
-}
-
-// virtual
-void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
-{
- if(event == MEDIA_EVENT_LOCATION_CHANGED)
- {
- const std::string url = self->getLocation();
-
- if ( url.length() )
- mStatusBarText->setText( url );
-
- set_current_url( url );
- }
- else if(event == MEDIA_EVENT_NAVIGATE_BEGIN)
- {
- // flags are sent with this event
- getChildView("back")->setEnabled( self->getHistoryBackAvailable() );
- getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() );
-
- // toggle visibility of these buttons based on browser state
- getChildView("reload")->setVisible( false );
- getChildView("stop")->setVisible( true );
-
- // turn "on" progress bar now we're about to start loading
- mStatusBarProgress->setVisible( true );
- }
- else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE)
- {
- // flags are sent with this event
- getChildView("back")->setEnabled( self->getHistoryBackAvailable() );
- getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() );
-
- // toggle visibility of these buttons based on browser state
- getChildView("reload")->setVisible( true );
- getChildView("stop")->setVisible( false );
-
- // turn "off" progress bar now we're loaded
- mStatusBarProgress->setVisible( false );
-
- // we populate the status bar with URLs as they change so clear it now we're done
- const std::string end_str = "";
- mStatusBarText->setText( end_str );
-
- // decide if secure browsing icon should be displayed
- std::string prefix = std::string("https://");
- std::string test_prefix = mCurrentURL.substr(0, prefix.length());
- LLStringUtil::toLower(test_prefix);
- if(test_prefix == prefix)
- {
- mSecureLockIcon->setVisible(true);
- }
- else
- {
- mSecureLockIcon->setVisible(false);
- }
- }
- else if(event == MEDIA_EVENT_CLOSE_REQUEST)
- {
- // The browser instance wants its window closed.
- closeFloater();
- }
- else if(event == MEDIA_EVENT_GEOMETRY_CHANGE)
- {
- geometryChanged(self->getGeometryX(), self->getGeometryY(), self->getGeometryWidth(), self->getGeometryHeight());
- }
- else if(event == MEDIA_EVENT_STATUS_TEXT_CHANGED )
- {
- const std::string text = self->getStatusText();
- if ( text.length() )
- mStatusBarText->setText( text );
- }
- else if(event == MEDIA_EVENT_PROGRESS_UPDATED )
- {
- int percent = (int)self->getProgressPercent();
- mStatusBarProgress->setValue( percent );
- }
- else if(event == MEDIA_EVENT_NAME_CHANGED )
- {
- std::string page_title = self->getMediaName();
- // simulate browser behavior - title is empty, use the current URL
- if ( page_title.length() > 0 )
- setTitle( page_title );
- else
- setTitle( mCurrentURL );
- }
- else if(event == MEDIA_EVENT_LINK_HOVERED )
- {
- const std::string link = self->getHoverLink();
- mStatusBarText->setText( link );
- }
-}
-
-void LLFloaterWebContent::set_current_url(const std::string& url)
-{
- mCurrentURL = url;
-
- // serialize url history into the system URL History manager
- LLURLHistory::removeURL("browser", mCurrentURL);
- LLURLHistory::addURL("browser", mCurrentURL);
-
- mAddressCombo->remove( mCurrentURL );
- mAddressCombo->add( mCurrentURL );
- mAddressCombo->selectByValue( mCurrentURL );
-}
-
-void LLFloaterWebContent::onClickForward()
-{
- mWebBrowser->navigateForward();
-}
-
-void LLFloaterWebContent::onClickBack()
-{
- mWebBrowser->navigateBack();
-}
-
-void LLFloaterWebContent::onClickReload()
-{
-
- if( mWebBrowser->getMediaPlugin() )
- {
- bool ignore_cache = true;
- mWebBrowser->getMediaPlugin()->browse_reload( ignore_cache );
- }
- else
- {
- mWebBrowser->navigateTo(mCurrentURL);
- }
-}
-
-void LLFloaterWebContent::onClickStop()
-{
- if( mWebBrowser->getMediaPlugin() )
- mWebBrowser->getMediaPlugin()->browse_stop();
-
- // still should happen when we catch the navigate complete event
- // but sometimes (don't know why) that event isn't sent from Qt
- // and we getto a point where the stop button stays active.
- getChildView("reload")->setVisible( true );
- getChildView("stop")->setVisible( false );
-}
-
-void LLFloaterWebContent::onEnterAddress()
-{
- // make sure there is at least something there.
- // (perhaps this test should be for minimum length of a URL)
- std::string url = mAddressCombo->getValue().asString();
- if ( url.length() > 0 )
- {
- mWebBrowser->navigateTo( url, "text/html");
- };
-}
-
-void LLFloaterWebContent::onPopExternal()
-{
- // make sure there is at least something there.
- // (perhaps this test should be for minimum length of a URL)
- std::string url = mAddressCombo->getValue().asString();
- if ( url.length() > 0 )
- {
- LLWeb::loadURLExternal( url );
- };
-}
+/** + * @file llfloaterwebcontent.cpp + * @brief floater for displaying web content - e.g. profiles and search (eventually) + * + * $LicenseInfo:firstyear=2006&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 "llcombobox.h" +#include "lliconctrl.h" +#include "llfloaterreg.h" +#include "lllayoutstack.h" +#include "llpluginclassmedia.h" +#include "llprogressbar.h" +#include "lltextbox.h" +#include "llurlhistory.h" +#include "llviewercontrol.h" +#include "llweb.h" +#include "llwindow.h" + +#include "llfloaterwebcontent.h" + +LLFloaterWebContent::LLFloaterWebContent( const LLSD& key ) + : LLFloater( key ) +{ + mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this )); + mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this )); + mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this )); + mCommitCallbackRegistrar.add( "WebContent.Stop", boost::bind( &LLFloaterWebContent::onClickStop, this )); + mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this )); + mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this )); +} + +BOOL LLFloaterWebContent::postBuild() +{ + // these are used in a bunch of places so cache them + mWebBrowser = getChild< LLMediaCtrl >( "webbrowser" ); + mAddressCombo = getChild< LLComboBox >( "address" ); + mStatusBarText = getChild< LLTextBox >( "statusbartext" ); + mStatusBarProgress = getChild<LLProgressBar>("statusbarprogress" ); + + // observe browser events + mWebBrowser->addObserver( this ); + + // these buttons are always enabled + getChildView("reload")->setEnabled( true ); + getChildView("popexternal")->setEnabled( true ); + + // cache image for secure browsing + mSecureLockIcon = getChild< LLIconCtrl >("media_secure_lock_flag"); + + // initialize the URL history using the system URL History manager + initializeURLHistory(); + + return TRUE; +} + +void LLFloaterWebContent::initializeURLHistory() +{ + // start with an empty list + LLCtrlListInterface* url_list = childGetListInterface("address"); + if (url_list) + { + url_list->operateOnAll(LLCtrlListInterface::OP_DELETE); + } + + // Get all of the entries in the "browser" collection + LLSD browser_history = LLURLHistory::getURLHistory("browser"); + LLSD::array_iterator iter_history = + browser_history.beginArray(); + LLSD::array_iterator end_history = + browser_history.endArray(); + for(; iter_history != end_history; ++iter_history) + { + std::string url = (*iter_history).asString(); + if(! url.empty()) + url_list->addSimpleElement(url); + } +} + +//static +void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid ) +{ + lldebugs << "url = " << url << ", target = " << target << ", uuid = " << uuid << llendl; + + std::string tag = target; + + if(target.empty() || target == "_blank") + { + if(!uuid.empty()) + { + tag = uuid; + } + else + { + // create a unique tag for this instance + LLUUID id; + id.generate(); + tag = id.asString(); + } + } + + S32 browser_window_limit = gSavedSettings.getS32("WebContentWindowLimit"); + + if(LLFloaterReg::findInstance("web_content", tag) != NULL) + { + // There's already a web browser for this tag, so we won't be opening a new window. + } + else if(browser_window_limit != 0) + { + // showInstance will open a new window. Figure out how many web browsers are already open, + // and close the least recently opened one if this will put us over the limit. + + LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList("web_content"); + lldebugs << "total instance count is " << instances.size() << llendl; + + for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++) + { + lldebugs << " " << (*iter)->getKey() << llendl; + } + + if(instances.size() >= (size_t)browser_window_limit) + { + // Destroy the least recently opened instance + (*instances.begin())->closeFloater(); + } + } + + LLFloaterWebContent *browser = dynamic_cast<LLFloaterWebContent*> (LLFloaterReg::showInstance("web_content", tag)); + llassert(browser); + if(browser) + { + browser->mUUID = uuid; + + // tell the browser instance to load the specified URL + browser->open_media(url, target); + LLViewerMedia::proxyWindowOpened(target, uuid); + } +} + +//static +void LLFloaterWebContent::closeRequest(const std::string &uuid) +{ + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content"); + lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl; + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) + { + LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter); + lldebugs << " " << i->mUUID << llendl; + if (i && i->mUUID == uuid) + { + i->closeFloater(false); + return; + } + } +} + +//static +void LLFloaterWebContent::geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height) +{ + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content"); + lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl; + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) + { + LLFloaterWebContent* i = dynamic_cast<LLFloaterWebContent*>(*iter); + lldebugs << " " << i->mUUID << llendl; + if (i && i->mUUID == uuid) + { + i->geometryChanged(x, y, width, height); + return; + } + } +} + +void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height) +{ + // Make sure the layout of the browser control is updated, so this calculation is correct. + LLLayoutStack::updateClass(); + + // TODO: need to adjust size and constrain position to make sure floaters aren't moved outside the window view, etc. + LLCoordWindow window_size; + getWindow()->getSize(&window_size); + + // Adjust width and height for the size of the chrome on the web Browser window. + width += getRect().getWidth() - mWebBrowser->getRect().getWidth(); + height += getRect().getHeight() - mWebBrowser->getRect().getHeight(); + + LLRect geom; + geom.setOriginAndSize(x, window_size.mY - (y + height), width, height); + + lldebugs << "geometry change: " << geom << llendl; + + handleReshape(geom,false); +} + +void LLFloaterWebContent::open_media(const std::string& web_url, const std::string& target) +{ + // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin. + mWebBrowser->setHomePageUrl(web_url, "text/html"); + mWebBrowser->setTarget(target); + mWebBrowser->navigateTo(web_url, "text/html"); + set_current_url(web_url); +} + +//virtual +void LLFloaterWebContent::onClose(bool app_quitting) +{ + LLViewerMedia::proxyWindowClosed(mUUID); + destroy(); +} + +// virtual +void LLFloaterWebContent::draw() +{ + // this is asychronous so we need to keep checking + getChildView( "back" )->setEnabled( mWebBrowser->canNavigateBack() ); + getChildView( "forward" )->setEnabled( mWebBrowser->canNavigateForward() ); + + LLFloater::draw(); +} + +// virtual +void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ + if(event == MEDIA_EVENT_LOCATION_CHANGED) + { + const std::string url = self->getLocation(); + + if ( url.length() ) + mStatusBarText->setText( url ); + + set_current_url( url ); + } + else if(event == MEDIA_EVENT_NAVIGATE_BEGIN) + { + // flags are sent with this event + getChildView("back")->setEnabled( self->getHistoryBackAvailable() ); + getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() ); + + // toggle visibility of these buttons based on browser state + getChildView("reload")->setVisible( false ); + getChildView("stop")->setVisible( true ); + + // turn "on" progress bar now we're about to start loading + mStatusBarProgress->setVisible( true ); + } + else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE) + { + // flags are sent with this event + getChildView("back")->setEnabled( self->getHistoryBackAvailable() ); + getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() ); + + // toggle visibility of these buttons based on browser state + getChildView("reload")->setVisible( true ); + getChildView("stop")->setVisible( false ); + + // turn "off" progress bar now we're loaded + mStatusBarProgress->setVisible( false ); + + // we populate the status bar with URLs as they change so clear it now we're done + const std::string end_str = ""; + mStatusBarText->setText( end_str ); + + // decide if secure browsing icon should be displayed + std::string prefix = std::string("https://"); + std::string test_prefix = mCurrentURL.substr(0, prefix.length()); + LLStringUtil::toLower(test_prefix); + if(test_prefix == prefix) + { + mSecureLockIcon->setVisible(true); + } + else + { + mSecureLockIcon->setVisible(false); + } + } + else if(event == MEDIA_EVENT_CLOSE_REQUEST) + { + // The browser instance wants its window closed. + closeFloater(); + } + else if(event == MEDIA_EVENT_GEOMETRY_CHANGE) + { + geometryChanged(self->getGeometryX(), self->getGeometryY(), self->getGeometryWidth(), self->getGeometryHeight()); + } + else if(event == MEDIA_EVENT_STATUS_TEXT_CHANGED ) + { + const std::string text = self->getStatusText(); + if ( text.length() ) + mStatusBarText->setText( text ); + } + else if(event == MEDIA_EVENT_PROGRESS_UPDATED ) + { + int percent = (int)self->getProgressPercent(); + mStatusBarProgress->setValue( percent ); + } + else if(event == MEDIA_EVENT_NAME_CHANGED ) + { + std::string page_title = self->getMediaName(); + // simulate browser behavior - title is empty, use the current URL + if ( page_title.length() > 0 ) + setTitle( page_title ); + else + setTitle( mCurrentURL ); + } + else if(event == MEDIA_EVENT_LINK_HOVERED ) + { + const std::string link = self->getHoverLink(); + mStatusBarText->setText( link ); + } +} + +void LLFloaterWebContent::set_current_url(const std::string& url) +{ + mCurrentURL = url; + + // serialize url history into the system URL History manager + LLURLHistory::removeURL("browser", mCurrentURL); + LLURLHistory::addURL("browser", mCurrentURL); + + mAddressCombo->remove( mCurrentURL ); + mAddressCombo->add( mCurrentURL ); + mAddressCombo->selectByValue( mCurrentURL ); +} + +void LLFloaterWebContent::onClickForward() +{ + mWebBrowser->navigateForward(); +} + +void LLFloaterWebContent::onClickBack() +{ + mWebBrowser->navigateBack(); +} + +void LLFloaterWebContent::onClickReload() +{ + + if( mWebBrowser->getMediaPlugin() ) + { + bool ignore_cache = true; + mWebBrowser->getMediaPlugin()->browse_reload( ignore_cache ); + } + else + { + mWebBrowser->navigateTo(mCurrentURL); + } +} + +void LLFloaterWebContent::onClickStop() +{ + if( mWebBrowser->getMediaPlugin() ) + mWebBrowser->getMediaPlugin()->browse_stop(); + + // still should happen when we catch the navigate complete event + // but sometimes (don't know why) that event isn't sent from Qt + // and we getto a point where the stop button stays active. + getChildView("reload")->setVisible( true ); + getChildView("stop")->setVisible( false ); +} + +void LLFloaterWebContent::onEnterAddress() +{ + // make sure there is at least something there. + // (perhaps this test should be for minimum length of a URL) + std::string url = mAddressCombo->getValue().asString(); + if ( url.length() > 0 ) + { + mWebBrowser->navigateTo( url, "text/html"); + }; +} + +void LLFloaterWebContent::onPopExternal() +{ + // make sure there is at least something there. + // (perhaps this test should be for minimum length of a URL) + std::string url = mAddressCombo->getValue().asString(); + if ( url.length() > 0 ) + { + LLWeb::loadURLExternal( url ); + }; +} diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index 001d822ada..ecc7e970d8 100644 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -1,82 +1,82 @@ -/**
- * @file llfloaterwebcontent.h
- * @brief floater for displaying web content - e.g. profiles and search (eventually)
- *
- * $LicenseInfo:firstyear=2006&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 LL_LLFLOATERWEBCONTENT_H
-#define LL_LLFLOATERWEBCONTENT_H
-
-#include "llfloater.h"
-#include "llmediactrl.h"
-
-class LLMediaCtrl;
-class LLComboBox;
-class LLTextBox;
-class LLProgressBar;
-class LLIconCtrl;
-
-class LLFloaterWebContent :
- public LLFloater,
- public LLViewerMediaObserver
-{
-public:
- LOG_CLASS(LLFloaterWebContent);
- LLFloaterWebContent(const LLSD& key);
-
+/** + * @file llfloaterwebcontent.h + * @brief floater for displaying web content - e.g. profiles and search (eventually) + * + * $LicenseInfo:firstyear=2006&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 LL_LLFLOATERWEBCONTENT_H +#define LL_LLFLOATERWEBCONTENT_H + +#include "llfloater.h" +#include "llmediactrl.h" + +class LLMediaCtrl; +class LLComboBox; +class LLTextBox; +class LLProgressBar; +class LLIconCtrl; + +class LLFloaterWebContent : + public LLFloater, + public LLViewerMediaObserver +{ +public: + LOG_CLASS(LLFloaterWebContent); + LLFloaterWebContent(const LLSD& key); + void initializeURLHistory(); -
- static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null);
-
- static void closeRequest(const std::string &uuid);
- static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height);
- void geometryChanged(S32 x, S32 y, S32 width, S32 height);
-
- /* virtual */ BOOL postBuild();
- /* virtual */ void onClose(bool app_quitting);
- /* virtual */ void draw();
-
- // inherited from LLViewerMediaObserver
- /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
-
- void onClickBack();
- void onClickForward();
- void onClickReload();
- void onClickStop();
- void onEnterAddress();
- void onPopExternal();
-
-private:
- void open_media(const std::string& media_url, const std::string& target);
- void set_current_url(const std::string& url);
-
- LLMediaCtrl* mWebBrowser;
- LLComboBox* mAddressCombo;
- LLIconCtrl *mSecureLockIcon;
- LLTextBox* mStatusBarText;
- LLProgressBar* mStatusBarProgress;
- std::string mCurrentURL;
- std::string mUUID;
-};
-
-#endif // LL_LLFLOATERWEBCONTENT_H
+ + static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null); + + static void closeRequest(const std::string &uuid); + static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height); + void geometryChanged(S32 x, S32 y, S32 width, S32 height); + + /* virtual */ BOOL postBuild(); + /* virtual */ void onClose(bool app_quitting); + /* virtual */ void draw(); + + // inherited from LLViewerMediaObserver + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + + void onClickBack(); + void onClickForward(); + void onClickReload(); + void onClickStop(); + void onEnterAddress(); + void onPopExternal(); + +private: + void open_media(const std::string& media_url, const std::string& target); + void set_current_url(const std::string& url); + + LLMediaCtrl* mWebBrowser; + LLComboBox* mAddressCombo; + LLIconCtrl *mSecureLockIcon; + LLTextBox* mStatusBarText; + LLProgressBar* mStatusBarProgress; + std::string mCurrentURL; + std::string mUUID; +}; + +#endif // LL_LLFLOATERWEBCONTENT_H diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index ba0eb8a711..017cd2fc49 100644..100755 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -72,7 +72,6 @@ #include "llweb.h" #include "llslider.h" #include "message.h" - #include "llwindow.h" // copyTextToClipboard() //--------------------------------------------------------------------------- @@ -106,8 +105,8 @@ class LLWorldMapHandler : public LLCommandHandler { public: // requires trusted browser to trigger - LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_THROTTLE) { } - + LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_THROTTLE ) { } + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) { @@ -117,21 +116,52 @@ public: LLFloaterReg::showInstance("world_map", "center"); return true; } - + // support the secondlife:///app/worldmap/{LOCATION}/{COORDS} SLapp const std::string region_name = LLURI::unescape(params[0].asString()); S32 x = (params.size() > 1) ? params[1].asInteger() : 128; S32 y = (params.size() > 2) ? params[2].asInteger() : 128; S32 z = (params.size() > 3) ? params[3].asInteger() : 0; - + LLFloaterWorldMap::getInstance()->trackURL(region_name, x, y, z); LLFloaterReg::showInstance("world_map", "center"); - + return true; } }; LLWorldMapHandler gWorldMapHandler; +// SocialMap handler secondlife:///app/maptrackavatar/id +class LLMapTrackAvatarHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_THROTTLE) + { + } + + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + { + //Make sure we have some parameters + if (params.size() == 0) + { + return false; + } + + //Get the ID + LLUUID id; + if (!id.set( params[0], FALSE )) + { + return false; + } + + LLFloaterWorldMap::getInstance()->avatarTrackFromSlapp( id ); + LLFloaterReg::showInstance( "world_map", "center" ); + + return true; + } +}; +LLMapTrackAvatarHandler gMapTrackAvatar; LLFloaterWorldMap* gFloaterWorldMap = NULL; @@ -142,7 +172,7 @@ public: virtual ~LLMapInventoryObserver() {} virtual void changed(U32 mask); }; - + void LLMapInventoryObserver::changed(U32 mask) { // if there's a change we're interested in. @@ -184,16 +214,16 @@ const LLUUID LLFloaterWorldMap::sHomeID( "10000000-0000-0000-0000-000000000001" LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key) : LLFloater(key), - mInventory(NULL), - mInventoryObserver(NULL), - mFriendObserver(NULL), - mCompletingRegionName(), - mCompletingRegionPos(), - mWaitingForTracker(FALSE), - mIsClosing(FALSE), - mSetToUserPosition(TRUE), - mTrackedLocation(0,0,0), - mTrackedStatus(LLTracker::TRACKING_NOTHING) +mInventory(NULL), +mInventoryObserver(NULL), +mFriendObserver(NULL), +mCompletingRegionName(), +mCompletingRegionPos(), +mWaitingForTracker(FALSE), +mIsClosing(FALSE), +mSetToUserPosition(TRUE), +mTrackedLocation(0,0,0), +mTrackedStatus(LLTracker::TRACKING_NOTHING) { gFloaterWorldMap = this; @@ -210,7 +240,7 @@ LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key) mCommitCallbackRegistrar.add("WMap.ShowAgent", boost::bind(&LLFloaterWorldMap::onShowAgentBtn, this)); mCommitCallbackRegistrar.add("WMap.Clear", boost::bind(&LLFloaterWorldMap::onClearBtn, this)); mCommitCallbackRegistrar.add("WMap.CopySLURL", boost::bind(&LLFloaterWorldMap::onCopySLURL, this)); - + gSavedSettings.getControl("PreferredMaturity")->getSignal()->connect(boost::bind(&LLFloaterWorldMap::onChangeMaturity, this)); } @@ -223,32 +253,32 @@ void* LLFloaterWorldMap::createWorldMapView(void* data) BOOL LLFloaterWorldMap::postBuild() { mPanel = getChild<LLPanel>("objects_mapview"); - + LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo"); avatar_combo->selectFirstItem(); avatar_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onAvatarComboPrearrange, this) ); avatar_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) ); - + LLSearchEditor *location_editor = getChild<LLSearchEditor>("location"); location_editor->setFocusChangedCallback(boost::bind(&LLFloaterWorldMap::onLocationFocusChanged, this, _1)); location_editor->setKeystrokeCallback( boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this)); getChild<LLScrollListCtrl>("search_results")->setDoubleClickCallback( boost::bind(&LLFloaterWorldMap::onClickTeleportBtn, this)); - + LLComboBox *landmark_combo = getChild<LLComboBox>( "landmark combo"); landmark_combo->selectFirstItem(); landmark_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onLandmarkComboPrearrange, this) ); landmark_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) ); - + mCurZoomVal = log(LLWorldMapView::sMapScale)/log(2.f); getChild<LLUICtrl>("zoom slider")->setValue(LLWorldMapView::sMapScale); - + setDefaultBtn(NULL); - + mZoomTimer.stop(); - + onChangeMaturity(); - + return TRUE; } @@ -257,11 +287,11 @@ LLFloaterWorldMap::~LLFloaterWorldMap() { // All cleaned up by LLView destructor mPanel = NULL; - + // Inventory deletes all observers on shutdown mInventory = NULL; mInventoryObserver = NULL; - + // avatar tracker will delete this for us. mFriendObserver = NULL; @@ -285,13 +315,13 @@ void LLFloaterWorldMap::onClose(bool app_quitting) void LLFloaterWorldMap::onOpen(const LLSD& key) { bool center_on_target = (key.asString() == "center"); - + mIsClosing = FALSE; - + LLWorldMapView* map_panel; map_panel = (LLWorldMapView*)gFloaterWorldMap->mPanel; map_panel->clearLastClick(); - + { // reset pan on show, so it centers on you again if (!center_on_target) @@ -299,27 +329,27 @@ void LLFloaterWorldMap::onOpen(const LLSD& key) LLWorldMapView::setPan(0, 0, TRUE); } map_panel->updateVisibleBlocks(); - + // Reload items as they may have changed LLWorldMap::getInstance()->reloadItems(); - + // We may already have a bounding box for the regions of the world, // so use that to adjust the view. adjustZoomSliderBounds(); - + // Could be first show //LLFirstUse::useMap(); - + // Start speculative download of landmarks const LLUUID landmark_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); LLInventoryModelBackgroundFetch::instance().start(landmark_folder_id); - + getChild<LLUICtrl>("location")->setFocus( TRUE); gFocusMgr.triggerFocusFlash(); - + buildAvatarIDList(); buildLandmarkIDLists(); - + // If nothing is being tracked, set flag so the user position will be found mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); } @@ -356,7 +386,7 @@ BOOL LLFloaterWorldMap::handleScrollWheel(S32 x, S32 y, S32 clicks) return TRUE; } } - + return LLFloater::handleScrollWheel(x, y, clicks); } @@ -381,7 +411,7 @@ void LLFloaterWorldMap::draw() bool agent_on_prelude = (regionp && regionp->isPrelude()); bool enable_go_home = gAgent.isGodlike() || !agent_on_prelude; getChildView("Go Home")->setEnabled(enable_go_home); - + updateLocation(); LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus(); @@ -393,7 +423,7 @@ void LLFloaterWorldMap::draw() { getChild<LLUICtrl>("avatar_icon")->setColor( map_track_disabled_color); } - + if (LLTracker::TRACKING_LANDMARK == tracking_status) { getChild<LLUICtrl>("landmark_icon")->setColor( map_track_color); @@ -402,7 +432,7 @@ void LLFloaterWorldMap::draw() { getChild<LLUICtrl>("landmark_icon")->setColor( map_track_disabled_color); } - + if (LLTracker::TRACKING_LOCATION == tracking_status) { getChild<LLUICtrl>("location_icon")->setColor( map_track_color); @@ -422,21 +452,21 @@ void LLFloaterWorldMap::draw() getChild<LLUICtrl>("location_icon")->setColor( map_track_disabled_color); } } - + // check for completion of tracking data if (mWaitingForTracker) { centerOnTarget(TRUE); } - + getChildView("Teleport")->setEnabled((BOOL)tracking_status); -// getChildView("Clear")->setEnabled((BOOL)tracking_status); + // getChildView("Clear")->setEnabled((BOOL)tracking_status); getChildView("Show Destination")->setEnabled((BOOL)tracking_status || LLWorldMap::getInstance()->isTracking()); getChildView("copy_slurl")->setEnabled((mSLURL.isValid()) ); - + setMouseOpaque(TRUE); getDragHandle()->setMouseOpaque(TRUE); - + //RN: snaps to zoom value because interpolation caused jitter in the text rendering if (!mZoomTimer.getStarted() && mCurZoomVal != (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal()) { @@ -451,7 +481,7 @@ void LLFloaterWorldMap::draw() mCurZoomVal = lerp(mCurZoomVal, (F32)getChild<LLUICtrl>("zoom slider")->getValue().asReal(), interp); F32 map_scale = 256.f*pow(2.f, mCurZoomVal); LLWorldMapView::setScale( map_scale ); - + // Enable/disable checkboxes depending on the zoom level // If above threshold level (i.e. low res) -> Disable all checkboxes // If under threshold level (i.e. high res) -> Enable all checkboxes @@ -477,7 +507,7 @@ void LLFloaterWorldMap::trackAvatar( const LLUUID& avatar_id, const std::string& { LLCtrlSelectionInterface *iface = childGetSelectionInterface("friend combo"); if (!iface) return; - + buildAvatarIDList(); if(iface->setCurrentByID(avatar_id) || gAgent.isGodlike()) { @@ -507,7 +537,7 @@ void LLFloaterWorldMap::trackLandmark( const LLUUID& landmark_item_id ) { LLCtrlSelectionInterface *iface = childGetSelectionInterface("landmark combo"); if (!iface) return; - + buildLandmarkIDLists(); BOOL found = FALSE; S32 idx; @@ -519,7 +549,7 @@ void LLFloaterWorldMap::trackLandmark( const LLUUID& landmark_item_id ) break; } } - + if (found && iface->setCurrentByID( landmark_item_id ) ) { LLUUID asset_id = mLandmarkAssetIDList.get( idx ); @@ -528,17 +558,17 @@ void LLFloaterWorldMap::trackLandmark( const LLUUID& landmark_item_id ) if (combo) name = combo->getSimple(); mTrackedStatus = LLTracker::TRACKING_LANDMARK; LLTracker::trackLandmark(mLandmarkAssetIDList.get( idx ), // assetID - mLandmarkItemIDList.get( idx ), // itemID - name); // name - + mLandmarkItemIDList.get( idx ), // itemID + name); // name + if( asset_id != sHomeID ) { // start the download process gLandmarkList.getAsset( asset_id); } - + // We have to download both region info and landmark data, so set busy. JC -// getWindow()->incBusyCount(); + // getWindow()->incBusyCount(); } else { @@ -574,10 +604,10 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global) S32 world_y = S32(pos_global.mdV[1] / 256); LLWorldMapMessage::getInstance()->sendMapBlockRequest(world_x, world_y, world_x, world_y, true); setDefaultBtn(""); - + // clicked on a non-region - turn off coord display enableTeleportCoordsDisplay( false ); - + return; } if (sim_info->isDown()) @@ -588,33 +618,33 @@ void LLFloaterWorldMap::trackLocation(const LLVector3d& pos_global) LLWorldMap::getInstance()->setTrackingInvalid(); LLTracker::stopTracking(NULL); setDefaultBtn(""); - + // clicked on a down region - turn off coord display enableTeleportCoordsDisplay( false ); - + return; } - + std::string sim_name = sim_info->getName(); F32 region_x = (F32)fmod( pos_global.mdV[VX], (F64)REGION_WIDTH_METERS ); F32 region_y = (F32)fmod( pos_global.mdV[VY], (F64)REGION_WIDTH_METERS ); std::string full_name = llformat("%s (%d, %d, %d)", - sim_name.c_str(), - llround(region_x), - llround(region_y), - llround((F32)pos_global.mdV[VZ])); - + sim_name.c_str(), + llround(region_x), + llround(region_y), + llround((F32)pos_global.mdV[VZ])); + std::string tooltip(""); mTrackedStatus = LLTracker::TRACKING_LOCATION; LLTracker::trackLocation(pos_global, full_name, tooltip); LLWorldMap::getInstance()->cancelTracking(); // The floater is taking over the tracking - + LLVector3d coord_pos = LLTracker::getTrackedPositionGlobal(); updateTeleportCoordsDisplay( coord_pos ); - + // we have a valid region - turn on coord display enableTeleportCoordsDisplay( true ); - + setDefaultBtn("Teleport"); } @@ -631,7 +661,7 @@ void LLFloaterWorldMap::updateTeleportCoordsDisplay( const LLVector3d& pos ) { // if we're going to update their value, we should also enable them enableTeleportCoordsDisplay( true ); - + // convert global specified position to a local one F32 region_local_x = (F32)fmod( pos.mdV[VX], (F64)REGION_WIDTH_METERS ); F32 region_local_y = (F32)fmod( pos.mdV[VY], (F64)REGION_WIDTH_METERS ); @@ -646,16 +676,16 @@ void LLFloaterWorldMap::updateTeleportCoordsDisplay( const LLVector3d& pos ) void LLFloaterWorldMap::updateLocation() { bool gotSimName; - + LLTracker::ETrackingStatus status = LLTracker::getTrackingStatus(); - + // These values may get updated by a message, so need to check them every frame // The fields may be changed by the user, so only update them if the data changes LLVector3d pos_global = LLTracker::getTrackedPositionGlobal(); if (pos_global.isExactlyZero()) { LLVector3d agentPos = gAgent.getPositionGlobal(); - + // Set to avatar's current postion if nothing is selected if ( status == LLTracker::TRACKING_NOTHING && mSetToUserPosition ) { @@ -665,19 +695,19 @@ void LLFloaterWorldMap::updateLocation() if ( gotSimName ) { mSetToUserPosition = FALSE; - + // Fill out the location field getChild<LLUICtrl>("location")->setValue(agent_sim_name); - + // update the coordinate display with location of avatar in region updateTeleportCoordsDisplay( agentPos ); - + // Figure out where user is // Set the current SLURL mSLURL = LLSLURL(agent_sim_name, gAgent.getPositionGlobal()); } } - + return; // invalid location } std::string sim_name; @@ -699,17 +729,17 @@ void LLFloaterWorldMap::updateLocation() pos_global[2] = 200; } } - + getChild<LLUICtrl>("location")->setValue(sim_name); - + // refresh coordinate display to reflect where user clicked. LLVector3d coord_pos = LLTracker::getTrackedPositionGlobal(); updateTeleportCoordsDisplay( coord_pos ); - + // simNameFromPosGlobal can fail, so don't give the user an invalid SLURL if ( gotSimName ) { - mSLURL = LLSLURL(sim_name, pos_global); + mSLURL = LLSLURL(sim_name, pos_global); } else { // Empty SLURL will disable the "Copy SLURL to clipboard" button @@ -736,12 +766,12 @@ void LLFloaterWorldMap::trackURL(const std::string& region_name, S32 x_coord, S3 { // fill in UI based on URL gFloaterWorldMap->getChild<LLUICtrl>("location")->setValue(region_name); - + // Save local coords to highlight position after region global // position is returned. gFloaterWorldMap->mCompletingRegionPos.set( - (F32)x_coord, (F32)y_coord, (F32)z_coord); - + (F32)x_coord, (F32)y_coord, (F32)z_coord); + // pass sim name to combo box gFloaterWorldMap->mCompletingRegionName = region_name; LLWorldMapMessage::getInstance()->sendNamedRegionRequest(region_name); @@ -813,7 +843,7 @@ void LLFloaterWorldMap::buildAvatarIDList() { LLCtrlListInterface *list = childGetListInterface("friend combo"); if (!list) return; - + // Delete all but the "None" entry S32 list_size = list->getItemCount(); if (list_size > 1) @@ -821,7 +851,7 @@ void LLFloaterWorldMap::buildAvatarIDList() list->selectItemRange(1, -1); list->operateOnSelection(LLCtrlListInterface::OP_DELETE); } - + // Get all of the calling cards for avatar that are currently online LLCollectMappableBuddies collector; LLAvatarTracker::instance().applyFunctor(collector); @@ -833,7 +863,7 @@ void LLFloaterWorldMap::buildAvatarIDList() { list->addSimpleElement((*it).first, ADD_BOTTOM, (*it).second); } - + list->setCurrentByID( LLAvatarTracker::instance().getAvatarID() ); list->selectFirstItem(); } @@ -843,7 +873,7 @@ void LLFloaterWorldMap::buildLandmarkIDLists() { LLCtrlListInterface *list = childGetListInterface("landmark combo"); if (!list) return; - + // Delete all but the "None" entry S32 list_size = list->getItemCount(); if (list_size > 1) @@ -851,17 +881,17 @@ void LLFloaterWorldMap::buildLandmarkIDLists() list->selectItemRange(1, -1); list->operateOnSelection(LLCtrlListInterface::OP_DELETE); } - + mLandmarkItemIDList.reset(); mLandmarkAssetIDList.reset(); - + // Get all of the current landmarks mLandmarkAssetIDList.put( LLUUID::null ); mLandmarkItemIDList.put( LLUUID::null ); - + mLandmarkAssetIDList.put( sHomeID ); mLandmarkItemIDList.put( sHomeID ); - + LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; LLIsType is_landmark(LLAssetType::AT_LANDMARK); @@ -870,20 +900,20 @@ void LLFloaterWorldMap::buildLandmarkIDLists() items, LLInventoryModel::EXCLUDE_TRASH, is_landmark); - + std::sort(items.begin(), items.end(), LLViewerInventoryItem::comparePointers()); S32 count = items.count(); for(S32 i = 0; i < count; ++i) { LLInventoryItem* item = items.get(i); - + list->addSimpleElement(item->getName(), ADD_BOTTOM, item->getUUID()); - + mLandmarkAssetIDList.put( item->getAssetUUID() ); mLandmarkItemIDList.put( item->getUUID() ); } - + list->selectFirstItem(); } @@ -949,31 +979,31 @@ void LLFloaterWorldMap::adjustZoomSliderBounds() // Currently (01/26/09), this value allows the whole grid to be visible in a 1024x1024 window. S32 world_width_regions = MAX_VISIBLE_REGIONS; S32 world_height_regions = MAX_VISIBLE_REGIONS; - + // Find how much space we have to display the world LLWorldMapView* map_panel; map_panel = (LLWorldMapView*)mPanel; LLRect view_rect = map_panel->getRect(); - + // View size in pixels S32 view_width = view_rect.getWidth(); S32 view_height = view_rect.getHeight(); - + // Pixels per region to display entire width/height F32 width_pixels_per_region = (F32) view_width / (F32) world_width_regions; F32 height_pixels_per_region = (F32) view_height / (F32) world_height_regions; - + F32 pixels_per_region = llmin(width_pixels_per_region, height_pixels_per_region); - + // Round pixels per region to an even number of slider increments S32 slider_units = llfloor(pixels_per_region / 0.2f); pixels_per_region = slider_units * 0.2f; - + // Make sure the zoom slider can be moved at least a little bit. // Likewise, less than the increment pixels per region is just silly. pixels_per_region = llclamp(pixels_per_region, 1.f, ZOOM_MAX); - + F32 min_power = log(pixels_per_region/256.f)/log(2.f); getChild<LLSlider>("zoom slider")->setMinValue(min_power); @@ -997,19 +1027,19 @@ void LLFloaterWorldMap::onLandmarkComboPrearrange( ) { return; } - + LLCtrlListInterface *list = childGetListInterface("landmark combo"); if (!list) return; - + LLUUID current_choice = list->getCurrentID(); - + buildLandmarkIDLists(); - + if( current_choice.isNull() || !list->setCurrentByID( current_choice ) ) { LLTracker::stopTracking(NULL); } - + } void LLFloaterWorldMap::onComboTextEntry() @@ -1033,18 +1063,18 @@ void LLFloaterWorldMap::onLandmarkComboCommit() { return; } - + LLCtrlListInterface *list = childGetListInterface("landmark combo"); if (!list) return; - + LLUUID asset_id; LLUUID item_id = list->getCurrentID(); - + LLTracker::stopTracking(NULL); - + //RN: stopTracking() clears current combobox selection, need to reassert it here list->setCurrentByID(item_id); - + if( item_id.isNull() ) { } @@ -1068,7 +1098,7 @@ void LLFloaterWorldMap::onLandmarkComboCommit() trackLandmark( item_id); onShowTargetBtn(); - + // Reset to user postion if nothing is tracked mSetToUserPosition = ( LLTracker::getTrackingStatus() == LLTracker::TRACKING_NOTHING ); } @@ -1080,19 +1110,19 @@ void LLFloaterWorldMap::onAvatarComboPrearrange( ) { return; } - + LLCtrlListInterface *list = childGetListInterface("friend combo"); if (!list) return; - + LLUUID current_choice; - + if( LLAvatarTracker::instance().haveTrackingInfo() ) { current_choice = LLAvatarTracker::instance().getAvatarID(); } - + buildAvatarIDList(); - + if( !list->setCurrentByID( current_choice ) || current_choice.isNull() ) { LLTracker::stopTracking(NULL); @@ -1105,10 +1135,10 @@ void LLFloaterWorldMap::onAvatarComboCommit() { return; } - + LLCtrlListInterface *list = childGetListInterface("friend combo"); if (!list) return; - + const LLUUID& new_avatar_id = list->getCurrentID(); if (new_avatar_id.notNull()) { @@ -1124,6 +1154,12 @@ void LLFloaterWorldMap::onAvatarComboCommit() } } +void LLFloaterWorldMap::avatarTrackFromSlapp( const LLUUID& id ) +{ + trackAvatar( id, "av" ); + onShowTargetBtn(); +} + void LLFloaterWorldMap::onLocationFocusChanged( LLFocusableElement* focus ) { updateSearchEnabled(); @@ -1148,13 +1184,13 @@ void LLFloaterWorldMap::onLocationCommit() { return; } - + clearLocationSelection(FALSE); mCompletingRegionName = ""; mLastRegionName = ""; - + std::string str = getChild<LLUICtrl>("location")->getValue().asString(); - + // Trim any leading and trailing spaces in the search target std::string saved_str = str; LLStringUtil::trim( str ); @@ -1162,7 +1198,7 @@ void LLFloaterWorldMap::onLocationCommit() { // Set the value in the UI if any spaces were removed getChild<LLUICtrl>("location")->setValue(str); } - + LLStringUtil::toLower(str); mCompletingRegionName = str; LLWorldMap::getInstance()->setTrackingCommit(); @@ -1183,13 +1219,13 @@ void LLFloaterWorldMap::onCoordinatesCommit() { return; } - + S32 x_coord = (S32)childGetValue("teleport_coordinate_x").asReal(); S32 y_coord = (S32)childGetValue("teleport_coordinate_y").asReal(); S32 z_coord = (S32)childGetValue("teleport_coordinate_z").asReal(); - + const std::string region_name = childGetValue("location").asString(); - + trackURL( region_name, x_coord, y_coord, z_coord ); } @@ -1225,7 +1261,7 @@ void LLFloaterWorldMap::onCopySLURL() LLSD args; args["SLURL"] = mSLURL.getSLURLString(); - + LLNotificationsUtil::add("CopySLURL", args); } @@ -1246,26 +1282,26 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate) else { // We've got the position finally, so we're no longer busy. JC -// getWindow()->decBusyCount(); + // getWindow()->decBusyCount(); pos_global = LLTracker::getTrackedPositionGlobal() - gAgentCamera.getCameraPositionGlobal(); } } else if(LLWorldMap::getInstance()->isTracking()) { pos_global = LLWorldMap::getInstance()->getTrackedPositionGlobal() - gAgentCamera.getCameraPositionGlobal();; - - - + + + } else { // default behavior = center on agent pos_global.clearVec(); } - + LLWorldMapView::setPan( -llfloor((F32)(pos_global.mdV[VX] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)), - -llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)), - !animate); + -llfloor((F32)(pos_global.mdV[VY] * (F64)LLWorldMapView::sMapScale / REGION_WIDTH_METERS)), + !animate); mWaitingForTracker = FALSE; } @@ -1273,7 +1309,7 @@ void LLFloaterWorldMap::centerOnTarget(BOOL animate) void LLFloaterWorldMap::fly() { LLVector3d pos_global = LLTracker::getTrackedPositionGlobal(); - + // Start the autopilot and close the floater, // so we can see where we're flying if (!pos_global.isExactlyZero()) @@ -1294,7 +1330,7 @@ void LLFloaterWorldMap::teleport() BOOL teleport_home = FALSE; LLVector3d pos_global; LLAvatarTracker& av_tracker = LLAvatarTracker::instance(); - + LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus(); if (LLTracker::TRACKING_AVATAR == tracking_status && av_tracker.haveTrackingInfo() ) @@ -1317,10 +1353,10 @@ void LLFloaterWorldMap::teleport() && landmark->getRegionID(region_id)) { LLLandmark::requestRegionHandle( - gMessageSystem, - gAgent.getRegionHost(), - region_id, - NULL); + gMessageSystem, + gAgent.getRegionHost(), + region_id, + NULL); } } } @@ -1332,7 +1368,7 @@ void LLFloaterWorldMap::teleport() { make_ui_sound("UISndInvalidOp"); } - + // Do the teleport, which will also close the floater if (teleport_home) { @@ -1367,7 +1403,7 @@ void LLFloaterWorldMap::teleportToLandmark() { BOOL has_destination = FALSE; LLUUID destination_id; // Null means "home" - + if( LLTracker::getTrackedLandmarkAssetID() == sHomeID ) { has_destination = TRUE; @@ -1388,14 +1424,14 @@ void LLFloaterWorldMap::teleportToLandmark() if(landmark->getRegionID(region_id)) { LLLandmark::requestRegionHandle( - gMessageSystem, - gAgent.getRegionHost(), - region_id, - NULL); + gMessageSystem, + gAgent.getRegionHost(), + region_id, + NULL); } } } - + if( has_destination ) { gAgent.teleportViaLandmark( destination_id ); @@ -1428,12 +1464,12 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) { return; } - + LLScrollListCtrl *list = getChild<LLScrollListCtrl>("search_results"); list->operateOnAll(LLCtrlListInterface::OP_DELETE); - + S32 name_length = mCompletingRegionName.length(); - + LLSD match; S32 num_results = 0; @@ -1443,7 +1479,7 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) LLSimInfo* info = it->second; std::string sim_name_lower = info->getName(); LLStringUtil::toLower(sim_name_lower); - + if (sim_name_lower.substr(0, name_length) == mCompletingRegionName) { if (sim_name_lower == mCompletingRegionName) @@ -1459,12 +1495,12 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) num_results++; } } - + if (found_null_sim) { mCompletingRegionName = ""; } - + // if match found, highlight it and go if (!match.isUndefined()) { @@ -1472,7 +1508,7 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim) getChild<LLUICtrl>("search_results")->setFocus(TRUE); onCommitSearchResult(); } - + // if we found nothing, say "none" if (num_results == 0) { @@ -1486,7 +1522,7 @@ void LLFloaterWorldMap::onCommitSearchResult() { LLCtrlListInterface *list = childGetListInterface("search_results"); if (!list) return; - + LLSD selected_value = list->getSelectedValue(); std::string sim_name = selected_value.asString(); if (sim_name.empty()) @@ -1494,19 +1530,19 @@ void LLFloaterWorldMap::onCommitSearchResult() return; } LLStringUtil::toLower(sim_name); - + std::map<U64, LLSimInfo*>::const_iterator it; for (it = LLWorldMap::getInstance()->getRegionMap().begin(); it != LLWorldMap::getInstance()->getRegionMap().end(); ++it) { LLSimInfo* info = it->second; - + if (info->isName(sim_name)) { LLVector3d pos_global = info->getGlobalOrigin(); - + const F64 SIM_COORD_DEFAULT = 128.0; LLVector3 pos_local(SIM_COORD_DEFAULT, SIM_COORD_DEFAULT, 0.0f); - + // Did this value come from a trackURL() request? if (!mCompletingRegionPos.isExactlyZero()) { @@ -1516,14 +1552,14 @@ void LLFloaterWorldMap::onCommitSearchResult() pos_global.mdV[VX] += (F64)pos_local.mV[VX]; pos_global.mdV[VY] += (F64)pos_local.mV[VY]; pos_global.mdV[VZ] = (F64)pos_local.mV[VZ]; - + getChild<LLUICtrl>("location")->setValue(sim_name); trackLocation(pos_global); setDefaultBtn("Teleport"); break; } } - + onShowTargetBtn(); } @@ -1531,15 +1567,15 @@ void LLFloaterWorldMap::onChangeMaturity() { bool can_access_mature = gAgent.canAccessMature(); bool can_access_adult = gAgent.canAccessAdult(); - + getChildView("events_mature_icon")->setVisible( can_access_mature); getChildView("events_mature_label")->setVisible( can_access_mature); getChildView("events_mature_chk")->setVisible( can_access_mature); - + getChildView("events_adult_icon")->setVisible( can_access_adult); getChildView("events_adult_label")->setVisible( can_access_adult); getChildView("events_adult_chk")->setVisible( can_access_adult); - + // disable mature / adult events. if (!can_access_mature) { diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 1628a421ec..783d9f4819 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -106,6 +106,11 @@ public: // teleport to the tracked item, if there is one void teleport(); void onChangeMaturity(); + + + //Slapp instigated avatar tracking + void avatarTrackFromSlapp( const LLUUID& id ); + protected: void onGoHome(); diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index ce305dcd89..afd565bb26 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -280,19 +280,19 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& void LLIMModel::LLIMSession::onAdHocNameCache(const LLAvatarName& av_name) { if (av_name.mIsDummy) - {
- S32 separator_index = mName.rfind(" ");
- std::string name = mName.substr(0, separator_index);
- ++separator_index;
- std::string conference_word = mName.substr(separator_index, mName.length());
-
- // additional check that session name is what we expected
- if ("Conference" == conference_word)
- {
- LLStringUtil::format_map_t args;
- args["[AGENT_NAME]"] = name;
- LLTrans::findString(mName, "conference-title-incoming", args);
- }
+ { + S32 separator_index = mName.rfind(" "); + std::string name = mName.substr(0, separator_index); + ++separator_index; + std::string conference_word = mName.substr(separator_index, mName.length()); + + // additional check that session name is what we expected + if ("Conference" == conference_word) + { + LLStringUtil::format_map_t args; + args["[AGENT_NAME]"] = name; + LLTrans::findString(mName, "conference-title-incoming", args); + } } else { diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index e765a8da2f..a15776c207 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -100,7 +100,7 @@ public: void onAvatarNameCache(const LLUUID& avatar_id, const LLAvatarName& av_name); - void onAdHocNameCache(const LLAvatarName& av_name);
+ void onAdHocNameCache(const LLAvatarName& av_name); //*TODO make private static std::string generateHash(const std::set<LLUUID>& sorted_uuids); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 0870b5b8dd..5a9d1524f3 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -921,6 +921,8 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open) { S32 z_min = S32_MAX; LLInventoryPanel* res = NULL; + LLFloater* active_inv_floaterp = NULL; + // A. If the inventory side panel is open, use that preferably. if (is_inventorysp_active()) { @@ -941,6 +943,7 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open) { res = inventorySP->getActivePanel(); z_min = gFloaterView->getZOrder(inv_floater); + active_inv_floaterp = inv_floater; } else { @@ -960,10 +963,19 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open) { res = iv->getPanel(); z_min = z_order; + active_inv_floaterp = iv; } } } - if (res) return res; + + if (res) + { + // Make sure the floater is not minimized (STORM-438). + if (active_inv_floaterp && active_inv_floaterp->isMinimized()) + active_inv_floaterp->setMinimized(FALSE); + + return res; + } // C. If no panels are open and we don't want to force open a panel, then just abort out. if (!auto_open) return NULL; diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp index 1527f8f4c9..55164f6094 100644 --- a/indra/newview/lllocationinputctrl.cpp +++ b/indra/newview/lllocationinputctrl.cpp @@ -547,6 +547,10 @@ void LLLocationInputCtrl::onFocusLost() { LLUICtrl::onFocusLost(); refreshLocation(); + + // Setting cursor to 0 to show the left edge of the text. See STORM-370. + mTextEntry->setCursor(0); + if(mTextEntry->hasSelection()){ mTextEntry->deselect(); } diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 0121bbb1ed..9adf374c71 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -89,15 +89,15 @@ const static boost::regex TIMESTAMP_AND_STUFF("^(\\[\\d{4}/\\d{1,2}/\\d{1,2}\\s+ */ const static boost::regex NAME_AND_TEXT("([^:]+[:]{1})?(\\s*)(.*)"); -/**
- * These are recognizers for matching the names of ad-hoc conferences when generating the log file name
- * On invited side, an ad-hoc is named like "<first name> <last name> Conference 2010/11/19 03:43 f0f4"
- * On initiating side, an ad-hoc is named like Ad-hoc Conference hash<hash>"
- * If the naming system for ad-hoc conferences are change in LLIMModel::LLIMSession::buildHistoryFileName()
- * then these definition need to be adjusted as well.
- */
-const static boost::regex INBOUND_CONFERENCE("^[a-zA-Z]{1,31} [a-zA-Z]{1,31} Conference [0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2} [0-9a-f]{4}");
-const static boost::regex OUTBOUND_CONFERENCE("^Ad-hoc Conference hash[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}");
+/** + * These are recognizers for matching the names of ad-hoc conferences when generating the log file name + * On invited side, an ad-hoc is named like "<first name> <last name> Conference 2010/11/19 03:43 f0f4" + * On initiating side, an ad-hoc is named like Ad-hoc Conference hash<hash>" + * If the naming system for ad-hoc conferences are change in LLIMModel::LLIMSession::buildHistoryFileName() + * then these definition need to be adjusted as well. + */ +const static boost::regex INBOUND_CONFERENCE("^[a-zA-Z]{1,31} [a-zA-Z]{1,31} Conference [0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2} [0-9a-f]{4}"); +const static boost::regex OUTBOUND_CONFERENCE("^Ad-hoc Conference hash[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"); //is used to parse complex object names like "Xstreet SL Terminal v2.2.5 st" const static std::string NAME_TEXT_DIVIDER(": "); diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index a9bcdef47c..94b2340c93 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -477,6 +477,7 @@ LLPanelAvatarProfile::LLPanelAvatarProfile() BOOL LLPanelAvatarProfile::postBuild() { + childSetCommitCallback("see_profile_btn",(boost::bind(&LLPanelAvatarProfile::onSeeProfileBtnClick,this)),NULL); childSetCommitCallback("add_friend",(boost::bind(&LLPanelAvatarProfile::onAddFriendButtonClick,this)),NULL); childSetCommitCallback("im",(boost::bind(&LLPanelAvatarProfile::onIMButtonClick,this)),NULL); childSetCommitCallback("call",(boost::bind(&LLPanelAvatarProfile::onCallButtonClick,this)),NULL); @@ -624,6 +625,35 @@ void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_g getChild<LLUICtrl>("sl_groups")->setValue(groups); } +void LLPanelAvatarProfile::got_full_name_callback( const LLUUID& id, const std::string& full_name, bool is_group )
+{
+ LLStringUtil::format_map_t args;
+
+ std::string name; + if (LLAvatarNameCache::useDisplayNames()) + { + name = LLCacheName::buildUsername(full_name); + } + else + { + name = full_name; + }
+
+ args["[NAME]"] = name;
+
+ std::string linden_name = getString("name_text_args", args);
+ getChild<LLUICtrl>("name_descr_text")->setValue(linden_name);
+}
+ +void LLPanelAvatarProfile::onNameCache(const LLUUID& agent_id, const LLAvatarName& av_name) +{ + LLStringUtil::format_map_t args;
+ args["[DISPLAY_NAME]"] = av_name.mDisplayName;
+
+ std::string display_name = getString("display_name_text_args", args);
+ getChild<LLUICtrl>("display_name_descr_text")->setValue(display_name);
+} + void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data) { //remove avatar id from cache to get fresh info @@ -635,6 +665,24 @@ void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data) LLStringUtil::format(birth_date, LLSD().with("datetime", (S32) avatar_data->born_on.secondsSinceEpoch())); args["[REG_DATE]"] = birth_date; } + + // ask (asynchronously) for the avatar name + std::string full_name;
+ if (gCacheName->getFullName(avatar_data->agent_id, full_name))
+ {
+ // name in cache, call callback directly
+ got_full_name_callback( avatar_data->agent_id, full_name, false );
+ }
+ else
+ {
+ // not in cache, lookup name
+ gCacheName->get(avatar_data->agent_id, false, boost::bind( &LLPanelAvatarProfile::got_full_name_callback, this, _1, _2, _3 ));
+ }
+
+ // get display name
+ LLAvatarNameCache::get(avatar_data->avatar_id, + boost::bind(&LLPanelAvatarProfile::onNameCache, this, _1, _2));
+
args["[AGE]"] = LLDateUtil::ageFromDate( avatar_data->born_on, LLDate::now()); std::string register_date = getString("RegisterDateFormat", args); getChild<LLUICtrl>("register_date")->setValue(register_date ); @@ -734,6 +782,11 @@ void LLPanelAvatarProfile::onAddFriendButtonClick() LLAvatarActions::requestFriendshipDialog(getAvatarId()); } +void LLPanelAvatarProfile::onSeeProfileBtnClick() +{ + LLAvatarActions::showProfile(getAvatarId()); +} + void LLPanelAvatarProfile::onIMButtonClick() { LLAvatarActions::startIM(getAvatarId()); diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index 71d9d0a95a..070fe4579a 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -1,295 +1,298 @@ -/** - * @file llpanelavatar.h - * @brief LLPanelAvatar and related class definitions - * - * $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$ - */ - -#ifndef LL_LLPANELAVATAR_H -#define LL_LLPANELAVATAR_H - -#include "llpanel.h" -#include "llavatarpropertiesprocessor.h" -#include "llcallingcard.h" -#include "llvoiceclient.h" - -class LLComboBox; -class LLLineEditor; - -enum EOnlineStatus -{ - ONLINE_STATUS_NO = 0, - ONLINE_STATUS_YES = 1 -}; - -/** -* Base class for any Profile View or My Profile Panel. -*/ -class LLPanelProfileTab - : public LLPanel - , public LLAvatarPropertiesObserver -{ -public: - - /** - * Sets avatar ID, sets panel as observer of avatar related info replies from server. - */ - virtual void setAvatarId(const LLUUID& id); - - /** - * Returns avatar ID. - */ - virtual const LLUUID& getAvatarId() { return mAvatarId; } - - /** - * Sends update data request to server. - */ - virtual void updateData() = 0; - - /** - * Clears panel data if viewing avatar info for first time and sends update data request. - */ - virtual void onOpen(const LLSD& key); - - /** - * Profile tabs should close any opened panels here. - * - * Called from LLPanelProfile::onOpen() before opening new profile. - * See LLPanelPicks::onClosePanel for example. LLPanelPicks closes picture info panel - * before new profile is displayed, otherwise new profile will - * be hidden behind picture info panel. - */ - virtual void onClosePanel() {} - - /** - * Resets controls visibility, state, etc. - */ - virtual void resetControls(){}; - - /** - * Clears all data received from server. - */ - virtual void resetData(){}; - - /*virtual*/ ~LLPanelProfileTab(); - -protected: - - LLPanelProfileTab(); - - /** - * Scrolls panel to top when viewing avatar info for first time. - */ - void scrollToTop(); - - virtual void onMapButtonClick(); - - virtual void updateButtons(); - -private: - - LLUUID mAvatarId; -}; - -/** -* Panel for displaying Avatar's first and second life related info. -*/ -class LLPanelAvatarProfile - : public LLPanelProfileTab - , public LLFriendObserver - , public LLVoiceClientStatusObserver -{ -public: - LLPanelAvatarProfile(); - /*virtual*/ ~LLPanelAvatarProfile(); - - /*virtual*/ void onOpen(const LLSD& key); - - /** - * LLFriendObserver trigger - */ - virtual void changed(U32 mask); - - // Implements LLVoiceClientStatusObserver::onChange() to enable the call - // button when voice is available - /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); - - /*virtual*/ void setAvatarId(const LLUUID& id); - - /** - * Processes data received from server. - */ - /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - - /*virtual*/ BOOL postBuild(); - - /*virtual*/ void updateData(); - - /*virtual*/ void resetControls(); - - /*virtual*/ void resetData(); - -protected: - - /** - * Process profile related data received from server. - */ - virtual void processProfileProperties(const LLAvatarData* avatar_data); - - /** - * Processes group related data received from server. - */ - virtual void processGroupProperties(const LLAvatarGroups* avatar_groups); - - /** - * Fills common for Avatar profile and My Profile fields. - */ - virtual void fillCommonData(const LLAvatarData* avatar_data); - - /** - * Fills partner data. - */ - virtual void fillPartnerData(const LLAvatarData* avatar_data); - - /** - * Fills account status. - */ - virtual void fillAccountStatus(const LLAvatarData* avatar_data); - - /** - * Opens "Pay Resident" dialog. - */ - void pay(); - - /** - * opens inventory and IM for sharing items - */ - void share(); - - /** - * Add/remove resident to/from your block list. - */ - void toggleBlock(); - - void kick(); - void freeze(); - void unfreeze(); - void csr(); - - bool enableShowOnMap(); - bool enableBlock(); - bool enableUnblock(); - bool enableGod(); - - - void onAddFriendButtonClick(); - void onIMButtonClick(); - void onCallButtonClick(); - void onTeleportButtonClick(); - void onShareButtonClick(); - -private: - - typedef std::map< std::string,LLUUID> group_map_t; - group_map_t mGroups; -}; - -/** - * Panel for displaying own first and second life related info. - */ -class LLPanelMyProfile - : public LLPanelAvatarProfile -{ -public: - LLPanelMyProfile(); - - /*virtual*/ BOOL postBuild(); - -protected: - - /*virtual*/ void onOpen(const LLSD& key); - - /*virtual*/ void processProfileProperties(const LLAvatarData* avatar_data); - - /*virtual*/ void resetControls(); - -protected: - void onStatusMessageChanged(); -}; - -/** - * Panel for displaying Avatar's notes and modifying friend's rights. - */ -class LLPanelAvatarNotes - : public LLPanelProfileTab - , public LLFriendObserver - , public LLVoiceClientStatusObserver -{ -public: - LLPanelAvatarNotes(); - /*virtual*/ ~LLPanelAvatarNotes(); - - virtual void setAvatarId(const LLUUID& id); - - /** - * LLFriendObserver trigger - */ - virtual void changed(U32 mask); - - // Implements LLVoiceClientStatusObserver::onChange() to enable the call - // button when voice is available - /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal); - - /*virtual*/ void onOpen(const LLSD& key); - - /*virtual*/ BOOL postBuild(); - - /*virtual*/ void processProperties(void* data, EAvatarProcessorType type); - - /*virtual*/ void updateData(); - -protected: - - /*virtual*/ void resetControls(); - - /*virtual*/ void resetData(); - - /** - * Fills rights data for friends. - */ - void fillRightsData(); - - void rightsConfirmationCallback(const LLSD& notification, - const LLSD& response, S32 rights); - void confirmModifyRights(bool grant, S32 rights); - void onCommitRights(); - void onCommitNotes(); - - void onAddFriendButtonClick(); - void onIMButtonClick(); - void onCallButtonClick(); - void onTeleportButtonClick(); - void onShareButtonClick(); - void enableCheckboxes(bool enable); -}; - -#endif // LL_LLPANELAVATAR_H +/**
+ * @file llpanelavatar.h
+ * @brief LLPanelAvatar and related class definitions
+ *
+ * $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$
+ */
+
+#ifndef LL_LLPANELAVATAR_H
+#define LL_LLPANELAVATAR_H
+
+#include "llpanel.h"
+#include "llavatarpropertiesprocessor.h"
+#include "llcallingcard.h"
+#include "llvoiceclient.h"
+#include "llavatarnamecache.h"
+
+class LLComboBox;
+class LLLineEditor;
+
+enum EOnlineStatus
+{
+ ONLINE_STATUS_NO = 0,
+ ONLINE_STATUS_YES = 1
+};
+
+/**
+* Base class for any Profile View or My Profile Panel.
+*/
+class LLPanelProfileTab
+ : public LLPanel
+ , public LLAvatarPropertiesObserver
+{
+public:
+
+ /**
+ * Sets avatar ID, sets panel as observer of avatar related info replies from server.
+ */
+ virtual void setAvatarId(const LLUUID& id);
+
+ /**
+ * Returns avatar ID.
+ */
+ virtual const LLUUID& getAvatarId() { return mAvatarId; }
+
+ /**
+ * Sends update data request to server.
+ */
+ virtual void updateData() = 0;
+
+ /**
+ * Clears panel data if viewing avatar info for first time and sends update data request.
+ */
+ virtual void onOpen(const LLSD& key);
+
+ /**
+ * Profile tabs should close any opened panels here.
+ *
+ * Called from LLPanelProfile::onOpen() before opening new profile.
+ * See LLPanelPicks::onClosePanel for example. LLPanelPicks closes picture info panel
+ * before new profile is displayed, otherwise new profile will
+ * be hidden behind picture info panel.
+ */
+ virtual void onClosePanel() {}
+
+ /**
+ * Resets controls visibility, state, etc.
+ */
+ virtual void resetControls(){};
+
+ /**
+ * Clears all data received from server.
+ */
+ virtual void resetData(){};
+
+ /*virtual*/ ~LLPanelProfileTab();
+
+protected:
+
+ LLPanelProfileTab();
+
+ /**
+ * Scrolls panel to top when viewing avatar info for first time.
+ */
+ void scrollToTop();
+
+ virtual void onMapButtonClick();
+
+ virtual void updateButtons();
+
+private:
+
+ LLUUID mAvatarId;
+};
+
+/**
+* Panel for displaying Avatar's first and second life related info.
+*/
+class LLPanelAvatarProfile
+ : public LLPanelProfileTab
+ , public LLFriendObserver
+ , public LLVoiceClientStatusObserver
+{
+public:
+ LLPanelAvatarProfile();
+ /*virtual*/ ~LLPanelAvatarProfile();
+
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ /**
+ * LLFriendObserver trigger
+ */
+ virtual void changed(U32 mask);
+
+ // Implements LLVoiceClientStatusObserver::onChange() to enable the call
+ // button when voice is available
+ /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
+
+ /*virtual*/ void setAvatarId(const LLUUID& id);
+
+ /**
+ * Processes data received from server.
+ */
+ /*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ void updateData();
+
+ /*virtual*/ void resetControls();
+
+ /*virtual*/ void resetData();
+
+protected:
+
+ /**
+ * Process profile related data received from server.
+ */
+ virtual void processProfileProperties(const LLAvatarData* avatar_data);
+
+ /**
+ * Processes group related data received from server.
+ */
+ virtual void processGroupProperties(const LLAvatarGroups* avatar_groups);
+
+ /**
+ * Fills common for Avatar profile and My Profile fields.
+ */
+ virtual void fillCommonData(const LLAvatarData* avatar_data);
+
+ /**
+ * Fills partner data.
+ */
+ virtual void fillPartnerData(const LLAvatarData* avatar_data);
+
+ /**
+ * Fills account status.
+ */
+ virtual void fillAccountStatus(const LLAvatarData* avatar_data);
+
+ /**
+ * Opens "Pay Resident" dialog.
+ */
+ void pay();
+
+ /**
+ * opens inventory and IM for sharing items
+ */
+ void share();
+
+ /**
+ * Add/remove resident to/from your block list.
+ */
+ void toggleBlock();
+
+ void kick();
+ void freeze();
+ void unfreeze();
+ void csr();
+
+ bool enableShowOnMap();
+ bool enableBlock();
+ bool enableUnblock();
+ bool enableGod();
+
+ void onSeeProfileBtnClick();
+ void onAddFriendButtonClick();
+ void onIMButtonClick();
+ void onCallButtonClick();
+ void onTeleportButtonClick();
+ void onShareButtonClick();
+
+private:
+ void got_full_name_callback( const LLUUID& id, const std::string& full_name, bool is_group );
+ void onNameCache(const LLUUID& agent_id, const LLAvatarName& av_name);
+
+ typedef std::map< std::string,LLUUID> group_map_t;
+ group_map_t mGroups;
+};
+
+/**
+ * Panel for displaying own first and second life related info.
+ */
+class LLPanelMyProfile
+ : public LLPanelAvatarProfile
+{
+public:
+ LLPanelMyProfile();
+
+ /*virtual*/ BOOL postBuild();
+
+protected:
+
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ /*virtual*/ void processProfileProperties(const LLAvatarData* avatar_data);
+
+ /*virtual*/ void resetControls();
+
+protected:
+ void onStatusMessageChanged();
+};
+
+/**
+ * Panel for displaying Avatar's notes and modifying friend's rights.
+ */
+class LLPanelAvatarNotes
+ : public LLPanelProfileTab
+ , public LLFriendObserver
+ , public LLVoiceClientStatusObserver
+{
+public:
+ LLPanelAvatarNotes();
+ /*virtual*/ ~LLPanelAvatarNotes();
+
+ virtual void setAvatarId(const LLUUID& id);
+
+ /**
+ * LLFriendObserver trigger
+ */
+ virtual void changed(U32 mask);
+
+ // Implements LLVoiceClientStatusObserver::onChange() to enable the call
+ // button when voice is available
+ /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
+
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ /*virtual*/ BOOL postBuild();
+
+ /*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
+
+ /*virtual*/ void updateData();
+
+protected:
+
+ /*virtual*/ void resetControls();
+
+ /*virtual*/ void resetData();
+
+ /**
+ * Fills rights data for friends.
+ */
+ void fillRightsData();
+
+ void rightsConfirmationCallback(const LLSD& notification,
+ const LLSD& response, S32 rights);
+ void confirmModifyRights(bool grant, S32 rights);
+ void onCommitRights();
+ void onCommitNotes();
+
+ void onAddFriendButtonClick();
+ void onIMButtonClick();
+ void onCallButtonClick();
+ void onTeleportButtonClick();
+ void onShareButtonClick();
+ void enableCheckboxes(bool enable);
+};
+
+#endif // LL_LLPANELAVATAR_H
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 5f89097c17..c143aff2d4 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -253,11 +253,67 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, gResponsePtr = LLIamHereLogin::build( this ); LLHTTPClient::head( LLGridManager::getInstance()->getLoginPage(), gResponsePtr ); - + + // Show last logged in user favorites in "Start at" combo. + addUsersWithFavoritesToUsername(); + getChild<LLComboBox>("username_combo")->setTextChangedCallback(boost::bind(&LLPanelLogin::addFavoritesToStartLocation, this)); + updateLocationCombo(false); } +void LLPanelLogin::addUsersWithFavoritesToUsername() +{ + LLComboBox* combo = getChild<LLComboBox>("username_combo"); + if (!combo) return; + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); + LLSD fav_llsd; + llifstream file; + file.open(filename); + if (!file.is_open()) return; + LLSDSerialize::fromXML(fav_llsd, file); + for (LLSD::map_const_iterator iter = fav_llsd.beginMap(); + iter != fav_llsd.endMap(); ++iter) + { + combo->add(iter->first); + } +} + +void LLPanelLogin::addFavoritesToStartLocation() +{ + LLComboBox* combo = getChild<LLComboBox>("start_location_combo"); + if (!combo) return; + int num_items = combo->getItemCount(); + for (int i = num_items - 1; i > 2; i--) + { + combo->remove(i); + } + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); + LLSD fav_llsd; + llifstream file; + file.open(filename); + if (!file.is_open()) return; + LLSDSerialize::fromXML(fav_llsd, file); + for (LLSD::map_const_iterator iter = fav_llsd.beginMap(); + iter != fav_llsd.endMap(); ++iter) + { + if(iter->first != getChild<LLComboBox>("username_combo")->getSimple()) continue; + combo->addSeparator(); + LLSD user_llsd = iter->second; + for (LLSD::array_const_iterator iter1 = user_llsd.beginArray(); + iter1 != user_llsd.endArray(); ++iter1) + { + std::string label = (*iter1)["name"].asString(); + std::string value = (*iter1)["slurl"].asString(); + if(label != "" && value != "") + { + combo->add(label, value); + } + } + break; + } +} + // force the size to be correct (XML doesn't seem to be sufficient to do this) // (with some padding so the other login screen doesn't show through) void LLPanelLogin::reshapeBrowser() @@ -393,13 +449,14 @@ void LLPanelLogin::giveFocus() if( sInstance ) { // Grab focus and move cursor to first blank input field - std::string username = sInstance->getChild<LLUICtrl>("username_edit")->getValue().asString(); + std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString(); std::string pass = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString(); BOOL have_username = !username.empty(); BOOL have_pass = !pass.empty(); LLLineEditor* edit = NULL; + LLComboBox* combo = NULL; if (have_username && !have_pass) { // User saved his name but not his password. Move @@ -409,7 +466,7 @@ void LLPanelLogin::giveFocus() else { // User doesn't have a name, so start there. - edit = sInstance->getChild<LLLineEditor>("username_edit"); + combo = sInstance->getChild<LLComboBox>("username_combo"); } if (edit) @@ -417,6 +474,10 @@ void LLPanelLogin::giveFocus() edit->setFocus(TRUE); edit->selectAll(); } + else if (combo) + { + combo->setFocus(TRUE); + } } } @@ -431,8 +492,8 @@ void LLPanelLogin::showLoginWidgets() // *TODO: Append all the usual login parameters, like first_login=Y etc. std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage(); web_browser->navigateTo( splash_screen_url, "text/html" ); - LLUICtrl* username_edit = sInstance->getChild<LLUICtrl>("username_edit"); - username_edit->setFocus(TRUE); + LLUICtrl* username_combo = sInstance->getChild<LLUICtrl>("username_combo"); + username_combo->setFocus(TRUE); } // static @@ -476,16 +537,17 @@ void LLPanelLogin::setFields(LLPointer<LLCredential> credential, login_id += " "; login_id += lastname; } - sInstance->getChild<LLUICtrl>("username_edit")->setValue(login_id); + sInstance->getChild<LLComboBox>("username_combo")->setLabel(login_id); } else if((std::string)identifier["type"] == "account") { - sInstance->getChild<LLUICtrl>("username_edit")->setValue((std::string)identifier["account_name"]); + sInstance->getChild<LLComboBox>("username_combo")->setLabel((std::string)identifier["account_name"]); } else { - sInstance->getChild<LLUICtrl>("username_edit")->setValue(std::string()); + sInstance->getChild<LLComboBox>("username_combo")->setLabel(std::string()); } + sInstance->addFavoritesToStartLocation(); // if the password exists in the credential, set the password field with // a filler to get some stars LLSD authenticator = credential->getAuthenticator(); @@ -533,7 +595,7 @@ void LLPanelLogin::getFields(LLPointer<LLCredential>& credential, authenticator = credential->getAuthenticator(); } - std::string username = sInstance->getChild<LLUICtrl>("username_edit")->getValue().asString(); + std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString(); LLStringUtil::trim(username); std::string password = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString(); @@ -625,15 +687,15 @@ BOOL LLPanelLogin::areCredentialFieldsDirty() } else { - std::string username = sInstance->getChild<LLUICtrl>("username_edit")->getValue().asString(); + std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString(); LLStringUtil::trim(username); std::string password = sInstance->getChild<LLUICtrl>("password_edit")->getValue().asString(); - LLLineEditor* ctrl = sInstance->getChild<LLLineEditor>("username_edit"); - if(ctrl && ctrl->isDirty()) + LLComboBox* combo = sInstance->getChild<LLComboBox>("username_combo"); + if(combo && combo->isDirty()) { return true; } - ctrl = sInstance->getChild<LLLineEditor>("password_edit"); + LLLineEditor* ctrl = sInstance->getChild<LLLineEditor>("password_edit"); if(ctrl && ctrl->isDirty()) { return true; @@ -873,7 +935,7 @@ void LLPanelLogin::onClickConnect(void *) return; } updateStartSLURL(); - std::string username = sInstance->getChild<LLUICtrl>("username_edit")->getValue().asString(); + std::string username = sInstance->getChild<LLUICtrl>("username_combo")->getValue().asString(); if(username.empty()) diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h index 83e76a308b..1ef6539ecc 100644 --- a/indra/newview/llpanellogin.h +++ b/indra/newview/llpanellogin.h @@ -85,6 +85,8 @@ public: private: friend class LLPanelLoginListener; void reshapeBrowser(); + void addFavoritesToStartLocation(); + void addUsersWithFavoritesToUsername(); static void onClickConnect(void*); static void onClickNewAccount(void*); // static bool newAccountAlertCallback(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp index 5ea94e0611..d3c9c3e131 100644 --- a/indra/newview/llpanelme.cpp +++ b/indra/newview/llpanelme.cpp @@ -76,17 +76,19 @@ void LLPanelMe::onOpen(const LLSD& key) { LLPanelProfile::onOpen(key); - // Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068) - bool opened = gSavedSettings.getBOOL("MePanelOpened"); - // In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this - // is the last time onOpen() is called - if( !opened && !LLSideTray::getInstance()->getCollapsed() ) - { - buildEditPanel(); - openPanel(mEditPanel, getAvatarId()); - - gSavedSettings.setBOOL("MePanelOpened", true); - } + // Removed this action as per SOCIAL-431 The first time a new resident opens the profile tab + // in the sidebar, they see the old profile editing panel + // + //// Force Edit My Profile if this is the first time when user is opening Me Panel (EXT-5068) + //bool opened = gSavedSettings.getBOOL("MePanelOpened"); + //// In some cases Side Tray my call onOpen() twice, check getCollapsed() to be sure this + //// is the last time onOpen() is called + //if( !opened && !LLSideTray::getInstance()->getCollapsed() ) + //{ + // buildEditPanel(); + // openPanel(mEditPanel, getAvatarId()); + // gSavedSettings.setBOOL("MePanelOpened", true); + //} } bool LLPanelMe::notifyChildren(const LLSD& info) diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 15e826ac2c..c4f3866cad 100644..100755 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -70,6 +70,111 @@ static const std::string CLASSIFIED_NAME("classified_name"); static LLRegisterPanelClassWrapper<LLPanelPicks> t_panel_picks("panel_picks"); +class LLPickHandler : public LLCommandHandler, + public LLAvatarPropertiesObserver +{ +public: + + std::set<LLUUID> mPickIds; + + // requires trusted browser to trigger + LLPickHandler() : LLCommandHandler("pick", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& params, const LLSD& query_map, + LLMediaCtrl* web) + { + // handle app/classified/create urls first + if (params.size() == 1 && params[0].asString() == "create") + { + createPick(); + return true; + } + + // then handle the general app/pick/{UUID}/{CMD} urls + if (params.size() < 2) + { + return false; + } + + // get the ID for the pick_id + LLUUID pick_id; + if (!pick_id.set(params[0], FALSE)) + { + return false; + } + + // edit the pick in the side tray. + // need to ask the server for more info first though... + const std::string verb = params[1].asString(); + if (verb == "edit") + { + mPickIds.insert(pick_id); + LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); + LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(gAgent.getID(),pick_id); + return true; + } + else + { + llwarns << "unknown verb " << verb << llendl; + return false; + } + } + + void createPick() + { + LLSD params; + params["id"] = gAgent.getID(); + params["open_tab_name"] = "panel_picks"; + params["show_tab_panel"] = "create_pick"; + LLSideTray::getInstance()->showPanel("panel_me", params); + } + + void editPick(LLPickData* pick_info) + { + LLSD params; + params["open_tab_name"] = "panel_picks"; + params["show_tab_panel"] = "edit_pick"; + params["pick_id"] = pick_info->pick_id; + params["avatar_id"] = pick_info->creator_id; + params["snapshot_id"] = pick_info->snapshot_id; + params["pick_name"] = pick_info->name; + params["pick_desc"] = pick_info->desc; + + LLSideTray::getInstance()->showPanel("panel_me", params); + } + + /*virtual*/ void processProperties(void* data, EAvatarProcessorType type) + { + if (APT_PICK_INFO != type) + { + return; + } + + // is this the pick that we asked for? + LLPickData* pick_info = static_cast<LLPickData*>(data); + if (!pick_info || mPickIds.find(pick_info->pick_id) == mPickIds.end()) + { + return; + } + + // open the edit side tray for this pick + if (pick_info->creator_id == gAgent.getID()) + { + editPick(pick_info); + } + else + { + llwarns << "Can't edit a pick you did not create" << llendl; + } + + // remove our observer now that we're done + mPickIds.erase(pick_info->pick_id); + LLAvatarPropertiesProcessor::getInstance()->removeObserver(LLUUID(), this); + } +}; + +LLPickHandler gPickHandler; + class LLClassifiedHandler : public LLCommandHandler, public LLAvatarPropertiesObserver @@ -80,6 +185,8 @@ public: std::set<LLUUID> mClassifiedIds; + std::string mRequestVerb; + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) { // handle app/classified/create urls first @@ -107,6 +214,15 @@ public: const std::string verb = params[1].asString(); if (verb == "about") { + mRequestVerb = verb; + mClassifiedIds.insert(classified_id); + LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); + LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id); + return true; + } + else if (verb == "edit") + { + mRequestVerb = verb; mClassifiedIds.insert(classified_id); LLAvatarPropertiesProcessor::getInstance()->addObserver(LLUUID(), this); LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(classified_id); @@ -128,18 +244,39 @@ public: void openClassified(LLAvatarClassifiedInfo* c_info) { - // open the classified info panel on the Me > Picks sidetray - LLSD params; - params["id"] = c_info->creator_id; - params["open_tab_name"] = "panel_picks"; - params["show_tab_panel"] = "classified_details"; - params["classified_id"] = c_info->classified_id; - params["classified_creator_id"] = c_info->creator_id; - params["classified_snapshot_id"] = c_info->snapshot_id; - params["classified_name"] = c_info->name; - params["classified_desc"] = c_info->description; - params["from_search"] = true; - LLSideTray::getInstance()->showPanel("panel_profile_view", params); + if (mRequestVerb == "about") + { + // open the classified info panel on the Me > Picks sidetray + LLSD params; + params["id"] = c_info->creator_id; + params["open_tab_name"] = "panel_picks"; + params["show_tab_panel"] = "classified_details"; + params["classified_id"] = c_info->classified_id; + params["classified_creator_id"] = c_info->creator_id; + params["classified_snapshot_id"] = c_info->snapshot_id; + params["classified_name"] = c_info->name; + params["classified_desc"] = c_info->description; + params["from_search"] = true; + LLSideTray::getInstance()->showPanel("panel_profile_view", params); + } + else if (mRequestVerb == "edit") + { + if (c_info->creator_id == gAgent.getID()) + { + llwarns << "edit in progress" << llendl; + // open the new classified panel on the Me > Picks sidetray + LLSD params; + params["id"] = gAgent.getID(); + params["open_tab_name"] = "panel_picks"; + params["show_tab_panel"] = "edit_classified"; + params["classified_id"] = c_info->classified_id; + LLSideTray::getInstance()->showPanel("panel_me", params); + } + else + { + llwarns << "Can't edit a classified you did not create" << llendl; + } + } } /*virtual*/ void processProperties(void* data, EAvatarProcessorType type) @@ -299,7 +436,10 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type) pick_value.insert(CLASSIFIED_ID, c_data.classified_id); pick_value.insert(CLASSIFIED_NAME, c_data.name); - mClassifiedsList->addItem(c_item, pick_value); + if (!findClassifiedById(c_data.classified_id)) + { + mClassifiedsList->addItem(c_item, pick_value); + } c_item->setDoubleClickCallback(boost::bind(&LLPanelPicks::onDoubleClickClassifiedItem, this, _1)); c_item->setRightMouseUpCallback(boost::bind(&LLPanelPicks::onRightMouseUpItem, this, _1, _2, _3, _4)); @@ -776,6 +916,13 @@ void LLPanelPicks::openClassifiedInfo(const LLSD ¶ms) getProfilePanel()->openPanel(mPanelClassifiedInfo, params); } +void LLPanelPicks::openClassifiedEdit(const LLSD& params) +{ + LLUUID classified_id = params["classified_id"].asUUID();; + llinfos << "opening classified " << classified_id << " for edit" << llendl; + editClassified(classified_id); +} + void LLPanelPicks::showAccordion(const std::string& name, bool show) { LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(name); @@ -945,6 +1092,12 @@ void LLPanelPicks::createPickEditPanel() // getProfilePanel()->openPanel(mPanelPickInfo, params); // } +void LLPanelPicks::openPickEdit(const LLSD& params) +{ + createPickEditPanel(); + getProfilePanel()->openPanel(mPanelPickEdit, params); +} + void LLPanelPicks::onPanelPickEdit() { LLSD selected_value = mPicksList->getSelectedValue(); @@ -978,6 +1131,35 @@ void LLPanelPicks::onPanelClassifiedEdit() { return; } + editClassified(c_item->getClassifiedId()); +} + +LLClassifiedItem *LLPanelPicks::findClassifiedById(const LLUUID& classified_id) +{ + // HACK - find item by classified id. Should be a better way. + std::vector<LLPanel*> items; + mClassifiedsList->getItems(items); + LLClassifiedItem* c_item = NULL; + for(std::vector<LLPanel*>::iterator it = items.begin(); it != items.end(); ++it) + { + LLClassifiedItem *test_item = dynamic_cast<LLClassifiedItem*>(*it); + if (test_item && test_item->getClassifiedId() == classified_id) + { + c_item = test_item; + break; + } + } + return c_item; +} + +void LLPanelPicks::editClassified(const LLUUID& classified_id) +{ + LLClassifiedItem* c_item = findClassifiedById(classified_id); + if (!c_item) + { + llwarns << "item not found for classified_id " << classified_id << llendl; + return; + } LLSD params; params["classified_id"] = c_item->getClassifiedId(); diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h index a02ed81bb0..29db110523 100644..100755 --- a/indra/newview/llpanelpicks.h +++ b/indra/newview/llpanelpicks.h @@ -76,6 +76,7 @@ public: // returns the selected pick item LLPickItem* getSelectedPickItem(); LLClassifiedItem* getSelectedClassifiedItem(); + LLClassifiedItem* findClassifiedById(const LLUUID& classified_id); //*NOTE top down approch when panel toggling is done only by // parent panels failed to work (picks related code was in my profile panel) @@ -106,8 +107,10 @@ private: void onPanelPickSave(LLPanel* panel); void onPanelClassifiedSave(LLPanelClassifiedEdit* panel); void onPanelClassifiedClose(LLPanelClassifiedInfo* panel); + void openPickEdit(const LLSD& params); void onPanelPickEdit(); void onPanelClassifiedEdit(); + void editClassified(const LLUUID& classified_id); void onClickMenuEdit(); bool onEnableMenuItem(const LLSD& user_data); @@ -118,6 +121,7 @@ private: void openPickInfo(); void openClassifiedInfo(); void openClassifiedInfo(const LLSD& params); + void openClassifiedEdit(const LLSD& params); friend class LLPanelProfile; void showAccordion(const std::string& name, bool show); diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 8ae3553857..82ff6c3487 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -92,7 +92,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() : mZoomObjectID(LLUUID::null), mZoomObjectFace(0), mVolumeSliderVisible(0), - mWindowShade(NULL) + mWindowShade(NULL), + mHideImmediately(false) { mCommitCallbackRegistrar.add("MediaCtrl.Close", boost::bind(&LLPanelPrimMediaControls::onClickClose, this)); mCommitCallbackRegistrar.add("MediaCtrl.Back", boost::bind(&LLPanelPrimMediaControls::onClickBack, this)); @@ -207,6 +208,8 @@ BOOL LLPanelPrimMediaControls::postBuild() mMediaAddress->setFocusReceivedCallback(boost::bind(&LLPanelPrimMediaControls::onInputURL, _1, this )); + gAgent.setMouselookModeInCallback(boost::bind(&LLPanelPrimMediaControls::onMouselookModeIn, this)); + LLWindowShade::Params window_shade_params; window_shade_params.name = "window_shade"; @@ -722,26 +725,22 @@ void LLPanelPrimMediaControls::draw() } F32 alpha = getDrawContext().mAlpha; - if(mFadeTimer.getStarted()) + if(mHideImmediately) + { + //hide this panel + clearFaceOnFade(); + + mHideImmediately = false; + } + else if(mFadeTimer.getStarted()) { F32 time = mFadeTimer.getElapsedTimeF32(); alpha *= llmax(lerp(1.0, 0.0, time / mControlFadeTime), 0.0f); if(time >= mControlFadeTime) { - if(mClearFaceOnFade) - { - // Hiding this object makes scroll events go missing after it fades out - // (see DEV-41755 for a full description of the train wreck). - // Only hide the controls when we're untargeting. - setVisible(FALSE); - - mClearFaceOnFade = false; - mVolumeSliderVisible = 0; - mTargetImplID = LLUUID::null; - mTargetObjectID = LLUUID::null; - mTargetObjectFace = 0; - } + //hide this panel + clearFaceOnFade(); } } @@ -1319,6 +1318,30 @@ bool LLPanelPrimMediaControls::shouldVolumeSliderBeVisible() return mVolumeSliderVisible > 0; } + +void LLPanelPrimMediaControls::clearFaceOnFade() +{ + if(mClearFaceOnFade) + { + // Hiding this object makes scroll events go missing after it fades out + // (see DEV-41755 for a full description of the train wreck). + // Only hide the controls when we're untargeting. + setVisible(FALSE); + + mClearFaceOnFade = false; + mVolumeSliderVisible = 0; + mTargetImplID = LLUUID::null; + mTargetObjectID = LLUUID::null; + mTargetObjectFace = 0; + } +} + +void LLPanelPrimMediaControls::onMouselookModeIn() +{ + LLViewerMediaFocus::getInstance()->clearHover(); + mHideImmediately = true; +} + void LLPanelPrimMediaControls::showNotification(LLNotificationPtr notify) { delete mWindowShade; diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h index 0b9664359c..66956181f2 100644 --- a/indra/newview/llpanelprimmediacontrols.h +++ b/indra/newview/llpanelprimmediacontrols.h @@ -59,6 +59,7 @@ public: void showNotification(LLNotificationPtr notify); void hideNotification(); + enum EZoomLevel { ZOOM_NONE = 0, @@ -136,7 +137,11 @@ private: LLPluginClassMedia* getTargetMediaPlugin(); private: - + + void clearFaceOnFade(); + + void onMouselookModeIn(); + LLView *mMediaRegion; LLUICtrl *mBackCtrl; LLUICtrl *mFwdCtrl; @@ -185,6 +190,7 @@ private: bool mPauseFadeout; bool mUpdateSlider; bool mClearFaceOnFade; + bool mHideImmediately; LLMatrix4 mLastCameraMat; EZoomLevel mCurrentZoom; diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index b035d7d473..4f13c0c022 100644..100755 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -33,10 +33,41 @@ #include "llcommandhandler.h" #include "llpanelpicks.h" #include "lltabcontainer.h" +#include "llviewercontrol.h" static const std::string PANEL_PICKS = "panel_picks"; static const std::string PANEL_PROFILE = "panel_profile"; +std::string getProfileURL(const std::string& agent_name) +{ + std::string url = gSavedSettings.getString("WebProfileURL"); + LLSD subs; + subs["AGENT_NAME"] = agent_name; + url = LLWeb::expandURLSubstitutions(url,subs); + LLStringUtil::toLower(url); + return url; +} + +class LLProfileHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLProfileHandler() : LLCommandHandler("profile", UNTRUSTED_THROTTLE) { } + + bool handle(const LLSD& params, const LLSD& query_map, + LLMediaCtrl* web) + { + if (params.size() < 1) return false; + std::string agent_name = params[0]; + llinfos << "Profile, agent_name " << agent_name << llendl; + std::string url = getProfileURL(agent_name); + LLWeb::loadWebURLInternal(url); + + return true; + } +}; +LLProfileHandler gProfileHandler; + class LLAgentHandler : public LLCommandHandler { public: @@ -281,6 +312,36 @@ void LLPanelProfile::onOpen(const LLSD& key) picks->openClassifiedInfo(params); } } + else if (panel == "edit_classified") + { + LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); + if (picks) + { + LLSD params = key; + params.erase("show_tab_panel"); + params.erase("open_tab_name"); + picks->openClassifiedEdit(params); + } + } + else if (panel == "create_pick") + { + LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); + if (picks) + { + picks->createNewPick(); + } + } + else if (panel == "edit_pick") + { + LLPanelPicks* picks = dynamic_cast<LLPanelPicks *>(getTabContainer()[PANEL_PICKS]); + if (picks) + { + LLSD params = key; + params.erase("show_tab_panel"); + params.erase("open_tab_name"); + picks->openPickEdit(params); + } + } } } diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h index 0a572e6f25..fca359f51e 100644..100755 --- a/indra/newview/llpanelprofile.h +++ b/indra/newview/llpanelprofile.h @@ -32,6 +32,8 @@ class LLTabContainer; +std::string getProfileURL(const std::string& agent_name); + /** * Base class for Profile View and My Profile. */ diff --git a/indra/newview/llshareavatarhandler.cpp b/indra/newview/llshareavatarhandler.cpp new file mode 100644 index 0000000000..34194970b8 --- /dev/null +++ b/indra/newview/llshareavatarhandler.cpp @@ -0,0 +1,59 @@ +/** + * @file llshareavatarhandler.cpp + * @brief slapp to handle sharing with an avatar + * + * $LicenseInfo:firstyear=2001&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 "llcommandhandler.h" +#include "llavataractions.h" + +class LLShareWithAvatarHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLShareWithAvatarHandler() : LLCommandHandler("sharewithavatar", UNTRUSTED_THROTTLE) + { + } + + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + { + //Make sure we have some parameters + if (params.size() == 0) + { + return false; + } + + //Get the ID + LLUUID id; + if (!id.set( params[0], FALSE )) + { + return false; + } + + //instigate share with this avatar + LLAvatarActions::share( id ); + return true; + } +}; +LLShareWithAvatarHandler gShareWithAvatar; diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp index 47d904dfcc..8774482acd 100644 --- a/indra/newview/llsidepaneltaskinfo.cpp +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -1120,17 +1120,17 @@ void LLSidepanelTaskInfo::updateVerbs() */ LLSafeHandle<LLObjectSelection> object_selection = LLSelectMgr::getInstance()->getSelection(); - const BOOL multi_select = (object_selection->getNumNodes() > 1); + const BOOL any_selected = (object_selection->getNumNodes() > 0); - mOpenBtn->setVisible(!multi_select); - mPayBtn->setVisible(!multi_select); - mBuyBtn->setVisible(!multi_select); - mDetailsBtn->setVisible(multi_select); - mDetailsBtn->setEnabled(multi_select); + mOpenBtn->setVisible(true); + mPayBtn->setVisible(true); + mBuyBtn->setVisible(true); + mDetailsBtn->setVisible(true); mOpenBtn->setEnabled(enable_object_open()); mPayBtn->setEnabled(enable_pay_object()); mBuyBtn->setEnabled(enable_buy_object()); + mDetailsBtn->setEnabled(any_selected); } void LLSidepanelTaskInfo::onOpenButtonClicked() diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 7dbaa4cf92..b3642a2c1e 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -48,6 +48,7 @@ #include "llinventorybridge.h" #include "llinventorypanel.h" #include "llfloaterinventory.h" +#include "lllandmarkactions.h" #include "llviewerassettype.h" #include "llviewerregion.h" @@ -59,6 +60,9 @@ #include "llcommandhandler.h" #include "llviewermessage.h" #include "llsidepanelappearance.h" +#include "llavatarnamecache.h" +#include "llavataractions.h" +#include "lllogininstance.h" ///---------------------------------------------------------------------------- /// Helper class to store special inventory item names and their localized values. @@ -211,6 +215,7 @@ public: }; LLInventoryHandler gInventoryHandler; + ///---------------------------------------------------------------------------- /// Class LLViewerInventoryItem ///---------------------------------------------------------------------------- @@ -1414,6 +1419,8 @@ public: S32 getSortIndex(const LLUUID& inv_item_id); void removeSortIndex(const LLUUID& inv_item_id); + void getSLURL(const LLUUID& asset_id); + /** * Implementation of LLDestroyClass. Calls cleanup() instance method. * @@ -1440,9 +1447,17 @@ private: void load(); void save(); + void saveFavoritesSLURLs(); + + void onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark); + void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl); + typedef std::map<LLUUID, S32> sort_index_map_t; sort_index_map_t mSortIndexes; + typedef std::map<LLUUID, std::string> slurls_map_t; + slurls_map_t mSLURLs; + bool mIsDirty; struct IsNotInFavorites @@ -1497,10 +1512,27 @@ void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id) mIsDirty = true; } +void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id) +{ + slurls_map_t::iterator slurl_iter = mSLURLs.find(asset_id); + if (slurl_iter != mSLURLs.end()) return; // SLURL for current landmark is already cached + + LLLandmark* lm = gLandmarkList.getAsset(asset_id, + boost::bind(&LLFavoritesOrderStorage::onLandmarkLoaded, this, asset_id, _1)); + if (lm) + { + onLandmarkLoaded(asset_id, lm); + } +} + // static void LLFavoritesOrderStorage::destroyClass() { LLFavoritesOrderStorage::instance().cleanup(); + if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin")) + { + LLFavoritesOrderStorage::instance().saveFavoritesSLURLs(); + } } void LLFavoritesOrderStorage::load() @@ -1523,6 +1555,76 @@ void LLFavoritesOrderStorage::load() } } +void LLFavoritesOrderStorage::saveFavoritesSLURLs() +{ + // Do not change the file if we are not logged in yet. + if (!LLLoginInstance::getInstance()->authSuccess()) return; + + std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); + if (user_dir.empty()) return; + + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); + llifstream in_file; + in_file.open(filename); + LLSD fav_llsd; + if (in_file.is_open()) + { + LLSDSerialize::fromXML(fav_llsd, in_file); + } + + const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); + + LLSD user_llsd; + for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++) + { + LLSD value; + value["name"] = (*it)->getName(); + value["asset_id"] = (*it)->getAssetUUID(); + + slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]); + if (slurl_iter != mSLURLs.end()) + { + value["slurl"] = slurl_iter->second; + user_llsd[(*it)->getSortField()] = value; + } + } + + LLAvatarName av_name; + LLAvatarNameCache::get( gAgentID, &av_name ); + fav_llsd[av_name.getLegacyName()] = user_llsd; + + llofstream file; + file.open(filename); + LLSDSerialize::toPrettyXML(fav_llsd, file); +} + +void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmark* landmark) +{ + if (!landmark) return; + + LLVector3d pos_global; + if (!landmark->getGlobalPos(pos_global)) + { + // If global position was unknown on first getGlobalPos() call + // it should be set for the subsequent calls. + landmark->getGlobalPos(pos_global); + } + + if (!pos_global.isExactlyZero()) + { + LLLandmarkActions::getSLURLfromPosGlobal(pos_global, + boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1)); + } +} + +void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl) +{ + mSLURLs[asset_id] = slurl; +} + void LLFavoritesOrderStorage::save() { // nothing to save if clean @@ -1579,6 +1681,12 @@ S32 LLViewerInventoryItem::getSortField() const void LLViewerInventoryItem::setSortField(S32 sortField) { LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField); + getSLURL(); +} + +void LLViewerInventoryItem::getSLURL() +{ + LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID); } const LLPermissions& LLViewerInventoryItem::getPermissions() const diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 1af06a1be8..41542a4e0f 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -62,6 +62,7 @@ public: virtual const std::string& getName() const; virtual S32 getSortField() const; virtual void setSortField(S32 sortField); + virtual void getSLURL(); //Caches SLURL for landmark. //*TODO: Find a better way to do it and remove this method from here. virtual const LLPermissions& getPermissions() const; virtual const bool getIsFullPerm() const; // 'fullperm' in the popular sense: modify-ok & copy-ok & transfer-ok, no special god rules applied virtual const LLUUID& getCreatorUUID() const; diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 9e16bf2fbb..60b118284b 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -557,7 +557,7 @@ class LLAdvancedCheckConsole : public view_listener_t new_value = get_visibility( (void*)gDebugView->mMemoryView ); } #endif - + return new_value; } }; @@ -4197,9 +4197,9 @@ class LLObjectEnableReturn : public view_listener_t { virtual bool apply(LLViewerObject* obj) { - return (obj->isOverAgentOwnedLand() || - obj->isOverGroupOwnedLand() || - obj->permModify()); + return + obj->permModify() || + obj->isReturnable(); } } func; const bool firstonly = true; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 1804fac1b3..18d6e4c8c8 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -516,20 +516,23 @@ void LLViewerObject::setNameValueList(const std::string& name_value_list) // This method returns true if the object is over land owned by the // agent. -BOOL LLViewerObject::isOverAgentOwnedLand() const +bool LLViewerObject::isReturnable() { - return mRegionp - && mRegionp->getParcelOverlay() - && mRegionp->getParcelOverlay()->isOwnedSelf(getPositionRegion()); -} + if (isAttachment()) + { + return false; + } + std::vector<LLBBox> boxes; + boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned()); + for (child_list_t::iterator iter = mChildList.begin(); + iter != mChildList.end(); iter++) + { + LLViewerObject* child = *iter; + boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned()); + } -// This method returns true if the object is over land owned by the -// agent. -BOOL LLViewerObject::isOverGroupOwnedLand() const -{ - return mRegionp - && mRegionp->getParcelOverlay() - && mRegionp->getParcelOverlay()->isOwnedGroup(getPositionRegion()); + return mRegionp + && mRegionp->objectIsReturnable(getPositionRegion(), boxes); } BOOL LLViewerObject::setParent(LLViewerObject* parent) diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index fe670f8827..5c1a34d555 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -226,12 +226,9 @@ public: virtual BOOL hasLightTexture() const { return FALSE; } // This method returns true if the object is over land owned by - // the agent. - BOOL isOverAgentOwnedLand() const; - - // True if over land owned by group of which the agent is - // either officer or member. - BOOL isOverGroupOwnedLand() const; + // the agent, one of its groups, or it encroaches and + // anti-encroachment is enabled + bool isReturnable(); /* // This method will scan through this object, and then query the diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index eee653b0c1..d07e06f6a7 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -145,6 +145,35 @@ BOOL LLViewerParcelOverlay::isOwnedOther(const LLVector3& pos) const return (PARCEL_OWNED == overlay || PARCEL_FOR_SALE == overlay); } +bool LLViewerParcelOverlay::encroachesOwned(const std::vector<LLBBox>& boxes) const +{ + // boxes are expected to already be axis aligned + for (U32 i = 0; i < boxes.size(); ++i) + { + LLVector3 min = boxes[i].getMinAgent(); + LLVector3 max = boxes[i].getMaxAgent(); + + S32 left = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 right = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 top = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + + for (S32 row = top; row <= bottom; row++) + { + for (S32 column = left; column <= right; column++) + { + U8 type = ownership(row, column); + if ((PARCEL_SELF == type) + || (PARCEL_GROUP == type)) + { + return true; + } + } + } + } + return false; +} + BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const { S32 row = S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS); diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index 61be220312..c80baedda6 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -30,6 +30,7 @@ // The ownership data for land parcels. // One of these structures per region. +#include "llbbox.h" #include "lldarray.h" #include "llframetimer.h" #include "lluuid.h" @@ -54,6 +55,12 @@ public: BOOL isOwnedSelf(const LLVector3& pos) const; BOOL isOwnedGroup(const LLVector3& pos) const; BOOL isOwnedOther(const LLVector3& pos) const; + + // "encroaches" means the prim hangs over the parcel, but its center + // might be in another parcel. for now, we simply test axis aligned + // bounding boxes which isn't perfect, but is close + bool encroachesOwned(const std::vector<LLBBox>& boxes) const; + BOOL isSoundLocal(const LLVector3& pos) const; BOOL isBuildCameraAllowed(const LLVector3& pos) const; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 551ba18dd5..2a67d12b64 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1400,7 +1400,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("SendUserReportWithScreenshot"); capabilityNames.append("ServerReleaseNotes"); capabilityNames.append("SetDisplayName"); - capabilityNames.append("SimConsole"); capabilityNames.append("SimConsoleAsync"); capabilityNames.append("StartGroupProposal"); capabilityNames.append("TextureStats"); @@ -1497,6 +1496,20 @@ LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type) return NULL; } +// the viewer can not yet distinquish between normal- and estate-owned objects +// so we collapse these two bits and enable the UI if either are set +const U32 ALLOW_RETURN_ENCROACHING_OBJECT = REGION_FLAGS_ALLOW_RETURN_ENCROACHING_OBJECT + | REGION_FLAGS_ALLOW_RETURN_ENCROACHING_ESTATE_OBJECT; + +bool LLViewerRegion::objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const +{ + return (mParcelOverlay != NULL) + && (mParcelOverlay->isOwnedSelf(pos) + || mParcelOverlay->isOwnedGroup(pos) + || ((mRegionFlags & ALLOW_RETURN_ENCROACHING_OBJECT) + && mParcelOverlay->encroachesOwned(boxes)) ); +} + void LLViewerRegion::showReleaseNotes() { std::string url = this->getCapability("ServerReleaseNotes"); diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 8b71998f60..3d3f1d62a6 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -33,6 +33,7 @@ #include "lldarray.h" #include "llwind.h" +#include "llbbox.h" #include "llcloud.h" #include "llstat.h" #include "v3dmath.h" @@ -293,6 +294,8 @@ public: std::string getHttpUrl() const { return mHttpUrl ;} LLSpatialPartition* getSpatialPartition(U32 type); + + bool objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const; public: struct CompareDistance { diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index bb4c5b1804..fd89044995 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -2106,31 +2106,6 @@ void LLVOAvatar::computeBodySize() gAgent.sendAgentSetAppearance(); } } - -/* debug spam - std::cout << "skull = " << skull << std::endl; // adebug - std::cout << "head = " << head << std::endl; // adebug - std::cout << "head_scale = " << head_scale << std::endl; // adebug - std::cout << "neck = " << neck << std::endl; // adebug - std::cout << "neck_scale = " << neck_scale << std::endl; // adebug - std::cout << "chest = " << chest << std::endl; // adebug - std::cout << "chest_scale = " << chest_scale << std::endl; // adebug - std::cout << "torso = " << torso << std::endl; // adebug - std::cout << "torso_scale = " << torso_scale << std::endl; // adebug - std::cout << std::endl; // adebug - - std::cout << "pelvis_scale = " << pelvis_scale << std::endl;// adebug - std::cout << std::endl; // adebug - - std::cout << "hip = " << hip << std::endl; // adebug - std::cout << "hip_scale = " << hip_scale << std::endl; // adebug - std::cout << "ankle = " << ankle << std::endl; // adebug - std::cout << "ankle_scale = " << ankle_scale << std::endl; // adebug - std::cout << "foot = " << foot << std::endl; // adebug - std::cout << "mBodySize = " << mBodySize << std::endl; // adebug - std::cout << "mPelvisToFoot = " << mPelvisToFoot << std::endl; // adebug - std::cout << std::endl; // adebug -*/ } //------------------------------------------------------------------------ diff --git a/indra/newview/llvoicecallhandler.cpp b/indra/newview/llvoicecallhandler.cpp new file mode 100644 index 0000000000..274bd75208 --- /dev/null +++ b/indra/newview/llvoicecallhandler.cpp @@ -0,0 +1,61 @@ + /** + * @file llvoicecallhandler.cpp + * @brief slapp to handle avatar to avatar voice call. + * + * $LicenseInfo:firstyear=2001&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 "llcommandhandler.h" +#include "llavataractions.h" + +class LLVoiceCallAvatarHandler : public LLCommandHandler +{ +public: + // requires trusted browser to trigger + LLVoiceCallAvatarHandler() : LLCommandHandler("voicecallavatar", UNTRUSTED_THROTTLE) + { + } + + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) + { + //Make sure we have some parameters + if (params.size() == 0) + { + return false; + } + + //Get the ID + LLUUID id; + if (!id.set( params[0], FALSE )) + { + return false; + } + + //instigate call with this avatar + LLAvatarActions::startCall( id ); + return true; + } +}; + +LLVoiceCallAvatarHandler gVoiceCallAvatarHandler; + diff --git a/indra/newview/skins/default/textures/icons/Web_Profile_Off.png b/indra/newview/skins/default/textures/icons/Web_Profile_Off.png Binary files differnew file mode 100644 index 0000000000..f5fb774a6f --- /dev/null +++ b/indra/newview/skins/default/textures/icons/Web_Profile_Off.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 89611d8899..2c00120177 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -553,11 +553,11 @@ with the same filename but different name <texture name="Wearables_Divider" file_name="windows/Wearables_Divider.png" preload="false" /> + <texture name="Web_Profile_Off" file_name="icons/Web_Profile_Off.png" preload="false" /> + <texture name="WellButton_Lit" file_name="bottomtray/WellButton_Lit.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" /> <texture name="WellButton_Lit_Selected" file_name="bottomtray/WellButton_Lit_Selected.png" preload="true" scale.left="4" scale.top="19" scale.right="28" scale.bottom="4" /> - - <texture name="Window_Background" file_name="windows/Window_Background.png" preload="true" scale.left="4" scale.top="24" scale.right="26" scale.bottom="4" /> <texture name="Window_Foreground" file_name="windows/Window_Foreground.png" preload="true" diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml index 2ad46824c2..d90d0feda9 100644 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -1,190 +1,190 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater
- legacy_header_height="18"
- can_resize="true"
- height="440"
- layout="topleft"
- min_height="140"
- min_width="467"
- name="floater_web_content"
- help_topic="floater_web_content"
- save_rect="true"
- auto_tile="true"
- title=""
- initial_mime_type="text/html"
- width="820">
- <layout_stack
- bottom="440"
- follows="left|right|top|bottom"
- layout="topleft"
- left="5"
- name="stack1"
- orientation="vertical"
- top="20"
- width="810">
- <layout_panel
- auto_resize="false"
- default_tab_group="1"
- height="22"
- layout="topleft"
- left="0"
- min_height="20"
- name="nav_controls"
- top="400"
- user_resize="false"
- width="800">
- <button
- image_overlay="Arrow_Left_Off"
- image_disabled="PushButton_Disabled"
- image_disabled_selected="PushButton_Disabled"
- image_selected="PushButton_Selected"
- image_unselected="PushButton_Off"
- hover_glow_amount="0.15"
- tool_tip="Navigate back"
- follows="left|top"
- height="22"
- layout="topleft"
- left="1"
- name="back"
- top="0"
- width="22">
- <button.commit_callback
- function="WebContent.Back" />
- </button>
- <button
- image_overlay="Arrow_Right_Off"
- image_disabled="PushButton_Disabled"
- image_disabled_selected="PushButton_Disabled"
- image_selected="PushButton_Selected"
- image_unselected="PushButton_Off"
- tool_tip="Navigate forward"
- follows="left|top"
- height="22"
- layout="topleft"
- left="27"
- name="forward"
- top_delta="0"
- width="22">
- <button.commit_callback
- function="WebContent.Forward" />
- </button>
- <button
- image_overlay="Stop_Off"
- image_disabled="PushButton_Disabled"
- image_disabled_selected="PushButton_Disabled"
- image_selected="PushButton_Selected"
- image_unselected="PushButton_Off"
- tool_tip="Stop navigation"
- enabled="true"
- follows="left|top"
- height="22"
- layout="topleft"
- left="51"
- name="stop"
- top_delta="0"
- width="22">
- <button.commit_callback
- function="WebContent.Stop" />
- </button>
- <button
- image_overlay="Refresh_Off"
- image_disabled="PushButton_Disabled"
- image_disabled_selected="PushButton_Disabled"
- image_selected="PushButton_Selected"
- image_unselected="PushButton_Off"
- tool_tip="Reload page"
- follows="left|top"
- height="22"
- layout="topleft"
- left="51"
- name="reload"
- top_delta="0"
- width="22">
- <button.commit_callback
- function="WebContent.Reload" />
- </button>
- <combo_box
- allow_text_entry="true"
- follows="left|top|right"
- tab_group="1"
- height="22"
- layout="topleft"
- left_pad="4"
- max_chars="1024"
- name="address"
- combo_editor.select_on_focus="true"
- tool_tip="Enter URL here"
- top_delta="0"
- width="702">
- <combo_box.commit_callback
- function="WebContent.EnterAddress" />
- </combo_box>
- <icon
- name="media_secure_lock_flag"
- height="16"
- follows="top|right"
- image_name="Lock2"
- layout="topleft"
- left_delta="656"
- top_delta="2"
- visible="false"
- tool_tip="Secured Browsing"
- width="16" />
- <button
- image_overlay="ExternalBrowser_Off"
- image_disabled="PushButton_Disabled"
- image_disabled_selected="PushButton_Disabled"
- image_selected="PushButton_Selected"
- image_unselected="PushButton_Off"
- tool_tip="Open current URL in your desktop browser"
- follows="right|top"
- enabled="true"
- height="22"
- layout="topleft"
- name="popexternal"
- right="800"
- top_delta="-2"
- width="22">
- <button.commit_callback
- function="WebContent.PopExternal" />
- </button>
- </layout_panel>
- <layout_panel
- height="40"
- layout="topleft"
- left_delta="0"
- name="external_controls"
- top_delta="0"
- user_resize="false"
- width="540">
- <web_browser
- bottom="-22"
- follows="all"
- layout="topleft"
- left="0"
- name="webbrowser"
- top="0"/>
- <text
- type="string"
- length="100"
- follows="bottom|left"
- height="20"
- layout="topleft"
- left_delta="0"
- name="statusbartext"
- parse_urls="false"
- text_color="0.4 0.4 0.4 1"
- top_pad="5"
- width="452"/>
- <progress_bar
- color_bar="0.3 1.0 0.3 1"
- follows="bottom|right"
- height="16"
- top_delta="-1"
- left_pad="24"
- layout="topleft"
- name="statusbarprogress"
- width="64"/>
- </layout_panel>
- </layout_stack>
-</floater>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + can_resize="true" + height="440" + layout="topleft" + min_height="140" + min_width="467" + name="floater_web_content" + help_topic="floater_web_content" + save_rect="true" + auto_tile="true" + title="" + initial_mime_type="text/html" + width="820"> + <layout_stack + bottom="440" + follows="left|right|top|bottom" + layout="topleft" + left="5" + name="stack1" + orientation="vertical" + top="20" + width="810"> + <layout_panel + auto_resize="false" + default_tab_group="1" + height="22" + layout="topleft" + left="0" + min_height="20" + name="nav_controls" + top="400" + user_resize="false" + width="800"> + <button + image_overlay="Arrow_Left_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + hover_glow_amount="0.15" + tool_tip="Navigate back" + follows="left|top" + height="22" + layout="topleft" + left="1" + name="back" + top="0" + width="22"> + <button.commit_callback + function="WebContent.Back" /> + </button> + <button + image_overlay="Arrow_Right_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + tool_tip="Navigate forward" + follows="left|top" + height="22" + layout="topleft" + left="27" + name="forward" + top_delta="0" + width="22"> + <button.commit_callback + function="WebContent.Forward" /> + </button> + <button + image_overlay="Stop_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + tool_tip="Stop navigation" + enabled="true" + follows="left|top" + height="22" + layout="topleft" + left="51" + name="stop" + top_delta="0" + width="22"> + <button.commit_callback + function="WebContent.Stop" /> + </button> + <button + image_overlay="Refresh_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + tool_tip="Reload page" + follows="left|top" + height="22" + layout="topleft" + left="51" + name="reload" + top_delta="0" + width="22"> + <button.commit_callback + function="WebContent.Reload" /> + </button> + <combo_box + allow_text_entry="true" + follows="left|top|right" + tab_group="1" + height="22" + layout="topleft" + left_pad="4" + max_chars="1024" + name="address" + combo_editor.select_on_focus="true" + tool_tip="Enter URL here" + top_delta="0" + width="702"> + <combo_box.commit_callback + function="WebContent.EnterAddress" /> + </combo_box> + <icon + name="media_secure_lock_flag" + height="16" + follows="top|right" + image_name="Lock2" + layout="topleft" + left_delta="656" + top_delta="2" + visible="false" + tool_tip="Secured Browsing" + width="16" /> + <button + image_overlay="ExternalBrowser_Off" + image_disabled="PushButton_Disabled" + image_disabled_selected="PushButton_Disabled" + image_selected="PushButton_Selected" + image_unselected="PushButton_Off" + tool_tip="Open current URL in your desktop browser" + follows="right|top" + enabled="true" + height="22" + layout="topleft" + name="popexternal" + right="800" + top_delta="-2" + width="22"> + <button.commit_callback + function="WebContent.PopExternal" /> + </button> + </layout_panel> + <layout_panel + height="40" + layout="topleft" + left_delta="0" + name="external_controls" + top_delta="0" + user_resize="false" + width="540"> + <web_browser + bottom="-22" + follows="all" + layout="topleft" + left="0" + name="webbrowser" + top="0"/> + <text + type="string" + length="100" + follows="bottom|left" + height="20" + layout="topleft" + left_delta="0" + name="statusbartext" + parse_urls="false" + text_color="0.4 0.4 0.4 1" + top_pad="5" + width="452"/> + <progress_bar + color_bar="0.3 1.0 0.3 1" + follows="bottom|right" + height="16" + top_delta="-1" + left_pad="24" + layout="topleft" + name="statusbarprogress" + width="64"/> + </layout_panel> + </layout_stack> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index d997a262a8..3d500c2371 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -2717,6 +2717,18 @@ function="Floater.Toggle" parameter="region_debug_console" /> </menu_item_check> + <menu_item_check + label="Region Debug Console" + name="Region Debug Console" + shortcut="control|shift|`" + use_mac_ctrl="true"> + <menu_item_check.on_check + function="Floater.Visible" + parameter="region_debug_console" /> + <menu_item_check.on_click + function="Floater.Toggle" + parameter="region_debug_console" /> + </menu_item_check> <menu_item_separator /> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 63c030b068..3df53ac442 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -253,6 +253,16 @@ Save all changes to clothing/body parts? <notification icon="alertmodal.tga" + name="FavoritesOnLogin" + type="alertmodal"> + Note: When you turn on this option, anyone who uses this computer can see your list of favorite locations. + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" name="GrantModifyRights" type="alertmodal"> Granting modify rights to another Resident allows them to change, delete or take ANY objects you may have in-world. Be VERY careful when handing out this permission. diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml index 4b21ffa1f9..e40dc430fc 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml @@ -134,7 +134,7 @@ <button follows="right" height="20" - image_overlay="ForwardArrow_Off" + image_overlay="Web_Profile_Off" layout="topleft" left_pad="5" right="-28" diff --git a/indra/newview/skins/default/xui/en/panel_edit_profile.xml b/indra/newview/skins/default/xui/en/panel_edit_profile.xml index 90dbddaff7..37265d65f1 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml @@ -328,17 +328,6 @@ name="homepage_edit" width="272"> </line_editor> - <check_box - follows="left|top" - font="SansSerifSmall" - label="Show me in Search results" - layout="topleft" - left="8" - name="show_in_search_checkbox" - height="15" - label_text.text_color="white" - top_pad="12" - width="100" /> <text follows="left|top" font="SansSerifSmall" diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item.xml b/indra/newview/skins/default/xui/en/panel_group_list_item.xml index 7d0b0890f0..12735026fa 100644 --- a/indra/newview/skins/default/xui/en/panel_group_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_group_list_item.xml @@ -63,7 +63,7 @@ <button follows="right" height="20" - image_overlay="ForwardArrow_Off" + image_overlay="Web_Profile_Off" layout="topleft" left_pad="5" right="-3" diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index 257ed799da..806182bcb4 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -61,23 +61,28 @@ left="20" width="150"> Username: </text> -<line_editor +<combo_box +allow_text_entry="true" follows="left|bottom" height="22" -label="bobsmith12 or Steller Sunshine" left_delta="0" -max_length_bytes="63" -name="username_edit" -prevalidate_callback="ascii" +max_chars="128" +prevalidate_callback="ascii" select_on_focus="true" tool_tip="The username you chose when you registered, like bobsmith12 or Steller Sunshine" top_pad="0" -width="150" /> +name="username_combo" +width="178"> + <combo_box.combo_button + visible ="false"/> + <combo_box.drop_down_button + visible ="false"/> +</combo_box> <text follows="left|bottom" font="SansSerifSmall" height="15" -left_pad="8" +left_pad="-19" name="password_text" top="20" width="150"> diff --git a/indra/newview/skins/default/xui/en/panel_my_profile.xml b/indra/newview/skins/default/xui/en/panel_my_profile.xml index 5b8abaca6f..4bd2235cda 100644 --- a/indra/newview/skins/default/xui/en/panel_my_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_my_profile.xml @@ -31,10 +31,18 @@ name="no_group_text" value="None" /> <string - name="RegisterDateFormat"> - [REG_DATE] ([AGE]) - </string> - <layout_stack + name="RegisterDateFormat"> + [REG_DATE] ([AGE]) + </string> + <string + name="name_text_args"> + [NAME] + </string> + <string + name="display_name_text_args"> + [DISPLAY_NAME] + </string> + <layout_stack name="layout" orientation="vertical" follows="all" @@ -79,11 +87,12 @@ name="second_life_image_panel" top="0" width="297"> + <texture_picker allow_no_texture="true" default_image_name="None" enabled="false" - fallback_image="Generic_Person_Large" + fallback_image="Generic_Person_Large" follows="top|left" height="124" layout="topleft" @@ -91,258 +100,47 @@ name="2nd_life_pic" top="10" width="102" /> - <icon - height="102" - image_name="Blank" - layout="topleft" - name="2nd_life_edit_icon" - label="" - left="3" - tool_tip="Click the Edit Profile button below to change image" - top="10" - width="102" /> - <text - follows="left|top|right" - font.style="BOLD" - height="15" - layout="topleft" - left_pad="10" - name="title_sl_descr_text" - text_color="white" - top_delta="0" - value="[SECOND_LIFE]:" - width="180" /> - <expandable_text - follows="left|top|right" - height="95" - layout="topleft" - left="107" - textbox.max_length="512" - textbox.show_context_menu="true" - name="sl_description_edit" - top_pad="-3" - translate="false" - width="181" - expanded_bg_visible="true" - expanded_bg_color="DkGray"> - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. - </expandable_text> - </panel> - <panel - follows="left|top|right" - height="117" - layout="topleft" - top_pad="0" - left="10" - name="first_life_image_panel" - width="297"> - <texture_picker - allow_no_texture="true" - default_image_name="None" - enabled="false" - fallback_image="Generic_Person_Large" - follows="top|left" - height="124" - layout="topleft" - left="3" - name="real_world_pic" - width="102" /> - <icon - height="102" - image_name="Blank" - layout="topleft" - name="real_world_edit_icon" - label="" - left="3" - tool_tip="Click the Edit Profile button below to change image" - top="4" - width="102" /> + <text - follows="left|top|right" - font.style="BOLD" - height="15" - layout="topleft" - left_pad="10" - name="title_rw_descr_text" - text_color="white" - top_delta="0" - value="Real World:" - width="180" /> - <expandable_text - follows="left|top|right" - height="95" - layout="topleft" - left="107" - textbox.max_length="512" - textbox.show_context_menu="true" - name="fl_description_edit" - top_pad="-3" - translate="false" - width="181" - expanded_bg_visible="true" - expanded_bg_color="DkGray"> - Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. - </expandable_text> - </panel> - <text - follows="left|top|right" - height="15" - font.style="BOLD" - font="SansSerifMedium" - layout="topleft" - left="10" - name="homepage_edit" - top_pad="0" - translate="false" - value="http://librarianavengers.org" - width="300" - word_wrap="false" - use_ellipses="true" - /> - <text - follows="left|top|right" - font.style="BOLD" - height="10" - layout="topleft" - left="10" - name="title_member_text" - text_color="white" - top_pad="10" - value="Resident Since:" - width="300" /> - <text_editor - allow_scroll="false" - bg_visible="false" - follows="left|top|right" - h_pad="0" - height="15" - layout="topleft" - left="10" - name="register_date" - read_only="true" - translate="false" - v_pad="0" - value="05/31/2376" - width="300" - word_wrap="true" /> - <text - follows="left|top|right" - font.style="BOLD" - height="15" - layout="topleft" - left="10" - name="title_acc_status_text" - text_color="white" - top_pad="5" - value="Account Status:" - width="300" /> - <!-- <text - type="string" - follows="left|top" - font="SansSerifSmall" - height="15" - layout="topleft" - left_pad="10" - name="my_account_link" - top_delta="0" - value="Go to Dashboard" - width="100"/> --> - <text_editor - allow_scroll="false" - bg_visible="false" - follows="left|top|right" - h_pad="0" - height="28" - layout="topleft" - left="10" - name="acc_status_text" - read_only="true" - top_pad="0" - translate="false" - v_pad="0" - width="300" - word_wrap="true"> - Resident. No payment info on file. - Linden. - </text_editor> - <text - follows="left|top|right" - font.style="BOLD" - height="15" - layout="topleft" - left="10" - name="title_partner_text" - text_color="white" - top_pad="3" - value="Partner:" - width="300" /> - <panel - follows="left|top|right" - height="15" - layout="topleft" - left="10" - name="partner_data_panel" - top_pad="0" - width="300"> + follows="left|top|right" + font="SansSerifLarge" + font.style="BOLD" + height="15" + layout="topleft" + left_pad="10" + name="display_name_descr_text" + text_color="0.7 0.7 0.7 1.0" + top_delta="0" + width="280" > + User name + </text> + <text - follows="left|top|right" - height="10" - initial_value="(retrieving)" - layout="topleft" - left="0" - link="true" - name="partner_text" - top="0" - use_ellipses="true" - width="300" /> + follows="left|top|right" + font.style="BOLD" + height="15" + layout="topleft" + left_delta="0" + name="name_descr_text" + text_color="0.4 0.4 0.4 1.0" + top_delta="20" + width="280"> + Display Name + </text> + + <button + follows="bottom" + height="23" + left_delta="0" + top_delta="20" + label="Profile" + name="see_profile_btn" + tool_tip="See profile for this avatar" + width="120" /> + </panel> - <text - follows="left|top|right" - font.style="BOLD" - height="13" - layout="topleft" - left="10" - name="title_groups_text" - text_color="white" - top_pad="3" - value="Groups:" - width="300" /> - <expandable_text - follows="all" - height="113" - layout="topleft" - left="7" - name="sl_groups" - top_pad="0" - translate="false" - textbox.show_context_menu="true" - width="298" - expanded_bg_visible="true" - expanded_bg_color="DkGray"> - Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. Aenean viverra tulip moosetop. Slan de heelish marfnik tooplod. Sum sum to whop de wompam booster copm. - </expandable_text> </panel> </scroll_container> </layout_panel> </layout_stack> - <panel - follows="bottom|left|right" - height="23" - layout="topleft" - left="0" - top_pad="1" - name="profile_me_buttons_panel" - visible="false" - width="315"> - <button - follows="bottom" - height="23" - left="6" - top="1" - label="Edit Profile" - name="edit_profile_btn" - tool_tip="Edit your personal information" - width="152" /> - </panel> - </panel> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index 626122c0b0..ef25588ca3 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -42,6 +42,15 @@ </text> <check_box height="16" + enabled="true" + label="Show me in Search results" + layout="topleft" + left="30" + name="online_searchresults" + top_pad="20" + width="350" /> + <check_box + height="16" enabled="false" label="Only friends and groups know I'm online" layout="topleft" @@ -69,6 +78,16 @@ name="auto_disengage_mic_check" top_pad="10" width="350" /> + <check_box + control_name="ShowFavoritesOnLogin" + enabled="false" + height="16" + label="Show my Favorite Landmarks at Login (via 'Start At' drop-down menu)" + layout="topleft" + left="30" + name="favorites_on_login_check" + top_pad="10" + width="350" /> <text type="string" length="1" @@ -78,7 +97,7 @@ left="30" mouse_opaque="false" name="Logs:" - top_pad="30" + top_pad="20" width="350"> Chat Logs: </text> @@ -170,7 +189,7 @@ layout="topleft" left="30" name="block_list" - top_pad="35" + top_pad="28" width="145"> <!--<button.commit_callback function="SideTray.ShowPanel"--> diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml index afaf41d073..e2b3d81bf6 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml @@ -533,7 +533,7 @@ left="5" name="open_btn" top="0" - width="100" /> + width="73" /> <button follows="bottom|left" height="23" @@ -542,7 +542,7 @@ left_pad="5" name="pay_btn" top="0" - width="100" /> + width="73" /> <button follows="bottom|left" height="23" @@ -551,17 +551,16 @@ left_pad="5" name="buy_btn" top="0" - width="100" /> + width="73" /> <button follows="bottom|left" height="23" label="Details" layout="topleft" - left="5" + left_pad="5" name="details_btn" top="0" - width="100" - visible="false" /> + width="74" /> </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml index 85d0c633af..2e5ebafe46 100644 --- a/indra/newview/skins/default/xui/en/widgets/floater.xml +++ b/indra/newview/skins/default/xui/en/widgets/floater.xml @@ -21,4 +21,5 @@ tear_off_pressed_image="tearoff_pressed.tga" dock_pressed_image="Icon_Dock_Press" help_pressed_image="Icon_Help_Press" + focus_root="true" /> diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp index a6c1f69c82..dae22521bb 100644 --- a/indra/newview/tests/llremoteparcelrequest_test.cpp +++ b/indra/newview/tests/llremoteparcelrequest_test.cpp @@ -1,134 +1,134 @@ -/**
- * @file llremoteparcelrequest_test.cpp
- * @author Brad Kittenbrink <brad@lindenlab.com>
- *
- * $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 "../test/lltut.h"
-
-#include "../llremoteparcelrequest.h"
-
-#include "../llagent.h"
-#include "message.h"
-
-namespace {
- LLControlGroup s_saved_settings("dummy_settings");
- const LLUUID TEST_PARCEL_ID("11111111-1111-1111-1111-111111111111");
-}
-
-LLCurl::Responder::Responder() { }
-LLCurl::Responder::~Responder() { }
-void LLCurl::Responder::error(U32,std::string const &) { }
-void LLCurl::Responder::result(LLSD const &) { }
-void LLCurl::Responder::errorWithContent(U32 status,std::string const &,LLSD const &) { }
-void LLCurl::Responder::completedRaw(U32 status, std::string const &, LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { }
-void LLCurl::Responder::completed(U32 status, std::string const &, LLSD const &) { }
-void LLCurl::Responder::completedHeader(U32 status, std::string const &, LLSD const &) { }
-void LLMessageSystem::getF32(char const *,char const *,F32 &,S32) { }
-void LLMessageSystem::getU8(char const *,char const *,U8 &,S32) { }
-void LLMessageSystem::getS32(char const *,char const *,S32 &,S32) { }
-void LLMessageSystem::getString(char const *,char const *, std::string &,S32) { }
-void LLMessageSystem::getUUID(char const *,char const *, LLUUID & out_id,S32)
-{
- out_id = TEST_PARCEL_ID;
-}
-void LLMessageSystem::nextBlock(char const *) { }
-void LLMessageSystem::addUUID(char const *,LLUUID const &) { }
-void LLMessageSystem::addUUIDFast(char const *,LLUUID const &) { }
-void LLMessageSystem::nextBlockFast(char const *) { }
-void LLMessageSystem::newMessage(char const *) { }
-LLMessageSystem * gMessageSystem;
-char * _PREHASH_AgentID;
-char * _PREHASH_AgentData;
-LLAgent gAgent;
-LLAgent::LLAgent() : mAgentAccess(s_saved_settings) { }
-LLAgent::~LLAgent() { }
-void LLAgent::sendReliableMessage(void) { }
-LLUUID gAgentSessionID;
-LLUUID gAgentID;
-LLUIColor::LLUIColor(void) { }
-LLAgentAccess::LLAgentAccess(LLControlGroup & settings) : mSavedSettings(settings) { }
-LLControlGroup::LLControlGroup(std::string const & name) : LLInstanceTracker<LLControlGroup, std::string>(name) { }
-LLControlGroup::~LLControlGroup(void) { }
-
-namespace tut
-{
- struct TestObserver : public LLRemoteParcelInfoObserver {
- TestObserver() : mProcessed(false) { }
-
- virtual void processParcelInfo(const LLParcelData& parcel_data)
- {
- mProcessed = true;
- }
-
- virtual void setParcelID(const LLUUID& parcel_id) { }
-
- virtual void setErrorStatus(U32 status, const std::string& reason) { }
-
- bool mProcessed;
- };
-
- struct RemoteParcelRequestData
- {
- RemoteParcelRequestData()
- {
- }
- };
-
- typedef test_group<RemoteParcelRequestData> remoteparcelrequest_t;
- typedef remoteparcelrequest_t::object remoteparcelrequest_object_t;
- tut::remoteparcelrequest_t tut_remoteparcelrequest("LLRemoteParcelRequest");
-
- template<> template<>
- void remoteparcelrequest_object_t::test<1>()
- {
- set_test_name("observer pointer");
-
- boost::scoped_ptr<TestObserver> observer(new TestObserver());
-
- LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance();
- processor.addObserver(LLUUID(TEST_PARCEL_ID), observer.get());
-
- processor.processParcelInfoReply(gMessageSystem, NULL);
-
- ensure(observer->mProcessed);
- }
-
- template<> template<>
- void remoteparcelrequest_object_t::test<2>()
- {
- set_test_name("CHOP-220: dangling observer pointer");
-
- LLRemoteParcelInfoObserver * observer = new TestObserver();
-
- LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance();
- processor.addObserver(LLUUID(TEST_PARCEL_ID), observer);
-
- delete observer;
- observer = NULL;
-
- processor.processParcelInfoReply(gMessageSystem, NULL);
- }
-}
+/** + * @file llremoteparcelrequest_test.cpp + * @author Brad Kittenbrink <brad@lindenlab.com> + * + * $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 "../test/lltut.h" + +#include "../llremoteparcelrequest.h" + +#include "../llagent.h" +#include "message.h" + +namespace { + LLControlGroup s_saved_settings("dummy_settings"); + const LLUUID TEST_PARCEL_ID("11111111-1111-1111-1111-111111111111"); +} + +LLCurl::Responder::Responder() { } +LLCurl::Responder::~Responder() { } +void LLCurl::Responder::error(U32,std::string const &) { } +void LLCurl::Responder::result(LLSD const &) { } +void LLCurl::Responder::errorWithContent(U32 status,std::string const &,LLSD const &) { } +void LLCurl::Responder::completedRaw(U32 status, std::string const &, LLChannelDescriptors const &,boost::shared_ptr<LLBufferArray> const &) { } +void LLCurl::Responder::completed(U32 status, std::string const &, LLSD const &) { } +void LLCurl::Responder::completedHeader(U32 status, std::string const &, LLSD const &) { } +void LLMessageSystem::getF32(char const *,char const *,F32 &,S32) { } +void LLMessageSystem::getU8(char const *,char const *,U8 &,S32) { } +void LLMessageSystem::getS32(char const *,char const *,S32 &,S32) { } +void LLMessageSystem::getString(char const *,char const *, std::string &,S32) { } +void LLMessageSystem::getUUID(char const *,char const *, LLUUID & out_id,S32) +{ + out_id = TEST_PARCEL_ID; +} +void LLMessageSystem::nextBlock(char const *) { } +void LLMessageSystem::addUUID(char const *,LLUUID const &) { } +void LLMessageSystem::addUUIDFast(char const *,LLUUID const &) { } +void LLMessageSystem::nextBlockFast(char const *) { } +void LLMessageSystem::newMessage(char const *) { } +LLMessageSystem * gMessageSystem; +char * _PREHASH_AgentID; +char * _PREHASH_AgentData; +LLAgent gAgent; +LLAgent::LLAgent() : mAgentAccess(s_saved_settings) { } +LLAgent::~LLAgent() { } +void LLAgent::sendReliableMessage(void) { } +LLUUID gAgentSessionID; +LLUUID gAgentID; +LLUIColor::LLUIColor(void) { } +LLAgentAccess::LLAgentAccess(LLControlGroup & settings) : mSavedSettings(settings) { } +LLControlGroup::LLControlGroup(std::string const & name) : LLInstanceTracker<LLControlGroup, std::string>(name) { } +LLControlGroup::~LLControlGroup(void) { } + +namespace tut +{ + struct TestObserver : public LLRemoteParcelInfoObserver { + TestObserver() : mProcessed(false) { } + + virtual void processParcelInfo(const LLParcelData& parcel_data) + { + mProcessed = true; + } + + virtual void setParcelID(const LLUUID& parcel_id) { } + + virtual void setErrorStatus(U32 status, const std::string& reason) { } + + bool mProcessed; + }; + + struct RemoteParcelRequestData + { + RemoteParcelRequestData() + { + } + }; + + typedef test_group<RemoteParcelRequestData> remoteparcelrequest_t; + typedef remoteparcelrequest_t::object remoteparcelrequest_object_t; + tut::remoteparcelrequest_t tut_remoteparcelrequest("LLRemoteParcelRequest"); + + template<> template<> + void remoteparcelrequest_object_t::test<1>() + { + set_test_name("observer pointer"); + + boost::scoped_ptr<TestObserver> observer(new TestObserver()); + + LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance(); + processor.addObserver(LLUUID(TEST_PARCEL_ID), observer.get()); + + processor.processParcelInfoReply(gMessageSystem, NULL); + + ensure(observer->mProcessed); + } + + template<> template<> + void remoteparcelrequest_object_t::test<2>() + { + set_test_name("CHOP-220: dangling observer pointer"); + + LLRemoteParcelInfoObserver * observer = new TestObserver(); + + LLRemoteParcelInfoProcessor & processor = LLRemoteParcelInfoProcessor::instance(); + processor.addObserver(LLUUID(TEST_PARCEL_ID), observer); + + delete observer; + observer = NULL; + + processor.processParcelInfoReply(gMessageSystem, NULL); + } +} diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index 5f8cd28f29..88ab5a2284 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -1,200 +1,200 @@ -/**
- * @file llupdaterservice_test.cpp
- * @brief Tests of llupdaterservice.cpp.
- *
- * $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$
- */
-
-// Precompiled header
-#include "linden_common.h"
-// associated header
-#include "../llupdaterservice.h"
-#include "../llupdatechecker.h"
-#include "../llupdatedownloader.h"
-#include "../llupdateinstaller.h"
-
-#include "../../../test/lltut.h"
-//#define DEBUG_ON
-#include "../../../test/debug.h"
-
-#include "llevents.h"
-#include "lldir.h"
-
-/*****************************************************************************
-* MOCK'd
-*****************************************************************************/
-LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client)
-{}
-void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl,
- std::string const & servicePath, std::string channel, std::string version)
-{}
-LLUpdateDownloader::LLUpdateDownloader(Client & ) {}
-void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, bool){}
-
-class LLDir_Mock : public LLDir
-{
- void initAppDirs(const std::string &app_name,
- const std::string& app_read_only_data_dir = "") {}
- U32 countFilesInDir(const std::string &dirname, const std::string &mask)
- {
- return 0;
- }
-
- BOOL getNextFileInDir(const std::string &dirname,
- const std::string &mask,
- std::string &fname)
- {
- return false;
- }
- void getRandomFileInDir(const std::string &dirname,
- const std::string &mask,
- std::string &fname) {}
- std::string getCurPath() { return ""; }
- BOOL fileExists(const std::string &filename) const { return false; }
- std::string getLLPluginLauncher() { return ""; }
- std::string getLLPluginFilename(std::string base_name) { return ""; }
-
-} gDirUtil;
-LLDir* gDirUtilp = &gDirUtil;
-LLDir::LLDir() {}
-LLDir::~LLDir() {}
-S32 LLDir::deleteFilesInDir(const std::string &dirname,
- const std::string &mask)
-{ return 0; }
-
-void LLDir::setChatLogsDir(const std::string &path){}
-void LLDir::setPerAccountChatLogsDir(const std::string &username){}
-void LLDir::setLindenUserDir(const std::string &username){}
-void LLDir::setSkinFolder(const std::string &skin_folder){}
-bool LLDir::setCacheDir(const std::string &path){ return true; }
-void LLDir::dumpCurrentDirectories() {}
-
-std::string LLDir::getExpandedFilename(ELLPath location,
- const std::string &filename) const
-{
- return "";
-}
-
-std::string LLUpdateDownloader::downloadMarkerPath(void)
-{
- return "";
-}
-
-void LLUpdateDownloader::resume(void) {}
-void LLUpdateDownloader::cancel(void) {}
-void LLUpdateDownloader::setBandwidthLimit(U64 bytesPerSecond) {}
-
-int ll_install_update(std::string const &, std::string const &, bool, LLInstallScriptMode)
-{
- return 0;
-}
-
-std::string const & ll_install_failed_marker_path()
-{
- static std::string wubba;
- return wubba;
-}
-
-/*
-#pragma warning(disable: 4273)
-llus_mock_llifstream::llus_mock_llifstream(const std::string& _Filename,
- ios_base::openmode _Mode,
- int _Prot) :
- std::basic_istream<char,std::char_traits< char > >(NULL,true)
-{}
-
-llus_mock_llifstream::~llus_mock_llifstream() {}
-bool llus_mock_llifstream::is_open() const {return true;}
-void llus_mock_llifstream::close() {}
-*/
-
-/*****************************************************************************
-* TUT
-*****************************************************************************/
-namespace tut
-{
- struct llupdaterservice_data
- {
- llupdaterservice_data() :
- pumps(LLEventPumps::instance()),
- test_url("dummy_url"),
- test_channel("dummy_channel"),
- test_version("dummy_version")
- {}
- LLEventPumps& pumps;
- std::string test_url;
- std::string test_channel;
- std::string test_version;
- };
-
- typedef test_group<llupdaterservice_data> llupdaterservice_group;
- typedef llupdaterservice_group::object llupdaterservice_object;
- llupdaterservice_group llupdaterservicegrp("LLUpdaterService");
-
- template<> template<>
- void llupdaterservice_object::test<1>()
- {
- DEBUG;
- LLUpdaterService updater;
- bool got_usage_error = false;
- try
- {
- updater.startChecking();
- }
- catch(LLUpdaterService::UsageError)
- {
- got_usage_error = true;
- }
- ensure("Caught start before params", got_usage_error);
- }
-
- template<> template<>
- void llupdaterservice_object::test<2>()
- {
- DEBUG;
- LLUpdaterService updater;
- bool got_usage_error = false;
- try
- {
- updater.initialize("1.0",test_url, "update" ,test_channel, test_version);
- updater.startChecking();
- updater.initialize("1.0", "other_url", "update", test_channel, test_version);
- }
- catch(LLUpdaterService::UsageError)
- {
- got_usage_error = true;
- }
- ensure("Caught params while running", got_usage_error);
- }
-
- template<> template<>
- void llupdaterservice_object::test<3>()
- {
- DEBUG;
- LLUpdaterService updater;
- updater.initialize("1.0", test_url, "update", test_channel, test_version);
- updater.startChecking();
- ensure(updater.isChecking());
- updater.stopChecking();
- ensure(!updater.isChecking());
- }
-}
+/** + * @file llupdaterservice_test.cpp + * @brief Tests of llupdaterservice.cpp. + * + * $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$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "../llupdaterservice.h" +#include "../llupdatechecker.h" +#include "../llupdatedownloader.h" +#include "../llupdateinstaller.h" + +#include "../../../test/lltut.h" +//#define DEBUG_ON +#include "../../../test/debug.h" + +#include "llevents.h" +#include "lldir.h" + +/***************************************************************************** +* MOCK'd +*****************************************************************************/ +LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client) +{} +void LLUpdateChecker::check(std::string const & protocolVersion, std::string const & hostUrl, + std::string const & servicePath, std::string channel, std::string version) +{} +LLUpdateDownloader::LLUpdateDownloader(Client & ) {} +void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, bool){} + +class LLDir_Mock : public LLDir +{ + void initAppDirs(const std::string &app_name, + const std::string& app_read_only_data_dir = "") {} + U32 countFilesInDir(const std::string &dirname, const std::string &mask) + { + return 0; + } + + BOOL getNextFileInDir(const std::string &dirname, + const std::string &mask, + std::string &fname) + { + return false; + } + void getRandomFileInDir(const std::string &dirname, + const std::string &mask, + std::string &fname) {} + std::string getCurPath() { return ""; } + BOOL fileExists(const std::string &filename) const { return false; } + std::string getLLPluginLauncher() { return ""; } + std::string getLLPluginFilename(std::string base_name) { return ""; } + +} gDirUtil; +LLDir* gDirUtilp = &gDirUtil; +LLDir::LLDir() {} +LLDir::~LLDir() {} +S32 LLDir::deleteFilesInDir(const std::string &dirname, + const std::string &mask) +{ return 0; } + +void LLDir::setChatLogsDir(const std::string &path){} +void LLDir::setPerAccountChatLogsDir(const std::string &username){} +void LLDir::setLindenUserDir(const std::string &username){} +void LLDir::setSkinFolder(const std::string &skin_folder){} +bool LLDir::setCacheDir(const std::string &path){ return true; } +void LLDir::dumpCurrentDirectories() {} + +std::string LLDir::getExpandedFilename(ELLPath location, + const std::string &filename) const +{ + return ""; +} + +std::string LLUpdateDownloader::downloadMarkerPath(void) +{ + return ""; +} + +void LLUpdateDownloader::resume(void) {} +void LLUpdateDownloader::cancel(void) {} +void LLUpdateDownloader::setBandwidthLimit(U64 bytesPerSecond) {} + +int ll_install_update(std::string const &, std::string const &, bool, LLInstallScriptMode) +{ + return 0; +} + +std::string const & ll_install_failed_marker_path() +{ + static std::string wubba; + return wubba; +} + +/* +#pragma warning(disable: 4273) +llus_mock_llifstream::llus_mock_llifstream(const std::string& _Filename, + ios_base::openmode _Mode, + int _Prot) : + std::basic_istream<char,std::char_traits< char > >(NULL,true) +{} + +llus_mock_llifstream::~llus_mock_llifstream() {} +bool llus_mock_llifstream::is_open() const {return true;} +void llus_mock_llifstream::close() {} +*/ + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct llupdaterservice_data + { + llupdaterservice_data() : + pumps(LLEventPumps::instance()), + test_url("dummy_url"), + test_channel("dummy_channel"), + test_version("dummy_version") + {} + LLEventPumps& pumps; + std::string test_url; + std::string test_channel; + std::string test_version; + }; + + typedef test_group<llupdaterservice_data> llupdaterservice_group; + typedef llupdaterservice_group::object llupdaterservice_object; + llupdaterservice_group llupdaterservicegrp("LLUpdaterService"); + + template<> template<> + void llupdaterservice_object::test<1>() + { + DEBUG; + LLUpdaterService updater; + bool got_usage_error = false; + try + { + updater.startChecking(); + } + catch(LLUpdaterService::UsageError) + { + got_usage_error = true; + } + ensure("Caught start before params", got_usage_error); + } + + template<> template<> + void llupdaterservice_object::test<2>() + { + DEBUG; + LLUpdaterService updater; + bool got_usage_error = false; + try + { + updater.initialize("1.0",test_url, "update" ,test_channel, test_version); + updater.startChecking(); + updater.initialize("1.0", "other_url", "update", test_channel, test_version); + } + catch(LLUpdaterService::UsageError) + { + got_usage_error = true; + } + ensure("Caught params while running", got_usage_error); + } + + template<> template<> + void llupdaterservice_object::test<3>() + { + DEBUG; + LLUpdaterService updater; + updater.initialize("1.0", test_url, "update", test_channel, test_version); + updater.startChecking(); + ensure(updater.isChecking()); + updater.stopChecking(); + ensure(!updater.isChecking()); + } +} |