diff options
162 files changed, 2829 insertions, 2675 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt index a74cf32afa..8c6bd5e0fe 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -185,6 +185,8 @@ Dale Glass VWR-2502 VWR-1358 VWR-2041 +Drew Dri + VWR-19683 Drewan Keats VWR-28 VWR-248 diff --git a/indra/cmake/CARes.cmake b/indra/cmake/CARes.cmake index 8a2dc01561..1850b706ac 100644 --- a/indra/cmake/CARes.cmake +++ b/indra/cmake/CARes.cmake @@ -9,6 +9,7 @@ if (STANDALONE) include(FindCARes) else (STANDALONE) use_prebuilt_binary(ares) + add_definitions("-DCARES_STATICLIB") if (WINDOWS) set(CARES_LIBRARIES areslib) elseif (DARWIN) diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index faf9da8b14..89422fbdb2 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -19,7 +19,7 @@ if(WINDOWS) set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-win32") set(vivox_files SLVoice.exe - libsndfile-1.dll + libsndfile-1.dll vivoxplatform.dll vivoxsdk.dll ortp.dll @@ -167,6 +167,7 @@ elseif(DARWIN) libexpat.dylib libllqtwebkit.dylib libndofdev.dylib + libexception_handler.dylib ) # fmod is statically linked on darwin @@ -216,6 +217,7 @@ elseif(LINUX) libapr-1.so.0 libaprutil-1.so.0 libatk-1.0.so + libbreakpad_client.so.0 libcrypto.so.0.9.7 libdb-4.2.so libexpat.so diff --git a/indra/cmake/GoogleBreakpad.cmake b/indra/cmake/GoogleBreakpad.cmake new file mode 100644 index 0000000000..8270c0fabb --- /dev/null +++ b/indra/cmake/GoogleBreakpad.cmake @@ -0,0 +1,19 @@ +# -*- cmake -*- +include(Prebuilt) + +if (STANDALONE) + MESSAGE(FATAL_ERROR "*TODO standalone support for google breakad is unimplemented") + # *TODO - implement this include(FindGoogleBreakpad) +else (STANDALONE) + use_prebuilt_binary(google_breakpad) + if (DARWIN) + set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler) + endif (DARWIN) + if (LINUX) + set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES breakpad_client) + endif (LINUX) + if (WINDOWS) + set(BREAKPAD_EXCEPTION_HANDLER_LIBRARIES exception_handler crash_generation_client common) + endif (WINDOWS) +endif (STANDALONE) + diff --git a/indra/linux_crash_logger/llcrashloggerlinux.cpp b/indra/linux_crash_logger/llcrashloggerlinux.cpp index 039b70ec4a..ce03ea0d6f 100644 --- a/indra/linux_crash_logger/llcrashloggerlinux.cpp +++ b/indra/linux_crash_logger/llcrashloggerlinux.cpp @@ -120,7 +120,6 @@ LLCrashLoggerLinux::~LLCrashLoggerLinux(void) void LLCrashLoggerLinux::gatherPlatformSpecificFiles() { - mFileMap["CrashLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log").c_str(); } bool LLCrashLoggerLinux::mainLoop() diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 527ab42fc9..2a036df06e 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -9,6 +9,7 @@ include(Linking) include(Boost) include(Pth) include(LLSharedLibs) +include(GoogleBreakpad) include(GooglePerfTools) include(Copy3rdPartyLibs) @@ -258,6 +259,7 @@ endif(LLCOMMON_LINK_SHARED) target_link_libraries( llcommon + ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES} ${APRUTIL_LIBRARIES} ${APR_LIBRARIES} ${EXPAT_LIBRARIES} diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index 6b2d1b7c20..eedec0b24e 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -30,6 +30,8 @@ * $/LicenseInfo$ */ +#include <cstdlib> + #include "linden_common.h" #include "llapp.h" @@ -41,8 +43,11 @@ #include "lllivefile.h" #include "llmemory.h" #include "llstl.h" // for DeletePointer() +#include "llstring.h" #include "lleventtimer.h" +#include "google_breakpad/exception_handler.h" + // // Signal handling // @@ -51,11 +56,22 @@ #if LL_WINDOWS LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop); BOOL ConsoleCtrlHandler(DWORD fdwCtrlType); +bool windows_post_minidump_callback(const wchar_t* dump_path, + const wchar_t* minidump_id, + void* context, + EXCEPTION_POINTERS* exinfo, + MDRawAssertionInfo* assertion, + bool succeeded); #else # include <signal.h> # include <unistd.h> // for fork() void setup_signals(); void default_unix_signal_handler(int signum, siginfo_t *info, void *); + +// Called by breakpad exception handler after the minidump has been generated. +bool unix_post_minidump_callback(const char *dump_dir, + const char *minidump_id, + void *context, bool succeeded); # if LL_DARWIN /* OSX doesn't support SIGRT* */ S32 LL_SMACKDOWN_SIGNAL = SIGUSR1; @@ -81,7 +97,6 @@ BOOL LLApp::sLogInSignal = FALSE; // static LLApp::EAppStatus LLApp::sStatus = LLApp::APP_STATUS_STOPPED; // Keeps track of application status LLAppErrorHandler LLApp::sErrorHandler = NULL; -LLAppErrorHandler LLApp::sSyncErrorHandler = NULL; BOOL LLApp::sErrorThreadRunning = FALSE; #if !LL_WINDOWS LLApp::child_map LLApp::sChildMap; @@ -123,7 +138,12 @@ void LLApp::commonCtor() // Set the application to this instance. sApplication = this; - + + mExceptionHandler = 0; + + // initialize the buffer to write the minidump filename to + // (this is used to avoid allocating memory in the crash handler) + memset(minidump_path, 0, MAX_MINDUMP_PATH_LENGTH); } LLApp::LLApp(LLErrorThread *error_thread) : @@ -152,6 +172,8 @@ LLApp::~LLApp() delete mThreadErrorp; mThreadErrorp = NULL; } + + if(mExceptionHandler != 0) delete mExceptionHandler; LLCommon::cleanupClass(); } @@ -262,19 +284,18 @@ void LLApp::setupErrorHandling() // occasionally checks to see if the app is in an error state, and sees if it needs to be run. #if LL_WINDOWS - // Windows doesn't have the same signal handling mechanisms as UNIX, thus APR doesn't provide - // a signal handling thread implementation. - // What we do is install an unhandled exception handler, which will try to do the right thing - // in the case of an error (generate a minidump) - - // Disable this until the viewer gets ported so server crashes can be JIT debugged. - //LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; - //prev_filter = SetUnhandledExceptionFilter(default_windows_exception_handler); - // This sets a callback to handle w32 signals to the console window. // The viewer shouldn't be affected, sicne its a windowed app. SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ConsoleCtrlHandler, TRUE); + // Install the Google Breakpad crash handler for Windows + if(mExceptionHandler == 0) + { + llwarns << "adding breakpad exception handler" << llendl; + mExceptionHandler = new google_breakpad::ExceptionHandler( + L"C:\\Temp\\", 0, windows_post_minidump_callback, 0, google_breakpad::ExceptionHandler::HANDLER_ALL); + } + #else // // Start up signal handling. @@ -282,9 +303,14 @@ void LLApp::setupErrorHandling() // There are two different classes of signals. Synchronous signals are delivered to a specific // thread, asynchronous signals can be delivered to any thread (in theory) // - setup_signals(); - + + // Add google breakpad exception handler configured for Darwin/Linux. + if(mExceptionHandler == 0) + { + std::string dumpPath = "/tmp/"; + mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, 0, &unix_post_minidump_callback, 0, true); + } #endif startErrorThread(); @@ -310,21 +336,6 @@ void LLApp::setErrorHandler(LLAppErrorHandler handler) LLApp::sErrorHandler = handler; } - -void LLApp::setSyncErrorHandler(LLAppErrorHandler handler) -{ - LLApp::sSyncErrorHandler = handler; -} - -// static -void LLApp::runSyncErrorHandler() -{ - if (LLApp::sSyncErrorHandler) - { - LLApp::sSyncErrorHandler(); - } -} - // static void LLApp::runErrorHandler() { @@ -337,7 +348,6 @@ void LLApp::runErrorHandler() LLApp::setStopped(); } - // static void LLApp::setStatus(EAppStatus status) { @@ -348,15 +358,27 @@ void LLApp::setStatus(EAppStatus status) // static void LLApp::setError() { - if (!isError()) - { - // perform any needed synchronous error-handling - runSyncErrorHandler(); - // set app status to ERROR so that the LLErrorThread notices - setStatus(APP_STATUS_ERROR); - } + // set app status to ERROR so that the LLErrorThread notices + setStatus(APP_STATUS_ERROR); } +void LLApp::setMiniDumpDir(const std::string &path) +{ + llassert(mExceptionHandler); +#ifdef LL_WINDOWS + wchar_t buffer[MAX_MINDUMP_PATH_LENGTH]; + mbstowcs(buffer, path.c_str(), MAX_MINDUMP_PATH_LENGTH); + mExceptionHandler->set_dump_path(std::wstring(buffer)); +#else + mExceptionHandler->set_dump_path(path); +#endif +} + +void LLApp::writeMiniDump() +{ + llassert(mExceptionHandler); + mExceptionHandler->WriteMinidump(); +} // static void LLApp::setQuitting() @@ -587,6 +609,7 @@ void setup_signals() // Asynchronous signals that result in core sigaction(SIGQUIT, &act, NULL); + } void clear_signals() @@ -765,4 +788,97 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) } } +bool unix_post_minidump_callback(const char *dump_dir, + const char *minidump_id, + void *context, bool succeeded) +{ + // Copy minidump file path into fixed buffer in the app instance to avoid + // heap allocations in a crash handler. + + // path format: <dump_dir>/<minidump_id>.dmp + int dirPathLength = strlen(dump_dir); + int idLength = strlen(minidump_id); + + // The path must not be truncated. + llassert((dirPathLength + idLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH); + + char * path = LLApp::instance()->getMiniDumpFilename(); + S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; + strncpy(path, dump_dir, remaining); + remaining -= dirPathLength; + path += dirPathLength; + if (remaining > 0 && dirPathLength > 0 && path[-1] != '/') + { + *path++ = '/'; + --remaining; + } + if (remaining > 0) + { + strncpy(path, minidump_id, remaining); + remaining -= idLength; + path += idLength; + strncpy(path, ".dmp", remaining); + } + + llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl; + LLApp::runErrorHandler(); + return true; +} #endif // !WINDOWS + +#ifdef LL_WINDOWS +bool windows_post_minidump_callback(const wchar_t* dump_path, + const wchar_t* minidump_id, + void* context, + EXCEPTION_POINTERS* exinfo, + MDRawAssertionInfo* assertion, + bool succeeded) +{ + char * path = LLApp::instance()->getMiniDumpFilename(); + S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; + size_t bytesUsed; + + bytesUsed = wcstombs(path, dump_path, static_cast<size_t>(remaining)); + remaining -= bytesUsed; + path += bytesUsed; + if(remaining > 0 && bytesUsed > 0 && path[-1] != '\\') + { + *path++ = '\\'; + --remaining; + } + if(remaining > 0) + { + bytesUsed = wcstombs(path, minidump_id, static_cast<size_t>(remaining)); + remaining -= bytesUsed; + path += bytesUsed; + } + if(remaining > 0) + { + strncpy(path, ".dmp", remaining); + } + + llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl; + // *NOTE:Mani - this code is stolen from LLApp, where its never actually used. + //OSMessageBox("Attach Debugger Now", "Error", OSMB_OK); + // *TODO: Translate the signals/exceptions into cross-platform stuff + // Windows implementation + llinfos << "Entering Windows Exception Handler..." << llendl; + + if (LLApp::isError()) + { + llwarns << "Got another fatal signal while in the error handler, die now!" << llendl; + } + + // Flag status to error, so thread_error starts its work + LLApp::setError(); + + // Block in the exception handler until the app has stopped + // This is pretty sketchy, but appears to work just fine + while (!LLApp::isStopped()) + { + ms_sleep(10); + } + + return true; +} +#endif diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index e5b8edf9c3..fef05a7939 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -66,6 +66,10 @@ public: }; #endif +namespace google_breakpad { + class ExceptionHandler; // See exception_handler.h +} + class LL_COMMON_API LLApp : public LLOptionInterface { friend class LLErrorThread; @@ -227,8 +231,20 @@ public: void setupErrorHandling(); void setErrorHandler(LLAppErrorHandler handler); - void setSyncErrorHandler(LLAppErrorHandler handler); + static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred. //@} + + // the maximum length of the minidump filename returned by getMiniDumpFilename() + static const U32 MAX_MINDUMP_PATH_LENGTH = 256; + + // change the directory where Breakpad minidump files are written to + void setMiniDumpDir(const std::string &path); + + // Return the Google Breakpad minidump filename after a crash. + char *getMiniDumpFilename() { return minidump_path; } + + // Write out a Google Breakpad minidump file. + void writeMiniDump(); #if !LL_WINDOWS // @@ -286,15 +302,14 @@ protected: private: void startErrorThread(); - static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred. - static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread. + // Contains the filename of the minidump file after a crash. + char minidump_path[MAX_MINDUMP_PATH_LENGTH]; // *NOTE: On Windows, we need a routine to reset the structured // exception handler when some evil driver has taken it over for // their own purposes typedef int(*signal_handler_func)(int signum); static LLAppErrorHandler sErrorHandler; - static LLAppErrorHandler sSyncErrorHandler; // Default application threads LLErrorThread* mThreadErrorp; // Waits for app to go to status ERROR, then runs the error callback @@ -315,6 +330,8 @@ private: private: // the static application instance if it was created. static LLApp* sApplication; + + google_breakpad::ExceptionHandler * mExceptionHandler; #if !LL_WINDOWS diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index de7f2ead74..a7ef28b431 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -248,8 +248,27 @@ bool LLDate::fromStream(std::istream& s) s >> fractional; seconds_since_epoch += fractional; } - c = s.get(); // skip the Z - if (c != 'Z') { return false; } + + c = s.peek(); // check for offset + if (c == '+' || c == '-') + { + S32 offset_sign = (c == '+') ? 1 : -1; + S32 offset_hours = 0; + S32 offset_minutes = 0; + S32 offset_in_seconds = 0; + + s >> offset_hours; + + c = s.get(); // skip the colon a get the minutes if there are any + if (c == ':') + { + s >> offset_minutes; + } + + offset_in_seconds = (offset_hours * 60 + offset_sign * offset_minutes) * 60; + seconds_since_epoch -= offset_in_seconds; + } + else if (c != 'Z') { return false; } // skip the Z mSecondsSinceEpoch = seconds_since_epoch; return true; diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index adef1a9192..dbb8ec5231 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -135,7 +135,7 @@ class LL_COMMON_API LLMutex { public: LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex - ~LLMutex(); + virtual ~LLMutex(); void lock(); // blocks void unlock(); diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h index e3663544db..87fe7001e0 100644 --- a/indra/llcommon/llversionserver.h +++ b/indra/llcommon/llversionserver.h @@ -33,10 +33,10 @@ #ifndef LL_LLVERSIONSERVER_H #define LL_LLVERSIONSERVER_H -const S32 LL_VERSION_MAJOR = 1; -const S32 LL_VERSION_MINOR = 31; +const S32 LL_VERSION_MAJOR = 2; +const S32 LL_VERSION_MINOR = 1; const S32 LL_VERSION_PATCH = 0; -const S32 LL_VERSION_BUILD = 203110; +const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Server"; diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index fc3ce6df7e..6e341b83a1 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -34,8 +34,8 @@ #define LL_LLVERSIONVIEWER_H const S32 LL_VERSION_MAJOR = 2; -const S32 LL_VERSION_MINOR = 0; -const S32 LL_VERSION_PATCH = 2; +const S32 LL_VERSION_MINOR = 1; +const S32 LL_VERSION_PATCH = 0; const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index c1022c1195..51e5f14bfe 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -155,25 +155,6 @@ std::string getStartupStateFromLog(std::string& sllog) void LLCrashLogger::gatherFiles() { - - /* - //TODO:This function needs to be reimplemented somewhere in here... - if(!previous_crash && is_crash_log) - { - // Make sure the file isn't too old. - double age = difftime(gLaunchTime, stat_data.st_mtimespec.tv_sec); - - // llinfos << "age is " << age << llendl; - - if(age > 60.0) - { - // The file was last modified more than 60 seconds before the crash reporter was launched. Assume it's stale. - llwarns << "File " << mFilename << " is too old!" << llendl; - return; - } - } - */ - updateApplication("Gathering logs..."); // Figure out the filename of the debug log @@ -209,11 +190,9 @@ void LLCrashLogger::gatherFiles() mFileMap["SettingsXml"] = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml"); } -#if !LL_DARWIN if(mCrashInPreviousExec) -#else -#endif { + // Restarting after freeze. // Replace the log file ext with .old, since the // instance that launched this process has overwritten // SecondLife.log @@ -225,7 +204,12 @@ void LLCrashLogger::gatherFiles() gatherPlatformSpecificFiles(); //Use the debug log to reconstruct the URL to send the crash report to - if(mDebugLog.has("CurrentSimHost")) + if(mDebugLog.has("CrashHostUrl")) + { + // Crash log receiver has been manually configured. + mCrashHost = mDebugLog["CrashHostUrl"].asString(); + } + else if(mDebugLog.has("CurrentSimHost")) { mCrashHost = "https://"; mCrashHost += mDebugLog["CurrentSimHost"].asString(); @@ -247,7 +231,6 @@ void LLCrashLogger::gatherFiles() mCrashInfo["DebugLog"] = mDebugLog; mFileMap["StatsLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stats.log"); - mFileMap["StackTrace"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); updateApplication("Encoding files..."); @@ -272,8 +255,30 @@ void LLCrashLogger::gatherFiles() trimSLLog(crash_info); } - mCrashInfo[(*itr).first] = rawstr_to_utf8(crash_info); + mCrashInfo[(*itr).first] = LLStringFn::strip_invalid_xml(rawstr_to_utf8(crash_info)); + } + + // Add minidump as binary. + std::string minidump_path = mDebugLog["MinidumpPath"]; + if(minidump_path != "") + { + std::ifstream minidump_stream(minidump_path.c_str(), std::ios_base::in | std::ios_base::binary); + if(minidump_stream.is_open()) + { + minidump_stream.seekg(0, std::ios::end); + size_t length = minidump_stream.tellg(); + minidump_stream.seekg(0, std::ios::beg); + + LLSD::Binary data; + data.resize(length); + + minidump_stream.read(reinterpret_cast<char *>(&(data[0])),length); + minidump_stream.close(); + + mCrashInfo["Minidump"] = data; + } } + mCrashInfo["DebugLog"].erase("MinidumpPath"); } LLSD LLCrashLogger::constructPostData() diff --git a/indra/llimage/llimagepng.cpp b/indra/llimage/llimagepng.cpp index b5de104e61..018ce993b5 100644 --- a/indra/llimage/llimagepng.cpp +++ b/indra/llimage/llimagepng.cpp @@ -42,17 +42,12 @@ // LLImagePNG // --------------------------------------------------------------------------- LLImagePNG::LLImagePNG() - : LLImageFormatted(IMG_CODEC_PNG), - mTmpWriteBuffer(NULL) + : LLImageFormatted(IMG_CODEC_PNG) { } LLImagePNG::~LLImagePNG() { - if (mTmpWriteBuffer) - { - delete[] mTmpWriteBuffer; - } } // Virtual @@ -123,27 +118,24 @@ BOOL LLImagePNG::encode(const LLImageRaw* raw_image, F32 encode_time) // Temporary buffer to hold the encoded image. Note: the final image // size should be much smaller due to compression. - if (mTmpWriteBuffer) - { - delete[] mTmpWriteBuffer; - } U32 bufferSize = getWidth() * getHeight() * getComponents() + 1024; - U8* mTmpWriteBuffer = new U8[ bufferSize ]; + U8* tmpWriteBuffer = new U8[ bufferSize ]; // Delegate actual encoding work to wrapper LLPngWrapper pngWrapper; - if (! pngWrapper.writePng(raw_image, mTmpWriteBuffer)) + if (! pngWrapper.writePng(raw_image, tmpWriteBuffer)) { setLastError(pngWrapper.getErrorMessage()); + delete[] tmpWriteBuffer; return FALSE; } // Resize internal buffer and copy from temp U32 encodedSize = pngWrapper.getFinalSize(); allocateData(encodedSize); - memcpy(getData(), mTmpWriteBuffer, encodedSize); + memcpy(getData(), tmpWriteBuffer, encodedSize); - delete[] mTmpWriteBuffer; + delete[] tmpWriteBuffer; return TRUE; } diff --git a/indra/llimage/llimagepng.h b/indra/llimage/llimagepng.h index 083dda73b9..4d6e2ee70a 100644 --- a/indra/llimage/llimagepng.h +++ b/indra/llimage/llimagepng.h @@ -47,9 +47,6 @@ public: /*virtual*/ BOOL updateData(); /*virtual*/ BOOL decode(LLImageRaw* raw_image, F32 decode_time); /*virtual*/ BOOL encode(const LLImageRaw* raw_image, F32 encode_time); - -private: - U8* mTmpWriteBuffer; }; #endif diff --git a/indra/llmath/tests/mathmisc_test.cpp b/indra/llmath/tests/mathmisc_test.cpp index ea42f6e001..68d9ddc0fe 100644 --- a/indra/llmath/tests/mathmisc_test.cpp +++ b/indra/llmath/tests/mathmisc_test.cpp @@ -334,6 +334,8 @@ namespace tut template<> template<> void sphere_object::test<2>() { + skip("See SNOW-620. Neither the test nor the code being tested seem good. Also sim-only."); + // test LLSphere::getBoundingSphere() S32 number_of_tests = 100; S32 number_of_spheres = 10; diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp index 00e77d20e9..5b7e5138ef 100644 --- a/indra/llmessage/llares.cpp +++ b/indra/llmessage/llares.cpp @@ -108,7 +108,8 @@ LLAres::LLAres() : mInitSuccess(false), mListener(new LLAresListener(this)) { - if (ares_init(&chan_) != ARES_SUCCESS) + if (ares_library_init( ARES_LIB_INIT_ALL ) != ARES_SUCCESS || + ares_init(&chan_) != ARES_SUCCESS) { llwarns << "Could not succesfully initialize ares!" << llendl; return; @@ -120,6 +121,7 @@ LLAres::LLAres() : LLAres::~LLAres() { ares_destroy(chan_); + ares_library_cleanup(); } void LLAres::cancel() @@ -473,7 +475,7 @@ bool LLAres::process(U64 timeout) ll_init_apr(); } - int socks[ARES_GETSOCK_MAXNUM]; + ares_socket_t socks[ARES_GETSOCK_MAXNUM]; apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM]; apr_int32_t nsds = 0; int nactive = 0; diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 9c2e4b5658..e8dc207114 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -199,6 +199,7 @@ namespace fileBuffer = new U8 [fileSize]; vfile.read(fileBuffer, fileSize); ostream.write((char*)fileBuffer, fileSize); + delete [] fileBuffer; eos = true; return STATUS_DONE; } diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index cd23d5cd33..fc93793ed8 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -523,6 +523,8 @@ void LLAccordionCtrl::arrangeMultiple() void LLAccordionCtrl::arrange() { + updateNoTabsHelpTextVisibility(); + if( mAccordionTabs.size() == 0) { //We do not arrange if we do not have what should be arranged @@ -818,7 +820,7 @@ void LLAccordionCtrl::setFilterSubString(const std::string& filter_string) { LLStringUtil::format_map_t args; args["[SEARCH_TERM]"] = LLURI::escape(filter_string); - std::string text = mNoVisibleTabsOrigString; + std::string text = filter_string.empty() ? LLStringUtil::null : mNoVisibleTabsOrigString; LLStringUtil::format(text, args); mNoVisibleTabsHelpText->setValue(text); diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 1bc8086a27..be231fd8cf 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -968,3 +968,16 @@ BOOL LLAccordionCtrlTab::handleToolTip(S32 x, S32 y, MASK mask) } return LLUICtrl::handleToolTip(x, y, mask); } +BOOL LLAccordionCtrlTab::handleScrollWheel ( S32 x, S32 y, S32 clicks ) +{ + if( LLUICtrl::handleScrollWheel(x,y,clicks)) + { + return TRUE; + } + if( mScrollbar->getVisible() && mScrollbar->handleScrollWheel( 0, 0, clicks ) ) + { + return TRUE; + } + return FALSE; +} + diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 480b26e130..19d4ec0a1c 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -166,6 +166,8 @@ public: virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); virtual BOOL handleToolTip(S32 x, S32 y, MASK mask); + virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); + virtual bool addChild(LLView* child, S32 tab_group); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 341debc9a8..9a56372e68 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -347,7 +347,7 @@ void LLFloater::layoutDragHandle() { rect = getLocalRect(); } - mDragHandle->setRect(rect); + mDragHandle->setShape(rect); updateTitleButtons(); } diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 72f3a14822..3c6c7d3e82 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -2791,7 +2791,7 @@ bool LLImageTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width height = llceil(mStyle->getFont()->getLineHeight());; LLUIImagePtr image = mStyle->getImage(); - if( image.notNull()) + if( num_chars>0 && image.notNull()) { width += image->getWidth() + IMAGE_HPAD; height = llmax(height, image->getHeight() + IMAGE_HPAD ); @@ -2803,13 +2803,13 @@ S32 LLImageTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin { LLUIImagePtr image = mStyle->getImage(); S32 image_width = image->getWidth(); - if(num_pixels>image_width + IMAGE_HPAD) + if(line_offset == 0 || num_pixels>image_width + IMAGE_HPAD) { return 1; } - return 0; } + F32 LLImageTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect) { if ( (start >= 0) && (end <= mEnd - mStart)) diff --git a/indra/mac_crash_logger/llcrashloggermac.cpp b/indra/mac_crash_logger/llcrashloggermac.cpp index 16efa4fe2c..90de39ba27 100644 --- a/indra/mac_crash_logger/llcrashloggermac.cpp +++ b/indra/mac_crash_logger/llcrashloggermac.cpp @@ -211,89 +211,6 @@ bool LLCrashLoggerMac::init(void) void LLCrashLoggerMac::gatherPlatformSpecificFiles() { updateApplication("Gathering hardware information..."); - char path[MAX_PATH]; - FSRef folder; - - if(FSFindFolder(kUserDomain, kLogsFolderType, false, &folder) == noErr) - { - // folder is an FSRef to ~/Library/Logs/ - if(FSRefMakePath(&folder, (UInt8*)&path, sizeof(path)) == noErr) - { - struct stat dw_stat; - std::string mBuf; - bool isLeopard = false; - // Try the 10.3 path first... - std::string dw_file_name = std::string(path) + std::string("/CrashReporter/Second Life.crash.log"); - int res = stat(dw_file_name.c_str(), &dw_stat); - - if (res) - { - // Try the 10.2 one next... - dw_file_name = std::string(path) + std::string("/Second Life.crash.log"); - res = stat(dw_file_name.c_str(), &dw_stat); - } - - if(res) - { - //10.5: Like 10.3+, except it puts the crash time in the file instead of dividing it up - //using asterisks. Get a directory listing, search for files starting with second life, - //use the last one found. - std::string old_file_name, current_file_name, pathname, mask; - pathname = std::string(path) + std::string("/CrashReporter/"); - mask = "Second Life*"; - while(gDirUtilp->getNextFileInDir(pathname, mask, current_file_name, false)) - { - old_file_name = current_file_name; - } - if(old_file_name != "") - { - dw_file_name = pathname + old_file_name; - res=stat(dw_file_name.c_str(), &dw_stat); - isLeopard = true; - } - } - - if (!res) - { - std::ifstream fp(dw_file_name.c_str()); - std::stringstream str; - if(!fp.is_open()) return; - str << fp.rdbuf(); - mBuf = str.str(); - - if(!isLeopard) - { - // Crash logs consist of a number of entries, one per crash. - // Each entry is preceeded by "**********" on a line by itself. - // We want only the most recent (i.e. last) one. - const char *sep = "**********"; - const char *start = mBuf.c_str(); - const char *cur = start; - const char *temp = strstr(cur, sep); - - while(temp != NULL) - { - // Skip past the marker we just found - cur = temp + strlen(sep); /* Flawfinder: ignore */ - - // and try to find another - temp = strstr(cur, sep); - } - - // If there's more than one entry in the log file, strip all but the last one. - if(cur != start) - { - mBuf.erase(0, cur - start); - } - } - mCrashInfo["CrashLog"] = mBuf; - } - else - { - llwarns << "Couldn't find any CrashReporter files..." << llendl; - } - } - } } bool LLCrashLoggerMac::mainLoop() diff --git a/indra/media_plugins/gstreamer010/CMakeLists.txt b/indra/media_plugins/gstreamer010/CMakeLists.txt index 3b73e04786..9f0ff654fc 100644 --- a/indra/media_plugins/gstreamer010/CMakeLists.txt +++ b/indra/media_plugins/gstreamer010/CMakeLists.txt @@ -42,12 +42,12 @@ set(media_plugin_gstreamer010_HEADER_FILES llmediaimplgstreamertriviallogging.h ) -if (${CXX_VERSION_NUMBER} MATCHES "4[23].") +if (${CXX_VERSION_NUMBER} MATCHES "4[23456789].") # Work around a bad interaction between broken gstreamer headers and - # g++ 4.3's increased strictness. + # g++ >= 4.2's increased strictness. set_source_files_properties(llmediaimplgstreamervidplug.cpp PROPERTIES COMPILE_FLAGS -Wno-write-strings) -endif (${CXX_VERSION_NUMBER} MATCHES "4[23].") +endif (${CXX_VERSION_NUMBER} MATCHES "4[23456789].") add_library(media_plugin_gstreamer010 SHARED diff --git a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp index 033c4ba2f3..e6d2ad3edc 100644 --- a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp +++ b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp @@ -544,8 +544,12 @@ MediaPluginGStreamer010::pause() { DEBUGMSG("pausing media..."); // todo: error-check this? - llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); - return true; + if (mDoneInit && mPlaybin) + { + llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); + return true; + } + return false; } bool @@ -553,8 +557,12 @@ MediaPluginGStreamer010::stop() { DEBUGMSG("stopping media..."); // todo: error-check this? - llgst_element_set_state(mPlaybin, GST_STATE_READY); - return true; + if (mDoneInit && mPlaybin) + { + llgst_element_set_state(mPlaybin, GST_STATE_READY); + return true; + } + return false; } bool @@ -564,8 +572,12 @@ MediaPluginGStreamer010::play(double rate) DEBUGMSG("playing media... rate=%f", rate); // todo: error-check this? - llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); - return true; + if (mDoneInit && mPlaybin) + { + llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); + return true; + } + return false; } bool @@ -608,7 +620,7 @@ bool MediaPluginGStreamer010::getTimePos(double &sec_out) { bool got_position = false; - if (mPlaybin) + if (mDoneInit && mPlaybin) { gint64 pos; GstFormat timefmt = GST_FORMAT_TIME; @@ -688,6 +700,7 @@ MediaPluginGStreamer010::load() this); llgst_object_unref (bus); +#if 0 // not quite stable/correct yet // get a visualizer element (bonus feature!) char* vis_name = getenv("LL_GST_VIS_NAME"); if (!vis_name || @@ -714,6 +727,7 @@ MediaPluginGStreamer010::load() } } } +#endif if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) { // instantiate a custom video sink diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 3c98cd5b85..24811db3cb 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1072,7 +1072,6 @@ set(viewer_HEADER_FILES llwearabletype.h llweb.h llwind.h - llwindebug.h llwlanimator.h llwldaycycle.h llwlparammanager.h @@ -1146,12 +1145,10 @@ endif (LINUX) if (WINDOWS) list(APPEND viewer_SOURCE_FILES llappviewerwin32.cpp - llwindebug.cpp ) list(APPEND viewer_HEADER_FILES llappviewerwin32.h - llwindebug.h ) # precompiled header configuration @@ -1708,6 +1705,29 @@ if (LINUX) add_dependencies(package linux-updater-target) check_message_template(package) endif (NOT INSTALL) + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched + COMMAND ${PYTHON_EXECUTABLE} + ARGS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + --arch=${ARCH} + --actions=copy + --artwork=${ARTWORK_DIR} + --build=${CMAKE_CURRENT_BINARY_DIR} + --buildtype=${CMAKE_BUILD_TYPE} + --configuration=${CMAKE_CFG_INTDIR} + --dest=${CMAKE_CURRENT_BINARY_DIR}/packaged + --grid=${GRID} + --source=${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py + ${COPY_INPUT_DEPENDENCIES} + COMMENT "Performing viewer_manifest copy" + ) + + add_custom_target(copy_l_viewer_manifest ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.copy_touched) + add_dependencies(copy_l_viewer_manifest "${VIEWER_BINARY_NAME}" linux-crash-logger-target linux-updater-target) endif (LINUX) if (DARWIN) @@ -1742,52 +1762,30 @@ if (DARWIN) DEPENDS ${VIEWER_BINARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit) + add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit mac-updater mac-crash-logger) if (PACKAGE) add_custom_target(package ALL DEPENDS ${VIEWER_BINARY_NAME}) check_message_template(package) - add_dependencies(package mac-updater mac-crash-logger) add_custom_command( TARGET package POST_BUILD COMMAND ${PYTHON_EXECUTABLE} ARGS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py - --grid=${GRID} - --buildtype=${CMAKE_BUILD_TYPE} - --configuration=${CMAKE_CFG_INTDIR} - --channel=${VIEWER_CHANNEL} - --login_channel=${VIEWER_LOGIN_CHANNEL} - --source=${CMAKE_CURRENT_SOURCE_DIR} --artwork=${ARTWORK_DIR} --build=${CMAKE_CURRENT_BINARY_DIR} - --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app - --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched - DEPENDS - ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py - ) - - - add_custom_command( - TARGET package POST_BUILD - COMMAND ${PYTHON_EXECUTABLE} - ARGS - ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py - --grid=${GRID} --buildtype=${CMAKE_BUILD_TYPE} - --configuration=${CMAKE_CFG_INTDIR} --channel=${VIEWER_CHANNEL} + --configuration=${CMAKE_CFG_INTDIR} + --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app + --grid=${GRID} --login_channel=${VIEWER_LOGIN_CHANNEL} --source=${CMAKE_CURRENT_SOURCE_DIR} - --artwork=${ARTWORK_DIR} - --build=${CMAKE_CURRENT_BINARY_DIR} - --dest=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app --touch=${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/.${product}.touched DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py ) - endif (PACKAGE) endif (DARWIN) @@ -1795,6 +1793,45 @@ if (INSTALL) include(${CMAKE_CURRENT_SOURCE_DIR}/ViewerInstall.cmake) endif (INSTALL) +if (PACKAGE) + if (WINDOWS) + set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") + set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-windows.tar.bz2") + set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe") + set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}") + set(VIEWER_COPY_MANIFEST copy_w_viewer_manifest) + endif (WINDOWS) + if (DARWIN) + set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app") + set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-darwin.tar.bz2") + set(VIEWER_EXE_GLOBS "'Second Life' SLPlugin") + set(VIEWER_LIB_GLOB "*.dylib") + endif (DARWIN) + if (LINUX) + set(VIEWER_DIST_DIR "${CMAKE_CURRENT_BINARY_DIR}/packaged") + set(VIEWER_SYMBOL_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/secondlife-symbols-linux.tar.bz2") + set(VIEWER_EXE_GLOBS "do-not-directly-run-secondlife-bin SLPlugin") + set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*") + set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest) + endif (LINUX) + + add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" + COMMAND "${PYTHON_EXECUTABLE}" + ARGS + "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" + "${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 ALL DEPENDS "${VIEWER_SYMBOL_FILE}") + add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}") + add_dependencies(package generate_breakpad_symbols) +endif (PACKAGE) + if (LL_TESTS) # To add a viewer unit test, just add the test .cpp file below # This creates a separate test project per file listed. diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index 4831dc7273..fc531f93d4 100644 --- a/indra/newview/English.lproj/InfoPlist.strings +++ b/indra/newview/English.lproj/InfoPlist.strings @@ -2,6 +2,6 @@ CFBundleName = "Second Life"; -CFBundleShortVersionString = "Second Life version 2.0.2.0"; -CFBundleGetInfoString = "Second Life version 2.0.2.0, Copyright 2004-2009 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version 2.1.0.0"; +CFBundleGetInfoString = "Second Life version 2.1.0.0, Copyright 2004-2009 Linden Research, Inc."; diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index fa2adac10c..97e24a0bd5 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -60,7 +60,7 @@ </dict> </array> <key>CFBundleVersion</key> - <string>2.0.2.0</string> + <string>2.1.0.0</string> <key>CSResourcesFileMapped</key> <true/> </dict> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index d4aebe6cb1..4506ee6e0c 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1,6 +1,17 @@ <?xml version="1.0" ?> <llsd> <map> + <key>CrashHostUrl</key> + <map> + <key>Comment</key> + <string>A URL pointing to a crash report handler; overrides cluster negotiation to locate crash handler.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string /> + </map> <key>AFKTimeout</key> <map> <key>Comment</key> diff --git a/indra/newview/generate_breakpad_symbols.py b/indra/newview/generate_breakpad_symbols.py new file mode 100644 index 0000000000..1f42004bb7 --- /dev/null +++ b/indra/newview/generate_breakpad_symbols.py @@ -0,0 +1,135 @@ +#!/usr/bin/env python +# @file generate_breakpad_symbols.py +# @author Brad Kittenbrink <brad@lindenlab.com> +# @brief Simple tool for generating google_breakpad symbol information +# for the crash reporter. +# +# $LicenseInfo:firstyear=2010&license=viewergpl$ +# +# Copyright (c) 2010-2010, Linden Research, Inc. +# +# Second Life Viewer Source Code +# The source code in this file ("Source Code") is provided by Linden Lab +# to you under the terms of the GNU General Public License, version 2.0 +# ("GPL"), unless you have obtained a separate licensing agreement +# ("Other License"), formally executed by you and Linden Lab. Terms of +# the GPL can be found in doc/GPL-license.txt in this distribution, or +# online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 +# +# There are special exceptions to the terms and conditions of the GPL as +# it is applied to this Source Code. View the full text of the exception +# in the file doc/FLOSS-exception.txt in this software distribution, or +# online at +# http://secondlifegrid.net/programs/open_source/licensing/flossexception +# +# By copying, modifying or distributing this software, you acknowledge +# that you have read and understood your obligations described above, +# and agree to abide by those obligations. +# +# ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO +# WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, +# COMPLETENESS OR PERFORMANCE. +# $/LicenseInfo$ + + +import collections +import fnmatch +import itertools +import operator +import os +import sys +import shlex +import subprocess +import tarfile +import StringIO + +def usage(): + print >>sys.stderr, "usage: %s viewer_dir viewer_exes libs_suffix dump_syms_tool viewer_symbol_file" % sys.argv[0] + +class MissingModuleError(Exception): + def __init__(self, modules): + Exception.__init__(self, "Failed to find required modules: %r" % modules) + self.modules = modules + +def main(viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file): + print "generate_breakpad_symbols run with args: %s" % str((viewer_dir, viewer_exes, libs_suffix, dump_syms_tool, viewer_symbol_file)) + + # split up list of viewer_exes + # "'Second Life' SLPlugin" becomes ['Second Life', 'SLPlugin'] + viewer_exes = shlex.split(viewer_exes) + + found_required = dict([(module, False) for module in viewer_exes]) + + def matches(f): + if f in viewer_exes: + found_required[f] = True + return True + return fnmatch.fnmatch(f, libs_suffix) + + def list_files(): + for (dirname, subdirs, filenames) in os.walk(viewer_dir): + #print "scanning '%s' for modules..." % dirname + for f in itertools.ifilter(matches, filenames): + yield os.path.join(dirname, f) + + def dump_module(m): + print "dumping module '%s' with '%s'..." % (m, dump_syms_tool) + child = subprocess.Popen([dump_syms_tool, m] , stdout=subprocess.PIPE) + out, err = child.communicate() + return (m,child.returncode, out, err) + + out = tarfile.open(viewer_symbol_file, 'w:bz2') + + for (filename,status,symbols,err) in itertools.imap(dump_module, list_files()): + if status == 0: + module_line = symbols[:symbols.index('\n')] + module_line = module_line.split() + hash_id = module_line[3] + module = ' '.join(module_line[4:]) + if sys.platform in ['win32', 'cygwin']: + mod_name = module[:module.rindex('.pdb')] + else: + mod_name = module + symbolfile = StringIO.StringIO(symbols) + info = tarfile.TarInfo("%(module)s/%(hash_id)s/%(mod_name)s.sym" % dict(module=module, hash_id=hash_id, mod_name=mod_name)) + info.size = symbolfile.len + out.addfile(info, symbolfile) + else: + print >>sys.stderr, "warning: failed to dump symbols for '%s': %s" % (filename, err) + + out.close() + + missing_modules = [m for (m,_) in + itertools.ifilter(lambda (k,v): not v, found_required.iteritems()) + ] + if missing_modules: + print >> sys.stderr, "failed to generate %s" % viewer_symbol_file + os.remove(viewer_symbol_file) + raise MissingModuleError(missing_modules) + + symbols = tarfile.open(viewer_symbol_file, 'r:bz2') + tarfile_members = symbols.getnames() + symbols.close() + + for required_module in viewer_exes: + def match_module_basename(m): + return os.path.splitext(required_module)[0].lower() \ + == os.path.splitext(os.path.basename(m))[0].lower() + # there must be at least one .sym file in tarfile_members that matches + # each required module (ignoring file extensions) + if not reduce(operator.or_, itertools.imap(match_module_basename, tarfile_members)): + print >> sys.stderr, "failed to find required %s in generated %s" \ + % (required_module, viewer_symbol_file) + os.remove(viewer_symbol_file) + raise MissingModuleError([required_module]) + + print "successfully generated %s including required modules '%s'" % (viewer_symbol_file, viewer_exes) + + return 0 + +if __name__ == "__main__": + if len(sys.argv) != 6: + usage() + sys.exit(1) + sys.exit(main(*sys.argv[1:])) + diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index c3f075fd49..977f1c9fa8 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -2312,12 +2312,6 @@ void LLAgentCamera::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL came startCameraAnimation(); } - // Remove any pitch from the avatar - //LLVector3 at = gAgent.getFrameAgent().getAtAxis(); - //at.mV[VZ] = 0.f; - //at.normalize(); - //gAgent.resetAxes(at); - if (mCameraMode != CAMERA_MODE_CUSTOMIZE_AVATAR) { updateLastCamera(); @@ -2338,9 +2332,11 @@ void LLAgentCamera::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL came if (isAgentAvatarValid()) { if(avatar_animate) - { - // Remove any pitch from the avatar - LLVector3 at = gAgent.getFrameAgent().getAtAxis(); + { + // slamming the avatar's axis to the camera so that when the rotation + // completes it correctly points to the front of the avatar + // Remove any pitch or rotation from the avatar + LLVector3 at = LLViewerCamera::getInstance()->getAtAxis(); at.mV[VZ] = 0.f; at.normalize(); gAgent.resetAxes(at); @@ -2360,6 +2356,10 @@ void LLAgentCamera::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL came mAnimationDuration = gSavedSettings.getF32("ZoomTime"); } } + + // this is what sets the avatar as the mFocusTargetGlobal + setFocusGlobal(LLVector3d::zero); + gAgentAvatarp->updateMeshTextures(); } else diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 342f9a5d80..557b3b0a77 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -2099,7 +2099,19 @@ void LLAgentWearables::populateMyOutfitsFolder(void) } } +boost::signals2::connection LLAgentWearables::addLoadingStartedCallback(loading_started_callback_t cb) +{ + return mLoadingStartedSignal.connect(cb); +} + boost::signals2::connection LLAgentWearables::addLoadedCallback(loaded_callback_t cb) { return mLoadedSignal.connect(cb); } + +void LLAgentWearables::notifyLoadingStarted() +{ + mLoadingStartedSignal(); +} + +// EOF diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index a41b949be6..3295544e04 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -224,11 +224,18 @@ public: // Signals //-------------------------------------------------------------------- public: + typedef boost::function<void()> loading_started_callback_t; + typedef boost::signals2::signal<void()> loading_started_signal_t; + boost::signals2::connection addLoadingStartedCallback(loading_started_callback_t cb); + typedef boost::function<void()> loaded_callback_t; typedef boost::signals2::signal<void()> loaded_signal_t; boost::signals2::connection addLoadedCallback(loaded_callback_t cb); + void notifyLoadingStarted(); + private: + loading_started_signal_t mLoadingStartedSignal; // should be called before wearables are changed loaded_signal_t mLoadedSignal; // emitted when all agent wearables get loaded //-------------------------------------------------------------------- diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 12d2752180..a7206095d3 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -644,6 +644,13 @@ const LLViewerInventoryItem* LLAppearanceMgr::getBaseOutfitLink() const LLViewerInventoryCategory *cat = item->getLinkedCategory(); if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) { + const LLUUID parent_id = cat->getParentUUID(); + LLViewerInventoryCategory* parent_cat = gInventory.getCategory(parent_id); + // if base outfit moved to trash it means that we don't have base outfit + if (parent_cat != NULL && parent_cat->getPreferredType() == LLFolderType::FT_TRASH) + { + return NULL; + } return item; } } @@ -965,18 +972,10 @@ bool LLAppearanceMgr::getCanRemoveOutfit(const LLUUID& outfit_cat_id) return false; } - // Check if the folder contains worn items. - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLFindWorn filter_worn; - gInventory.collectDescendentsIf(outfit_cat_id, cats, items, false, filter_worn); - if (!items.empty()) - { - return false; - } - // Check for the folder's non-removable descendants. LLFindNonRemovableObjects filter_non_removable; + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; LLInventoryModel::item_array_t::const_iterator it; gInventory.collectDescendentsIf(outfit_cat_id, cats, items, false, filter_non_removable); if (!cats.empty() || !items.empty()) @@ -1408,6 +1407,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category, void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append) { + gAgentWearables.notifyLoadingStarted(); if(!category) return; llinfos << "wearInventoryCategory( " << category->getName() @@ -2000,13 +2000,19 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id) class LLShowCreatedOutfit: public LLInventoryCallback { public: - LLShowCreatedOutfit(LLUUID& folder_id): mFolderID(folder_id) + LLShowCreatedOutfit(LLUUID& folder_id, bool show_panel = true): mFolderID(folder_id), mShowPanel(show_panel) {} virtual ~LLShowCreatedOutfit() { LLSD key; - LLSideTray::getInstance()->showPanel("panel_outfits_inventory", key); + + //EXT-7727. For new accounts LLShowCreatedOutfit is created during login process + // add may be processed after login process is finished + if (mShowPanel) + { + LLSideTray::getInstance()->showPanel("panel_outfits_inventory", key); + } LLPanelOutfitsInventory *outfit_panel = dynamic_cast<LLPanelOutfitsInventory*>(LLSideTray::getInstance()->getPanel("panel_outfits_inventory")); if (outfit_panel) @@ -2030,9 +2036,10 @@ public: private: LLUUID mFolderID; + bool mShowPanel; }; -LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name) +LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, bool show_panel) { if (!isAgentAvatarValid()) return LLUUID::null; @@ -2045,7 +2052,7 @@ LLUUID LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name) updateClothingOrderingInfo(); - LLPointer<LLInventoryCallback> cb = new LLShowCreatedOutfit(folder_id); + LLPointer<LLInventoryCallback> cb = new LLShowCreatedOutfit(folder_id,show_panel); shallowCopyCategoryContents(getCOF(),folder_id, cb); createBaseOutfitLink(folder_id, cb); diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 2227a43cd8..e42f9f7d6f 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -151,7 +151,7 @@ public: void removeItemFromAvatar(const LLUUID& item_id); - LLUUID makeNewOutfitLinks(const std::string& new_folder_name); + LLUUID makeNewOutfitLinks(const std::string& new_folder_name,bool show_panel = true); bool moveWearable(LLViewerInventoryItem* item, bool closer_to_body); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 82bd59d25c..f4004d5664 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -103,8 +103,8 @@ // Third party library includes #include <boost/bind.hpp> + #if LL_WINDOWS - #include "llwindebug.h" # include <share.h> // For _SH_DENYWR in initMarkerFile #else # include <sys/file.h> // For initMarkerFile support @@ -599,6 +599,11 @@ bool LLAppViewer::init() if (!initConfiguration()) return false; + // write Google Breakpad minidump files to our log directory + std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + logdir += gDirUtilp->getDirDelimiter(); + setMiniDumpDir(logdir); + // Although initLogging() is the right place to mess with // setFatalFunction(), we can't query gSavedSettings until after // initConfiguration(). @@ -1239,6 +1244,14 @@ bool LLAppViewer::cleanup() // workaround for DEV-35406 crash on shutdown LLEventPumps::instance().reset(); + // remove any old breakpad minidump files from the log directory + if (! isError()) + { + std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ""); + logdir += gDirUtilp->getDirDelimiter(); + gDirUtilp->deleteFilesInDir(logdir, "*-*-*-*-*.dmp"); + } + // *TODO - generalize this and move DSO wrangling to a helper class -brad std::set<struct apr_dso_handle_t *>::const_iterator i; for(i = mPlugins.begin(); i != mPlugins.end(); ++i) @@ -2295,17 +2308,7 @@ void LLAppViewer::checkForCrash(void) { #if LL_SEND_CRASH_REPORTS - //*NOTE:Mani The current state of the crash handler has the MacOSX - // sending all crash reports as freezes, in order to let - // the MacOSX CrashRepoter generate stacks before spawning the - // SL crash logger. - // The Linux and Windows clients generate their own stacks and - // spawn the SL crash logger immediately. This may change in the future. -#if LL_DARWIN - if(gLastExecEvent != LAST_EXEC_NORMAL) -#else if (gLastExecEvent == LAST_EXEC_FROZE) -#endif { llinfos << "Last execution froze, requesting to send crash report." << llendl; // @@ -2515,6 +2518,15 @@ void LLAppViewer::writeSystemInfo() // If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze, // then the value of "CrashNotHandled" will be set to true. gDebugInfo["CrashNotHandled"] = (LLSD::Boolean)true; + + // Insert crash host url (url to post crash log to) if configured. This insures + // that the crash report will go to the proper location in the case of a + // prior freeze. + std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl"); + if(crashHostUrl != "") + { + gDebugInfo["CrashHostUrl"] = crashHostUrl; + } // Dump some debugging info LL_INFOS("SystemInfo") << LLTrans::getString("APP_NAME") @@ -2536,13 +2548,6 @@ void LLAppViewer::writeSystemInfo() writeDebugInfo(); // Save out debug_info.log early, in case of crash. } -void LLAppViewer::handleSyncViewerCrash() -{ - LLAppViewer* pApp = LLAppViewer::instance(); - // Call to pure virtual, handled by platform specific llappviewer instance. - pApp->handleSyncCrashTrace(); -} - void LLAppViewer::handleViewerCrash() { llinfos << "Handle viewer crash entry." << llendl; @@ -2566,9 +2571,13 @@ void LLAppViewer::handleViewerCrash() return; } pApp->mReportedCrash = TRUE; - - // Make sure the watchdog gets turned off... -// pApp->destroyMainloopTimeout(); // SJB: Bah. This causes the crash handler to hang, not sure why. + + // Insert crash host url (url to post crash log to) if configured. + std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl"); + if(crashHostUrl != "") + { + gDebugInfo["CrashHostUrl"] = crashHostUrl; + } //We already do this in writeSystemInfo(), but we do it again here to make /sure/ we have a version //to check against no matter what @@ -2600,6 +2609,12 @@ void LLAppViewer::handleViewerCrash() gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin(); gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); + char *minidump_file = pApp->getMiniDumpFilename(); + if(minidump_file && minidump_file[0] != 0) + { + gDebugInfo["MinidumpPath"] = minidump_file; + } + if(gLogoutInProgress) { gDebugInfo["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH; @@ -2677,10 +2692,6 @@ void LLAppViewer::handleViewerCrash() LLError::logToFile(""); -// On Mac, we send the report on the next run, since we need macs crash report -// for a stack trace, so we have to let it the app fail. -#if !LL_DARWIN - // Remove the marker file, since otherwise we'll spawn a process that'll keep it locked if(gDebugInfo["LastExecEvent"].asInteger() == LAST_EXEC_LOGOUT_CRASH) { @@ -2693,8 +2704,6 @@ void LLAppViewer::handleViewerCrash() // Call to pure virtual, handled by platform specific llappviewer instance. pApp->handleCrashReporting(); - -#endif //!LL_DARWIN return; } @@ -3338,13 +3347,6 @@ void LLAppViewer::badNetworkHandler() mPurgeOnExit = TRUE; -#if LL_WINDOWS - // Generates the minidump. - LLWinDebug::generateCrashStacks(NULL); -#endif - LLAppViewer::handleSyncViewerCrash(); - LLAppViewer::handleViewerCrash(); - std::ostringstream message; message << "The viewer has detected mangled network data indicative\n" @@ -3357,6 +3359,8 @@ void LLAppViewer::badNetworkHandler() "If the problem continues, see the Tech Support FAQ at: \n" "www.secondlife.com/support"; forceDisconnect(message.str()); + + LLApp::instance()->writeMiniDump(); } // This routine may get called more than once during the shutdown process. diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 5acd6e11c4..0b862a92a1 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -92,9 +92,7 @@ public: virtual bool restoreErrorTrap() = 0; // Require platform specific override to reset error handling mechanism. // return false if the error trap needed restoration. virtual void handleCrashReporting(bool reportFreeze = false) = 0; // What to do with crash report? - virtual void handleSyncCrashTrace() = 0; // any low-level crash-prep that has to happen in the context of the crashing thread before the crash report is delivered. static void handleViewerCrash(); // Hey! The viewer crashed. Do this, soon. - static void handleSyncViewerCrash(); // Hey! The viewer crashed. Do this right NOW in the context of the crashing thread. void checkForCrash(); // Thread accessors diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp index 78b0f7ba83..78afdc8995 100644 --- a/indra/newview/llappviewerlinux.cpp +++ b/indra/newview/llappviewerlinux.cpp @@ -46,23 +46,6 @@ #include <exception> -#if LL_LINUX -# include <dlfcn.h> // RTLD_LAZY -# include <execinfo.h> // backtrace - glibc only -#elif LL_SOLARIS -# include <sys/types.h> -# include <unistd.h> -# include <fcntl.h> -# include <ucontext.h> -#endif - -#ifdef LL_ELFBIN -# ifdef __GNUC__ -# include <cxxabi.h> // for symbol demangling -# endif -# include "ELFIO/ELFIO.h" // for better backtraces -#endif - #if LL_DBUS_ENABLED # include "llappviewerlinux_api_dbus.h" @@ -86,7 +69,6 @@ static void exceptionTerminateHandler() // reinstall default terminate() handler in case we re-terminate. if (gOldTerminateHandler) std::set_terminate(gOldTerminateHandler); // treat this like a regular viewer crash, with nice stacktrace etc. - LLAppViewer::handleSyncViewerCrash(); LLAppViewer::handleViewerCrash(); // we've probably been killed-off before now, but... gOldTerminateHandler(); // call old terminate() handler @@ -109,7 +91,6 @@ int main( int argc, char **argv ) gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler); // install crash handlers viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); - viewer_app_ptr->setSyncErrorHandler(LLAppViewer::handleSyncViewerCrash); bool ok = viewer_app_ptr->init(); if(!ok) @@ -138,201 +119,6 @@ int main( int argc, char **argv ) return 0; } -#ifdef LL_SOLARIS -static inline BOOL do_basic_glibc_backtrace() -{ - BOOL success = FALSE; - - std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); - llinfos << "Opening stack trace file " << strace_filename << llendl; - LLFILE* StraceFile = LLFile::fopen(strace_filename, "w"); - if (!StraceFile) - { - llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl; - StraceFile = stderr; - } - - printstack(fileno(StraceFile)); - - if (StraceFile != stderr) - fclose(StraceFile); - - return success; -} -#else -#define MAX_STACK_TRACE_DEPTH 40 -// This uses glibc's basic built-in stack-trace functions for a not very -// amazing backtrace. -static inline BOOL do_basic_glibc_backtrace() -{ - void *stackarray[MAX_STACK_TRACE_DEPTH]; - size_t size; - char **strings; - size_t i; - BOOL success = FALSE; - - size = backtrace(stackarray, MAX_STACK_TRACE_DEPTH); - strings = backtrace_symbols(stackarray, size); - - std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); - llinfos << "Opening stack trace file " << strace_filename << llendl; - LLFILE* StraceFile = LLFile::fopen(strace_filename, "w"); // Flawfinder: ignore - if (!StraceFile) - { - llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl; - StraceFile = stderr; - } - - if (size) - { - for (i = 0; i < size; i++) - { - // the format of the StraceFile is very specific, to allow (kludgy) machine-parsing - fprintf(StraceFile, "%-3lu ", (unsigned long)i); - fprintf(StraceFile, "%-32s\t", "unknown"); - fprintf(StraceFile, "%p ", stackarray[i]); - fprintf(StraceFile, "%s\n", strings[i]); - } - - success = TRUE; - } - - if (StraceFile != stderr) - fclose(StraceFile); - - free (strings); - return success; -} - -#if LL_ELFBIN -// This uses glibc's basic built-in stack-trace functions together with -// ELFIO's ability to parse the .symtab ELF section for better symbol -// extraction without exporting symbols (which'd cause subtle, fatal bugs). -static inline BOOL do_elfio_glibc_backtrace() -{ - void *stackarray[MAX_STACK_TRACE_DEPTH]; - size_t btsize; - char **strings; - BOOL success = FALSE; - - std::string appfilename = gDirUtilp->getExecutablePathAndName(); - - std::string strace_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); - llinfos << "Opening stack trace file " << strace_filename << llendl; - LLFILE* StraceFile = LLFile::fopen(strace_filename, "w"); // Flawfinder: ignore - if (!StraceFile) - { - llinfos << "Opening stack trace file " << strace_filename << " failed. Using stderr." << llendl; - StraceFile = stderr; - } - - // get backtrace address list and basic symbol info - btsize = backtrace(stackarray, MAX_STACK_TRACE_DEPTH); - strings = backtrace_symbols(stackarray, btsize); - - // create ELF reader for our app binary - IELFI* pReader; - const IELFISection* pSec = NULL; - IELFISymbolTable* pSymTbl = 0; - if (ERR_ELFIO_NO_ERROR != ELFIO::GetInstance()->CreateELFI(&pReader) || - ERR_ELFIO_NO_ERROR != pReader->Load(appfilename.c_str()) || - // find symbol table, create reader-object - NULL == (pSec = pReader->GetSection( ".symtab" )) || - ERR_ELFIO_NO_ERROR != pReader->CreateSectionReader(IELFI::ELFI_SYMBOL, pSec, (void**)&pSymTbl) ) - { - // Failed to open our binary and read its symbol table somehow - llinfos << "Could not initialize ELF symbol reading - doing basic backtrace." << llendl; - if (StraceFile != stderr) - fclose(StraceFile); - // note that we may be leaking some of the above ELFIO - // objects now, but it's expected that we'll be dead soon - // and we want to tread delicately until we get *some* kind - // of useful backtrace. - return do_basic_glibc_backtrace(); - } - - // iterate over trace and symtab, looking for plausible symbols - std::string name; - Elf32_Addr value; - Elf32_Word ssize; - unsigned char bind; - unsigned char type; - Elf32_Half section; - int nSymNo = pSymTbl->GetSymbolNum(); - size_t btpos; - for (btpos = 0; btpos < btsize; ++btpos) - { - // the format of the StraceFile is very specific, to allow (kludgy) machine-parsing - fprintf(StraceFile, "%-3ld ", (long)btpos); - int symidx; - for (symidx = 0; symidx < nSymNo; ++symidx) - { - if (ERR_ELFIO_NO_ERROR == - pSymTbl->GetSymbol(symidx, name, value, ssize, - bind, type, section)) - { - // check if trace address within symbol range - if (uintptr_t(stackarray[btpos]) >= value && - uintptr_t(stackarray[btpos]) < value+ssize) - { - // symbol is inside viewer - fprintf(StraceFile, "%-32s\t", "com.secondlife.indra.viewer"); - fprintf(StraceFile, "%p ", stackarray[btpos]); - - char *demangled_str = NULL; - int demangle_result = 1; - demangled_str = - abi::__cxa_demangle - (name.c_str(), NULL, NULL, - &demangle_result); - if (0 == demangle_result && - NULL != demangled_str) { - fprintf(StraceFile, - "%s", demangled_str); - free(demangled_str); - } - else // failed demangle; print it raw - { - fprintf(StraceFile, - "%s", name.c_str()); - } - // print offset from symbol start - fprintf(StraceFile, - " + %lu\n", - uintptr_t(stackarray[btpos]) - - value); - goto got_sym; // early escape - } - } - } - // Fallback: - // Didn't find a suitable symbol in the binary - it's probably - // a symbol in a DSO; use glibc's idea of what it should be. - fprintf(StraceFile, "%-32s\t", "unknown"); - fprintf(StraceFile, "%p ", stackarray[btpos]); - fprintf(StraceFile, "%s\n", strings[btpos]); - got_sym:; - } - - if (StraceFile != stderr) - fclose(StraceFile); - - pSymTbl->Release(); - pSec->Release(); - pReader->Release(); - - free(strings); - - llinfos << "Finished generating stack trace." << llendl; - - success = TRUE; - return success; -} -#endif // LL_ELFBIN - -#endif // LL_SOLARIS - - LLAppViewerLinux::LLAppViewerLinux() { } @@ -541,16 +327,6 @@ bool LLAppViewerLinux::sendURLToOtherInstance(const std::string& url) } #endif // LL_DBUS_ENABLED -void LLAppViewerLinux::handleSyncCrashTrace() -{ - // This backtrace writes into stack_trace.log -# if LL_ELFBIN - do_elfio_glibc_backtrace(); // more useful backtrace -# else - do_basic_glibc_backtrace(); // only slightly useful backtrace -# endif // LL_ELFBIN -} - void LLAppViewerLinux::handleCrashReporting(bool reportFreeze) { std::string cmd =gDirUtilp->getExecutableDir(); @@ -686,6 +462,8 @@ bool LLAppViewerLinux::beingDebugged() bool LLAppViewerLinux::initLogging() { // Remove the last stack trace, if any + // This file is no longer created, since the move to Google Breakpad + // The code is left here to clean out any old state in the log dir std::string old_stack_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"stack_trace.log"); LLFile::remove(old_stack_file); diff --git a/indra/newview/llappviewerlinux.h b/indra/newview/llappviewerlinux.h index 230c0dc24b..b17380d4d8 100644 --- a/indra/newview/llappviewerlinux.h +++ b/indra/newview/llappviewerlinux.h @@ -68,7 +68,6 @@ protected: virtual bool restoreErrorTrap(); virtual void handleCrashReporting(bool reportFreeze); - virtual void handleSyncCrashTrace(); virtual bool initLogging(); virtual bool initParseCommandLine(LLCommandLineParser& clp); diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 0b5f18c330..1e66e55f3d 100644 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -264,11 +264,6 @@ bool LLAppViewerMacOSX::restoreErrorTrap() return reset_count == 0; } -void LLAppViewerMacOSX::handleSyncCrashTrace() -{ - // do nothing -} - static OSStatus CarbonEventHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void* inUserData) @@ -384,38 +379,6 @@ void LLAppViewerMacOSX::handleCrashReporting(bool reportFreeze) } } - - if(!reportFreeze) - { - _exit(1); - } - - // TODO from palmer: Find a better way to handle managing old crash logs - // when this is a separate imbedable module. Ideally just sort crash stack - // logs based on date, and grab the latest one as opposed to deleting them - // for thoughts on what the module would look like. - // See: https://wiki.lindenlab.com/wiki/Viewer_Crash_Reporter_Round_4 - - // Remove the crash stack log from previous executions. - // Since we've started logging a new instance of the app, we can assume - // The old crash stack is invalid for the next crash report. - char path[MAX_PATH]; - FSRef folder; - if(FSFindFolder(kUserDomain, kLogsFolderType, false, &folder) == noErr) - { - // folder is an FSRef to ~/Library/Logs/ - if(FSRefMakePath(&folder, (UInt8*)&path, sizeof(path)) == noErr) - { - std::string pathname = std::string(path) + std::string("/CrashReporter/"); - std::string mask = "Second Life*"; - std::string file_name; - while(gDirUtilp->getNextFileInDir(pathname, mask, file_name, false)) - { - LLFile::remove(pathname + file_name); - } - } - } - } std::string LLAppViewerMacOSX::generateSerialNumber() diff --git a/indra/newview/llappviewermacosx.h b/indra/newview/llappviewermacosx.h index cbf7e6c209..3d7bb55556 100644 --- a/indra/newview/llappviewermacosx.h +++ b/indra/newview/llappviewermacosx.h @@ -55,7 +55,6 @@ public: protected: virtual bool restoreErrorTrap(); virtual void handleCrashReporting(bool reportFreeze); - virtual void handleSyncCrashTrace(); std::string generateSerialNumber(); virtual bool initParseCommandLine(LLCommandLineParser& clp); diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 60a6d2f072..e3ef04d03d 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -57,8 +57,6 @@ #include "llweb.h" #include "llsecondlifeurls.h" -#include "llwindebug.h" - #include "llviewernetwork.h" #include "llmd5.h" #include "llfindlocale.h" @@ -81,51 +79,6 @@ extern "C" { const std::string LLAppViewerWin32::sWindowClass = "Second Life"; -LONG WINAPI viewer_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop) -{ - // *NOTE:Mani - this code is stolen from LLApp, where its never actually used. - //OSMessageBox("Attach Debugger Now", "Error", OSMB_OK); - // *TODO: Translate the signals/exceptions into cross-platform stuff - // Windows implementation - _tprintf( _T("Entering Windows Exception Handler...\n") ); - llinfos << "Entering Windows Exception Handler..." << llendl; - - // Make sure the user sees something to indicate that the app crashed. - LONG retval; - - if (LLApp::isError()) - { - _tprintf( _T("Got another fatal signal while in the error handler, die now!\n") ); - llwarns << "Got another fatal signal while in the error handler, die now!" << llendl; - - retval = EXCEPTION_EXECUTE_HANDLER; - return retval; - } - - // Generate a minidump if we can. - // Before we wake the error thread... - // Which will start the crash reporting. - LLWinDebug::generateCrashStacks(exception_infop); - - // Flag status to error, so thread_error starts its work - LLApp::setError(); - - // Block in the exception handler until the app has stopped - // This is pretty sketchy, but appears to work just fine - while (!LLApp::isStopped()) - { - ms_sleep(10); - } - - // - // At this point, we always want to exit the app. There's no graceful - // recovery for an unhandled exception. - // - // Just kill the process. - retval = EXCEPTION_EXECUTE_HANDLER; - return retval; -} - // Create app mutex creates a unique global windows object. // If the object can be created it returns true, otherwise // it returns false. The false result can be used to determine @@ -191,8 +144,6 @@ int APIENTRY WINMAIN(HINSTANCE hInstance, gIconResource = MAKEINTRESOURCE(IDI_LL_ICON); LLAppViewerWin32* viewer_app_ptr = new LLAppViewerWin32(lpCmdLine); - - LLWinDebug::initExceptionHandler(viewer_windows_exception_handler); viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash); @@ -405,12 +356,6 @@ bool LLAppViewerWin32::cleanup() bool LLAppViewerWin32::initLogging() { - // Remove the crash stack log from previous executions. - // Since we've started logging a new instance of the app, we can assume - // *NOTE: This should happen before the we send a 'previous instance froze' - // crash report, but it must happen after we initialize the DirUtil. - LLWinDebug::clearCrashStacks(); - return LLAppViewer::initLogging(); } @@ -529,13 +474,9 @@ bool LLAppViewerWin32::initParseCommandLine(LLCommandLineParser& clp) } bool LLAppViewerWin32::restoreErrorTrap() -{ - return LLWinDebug::checkExceptionHandler(); -} - -void LLAppViewerWin32::handleSyncCrashTrace() -{ - // do nothing +{ + return true; + //return LLWinDebug::checkExceptionHandler(); } void LLAppViewerWin32::handleCrashReporting(bool reportFreeze) diff --git a/indra/newview/llappviewerwin32.h b/indra/newview/llappviewerwin32.h index 13454edeec..52dcc583a4 100644 --- a/indra/newview/llappviewerwin32.h +++ b/indra/newview/llappviewerwin32.h @@ -57,7 +57,6 @@ protected: virtual bool restoreErrorTrap(); virtual void handleCrashReporting(bool reportFreeze); - virtual void handleSyncCrashTrace(); virtual bool sendURLToOtherInstance(const std::string& url); diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 27dcb9f1c7..116c4cafc2 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -203,19 +203,13 @@ void LLAssetUploadResponder::uploadComplete(const LLSD& content) LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data, const LLUUID& vfile_id, - LLAssetType::EType asset_type, - boost::function<void(const LLUUID& uuid)> callback) -: LLAssetUploadResponder(post_data, vfile_id, asset_type), - mCallback(callback) + LLAssetType::EType asset_type) +: LLAssetUploadResponder(post_data, vfile_id, asset_type) { } -LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data, - const std::string& file_name, - LLAssetType::EType asset_type, - boost::function<void(const LLUUID& uuid)> callback) -: LLAssetUploadResponder(post_data, file_name, asset_type), - mCallback(callback) +LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name, LLAssetType::EType asset_type) +: LLAssetUploadResponder(post_data, file_name, asset_type) { } @@ -293,12 +287,6 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) creation_date_now); gInventory.updateItem(item); gInventory.notifyObservers(); - - if (mCallback) - { - // call the callback with the new Asset UUID - mCallback(item->getAssetUUID()); - } // Show the preview panel for textures and sounds to let // user know that the image (or snapshot) arrived intact. @@ -346,11 +334,13 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) U32 group_perms = mPostData.has("group_mask") ? mPostData.get("group_mask" ).asInteger() : PERM_NONE; U32 next_owner_perms = mPostData.has("next_owner_mask") ? mPostData.get("next_owner_mask").asInteger() : PERM_NONE; std::string display_name = LLStringUtil::null; + LLAssetStorage::LLStoreAssetCallback callback = NULL; + void *userdata = NULL; upload_new_resource(next_file, asset_name, asset_name, - LLFolderType::FT_NONE, LLInventoryType::IT_NONE, + 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, next_owner_perms, group_perms, everyone_perms, display_name, - NULL, expected_upload_cost); + callback, expected_upload_cost, userdata); } } diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h index 2358aeb39d..91fb39916d 100644 --- a/indra/newview/llassetuploadresponders.h +++ b/indra/newview/llassetuploadresponders.h @@ -33,7 +33,6 @@ #ifndef LL_LLASSETUPLOADRESPONDER_H #define LL_LLASSETUPLOADRESPONDER_H -#include "llassetstorage.h" #include "llhttpclient.h" // Abstract class for supporting asset upload @@ -67,15 +66,10 @@ class LLNewAgentInventoryResponder : public LLAssetUploadResponder public: LLNewAgentInventoryResponder(const LLSD& post_data, const LLUUID& vfile_id, - LLAssetType::EType asset_type, - boost::function<void(const LLUUID& uuid)> callback = NULL); - LLNewAgentInventoryResponder(const LLSD& post_data, - const std::string& file_name, - LLAssetType::EType asset_type, - boost::function<void(const LLUUID& uuid)> callback = NULL); + LLAssetType::EType asset_type); + LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name, + LLAssetType::EType asset_type); virtual void uploadComplete(const LLSD& content); - - boost::function<void(const LLUUID& uuid)> mCallback; }; struct LLBakedUploadData; diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 0bd03571da..18c69b5130 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -243,7 +243,7 @@ public: gCacheName->get(mAvatarID, FALSE, boost::bind(&LLChatHistoryHeader::nameUpdatedCallback, this, _1, _2, _3, _4)); //*TODO overly defensive thing, source type should be maintained out there - if((chat.mFromID.isNull() && chat.mFromName.empty()) || chat.mFromName == SYSTEM_FROM) + if((chat.mFromID.isNull() && chat.mFromName.empty()) || chat.mFromName == SYSTEM_FROM && chat.mFromID.isNull()) { mSourceType = CHAT_SOURCE_SYSTEM; } @@ -667,7 +667,7 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL // (don't let object names with hyperlinks override our objectim Url) LLStyle::Params link_params(style_params); link_params.color.control = "HTMLLinkColor"; - link_params.link_href = url; + link_params.link_href = LLURI::escape(url); mEditor->appendText("<nolink>" + chat.mFromName + "</nolink>" + delimiter, false, link_params); } diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index 043f753e01..f14e64e3e4 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -1001,18 +1001,19 @@ void LLFloaterAnimPreview::onBtnOK(void* userdata) { std::string name = floaterp->childGetValue("name_form").asString(); std::string desc = floaterp->childGetValue("description_form").asString(); + LLAssetStorage::LLStoreAssetCallback callback = NULL; S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + void *userdata = NULL; upload_new_resource(floaterp->mTransactionID, // tid LLAssetType::AT_ANIMATION, name, desc, + 0, LLFolderType::FT_NONE, LLInventoryType::IT_ANIMATION, - LLFloaterPerms::getNextOwnerPerms(), - LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), + LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), name, - NULL, - expected_upload_cost); + callback, expected_upload_cost, userdata); } else { diff --git a/indra/newview/llfloaterbuycurrencyhtml.cpp b/indra/newview/llfloaterbuycurrencyhtml.cpp index 5815df36d1..7f41a64064 100644 --- a/indra/newview/llfloaterbuycurrencyhtml.cpp +++ b/indra/newview/llfloaterbuycurrencyhtml.cpp @@ -87,6 +87,9 @@ void LLFloaterBuyCurrencyHTML::navigateToFinalURL() replace[ "[MSG]" ] = LLURI::escape( mMessage ); LLStringUtil::format( buy_currency_url, replace ); + // write final URL to debug console + llinfos << "Buy currency HTML prased URL is " << buy_currency_url << llendl; + // kick off the navigation mBrowser->navigateTo( buy_currency_url ); } @@ -98,6 +101,9 @@ void LLFloaterBuyCurrencyHTML::handleMediaEvent( LLPluginClassMedia* self, EMedi // placeholder for now - just in case we want to catch media events if ( LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_COMPLETE == event ) { + // update currency after we complete a navigation since there are many ways + // this can result in a different L$ balance + LLStatusBar::sendMoneyBalanceRequest(); }; } @@ -105,6 +111,9 @@ void LLFloaterBuyCurrencyHTML::handleMediaEvent( LLPluginClassMedia* self, EMedi // void LLFloaterBuyCurrencyHTML::onClose( bool app_quitting ) { + // update L$ balanace one more time + LLStatusBar::sendMoneyBalanceRequest(); + destroy(); } diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp index 5c343ecb22..159ce41b79 100644 --- a/indra/newview/llfloaternamedesc.cpp +++ b/indra/newview/llfloaternamedesc.cpp @@ -169,14 +169,16 @@ void LLFloaterNameDesc::onBtnOK( ) { childDisable("ok_btn"); // don't allow inadvertent extra uploads + LLAssetStorage::LLStoreAssetCallback callback = NULL; S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); // kinda hack - assumes that unsubclassed LLFloaterNameDesc is only used for uploading chargeable assets, which it is right now (it's only used unsubclassed for the sound upload dialog, and THAT should be a subclass). + void *nruserdata = NULL; std::string display_name = LLStringUtil::null; upload_new_resource(mFilenameAndPath, // file childGetValue("name_form").asString(), childGetValue("description_form").asString(), - LLFolderType::FT_NONE, LLInventoryType::IT_NONE, + 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), - display_name, NULL, expected_upload_cost); + display_name, callback, expected_upload_cost, nruserdata); closeFloater(false); } diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 00981d3c25..f3baa482a0 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -39,33 +39,28 @@ // Viewer includes #include "llagent.h" #include "llagentcamera.h" -#include "llagentui.h" -#include "llavatarpropertiesprocessor.h" -#include "llbottomtray.h" -#include "llbutton.h" #include "llcallbacklist.h" -#include "llcheckboxctrl.h" -#include "llcombobox.h" #include "llcriticaldamp.h" -#include "lleconomy.h" -#include "llfloaterpostcard.h" +#include "llui.h" #include "llfocusmgr.h" -#include "lllandmarkactions.h" -#include "llradiogroup.h" +#include "llbutton.h" +#include "llcombobox.h" +#include "lleconomy.h" #include "llsliderctrl.h" -#include "llslurl.h" #include "llspinctrl.h" -#include "lltoolfocus.h" -#include "lltoolmgr.h" -#include "llui.h" -#include "lluictrlfactory.h" -#include "llviewercamera.h" #include "llviewercontrol.h" -#include "llviewermenufile.h" // upload_new_resource() +#include "lluictrlfactory.h" #include "llviewerstats.h" +#include "llviewercamera.h" #include "llviewerwindow.h" -#include "llweb.h" +#include "llviewermenufile.h" // upload_new_resource() +#include "llfloaterpostcard.h" +#include "llcheckboxctrl.h" +#include "llradiogroup.h" +#include "lltoolfocus.h" +#include "lltoolmgr.h" #include "llworld.h" +#include "llagentui.h" // Linden library includes #include "llfontgl.h" @@ -91,6 +86,10 @@ ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- +S32 LLFloaterSnapshot::sUIWinHeightLong = 526 ; +S32 LLFloaterSnapshot::sUIWinHeightShort = LLFloaterSnapshot::sUIWinHeightLong - 230 ; +S32 LLFloaterSnapshot::sUIWinWidth = 215 ; + LLSnapshotFloaterView* gSnapshotFloaterView = NULL; const F32 AUTO_SNAPSHOT_TIME_DELAY = 1.f; @@ -115,7 +114,6 @@ public: enum ESnapshotType { SNAPSHOT_POSTCARD, - SNAPSHOT_WEB, SNAPSHOT_TEXTURE, SNAPSHOT_LOCAL }; @@ -164,11 +162,8 @@ public: void setSnapshotBufferType(LLViewerWindow::ESnapshotType type) { mSnapshotBufferType = type; } void updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail = FALSE, F32 delay = 0.f); LLFloaterPostcard* savePostcard(); - void confirmSavingTexture(bool set_as_profile_pic = false); - bool onSavingTextureConfirmed(const LLSD& notification, const LLSD& response, bool set_as_profile_pic); - void saveTexture(bool set_as_profile_pic = false); + void saveTexture(); BOOL saveLocal(); - void saveWeb(std::string url); BOOL setThumbnailImageSize() ; void generateThumbnailImage(BOOL force_update = FALSE) ; @@ -177,9 +172,6 @@ public: // Returns TRUE when snapshot generated, FALSE otherwise. static BOOL onIdle( void* snapshot_preview ); - - // callback for region name resolve - void regionNameCallback(std::string url, LLSD body, const std::string& name, S32 x, S32 y, S32 z); private: LLColor4 mColor; @@ -301,7 +293,7 @@ F32 LLSnapshotLivePreview::getAspect() F32 image_aspect_ratio = ((F32)mWidth[mCurImageIndex]) / ((F32)mHeight[mCurImageIndex]); F32 window_aspect_ratio = ((F32)getRect().getWidth()) / ((F32)getRect().getHeight()); - if (!mKeepAspectRatio) + if (!mKeepAspectRatio)//gSavedSettings.getBOOL("KeepAspectForSnapshot")) { return image_aspect_ratio; } @@ -634,20 +626,20 @@ BOOL LLSnapshotLivePreview::setThumbnailImageSize() F32 window_aspect_ratio = ((F32)window_width) / ((F32)window_height); // UI size for thumbnail - LLFloater* floater = LLFloaterReg::getInstance("snapshot"); - mThumbnailWidth = floater->getChild<LLView>("thumbnail_placeholder")->getRect().getWidth(); - mThumbnailHeight = floater->getChild<LLView>("thumbnail_placeholder")->getRect().getHeight(); + S32 max_width = LLFloaterSnapshot::getUIWinWidth() - 20; + S32 max_height = 90; - - if (window_aspect_ratio > (F32)mThumbnailWidth / mThumbnailHeight) + if (window_aspect_ratio > (F32)max_width / max_height) { // image too wide, shrink to width - mThumbnailHeight = llround((F32)mThumbnailWidth / window_aspect_ratio); + mThumbnailWidth = max_width; + mThumbnailHeight = llround((F32)max_width / window_aspect_ratio); } else { // image too tall, shrink to height - mThumbnailWidth = llround((F32)mThumbnailHeight * window_aspect_ratio); + mThumbnailHeight = max_height; + mThumbnailWidth = llround((F32)max_height * window_aspect_ratio); } if(mThumbnailWidth > window_width || mThumbnailHeight > window_height) @@ -833,21 +825,10 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) { // delete any existing image previewp->mFormattedImage = NULL; - // now create the new one of the appropriate format. - // note: postcards and web hardcoded to use jpeg always. - LLFloaterSnapshot::ESnapshotFormat format; - - if (previewp->getSnapshotType() == SNAPSHOT_POSTCARD || - previewp->getSnapshotType() == SNAPSHOT_WEB) - { - format = LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG; - } - else - { - format = previewp->getSnapshotFormat(); - } - + // note: postcards hardcoded to use jpeg always. + LLFloaterSnapshot::ESnapshotFormat format = previewp->getSnapshotType() == SNAPSHOT_POSTCARD + ? LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG : previewp->getSnapshotFormat(); switch(format) { case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG: @@ -974,41 +955,13 @@ LLFloaterPostcard* LLSnapshotLivePreview::savePostcard() return floater; } -// Callback for asset upload -void profile_pic_upload_callback(const LLUUID& uuid) -{ - LLFloaterSnapshot* floater = LLFloaterReg::getTypedInstance<LLFloaterSnapshot>("snapshot"); - floater->setAsProfilePic(uuid); -} - -void LLSnapshotLivePreview::confirmSavingTexture(bool set_as_profile_pic) -{ - LLSD args; - args["AMOUNT"] = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); - LLNotificationsUtil::add("UploadConfirmation", args, LLSD(), - boost::bind(&LLSnapshotLivePreview::onSavingTextureConfirmed, this, _1, _2, set_as_profile_pic)); -} - -bool LLSnapshotLivePreview::onSavingTextureConfirmed(const LLSD& notification, const LLSD& response, bool set_as_profile_pic) -{ - S32 option = LLNotificationsUtil::getSelectedOption(notification, response); - - if (option == 0) - { - saveTexture(set_as_profile_pic); - } - - return false; -} - - -void LLSnapshotLivePreview::saveTexture(bool set_as_profile_pic) +void LLSnapshotLivePreview::saveTexture() { // gen a new uuid for this asset LLTransactionID tid; tid.generate(); LLAssetID new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); - + LLPointer<LLImageJ2C> formatted = new LLImageJ2C; LLPointer<LLImageRaw> scaled = new LLImageRaw(mPreviewImage->getData(), mPreviewImage->getWidth(), @@ -1019,30 +972,26 @@ void LLSnapshotLivePreview::saveTexture(bool set_as_profile_pic) if (formatted->encode(scaled, 0.0f)) { - boost::function<void(const LLUUID& uuid)> callback = NULL; - - if (set_as_profile_pic) - { - callback = profile_pic_upload_callback; - } - LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE); std::string pos_string; LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL); std::string who_took_it; LLAgentUI::buildFullname(who_took_it); + LLAssetStorage::LLStoreAssetCallback callback = NULL; S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + void *userdata = NULL; upload_new_resource(tid, // tid LLAssetType::AT_TEXTURE, "Snapshot : " + pos_string, "Taken by " + who_took_it + " at " + pos_string, + 0, LLFolderType::FT_SNAPSHOT_CATEGORY, LLInventoryType::IT_SNAPSHOT, PERM_ALL, // Note: Snapshots to inventory is a special case of content upload PERM_NONE, // that ignores the user's premissions preferences and continues to PERM_NONE, // always use these fairly permissive hard-coded initial perms. - MG "Snapshot : " + pos_string, - callback, expected_upload_cost); + callback, expected_upload_cost, userdata); gViewerWindow->playSnapshotAnimAndSound(); } else @@ -1072,81 +1021,6 @@ BOOL LLSnapshotLivePreview::saveLocal() return success; } - -class LLSendWebResponder : public LLHTTPClient::Responder -{ -public: - - virtual void error(U32 status, const std::string& reason) - { - llwarns << status << ": " << reason << llendl; - LLNotificationsUtil::add("ShareToWebFailed"); - } - - virtual void result(const LLSD& content) - { - std::string response_url = content["response_url"].asString(); - - if (!response_url.empty()) - { - LLWeb::loadURLExternal(response_url); - } - else - { - LLNotificationsUtil::add("ShareToWebFailed"); - } - } - -}; - -void LLSnapshotLivePreview::saveWeb(std::string url) -{ - if (url.empty()) - { - llwarns << "No share to web url" << llendl; - return; - } - - LLImageJPEG* jpg = dynamic_cast<LLImageJPEG*>(mFormattedImage.get()); - if(!jpg) - { - llwarns << "Formatted image not a JPEG" << llendl; - return; - } - -/* figure out if there's a better way to serialize */ - LLSD body; - std::vector<U8> binary_image; - U8* data = jpg->getData(); - for (int i = 0; i < jpg->getDataSize(); i++) - { - binary_image.push_back(data[i]); - } - - body["image"] = binary_image; - - body["description"] = getChild<LLLineEditor>("description")->getText(); - - std::string name; - LLAgentUI::buildFullname(name); - - body["avatar_name"] = name; - - LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(gAgentCamera.getCameraPositionGlobal(), - boost::bind(&LLSnapshotLivePreview::regionNameCallback, this, url, body, _1, _2, _3, _4)); - - gViewerWindow->playSnapshotAnimAndSound(); -} - - -void LLSnapshotLivePreview::regionNameCallback(std::string url, LLSD body, const std::string& name, S32 x, S32 y, S32 z) -{ - body["slurl"] = LLSLURL(name, LLVector3d(x, y, z)).getSLURLString(); - - LLHTTPClient::post(url, body, - new LLSendWebResponder()); -} - ///---------------------------------------------------------------------------- /// Class LLFloaterSnapshot::Impl ///---------------------------------------------------------------------------- @@ -1166,8 +1040,14 @@ public: mAvatarPauseHandles.clear(); } + static void onClickDiscard(void* data); + static void onClickKeep(void* data); + static void onCommitSave(LLUICtrl* ctrl, void* data); static void onClickNewSnapshot(void* data); static void onClickAutoSnap(LLUICtrl *ctrl, void* data); + //static void onClickAdvanceSnap(LLUICtrl *ctrl, void* data); + static void onClickLess(void* data) ; + static void onClickMore(void* data) ; static void onClickUICheck(LLUICtrl *ctrl, void* data); static void onClickHUDCheck(LLUICtrl *ctrl, void* data); static void onClickKeepOpenCheck(LLUICtrl *ctrl, void* data); @@ -1177,11 +1057,9 @@ public: static void updateResolution(LLUICtrl* ctrl, void* data, BOOL do_update = TRUE); static void onCommitFreezeFrame(LLUICtrl* ctrl, void* data); static void onCommitLayerTypes(LLUICtrl* ctrl, void*data); + static void onCommitSnapshotType(LLUICtrl* ctrl, void* data); static void onCommitSnapshotFormat(LLUICtrl* ctrl, void* data); static void onCommitCustomResolution(LLUICtrl *ctrl, void* data); - static void onCommitSnapshot(LLFloaterSnapshot* view, LLSnapshotLivePreview::ESnapshotType type); - static void onCommitProfilePic(LLFloaterSnapshot* view); - static void showAdvanced(LLFloaterSnapshot* view, const BOOL visible); static void resetSnapshotSizeOnUI(LLFloaterSnapshot *view, S32 width, S32 height) ; static BOOL checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value); @@ -1189,8 +1067,10 @@ public: static void setResolution(LLFloaterSnapshot* floater, const std::string& comboname); static void updateControls(LLFloaterSnapshot* floater); static void updateLayout(LLFloaterSnapshot* floater); + static void updateResolutionTextEntry(LLFloaterSnapshot* floater); private: + static LLSnapshotLivePreview::ESnapshotType getTypeIndex(LLFloaterSnapshot* floater); static ESnapshotFormat getFormatIndex(LLFloaterSnapshot* floater); static LLViewerWindow::ESnapshotType getLayerType(LLFloaterSnapshot* floater); static void comboSetCustom(LLFloaterSnapshot *floater, const std::string& comboname); @@ -1213,6 +1093,22 @@ LLSnapshotLivePreview* LLFloaterSnapshot::Impl::getPreviewView(LLFloaterSnapshot } // static +LLSnapshotLivePreview::ESnapshotType LLFloaterSnapshot::Impl::getTypeIndex(LLFloaterSnapshot* floater) +{ + LLSnapshotLivePreview::ESnapshotType index = LLSnapshotLivePreview::SNAPSHOT_POSTCARD; + LLSD value = floater->childGetValue("snapshot_type_radio"); + const std::string id = value.asString(); + if (id == "postcard") + index = LLSnapshotLivePreview::SNAPSHOT_POSTCARD; + else if (id == "texture") + index = LLSnapshotLivePreview::SNAPSHOT_TEXTURE; + else if (id == "local") + index = LLSnapshotLivePreview::SNAPSHOT_LOCAL; + return index; +} + + +// static LLFloaterSnapshot::ESnapshotFormat LLFloaterSnapshot::Impl::getFormatIndex(LLFloaterSnapshot* floater) { ESnapshotFormat index = SNAPSHOT_FORMAT_PNG; @@ -1260,12 +1156,20 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) { LLSnapshotLivePreview* previewp = getPreviewView(floaterp); + S32 delta_height = gSavedSettings.getBOOL("AdvanceSnapshot") ? 0 : floaterp->getUIWinHeightShort() - floaterp->getUIWinHeightLong() ; + if(!gSavedSettings.getBOOL("AdvanceSnapshot")) //set to original window resolution { previewp->mKeepAspectRatio = TRUE; - floaterp->getChild<LLComboBox>("snapshot_size_combo")->setCurrentByIndex(0); - gSavedSettings.setS32("SnapshotLastResolution", 0); + floaterp->getChild<LLComboBox>("postcard_size_combo")->setCurrentByIndex(0); + gSavedSettings.setS32("SnapshotPostcardLastResolution", 0); + + floaterp->getChild<LLComboBox>("texture_size_combo")->setCurrentByIndex(0); + gSavedSettings.setS32("SnapshotTextureLastResolution", 0); + + floaterp->getChild<LLComboBox>("local_size_combo")->setCurrentByIndex(0); + gSavedSettings.setS32("SnapshotLocalLastResolution", 0); LLSnapshotLivePreview* previewp = getPreviewView(floaterp); previewp->setSize(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()); @@ -1278,6 +1182,9 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) // stop all mouse events at fullscreen preview layer floaterp->getParent()->setMouseOpaque(TRUE); + // shrink to smaller layout + floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getUIWinHeightLong() + delta_height); + // can see and interact with fullscreen preview now if (previewp) { @@ -1306,6 +1213,7 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) else // turning off freeze frame mode { floaterp->getParent()->setMouseOpaque(FALSE); + floaterp->reshape(floaterp->getRect().getWidth(), floaterp->getUIWinHeightLong() + delta_height); if (previewp) { previewp->setVisible(FALSE); @@ -1334,27 +1242,127 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) // static void LLFloaterSnapshot::Impl::updateControls(LLFloaterSnapshot* floater) { + LLRadioGroup* snapshot_type_radio = floater->getChild<LLRadioGroup>("snapshot_type_radio"); + snapshot_type_radio->setSelectedIndex(gSavedSettings.getS32("LastSnapshotType")); + LLSnapshotLivePreview::ESnapshotType shot_type = getTypeIndex(floater); + ESnapshotFormat shot_format = (ESnapshotFormat)gSavedSettings.getS32("SnapshotFormat"); //getFormatIndex(floater); LLViewerWindow::ESnapshotType layer_type = getLayerType(floater); + LLViewerWindow::ESnapshotType layer_type = getLayerType(floater); + + floater->childSetVisible("postcard_size_combo", FALSE); + floater->childSetVisible("texture_size_combo", FALSE); + floater->childSetVisible("local_size_combo", FALSE); + + floater->getChild<LLComboBox>("postcard_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotPostcardLastResolution")); + floater->getChild<LLComboBox>("texture_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotTextureLastResolution")); + floater->getChild<LLComboBox>("local_size_combo")->selectNthItem(gSavedSettings.getS32("SnapshotLocalLastResolution")); + floater->getChild<LLComboBox>("local_format_combo")->selectNthItem(gSavedSettings.getS32("SnapshotFormat")); + + floater->childSetVisible("upload_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE); + floater->childSetVisible("send_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD); + floater->childSetVisible("save_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL); + floater->childSetEnabled("keep_aspect_check", shot_type != LLSnapshotLivePreview::SNAPSHOT_TEXTURE && !floater->impl.mAspectRatioCheckOff); + floater->childSetEnabled("layer_types", shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL); + + BOOL is_advance = gSavedSettings.getBOOL("AdvanceSnapshot"); + BOOL is_local = shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL; + BOOL show_slider = + shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD + || (is_local && shot_format == LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG); + + floater->childSetVisible("more_btn", !is_advance); // the only item hidden in advanced mode + floater->childSetVisible("less_btn", is_advance); + floater->childSetVisible("type_label2", is_advance); + floater->childSetVisible("format_label", is_advance && is_local); + floater->childSetVisible("local_format_combo", is_advance && is_local); + floater->childSetVisible("layer_types", is_advance); + floater->childSetVisible("layer_type_label", is_advance); + floater->childSetVisible("snapshot_width", is_advance); + floater->childSetVisible("snapshot_height", is_advance); + floater->childSetVisible("keep_aspect_check", is_advance); + floater->childSetVisible("ui_check", is_advance); + floater->childSetVisible("hud_check", is_advance); + floater->childSetVisible("keep_open_check", is_advance); + floater->childSetVisible("freeze_frame_check", is_advance); + floater->childSetVisible("auto_snapshot_check", is_advance); + floater->childSetVisible("image_quality_slider", is_advance && show_slider); + LLSnapshotLivePreview* previewp = getPreviewView(floater); - if (NULL == previewp) - { - return; + BOOL got_bytes = previewp && previewp->getDataSize() > 0; + BOOL got_snap = previewp && previewp->getSnapshotUpToDate(); + + floater->childSetEnabled("send_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD && got_snap && previewp->getDataSize() <= MAX_POSTCARD_DATASIZE); + floater->childSetEnabled("upload_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE && got_snap); + floater->childSetEnabled("save_btn", shot_type == LLSnapshotLivePreview::SNAPSHOT_LOCAL && got_snap); + + LLLocale locale(LLLocale::USER_LOCALE); + std::string bytes_string; + if (got_snap) + { + LLResMgr::getInstance()->getIntegerString(bytes_string, (previewp->getDataSize()) >> 10 ); + } + S32 upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); + floater->childSetLabelArg("texture", "[AMOUNT]", llformat("%d",upload_cost)); + floater->childSetLabelArg("upload_btn", "[AMOUNT]", llformat("%d",upload_cost)); + floater->childSetTextArg("file_size_label", "[SIZE]", got_snap ? bytes_string : floater->getString("unknown")); + floater->childSetColor("file_size_label", + shot_type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD + && got_bytes + && previewp->getDataSize() > MAX_POSTCARD_DATASIZE ? LLUIColor(LLColor4::red) : LLUIColorTable::instance().getColor( "LabelTextColor" )); + + switch(shot_type) + { + case LLSnapshotLivePreview::SNAPSHOT_POSTCARD: + layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; + floater->childSetValue("layer_types", "colors"); + if(is_advance) + { + setResolution(floater, "postcard_size_combo"); + } + break; + case LLSnapshotLivePreview::SNAPSHOT_TEXTURE: + layer_type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; + floater->childSetValue("layer_types", "colors"); + if(is_advance) + { + setResolution(floater, "texture_size_combo"); + } + break; + case LLSnapshotLivePreview::SNAPSHOT_LOCAL: + if(is_advance) + { + setResolution(floater, "local_size_combo"); + } + break; + default: + break; } - // Disable buttons until Snapshot is ready. EXT-6534 - BOOL got_snap = previewp->getSnapshotUpToDate(); + updateResolutionTextEntry(floater); - // process Main buttons - floater->childSetEnabled("share", got_snap); - floater->childSetEnabled("save", got_snap); - floater->childSetEnabled("set_profile_pic", got_snap); + if (previewp) + { + previewp->setSnapshotType(shot_type); + previewp->setSnapshotFormat(shot_format); + previewp->setSnapshotBufferType(layer_type); + } +} - // process Share actions buttons - floater->childSetEnabled("share_to_web", got_snap); - floater->childSetEnabled("share_to_email", got_snap); +// static +void LLFloaterSnapshot::Impl::updateResolutionTextEntry(LLFloaterSnapshot* floater) +{ + LLSpinCtrl* width_spinner = floater->getChild<LLSpinCtrl>("snapshot_width"); + LLSpinCtrl* height_spinner = floater->getChild<LLSpinCtrl>("snapshot_height"); - // process Save actions buttons - floater->childSetEnabled("save_to_inventory", got_snap); - floater->childSetEnabled("save_to_computer", got_snap); + if(getTypeIndex(floater) == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) + { + width_spinner->setAllowEdit(FALSE); + height_spinner->setAllowEdit(FALSE); + } + else + { + width_spinner->setAllowEdit(TRUE); + height_spinner->setAllowEdit(TRUE); + } } // static @@ -1368,6 +1376,70 @@ void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp, } // static +void LLFloaterSnapshot::Impl::onClickDiscard(void* data) +{ + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + + if (view) + { + view->closeFloater(); + } +} + + +// static +void LLFloaterSnapshot::Impl::onCommitSave(LLUICtrl* ctrl, void* data) +{ + if (ctrl->getValue().asString() == "save as") + { + gViewerWindow->resetSnapshotLoc(); + } + onClickKeep(data); +} + +// static +void LLFloaterSnapshot::Impl::onClickKeep(void* data) +{ + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + LLSnapshotLivePreview* previewp = getPreviewView(view); + + if (previewp) + { + if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_POSTCARD) + { + LLFloaterPostcard* floater = previewp->savePostcard(); + // if still in snapshot mode, put postcard floater in snapshot floaterview + // and link it to snapshot floater + if (floater && !gSavedSettings.getBOOL("CloseSnapshotOnKeep")) + { + gFloaterView->removeChild(floater); + gSnapshotFloaterView->addChild(floater); + view->addDependentFloater(floater, FALSE); + } + } + else if (previewp->getSnapshotType() == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) + { + previewp->saveTexture(); + } + else + { + previewp->saveLocal(); + } + + if (gSavedSettings.getBOOL("CloseSnapshotOnKeep")) + { + view->closeFloater(); + } + else + { + checkAutoSnapshot(previewp); + } + + updateControls(view); + } +} + +// static void LLFloaterSnapshot::Impl::onClickNewSnapshot(void* data) { LLSnapshotLivePreview* previewp = getPreviewView((LLFloaterSnapshot *)data); @@ -1392,6 +1464,41 @@ void LLFloaterSnapshot::Impl::onClickAutoSnap(LLUICtrl *ctrl, void* data) } } +void LLFloaterSnapshot::Impl::onClickMore(void* data) +{ + gSavedSettings.setBOOL( "AdvanceSnapshot", TRUE ); + + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + if (view) + { + view->translate( 0, view->getUIWinHeightShort() - view->getUIWinHeightLong() ); + view->reshape(view->getRect().getWidth(), view->getUIWinHeightLong()); + updateControls(view) ; + updateLayout(view) ; + if(getPreviewView(view)) + { + getPreviewView(view)->setThumbnailImageSize() ; + } + } +} +void LLFloaterSnapshot::Impl::onClickLess(void* data) +{ + gSavedSettings.setBOOL( "AdvanceSnapshot", FALSE ); + + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + if (view) + { + view->translate( 0, view->getUIWinHeightLong() - view->getUIWinHeightShort() ); + view->reshape(view->getRect().getWidth(), view->getUIWinHeightShort()); + updateControls(view) ; + updateLayout(view) ; + if(getPreviewView(view)) + { + getPreviewView(view)->setThumbnailImageSize() ; + } + } +} + // static void LLFloaterSnapshot::Impl::onClickUICheck(LLUICtrl *ctrl, void* data) { @@ -1568,8 +1675,10 @@ void LLFloaterSnapshot::Impl::updateResolution(LLUICtrl* ctrl, void* data, BOOL } // save off all selected resolution values - gSavedSettings.setS32("SnapshotLastResolution", view->getChild<LLComboBox>("snapshot_size_combo")->getCurrentIndex()); - + gSavedSettings.setS32("SnapshotPostcardLastResolution", view->getChild<LLComboBox>("postcard_size_combo")->getCurrentIndex()); + gSavedSettings.setS32("SnapshotTextureLastResolution", view->getChild<LLComboBox>("texture_size_combo")->getCurrentIndex()); + gSavedSettings.setS32("SnapshotLocalLastResolution", view->getChild<LLComboBox>("local_size_combo")->getCurrentIndex()); + std::string sdstring = combobox->getSelectedValue(); LLSD sdres; std::stringstream sstream(sdstring); @@ -1649,128 +1758,17 @@ void LLFloaterSnapshot::Impl::onCommitLayerTypes(LLUICtrl* ctrl, void*data) } //static -void LLFloaterSnapshot::Impl::showAdvanced(LLFloaterSnapshot* view, const BOOL visible) +void LLFloaterSnapshot::Impl::onCommitSnapshotType(LLUICtrl* ctrl, void* data) { - LLPanel* advanced_panel = view->getChild<LLPanel>("snapshot_advanced"); - - if (advanced_panel->getVisible() != visible) - { - gSavedSettings.setBOOL("AdvanceSnapshot", visible); - - advanced_panel->setVisible(visible); - view->getChild<LLButton>("hide_advanced")->setVisible(visible); - view->getChild<LLButton>("show_advanced")->setVisible(!visible); - - if (visible) - { - // stretch the floater so it can accommodate the advanced panel - view->reshape(view->getRect().getWidth() + advanced_panel->getRect().getWidth(), view->getRect().getHeight()); - } - else - { - // shrink floater back to original size - view->reshape(view->getRect().getWidth() - advanced_panel->getRect().getWidth(), view->getRect().getHeight()); - } - } -} - -// This object represents a pending request for avatar properties information -class LLAvatarDataRequest : public LLAvatarPropertiesObserver -{ -public: - LLAvatarDataRequest(const LLUUID& avatar_id, const LLUUID& image_id, LLFloaterSnapshot* floater) - : mAvatarID(avatar_id), - mImageID(image_id), - mSnapshotFloater(floater) - - { - } - - ~LLAvatarDataRequest() - { - // remove ourselves as an observer - LLAvatarPropertiesProcessor::getInstance()-> - removeObserver(mAvatarID, this); - } - - void processProperties(void* data, EAvatarProcessorType type) - { - // route the data to the inspector - if (data - && type == APT_PROPERTIES) - { - - LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data); - - LLAvatarData new_data(*avatar_data); - new_data.image_id = mImageID; - - LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate(&new_data); - - delete this; - } - } - - // Store avatar ID so we can un-register the observer on destruction - LLUUID mAvatarID; - LLUUID mImageID; - LLFloaterSnapshot* mSnapshotFloater; -}; - -void LLFloaterSnapshot::Impl::onCommitProfilePic(LLFloaterSnapshot* view) -{ - //first save to harddrive - LLSnapshotLivePreview* previewp = getPreviewView(view); - - if(previewp) + LLFloaterSnapshot *view = (LLFloaterSnapshot *)data; + if (view) { - previewp->confirmSavingTexture(true); + gSavedSettings.setS32("LastSnapshotType", getTypeIndex(view)); + getPreviewView(view)->updateSnapshot(TRUE); + updateControls(view); } } -void LLFloaterSnapshot::Impl::onCommitSnapshot(LLFloaterSnapshot* view, LLSnapshotLivePreview::ESnapshotType type) -{ - LLSnapshotLivePreview* previewp = getPreviewView(view); - - if (previewp) - { - previewp->setSnapshotType(type); - - if (type == LLSnapshotLivePreview::SNAPSHOT_WEB) - { - previewp->saveWeb(view->getString("share_to_web_url")); - } - else if (type == LLSnapshotLivePreview::SNAPSHOT_LOCAL) - { - previewp->saveLocal(); - } - else if (type == LLSnapshotLivePreview::SNAPSHOT_TEXTURE) - { - previewp->confirmSavingTexture(); - } - else if (type == LLSnapshotLivePreview::SNAPSHOT_POSTCARD) - { - LLFloaterPostcard* floater = previewp->savePostcard(); - // if still in snapshot mode, put postcard floater in snapshot floaterview - // and link it to snapshot floater - if (floater && !gSavedSettings.getBOOL("CloseSnapshotOnKeep")) - { - gFloaterView->removeChild(floater); - gSnapshotFloaterView->addChild(floater); - view->addDependentFloater(floater, FALSE); - } - } - - if (gSavedSettings.getBOOL("CloseSnapshotOnKeep")) - { - view->closeFloater(); - } - else - { - checkAutoSnapshot(previewp); - } - } -} //static void LLFloaterSnapshot::Impl::onCommitSnapshotFormat(LLUICtrl* ctrl, void* data) @@ -1784,6 +1782,8 @@ void LLFloaterSnapshot::Impl::onCommitSnapshotFormat(LLUICtrl* ctrl, void* data) } } + + // Sets the named size combo to "custom" mode. // static void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const std::string& comboname) @@ -1792,11 +1792,24 @@ void LLFloaterSnapshot::Impl::comboSetCustom(LLFloaterSnapshot* floater, const s combo->setCurrentByIndex(combo->getItemCount() - 1); // "custom" is always the last index - gSavedSettings.setS32("SnapshotLastResolution", combo->getCurrentIndex()); + if(comboname == "postcard_size_combo") + { + gSavedSettings.setS32("SnapshotPostcardLastResolution", combo->getCurrentIndex()); + } + else if(comboname == "texture_size_combo") + { + gSavedSettings.setS32("SnapshotTextureLastResolution", combo->getCurrentIndex()); + } + else if(comboname == "local_size_combo") + { + gSavedSettings.setS32("SnapshotLocalLastResolution", combo->getCurrentIndex()); + } checkAspectRatio(floater, -1); // -1 means custom } + + //static BOOL LLFloaterSnapshot::Impl::checkImageSize(LLSnapshotLivePreview* previewp, S32& width, S32& height, BOOL isWidthChanged, S32 max_value) { @@ -1937,7 +1950,9 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat previewp->setSize(w,h); checkAutoSnapshot(previewp, FALSE); previewp->updateSnapshot(FALSE, TRUE); - comboSetCustom(view, "snapshot_size_combo"); + comboSetCustom(view, "postcard_size_combo"); + comboSetCustom(view, "texture_size_combo"); + comboSetCustom(view, "local_size_combo"); } } @@ -1954,15 +1969,10 @@ void LLFloaterSnapshot::Impl::onCommitCustomResolution(LLUICtrl *ctrl, void* dat // Default constructor LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key) - : LLTransientDockableFloater(NULL, true, key), + : LLFloater(key), impl (*(new Impl)) { //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_snapshot.xml", FALSE); - - mCommitCallbackRegistrar.add("Snapshot.ShowButtons", boost::bind(&LLFloaterSnapshot::updateButtons, this, _2)); - mCommitCallbackRegistrar.add("Snapshot.ShowAdvanced", boost::bind(&Impl::showAdvanced, this, true)); - mCommitCallbackRegistrar.add("Snapshot.HideAdvanced", boost::bind(&Impl::showAdvanced, this, false)); - mCommitCallbackRegistrar.add("Snapshot.Refresh", boost::bind(&Impl::onClickNewSnapshot, this)); } // Destroys the object @@ -1984,14 +1994,19 @@ LLFloaterSnapshot::~LLFloaterSnapshot() BOOL LLFloaterSnapshot::postBuild() { - getChild<LLButton>("share_to_web")->setCommitCallback(boost::bind(&Impl::onCommitSnapshot, this, LLSnapshotLivePreview::SNAPSHOT_WEB)); - getChild<LLButton>("share_to_email")->setCommitCallback(boost::bind(&Impl::onCommitSnapshot, this, LLSnapshotLivePreview::SNAPSHOT_POSTCARD)); - getChild<LLButton>("save_to_inventory")->setCommitCallback(boost::bind(&Impl::onCommitSnapshot, this, LLSnapshotLivePreview::SNAPSHOT_TEXTURE)); - getChild<LLButton>("save_to_computer")->setCommitCallback(boost::bind(&Impl::onCommitSnapshot, this, LLSnapshotLivePreview::SNAPSHOT_LOCAL)); - getChild<LLButton>("set_profile_pic")->setCommitCallback(boost::bind(&Impl::onCommitProfilePic, this)); - + childSetCommitCallback("snapshot_type_radio", Impl::onCommitSnapshotType, this); childSetCommitCallback("local_format_combo", Impl::onCommitSnapshotFormat, this); + childSetAction("new_snapshot_btn", Impl::onClickNewSnapshot, this); + + childSetAction("more_btn", Impl::onClickMore, this); + childSetAction("less_btn", Impl::onClickLess, this); + + childSetAction("upload_btn", Impl::onClickKeep, this); + childSetAction("send_btn", Impl::onClickKeep, this); + childSetCommitCallback("save_btn", Impl::onCommitSave, this); + childSetAction("discard_btn", Impl::onClickDiscard, this); + childSetCommitCallback("image_quality_slider", Impl::onCommitQuality, this); childSetValue("image_quality_slider", gSavedSettings.getS32("SnapshotQuality")); @@ -2012,6 +2027,7 @@ BOOL LLFloaterSnapshot::postBuild() childSetCommitCallback("layer_types", Impl::onCommitLayerTypes, this); childSetValue("layer_types", "colors"); + childSetEnabled("layer_types", FALSE); childSetValue("snapshot_width", gSavedSettings.getS32(lastSnapshotWidthName())); childSetValue("snapshot_height", gSavedSettings.getS32(lastSnapshotHeightName())); @@ -2022,7 +2038,9 @@ BOOL LLFloaterSnapshot::postBuild() childSetValue("auto_snapshot_check", gSavedSettings.getBOOL("AutoSnapshot")); childSetCommitCallback("auto_snapshot_check", Impl::onClickAutoSnap, this); - childSetCommitCallback("snapshot_size_combo", Impl::onCommitResolution, this); + childSetCommitCallback("postcard_size_combo", Impl::onCommitResolution, this); + childSetCommitCallback("texture_size_combo", Impl::onCommitResolution, this); + childSetCommitCallback("local_size_combo", Impl::onCommitResolution, this); // create preview window LLRect full_screen_rect = getRootView()->getRect(); @@ -2043,15 +2061,8 @@ BOOL LLFloaterSnapshot::postBuild() impl.mPreviewHandle = previewp->getHandle(); impl.updateControls(this); impl.updateLayout(this); - impl.showAdvanced(this, gSavedSettings.getBOOL("AdvanceSnapshot")); - - //save off the refresh button's rectangle so we can apply offsets with thumbnail resize - mRefreshBtnRect = getChild<LLButton>("new_snapshot_btn")->getRect(); - - // make sure we share/hide the general buttons - updateButtons(LLSD("main")); - return LLDockableFloater::postBuild(); + return TRUE; } void LLFloaterSnapshot::draw() @@ -2064,19 +2075,15 @@ void LLFloaterSnapshot::draw() return; } - LLDockableFloater::draw(); - - LLButton* refresh_btn = getChild<LLButton>("new_snapshot_btn"); - // revert the refresh button to original intended position - LLRect refresh_rect = mRefreshBtnRect; + LLFloater::draw(); if (previewp) { if(previewp->getThumbnailImage()) { - LLRect thumbnail_rect = getChild<LLView>("thumbnail_placeholder")->getRect(); + LLRect thumbnail_rect = getChild<LLUICtrl>("thumbnail_placeholder")->getRect(); - S32 offset_x = (thumbnail_rect.getWidth() - previewp->getThumbnailWidth()) / 2 + thumbnail_rect.mLeft; + S32 offset_x = (getRect().getWidth() - previewp->getThumbnailWidth()) / 2 ; S32 offset_y = thumbnail_rect.mBottom + (thumbnail_rect.getHeight() - previewp->getThumbnailHeight()) / 2 ; glMatrixMode(GL_MODELVIEW); @@ -2085,14 +2092,8 @@ void LLFloaterSnapshot::draw() previewp->getThumbnailImage(), LLColor4::white); previewp->drawPreviewRect(offset_x, offset_y) ; - - refresh_rect.translate(offset_x - thumbnail_rect.mLeft, offset_y - thumbnail_rect.mBottom); } } - - refresh_btn->setRect(refresh_rect); - drawChild(refresh_btn); - } void LLFloaterSnapshot::onOpen(const LLSD& key) @@ -2106,12 +2107,6 @@ void LLFloaterSnapshot::onOpen(const LLSD& key) gSnapshotFloaterView->setEnabled(TRUE); gSnapshotFloaterView->setVisible(TRUE); gSnapshotFloaterView->adjustToFitScreen(this, FALSE); - - LLButton *snapshots = LLBottomTray::getInstance()->getChild<LLButton>("snapshots"); - - setDockControl(new LLDockControl( - snapshots, this, - getDockTongue(), LLDockControl::TOP)); } void LLFloaterSnapshot::onClose(bool app_quitting) @@ -2139,34 +2134,6 @@ void LLFloaterSnapshot::update() } } -bool LLFloaterSnapshot::updateButtons(const LLSD& mode) -{ - std::string button_mode = mode.asString(); - - bool mode_main("main" == button_mode); - bool mode_share("share" == button_mode); - bool mode_save("save" == button_mode); - - // Default to a known state if mode is invalid. - if (!mode_main && !mode_share && !mode_save) mode_main = true; - - childSetVisible("panel_snapshot_main", mode_main); - childSetVisible("panel_snapshot_share", mode_share); - childSetVisible("panel_snapshot_save", mode_save); - - return true; -} - -void LLFloaterSnapshot::setAsProfilePic(const LLUUID& image_id) -{ - LLAvatarDataRequest* avatar_data_request = new LLAvatarDataRequest(gAgent.getID(), image_id, this); - - LLAvatarPropertiesProcessor* processor = - LLAvatarPropertiesProcessor::getInstance(); - - processor->addObserver(gAgent.getID(), avatar_data_request); - processor->sendAvatarPropertiesRequest(gAgent.getID()); -} ///---------------------------------------------------------------------------- /// Class LLSnapshotFloaterView diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index 8c4373c35c..1333497bd2 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -34,10 +34,9 @@ #define LL_LLFLOATERSNAPSHOT_H #include "llfloater.h" -#include "lltransientdockablefloater.h" -class LLFloaterSnapshot : public LLTransientDockableFloater +class LLFloaterSnapshot : public LLFloater { public: typedef enum e_snapshot_format @@ -57,10 +56,6 @@ public: static void update(); - void setAsProfilePic(const LLUUID& image_id); - - bool updateButtons(const LLSD& mode); - static S32 getUIWinHeightLong() {return sUIWinHeightLong ;} static S32 getUIWinHeightShort() {return sUIWinHeightShort ;} static S32 getUIWinWidth() {return sUIWinWidth ;} @@ -72,8 +67,6 @@ private: static S32 sUIWinHeightLong ; static S32 sUIWinHeightShort ; static S32 sUIWinWidth ; - - LLRect mRefreshBtnRect; }; class LLSnapshotFloaterView : public LLFloaterView diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 5682e691cd..f241d18a21 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -88,6 +88,10 @@ const S32 MIN_ITEM_WIDTH_VISIBLE = LLFolderViewItem::ICON_WIDTH + /*first few characters*/ 40; const S32 MINIMUM_RENAMER_WIDTH = 80; +// *TODO: move in params in xml if necessary. Requires modification of LLFolderView & LLInventoryPanel Params. +const S32 STATUS_TEXT_HPAD = 6; +const S32 STATUS_TEXT_VPAD = 8; + enum { SIGNAL_NO_KEYBOARD_FOCUS = 1, SIGNAL_KEYBOARD_FOCUS = 2 @@ -247,6 +251,10 @@ LLFolderView::LLFolderView(const Params& p) text_p.font(font); text_p.visible(false); text_p.allow_html(true); + text_p.wrap(true); // allow multiline text. See EXT-7564, EXT-7047 + // set text padding the same as in People panel. EXT-7047, EXT-4837 + text_p.h_pad(STATUS_TEXT_HPAD); + text_p.v_pad(STATUS_TEXT_VPAD); mStatusTextBox = LLUICtrlFactory::create<LLTextBox> (text_p); mStatusTextBox->setFollowsLeft(); mStatusTextBox->setFollowsTop(); @@ -955,6 +963,23 @@ void LLFolderView::draw() mStatusTextBox->setValue(mStatusText); mStatusTextBox->setVisible( TRUE ); + // firstly reshape message textbox with current size. This is necessary to + // LLTextBox::getTextPixelHeight works properly + const LLRect local_rect = getLocalRect(); + mStatusTextBox->setShape(local_rect); + + // get preferable text height... + S32 pixel_height = mStatusTextBox->getTextPixelHeight(); + bool height_changed = local_rect.getHeight() != pixel_height; + if (height_changed) + { + // ... if it does not match current height, lets rearrange current view. + // This will indirectly call ::arrange and reshape of the status textbox. + // We should call this method to also notify parent about required rect. + // See EXT-7564, EXT-7047. + arrangeFromRoot(); + } + } LLFolderViewFolder::draw(); @@ -2311,7 +2336,7 @@ void LLFolderView::updateRenamerPosition() bool LLFolderView::selectFirstItem() { for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + iter != mFolders.end();++iter) { LLFolderViewFolder* folder = (*iter ); if (folder->getVisible()) @@ -2348,7 +2373,7 @@ bool LLFolderView::selectLastItem() } } for (folders_t::reverse_iterator iter = mFolders.rbegin(); - iter != mFolders.rend();) + iter != mFolders.rend();++iter) { LLFolderViewFolder* folder = (*iter); if (folder->getVisible()) diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h index a2ef8c1d12..82f8a10cf3 100644 --- a/indra/newview/llfoldervieweventlistener.h +++ b/indra/newview/llfoldervieweventlistener.h @@ -37,6 +37,7 @@ #include "llinventorytype.h" #include "llpermissionsflags.h" #include "llpointer.h" +#include "llwearabletype.h" class LLFolderViewItem; @@ -89,6 +90,7 @@ public: virtual BOOL hasChildren() const = 0; virtual LLInventoryType::EType getInventoryType() const = 0; virtual void performAction(LLInventoryModel* model, std::string action) = 0; + virtual LLWearableType::EType getWearableType() const = 0; // This method should be called when a drag begins. returns TRUE // if the drag can begin, otherwise FALSE. diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index d97dfd535e..757808eb93 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -123,6 +123,7 @@ public: EDragAndDropType cargo_type, void* cargo_data) { return FALSE; } virtual LLInventoryType::EType getInventoryType() const { return mInvType; } + virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } //-------------------------------------------------------------------- // Convenience functions for adding various common menu options. @@ -471,6 +472,7 @@ public: virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual std::string getLabelSuffix() const; virtual BOOL renameItem(const std::string& new_name); + virtual LLWearableType::EType getWearableType() const { return mWearableType; } static void onWearOnAvatar( void* userdata ); // Access to wearOnAvatar() from menu static BOOL canWearOnAvatar( void* userdata ); diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index c90919e8fd..6e829f2dc2 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -49,6 +49,7 @@ LLInventoryFilter::FilterOps::FilterOps() : mFilterObjectTypes(0xffffffffffffffffULL), mFilterCategoryTypes(0xffffffffffffffffULL), + mFilterWearableTypes(0xffffffffffffffffULL), mMinDate(time_min()), mMaxDate(time_max()), mHoursAgo(0), @@ -139,8 +140,6 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con return FALSE; } } - // - //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -164,8 +163,6 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con if ((1LL << cat->getPreferredType() & mFilterOps.mFilterCategoryTypes) == U64(0)) return FALSE; } - // - //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -178,8 +175,6 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con if (object->getLinkedUUID() != mFilterOps.mFilterUUID) return FALSE; } - // - //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// @@ -201,8 +196,18 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con listener->getCreationDate() > mFilterOps.mMaxDate) return FALSE; } - // + //////////////////////////////////////////////////////////////////////////////// + // FILTERTYPE_WEARABLE + // Pass if this item is a wearable of the appropriate type + if (filterTypes & FILTERTYPE_WEARABLE) + { + LLWearableType::EType type = listener->getWearableType(); + if ((0x1LL << type & mFilterOps.mFilterWearableTypes) == 0) + { + return FALSE; + } + } return TRUE; } @@ -238,6 +243,8 @@ std::string::size_type LLInventoryFilter::getStringMatchOffset() const BOOL LLInventoryFilter::isNotDefault() const { return mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes + || mFilterOps.mFilterCategoryTypes != mDefaultFilterOps.mFilterCategoryTypes + || mFilterOps.mFilterWearableTypes != mDefaultFilterOps.mFilterWearableTypes || mFilterOps.mFilterTypes != FILTERTYPE_OBJECT || mFilterSubString.size() || mFilterOps.mPermissions != mDefaultFilterOps.mPermissions @@ -249,6 +256,8 @@ BOOL LLInventoryFilter::isNotDefault() const BOOL LLInventoryFilter::isActive() const { return mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL + || mFilterOps.mFilterCategoryTypes != 0xffffffffffffffffULL + || mFilterOps.mFilterWearableTypes != 0xffffffffffffffffULL || mFilterOps.mFilterTypes != FILTERTYPE_OBJECT || mFilterSubString.size() || mFilterOps.mPermissions != PERM_NONE @@ -322,7 +331,35 @@ void LLInventoryFilter::setFilterCategoryTypes(U64 types) setModified(FILTER_MORE_RESTRICTIVE); } } - mFilterOps.mFilterTypes |= FILTERTYPE_CATEGORY; + mFilterOps.mFilterTypes |= FILTERTYPE_OBJECT; +} + +void LLInventoryFilter::setFilterWearableTypes(U64 types) +{ + if (mFilterOps.mFilterWearableTypes != types) + { + // keep current items only if no type bits getting turned off + BOOL fewer_bits_set = (mFilterOps.mFilterWearableTypes & ~types); + BOOL more_bits_set = (~mFilterOps.mFilterWearableTypes & types); + + mFilterOps.mFilterWearableTypes = types; + if (more_bits_set && fewer_bits_set) + { + // neither less or more restrive, both simultaneously + // so we need to filter from scratch + setModified(FILTER_RESTART); + } + else if (more_bits_set) + { + // target is only one of all requested types so more type bits == less restrictive + setModified(FILTER_LESS_RESTRICTIVE); + } + else if (fewer_bits_set) + { + setModified(FILTER_MORE_RESTRICTIVE); + } + } + mFilterOps.mFilterTypes |= FILTERTYPE_WEARABLE; } void LLInventoryFilter::setFilterUUID(const LLUUID& object_id) diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 3ef51baefc..f740a6b333 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -59,10 +59,11 @@ public: enum EFilterType { FILTERTYPE_NONE = 0, - FILTERTYPE_OBJECT = 1, // normal default search-by-object-type - FILTERTYPE_CATEGORY = 2, // search by folder type - FILTERTYPE_UUID = 4, // find the object with UUID and any links to it - FILTERTYPE_DATE = 8 // search by date range + FILTERTYPE_OBJECT = 0x1 << 0, // normal default search-by-object-type + FILTERTYPE_CATEGORY = 0x1 << 1, // search by folder type + FILTERTYPE_UUID = 0x1 << 2, // find the object with UUID and any links to it + FILTERTYPE_DATE = 0x1 << 3, // search by date range + FILTERTYPE_WEARABLE = 0x1 << 4 // search by wearable type }; // REFACTOR: Change this to an enum. @@ -81,6 +82,7 @@ public: BOOL isFilterObjectTypesWith(LLInventoryType::EType t) const; void setFilterCategoryTypes(U64 types); void setFilterUUID(const LLUUID &object_id); + void setFilterWearableTypes(U64 types); void setFilterSubString(const std::string& string); const std::string& getFilterSubString(BOOL trim = FALSE) const; @@ -168,6 +170,7 @@ private: U32 mFilterTypes; U64 mFilterObjectTypes; // For _OBJECT + U64 mFilterWearableTypes; U64 mFilterCategoryTypes; // For _CATEGORY LLUUID mFilterUUID; // for UUID diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index c82ebd1439..93c56e1b8a 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -271,6 +271,32 @@ public: // // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLFindByMask : public LLInventoryCollectFunctor +{ +public: + LLFindByMask(U64 mask) + : mFilterMask(mask) + {} + + virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) + { + if(item && (mFilterMask & (1LL << item->getInventoryType())) ) + { + return true; + } + + return false; + } + +private: + U64 mFilterMask; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFindNonLinksByMask +// +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ class LLFindNonLinksByMask : public LLInventoryCollectFunctor { public: diff --git a/indra/newview/llinventoryitemslist.cpp b/indra/newview/llinventoryitemslist.cpp index 3e5f8d9848..23ea786484 100644 --- a/indra/newview/llinventoryitemslist.cpp +++ b/indra/newview/llinventoryitemslist.cpp @@ -70,16 +70,20 @@ void LLPanelInventoryListItemBase::draw() { if (getNeedsRefresh()) { - updateItem(); + if (mItem) + { + updateItem(mItem->getName()); + } setNeedsRefresh(false); } LLPanel::draw(); } -void LLPanelInventoryListItemBase::updateItem() +// virtual +void LLPanelInventoryListItemBase::updateItem(const std::string& name) { setIconImage(mIconImage); - setTitle(mItem->getName(), mHighlightedText); + setTitle(name, mHighlightedText); } void LLPanelInventoryListItemBase::addWidgetToLeftSide(const std::string& name, bool show_widget/* = true*/) @@ -132,7 +136,11 @@ BOOL LLPanelInventoryListItemBase::postBuild() setIconCtrl(getChild<LLIconCtrl>("item_icon")); setTitleCtrl(getChild<LLTextBox>("item_name")); - mIconImage = LLInventoryIcon::getIcon(mItem->getType(), mItem->getInventoryType(), mItem->getFlags(), FALSE); + if (mItem) + { + mIconImage = LLInventoryIcon::getIcon(mItem->getType(), mItem->getInventoryType(), mItem->getFlags(), FALSE); + updateItem(mItem->getName()); + } setNeedsRefresh(true); @@ -161,6 +169,42 @@ void LLPanelInventoryListItemBase::onMouseLeave(S32 x, S32 y, MASK mask) LLPanel::onMouseLeave(x, y, mask); } +const std::string& LLPanelInventoryListItemBase::getItemName() const +{ + if (!mItem) + { + return LLStringUtil::null; + } + return mItem->getName(); +} + +LLAssetType::EType LLPanelInventoryListItemBase::getType() const +{ + if (!mItem) + { + return LLAssetType::AT_NONE; + } + return mItem->getType(); +} + +LLWearableType::EType LLPanelInventoryListItemBase::getWearableType() const +{ + if (!mItem) + { + return LLWearableType::WT_NONE; + } + return mItem->getWearableType(); +} + +const std::string& LLPanelInventoryListItemBase::getDescription() const +{ + if (!mItem) + { + return LLStringUtil::null; + } + return mItem->getDescription(); +} + S32 LLPanelInventoryListItemBase::notify(const LLSD& info) { S32 rv = 0; @@ -168,7 +212,7 @@ S32 LLPanelInventoryListItemBase::notify(const LLSD& info) { mHighlightedText = info["match_filter"].asString(); - std::string test(mItem->getName()); + std::string test(mTitleCtrl->getText()); LLStringUtil::toUpper(test); if(mHighlightedText.empty() || std::string::npos != test.find(mHighlightedText)) diff --git a/indra/newview/llinventoryitemslist.h b/indra/newview/llinventoryitemslist.h index c1b1a6f281..d6132717e8 100644 --- a/indra/newview/llinventoryitemslist.h +++ b/indra/newview/llinventoryitemslist.h @@ -122,16 +122,16 @@ public: /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); /** Get the name of a corresponding inventory item */ - const std::string& getItemName() const { return mItem->getName(); } + const std::string& getItemName() const; /** Get the asset type of a corresponding inventory item */ - LLAssetType::EType getType() const { return mItem->getType(); } + LLAssetType::EType getType() const; /** Get the wearable type of a corresponding inventory item */ - LLWearableType::EType getWearableType() const { return mItem->getWearableType(); } + LLWearableType::EType getWearableType() const; /** Get the description of a corresponding inventory item */ - const std::string& getDescription() const { return mItem->getDescription(); } + const std::string& getDescription() const; /** Get the associated inventory item */ LLViewerInventoryItem* getItem() const { return mItem; } @@ -152,7 +152,7 @@ protected: /** * Called after inventory item was updated, update panel widgets to reflect inventory changes. */ - virtual void updateItem(); + virtual void updateItem(const std::string& name); /** setter for mIconCtrl */ void setIconCtrl(LLIconCtrl* icon) { mIconCtrl = icon; } diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index a20bf366c5..5e88140848 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -188,6 +188,8 @@ LLInventoryPanel::~LLInventoryPanel() } } + gIdleCallbacks.deleteFunction(onIdle, this); + // LLView destructor will take care of the sub-views. mInventory->removeObserver(mInventoryObserver); delete mInventoryObserver; @@ -223,6 +225,11 @@ void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask) getFilter()->setFilterPermissions(filter_perm_mask); } +void LLInventoryPanel::setFilterWearableTypes(U64 types) +{ + getFilter()->setFilterWearableTypes(types); +} + void LLInventoryPanel::setFilterSubString(const std::string& string) { getFilter()->setFilterSubString(string); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index ad17227d56..84603e8b4f 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -139,6 +139,7 @@ public: U32 getFilterObjectTypes() const { return mFolderRoot->getFilterObjectTypes(); } void setFilterPermMask(PermissionMask filter_perm_mask); U32 getFilterPermMask() const { return mFolderRoot->getFilterPermissions(); } + void setFilterWearableTypes(U64 filter); void setFilterSubString(const std::string& string); const std::string getFilterSubString() { return mFolderRoot->getFilterSubString(); } void setSinceLogoff(BOOL sl); diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 4b5e765c4f..1fadb126e4 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -32,6 +32,7 @@ #include "llviewerprecompiledheaders.h" +#include "llagentdata.h" // for gAgentID #include "llnearbychathandler.h" #include "llbottomtray.h" @@ -367,6 +368,13 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args) { if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) return; + + // don't process debug messages from not owned objects, see EXT-7762 + if (gAgentID != chat_msg.mOwnerID) + { + return; + } + if (gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)// show error in window //("ScriptErrorsAsChat")) { diff --git a/indra/newview/lloutfitobserver.cpp b/indra/newview/lloutfitobserver.cpp index 5652a98981..03414b9964 100644 --- a/indra/newview/lloutfitobserver.cpp +++ b/indra/newview/lloutfitobserver.cpp @@ -56,12 +56,9 @@ void LLOutfitObserver::changed(U32 mask) if (!gInventory.isInventoryUsable()) return; - bool COF_changed = checkCOF(); + checkCOF(); - if (!COF_changed) - { - checkBaseOutfit(); - } + checkBaseOutfit(); } // static @@ -74,6 +71,16 @@ S32 LLOutfitObserver::getCategoryVersion(const LLUUID& cat_id) return cat->getVersion(); } +// static +const std::string& LLOutfitObserver::getCategoryName(const LLUUID& cat_id) +{ + LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); + if (!cat) + return LLStringUtil::null; + + return cat->getName(); +} + bool LLOutfitObserver::checkCOF() { LLUUID cof = LLAppearanceMgr::getInstance()->getCOF(); @@ -105,8 +112,11 @@ void LLOutfitObserver::checkBaseOutfit() return; const S32 baseoutfit_ver = getCategoryVersion(baseoutfit_id); + const std::string& baseoutfit_name = getCategoryName(baseoutfit_id); - if (baseoutfit_ver == mBaseOutfitLastVersion) + if (baseoutfit_ver == mBaseOutfitLastVersion + // renaming category doesn't change version, so it's need to check it + && baseoutfit_name == mLastBaseOutfitName) return; } else @@ -116,10 +126,11 @@ void LLOutfitObserver::checkBaseOutfit() if (baseoutfit_id.isNull()) return; - - mBaseOutfitLastVersion = getCategoryVersion(mBaseOutfitId); } + mBaseOutfitLastVersion = getCategoryVersion(mBaseOutfitId); + mLastBaseOutfitName = getCategoryName(baseoutfit_id); + LLAppearanceMgr& app_mgr = LLAppearanceMgr::instance(); // dirtiness state should be updated before sending signal app_mgr.updateIsDirty(); diff --git a/indra/newview/lloutfitobserver.h b/indra/newview/lloutfitobserver.h index a4b5fbe04a..3a66b5ea9f 100644 --- a/indra/newview/lloutfitobserver.h +++ b/indra/newview/lloutfitobserver.h @@ -68,6 +68,8 @@ protected: /** Get a version of an inventory category specified by its UUID */ static S32 getCategoryVersion(const LLUUID& cat_id); + static const std::string& getCategoryName(const LLUUID& cat_id); + bool checkCOF(); void checkBaseOutfit(); @@ -78,6 +80,7 @@ protected: LLUUID mBaseOutfitId; S32 mBaseOutfitLastVersion; + std::string mLastBaseOutfitName; bool mLastOutfitDirtiness; diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index caa29db9d3..de074d6aaf 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -44,6 +44,7 @@ #include "llinventorymodel.h" #include "lllistcontextmenu.h" #include "llnotificationsutil.h" +#include "lloutfitobserver.h" #include "llsidetray.h" #include "lltransutil.h" #include "llviewermenu.h" @@ -89,17 +90,33 @@ protected: registrar.add("Outfit.Delete", boost::bind(deleteOutfit, selected_id)); enable_registrar.add("Outfit.OnEnable", boost::bind(&OutfitContextMenu::onEnable, this, _2)); + enable_registrar.add("Outfit.OnVisible", boost::bind(&OutfitContextMenu::onVisible, this, _2)); return createFromFile("menu_outfit_tab.xml"); } - bool onEnable(const LLSD& data) + bool onEnable(LLSD::String param) + { + LLUUID outfit_cat_id = mUUIDs.back(); + + if ("rename" == param) + { + return get_is_category_renameable(&gInventory, outfit_cat_id); + } + + return true; + } + + bool onVisible(LLSD::String param) { - std::string param = data.asString(); LLUUID outfit_cat_id = mUUIDs.back(); bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == outfit_cat_id; - if ("wear_replace" == param) + if ("edit" == param) + { + return is_worn; + } + else if ("wear_replace" == param) { return !is_worn; } @@ -111,14 +128,6 @@ protected: { return is_worn; } - else if ("edit" == param) - { - return is_worn; - } - else if ("rename" == param) - { - return get_is_category_renameable(&gInventory, outfit_cat_id); - } else if ("delete" == param) { return LLAppearanceMgr::instance().getCanRemoveOutfit(outfit_cat_id); @@ -199,6 +208,9 @@ void LLOutfitsList::onOpen(const LLSD& /*info*/) mCategoriesObserver->addCategory(outfits, boost::bind(&LLOutfitsList::refreshList, this, outfits)); + // Start observing changes in Current Outfit to update items worn state. + LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLOutfitsList::onCOFChanged, this)); + // Fetch "My Outfits" contents and refresh the list to display // initially fetched items. If not all items are fetched now // the observer will refresh the list as soon as the new items @@ -319,7 +331,7 @@ void LLOutfitsList::refreshList(const LLUUID& category_id) // 3. Reset currently selected outfit id if it is being removed. if (outfit_id == mSelectedOutfitUUID) { - mSelectedOutfitUUID = LLUUID(); + setSelectedOutfitUUID(LLUUID()); } // 4. Remove category UUID to accordion tab mapping. @@ -382,6 +394,11 @@ void LLOutfitsList::setFilterSubString(const std::string& string) mFilterSubString = string; } +boost::signals2::connection LLOutfitsList::addSelectionChangeCallback(selection_change_callback_t cb) +{ + return mSelectionChangeSignal.connect(cb); +} + ////////////////////////////////////////////////////////////////////////// // Private methods ////////////////////////////////////////////////////////////////////////// @@ -468,7 +485,12 @@ void LLOutfitsList::changeOutfitSelection(LLWearableItemsList* list, const LLUUI } mSelectedListsMap.insert(wearables_lists_map_value_t(category_id, list)); - mSelectedOutfitUUID = category_id; + setSelectedOutfitUUID(category_id); +} + +void LLOutfitsList::setSelectedOutfitUUID(const LLUUID& category_id) +{ + mSelectionChangeSignal(mSelectedOutfitUUID = category_id); } void LLOutfitsList::onFilteredWearableItemsListRefresh(LLUICtrl* ctrl) @@ -630,6 +652,43 @@ void LLOutfitsList::onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y) LLWearableItemsList::ContextMenu::instance().show(list, selected_uuids, x, y); } +void LLOutfitsList::onCOFChanged() +{ + LLInventoryModel::changed_items_t changed_linked_items; + + const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs(); + for (LLInventoryModel::changed_items_t::const_iterator iter = changed_items.begin(); + iter != changed_items.end(); + ++iter) + { + LLViewerInventoryItem* item = gInventory.getItem(*iter); + if (item) + { + // From gInventory we get the UUIDs of new links added to COF + // or removed from COF. These links UUIDs are not the same UUIDs + // that we have in each wearable items list. So we collect base items + // UUIDs to find all items or links that point to same base items in wearable + // items lists and update their worn state there. + changed_linked_items.insert(item->getLinkedUUID()); + } + } + + for (outfits_map_t::iterator iter = mOutfitsMap.begin(); + iter != mOutfitsMap.end(); + ++iter) + { + LLAccordionCtrlTab* tab = iter->second; + if (!tab) continue; + + LLWearableItemsList* list = dynamic_cast<LLWearableItemsList*>(tab->getAccordionView()); + if (!list) continue; + + // Every list updates the labels of changed items or + // the links that point to these items. + list->updateChangedItems(changed_linked_items); + } +} + bool is_tab_header_clicked(LLAccordionCtrlTab* tab, S32 y) { if(!tab || !tab->getHeaderVisible()) return false; diff --git a/indra/newview/lloutfitslist.h b/indra/newview/lloutfitslist.h index 3f4a65a6e6..5605044f41 100644 --- a/indra/newview/lloutfitslist.h +++ b/indra/newview/lloutfitslist.h @@ -71,6 +71,9 @@ public: class LLOutfitsList : public LLPanel { public: + typedef boost::function<void (const LLUUID&)> selection_change_callback_t; + typedef boost::signals2::signal<void (const LLUUID&)> selection_change_signal_t; + LLOutfitsList(); virtual ~LLOutfitsList(); @@ -86,6 +89,8 @@ public: const LLUUID& getSelectedOutfitUUID() const { return mSelectedOutfitUUID; } + boost::signals2::connection addSelectionChangeCallback(selection_change_callback_t cb); + private: /** * Reads xml with accordion tab and Flat list from xml file. @@ -110,6 +115,11 @@ private: void changeOutfitSelection(LLWearableItemsList* list, const LLUUID& category_id); /** + * Saves newly selected outfit ID. + */ + void setSelectedOutfitUUID(const LLUUID& category_id); + + /** * Called upon list refresh event to update tab visibility depending on * the results of applying filter to the title and list items of the tab. */ @@ -122,6 +132,7 @@ private: void onAccordionTabRightClick(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& cat_id); void onWearableItemsListRightClick(LLUICtrl* ctrl, S32 x, S32 y); + void onCOFChanged(); void onSelectionChange(LLUICtrl* ctrl); @@ -137,6 +148,7 @@ private: wearables_lists_map_t mSelectedListsMap; LLUUID mSelectedOutfitUUID; + selection_change_signal_t mSelectionChangeSignal; std::string mFilterSubString; diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index b356fe6bfd..26e8a932aa 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -815,6 +815,8 @@ void LLPanelGroupRolesSubTab::setGroupID(const LLUUID& id) if(mRoleDescription) mRoleDescription->clear(); if(mRoleTitle) mRoleTitle->clear(); + mHasRoleChange = FALSE; + setFooterEnabled(FALSE); LLPanelGroupSubTab::setGroupID(id); diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index ad3a5c2380..da809b7baa 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -135,6 +135,8 @@ public: virtual BOOL isUpToDate() const { return TRUE; } virtual BOOL hasChildren() const { return FALSE; } virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; } + virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } + // LLDragAndDropBridge functionality virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, @@ -184,6 +186,7 @@ void LLTaskInvFVBridge::showProperties() floater->setObjectID(mPanel->getTaskUUID()); } */ + } struct LLBuyInvItemData diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 3d0684afca..1454a2f6af 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -65,6 +65,7 @@ #include "llsaveoutfitcombobtn.h" #include "llscrolllistctrl.h" #include "lltextbox.h" +#include "lltrans.h" #include "lluictrlfactory.h" #include "llsdutil.h" #include "llsidepanelappearance.h" @@ -188,9 +189,8 @@ LLPanelOutfitEdit::LLPanelOutfitEdit() mCOFDragAndDropObserver(NULL), mInitialized(false), mAddWearablesPanel(NULL), - mWearableListMaskCollector(NULL), - mWearableListTypeCollector(NULL), - mFilterComboBox(NULL) + mFolderViewFilterCmbBox(NULL), + mListViewFilterCmbBox(NULL) { mSavedFolderState = new LLSaveFolderState(); mSavedFolderState->setApply(FALSE); @@ -202,12 +202,11 @@ LLPanelOutfitEdit::LLPanelOutfitEdit() observer.addOutfitLockChangedCallback(boost::bind(&LLPanelOutfitEdit::updateVerbs, this)); observer.addCOFChangedCallback(boost::bind(&LLPanelOutfitEdit::update, this)); - mLookItemTypes.reserve(NUM_LOOK_ITEM_TYPES); - for (U32 i = 0; i < NUM_LOOK_ITEM_TYPES; i++) + mFolderViewItemTypes.reserve(NUM_FOLDER_VIEW_ITEM_TYPES); + for (U32 i = 0; i < NUM_FOLDER_VIEW_ITEM_TYPES; i++) { - mLookItemTypes.push_back(LLLookItemType()); + mFolderViewItemTypes.push_back(LLLookItemType()); } - } @@ -217,17 +216,40 @@ LLPanelOutfitEdit::~LLPanelOutfitEdit() delete mCOFDragAndDropObserver; - delete mWearableListMaskCollector; - delete mWearableListTypeCollector; + while (!mListViewItemTypes.empty()) { + delete mListViewItemTypes.back(); + mListViewItemTypes.pop_back(); + } } BOOL LLPanelOutfitEdit::postBuild() { // gInventory.isInventoryUsable() no longer needs to be tested per Richard's fix for race conditions between inventory and panels - - mLookItemTypes[LIT_ALL] = LLLookItemType(getString("Filter.All"), ALL_ITEMS_MASK); - mLookItemTypes[LIT_WEARABLE] = LLLookItemType(getString("Filter.Clothes/Body"), WEARABLE_MASK); - mLookItemTypes[LIT_ATTACHMENT] = LLLookItemType(getString("Filter.Objects"), ATTACHMENT_MASK); + + mFolderViewItemTypes[FVIT_ALL] = LLLookItemType(getString("Filter.All"), ALL_ITEMS_MASK); + mFolderViewItemTypes[FVIT_WEARABLE] = LLLookItemType(getString("Filter.Clothes/Body"), WEARABLE_MASK); + mFolderViewItemTypes[FVIT_ATTACHMENT] = LLLookItemType(getString("Filter.Objects"), ATTACHMENT_MASK); + + //order is important, see EListViewItemType for order information + mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.All"), new LLFindByMask(ALL_ITEMS_MASK))); + mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Clothing"), new LLIsType(LLAssetType::AT_CLOTHING))); + mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Bodyparts"), new LLIsType(LLAssetType::AT_BODYPART))); + mListViewItemTypes.push_back(new LLFilterItem(getString("Filter.Objects"), new LLFindByMask(ATTACHMENT_MASK)));; + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("shape"), new LLFindActualWearablesOfType(LLWearableType::WT_SHAPE))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("skin"), new LLFindActualWearablesOfType(LLWearableType::WT_SKIN))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("hair"), new LLFindActualWearablesOfType(LLWearableType::WT_HAIR))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("eyes"), new LLFindActualWearablesOfType(LLWearableType::WT_EYES))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("shirt"), new LLFindActualWearablesOfType(LLWearableType::WT_SHIRT))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("pants"), new LLFindActualWearablesOfType(LLWearableType::WT_PANTS))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("shoes"), new LLFindActualWearablesOfType(LLWearableType::WT_SHOES))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("socks"), new LLFindActualWearablesOfType(LLWearableType::WT_SOCKS))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("jacket"), new LLFindActualWearablesOfType(LLWearableType::WT_JACKET))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("gloves"), new LLFindActualWearablesOfType(LLWearableType::WT_GLOVES))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("undershirt"), new LLFindActualWearablesOfType(LLWearableType::WT_UNDERSHIRT))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("underpants"), new LLFindActualWearablesOfType(LLWearableType::WT_UNDERPANTS))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("skirt"), new LLFindActualWearablesOfType(LLWearableType::WT_SKIRT))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("alpha"), new LLFindActualWearablesOfType(LLWearableType::WT_ALPHA))); + mListViewItemTypes.push_back(new LLFilterItem(LLTrans::getString("tattoo"), new LLFindActualWearablesOfType(LLWearableType::WT_TATTOO))); mCurrentOutfitName = getChild<LLTextBox>("curr_outfit_name"); mStatus = getChild<LLTextBox>("status"); @@ -252,7 +274,7 @@ BOOL LLPanelOutfitEdit::postBuild() mAddWearablesPanel = getChild<LLPanel>("add_wearables_panel"); - mInventoryItemsPanel = getChild<LLInventoryPanel>("inventory_items"); + mInventoryItemsPanel = getChild<LLInventoryPanel>("folder_view"); mInventoryItemsPanel->setFilterTypes(ALL_ITEMS_MASK); mInventoryItemsPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); mInventoryItemsPanel->setSelectCallback(boost::bind(&LLPanelOutfitEdit::onInventorySelectionChange, this, _1, _2)); @@ -260,15 +282,24 @@ BOOL LLPanelOutfitEdit::postBuild() mCOFDragAndDropObserver = new LLCOFDragAndDropObserver(mInventoryItemsPanel->getModel()); - mFilterComboBox = getChild<LLComboBox>("filter_wearables_combobox"); - mFilterComboBox->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onTypeFilterChanged, this, _1)); - mFilterComboBox->removeall(); - for (U32 i = 0; i < mLookItemTypes.size(); ++i) + mFolderViewFilterCmbBox = getChild<LLComboBox>("folder_view_filter_combobox"); + mFolderViewFilterCmbBox->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onFolderViewFilterCommitted, this, _1)); + mFolderViewFilterCmbBox->removeall(); + for (U32 i = 0; i < mFolderViewItemTypes.size(); ++i) { - mFilterComboBox->add(mLookItemTypes[i].displayName); + mFolderViewFilterCmbBox->add(mFolderViewItemTypes[i].displayName); } - mFilterComboBox->setCurrentByIndex(LIT_ALL); + mFolderViewFilterCmbBox->setCurrentByIndex(FVIT_ALL); + mListViewFilterCmbBox = getChild<LLComboBox>("list_view_filter_combobox"); + mListViewFilterCmbBox->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onListViewFilterCommitted, this, _1)); + mListViewFilterCmbBox->removeall(); + for (U32 i = 0; i < mListViewItemTypes.size(); ++i) + { + mListViewFilterCmbBox->add(mListViewItemTypes[i]->displayName); + } + mListViewFilterCmbBox->setCurrentByIndex(LVIT_ALL); + mSearchFilter = getChild<LLFilterEditor>("look_item_filter"); mSearchFilter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onSearchEdit, this, _2)); @@ -283,11 +314,8 @@ BOOL LLPanelOutfitEdit::postBuild() childSetAction(REVERT_BTN, boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance())); - mWearableListMaskCollector = new LLFindNonLinksByMask(ALL_ITEMS_MASK); - mWearableListTypeCollector = new LLFindActualWearablesOfType(LLWearableType::WT_NONE); - - mWearableItemsPanel = getChild<LLPanel>("filtered_wearables_panel"); - mWearableItemsList = getChild<LLInventoryItemsList>("filtered_wearables_list"); + mWearablesListViewPanel = getChild<LLPanel>("filtered_wearables_panel"); + mWearableItemsList = getChild<LLInventoryItemsList>("list_view"); mSaveComboBtn.reset(new LLSaveOutfitComboBtn(this)); return TRUE; @@ -300,7 +328,7 @@ void LLPanelOutfitEdit::onOpen(const LLSD& key) { // *TODO: this method is called even panel is not visible to user because its parent layout panel is hidden. // So, we can defer initializing a bit. - mWearableListManager = new LLFilteredWearableListManager(mWearableItemsList, mWearableListMaskCollector); + mWearableListManager = new LLFilteredWearableListManager(mWearableItemsList, mListViewItemTypes[LVIT_ALL]->collector); mWearableListManager->populateList(); displayCurrentOutfit(); mInitialized = true; @@ -328,13 +356,17 @@ void LLPanelOutfitEdit::showAddWearablesPanel(bool show_add_wearables) childSetValue("show_add_wearables_btn", show_add_wearables); - childSetVisible("filter_wearables_combobox", show_add_wearables); + updateFiltersVisibility(); childSetVisible("filter_button", show_add_wearables); //search filter should be disabled if (!show_add_wearables) { childSetValue("filter_button", false); + + mFolderViewFilterCmbBox->setVisible(false); + mListViewFilterCmbBox->setVisible(false); + showWearablesFilter(); } @@ -358,33 +390,40 @@ void LLPanelOutfitEdit::showWearablesFilter() void LLPanelOutfitEdit::showWearablesListView() { - if(switchPanels(mInventoryItemsPanel, mWearableItemsPanel)) + if(switchPanels(mInventoryItemsPanel, mWearablesListViewPanel)) { mFolderViewBtn->setToggleState(FALSE); mFolderViewBtn->setImageOverlay(getString("folder_view_off"), mFolderViewBtn->getImageOverlayHAlign()); mListViewBtn->setImageOverlay(getString("list_view_on"), mListViewBtn->getImageOverlayHAlign()); + updateFiltersVisibility(); } mListViewBtn->setToggleState(TRUE); } void LLPanelOutfitEdit::showWearablesFolderView() { - if(switchPanels(mWearableItemsPanel, mInventoryItemsPanel)) + if(switchPanels(mWearablesListViewPanel, mInventoryItemsPanel)) { mListViewBtn->setToggleState(FALSE); mListViewBtn->setImageOverlay(getString("list_view_off"), mListViewBtn->getImageOverlayHAlign()); mFolderViewBtn->setImageOverlay(getString("folder_view_on"), mFolderViewBtn->getImageOverlayHAlign()); + updateFiltersVisibility(); } mFolderViewBtn->setToggleState(TRUE); } -void LLPanelOutfitEdit::onTypeFilterChanged(LLUICtrl* ctrl) +void LLPanelOutfitEdit::updateFiltersVisibility() +{ + mListViewFilterCmbBox->setVisible(mWearablesListViewPanel->getVisible()); + mFolderViewFilterCmbBox->setVisible(mInventoryItemsPanel->getVisible()); +} + +void LLPanelOutfitEdit::onFolderViewFilterCommitted(LLUICtrl* ctrl) { - U32 curr_filter_type = mFilterComboBox->getCurrentIndex(); - mInventoryItemsPanel->setFilterTypes(mLookItemTypes[curr_filter_type].inventoryMask); + S32 curr_filter_type = mFolderViewFilterCmbBox->getCurrentIndex(); + if (curr_filter_type < 0) return; - mWearableListMaskCollector->setFilterMask(mLookItemTypes[curr_filter_type].inventoryMask); - mWearableListManager->setFilterCollector(mWearableListMaskCollector); + mInventoryItemsPanel->setFilterTypes(mFolderViewItemTypes[curr_filter_type].inventoryMask); mSavedFolderState->setApply(TRUE); mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -396,6 +435,14 @@ void LLPanelOutfitEdit::onTypeFilterChanged(LLUICtrl* ctrl) LLInventoryModelBackgroundFetch::instance().start(); } +void LLPanelOutfitEdit::onListViewFilterCommitted(LLUICtrl* ctrl) +{ + S32 curr_filter_type = mListViewFilterCmbBox->getCurrentIndex(); + if (curr_filter_type < 0) return; + + mWearableListManager->setFilterCollector(mListViewItemTypes[curr_filter_type]->collector); +} + void LLPanelOutfitEdit::onSearchEdit(const std::string& string) { if (mSearchString != string) @@ -453,7 +500,7 @@ void LLPanelOutfitEdit::onAddToOutfitClicked(void) selected_id = listenerp->getUUID(); } - else if (mWearableItemsPanel->getVisible()) + else if (mWearablesListViewPanel->getVisible()) { selected_id = mWearableItemsList->getSelectedUUID(); } @@ -537,10 +584,16 @@ void LLPanelOutfitEdit::onInventorySelectionChange(const std::deque<LLFolderView } -void LLPanelOutfitEdit::applyFilter(e_look_item_type type) +void LLPanelOutfitEdit::applyFolderViewFilter(EFolderViewItemType type) +{ + mFolderViewFilterCmbBox->setCurrentByIndex(type); + mFolderViewFilterCmbBox->onCommit(); +} + +void LLPanelOutfitEdit::applyListViewFilter(EListViewItemType type) { - mFilterComboBox->setCurrentByIndex(type); - mFilterComboBox->onCommit(); + mListViewFilterCmbBox->setCurrentByIndex(type); + mListViewFilterCmbBox->onCommit(); } void LLPanelOutfitEdit::filterWearablesBySelectedItem(void) @@ -561,14 +614,15 @@ void LLPanelOutfitEdit::filterWearablesBySelectedItem(void) if (nothing_selected) { showWearablesFolderView(); + applyFolderViewFilter(FVIT_ALL); } if (more_than_one_selected) { showWearablesListView(); + applyListViewFilter(LVIT_ALL); } - - applyFilter(LIT_ALL); + return; } @@ -585,7 +639,7 @@ void LLPanelOutfitEdit::filterWearablesBySelectedItem(void) { //Inventory misses an item with non-zero id showWearablesListView(); - applyFilter(LIT_ALL); + applyListViewFilter(LVIT_ALL); return; } @@ -595,14 +649,13 @@ void LLPanelOutfitEdit::filterWearablesBySelectedItem(void) { //single clothing or bodypart item is selected showFilteredWearablesListView(item->getWearableType()); - mFilterComboBox->setLabel(getString("Filter.Custom")); return; } else { //attachment is selected showWearablesListView(); - applyFilter(LIT_ATTACHMENT); + applyListViewFilter(LVIT_ATTACHMENT); return; } } @@ -707,6 +760,7 @@ void LLPanelOutfitEdit::updateVerbs() mStatus->setText(outfit_is_dirty ? getString("unsaved_changes") : getString("now_editing")); + updateCurrentOutfitName(); } bool LLPanelOutfitEdit::switchPanels(LLPanel* switch_from_panel, LLPanel* switch_to_panel) @@ -739,11 +793,11 @@ void LLPanelOutfitEdit::onAddMoreButtonClicked() void LLPanelOutfitEdit::showFilteredWearablesListView(LLWearableType::EType type) { - mFilterComboBox->setLabel(getString("Filter.Custom")); - mWearableListTypeCollector->setType(type); - mWearableListManager->setFilterCollector(mWearableListTypeCollector); showAddWearablesPanel(true); showWearablesListView(); + + //e_list_view_item_type implicitly contains LLWearableType::EType starting from LVIT_SHAPE + applyListViewFilter((EListViewItemType) (LVIT_SHAPE + type)); } diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index d19ede04f1..56c6c6d680 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -42,6 +42,7 @@ #include "llremoteparcelrequest.h" #include "llinventory.h" +#include "llinventoryfunctions.h" #include "llinventoryitemslist.h" #include "llinventorymodel.h" @@ -69,21 +70,59 @@ class LLPanelOutfitEdit : public LLPanel LOG_CLASS(LLPanelOutfitEdit); public: - // NOTE: initialize mLookItemTypes at the index of any new enum you add in the LLPanelOutfitEdit() constructor - typedef enum e_look_item_type + // NOTE: initialize mFolderViewItemTypes at the index of any new enum you add in the LLPanelOutfitEdit() constructor + typedef enum e_folder_view_item_type { - LIT_ALL = 0, - LIT_WEARABLE, // clothing or shape - LIT_ATTACHMENT, - NUM_LOOK_ITEM_TYPES - } ELookItemType; + FVIT_ALL = 0, + FVIT_WEARABLE, // clothing or shape + FVIT_ATTACHMENT, + NUM_FOLDER_VIEW_ITEM_TYPES + } EFolderViewItemType; + //should reflect order from LLWearableType::EType + typedef enum e_list_view_item_type + { + LVIT_ALL = 0, + LVIT_CLOTHING, + LVIT_BODYPART, + LVIT_ATTACHMENT, + LVIT_SHAPE, + LVIT_SKIN, + LVIT_HAIR, + LVIT_EYES, + LVIT_SHIRT, + LVIT_PANTS, + LVIT_SHOES, + LVIT_SOCKS, + LVIT_JACKET, + LVIT_GLOVES, + LVIT_UNDERSHIRT, + LVIT_UNDERPANTS, + LVIT_SKIRT, + LVIT_ALPHA, + LVIT_TATTOO, + NUM_LIST_VIEW_ITEM_TYPES + } EListViewItemType; + struct LLLookItemType { std::string displayName; U64 inventoryMask; LLLookItemType() : displayName("NONE"), inventoryMask(0) {} LLLookItemType(std::string name, U64 mask) : displayName(name), inventoryMask(mask) {} }; + + struct LLFilterItem { + std::string displayName; + LLInventoryCollectFunctor* collector; + LLFilterItem() : displayName("NONE"), collector(NULL) {} + LLFilterItem(std::string name, LLInventoryCollectFunctor* _collector) : displayName(name), collector(_collector) {} + ~LLFilterItem() { delete collector; } + + //the struct is not supposed to by copied, either way the destructor kills collector + //LLPointer is not used as it requires LLInventoryCollectFunctor to extend LLRefCount what it doesn't do + private: + LLFilterItem(const LLFilterItem& filter_item) {}; + }; LLPanelOutfitEdit(); /*virtual*/ ~LLPanelOutfitEdit(); @@ -101,12 +140,16 @@ public: void showWearablesListView(); void showWearablesFolderView(); - void onTypeFilterChanged(LLUICtrl* ctrl); + void updateFiltersVisibility(); + + void onFolderViewFilterCommitted(LLUICtrl* ctrl); + void onListViewFilterCommitted(LLUICtrl* ctrl); void onSearchEdit(const std::string& string); void onInventorySelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); void onAddToOutfitClicked(void); - void applyFilter(e_look_item_type type); + void applyFolderViewFilter(EFolderViewItemType type); + void applyListViewFilter(EListViewItemType type); /** * Filter items in views of Add Wearables Panel and show appropriate view depending on currently selected COF item(s) @@ -159,18 +202,18 @@ private: LLButton* mFolderViewBtn; LLButton* mListViewBtn; LLPanel* mAddWearablesPanel; - LLComboBox* mFilterComboBox; - - LLFindNonLinksByMask* mWearableListMaskCollector; - LLFindWearablesOfType* mWearableListTypeCollector; + + LLComboBox* mFolderViewFilterCmbBox; + LLComboBox* mListViewFilterCmbBox; LLFilteredWearableListManager* mWearableListManager; LLInventoryItemsList* mWearableItemsList; - LLPanel* mWearableItemsPanel; + LLPanel* mWearablesListViewPanel; LLCOFDragAndDropObserver* mCOFDragAndDropObserver; - std::vector<LLLookItemType> mLookItemTypes; + std::vector<LLLookItemType> mFolderViewItemTypes; + std::vector<LLFilterItem*> mListViewItemTypes; LLCOFWearables* mCOFWearables; LLMenuGL* mGearMenu; diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 8b451c156c..5563214407 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -91,6 +91,7 @@ public: registrar.add("Gear.Create", boost::bind(&LLOutfitListGearMenu::onCreate, this, _2)); enable_registrar.add("Gear.OnEnable", boost::bind(&LLOutfitListGearMenu::onEnable, this, _2)); + enable_registrar.add("Gear.OnVisible", boost::bind(&LLOutfitListGearMenu::onVisible, this, _2)); mMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>( "menu_outfit_gear.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); @@ -99,6 +100,28 @@ public: LLMenuGL* getMenu() { return mMenu; } + void show(LLView* spawning_view) + { + if (!mMenu) return; + + updateItemsVisibility(); + mMenu->buildDrawLabels(); + mMenu->updateParent(LLMenuGL::sMenuContainer); + S32 menu_x = 0; + S32 menu_y = spawning_view->getRect().getHeight() + mMenu->getRect().getHeight(); + LLMenuGL::showPopup(spawning_view, mMenu, menu_x, menu_y); + } + + void updateItemsVisibility() + { + if (!mMenu) return; + + bool have_selection = getSelectedOutfitID().notNull(); + mMenu->setItemVisible("sepatator1", have_selection); + mMenu->setItemVisible("sepatator2", have_selection); + mMenu->arrangeAndClear(); // update menu height + } + private: const LLUUID& getSelectedOutfitID() { @@ -169,6 +192,31 @@ private: bool onEnable(LLSD::String param) { const LLUUID& selected_outfit_id = getSelectedOutfitID(); + if (selected_outfit_id.isNull()) // no selection or invalid outfit selected + { + return false; + } + + if ("rename" == param) + { + return get_is_category_renameable(&gInventory, selected_outfit_id); + } + else if ("delete" == param) + { + return LLAppearanceMgr::instance().getCanRemoveOutfit(selected_outfit_id); + } + + return true; + } + + bool onVisible(LLSD::String param) + { + const LLUUID& selected_outfit_id = getSelectedOutfitID(); + if (selected_outfit_id.isNull()) // no selection or invalid outfit selected + { + return false; + } + bool is_worn = LLAppearanceMgr::instance().getBaseOutfitUUID() == selected_outfit_id; if ("wear" == param) @@ -179,14 +227,6 @@ private: { return is_worn; } - else if ("rename" == param) - { - return get_is_category_renameable(&gInventory, selected_outfit_id); - } - else if ("delete" == param) - { - return LLAppearanceMgr::instance().getCanRemoveOutfit(selected_outfit_id); - } return true; } @@ -205,6 +245,7 @@ LLPanelOutfitsInventory::LLPanelOutfitsInventory() : mSavedFolderState = new LLSaveFolderState(); mSavedFolderState->setApply(FALSE); gAgentWearables.addLoadedCallback(boost::bind(&LLPanelOutfitsInventory::onWearablesLoaded, this)); + gAgentWearables.addLoadingStartedCallback(boost::bind(&LLPanelOutfitsInventory::onWearablesLoading, this)); LLOutfitObserver& observer = LLOutfitObserver::instance(); observer.addBOFChangedCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this)); @@ -342,7 +383,6 @@ void LLPanelOutfitsInventory::onWearButtonClick() if (!isCOFPanelActive()) { mMyOutfitsPanel->performAction("replaceoutfit"); - setWearablesLoading(true); } else { @@ -523,28 +563,21 @@ void LLPanelOutfitsInventory::updateListCommands() { bool trash_enabled = isActionEnabled("delete"); bool wear_enabled = isActionEnabled("wear"); + bool wear_visible = !isCOFPanelActive(); bool make_outfit_enabled = isActionEnabled("save_outfit"); mListCommands->childSetEnabled("trash_btn", trash_enabled); mListCommands->childSetEnabled("wear_btn", wear_enabled); - mListCommands->childSetVisible("wear_btn", wear_enabled); + mListCommands->childSetVisible("wear_btn", wear_visible); mSaveComboBtn->setMenuItemEnabled("save_outfit", make_outfit_enabled); } void LLPanelOutfitsInventory::showGearMenu() { - LLMenuGL* menu = mGearMenu ? mGearMenu->getMenu() : NULL; - if (menu) - { - menu->buildDrawLabels(); - menu->updateParent(LLMenuGL::sMenuContainer); - LLView* spawning_view = getChild<LLView>("options_gear_btn"); - S32 menu_x, menu_y; - //show menu in co-ordinates of panel - spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this); - menu_y += menu->getRect().getHeight(); - LLMenuGL::showPopup(this, menu, menu_x, menu_y); - } + if (!mGearMenu) return; + + LLView* spawning_view = getChild<LLView>("options_gear_btn"); + mGearMenu->show(spawning_view); } void LLPanelOutfitsInventory::onTrashButtonClick() @@ -555,11 +588,25 @@ void LLPanelOutfitsInventory::onTrashButtonClick() void LLPanelOutfitsInventory::onClipboardAction(const LLSD& userdata) { std::string command_name = userdata.asString(); - // TODO: add handling "My Outfits" tab. if (isCOFPanelActive()) { getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name); } + else // "My Outfits" tab active + { + if (command_name == "delete") + { + const LLUUID& selected_outfit_id = mMyOutfitsPanel->getSelectedOutfitUUID(); + if (selected_outfit_id.notNull()) + { + remove_category(&gInventory, selected_outfit_id); + } + } + else + { + llwarns << "Unrecognized action" << llendl; + } + } updateListCommands(); updateVerbs(); } @@ -614,7 +661,6 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) { BOOL can_delete = FALSE; - // TODO: add handling "My Outfits" tab. if (isCOFPanelActive()) { LLFolderView* root = getActivePanel()->getRootFolder(); @@ -630,10 +676,15 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) LLFolderViewItem *item = root->getItemByID(item_id); can_delete &= item->getListener()->isItemRemovable(); } - return can_delete; } } - return FALSE; + else // "My Outfits" tab active + { + const LLUUID& selected_outfit = mMyOutfitsPanel->getSelectedOutfitUUID(); + can_delete = LLAppearanceMgr::instance().getCanRemoveOutfit(selected_outfit); + } + + return can_delete; } if (command_name == "remove_link") { @@ -668,6 +719,7 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata) { return FALSE; } + return hasItemsSelected(); } if (command_name == "save_outfit") { @@ -690,7 +742,6 @@ bool LLPanelOutfitsInventory::hasItemsSelected() { bool has_items_selected = false; - // TODO: add handling "My Outfits" tab. if (isCOFPanelActive()) { LLFolderView* root = getActivePanel()->getRootFolder(); @@ -700,6 +751,10 @@ bool LLPanelOutfitsInventory::hasItemsSelected() has_items_selected = (selection_set.size() > 0); } } + else // My Outfits Tab is active + { + has_items_selected = mMyOutfitsPanel->getSelectedOutfitUUID().notNull(); + } return has_items_selected; } @@ -730,6 +785,7 @@ void LLPanelOutfitsInventory::initTabPanels() mCurrentOutfitPanel->setSelectCallback(boost::bind(&LLPanelOutfitsInventory::onTabSelectionChange, this, mCurrentOutfitPanel, _1, _2)); mMyOutfitsPanel = getChild<LLOutfitsList>(OUTFITS_TAB_NAME); + mMyOutfitsPanel->addSelectionChangeCallback(boost::bind(&LLPanelOutfitsInventory::updateVerbs, this)); mAppearanceTabs = getChild<LLTabContainer>("appearance_tabs"); mAppearanceTabs->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::onTabChange, this)); @@ -798,6 +854,11 @@ void LLPanelOutfitsInventory::onWearablesLoaded() setWearablesLoading(false); } +void LLPanelOutfitsInventory::onWearablesLoading() +{ + setWearablesLoading(true); +} + // static LLSidepanelAppearance* LLPanelOutfitsInventory::getAppearanceSP() { diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index d58ae554b0..863dc9dd7c 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -127,6 +127,7 @@ protected: bool hasItemsSelected(); void setWearablesLoading(bool val); void onWearablesLoaded(); + void onWearablesLoading(); private: LLPanel* mListCommands; LLOutfitListGearMenu* mGearMenu; diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index c8abcc83c4..1f979b0ef1 100644 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -84,7 +84,9 @@ LLPanelPlaceProfile::LLPanelPlaceProfile() // virtual LLPanelPlaceProfile::~LLPanelPlaceProfile() -{} +{ + gIdleCallbacks.deleteFunction(&LLPanelPlaceProfile::updateYouAreHereBanner, this); +} // virtual BOOL LLPanelPlaceProfile::postBuild() diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index a27afeab7c..8fe78a0f81 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -52,6 +52,18 @@ static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR; +// helper function to update AvatarList Item's indicator in the voice participant list +static void update_speaker_indicator(const LLAvatarList* const avatar_list, const LLUUID& avatar_uuid, bool is_muted) +{ + LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(avatar_list->getItemByValue(avatar_uuid)); + if (item) + { + LLOutputMonitorCtrl* indicator = item->getChild<LLOutputMonitorCtrl>("speaking_indicator"); + indicator->setIsMuted(is_muted); + } +} + + // See EXT-4301. /** * class LLAvalineUpdater - observe the list of voice participants in session and check @@ -354,6 +366,20 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) } } } + + // update voice mute state of all items. See EXT-7235 + LLSpeakerMgr::speaker_list_t speaker_list; + + // Use also participants which are not in voice session now (the second arg is TRUE). + // They can already have mModeratorMutedVoice set from the previous voice session + // and LLSpeakerVoiceModerationEvent will not be sent when speaker manager is updated next time. + mSpeakerMgr->getSpeakerList(&speaker_list, TRUE); + for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++) + { + const LLPointer<LLSpeaker>& speakerp = *it; + + update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice); + } } } @@ -506,12 +532,7 @@ bool LLParticipantList::onSpeakerMuteEvent(LLPointer<LLOldEvents::LLEvent> event // update UI on confirmation of moderator mutes if (event->getValue().asString() == "voice") { - LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(mAvatarList->getItemByValue(speakerp->mID)); - if (item) - { - LLOutputMonitorCtrl* indicator = item->getChild<LLOutputMonitorCtrl>("speaking_indicator"); - indicator->setIsMuted(speakerp->mModeratorMutedVoice); - } + update_speaker_indicator(mAvatarList, speakerp->mID, speakerp->mModeratorMutedVoice); } return true; } diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index e23643da0b..e2d4f5ad45 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -83,6 +83,7 @@ LLSidepanelAppearance::LLSidepanelAppearance() : mOpened(false) { LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); + outfit_observer.addBOFReplacedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); outfit_observer.addBOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); outfit_observer.addCOFChangedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); } @@ -352,12 +353,12 @@ void LLSidepanelAppearance::toggleWearableEditPanel(BOOL visible, LLWearable *we if (visible) { - mEditWearable->setWearable(wearable); - mEditWearable->onOpen(LLSD()); // currently no-op, just for consistency if (!disable_camera_switch && gSavedSettings.getBOOL("AppearanceCameraMovement") ) { gAgentCamera.changeCameraToCustomizeAvatar(); } + mEditWearable->setWearable(wearable); + mEditWearable->onOpen(LLSD()); // currently no-op, just for consistency } else { diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 9406f80b75..fed39c362e 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -35,6 +35,7 @@ #include "lltextbox.h" #include "llagentcamera.h" +#include "llappviewer.h" #include "llbottomtray.h" #include "llsidetray.h" #include "llviewerwindow.h" @@ -272,9 +273,18 @@ BOOL LLSideTray::postBuild() collapseSideBar(); setMouseOpaque(false); + + LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLSideTray::handleLoginComplete, this)); + return true; } +void LLSideTray::handleLoginComplete() +{ + //reset tab to "home" tab if it was changesd during login process + selectTabByName("sidebar_home"); +} + LLSideTrayTab* LLSideTray::getTab(const std::string& name) { return getChild<LLSideTrayTab>(name,false); diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index e176ff5aff..3a8d308425 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -161,6 +161,8 @@ public: commit_signal_t& getCollapseSignal() { return mCollapseSignal; } + void handleLoginComplete(); + protected: LLSideTrayTab* getTab (const std::string& name); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index fff80e57dc..df5be34e39 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -199,7 +199,6 @@ #include "llstartuplistener.h" #if LL_WINDOWS -#include "llwindebug.h" #include "lldxhardware.h" #endif @@ -2495,8 +2494,7 @@ void LLStartUp::saveInitialOutfit() { sWearablesLoadedCon.disconnect(); } - - LLAppearanceMgr::getInstance()->makeNewOutfitLinks(sInitialOutfit); + LLAppearanceMgr::getInstance()->makeNewOutfitLinks(sInitialOutfit,false); } std::string& LLStartUp::getInitialOutfitName() diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index 2859dabfba..56b5d7467c 100644 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -45,10 +45,11 @@ struct ViewerFolderEntry : public LLDictionaryEntry ViewerFolderEntry(const std::string &new_category_name, // default name when creating a new category of this type const std::string &icon_name_open, // name of the folder icon const std::string &icon_name_closed, - BOOL is_quiet // folder doesn't need a UI update when changed + BOOL is_quiet, // folder doesn't need a UI update when changed + const std::string &dictionary_name = empty_string // no reverse lookup needed on non-ensembles, so in most cases just leave this blank ) : - LLDictionaryEntry(empty_string), // no reverse lookup needed on non-ensembles, so just leave this blank + LLDictionaryEntry(dictionary_name), mNewCategoryName(new_category_name), mIconNameOpen(icon_name_open), mIconNameClosed(icon_name_closed), @@ -65,8 +66,11 @@ struct ViewerFolderEntry : public LLDictionaryEntry ) : LLDictionaryEntry(xui_name), + /* Just use default icons until we actually support ensembles mIconNameOpen(icon_name), mIconNameClosed(icon_name), + */ + mIconNameOpen("Inv_FolderOpen"), mIconNameClosed("Inv_FolderClosed"), mNewCategoryName(new_category_name), mIsQuiet(FALSE) { @@ -132,7 +136,7 @@ LLViewerFolderDictionary::LLViewerFolderDictionary() addEntry(LLFolderType::FT_MY_OUTFITS, new ViewerFolderEntry("My Outfits", "Inv_SysOpen", "Inv_SysClosed", TRUE)); addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "Inv_SysOpen", "Inv_SysClosed", FALSE)); - addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "Inv_SysOpen", "Inv_SysClosed", FALSE)); + addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "Inv_FolderOpen", "Inv_FolderClosed", FALSE, "default")); } bool LLViewerFolderDictionary::initEnsemblesFromFile() diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 5570fe5fec..f741e1bc10 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -318,11 +318,13 @@ class LLFileUploadBulk : public view_listener_t LLStringUtil::trim(asset_name); std::string display_name = LLStringUtil::null; + LLAssetStorage::LLStoreAssetCallback callback = NULL; S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); - upload_new_resource(filename, asset_name, asset_name, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, + void *userdata = NULL; + upload_new_resource(filename, asset_name, asset_name, 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(), display_name, - NULL, expected_upload_cost); + callback, expected_upload_cost, userdata); // *NOTE: Ew, we don't iterate over the file list here, // we handle the next files in upload_done_callback() @@ -478,15 +480,16 @@ void handle_compress_image(void*) } void upload_new_resource(const std::string& src_filename, std::string name, - std::string desc, + std::string desc, S32 compression_info, LLFolderType::EType destination_folder_type, LLInventoryType::EType inv_type, U32 next_owner_perms, U32 group_perms, U32 everyone_perms, const std::string& display_name, - boost::function<void(const LLUUID& uuid)> callback, - S32 expected_upload_cost) + LLAssetStorage::LLStoreAssetCallback callback, + S32 expected_upload_cost, + void *userdata) { // Generate the temporary UUID. std::string filename = gDirUtilp->getTempFilename(); @@ -768,9 +771,9 @@ void upload_new_resource(const std::string& src_filename, std::string name, { t_disp_name = src_filename; } - upload_new_resource(tid, asset_type, name, desc, + upload_new_resource(tid, asset_type, name, desc, compression_info, // tid destination_folder_type, inv_type, next_owner_perms, group_perms, everyone_perms, - display_name, callback, expected_upload_cost); + display_name, callback, expected_upload_cost, userdata); } else { @@ -889,28 +892,30 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt LLStringUtil::trim(asset_name); std::string display_name = LLStringUtil::null; + LLAssetStorage::LLStoreAssetCallback callback = NULL; + void *userdata = NULL; upload_new_resource(next_file, asset_name, asset_name, // file - LLFolderType::FT_NONE, LLInventoryType::IT_NONE, + 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, PERM_NONE, PERM_NONE, PERM_NONE, display_name, - NULL, - expected_upload_cost); // assuming next in a group of uploads is of roughly the same type, i.e. same upload cost - + callback, + expected_upload_cost, // assuming next in a group of uploads is of roughly the same type, i.e. same upload cost + userdata); } } -void upload_new_resource(const LLTransactionID &tid, - LLAssetType::EType asset_type, +void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type, std::string name, - std::string desc, + std::string desc, S32 compression_info, LLFolderType::EType destination_folder_type, LLInventoryType::EType inv_type, U32 next_owner_perms, U32 group_perms, U32 everyone_perms, const std::string& display_name, - boost::function<void(const LLUUID& uuid)> callback, - S32 expected_upload_cost) + LLAssetStorage::LLStoreAssetCallback callback, + S32 expected_upload_cost, + void *userdata) { if(gDisconnected) { @@ -954,26 +959,79 @@ void upload_new_resource(const LLTransactionID &tid, upload_message.append(display_name); LLUploadDialog::modalUploadDialog(upload_message); + llinfos << "*** Uploading: " << llendl; + llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl; + llinfos << "UUID: " << uuid << llendl; + llinfos << "Name: " << name << llendl; + llinfos << "Desc: " << desc << llendl; + llinfos << "Expected Upload Cost: " << expected_upload_cost << llendl; + lldebugs << "Folder: " << gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type) << llendl; + lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl; std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory"); - - if (url.empty()) { - llwarns << "Could not get NewFileAgentInventory capability" << llendl; - return; - } + if (!url.empty()) + { + llinfos << "New Agent Inventory via capability" << llendl; + LLSD body; + body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type); + body["asset_type"] = LLAssetType::lookup(asset_type); + body["inventory_type"] = LLInventoryType::lookup(inv_type); + body["name"] = name; + body["description"] = desc; + body["next_owner_mask"] = LLSD::Integer(next_owner_perms); + body["group_mask"] = LLSD::Integer(group_perms); + body["everyone_mask"] = LLSD::Integer(everyone_perms); + body["expected_upload_cost"] = LLSD::Integer(expected_upload_cost); + + //std::ostringstream llsdxml; + //LLSDSerialize::toPrettyXML(body, llsdxml); + //llinfos << "posting body to capability: " << llsdxml.str() << llendl; - llinfos << "New Agent Inventory via capability" << llendl; - LLSD body; - body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type); - body["asset_type"] = LLAssetType::lookup(asset_type); - body["inventory_type"] = LLInventoryType::lookup(inv_type); - body["name"] = name; - body["description"] = desc; - body["next_owner_mask"] = LLSD::Integer(next_owner_perms); - body["group_mask"] = LLSD::Integer(group_perms); - body["everyone_mask"] = LLSD::Integer(everyone_perms); - body["expected_upload_cost"] = LLSD::Integer(expected_upload_cost); + LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type)); + } + else + { + llinfos << "NewAgentInventory capability not found, new agent inventory via asset system." << llendl; + // check for adequate funds + // TODO: do this check on the sim + if (LLAssetType::AT_SOUND == asset_type || + LLAssetType::AT_TEXTURE == asset_type || + LLAssetType::AT_ANIMATION == asset_type) + { + S32 balance = gStatusBar->getBalance(); + if (balance < expected_upload_cost) + { + LLStringUtil::format_map_t args; + args["NAME"] = name; + args["AMOUNT"] = llformat("%d", expected_upload_cost); + // insufficient funds, bail on this upload + LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("UploadingCosts", args), expected_upload_cost ); + return; + } + } - LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type, callback)); + LLResourceData* data = new LLResourceData; + data->mAssetInfo.mTransactionID = tid; + data->mAssetInfo.mUuid = uuid; + data->mAssetInfo.mType = asset_type; + data->mAssetInfo.mCreatorID = gAgentID; + data->mInventoryType = inv_type; + data->mNextOwnerPerm = next_owner_perms; + data->mExpectedUploadCost = expected_upload_cost; + data->mUserData = userdata; + data->mAssetInfo.setName(name); + data->mAssetInfo.setDescription(desc); + data->mPreferredLocation = destination_folder_type; + + LLAssetStorage::LLStoreAssetCallback asset_callback = &upload_done_callback; + if (callback) + { + asset_callback = callback; + } + gAssetStorage->storeAssetData(data->mAssetInfo.mTransactionID, data->mAssetInfo.mType, + asset_callback, + (void*)data, + FALSE); + } } void init_menu_file() diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index 33f8243ac0..1e6d13f1c6 100644 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -34,35 +34,41 @@ #define LLVIEWERMENUFILE_H #include "llfoldertype.h" +#include "llassetstorage.h" #include "llinventorytype.h" class LLTransactionID; + void init_menu_file(); void upload_new_resource(const std::string& src_filename, std::string name, std::string desc, + S32 compression_info, LLFolderType::EType destination_folder_type, LLInventoryType::EType inv_type, U32 next_owner_perms, U32 group_perms, U32 everyone_perms, const std::string& display_name, - boost::function<void(const LLUUID& uuid)> callback, - S32 expected_upload_cost); + LLAssetStorage::LLStoreAssetCallback callback, + S32 expected_upload_cost, + void *userdata); void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType type, std::string name, std::string desc, + S32 compression_info, LLFolderType::EType destination_folder_type, LLInventoryType::EType inv_type, U32 next_owner_perms, U32 group_perms, U32 everyone_perms, const std::string& display_name, - boost::function<void(const LLUUID& uuid)> callback, - S32 expected_upload_cost); + LLAssetStorage::LLStoreAssetCallback callback, + S32 expected_upload_cost, + void *userdata); #endif diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index b00fa39815..3d107555bf 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -109,10 +109,6 @@ #include <boost/algorithm/string/split.hpp> // #include <boost/regex.hpp> -#if LL_WINDOWS // For Windows specific error handler -#include "llwindebug.h" // For the invalid message handler -#endif - #include "llnotificationmanager.h" // #if LL_MSVC diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 39649f0370..4dc9edb247 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -402,19 +402,16 @@ void LLVivoxVoiceClient::init(LLPumpIO *pump) void LLVivoxVoiceClient::terminate() { - -// leaveAudioSession(); - logout(); - // As of SDK version 4885, this should no longer be necessary. It will linger after the socket close if it needs to. - // ms_sleep(2000); - connectorShutdown(); - closeSocket(); // Need to do this now -- bad things happen if the destructor does it later. - - // This will do unpleasant things on windows. -// killGateway(); - - - + if(mConnected) + { + logout(); + connectorShutdown(); + closeSocket(); // Need to do this now -- bad things happen if the destructor does it later. + } + else + { + killGateway(); + } } const LLVoiceVersionInfo& LLVivoxVoiceClient::getVersion() diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 58a0ea8ef5..5e9c4dcec8 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -38,7 +38,6 @@ #include "llagentwearables.h" #include "llappearancemgr.h" #include "llinventoryfunctions.h" -#include "llinventorymodel.h" #include "llmenugl.h" // for LLContextMenu #include "lltransutil.h" #include "llviewerattachmenu.h" @@ -112,6 +111,19 @@ LLPanelWearableOutfitItem::LLPanelWearableOutfitItem(LLViewerInventoryItem* item { } +// virtual +void LLPanelWearableOutfitItem::updateItem(const std::string& name) +{ + std::string search_label = name; + + if (mItem && get_is_item_worn(mItem->getUUID())) + { + search_label += LLTrans::getString("worn"); + } + + LLPanelInventoryListItemBase::updateItem(search_label); +} + ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// @@ -273,22 +285,16 @@ LLPanelDummyClothingListItem* LLPanelDummyClothingListItem::create(LLWearableTyp return list_item; } -void LLPanelDummyClothingListItem::updateItem() -{ - std::string title = wearableTypeToString(mWearableType); - setTitle(title, LLStringUtil::null); -} - BOOL LLPanelDummyClothingListItem::postBuild() { LLIconCtrl* icon = getChild<LLIconCtrl>("item_icon"); setIconCtrl(icon); setTitleCtrl(getChild<LLTextBox>("item_name")); - addWidgetToRightSide("btn_add"); + addWidgetToRightSide("btn_add_panel"); setIconImage(LLInventoryIcon::getIcon(LLAssetType::AT_CLOTHING, LLInventoryType::IT_NONE, mWearableType, FALSE)); - updateItem(); + updateItem(wearableTypeToString(mWearableType)); // Make it look loke clothing item - reserve space for 'delete' button setLeftWidgetsWidth(icon->getRect().mLeft); @@ -433,15 +439,17 @@ static const LLWearableItemTypeNameComparator WEARABLE_TYPE_NAME_COMPARATOR; static const LLDefaultChildRegistry::Register<LLWearableItemsList> r("wearable_items_list"); LLWearableItemsList::Params::Params() -: use_internal_context_menu("use_internal_context_menu", true) +: standalone("standalone", true) {} LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p) : LLInventoryItemsList(p) { setComparator(&WEARABLE_TYPE_NAME_COMPARATOR); - if (p.use_internal_context_menu) + mIsStandalone = p.standalone; + if (mIsStandalone) { + // Use built-in context menu. setRightMouseDownCallback(boost::bind(&LLWearableItemsList::onRightClick, this, _2, _3)); } } @@ -488,6 +496,37 @@ void LLWearableItemsList::updateList(const LLUUID& category_id) refreshList(item_array); } +void LLWearableItemsList::updateChangedItems(const LLInventoryModel::changed_items_t& changed_items_uuids) +{ + typedef std::vector<LLPanel*> item_panel_list_t; + + item_panel_list_t items; + getItems(items); + + for (item_panel_list_t::iterator items_iter = items.begin(); + items_iter != items.end(); + ++items_iter) + { + LLPanelInventoryListItemBase* item = dynamic_cast<LLPanelInventoryListItemBase*>(*items_iter); + if (!item) continue; + + LLViewerInventoryItem* inv_item = item->getItem(); + if (!inv_item) continue; + + LLUUID linked_uuid = inv_item->getLinkedUUID(); + + for (LLInventoryModel::changed_items_t::const_iterator iter = changed_items_uuids.begin(); + iter != changed_items_uuids.end(); + ++iter) + { + if (linked_uuid == *iter) + { + item->setNeedsRefresh(true); + } + } + } +} + void LLWearableItemsList::onRightClick(S32 x, S32 y) { uuid_vec_t selected_uuids; @@ -505,6 +544,18 @@ void LLWearableItemsList::onRightClick(S32 x, S32 y) /// ContextMenu ////////////////////////////////////////////////////////////////////////// +LLWearableItemsList::ContextMenu::ContextMenu() +: mParent(NULL) +{ +} + +void LLWearableItemsList::ContextMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y) +{ + mParent = dynamic_cast<LLWearableItemsList*>(spawning_view); + LLListContextMenu::show(spawning_view, uuids, x, y); + mParent = NULL; // to avoid dereferencing an invalid pointer +} + // virtual LLContextMenu* LLWearableItemsList::ContextMenu::createMenu() { @@ -592,17 +643,21 @@ void LLWearableItemsList::ContextMenu::updateItemsVisibility(LLContextMenu* menu } } // for + bool standalone = mParent ? mParent->isStandalone() : false; + // *TODO: eliminate multiple traversals over the menu items + setMenuItemVisible(menu, "wear_add", mask == MASK_CLOTHING && n_worn == 0); setMenuItemVisible(menu, "wear", n_worn == 0); - setMenuItemVisible(menu, "edit", mask & (MASK_CLOTHING|MASK_BODYPART) && n_items == 1); - setMenuItemEnabled(menu, "edit", n_editable == 1 && n_worn == 1); + setMenuItemVisible(menu, "edit", !standalone && mask & (MASK_CLOTHING|MASK_BODYPART)); + setMenuItemEnabled(menu, "edit", n_editable == 1 && n_worn == 1 && n_items == 1); setMenuItemVisible(menu, "create_new", mask & (MASK_CLOTHING|MASK_BODYPART) && n_items == 1); + setMenuItemVisible(menu, "show_original", !standalone); setMenuItemEnabled(menu, "show_original", n_items == 1 && n_links == n_items); setMenuItemVisible(menu, "take_off", mask == MASK_CLOTHING && n_worn == n_items); setMenuItemVisible(menu, "detach", mask == MASK_ATTACHMENT && n_worn == n_items); setMenuItemVisible(menu, "take_off_or_detach", mask == (MASK_ATTACHMENT|MASK_CLOTHING)); setMenuItemEnabled(menu, "take_off_or_detach", n_worn == n_items); - setMenuItemVisible(menu, "object_profile", mask & (MASK_ATTACHMENT|MASK_CLOTHING)); + setMenuItemVisible(menu, "object_profile", !standalone); setMenuItemEnabled(menu, "object_profile", n_items == 1); // Populate or hide the "Attach to..." / "Attach to HUD..." submenus. diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index 73a176d061..fe859075c4 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -83,6 +83,12 @@ class LLPanelWearableOutfitItem : public LLPanelInventoryListItemBase public: static LLPanelWearableOutfitItem* create(LLViewerInventoryItem* item); + /** + * Updates item name and (worn) suffix. + */ + /*virtual*/ void updateItem(const std::string& name); + + protected: LLPanelWearableOutfitItem(LLViewerInventoryItem* item); }; @@ -191,7 +197,6 @@ class LLPanelDummyClothingListItem : public LLPanelWearableListItem public: static LLPanelDummyClothingListItem* create(LLWearableType::EType w_type); - /*virtual*/ void updateItem(); /*virtual*/ BOOL postBuild(); LLWearableType::EType getWearableType() const; @@ -318,6 +323,10 @@ public: */ class ContextMenu : public LLListContextMenu, public LLSingleton<ContextMenu> { + public: + ContextMenu(); + /*virtual*/ void show(LLView* spawning_view, const uuid_vec_t& uuids, S32 x, S32 y); + protected: enum { MASK_CLOTHING = 0x01, @@ -333,11 +342,13 @@ public: static void setMenuItemEnabled(LLContextMenu* menu, const std::string& name, bool val); static void updateMask(U32& mask, LLAssetType::EType at); static void createNewWearable(const LLUUID& item_id); + + LLWearableItemsList* mParent; }; struct Params : public LLInitParam::Block<Params, LLInventoryItemsList::Params> { - Optional<bool> use_internal_context_menu; + Optional<bool> standalone; Params(); }; @@ -348,11 +359,21 @@ public: void updateList(const LLUUID& category_id); + /** + * Update items that match UUIDs from changed_items_uuids + * or links that point at such items. + */ + void updateChangedItems(const LLInventoryModel::changed_items_t& changed_items_uuids); + + bool isStandalone() const { return mIsStandalone; } + protected: friend class LLUICtrlFactory; LLWearableItemsList(const LLWearableItemsList::Params& p); void onRightClick(S32 x, S32 y); + + bool mIsStandalone; }; #endif //LL_LLWEARABLEITEMSLIST_H diff --git a/indra/newview/llwindebug.cpp b/indra/newview/llwindebug.cpp deleted file mode 100644 index 59bc9dc62b..0000000000 --- a/indra/newview/llwindebug.cpp +++ /dev/null @@ -1,912 +0,0 @@ -/** - * @file llwindebug.cpp - * @brief Windows debugging functions - * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include <tchar.h> -#include <tlhelp32.h> -#include "llwindebug.h" -#include "llviewercontrol.h" -#include "lldir.h" -#include "llsd.h" -#include "llsdserialize.h" - -#pragma warning(disable: 4200) //nonstandard extension used : zero-sized array in struct/union -#pragma warning(disable: 4100) //unreferenced formal parameter - - -/* -LLSD Block for Windows Dump Information -<llsd> - <map> - <key>Platform</key> - <string></string> - <key>Process</key> - <string></string> - <key>Module</key> - <string></string> - <key>DateModified</key> - <string></string> - <key>ExceptionCode</key> - <string></string> - <key>ExceptionRead/WriteAddress</key> - <string></string> - <key>Instruction</key> - <string></string> - <key>Registers</key> - <map> - <!-- Continued for all registers --> - <key>EIP</key> - <string>...</string> - <!-- ... --> - </map> - <key>Call Stack</key> - <array> - <!-- One map per stack frame --> - <map> - <key>ModuleName</key> - <string></string> - <key>ModuleBaseAddress</key> - <string></string> - <key>ModuleOffsetAddress</key> - <string></string> - <key>Parameters</key> - <array> - <string></string> - </array> - </map> - <!-- ... --> - </array> - </map> -</llsd> - -*/ - - -extern void (*gCrashCallback)(void); - -// based on dbghelp.h -typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)(HANDLE hProcess, DWORD dwPid, HANDLE hFile, MINIDUMP_TYPE DumpType, - CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, - CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, - CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam - ); - -MINIDUMPWRITEDUMP f_mdwp = NULL; - -#undef UNICODE - -static LPTOP_LEVEL_EXCEPTION_FILTER gFilterFunc = NULL; - -HMODULE hDbgHelp; - -// Tool Help functions. -typedef HANDLE (WINAPI * CREATE_TOOL_HELP32_SNAPSHOT)(DWORD dwFlags, DWORD th32ProcessID); -typedef BOOL (WINAPI * MODULE32_FIRST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); -typedef BOOL (WINAPI * MODULE32_NEST)(HANDLE hSnapshot, LPMODULEENTRY32 lpme); - -CREATE_TOOL_HELP32_SNAPSHOT CreateToolhelp32Snapshot_; -MODULE32_FIRST Module32First_; -MODULE32_NEST Module32Next_; - -#define DUMP_SIZE_MAX 8000 //max size of our dump -#define CALL_TRACE_MAX ((DUMP_SIZE_MAX - 2000) / (MAX_PATH + 40)) //max number of traced calls -#define NL L"\r\n" //new line - - -typedef struct STACK -{ - STACK * Ebp; - PBYTE Ret_Addr; - DWORD Param[0]; -} STACK, * PSTACK; - -BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, LPWSTR Module_Name, PBYTE & Module_Addr); -void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record, - const CONTEXT* context_record, - LLSD& info); - -void printError( CHAR* msg ) -{ - DWORD eNum; - TCHAR sysMsg[256]; - TCHAR* p; - - eNum = GetLastError( ); - FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, eNum, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language - sysMsg, 256, NULL ); - - // Trim the end of the line and terminate it with a null - p = sysMsg; - while( ( *p > 31 ) || ( *p == 9 ) ) - ++p; - do { *p-- = 0; } while( ( p >= sysMsg ) && - ( ( *p == '.' ) || ( *p < 33 ) ) ); - - // Display the message - printf( "\n WARNING: %s failed with error %d (%s)", msg, eNum, sysMsg ); -} - -BOOL GetProcessThreadIDs(DWORD process_id, std::vector<DWORD>& thread_ids) -{ - HANDLE hThreadSnap = INVALID_HANDLE_VALUE; - THREADENTRY32 te32; - - // Take a snapshot of all running threads - hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); - if( hThreadSnap == INVALID_HANDLE_VALUE ) - return( FALSE ); - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32 ); - - // Retrieve information about the first thread, - // and exit if unsuccessful - if( !Thread32First( hThreadSnap, &te32 ) ) - { - printError( "Thread32First" ); // Show cause of failure - CloseHandle( hThreadSnap ); // Must clean up the snapshot object! - return( FALSE ); - } - - // Now walk the thread list of the system, - // and display information about each thread - // associated with the specified process - do - { - if( te32.th32OwnerProcessID == process_id ) - { - thread_ids.push_back(te32.th32ThreadID); - } - } while( Thread32Next(hThreadSnap, &te32 ) ); - -// Don't forget to clean up the snapshot object. - CloseHandle( hThreadSnap ); - return( TRUE ); -} - -BOOL GetThreadCallStack(DWORD thread_id, LLSD& info) -{ - if(GetCurrentThreadId() == thread_id) - { - // Early exit for the current thread. - // Suspending the current thread would be a bad idea. - // Plus you can't retrieve a valid current thread context. - return false; - } - - HANDLE thread_handle = INVALID_HANDLE_VALUE; - thread_handle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread_id); - if(INVALID_HANDLE_VALUE == thread_handle) - { - return FALSE; - } - - BOOL result = false; - if(-1 != SuspendThread(thread_handle)) - { - CONTEXT context_struct; - context_struct.ContextFlags = CONTEXT_FULL; - if(GetThreadContext(thread_handle, &context_struct)) - { - Get_Call_Stack(NULL, &context_struct, info); - result = true; - } - ResumeThread(thread_handle); - } - else - { - // Couldn't suspend thread. - } - - CloseHandle(thread_handle); - return result; -} - - -//Windows Call Stack Construction idea from -//http://www.codeproject.com/tools/minidump.asp - -//**************************************************************************************** -BOOL WINAPI Get_Module_By_Ret_Addr(PBYTE Ret_Addr, LPWSTR Module_Name, PBYTE & Module_Addr) -//**************************************************************************************** -// Find module by Ret_Addr (address in the module). -// Return Module_Name (full path) and Module_Addr (start address). -// Return TRUE if found. -{ - MODULEENTRY32 M = {sizeof(M)}; - HANDLE hSnapshot; - - bool found = false; - - if (CreateToolhelp32Snapshot_) - { - hSnapshot = CreateToolhelp32Snapshot_(TH32CS_SNAPMODULE, 0); - - if ((hSnapshot != INVALID_HANDLE_VALUE) && - Module32First_(hSnapshot, &M)) - { - do - { - if (DWORD(Ret_Addr - M.modBaseAddr) < M.modBaseSize) - { - lstrcpyn(Module_Name, M.szExePath, MAX_PATH); - Module_Addr = M.modBaseAddr; - found = true; - break; - } - } while (Module32Next_(hSnapshot, &M)); - } - - CloseHandle(hSnapshot); - } - - return found; -} //Get_Module_By_Ret_Addr - -bool has_valid_call_before(PDWORD cur_stack_loc) -{ - PBYTE p_first_byte = (PBYTE)(*cur_stack_loc - 1); - PBYTE p_second_byte = (PBYTE)(*cur_stack_loc -2); - PBYTE p_fifth_byte = (PBYTE)(*cur_stack_loc - 5); - PBYTE p_sixth_byte = (PBYTE)(*cur_stack_loc - 6); - - // make sure we can read it - if(IsBadReadPtr(p_sixth_byte, 6 * sizeof(BYTE))) - { - return false; - } - - // check for 9a + 4 bytes - if(*p_fifth_byte == 0x9A) - { - return true; - } - - // Check for E8 + 4 bytes and last byte is 00 or FF - if(*p_fifth_byte == 0xE8 && (*p_first_byte == 0x00 || *p_first_byte == 0xFF)) - { - return true; - } - - // the other is six bytes - if(*p_sixth_byte == 0xFF || *p_second_byte == 0xFF) - { - return true; - } - - return false; -} - -PBYTE get_valid_frame(PBYTE esp) -{ - PDWORD cur_stack_loc = NULL; - const int max_search = 400; - WCHAR module_name[MAX_PATH]; - PBYTE module_addr = 0; - - // round to highest multiple of four - esp = (esp + (4 - ((int)esp % 4)) % 4); - - // scroll through stack a few hundred places. - for (cur_stack_loc = (PDWORD) esp; cur_stack_loc < (PDWORD)esp + max_search; cur_stack_loc += 1) - { - // if you can read the pointer, - if (IsBadReadPtr(cur_stack_loc, sizeof(PDWORD))) - { - continue; - } - - // check if it's in a module - if (!Get_Module_By_Ret_Addr((PBYTE)*cur_stack_loc, module_name, module_addr)) - { - continue; - } - - // check if the code before the instruction ptr is a call - if(!has_valid_call_before(cur_stack_loc)) - { - continue; - } - - // if these all pass, return that ebp, otherwise continue till we're dead - return (PBYTE)(cur_stack_loc - 1); - } - - return NULL; -} - -bool shouldUseStackWalker(PSTACK Ebp, int max_depth) -{ - WCHAR Module_Name[MAX_PATH]; - PBYTE Module_Addr = 0; - int depth = 0; - - while (depth < max_depth) - { - if (IsBadReadPtr(Ebp, sizeof(PSTACK)) || - IsBadReadPtr(Ebp->Ebp, sizeof(PSTACK)) || - Ebp->Ebp < Ebp || - Ebp->Ebp - Ebp > 0xFFFFFF || - IsBadCodePtr(FARPROC(Ebp->Ebp->Ret_Addr)) || - !Get_Module_By_Ret_Addr(Ebp->Ebp->Ret_Addr, Module_Name, Module_Addr)) - { - return true; - } - depth++; - Ebp = Ebp->Ebp; - } - - return false; -} - -//****************************************************************** -void WINAPI Get_Call_Stack(const EXCEPTION_RECORD* exception_record, - const CONTEXT* context_record, - LLSD& info) -//****************************************************************** -// Fill Str with call stack info. -// pException can be either GetExceptionInformation() or NULL. -// If pException = NULL - get current call stack. -{ - LPWSTR Module_Name = new WCHAR[MAX_PATH]; - PBYTE Module_Addr = 0; - LLSD params; - PBYTE Esp = NULL; - LLSD tmp_info; - - bool fake_frame = false; - bool ebp_used = false; - const int HEURISTIC_MAX_WALK = 20; - int heuristic_walk_i = 0; - int Ret_Addr_I = 0; - - STACK Stack = {0, 0}; - PSTACK Ebp; - - if (exception_record && context_record) //fake frame for exception address - { - Stack.Ebp = (PSTACK)(context_record->Ebp); - Stack.Ret_Addr = (PBYTE)exception_record->ExceptionAddress; - Ebp = &Stack; - Esp = (PBYTE) context_record->Esp; - fake_frame = true; - } - else if(context_record) - { - Ebp = (PSTACK)(context_record->Ebp); - Esp = (PBYTE)(context_record->Esp); - } - else - { - Ebp = (PSTACK)&exception_record - 1; //frame addr of Get_Call_Stack() - Esp = (PBYTE)&exception_record; - - // Skip frame of Get_Call_Stack(). - if (!IsBadReadPtr(Ebp, sizeof(PSTACK))) - Ebp = Ebp->Ebp; //caller ebp - } - - // Trace CALL_TRACE_MAX calls maximum - not to exceed DUMP_SIZE_MAX. - // Break trace on wrong stack frame. - for (Ret_Addr_I = 0; - heuristic_walk_i < HEURISTIC_MAX_WALK && - Ret_Addr_I < CALL_TRACE_MAX && !IsBadReadPtr(Ebp, sizeof(PSTACK)) && !IsBadCodePtr(FARPROC(Ebp->Ret_Addr)); - Ret_Addr_I++) - { - // If module with Ebp->Ret_Addr found. - if (Get_Module_By_Ret_Addr(Ebp->Ret_Addr, Module_Name, Module_Addr)) - { - // Save module's address and full path. - tmp_info["CallStack"][Ret_Addr_I]["ModuleName"] = ll_convert_wide_to_string(Module_Name); - tmp_info["CallStack"][Ret_Addr_I]["ModuleAddress"] = (int)Module_Addr; - tmp_info["CallStack"][Ret_Addr_I]["CallOffset"] = (int)(Ebp->Ret_Addr - Module_Addr); - - // Save 5 params of the call. We don't know the real number of params. - if (fake_frame && !Ret_Addr_I) //fake frame for exception address - params[0] = "Exception Offset"; - else if (!IsBadReadPtr(Ebp, sizeof(PSTACK) + 5 * sizeof(DWORD))) - { - for(int j = 0; j < 5; ++j) - { - params[j] = (int)Ebp->Param[j]; - } - } - tmp_info["CallStack"][Ret_Addr_I]["Parameters"] = params; - } - - tmp_info["CallStack"][Ret_Addr_I]["ReturnAddress"] = (int)Ebp->Ret_Addr; - - // get ready for next frame - // Set ESP to just after return address. Not the real esp, but just enough after the return address - if(!fake_frame) { - Esp = (PBYTE)Ebp + 8; - } - else - { - fake_frame = false; - } - - // is next ebp valid? - // only run if we've never found a good ebp - // and make sure the one after is valid as well - if( !ebp_used && - shouldUseStackWalker(Ebp, 2)) - { - heuristic_walk_i++; - PBYTE new_ebp = get_valid_frame(Esp); - if (new_ebp != NULL) - { - Ebp = (PSTACK)new_ebp; - } - } - else - { - ebp_used = true; - Ebp = Ebp->Ebp; - } - } -/* TODO remove or turn this code back on to edit the stack after i see a few raw ones. -Palmer - // Now go back through and edit out heuristic stacks that could very well be bogus. - // Leave the top and the last 3 stack chosen by the heuristic, however. - if(heuristic_walk_i > 2) - { - info["CallStack"][0] = tmp_info["CallStack"][0]; - std::string ttest = info["CallStack"][0]["ModuleName"]; - for(int cur_frame = 1; - (cur_frame + heuristic_walk_i - 2 < Ret_Addr_I); - ++cur_frame) - { - // edit out the middle heuristic found frames - info["CallStack"][cur_frame] = tmp_info["CallStack"][cur_frame + heuristic_walk_i - 2]; - } - } - else - { - info = tmp_info; - } -*/ - info = tmp_info; - info["HeuristicWalkI"] = heuristic_walk_i; - info["EbpUsed"] = ebp_used; - -} //Get_Call_Stack - -//*********************************** -void WINAPI Get_Version_Str(LLSD& info) -//*********************************** -// Fill Str with Windows version. -{ - OSVERSIONINFOEX V = {sizeof(OSVERSIONINFOEX)}; //EX for NT 5.0 and later - - if (!GetVersionEx((POSVERSIONINFO)&V)) - { - ZeroMemory(&V, sizeof(V)); - V.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx((POSVERSIONINFO)&V); - } - - if (V.dwPlatformId != VER_PLATFORM_WIN32_NT) - V.dwBuildNumber = LOWORD(V.dwBuildNumber); //for 9x HIWORD(dwBuildNumber) = 0x04xx - - info["Platform"] = llformat("Windows: %d.%d.%d, SP %d.%d, Product Type %d", //SP - service pack, Product Type - VER_NT_WORKSTATION,... - V.dwMajorVersion, V.dwMinorVersion, V.dwBuildNumber, V.wServicePackMajor, V.wServicePackMinor, V.wProductType); -} //Get_Version_Str - -//************************************************************* -LLSD WINAPI Get_Exception_Info(PEXCEPTION_POINTERS pException) -//************************************************************* -// Allocate Str[DUMP_SIZE_MAX] and return Str with dump, if !pException - just return call stack in Str. -{ - LLSD info; - LPWSTR Str; - int Str_Len; -// int i; - LPWSTR Module_Name = new WCHAR[MAX_PATH]; - PBYTE Module_Addr; - HANDLE hFile; - FILETIME Last_Write_Time; - FILETIME Local_File_Time; - SYSTEMTIME T; - - Str = new WCHAR[DUMP_SIZE_MAX]; - Str_Len = 0; - if (!Str) - return NULL; - - Get_Version_Str(info); - - GetModuleFileName(NULL, Str, MAX_PATH); - info["Process"] = ll_convert_wide_to_string(Str); - info["ThreadID"] = (S32)GetCurrentThreadId(); - - // If exception occurred. - if (pException) - { - EXCEPTION_RECORD & E = *pException->ExceptionRecord; - CONTEXT & C = *pException->ContextRecord; - - // If module with E.ExceptionAddress found - save its path and date. - if (Get_Module_By_Ret_Addr((PBYTE)E.ExceptionAddress, Module_Name, Module_Addr)) - { - info["Module"] = ll_convert_wide_to_string(Module_Name); - - if ((hFile = CreateFile(Module_Name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) - { - if (GetFileTime(hFile, NULL, NULL, &Last_Write_Time)) - { - FileTimeToLocalFileTime(&Last_Write_Time, &Local_File_Time); - FileTimeToSystemTime(&Local_File_Time, &T); - - info["DateModified"] = llformat("%02d/%02d/%d", T.wMonth, T.wDay, T.wYear); - } - CloseHandle(hFile); - } - } - else - { - info["ExceptionAddr"] = (int)E.ExceptionAddress; - } - - info["ExceptionCode"] = (int)E.ExceptionCode; - - /* - //TODO: Fix this - if (E.ExceptionCode == EXCEPTION_ACCESS_VIOLATION) - { - // Access violation type - Write/Read. - LLSD exception_info; - exception_info["Type"] = E.ExceptionInformation[0] ? "Write" : "Read"; - exception_info["Address"] = llformat("%08x", E.ExceptionInformation[1]); - info["Exception Information"] = exception_info; - } - */ - - - // Save instruction that caused exception. - /* - std::string str; - for (i = 0; i < 16; i++) - str += llformat(" %02X", PBYTE(E.ExceptionAddress)[i]); - info["Instruction"] = str; - */ - LLSD registers; - registers["EAX"] = (int)C.Eax; - registers["EBX"] = (int)C.Ebx; - registers["ECX"] = (int)C.Ecx; - registers["EDX"] = (int)C.Edx; - registers["ESI"] = (int)C.Esi; - registers["EDI"] = (int)C.Edi; - registers["ESP"] = (int)C.Esp; - registers["EBP"] = (int)C.Ebp; - registers["EIP"] = (int)C.Eip; - registers["EFlags"] = (int)C.EFlags; - info["Registers"] = registers; - } //if (pException) - - // Save call stack info. - Get_Call_Stack(pException->ExceptionRecord, pException->ContextRecord, info); - - return info; -} //Get_Exception_Info - -#define UNICODE - - -class LLMemoryReserve { -public: - LLMemoryReserve(); - ~LLMemoryReserve(); - void reserve(); - void release(); -protected: - unsigned char *mReserve; - static const size_t MEMORY_RESERVATION_SIZE; -}; - -LLMemoryReserve::LLMemoryReserve() : - mReserve(NULL) -{ -}; - -LLMemoryReserve::~LLMemoryReserve() -{ - release(); -} - -// I dunno - this just seemed like a pretty good value. -const size_t LLMemoryReserve::MEMORY_RESERVATION_SIZE = 5 * 1024 * 1024; - -void LLMemoryReserve::reserve() -{ - if(NULL == mReserve) - mReserve = new unsigned char[MEMORY_RESERVATION_SIZE]; -}; - -void LLMemoryReserve::release() -{ - delete [] mReserve; - mReserve = NULL; -}; - -static LLMemoryReserve gEmergencyMemoryReserve; - -#ifndef _M_IX86 - #error "The following code only works for x86!" -#endif -LPTOP_LEVEL_EXCEPTION_FILTER WINAPI MyDummySetUnhandledExceptionFilter( - LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter) -{ - if(lpTopLevelExceptionFilter == gFilterFunc) - return gFilterFunc; - - llinfos << "Someone tried to set the exception filter. Listing call stack modules" << llendl; - LLSD cs_info; - Get_Call_Stack(NULL, NULL, cs_info); - - if(cs_info.has("CallStack") && cs_info["CallStack"].isArray()) - { - LLSD cs = cs_info["CallStack"]; - for(LLSD::array_iterator i = cs.beginArray(); - i != cs.endArray(); - ++i) - { - llinfos << "Module: " << (*i)["ModuleName"] << llendl; - } - } - - return gFilterFunc; -} - -BOOL PreventSetUnhandledExceptionFilter() -{ - HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll")); - if (hKernel32 == NULL) - return FALSE; - - void *pOrgEntry = GetProcAddress(hKernel32, "SetUnhandledExceptionFilter"); - if(pOrgEntry == NULL) - return FALSE; - - unsigned char newJump[ 100 ]; - DWORD dwOrgEntryAddr = (DWORD)pOrgEntry; - dwOrgEntryAddr += 5; // add 5 for 5 op-codes for jmp far - void *pNewFunc = &MyDummySetUnhandledExceptionFilter; - DWORD dwNewEntryAddr = (DWORD) pNewFunc; - DWORD dwRelativeAddr = dwNewEntryAddr - dwOrgEntryAddr; - - newJump[ 0 ] = 0xE9; // JMP absolute - memcpy(&newJump[ 1 ], &dwRelativeAddr, sizeof(pNewFunc)); - SIZE_T bytesWritten; - BOOL bRet = WriteProcessMemory(GetCurrentProcess(), - pOrgEntry, newJump, sizeof(pNewFunc) + 1, &bytesWritten); - return bRet; -} - -// static -void LLWinDebug::initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func) -{ - - static bool s_first_run = true; - // Load the dbghelp dll now, instead of waiting for the crash. - // Less potential for stack mangling - - if (s_first_run) - { - // First, try loading from the directory that the app resides in. - std::string local_dll_name = gDirUtilp->findFile("dbghelp.dll", gDirUtilp->getWorkingDir(), gDirUtilp->getExecutableDir()); - - HMODULE hDll = NULL; - hDll = LoadLibraryA(local_dll_name.c_str()); - if (!hDll) - { - hDll = LoadLibrary(L"dbghelp.dll"); - } - - if (!hDll) - { - LL_WARNS("AppInit") << "Couldn't find dbghelp.dll!" << LL_ENDL; - } - else - { - f_mdwp = (MINIDUMPWRITEDUMP) GetProcAddress(hDll, "MiniDumpWriteDump"); - - if (!f_mdwp) - { - FreeLibrary(hDll); - hDll = NULL; - } - } - - gEmergencyMemoryReserve.reserve(); - - s_first_run = false; - } - - // Try to get Tool Help library functions. - HMODULE hKernel32; - hKernel32 = GetModuleHandle(_T("KERNEL32")); - CreateToolhelp32Snapshot_ = (CREATE_TOOL_HELP32_SNAPSHOT)GetProcAddress(hKernel32, "CreateToolhelp32Snapshot"); - Module32First_ = (MODULE32_FIRST)GetProcAddress(hKernel32, "Module32FirstW"); - Module32Next_ = (MODULE32_NEST)GetProcAddress(hKernel32, "Module32NextW"); - - LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; - prev_filter = SetUnhandledExceptionFilter(filter_func); - - // *REMOVE:Mani - //PreventSetUnhandledExceptionFilter(); - - if(prev_filter != gFilterFunc) - { - LL_WARNS("AppInit") - << "Replacing unknown exception (" << (void *)prev_filter << ") with (" << (void *)filter_func << ") !" << LL_ENDL; - } - - gFilterFunc = filter_func; -} - -bool LLWinDebug::checkExceptionHandler() -{ - bool ok = true; - LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; - prev_filter = SetUnhandledExceptionFilter(gFilterFunc); - - if (prev_filter != gFilterFunc) - { - LL_WARNS("AppInit") << "Our exception handler (" << (void *)gFilterFunc << ") replaced with " << prev_filter << "!" << LL_ENDL; - ok = false; - } - - if (prev_filter == NULL) - { - ok = FALSE; - if (gFilterFunc == NULL) - { - LL_WARNS("AppInit") << "Exception handler uninitialized." << LL_ENDL; - } - else - { - LL_WARNS("AppInit") << "Our exception handler (" << (void *)gFilterFunc << ") replaced with NULL!" << LL_ENDL; - } - } - - return ok; -} - -void LLWinDebug::writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename) -{ - if(f_mdwp == NULL || gDirUtilp == NULL) - { - return; - //write_debug("No way to generate a minidump, no MiniDumpWriteDump function!\n"); - } - else - { - std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, filename); - - HANDLE hFile = CreateFileA(dump_path.c_str(), - GENERIC_WRITE, - FILE_SHARE_WRITE, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (hFile != INVALID_HANDLE_VALUE) - { - // Write the dump, ignoring the return value - f_mdwp(GetCurrentProcess(), - GetCurrentProcessId(), - hFile, - type, - ExInfop, - NULL, - NULL); - - CloseHandle(hFile); - } - - } -} - -// static -void LLWinDebug::generateCrashStacks(struct _EXCEPTION_POINTERS *exception_infop) -{ - // *NOTE:Mani - This method is no longer the exception handler. - // Its called from viewer_windows_exception_handler() and other places. - - // - // Let go of a bunch of reserved memory to give library calls etc - // a chance to execute normally in the case that we ran out of - // memory. - // - LLSD info; - std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, - "SecondLifeException"); - std::string log_path = dump_path + ".log"; - - if (exception_infop) - { - // Since there is exception info... Release the hounds. - gEmergencyMemoryReserve.release(); - - if(gSavedSettings.getControl("SaveMinidump").notNull() && gSavedSettings.getBOOL("SaveMinidump")) - { - _MINIDUMP_EXCEPTION_INFORMATION ExInfo; - - ExInfo.ThreadId = ::GetCurrentThreadId(); - ExInfo.ExceptionPointers = exception_infop; - ExInfo.ClientPointers = NULL; - - writeDumpToFile(MiniDumpNormal, &ExInfo, "SecondLife.dmp"); - writeDumpToFile((MINIDUMP_TYPE)(MiniDumpWithDataSegs | MiniDumpWithIndirectlyReferencedMemory), &ExInfo, "SecondLifePlus.dmp"); - } - - info = Get_Exception_Info(exception_infop); - } - - LLSD threads; - std::vector<DWORD> thread_ids; - GetProcessThreadIDs(GetCurrentProcessId(), thread_ids); - - for(std::vector<DWORD>::iterator th_itr = thread_ids.begin(); - th_itr != thread_ids.end(); - ++th_itr) - { - LLSD thread_info; - if(*th_itr != GetCurrentThreadId()) - { - GetThreadCallStack(*th_itr, thread_info); - } - - if(thread_info) - { - threads[llformat("ID %d", *th_itr)] = thread_info; - } - } - - info["Threads"] = threads; - - llofstream out_file(log_path); - LLSDSerialize::toPrettyXML(info, out_file); - out_file.close(); -} - -void LLWinDebug::clearCrashStacks() -{ - LLSD info; - std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLifeException.log"); - LLFile::remove(dump_path); -} diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h deleted file mode 100644 index f4a6a2d54d..0000000000 --- a/indra/newview/llwindebug.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @file llwindebug.h - * @brief LLWinDebug class header file - * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLWINDEBUG_H -#define LL_LLWINDEBUG_H - -#include "stdtypes.h" -#include <dbghelp.h> - -class LLWinDebug -{ -public: - - /** - * @brief initialize the llwindebug exception filter callback - * - * Hand a windows unhandled exception filter to LLWinDebug - * This method should only be called to change the - * exception filter used by llwindebug. - * - * Setting filter_func to NULL will clear any custom filters. - **/ - static void initExceptionHandler(LPTOP_LEVEL_EXCEPTION_FILTER filter_func); - - /** - * @brief check the status of the exception filter. - * - * Resets unhandled exception filter to the filter specified - * w/ initExceptionFilter). - * Returns false if the exception filter was modified. - * - * *NOTE:Mani In the past mozlib has been accused of - * overriding the exception filter. If the mozlib filter - * is required, perhaps we can chain calls from our - * filter to mozlib's. - **/ - static bool checkExceptionHandler(); - - static void generateCrashStacks(struct _EXCEPTION_POINTERS *pExceptionInfo = NULL); - static void clearCrashStacks(); // Delete the crash stack file(s). - - static void writeDumpToFile(MINIDUMP_TYPE type, MINIDUMP_EXCEPTION_INFORMATION *ExInfop, const std::string& filename); -private: -}; - -#endif // LL_LLWINDEBUG_H diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index a8ac0c0c90..1d10ec7b28 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -513,7 +513,7 @@ void LLXMLRPCTransaction::Impl::setStatus(EStatus status, // Usually this means that there's a problem with the login server, // not with the client. Direct user to status page. mStatusMessage = LLTrans::getString("server_is_down"); - mStatusURI = "http://secondlife.com/status/"; + mStatusURI = "http://status.secondlifegrid.net/"; } } } diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index 731953f9bb..df2fb2a6ea 100644 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -129,8 +129,8 @@ TOOLSIT CURSOR "toolsit.cur" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,0,2,0 - PRODUCTVERSION 2,0,2,0 + FILEVERSION 2,1,0,0 + PRODUCTVERSION 2,1,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -147,12 +147,12 @@ BEGIN BEGIN VALUE "CompanyName", "Linden Lab" VALUE "FileDescription", "Second Life" - VALUE "FileVersion", "2.0.2.0" + VALUE "FileVersion", "2.1.0.0" VALUE "InternalName", "Second Life" VALUE "LegalCopyright", "Copyright © 2001-2008, Linden Research, Inc." VALUE "OriginalFilename", "SecondLife.exe" VALUE "ProductName", "Second Life" - VALUE "ProductVersion", "2.0.2.0" + VALUE "ProductVersion", "2.1.0.0" END END BLOCK "VarFileInfo" diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency_html.xml b/indra/newview/skins/default/xui/en/floater_buy_currency_html.xml index 4643f66bd8..4b990fa566 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_currency_html.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_currency_html.xml @@ -1,27 +1,27 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater - legacy_header_height="18" can_resize="false" - height="280" + can_close="true" + width="422" + height="202" layout="topleft" - min_height="280" - min_width="450" name="floater_buy_currency_html" help_topic="floater_buy_currency_html" save_rect="true" single_instance="true" title="BUY CURRENCY" - width="452"> - <floater.string - name="buy_currency_url" translate="false"> - https://quick-buy-www.jeff.ooze.lindenlab.com/en/display - </floater.string> - <web_browser - bottom="278" - follows="left|right|top|bottom" - layout="topleft" - left="2" - name="browser" - top="18" - width="450" /> +> + <floater.string + name="buy_currency_url" translate="false"> + https://quick-buy.secondlife.com/[LANGUAGE]/display/?sa=[SPECIFIC_AMOUNT]&sum=[SUM]&msg=[MSG]&bal=[BAL] + </floater.string> + <web_browser + follows="all" + layout="topleft" + left="1" + right="-1" + top="1" + bottom="-1" + ignore_ui_scale="false" + name="browser"/> </floater> diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml index 7d81c3e551..452b2ac664 100644 --- a/indra/newview/skins/default/xui/en/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml @@ -1,166 +1,399 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" - can_minimize="true" - can_close="false" + can_minimize="false" + can_close="true" follows="left|top" - height="340" + height="516" layout="topleft" name="Snapshot" help_topic="snapshot" save_rect="true" save_visibility="true" - can_dock="true" - title="Snapshot" - width="250"> - <floater.string - name="unknown"> - unknown - </floater.string> - <floater.string - name="share_to_web_url" translate="false"> - http://pdp36.lindenlab.com:12777/ - </floater.string> - <view - height="160" - width="230" + title="SNAPSHOT PREVIEW" + width="215"> + <floater.string + name="share_to_web_url" translate="false"> +http://pdp36.lindenlab.com:12777/ + </floater.string> + <floater.string + name="unknown"> + unknown + </floater.string> + <radio_group + height="58" + label="Snapshot type" + layout="topleft" + left="10" + name="snapshot_type_radio" + top="25" + width="205"> + <radio_item + bottom="19" + height="16" + label="Email" + layout="topleft" + name="postcard" /> + <radio_item + bottom="38" + height="16" + label="My inventory (L$[AMOUNT])" + layout="topleft" + name="texture" /> + <radio_item + bottom="57" + height="16" + label="Save to my computer" + layout="topleft" + name="local" /> + </radio_group> + <ui_ctrl + height="90" + width="125" layout="topleft" name="thumbnail_placeholder" - top_pad="30" + top_pad="6" follows="left|top" left="10" /> - <button - follows="left|top" - height="22" - image_overlay="Refresh_Off" - layout="topleft" - left="20" - top_pad="-30" - name="new_snapshot_btn" - width="23" - commit_callback.function="Snapshot.Refresh"/> - <line_editor - border_style="line" - border_thickness="1" - follows="left|top" - height="20" - layout="topleft" - left="10" - max_length="500" - name="description" - top_pad="15" - width="230" - label="Description"/> - <panel - top_pad="20" - left="10" - height="83" - name="panel_snapshot_main" - width="130"> - <button - label="Share Snapshot" - name="share" - top="0" - left="0" - width="130" - commit_callback.function="Snapshot.ShowButtons" - commit_callback.parameter="share"/> - <button - label="Save Snapshot" - name="save" - top_pad="7" + <text + type="string" + font="SansSerifSmall" + length="1" + follows="left|top" + height="14" + layout="topleft" + right="-5" left_delta="0" - width="130" - commit_callback.function="Snapshot.ShowButtons" - commit_callback.parameter="save"/> + halign="right" + name="file_size_label" + top_pad="10" + width="195"> + [SIZE] KB + </text> <button - label="Set As Profile Pic" - name="set_profile_pic" - top_pad="7" - left_delta="0" - width="130"/> - </panel> - <panel - top_delta="0" - left_delta="0" - height="83" - name="panel_snapshot_share" - width="130"> + follows="left|top" + height="22" + image_overlay="Refresh_Off" + layout="topleft" + left="10" + name="new_snapshot_btn" + width="23" /> <button - label="Share to Web" - name="share_to_web" - top="0" - left="0" - visible="false" - width="130"/> + follows="left|top" + height="23" + label="Send" + layout="topleft" + left_pad="5" + right="-5" + name="send_btn" + width="100" /> <button - label="Email Snapshot" - name="share_to_email" - top_pad="7" - left_delta="0" - width="130"/> + follows="left|top" + height="23" + label="Save (L$[AMOUNT])" + layout="topleft" + right="-5" + name="upload_btn" + top_delta="0" + width="100" /> + <flyout_button + follows="left|top" + height="23" + label="Save" + layout="topleft" + right="-5" + name="save_btn" + tool_tip="Save image to a file" + top_delta="0" + width="100"> + <flyout_button.item + label="Save" + name="save_item" + value="save" /> + <flyout_button.item + label="Save As..." + name="saveas_item" + value="save as" /> + </flyout_button> + <button + follows="left|top" + height="23" + label="More" + layout="topleft" + left="10" + name="more_btn" + tool_tip="Advanced options" + width="80" /> <button - label="Back" - name="cancel_share" - top_pad="7" + follows="left|top" + height="23" + label="Less" + layout="topleft" left_delta="0" - width="130" - commit_callback.function="Snapshot.ShowButtons" - commit_callback.parameter="main"/> - </panel> - <panel - top_delta="0" - left_delta="0" - height="83" - name="panel_snapshot_save" - width="130"> + name="less_btn" + tool_tip="Advanced options" + top_delta="0" + width="80" /> <button - label="Save to My Inventory" - name="save_to_inventory" - top="0" - left="0" - width="130"/> - <button - label="Save to My Computer" - name="save_to_computer" - top_pad="7" + follows="left|top" + height="23" + label="Cancel" + layout="topleft" + right="-5" + left_pad="5" + name="discard_btn" + width="100" /> + <text + type="string" + length="1" + follows="top|left" + height="12" + layout="topleft" + left="10" + name="type_label2" + top_pad="5" + width="127"> + Size + </text> + <text + type="string" + length="1" + follows="top|left" + height="12" + layout="topleft" + left_pad="5" + name="format_label" + top_delta="0" + width="70"> + Format + </text> + <combo_box + height="23" + label="Resolution" + layout="topleft" + left="10" + name="postcard_size_combo" + width="120"> + <combo_box.item + label="Current Window" + name="CurrentWindow" + value="[i0,i0]" /> + <combo_box.item + label="640x480" + name="640x480" + value="[i640,i480]" /> + <combo_box.item + label="800x600" + name="800x600" + value="[i800,i600]" /> + <combo_box.item + label="1024x768" + name="1024x768" + value="[i1024,i768]" /> + <combo_box.item + label="Custom" + name="Custom" + value="[i-1,i-1]" /> + </combo_box> + <combo_box + height="23" + label="Resolution" + layout="topleft" left_delta="0" - width="130"/> - <button - label="Back" - name="cancel_save" - top_pad="7" + name="texture_size_combo" + top_delta="0" + width="127"> + <combo_box.item + label="Current Window" + name="CurrentWindow" + value="[i0,i0]" /> + <combo_box.item + label="Small (128x128)" + name="Small(128x128)" + value="[i128,i128]" /> + <combo_box.item + label="Medium (256x256)" + name="Medium(256x256)" + value="[i256,i256]" /> + <combo_box.item + label="Large (512x512)" + name="Large(512x512)" + value="[i512,i512]" /> + <combo_box.item + label="Custom" + name="Custom" + value="[i-1,i-1]" /> + </combo_box> + <combo_box + height="23" + label="Resolution" + layout="topleft" + left_delta="0" + name="local_size_combo" + top_delta="0" + width="127"> + <combo_box.item + label="Current Window" + name="CurrentWindow" + value="[i0,i0]" /> + <combo_box.item + label="320x240" + name="320x240" + value="[i320,i240]" /> + <combo_box.item + label="640x480" + name="640x480" + value="[i640,i480]" /> + <combo_box.item + label="800x600" + name="800x600" + value="[i800,i600]" /> + <combo_box.item + label="1024x768" + name="1024x768" + value="[i1024,i768]" /> + <combo_box.item + label="1280x1024" + name="1280x1024" + value="[i1280,i1024]" /> + <combo_box.item + label="1600x1200" + name="1600x1200" + value="[i1600,i1200]" /> + <combo_box.item + label="Custom" + name="Custom" + value="[i-1,i-1]" /> + </combo_box> + <combo_box + height="23" + label="Format" + layout="topleft" + left_pad="5" + name="local_format_combo" + width="70"> + <combo_box.item + label="PNG" + name="PNG" /> + <combo_box.item + label="JPEG" + name="JPEG" /> + <combo_box.item + label="BMP" + name="BMP" /> + </combo_box> + <spinner + allow_text_entry="false" + decimal_digits="0" + follows="left|top" + height="20" + increment="32" + label="Width" + label_width="40" + layout="topleft" + left="10" + max_val="6016" + min_val="32" + name="snapshot_width" + top_pad="10" + width="95" /> + <spinner + allow_text_entry="false" + decimal_digits="0" + follows="left|top" + height="20" + increment="32" + label="Height" + label_width="40" + layout="topleft" + left_pad="5" + max_val="6016" + min_val="32" + name="snapshot_height" + top_delta="0" + width="95" /> + <check_box + bottom_delta="20" + label="Constrain proportions" + layout="topleft" + left="10" + name="keep_aspect_check" /> + <slider + decimal_digits="0" + follows="left|top" + height="15" + increment="1" + initial_value="75" + label="Image quality" + label_width="100" + layout="topleft" left_delta="0" - width="130" - commit_callback.function="Snapshot.ShowButtons" - commit_callback.parameter="main"/> - </panel> - <button - follows="left" - height="22" - layout="topleft" - left="210" - name="show_advanced" - image_overlay="TabIcon_Close_Off" - bottom_delta="0" - width="30" - commit_callback.function="Snapshot.ShowAdvanced"/> - <button - follows="left" - height="22" - layout="topleft" - left="210" - name="hide_advanced" - image_overlay="TabIcon_Open_Off" - top_delta="0" - visible="false" - width="30" - commit_callback.function="Snapshot.HideAdvanced"/> - <panel - visible="false" - left="250" - top="17" - name="snapshot_advanced" - filename="panel_snapshot_advanced.xml"/> + max_val="100" + name="image_quality_slider" + top_pad="5" + width="205" /> + <text + type="string" + length="1" + follows="left|top" + height="13" + layout="topleft" + left="10" + name="layer_type_label" + top_pad="5" + width="50"> + Capture: + </text> + <combo_box + height="23" + label="Image Layers" + layout="topleft" + left="30" + name="layer_types" + width="145"> + <combo_box.item + label="Colors" + name="Colors" + value="colors" /> + <combo_box.item + label="Depth" + name="Depth" + value="depth" /> + </combo_box> + <check_box + label="Interface" + layout="topleft" + left="30" + top_pad="10" + width="180" + name="ui_check" /> + <check_box + label="HUDs" + layout="topleft" + left="30" + top_pad="10" + width="180" + name="hud_check" /> + <check_box + label="Keep open after saving" + layout="topleft" + left="10" + top_pad="8" + width="180" + name="keep_open_check" /> + <check_box + label="Freeze frame (fullscreen)" + layout="topleft" + left="10" + top_pad="8" + width="180" + name="freeze_frame_check" /> + <check_box + label="Auto-refresh" + layout="topleft" + left="10" + top_pad="8" + width="180" + name="auto_snapshot_check" /> </floater> diff --git a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml index c4e31ed180..8e7ef7f0b5 100644 --- a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml @@ -11,6 +11,9 @@ <on_enable function="Gear.OnEnable" parameter="wear" /> + <on_visible + function="Gear.OnVisible" + parameter="wear" /> </menu_item_call> <menu_item_call label="Take Off - Remove from Current Outfit" @@ -21,9 +24,12 @@ <on_enable function="Gear.OnEnable" parameter="take_off" /> + <on_visible + function="Gear.OnVisible" + parameter="take_off" /> </menu_item_call> - <menu_item_separator /> + <menu_item_separator name="sepatator1" /> <!-- copied (with minor modifications) from menu_inventory_add.xml --> <!-- *TODO: generate dynamically? --> <menu @@ -168,7 +174,7 @@ </menu> <!-- copied from menu_inventory_add.xml --> - <menu_item_separator /> + <menu_item_separator name="sepatator2" /> <menu_item_call label="Rename Outfit" layout="topleft" @@ -178,6 +184,9 @@ <on_enable function="Gear.OnEnable" parameter="rename" /> + <on_visible + function="Gear.OnVisible" + parameter="rename" /> </menu_item_call> <menu_item_call label="Delete Outfit" @@ -188,5 +197,8 @@ <on_enable function="Gear.OnEnable" parameter="delete" /> + <on_visible + function="Gear.OnVisible" + parameter="delete" /> </menu_item_call> </menu> diff --git a/indra/newview/skins/default/xui/en/menu_outfit_tab.xml b/indra/newview/skins/default/xui/en/menu_outfit_tab.xml index 67559638d9..e084216a69 100644 --- a/indra/newview/skins/default/xui/en/menu_outfit_tab.xml +++ b/indra/newview/skins/default/xui/en/menu_outfit_tab.xml @@ -8,8 +8,8 @@ name="wear_replace"> <on_click function="Outfit.WearReplace" /> - <on_enable - function="Outfit.OnEnable" + <on_visible + function="Outfit.OnVisible" parameter="wear_replace" /> </menu_item_call> <menu_item_call @@ -18,8 +18,8 @@ name="wear_add"> <on_click function="Outfit.WearAdd" /> - <on_enable - function="Outfit.OnEnable" + <on_visible + function="Outfit.OnVisible" parameter="wear_add" /> </menu_item_call> <menu_item_call @@ -28,8 +28,8 @@ name="take_off"> <on_click function="Outfit.TakeOff" /> - <on_enable - function="Outfit.OnEnable" + <on_visible + function="Outfit.OnVisible" parameter="take_off" /> </menu_item_call> <menu_item_call @@ -38,8 +38,8 @@ name="edit"> <on_click function="Outfit.Edit" /> - <on_enable - function="Outfit.OnEnable" + <on_visible + function="Outfit.OnVisible" parameter="edit" /> </menu_item_call> <menu_item_separator /> @@ -59,8 +59,8 @@ name="delete"> <on_click function="Outfit.Delete" /> - <on_enable - function="Outfit.OnEnable" + <on_visible + function="Outfit.OnVisible" parameter="delete" /> </menu_item_call> </context_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 2641ce4ee4..3557318705 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -927,7 +927,7 @@ <menu_item_check label="Show Advanced Menu" name="Show Advanced Menu" - shortcut="control|alt|D"> + shortcut="control|alt|shift|D"> <on_check function="CheckControl" parameter="UseDebugMenus" /> @@ -1477,6 +1477,18 @@ <menu_item_call.on_click function="View.DefaultUISize" /> </menu_item_call> + <!-- This second, alternative shortcut for Show Advanced Menu is for backward compatibility. The main shortcut has been changed so it's Linux-friendly, where the old shortcut is typically eaten by the window manager. --> + <menu_item_check + label="Show Advanced Menu - legacy shortcut" + name="Show Advanced Menu - legacy shortcut" + shortcut="control|alt|D"> + <on_check + function="CheckControl" + parameter="UseDebugMenus" /> + <on_click + function="ToggleControl" + parameter="UseDebugMenus" /> + </menu_item_check> <menu_item_separator/> <menu_item_check label="Always Run" @@ -1652,7 +1664,6 @@ function="ToggleControl" parameter="QAMode" /> </menu_item_check> - </menu> <menu create_jump_keys="true" @@ -3278,4 +3289,4 @@ </menu> </menu> </menu> -</menu_bar>
\ No newline at end of file +</menu_bar> diff --git a/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml b/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml index fa5ca60a19..430a7b6444 100644 --- a/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml +++ b/indra/newview/skins/default/xui/en/menu_wearable_list_item.xml @@ -38,13 +38,6 @@ layout="topleft" name="wearable_attach_to_hud" /> <menu_item_call - label="Object Profile" - layout="topleft" - name="object_profile"> - <on_click - function="Attachment.Profile" /> - </menu_item_call> - <menu_item_call label="Take Off" layout="topleft" name="take_off"> @@ -59,6 +52,13 @@ function="Wearable.Edit" /> </menu_item_call> <menu_item_call + label="Object Profile" + layout="topleft" + name="object_profile"> + <on_click + function="Attachment.Profile" /> + </menu_item_call> + <menu_item_call label="Show Original" layout="topleft" name="show_original"> diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 76a41a3b13..20a2a7d954 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -1397,8 +1397,7 @@ Unable to encode file: [FILE] icon="alertmodal.tga" name="CorruptedProtectedDataStore" type="alertmodal"> - We are unable to read your protected data so it is being reset. - This may happen when you change network setup. + We can't fill in your username and password. This may happen when you change network setup <usetemplate name="okbutton" @@ -2066,6 +2065,7 @@ Would you be my friend? name="Cancel" text="Cancel"/> </form> + <unique/> </notification> <notification @@ -4518,18 +4518,6 @@ Uploading in-world and web site snapshots... </notification> <notification - icon="alertmodal.tga" - name="UploadConfirmation" - type="alertmodal"> -Uploading costs L$[AMOUNT]. -Do you wish to proceed? - <usetemplate - name="okcancelbuttons" - notext="Cancel" - yestext="Upload"/> - </notification> - - <notification icon="notify.tga" name="UploadPayment" persist="true" @@ -5527,14 +5515,6 @@ Failed to find [TYPE] named [DESC] in database. <notification icon="notify.tga" - name="ShareToWebFailed" - persist="true" - type="notify"> - Failed to upload image to web. - </notification> - - <notification - icon="notify.tga" name="InvalidWearable" persist="true" type="notify"> diff --git a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml index 44437d01eb..bdfa928b1d 100644 --- a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml +++ b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml @@ -19,6 +19,6 @@ multi_select="true" name="wearable_items_list" translate="false" - use_internal_context_menu="false" + standalone="false" /> </accordion_tab> diff --git a/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml b/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml index 4e5f594ffe..4f989a6f6f 100644 --- a/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_body_parts_list_item.xml @@ -57,7 +57,8 @@ left="0" height="23" width="23" - tab_stop="false"> + tab_stop="false" + tool_tip="You don't have permission to edit"> <icon name="btn_lock1" layout="topleft" @@ -88,7 +89,8 @@ left="0" height="23" width="23" - tab_stop="false" /> + tab_stop="false" + tool_tip="Edit this shape"/> </panel> <icon follows="left|right|top" diff --git a/indra/newview/skins/default/xui/en/panel_classified_info.xml b/indra/newview/skins/default/xui/en/panel_classified_info.xml index 859cc82e81..976f6d6cd0 100644 --- a/indra/newview/skins/default/xui/en/panel_classified_info.xml +++ b/indra/newview/skins/default/xui/en/panel_classified_info.xml @@ -47,7 +47,7 @@ layout="topleft" name="back_btn" picture_style="true" - left="9" + left="10" tab_stop="false" top="2" width="30" /> @@ -56,7 +56,7 @@ font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="10" + left_pad="4" name="title" text_color="LtGray" top="0" diff --git a/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml b/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml index 5d81aebbd5..93d7720c57 100644 --- a/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_clothing_list_item.xml @@ -37,7 +37,8 @@ left="0" height="18" width="18" - tab_stop="false" /> + tab_stop="false" + tool_tip="Remove from outfit" /> <icon height="16" follows="top|left" @@ -88,7 +89,8 @@ left="0" height="23" width="23" - tab_stop="false"> + tab_stop="false" + tool_tip="You don't have permission to edit"> <icon name="btn_lock1" layout="topleft" @@ -119,7 +121,8 @@ left="0" height="23" width="23" - tab_stop="false" /> + tab_stop="false" + tool_tip="Edit this wearable"/> </panel> <icon follows="left|right|top" diff --git a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml index d36c2a4e6f..f016c27b0a 100644 --- a/indra/newview/skins/default/xui/en/panel_cof_wearables.xml +++ b/indra/newview/skins/default/xui/en/panel_cof_wearables.xml @@ -28,7 +28,7 @@ allow_select="true" follows="all" height="10" - item_pad="2" + item_pad="3" layout="topleft" left="0" multi_select="true" @@ -44,7 +44,7 @@ allow_select="true" follows="all" height="10" - item_pad="2" + item_pad="3" layout="topleft" left="0" multi_select="true" @@ -60,7 +60,7 @@ allow_select="true" follows="all" height="10" - item_pad="2" + item_pad="3" layout="topleft" left="0" multi_select="true" diff --git a/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml b/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml index 45031859f1..75b5fd1532 100644 --- a/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_deletable_wearable_list_item.xml @@ -37,7 +37,8 @@ left="0" height="18" width="18" - tab_stop="false" /> + tab_stop="false" + tool_tip="Remove from outfit"/> <icon height="16" follows="top|left" diff --git a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml index 20652df918..a5dd34bd22 100644 --- a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml @@ -49,16 +49,27 @@ top="4" value="..." width="359" /> - <button - name="btn_add" + <panel + name="btn_add_panel" layout="topleft" follows="top|right" - image_overlay="AddItem_Off" top="0" left="0" height="23" - width="23" - tab_stop="false" /> + width="26" + tab_stop="false"> + <button + name="btn_add" + layout="topleft" + follows="top|right" + image_overlay="AddItem_Off" + top="0" + left="0" + height="23" + width="23" + tab_stop="false" + tool_tip="Add more items of this type" /> + </panel> <icon follows="left|right|top" height="3" diff --git a/indra/newview/skins/default/xui/en/panel_edit_classified.xml b/indra/newview/skins/default/xui/en/panel_edit_classified.xml index 1b4f547f9d..6744a7b9c2 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_classified.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_classified.xml @@ -31,7 +31,7 @@ layout="topleft" name="back_btn" picture_style="true" - left="7" + left="10" tab_stop="false" top="2" width="30" /> @@ -42,7 +42,7 @@ font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="10" + left_pad="4" name="title" text_color="LtGray" top="0" diff --git a/indra/newview/skins/default/xui/en/panel_edit_pick.xml b/indra/newview/skins/default/xui/en/panel_edit_pick.xml index 589ea10e8d..dc83b334b5 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_pick.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_pick.xml @@ -24,7 +24,7 @@ image_unselected="BackButton_Off" layout="topleft" name="back_btn" - left="7" + left="10" tab_stop="false" top="2" width="30" /> @@ -35,10 +35,10 @@ font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="10" + left_pad="4" name="title" text_color="LtGray" - top="0" + top="2" width="250"> Edit Pick </text> diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml index 645ee8a435..950c4a5fdb 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml @@ -141,15 +141,16 @@ left="0" layout="topleft" name="back_btn" left="11" - top="7" /> + top="3" /> <text follows="top|left" font="SansSerifHugeBold" height="22" layout="topleft" - left_pad="15" + left_pad="8" name="edit_wearable_title" text_color="white" + top="3" value="Editing Shape" width="270" /> <panel diff --git a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml index 58b78cfa02..e4eb9afb29 100644 --- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml @@ -57,9 +57,9 @@ background_visible="true" font="SansSerifHugeBold" h_pad="0" height="26" - left_pad="10" + left_pad="8" text_color="LtGray" - top="0" + top="1" use_ellipses="true" width="275" follows="top|left|right" diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml index bb73360e0b..55fef5aaf7 100644 --- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml +++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml @@ -63,7 +63,7 @@ image_pressed="BackButton_Press" image_unselected="BackButton_Off" layout="topleft" - left="8" + left="9" name="back_btn" tool_tip="Back" tab_stop="false" @@ -74,10 +74,10 @@ font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="10" + left_pad="7" name="title" text_color="LtGray" - top="2" + top="3" use_ellipses="true" value="Place Profile" width="280" /> diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml index 741f60669a..ed3b176267 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -51,7 +51,8 @@ <string name="Filter.All" value="All"/> <string name="Filter.Clothes/Body" value="Clothes/Body"/> <string name="Filter.Objects" value="Objects"/> - <string name="Filter.Custom" value="Custom filter"/> + <string name="Filter.Clothing" value="Clothing"/> + <string name="Filter.Bodyparts" value="Body parts"/> <button @@ -64,14 +65,14 @@ name="back_btn" left="5" tab_stop="false" - top="2" + top="1" width="30" /> <text follows="top|right" font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="20" + left_pad="10" name="title" text_color="LtGray" top="0" @@ -211,6 +212,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap left="2" name="show_add_wearables_btn" top_pad="2" + tool_tip="Open/Close" width="125" /> <combo_box @@ -218,11 +220,20 @@ It is calculated as border_size + 2*UIResizeBarOverlap height="22" layout="topleft" left_pad="5" - name="filter_wearables_combobox" + name="list_view_filter_combobox" top_delta="0" visible="false" width="152"/> - + <combo_box + follows="left|right|bottom" + height="22" + layout="topleft" + left_delta="0" + name="folder_view_filter_combobox" + top_delta="0" + visible="false" + width="152"/> + <button follows="bottom|right" height="22" @@ -300,7 +311,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap layout="topleft" left="0" mouse_opaque="false" - name="inventory_items" + name="folder_view" top_pad="5" width="310" visible="false"/> @@ -319,7 +330,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap visible="true"> <wearable_items_list color="0.107 0.107 0.107 1" - name="filtered_wearables_list" + name="list_view" allow_select="true" layout="topleft" follows="all" @@ -483,6 +494,7 @@ It is calculated as border_size + 2*UIResizeBarOverlap layout="topleft" name="revert_btn" top="0" + tool_tip="Revert to last saved version" width="147" /> </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml index 7a7f910171..c1e5ae50e6 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -94,7 +94,7 @@ layout="topleft" left_pad="1" name="trash_btn" - tool_tip="Remove selected item" + tool_tip="Delete selected outfit" width="31"/> <button follows="bottom|left" diff --git a/indra/newview/skins/default/xui/en/panel_pick_info.xml b/indra/newview/skins/default/xui/en/panel_pick_info.xml index 49e1d16f6a..1d01bcb8a5 100644 --- a/indra/newview/skins/default/xui/en/panel_pick_info.xml +++ b/indra/newview/skins/default/xui/en/panel_pick_info.xml @@ -18,7 +18,7 @@ image_unselected="BackButton_Off" layout="topleft" name="back_btn" - left="7" + left="10" tab_stop="false" top="2" width="30" /> @@ -27,10 +27,10 @@ font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="10" + left_pad="4" name="title" text_color="LtGray" - top="0" + top="2" value="Pick Info" use_ellipses="true" width="275" /> diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml index 59f1f6d638..55e0184282 100644 --- a/indra/newview/skins/default/xui/en/panel_place_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml @@ -160,7 +160,7 @@ image_pressed="BackButton_Press" image_unselected="BackButton_Off" layout="topleft" - left="7" + left="8" name="back_btn" tool_tip="Back" tab_stop="false" @@ -174,7 +174,7 @@ left_pad="10" name="title" text_color="LtGray" - top="2" + top="4" use_ellipses="true" value="Place Profile" width="280" /> diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml index 33f895e13a..638e190e8f 100644 --- a/indra/newview/skins/default/xui/en/panel_places.xml +++ b/indra/newview/skins/default/xui/en/panel_places.xml @@ -37,6 +37,7 @@ background_visible="true" left="6" name="Places Tabs" tab_min_width="80" + tab_max_width="157" tab_height="30" tab_group="1" tab_position="top" diff --git a/indra/newview/skins/default/xui/en/panel_profile_view.xml b/indra/newview/skins/default/xui/en/panel_profile_view.xml index cc5ba334d6..d9030fc0d6 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_view.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml @@ -24,7 +24,7 @@ image_unselected="BackButton_Off" layout="topleft" name="back" - left="9" + left="10" tab_stop="false" top="2" width="30" /> @@ -38,10 +38,10 @@ font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="10" + left_pad="5" name="user_name" text_color="LtGray" - top="0" + top="2" value="(Loading...)" use_ellipses="true" width="275" /> diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml index ae08a13793..e189d11d35 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml @@ -92,6 +92,7 @@ width="333"> layout="topleft" left="265" name="edit_outfit_btn" + tool_tip="Edit this outfit" top="7" width="30" /> <loading_indicator @@ -144,7 +145,7 @@ width="333"> left="5" min_height="410" name="panel_outfit_edit" - top="5" + top="2" visible="false" width="320"/> <panel diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml index b736f5e29c..e2bd6f375e 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml @@ -55,10 +55,10 @@ font="SansSerifHugeBold" height="26" layout="topleft" - left_pad="10" + left_pad="3" name="title" text_color="LtGray" - top="0" + top="2" use_ellipses="true" value="Object Profile" width="275" /> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 361af0e8fb..294267d43b 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3186,7 +3186,7 @@ Abuse Report</string> <string name="server_is_down"> Despite our best efforts, something unexpected has gone wrong. - Please check secondlife.com/status to see if there is a known problem with the service. + Please check status.secondlifegrid.net to see if there is a known problem with the service. If you continue to experience problems, please check your network and firewall setup. </string> diff --git a/indra/newview/skins/default/xui/en/widgets/accordion.xml b/indra/newview/skins/default/xui/en/widgets/accordion.xml index b817ba56ca..05d7447a6f 100644 --- a/indra/newview/skins/default/xui/en/widgets/accordion.xml +++ b/indra/newview/skins/default/xui/en/widgets/accordion.xml @@ -8,7 +8,6 @@ height="100" h_pad="10" name="no_visible_items_msg" - value="There are no visible content here." v_pad="15" width="200" wrap="true "/> diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml index 55e699612c..026b7b7616 100644 --- a/indra/newview/skins/default/xui/it/floater_about.xml +++ b/indra/newview/skins/default/xui/it/floater_about.xml @@ -27,9 +27,9 @@ Scheda grafica: [GRAPHICS_CARD] Versione libcurl: [LIBCURL_VERSION] Versione J2C Decoder: [J2C_VERSION] -Versione Audio Driver: [AUDIO_DRIVER_VERSION] +Versione Driver audio: [AUDIO_DRIVER_VERSION] Versione Qt Webkit: [QT_WEBKIT_VERSION] -Versione Vivox: [VIVOX_VERSION] +Versione Server voice: [VOICE_VERSION] </floater.string> <floater.string name="none"> (nessuno) diff --git a/indra/newview/skins/default/xui/it/floater_about_land.xml b/indra/newview/skins/default/xui/it/floater_about_land.xml index c55f79738e..942b79b7d3 100644 --- a/indra/newview/skins/default/xui/it/floater_about_land.xml +++ b/indra/newview/skins/default/xui/it/floater_about_land.xml @@ -63,6 +63,9 @@ Nessun appezzamento selezionato. Vai al menu Mondo > Informazioni sul terreno oppure seleziona un altro appezzamento per vederne i dettagli. </panel.string> + <panel.string name="time_stamp_template"> + [wkday,datetime,local] [day,datetime,local] [mth,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] + </panel.string> <text name="Name:"> Nome: </text> diff --git a/indra/newview/skins/default/xui/it/floater_avatar_textures.xml b/indra/newview/skins/default/xui/it/floater_avatar_textures.xml index 2935f0fdb6..b6376973cd 100644 --- a/indra/newview/skins/default/xui/it/floater_avatar_textures.xml +++ b/indra/newview/skins/default/xui/it/floater_avatar_textures.xml @@ -3,41 +3,48 @@ <floater.string name="InvalidAvatar"> AVATAR NON VALIDO </floater.string> - <text name="composite_label"> - Texture Composite - </text> - <button label="Deposito" label_selected="Deposito" name="Dump"/> <scroll_container name="profile_scroll"> <panel name="scroll_content_panel"> - <texture_picker label="Capigliature" name="hair-baked"/> - <texture_picker label="Capigliature" name="hair_grain"/> - <texture_picker label="Alpha dei capelli" name="hair_alpha"/> - <texture_picker label="Testa" name="head-baked"/> - <texture_picker label="Makeup" name="head_bodypaint"/> - <texture_picker label="Alpha della testa" name="head_alpha"/> - <texture_picker label="Tatuaggio della testa" name="head_tattoo"/> - <texture_picker label="Occhi" name="eyes-baked"/> - <texture_picker label="Occhio" name="eyes_iris"/> - <texture_picker label="Alpha degli occhi" name="eyes_alpha"/> - <texture_picker label="Parte superiore del corpo" name="upper-baked"/> - <texture_picker label="Bodypaint parte superiore del corpo" name="upper_bodypaint"/> - <texture_picker label="Maglietta intima" name="upper_undershirt"/> - <texture_picker label="Guanti" name="upper_gloves"/> - <texture_picker label="Camicia" name="upper_shirt"/> - <texture_picker label="Parte superiore della giacca" name="upper_jacket"/> - <texture_picker label="Alpha superiore" name="upper_alpha"/> - <texture_picker label="Tatuaggio superiore" name="upper_tattoo"/> - <texture_picker label="Parte inferiore del corpo" name="lower-baked"/> - <texture_picker label="Bodypaint parte inferiore del corpo" name="lower_bodypaint"/> - <texture_picker label="Slip" name="lower_underpants"/> - <texture_picker label="Calzini" name="lower_socks"/> - <texture_picker label="Scarpe" name="lower_shoes"/> - <texture_picker label="Pantaloni" name="lower_pants"/> - <texture_picker label="Giacca" name="lower_jacket"/> - <texture_picker label="Alpha inferiore" name="lower_alpha"/> - <texture_picker label="Tattuaggio inferiore" name="lower_tattoo"/> - <texture_picker label="Gonna" name="skirt-baked"/> - <texture_picker label="Gonna" name="skirt"/> + <text name="label"> + Baking delle +texture + </text> + <text name="composite_label"> + Composito +Texture + </text> + <button label="Memorizza gli ID sulla console" label_selected="Dump" name="Dump"/> + <panel name="scroll_content_panel"> + <texture_picker label="Capigliature" name="hair-baked"/> + <texture_picker label="Capigliature" name="hair_grain"/> + <texture_picker label="Alpha dei capelli" name="hair_alpha"/> + <texture_picker label="Testa" name="head-baked"/> + <texture_picker label="Makeup" name="head_bodypaint"/> + <texture_picker label="Alpha della testa" name="head_alpha"/> + <texture_picker label="Tatuaggio della testa" name="head_tattoo"/> + <texture_picker label="Occhi" name="eyes-baked"/> + <texture_picker label="Occhio" name="eyes_iris"/> + <texture_picker label="Alpha degli occhi" name="eyes_alpha"/> + <texture_picker label="Parte superiore del corpo" name="upper-baked"/> + <texture_picker label="Bodypaint parte superiore del corpo" name="upper_bodypaint"/> + <texture_picker label="Maglietta intima" name="upper_undershirt"/> + <texture_picker label="Guanti" name="upper_gloves"/> + <texture_picker label="Camicia" name="upper_shirt"/> + <texture_picker label="Parte superiore della giacca" name="upper_jacket"/> + <texture_picker label="Alpha superiore" name="upper_alpha"/> + <texture_picker label="Tatuaggio superiore" name="upper_tattoo"/> + <texture_picker label="Parte inferiore del corpo" name="lower-baked"/> + <texture_picker label="BodyPaint parte inferiore del corpo" name="lower_bodypaint"/> + <texture_picker label="Slip" name="lower_underpants"/> + <texture_picker label="Calzini" name="lower_socks"/> + <texture_picker label="Scarpe" name="lower_shoes"/> + <texture_picker label="Pantaloni" name="lower_pants"/> + <texture_picker label="Giacca" name="lower_jacket"/> + <texture_picker label="Alpha inferiore" name="lower_alpha"/> + <texture_picker label="Tattuaggio inferiore" name="lower_tattoo"/> + <texture_picker label="Gonna" name="skirt-baked"/> + <texture_picker label="Gonna" name="skirt"/> + </panel> </panel> </scroll_container> </floater> diff --git a/indra/newview/skins/default/xui/it/floater_buy_currency_html.xml b/indra/newview/skins/default/xui/it/floater_buy_currency_html.xml new file mode 100644 index 0000000000..4a1bf33403 --- /dev/null +++ b/indra/newview/skins/default/xui/it/floater_buy_currency_html.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<floater name="floater_buy_currency_html" title="ACQUISTA VALUTA"/> diff --git a/indra/newview/skins/default/xui/it/floater_map.xml b/indra/newview/skins/default/xui/it/floater_map.xml index 70ab8dcb5a..d1e9c98e79 100644 --- a/indra/newview/skins/default/xui/it/floater_map.xml +++ b/indra/newview/skins/default/xui/it/floater_map.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="Map" title="Mini mappa"> +<floater name="Map" title=""> <floater.string name="mini_map_north"> N </floater.string> diff --git a/indra/newview/skins/default/xui/it/floater_moveview.xml b/indra/newview/skins/default/xui/it/floater_moveview.xml index 26d861c566..cdafdb0089 100644 --- a/indra/newview/skins/default/xui/it/floater_moveview.xml +++ b/indra/newview/skins/default/xui/it/floater_moveview.xml @@ -6,18 +6,48 @@ <string name="walk_back_tooltip"> Cammina indietro (premi freccia giù o S) </string> + <string name="walk_left_tooltip"> + Cammina a sinistra (premi Maiusc + freccia sinistra o A) + </string> + <string name="walk_right_tooltip"> + Cammina a destra (premi Maiusc + freccia destra o D) + </string> <string name="run_forward_tooltip"> Corri in avanti (premi freccia su o W) </string> <string name="run_back_tooltip"> Corri indietro (premi freccia giù o S) </string> + <string name="run_left_tooltip"> + Corri a sinistra (premi Maiusc + freccia sinistra o A) + </string> + <string name="run_right_tooltip"> + Corri a destra (premi Maiusc + freccia destra o D) + </string> <string name="fly_forward_tooltip"> Vola in avanti (premi freccia su o W) </string> <string name="fly_back_tooltip"> Vola indietro (premi freccia giù o S) </string> + <string name="fly_left_tooltip"> + Vola a sinistra (premi Maiusc + freccia sinistra o A) + </string> + <string name="fly_right_tooltip"> + Vola a destra (premi Maiusc + freccia destra o D) + </string> + <string name="fly_up_tooltip"> + Vola in alto (premi E) + </string> + <string name="fly_down_tooltip"> + Vola in basso (premi C) + </string> + <string name="jump_tooltip"> + Salta (premi E) + </string> + <string name="crouch_tooltip"> + Accovacciarsi (premi C) + </string> <string name="walk_title"> Cammina </string> @@ -28,10 +58,12 @@ Vola </string> <panel name="panel_actions"> + <button label="" label_selected="" name="move up btn" tool_tip="Vola in alto (premi E)"/> <button label="" label_selected="" name="turn left btn" tool_tip="Gira a sinistra (premi freccia sinistra o A)"/> + <joystick_slide name="move left btn" tool_tip="Cammina a sinistra (premi Maiusc + freccia sinistra o A)"/> + <button label="" label_selected="" name="move down btn" tool_tip="Vola in basso (premi C)"/> <button label="" label_selected="" name="turn right btn" tool_tip="Gira a destra (premi freccia destra o D)"/> - <button label="" label_selected="" name="move up btn" tool_tip="Vola in alto, premi E"/> - <button label="" label_selected="" name="move down btn" tool_tip="Vola in basso, premi C"/> + <joystick_slide name="move right btn" tool_tip="Cammina a destra (premi Maiusc + freccia destra o D)"/> <joystick_turn name="forward btn" tool_tip="Cammina in avanti (premi freccia su o W)"/> <joystick_turn name="backward btn" tool_tip="Cammina indietro (premi freccia giù o S)"/> </panel> diff --git a/indra/newview/skins/default/xui/it/floater_preview_notecard.xml b/indra/newview/skins/default/xui/it/floater_preview_notecard.xml index 70e28dde35..7ec229f9d3 100644 --- a/indra/newview/skins/default/xui/it/floater_preview_notecard.xml +++ b/indra/newview/skins/default/xui/it/floater_preview_notecard.xml @@ -9,9 +9,6 @@ <floater.string name="Title"> Biglietto: [NAME] </floater.string> - <floater.string label="Salva" label_selected="Salva" name="Save"> - Salva - </floater.string> <text name="desc txt"> Descrizione: </text> @@ -19,4 +16,5 @@ In caricamento... </text_editor> <button label="Salva" label_selected="Salva" name="Save"/> + <button label="Elimina" label_selected="Elimina" name="Delete"/> </floater> diff --git a/indra/newview/skins/default/xui/it/floater_tools.xml b/indra/newview/skins/default/xui/it/floater_tools.xml index 04d61b97ff..68d193ff33 100644 --- a/indra/newview/skins/default/xui/it/floater_tools.xml +++ b/indra/newview/skins/default/xui/it/floater_tools.xml @@ -67,9 +67,9 @@ <text name="RenderingCost" tool_tip="Mostra il costo di rendering calcolato per questo oggetto"> þ: [COUNT] </text> - <check_box name="checkbox uniform"/> - <text name="checkbox uniform label"> - Ridimens. simmetricamente + <check_box label="" name="checkbox uniform"/> + <text label="Allunga entrambi i lati" name="checkbox uniform label"> + Allunga entrambi i lati </text> <check_box initial_value="true" label="Ridimensiona le texture" name="checkbox stretch textures"/> <check_box initial_value="true" label="Posiziona nella griglia" name="checkbox snap to grid"/> @@ -445,8 +445,8 @@ <check_box label="Inverti" name="checkbox flip s"/> <spinner label="Verticale (V)" name="TexScaleV"/> <check_box label="Inverti" name="checkbox flip t"/> - <spinner label="RotazioneËš" name="TexRot" /> - <spinner label="Ripetizioni / Metro" name="rptctrl" /> + <spinner label="RotazioneËš" name="TexRot"/> + <spinner label="Ripetizioni / Metro" name="rptctrl"/> <button label="Applica" label_selected="Applica" name="button apply"/> <text name="tex offset"> Bilanciamento della texture diff --git a/indra/newview/skins/default/xui/it/menu_attachment_self.xml b/indra/newview/skins/default/xui/it/menu_attachment_self.xml index 054f4802e6..c480a2fe0e 100644 --- a/indra/newview/skins/default/xui/it/menu_attachment_self.xml +++ b/indra/newview/skins/default/xui/it/menu_attachment_self.xml @@ -5,7 +5,7 @@ <menu_item_call label="Stacca" name="Detach"/> <menu_item_call label="Lascia" name="Drop"/> <menu_item_call label="Alzati" name="Stand Up"/> - <menu_item_call label="Il mio aspetto" name="Appearance..."/> + <menu_item_call label="Cambia vestiario" name="Change Outfit"/> <menu_item_call label="I miei amici..." name="Friends..."/> <menu_item_call label="I miei gruppi" name="Groups..."/> <menu_item_call label="Il mio profilo" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/it/menu_avatar_self.xml b/indra/newview/skins/default/xui/it/menu_avatar_self.xml index d73d97d499..7796d41286 100644 --- a/indra/newview/skins/default/xui/it/menu_avatar_self.xml +++ b/indra/newview/skins/default/xui/it/menu_avatar_self.xml @@ -20,7 +20,9 @@ <context_menu label="Stacca â–¶" name="Object Detach"/> <menu_item_call label="Stacca tutto" name="Detach All"/> </context_menu> - <menu_item_call label="Il mio aspetto" name="Appearance..."/> + <menu_item_call label="Cambia vestiario" name="Chenge Outfit"/> + <menu_item_call label="Modifica il mio vestiario" name="Edit Outfit"/> + <menu_item_call label="Modifica la figura corporea" name="Edit My Shape"/> <menu_item_call label="I miei amici..." name="Friends..."/> <menu_item_call label="I miei gruppi" name="Groups..."/> <menu_item_call label="Il mio profilo" name="Profile..."/> diff --git a/indra/newview/skins/default/xui/it/menu_bottomtray.xml b/indra/newview/skins/default/xui/it/menu_bottomtray.xml index 7203d002d2..8ca5b24b48 100644 --- a/indra/newview/skins/default/xui/it/menu_bottomtray.xml +++ b/indra/newview/skins/default/xui/it/menu_bottomtray.xml @@ -4,6 +4,11 @@ <menu_item_check label="Tasto Movimento" name="ShowMoveButton"/> <menu_item_check label="Tasto Visuale" name="ShowCameraButton"/> <menu_item_check label="Tasto Foto" name="ShowSnapshotButton"/> + <menu_item_check label="Pulsante barra laterale" name="ShowSidebarButton"/> + <menu_item_check label="Pulsante Costruisci" name="ShowBuildButton"/> + <menu_item_check label="Pulsante Cerca" name="ShowSearchButton"/> + <menu_item_check label="Pulsante Mappa" name="ShowWorldMapButton"/> + <menu_item_check label="Pulsante Mini mappa" name="ShowMiniMapButton"/> <menu_item_call label="Taglia" name="NearbyChatBar_Cut"/> <menu_item_call label="Copia" name="NearbyChatBar_Copy"/> <menu_item_call label="Incolla" name="NearbyChatBar_Paste"/> diff --git a/indra/newview/skins/default/xui/it/menu_inspect_self_gear.xml b/indra/newview/skins/default/xui/it/menu_inspect_self_gear.xml index 33229bb7c0..80edae8a2b 100644 --- a/indra/newview/skins/default/xui/it/menu_inspect_self_gear.xml +++ b/indra/newview/skins/default/xui/it/menu_inspect_self_gear.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <menu name="Gear Menu"> <menu_item_call label="Alzati" name="stand_up"/> - <menu_item_call label="Il mio aspetto" name="my_appearance"/> + <menu_item_call label="Cambia vestiario" name="change_outfit"/> <menu_item_call label="Il mio profilo" name="my_profile"/> <menu_item_call label="I miei amici..." name="my_friends"/> <menu_item_call label="I miei gruppi" name="my_groups"/> diff --git a/indra/newview/skins/default/xui/it/menu_inventory.xml b/indra/newview/skins/default/xui/it/menu_inventory.xml index 3b36198774..b127f8b816 100644 --- a/indra/newview/skins/default/xui/it/menu_inventory.xml +++ b/indra/newview/skins/default/xui/it/menu_inventory.xml @@ -54,6 +54,7 @@ <menu_item_call label="Elimina oggetto" name="Purge Item"/> <menu_item_call label="Ripristina oggetto" name="Restore Item"/> <menu_item_call label="Apri" name="Open"/> + <menu_item_call label="Apri originale" name="Open Original"/> <menu_item_call label="Proprietà " name="Properties"/> <menu_item_call label="Rinomina" name="Rename"/> <menu_item_call label="Copia UUID dell'oggetto" name="Copy Asset UUID"/> diff --git a/indra/newview/skins/default/xui/it/menu_login.xml b/indra/newview/skins/default/xui/it/menu_login.xml index 904b819198..0a6d803058 100644 --- a/indra/newview/skins/default/xui/it/menu_login.xml +++ b/indra/newview/skins/default/xui/it/menu_login.xml @@ -2,7 +2,7 @@ <menu_bar name="Login Menu"> <menu label="Io" name="File"> <menu_item_call label="Preferenze" name="Preferences..."/> - <menu_item_call label="Chiudi" name="Quit"/> + <menu_item_call label="Esci da [APP_NAME]" name="Quit"/> </menu> <menu label="Aiuto" name="Help"> <menu_item_call label="Aiuto di [SECOND_LIFE]" name="Second Life Help"/> diff --git a/indra/newview/skins/default/xui/it/menu_participant_list.xml b/indra/newview/skins/default/xui/it/menu_participant_list.xml index 71f1a9a0da..f70b886a1e 100644 --- a/indra/newview/skins/default/xui/it/menu_participant_list.xml +++ b/indra/newview/skins/default/xui/it/menu_participant_list.xml @@ -14,8 +14,8 @@ <context_menu label="Opzioni moderatore >" name="Moderator Options"> <menu_item_check label="Consenti chat di testo" name="AllowTextChat"/> <menu_item_call label="Disattiva audio di questo participante" name="ModerateVoiceMuteSelected"/> - <menu_item_call label="Disattiva audio di tutti gli altri" name="ModerateVoiceMuteOthers"/> <menu_item_call label="Riattiva audio di questo participante" name="ModerateVoiceUnMuteSelected"/> - <menu_item_call label="Riattiva audio di tutti gli altri" name="ModerateVoiceUnMuteOthers"/> + <menu_item_call label="Disattiva audio di tutti" name="ModerateVoiceMute"/> + <menu_item_call label="Riattiva audio di tutti" name="ModerateVoiceUnmute"/> </context_menu> </context_menu> diff --git a/indra/newview/skins/default/xui/it/menu_viewer.xml b/indra/newview/skins/default/xui/it/menu_viewer.xml index a5923ac42b..999f89a80d 100644 --- a/indra/newview/skins/default/xui/it/menu_viewer.xml +++ b/indra/newview/skins/default/xui/it/menu_viewer.xml @@ -7,7 +7,7 @@ </menu_item_call> <menu_item_call label="Compra L$" name="Buy and Sell L$"/> <menu_item_call label="Il mio profilo" name="Profile"/> - <menu_item_call label="Il mio aspetto" name="Appearance"/> + <menu_item_call label="Cambia vestiario" name="ChangeOutfit"/> <menu_item_check label="Il mio inventario" name="Inventory"/> <menu_item_check label="Il mio inventario" name="ShowSidetrayInventory"/> <menu_item_check label="Le mie gesture" name="Gestures"/> @@ -162,6 +162,7 @@ <menu_item_check label="Oggetti flessibili" name="Flexible Objects"/> </menu> <menu_item_check label="Esegui thread multipli" name="Run Multiple Threads"/> + <menu_item_check label="Usa thread lettura plugin" name="Use Plugin Read Thread"/> <menu_item_call label="Pulisci cache di gruppo" name="ClearGroupCache"/> <menu_item_check label="Fluidità mouse" name="Mouse Smoothing"/> <menu label="Scorciatoie" name="Shortcuts"> @@ -188,7 +189,6 @@ <menu_item_call label="Zoom avanti" name="Zoom In"/> <menu_item_call label="Zoom predefinito" name="Zoom Default"/> <menu_item_call label="Zoom indietro" name="Zoom Out"/> - <menu_item_call label="Alterna schermo intero" name="Toggle Fullscreen"/> </menu> <menu_item_call label="Mostra impostazioni di debug" name="Debug Settings"/> <menu_item_check label="Mostra menu sviluppo" name="Debug Mode"/> diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 4739e5cce9..058353da38 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -326,6 +326,9 @@ Hai bisogno di un account per entrare in [SECOND_LIFE]. Ne vuoi creare uno adess </url> <usetemplate name="okcancelbuttons" notext="Riprova" yestext="Crea un nuovo account"/> </notification> + <notification name="InvalidCredentialFormat"> + Immetti sia il nome che il cognome del tuo avatar nel campo del nome utente, quindi effettua l'accesso. + </notification> <notification name="AddClassified"> L'inserzione comparirà nella sezione 'Annunci' della Ricerca e su [http://secondlife.com/community/classifieds secondlife.com] per una settimana. Compila la tua inserzione, quindi clicca 'Pubblica...' per aggiungerla all'elenco degli annunci. @@ -608,6 +611,11 @@ Attese [VALIDS] <notification name="CannotEncodeFile"> Impossibile codificare il file: [FILE] </notification> + <notification name="CorruptedProtectedDataStore"> + Poiché non è possibile leggere i dati protetti, ora verranno ripristinati. + Ciò può succedere alla modifica delle impostazioni di rete. + <usetemplate name="okbutton" yestext="OK"/> + </notification> <notification name="CorruptResourceFile"> File risorsa corrotto: [FILE] </notification> @@ -968,6 +976,12 @@ su TUTTI I TERRENI di questa sim? Introduci un prezzo più alto. </notification> + <notification name="ConfirmItemDeleteHasLinks"> + Almeno uno degli oggetti selezionati è collegato tramite link ad altri oggetti. Se elimini l'oggetto, i relativi link non funzioneranno più. Pertanto si consiglia vivamente di eliminare prima i link. + +Sei sicuro di volere eliminare gli oggetti? + <usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/> + </notification> <notification name="ConfirmObjectDeleteLock"> Almeno uno degli elementi selezionati è bloccato. @@ -1117,6 +1131,42 @@ Premi F1 in qualunque momento per la guida o per apprendere altre cose di [SECON Scegli un avatar maschile o femminile. Puoi sempre cambiare idea più tardi. <usetemplate name="okcancelbuttons" notext="Femminile" yestext="Maschile"/> </notification> + <notification name="CantTeleportToGrid"> + Impossibile effettuare il teleport su [SLURL], in quanto si trova su una griglia ([GRID]) diversa da quella attuale ([CURRENT_GRID]). Chiudi il viewer e prova nuovamente. + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="GeneralCertificateError"> + Impossibile collegarsi al server. +[REASON] + +Nome oggetto: [SUBJECT_NAME_STRING] +Nome emittente: [ISSUER_NAME_STRING] +Valido da: [VALID_FROM] +Valido fino a: [VALID_TO] +Impronta MD5: [SHA1_DIGEST] +Impronta SHA1: [MD5_DIGEST] +Uso chiave: [KEYUSAGE] +Uso chiave estesa: [EXTENDEDKEYUSAGE] +Identificatore chiave oggetto: [SUBJECTKEYIDENTIFIER] + <usetemplate name="okbutton" yestext="OK"/> + </notification> + <notification name="TrustCertificateError"> + Autorità di certificazione di questo server sconosciuta. + +Informazioni sul certificato: +Nome oggetto: [SUBJECT_NAME_STRING] +Nome emittente: [ISSUER_NAME_STRING] +Valido da: [VALID_FROM] +Valido fino a: [VALID_TO] +Impronta MD5: [SHA1_DIGEST] +Impronta SHA1: [MD5_DIGEST] +Uso chiave: [KEYUSAGE] +Uso chiave estesa: [EXTENDEDKEYUSAGE] +Identificatore chiave oggetto: [SUBJECTKEYIDENTIFIER] + +Accettare questa autorità ? + <usetemplate name="okcancelbuttons" notext="Annulla" yestext="Accetta"/> + </notification> <notification name="NotEnoughCurrency"> [NAME] [PRICE]L$ Non hai abbastanza L$ per farlo. </notification> @@ -1512,7 +1562,7 @@ Vuoi andare alla Knowledge Base per ulteriori informazioni sulle categorie di ac <notification name="RegionEntryAccessBlocked_Change"> Non ti è consentito entrare in quella regione a causa della tua categoria di accesso impostata nelle preferenze. -Puoi cliccare su Cambia preferenze per modificare la categoria di accesso e quindi riuscire ad entrare. Da adesso potrai accedere ai contenuti [REGIONMATURITY] ed effettuare ricerche in questa categoria. Se in seguito tu volessi cambiare di nuovo le tue impostazioni, apri la finestra di dialogo da Io > Preferenze > Generale. +Clicca su Cambia preferenze per modificare la categoria di accesso e potere entrare subito. Ciò ti consentirà di effettuare ricerche di contenuti di categoria [REGIONMATURITY]. Potrai modificare queste impostazioni in un secondo momento da Io > Preferenze > Generali. <form name="form"> <button name="OK" text="Cambia preferenza"/> <button default="true" name="Cancel" text="Chiudi"/> @@ -2283,15 +2333,6 @@ Riprova tra qualche istante. <button name="Mute" text="Blocca"/> </form> </notification> - <notification name="ObjectGiveItemUnknownUser"> - Un oggetto chiamato [OBJECTFROMNAME] di proprietà di (residente sconosciuto) ti ha dato questo [OBJECTTYPE]: -[ITEM_SLURL] - <form name="form"> - <button name="Keep" text="Prendi"/> - <button name="Discard" text="Rifiuta"/> - <button name="Mute" text="Blocca"/> - </form> - </notification> <notification name="UserGiveItem"> [NAME_SLURL] ti ha dato questo [OBJECTTYPE]: [ITEM_SLURL] @@ -2604,8 +2645,52 @@ Il pulsante verrà visualizzato quando lo spazio sarà sufficiente. <notification name="ShareNotification"> Trascina articoli dell'inventario su una persona nel selettore residenti </notification> + <notification name="DeedToGroupFail"> + Cessione al gruppo non riuscita. + </notification> <notification name="AvatarRezNotification"> - Avatar '[NAME]' rezzato in [TIME] secondi. + ( presente da [EXISTENCE] secondi ) +Nuvola avatar '[NAME]' risolta in [TIME] secondi. + </notification> + <notification name="AvatarRezSelfNotification"> + ( presente da [EXISTENCE] secondi ) +Baking dei vestiti eseguito in [TIME] secondi. + </notification> + <notification name="AvatarRezCloudNotification"> + ( presente da [EXISTENCE] secondi ) +Avatar '[NAME]' trasformato in nuvola. + </notification> + <notification name="AvatarRezArrivedNotification"> + ( presente da [EXISTENCE] secondi ) +È comparso l'avatar '[NAME]'. + </notification> + <notification name="AvatarRezLeftCloudNotification"> + ( presente da [EXISTENCE] secondi ) +Avatar '[NAME]' partito dopo [TIME] secondi sotto forma di nuvola. + </notification> + <notification name="AvatarRezEnteredAppearanceNotification"> + ( presente da [EXISTENCE] secondi ) +Avatar '[NAME]' è entrato nella modalità aspetto. + </notification> + <notification name="AvatarRezLeftAppearanceNotification"> + ( presente da [EXISTENCE] secondi ) +Avatar '[NAME]' ha lasciato la modalità aspetto. + </notification> + <notification name="AvatarRezLeftNotification"> + ( presente da [EXISTENCE] secondi ) +Avatar '[NAME]' è partito completamente caricato. + </notification> + <notification name="ConfirmLeaveCall"> + Sei sicuro di volere uscire dalla chiamata? + <usetemplate ignoretext="Conferma prima di uscire dalla chiamata" name="okcancelignore" notext="No" yestext="Sì"/> + </notification> + <notification name="ConfirmMuteAll"> + Hai scelto di disattivare l'audio di tutti i partecipanti alla chiamata di gruppo. +In questo modo verrà disattivato l'audio anche di tutti i residenti che si +uniscono alla chiamata in un secondo momento, anche dopo che tu ti fossi scollegato. + +Disattiva audio di tutti? + <usetemplate ignoretext="Conferma prima di disattivare l'audio di tutti i partecipanti alla chiamata di gruppo" name="okcancelignore" notext="Ok" yestext="Annulla"/> </notification> <global name="UnsupportedCPU"> - La velocità della tua CPU non soddisfa i requisiti minimi. diff --git a/indra/newview/skins/default/xui/it/panel_body_parts_list_item.xml b/indra/newview/skins/default/xui/it/panel_body_parts_list_item.xml new file mode 100644 index 0000000000..de764d8025 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_body_parts_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="wearable_item"> + <text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_bodyparts_list_button_bar.xml b/indra/newview/skins/default/xui/it/panel_bodyparts_list_button_bar.xml new file mode 100644 index 0000000000..8fc23d34f1 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_bodyparts_list_button_bar.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="clothing_list_button_bar_panel"> + <button label="Cambia" name="switch_btn"/> + <button label="Acquista >" name="bodyparts_shop_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_bottomtray.xml b/indra/newview/skins/default/xui/it/panel_bottomtray.xml index c0218fad5e..e4d99cc402 100644 --- a/indra/newview/skins/default/xui/it/panel_bottomtray.xml +++ b/indra/newview/skins/default/xui/it/panel_bottomtray.xml @@ -1,11 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="bottom_tray"> - <string name="SpeakBtnToolTip"> - Accende o spegne il microfono - </string> - <string name="VoiceControlBtnToolTip"> - Mostra o nasconde il pannello di regolazione voce - </string> + <string name="SpeakBtnToolTip" value="Accende o spegne il microfono"/> + <string name="VoiceControlBtnToolTip" value="Mostra o nasconde il pannello di regolazione voce"/> <layout_stack name="toolbar_stack"> <layout_panel name="speak_panel"> <talk_button name="talk"> @@ -24,6 +20,21 @@ <layout_panel name="snapshot_panel"> <button label="" name="snapshots" tool_tip="Scatta una foto"/> </layout_panel> + <layout_panel name="sidebar_btn_panel"> + <button label="Barra laterale" name="sidebar_btn" tool_tip="Mostra o nasconde la barra laterale"/> + </layout_panel> + <layout_panel name="build_btn_panel"> + <button label="Costruisci" name="build_btn" tool_tip="Mostra o nasconde gli strumenti di costruzione"/> + </layout_panel> + <layout_panel name="search_btn_panel"> + <button label="Cerca" name="search_btn" tool_tip="Mostra o nasconde la ricerca"/> + </layout_panel> + <layout_panel name="world_map_btn_panel"> + <button label="Mappa" name="world_map_btn" tool_tip="Mostra o nasconde la mappa del mondo"/> + </layout_panel> + <layout_panel name="mini_map_btn_panel"> + <button label="Mini mappa" name="mini_map_btn" tool_tip="Mostra o nasconde la mini mappa"/> + </layout_panel> <layout_panel name="im_well_panel"> <chiclet_im_well name="im_well"> <button name="Unread IM messages" tool_tip="Conversazioni"/> diff --git a/indra/newview/skins/default/xui/it/panel_clothing_list_button_bar.xml b/indra/newview/skins/default/xui/it/panel_clothing_list_button_bar.xml new file mode 100644 index 0000000000..e9d9795b3a --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_clothing_list_button_bar.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="clothing_list_button_bar_panel"> + <button label="Aggiungi +" name="add_btn"/> + <button label="Acquista >" name="clothing_shop_btn"/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_clothing_list_item.xml b/indra/newview/skins/default/xui/it/panel_clothing_list_item.xml new file mode 100644 index 0000000000..de764d8025 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_clothing_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="wearable_item"> + <text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_cof_wearables.xml b/indra/newview/skins/default/xui/it/panel_cof_wearables.xml new file mode 100644 index 0000000000..d914a5740f --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_cof_wearables.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="cof_wearables"> + <accordion name="cof_wearables_accordion"> + <accordion_tab name="tab_attachments" title="Allegati"/> + <accordion_tab name="tab_clothing" title="Vestiario"/> + <accordion_tab name="tab_body_parts" title="Parti del corpo"/> + </accordion> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_deletable_wearable_list_item.xml b/indra/newview/skins/default/xui/it/panel_deletable_wearable_list_item.xml new file mode 100644 index 0000000000..91d90a5660 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_deletable_wearable_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="deletable_wearable_item"> + <text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/it/panel_dummy_clothing_list_item.xml new file mode 100644 index 0000000000..6af84de0c7 --- /dev/null +++ b/indra/newview/skins/default/xui/it/panel_dummy_clothing_list_item.xml @@ -0,0 +1,4 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes"?> +<panel name="dummy_clothing_item"> + <text name="item_name" value="..."/> +</panel> diff --git a/indra/newview/skins/default/xui/it/panel_edit_shape.xml b/indra/newview/skins/default/xui/it/panel_edit_shape.xml index 7e1ba43756..ab77548f26 100644 --- a/indra/newview/skins/default/xui/it/panel_edit_shape.xml +++ b/indra/newview/skins/default/xui/it/panel_edit_shape.xml @@ -1,14 +1,8 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel name="edit_shape_panel"> - <panel name="avatar_sex_panel"> - <text name="gender_text"> - Sesso: - </text> - <radio_group name="sex_radio"> - <radio_item label="Femmina" name="radio"/> - <radio_item label="Maschio" name="radio2"/> - </radio_group> - </panel> + <text name="avatar_height"> + Statura: [HEIGHT] metri + </text> <panel label="Camicia" name="accordion_panel"> <accordion name="wearable_accordion"> <accordion_tab name="shape_body_tab" title="Corpo"/> diff --git a/indra/newview/skins/default/xui/it/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/it/panel_edit_tattoo.xml index d8cfa15b25..d76fb62c53 100644 --- a/indra/newview/skins/default/xui/it/panel_edit_tattoo.xml +++ b/indra/newview/skins/default/xui/it/panel_edit_tattoo.xml @@ -4,5 +4,6 @@ <texture_picker label="Tatuaggio della testa" name="Head Tattoo" tool_tip="Clicca per scegliere una fotografia"/> <texture_picker label="Tatuaggio superiore" name="Upper Tattoo" tool_tip="Clicca per scegliere una fotografia"/> <texture_picker label="Tattuaggio inferiore" name="Lower Tattoo" tool_tip="Clicca per scegliere una fotografia"/> + <color_swatch label="Colore/Tinta" name="Color/Tint" tool_tip="Clicca per aprire il selettore dei colori"/> </panel> </panel> diff --git a/indra/newview/skins/default/xui/it/panel_edit_wearable.xml b/indra/newview/skins/default/xui/it/panel_edit_wearable.xml index 1135a582f5..3d8aa858db 100644 --- a/indra/newview/skins/default/xui/it/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/it/panel_edit_wearable.xml @@ -93,6 +93,12 @@ <text name="edit_wearable_title" value="Modifica della figura corporea"/> <panel label="Camicia" name="wearable_type_panel"> <text name="description_text" value="Figura corporea:"/> + <radio_group name="sex_radio"> + <radio_item label="" name="sex_male" tool_tip="Maschio" value="1"/> + <radio_item label="" name="sex_female" tool_tip="Femmina" value="0"/> + </radio_group> + <icon name="male_icon" tool_tip="Maschio"/> + <icon name="female_icon" tool_tip="Femmina"/> </panel> <panel label="gear_buttom_panel" name="gear_buttom_panel"> <button name="friends_viewsort_btn" tool_tip="Opzioni"/> diff --git a/indra/newview/skins/default/xui/it/panel_group_land_money.xml b/indra/newview/skins/default/xui/it/panel_group_land_money.xml index 1e3ef5e657..16cc91cd9d 100644 --- a/indra/newview/skins/default/xui/it/panel_group_land_money.xml +++ b/indra/newview/skins/default/xui/it/panel_group_land_money.xml @@ -6,6 +6,9 @@ <panel.string name="cant_view_group_land_text"> Non sei autorizzato a vedere quali terreni appartengono al gruppo. </panel.string> + <panel.string name="epmty_view_group_land_text"> + Nessuna voce + </panel.string> <panel.string name="cant_view_group_accounting_text"> Non sei autorizzato a visionare le informazioni finanziarie del gruppo. </panel.string> diff --git a/indra/newview/skins/default/xui/it/panel_group_notices.xml b/indra/newview/skins/default/xui/it/panel_group_notices.xml index 9dac282de9..8dd945830e 100644 --- a/indra/newview/skins/default/xui/it/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/it/panel_group_notices.xml @@ -40,6 +40,7 @@ Massimo 200 per gruppo al giorno <text name="string"> Trascina e rilascia qui l'oggetto da allegare: </text> + <button label="Inventario" name="open_inventory" tool_tip="Apri l'inventario"/> <button label="Rimuovi" label_selected="Rimuovi allegato" name="remove_attachment" tool_tip="Rimuovi allegato dal tuo avviso"/> <button label="Invia" label_selected="Invia" name="send_notice"/> <group_drop_target name="drop_target" tool_tip="Trascina un oggetto dall'inventario Ãn questa casella per spedirlo con questo avviso. Devi avere i diritti per la copia e il trasferimento per poter allegare l'oggetto."/> diff --git a/indra/newview/skins/default/xui/it/panel_login.xml b/indra/newview/skins/default/xui/it/panel_login.xml index 287e938d57..473bcfa88d 100644 --- a/indra/newview/skins/default/xui/it/panel_login.xml +++ b/indra/newview/skins/default/xui/it/panel_login.xml @@ -8,18 +8,15 @@ </panel.string> <layout_stack name="login_widgets"> <layout_panel name="login"> - <text name="first_name_text"> - Nome: + <text name="username_text"> + Nome utente: </text> - <line_editor label="Nome" name="first_name_edit" tool_tip="[SECOND_LIFE] First Name"/> - <text name="last_name_text"> - Cognome: - </text> - <line_editor label="Cognome" name="last_name_edit" tool_tip="[SECOND_LIFE] Last Name"/> + <line_editor label="Nome utente" name="username_edit" tool_tip="Nome utente [SECOND_LIFE]"/> <text name="password_text"> Password: </text> <check_box label="Ricorda password" name="remember_check"/> + <button label="Accedi" name="connect_btn"/> <text name="start_location_text"> Inizia da: </text> @@ -28,7 +25,6 @@ <combo_box.item label="Casa mia" name="MyHome"/> <combo_box.item label="<Scrivi nome regione>" name="Typeregionname"/> </combo_box> - <button label="Accedi" name="connect_btn"/> </layout_panel> <layout_panel name="links"> <text name="create_new_account_text"> diff --git a/indra/newview/skins/default/xui/it/panel_main_inventory.xml b/indra/newview/skins/default/xui/it/panel_main_inventory.xml index 878daf1e6b..446b51ffa3 100644 --- a/indra/newview/skins/default/xui/it/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/it/panel_main_inventory.xml @@ -9,62 +9,20 @@ <text name="ItemcountText"> Oggetti: </text> - <menu_bar name="Inventory Menu"> - <menu label="File" name="File"> - <menu_item_call label="Apri" name="Open"/> - <menu label="Carica nel server" name="upload"> - <menu_item_call label="Immagine ([COST]L$)..." name="Upload Image"/> - <menu_item_call label="Suono ([COST]L$)..." name="Upload Sound"/> - <menu_item_call label="Animazione ([COST]L$)..." name="Upload Animation"/> - <menu_item_call label="In blocco ([COST]L$ per file)..." name="Bulk Upload"/> - </menu> - <menu_item_call label="Nuova finestra" name="New Window"/> - <menu_item_call label="Mostra filtri" name="Show Filters"/> - <menu_item_call label="Ripristina filtri" name="Reset Current"/> - <menu_item_call label="Chiudi tutte le cartelle" name="Close All Folders"/> - <menu_item_call label="Svuota cestino" name="Empty Trash"/> - <menu_item_call label="Svuota oggetti smarriti" name="Empty Lost And Found"/> - </menu> - <menu label="Crea" name="Create"> - <menu_item_call label="Nuova cartella" name="New Folder"/> - <menu_item_call label="Nuovo script" name="New Script"/> - <menu_item_call label="Nuovo biglietto" name="New Note"/> - <menu_item_call label="Nuova gesture" name="New Gesture"/> - <menu label="Maglietta intima" name="New Clothes"> - <menu_item_call label="Nuova camicia" name="New Shirt"/> - <menu_item_call label="Nuovi pantaloni" name="New Pants"/> - <menu_item_call label="Nuove scarpe" name="New Shoes"/> - <menu_item_call label="Nuove calze" name="New Socks"/> - <menu_item_call label="Nuova giacca" name="New Jacket"/> - <menu_item_call label="Nuova gonna" name="New Skirt"/> - <menu_item_call label="Nuovi guanti" name="New Gloves"/> - <menu_item_call label="Nuova maglietta intima" name="New Undershirt"/> - <menu_item_call label="Nuovi slip" name="New Underpants"/> - <menu_item_call label="Nuovo Alfa (trasparenza)" name="New Alpha"/> - <menu_item_call label="Nuovo tatuaggio" name="New Tattoo"/> - </menu> - <menu label="Nuove parti del corpo" name="New Body Parts"> - <menu_item_call label="Nuova figura corporea" name="New Shape"/> - <menu_item_call label="Nuova pelle" name="New Skin"/> - <menu_item_call label="Nuovi capelli" name="New Hair"/> - <menu_item_call label="Nuovi occhi" name="New Eyes"/> - </menu> - </menu> - <menu label="Ordina" name="Sort"> - <menu_item_check label="In base al nome" name="By Name"/> - <menu_item_check label="In base alla data" name="By Date"/> - <menu_item_check label="Cartelle sempre in base al nome" name="Folders Always By Name"/> - <menu_item_check label="Cartelle di sistema all'inizio" name="System Folders To Top"/> - </menu> - </menu_bar> <filter_editor label="Filtro" name="inventory search editor"/> <tab_container name="inventory filter tabs"> <inventory_panel label="Tutti gli elementi" name="All Items"/> - <inventory_panel label="Elementi recenti" name="Recent Items"/> + <recent_inventory_panel label="Elementi recenti" name="Recent Items"/> </tab_container> - <panel name="bottom_panel"> - <button name="options_gear_btn" tool_tip="Mostra opzioni addizionali"/> - <button name="add_btn" tool_tip="Aggiungi nuovo elemento"/> - <dnd_button name="trash_btn" tool_tip="Rimuovi l'articolo selezionato"/> - </panel> + <layout_stack name="bottom_panel"> + <layout_panel name="options_gear_btn_panel"> + <button name="options_gear_btn" tool_tip="Mostra opzioni addizionali"/> + </layout_panel> + <layout_panel name="add_btn_panel"> + <button name="add_btn" tool_tip="Aggiungi nuovo elemento"/> + </layout_panel> + <layout_panel name="trash_btn_panel"> + <dnd_button name="trash_btn" tool_tip="Rimuovi l'articolo selezionato"/> + </layout_panel> + </layout_stack> </panel> diff --git a/indra/newview/skins/default/xui/it/panel_outfit_edit.xml b/indra/newview/skins/default/xui/it/panel_outfit_edit.xml index 516181e0e9..bd2202b60e 100644 --- a/indra/newview/skins/default/xui/it/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/it/panel_outfit_edit.xml @@ -2,6 +2,8 @@ <!-- Side tray Outfit Edit panel --> <panel label="Modifica del vestiario" name="outfit_edit"> <string name="No Outfit" value="Nessun vestiario"/> + <string name="unsaved_changes" value="Modifiche non salvate"/> + <string name="now_editing" value="Modifica di"/> <panel.string name="not_available"> (non pert.) </panel.string> @@ -15,24 +17,19 @@ <text name="title" value="Modifica vestiario"/> <panel label="bottom_panel" name="header_panel"> <panel label="bottom_panel" name="outfit_name_and_status"> - <text name="status" value="Modifica..."/> + <text name="status" value="Modifica di..."/> <text name="curr_outfit_name" value="[Current Outfit]"/> </panel> </panel> <layout_stack name="im_panels"> <layout_panel label="Pannello di controllo IM" name="outfit_wearables_panel"> - <scroll_list name="look_items_list"> - <scroll_list.columns label="Articolo look" name="look_item"/> - <scroll_list.columns label="Ordina in base agli articoli del vestiario" name="look_item_sort"/> - </scroll_list> <panel label="bottom_panel" name="edit_panel"/> </layout_panel> <layout_panel name="add_wearables_panel"> - <filter_editor label="Filtro" name="look_item_filter"/> + <text name="add_to_outfit_label" value="Aggiungi al vestiario:"/> <layout_stack name="filter_panels"> - <layout_panel label="Pannello di controllo IM" name="filter_button_panel"> - <text name="add_to_outfit_label" value="Aggiungi al vestiario:"/> - <button label="V" name="filter_button"/> + <layout_panel label="Pannello di controllo IM" name="filter_panel"> + <filter_editor label="Filtro" name="look_item_filter"/> </layout_panel> </layout_stack> <panel label="add_wearables_button_bar" name="add_wearables_button_bar"> diff --git a/indra/newview/skins/default/xui/it/panel_people.xml b/indra/newview/skins/default/xui/it/panel_people.xml index c469da014a..056e424436 100644 --- a/indra/newview/skins/default/xui/it/panel_people.xml +++ b/indra/newview/skins/default/xui/it/panel_people.xml @@ -2,9 +2,9 @@ <!-- Side tray panel --> <panel label="Persone" name="people_panel"> <string name="no_recent_people" value="Nessuna persona recente. Stai cercando persone da frequentare? Prova la [secondlife:///app/search/people Ricerca] o la [secondlife:///app/worldmap Mappa del mondo]."/> - <string name="no_filtered_recent_people" value="Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/people Cerca]."/> + <string name="no_filtered_recent_people" value="Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/people/[SEARCH_TERM] Cerca]."/> <string name="no_one_near" value="Nessuno vicino. Stai cercando persone da frequentare? Try la [secondlife:///app/search/people Ricerca] o la [secondlife:///app/worldmap Mappa del mondo]."/> - <string name="no_one_filtered_near" value="Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/people Cerca]."/> + <string name="no_one_filtered_near" value="Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/people/[SEARCH_TERM] Cerca]."/> <string name="no_friends_online" value="Nessun amico online"/> <string name="no_friends" value="Nessun amico"/> <string name="no_friends_msg"> @@ -12,11 +12,11 @@ Stai cercando persone da frequentare? Prova la [secondlife:///app/worldmap Mappa del mondo]. </string> <string name="no_filtered_friends_msg"> - Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/people Cerca]. + Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/people/[SEARCH_TERM] Cerca]. </string> <string name="people_filter_label" value="Filtro persone"/> <string name="groups_filter_label" value="Filtro gruppi"/> - <string name="no_filtered_groups_msg" value="Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/groups Cerca]."/> + <string name="no_filtered_groups_msg" value="Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/groups/[SEARCH_TERM] Cerca]."/> <string name="no_groups_msg" value="Stai cercando gruppi di cui far parte? Prova [secondlife:///app/search/groups Cerca]."/> <filter_editor label="Filtro" name="filter_input"/> <tab_container name="tabs"> @@ -55,7 +55,7 @@ Stai cercando persone da frequentare? Prova la [secondlife:///app/worldmap Mappa <button label="Profilo" name="view_profile_btn" tool_tip="Mostra immagine, gruppi e altre informazioni del residente"/> <button label="IM" name="im_btn" tool_tip="Apri una sessione messaggio istantaneo"/> <button label="Chiama" name="call_btn" tool_tip="Chiama questo residente"/> - <button label="Condividi" name="share_btn"/> + <button label="Condividi" name="share_btn" tool_tip="Condividi un oggetto dell'inventario"/> <button label="Teleport" name="teleport_btn" tool_tip="Offri teleport"/> <button label="Profilo del gruppo" name="group_info_btn" tool_tip="Mostra informazioni gruppo"/> <button label="Chat di gruppo" name="chat_btn" tool_tip="Apri sessione chat"/> diff --git a/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml index 09e19f4bc0..7c3f32ad7b 100644 --- a/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/it/panel_preferences_advanced.xml @@ -13,6 +13,7 @@ </text> <check_box label="Costruire/Modificare" name="edit_camera_movement" tool_tip="Utilizza il posizionamento automatico della fotocamera entrando o uscendo dalla modalità modifica"/> <check_box label="Aspetto fisico" name="appearance_camera_movement" tool_tip="Utilizza il posizionamento automatico della camera in modalità modifica"/> + <check_box initial_value="1" label="Barra laterale" name="appearance_sidebar_positioning" tool_tip="Utilizza il posizionamento automatico della fotocamera per la barra laterale"/> <check_box label="Visualizzami in modalità soggettiva" name="first_person_avatar_visible"/> <check_box label="Le frecce di direzione mi fanno sempre spostare" name="arrow_keys_move_avatar_check"/> <check_box label="Doppio click e tieni premuto per correre" name="tap_tap_hold_to_run"/> diff --git a/indra/newview/skins/default/xui/it/panel_preferences_chat.xml b/indra/newview/skins/default/xui/it/panel_preferences_chat.xml index 28df9d2e43..fb8ddf607d 100644 --- a/indra/newview/skins/default/xui/it/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/it/panel_preferences_chat.xml @@ -45,6 +45,7 @@ </text> <check_box initial_value="true" label="Simula la battitura tasti quando scrivi" name="play_typing_animation"/> <check_box label="Quando sono OFF-LINE, spediscimi gli IM in una e-mail" name="send_im_to_email"/> + <check_box label="Attiva IM in testo semplice e cronologia chat" name="plain_text_chat_history"/> <text name="show_ims_in_label"> Mostra gli IM in: </text> diff --git a/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml index 5bd0cfb106..37857473aa 100644 --- a/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/it/panel_preferences_graphics1.xml @@ -1,8 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="Grafica" name="Display panel"> - <text name="UI Size:"> - Dimensioni UI: - </text> <text name="QualitySpeed"> Qualità e velocità : </text> @@ -52,6 +49,10 @@ m </text> <slider label="Conteggio massimo particelle:" name="MaxParticleCount"/> + <slider label="Distanza visual. max avatar:" name="MaxAvatarDrawDistance"/> + <text name="DrawDistanceMeterText3"> + m + </text> <slider label="Qualità in post-produzione:" name="RenderPostProcess"/> <text name="MeshDetailText"> Dettagli reticolo: diff --git a/indra/newview/skins/default/xui/it/sidepanel_appearance.xml b/indra/newview/skins/default/xui/it/sidepanel_appearance.xml index c2e99b5573..df25772ffb 100644 --- a/indra/newview/skins/default/xui/it/sidepanel_appearance.xml +++ b/indra/newview/skins/default/xui/it/sidepanel_appearance.xml @@ -1,9 +1,13 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <panel label="Vestiario" name="appearance panel"> <string name="No Outfit" value="Nessun vestiario"/> + <string name="Unsaved Changes" value="Modifiche non salvate"/> + <string name="Now Wearing" value="Abbigliamento attuale..."/> <panel name="panel_currentlook"> - <text name="currentlook_title"> - (non salvato) + <button label="M" name="editappearance_btn"/> + <button label="A" name="openoutfit_btn"/> + <text name="currentlook_status"> + (Stato) </text> </panel> <filter_editor label="Filtri per il vestiario" name="Filter"/> diff --git a/indra/newview/skins/default/xui/it/sidepanel_inventory.xml b/indra/newview/skins/default/xui/it/sidepanel_inventory.xml index 8a391c882c..0d862a0ff7 100644 --- a/indra/newview/skins/default/xui/it/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/it/sidepanel_inventory.xml @@ -4,6 +4,7 @@ <panel name="button_panel"> <button label="Profilo" name="info_btn"/> <button label="Condividi" name="share_btn"/> + <button label="Acquisti" name="shop_btn"/> <button label="Indossa" name="wear_btn"/> <button label="Riproduci" name="play_btn"/> <button label="Teleport" name="teleport_btn"/> diff --git a/indra/newview/skins/default/xui/it/strings.xml b/indra/newview/skins/default/xui/it/strings.xml index 9a6c648c8e..67cd4c35b2 100644 --- a/indra/newview/skins/default/xui/it/strings.xml +++ b/indra/newview/skins/default/xui/it/strings.xml @@ -94,6 +94,24 @@ <string name="LoginDownloadingClothing"> Sto caricando i vestiti... </string> + <string name="InvalidCertificate"> + Il server ha inviato un certificato non valido o errato. Rivolgiti all'amministratore della griglia. + </string> + <string name="CertInvalidHostname"> + Per accedere al server è stato utilizzato un nome host non valido; controlla lo SLURL o il nome host della griglia. + </string> + <string name="CertExpired"> + Il certificato inviato dalla griglia sembra essere scaduto. Controlla l'orologio del sistema o rivolgiti all'amministratore della griglia. + </string> + <string name="CertKeyUsage"> + Impossibile utilizzare per SSl il certificato inviato dal server. Rivolgiti all'amministratore della griglia. + </string> + <string name="CertBasicConstraints"> + Nella catena dei certificati del server erano presenti troppi certificati. Rivolgiti all'amministratore della griglia. + </string> + <string name="CertInvalidSignature"> + Impossibile verificare la firma del certificato inviato dal server della griglia. Rivolgiti all'amministratore della griglia. + </string> <string name="LoginFailedNoNetwork"> Errore di rete: Non è stato possibile stabilire un collegamento, controlla la tua connessione. </string> @@ -825,6 +843,42 @@ <string name="invalid"> non valido </string> + <string name="shirt_not_worn"> + Camicia non indossata + </string> + <string name="pants_not_worn"> + Pantaloni non indossati + </string> + <string name="shoes_not_worn"> + Scarpe non indossate + </string> + <string name="socks_not_worn"> + Calzini non indossati + </string> + <string name="jacket_not_worn"> + Giacca non indossata + </string> + <string name="gloves_not_worn"> + Guanti non indossati + </string> + <string name="undershirt_not_worn"> + Maglietta intima non indossata + </string> + <string name="underpants_not_worn"> + Slip non indossati + </string> + <string name="skirt_not_worn"> + Gonna non indossata + </string> + <string name="alpha_not_worn"> + Alpha non portato + </string> + <string name="tattoo_not_worn"> + Tatuaggio non portato + </string> + <string name="invalid_not_worn"> + non valido + </string> <string name="NewWearable"> Nuovo [WEARABLE_ITEM] </string> @@ -895,7 +949,10 @@ Premi ESC per tornare in visualizzazione normale </string> <string name="InventoryNoMatchingItems"> - Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/all Cerca]. + Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/all/[SEARCH_TERM] Cerca]. + </string> + <string name="PlacesNoMatchingItems"> + Non riesci a trovare quello che cerchi? Prova [secondlife:///app/search/places/[SEARCH_TERM] Cerca]. </string> <string name="FavoritesNoMatchingItems"> Trascina qui un punto di riferimento per aggiungerlo ai Preferiti. @@ -925,6 +982,7 @@ <string name="Wave" value="Saluta con la mano"/> <string name="HelloAvatar" value="Ciao, avatar!"/> <string name="ViewAllGestures" value="Visualizza tutto >>"/> + <string name="GetMoreGestures" value="Altre >>"/> <string name="Animations" value="Animazioni,"/> <string name="Calling Cards" value="Biglietti da visita,"/> <string name="Clothing" value="Vestiti,"/> @@ -1537,16 +1595,19 @@ Il residente al quale hai inviato un messaggio è in modalità 'occupato', ovvero ha chiesto di non essere disturbato. Il tuo messaggio comparirà nel suo pannello IM, dove potrà essere letto in un secondo momento. </string> <string name="MuteByName"> - (in base al nome) + (In base al nome) </string> <string name="MuteAgent"> (Residente) </string> <string name="MuteObject"> - (oggetto) + (Oggetto) </string> <string name="MuteGroup"> - (gruppo) + (Gruppo) + </string> + <string name="MuteExternal"> + (esterno) </string> <string name="RegionNoCovenant"> Non esiste alcun regolamento per questa proprietà . @@ -3306,11 +3367,14 @@ Se il messaggio persiste, contatta [SUPPORT_SITE]. <string name="answered_call"> Risposto alla chiamata </string> - <string name="started_call"> - Chiamata vocale iniziata + <string name="you_started_call"> + Hai iniziato una chiamata vocale + </string> + <string name="you_joined_call"> + Ti sei collegato alla chiamata in voce </string> - <string name="joined_call"> - Si è collegato alla chiamata in voce + <string name="name_started_call"> + [NAME] ha iniziato una chiamata vocale </string> <string name="ringing-im"> Collegamento alla chiamata vocale... @@ -3509,6 +3573,90 @@ Segnala abuso <string name="Contents"> Contenuto </string> + <string name="Gesture"> + Gesture + </string> + <string name="Male Gestures"> + Gesture maschili + </string> + <string name="Female Gestures"> + Gesture femminili + </string> + <string name="Other Gestures"> + Altre gesture + </string> + <string name="Speech Gestures"> + Gesture del parlato + </string> + <string name="Common Gestures"> + Gesture comuni + </string> + <string name="Male - Excuse me"> + Maschio - Chiedere scusa + </string> + <string name="Male - Get lost"> + Maschio - Levati dai piedi! + </string> + <string name="Male - Blow kiss"> + Maschio - Butta un bacio + </string> + <string name="Male - Boo"> + Maschio - Bu + </string> + <string name="Male - Bored"> + Maschio - Annoiato + </string> + <string name="Male - Hey"> + Maschio - Ehi + </string> + <string name="Male - Laugh"> + Maschio - Ridere + </string> + <string name="Male - Repulsed"> + Maschio - Disgustato + </string> + <string name="Male - Shrug"> + Maschio - Spallucce + </string> + <string name="Male - Stick tougue out"> + Maschio - Tira fuori la lingua + </string> + <string name="Male - Wow"> + Maschio - Accipicchia + </string> + <string name="FeMale - Excuse me"> + Femmina - Chiedere scusa + </string> + <string name="FeMale - Get lost"> + Femmina - Levati dai piedi! + </string> + <string name="FeMale - Blow kiss"> + Femmina - Butta un bacio + </string> + <string name="FeMale - Boo"> + Femmina - Bu + </string> + <string name="Female - Bored"> + Femmina - Annoiata + </string> + <string name="Female - Hey"> + Femmina - Ehi + </string> + <string name="Female - Laugh"> + Femmina - Ridere + </string> + <string name="Female - Repulsed"> + Femmina - Disgustata + </string> + <string name="Female - Shrug"> + Femmina - Spallucce + </string> + <string name="Female - Stick tougue out"> + Femmina - Tira fuori la lingua + </string> + <string name="Female - Wow"> + Femmina - Accipicchia + </string> <string name="AvatarBirthDateFormat"> [day,datetime,slt]/[mthnum,datetime,slt]/[year,datetime,slt] </string> diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 8c089c0b79..0fd3cf5b3b 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -41,9 +41,12 @@ from llmanifest import LLManifest, main, proper_windows_path, path_ancestors class ViewerManifest(LLManifest): def is_packaging_viewer(self): - # This is overridden by the WindowsManifest sub-class, - # which has different behavior if it is not packaging the viewer. - return True + # Some commands, files will only be included + # if we are packaging the viewer on windows. + # This manifest is also used to copy + # files during the build (see copy_w_viewer_manifest + # and copy_l_viewer_manifest targets) + return 'package' in self.args['actions'] def construct(self): super(ViewerManifest, self).construct() @@ -175,13 +178,6 @@ class WindowsManifest(ViewerManifest): else: return ''.join(self.channel().split()) + '.exe' - def is_packaging_viewer(self): - # Some commands, files will only be included - # if we are packaging the viewer on windows. - # This manifest is also used to copy - # files during the build. - return 'package' in self.args['actions'] - def test_msvcrt_and_copy_action(self, src, dst): # This is used to test a dll manifest. # It is used as a temporary override during the construct method @@ -563,6 +559,10 @@ class WindowsManifest(ViewerManifest): class DarwinManifest(ViewerManifest): + def is_packaging_viewer(self): + # darwin requires full app bundle packaging even for debugging. + return True + def construct(self): # copy over the build result (this is a no-op if run within the xcode script) self.path(self.args['configuration'] + "/Second Life.app", dst="") @@ -641,7 +641,9 @@ class DarwinManifest(ViewerManifest): if dylibs["llcommon"]: for libfile in ("libapr-1.0.3.7.dylib", "libaprutil-1.0.3.8.dylib", - "libexpat.0.5.0.dylib"): + "libexpat.0.5.0.dylib", + "libexception_handler.dylib", + ): self.path(os.path.join(libdir, libfile), libfile) #libfmodwrapper.dylib @@ -662,7 +664,9 @@ class DarwinManifest(ViewerManifest): for libfile in ("libllcommon.dylib", "libapr-1.0.3.7.dylib", "libaprutil-1.0.3.8.dylib", - "libexpat.0.5.0.dylib"): + "libexpat.0.5.0.dylib", + "libexception_handler.dylib", + ): target_lib = os.path.join('../../..', libfile) self.run_command("ln -sf %(target)r %(link)r" % {'target': target_lib, @@ -893,6 +897,7 @@ class Linux_i686Manifest(LinuxManifest): if self.prefix("../../libraries/i686-linux/lib_release_client", dst="lib"): self.path("libapr-1.so.0") self.path("libaprutil-1.so.0") + self.path("libbreakpad_client.so.0.0.0", "libbreakpad_client.so.0") self.path("libdb-4.2.so") self.path("libcrypto.so.0.9.7") self.path("libexpat.so.1") @@ -930,7 +935,7 @@ class Linux_i686Manifest(LinuxManifest): self.path("libvivoxplatform.so") self.end_prefix("lib") - if self.args['buildtype'].lower() == 'release': + if self.args['buildtype'].lower() == 'release' and self.is_packaging_viewer(): print "* Going strip-crazy on the packaged binaries, since this is a RELEASE build" self.run_command("find %(d)r/bin %(d)r/lib -type f | xargs --no-run-if-empty strip -S" % {'d': self.get_dst_prefix()} ) # makes some small assumptions about our packaged dir structure diff --git a/indra/win_crash_logger/llcrashloggerwindows.cpp b/indra/win_crash_logger/llcrashloggerwindows.cpp index c9e01c8418..2884231299 100644 --- a/indra/win_crash_logger/llcrashloggerwindows.cpp +++ b/indra/win_crash_logger/llcrashloggerwindows.cpp @@ -299,7 +299,6 @@ void LLCrashLoggerWindows::gatherPlatformSpecificFiles() // At this point we're responsive enough the user could click the close button SetCursor(gCursorArrow); mDebugLog["DisplayDeviceInfo"] = gDXHardware.getDisplayInfo(); - mFileMap["CrashLog"] = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,"SecondLifeException.log"); } bool LLCrashLoggerWindows::mainLoop() diff --git a/install.xml b/install.xml index 8387372400..1f3e74a27a 100644 --- a/install.xml +++ b/install.xml @@ -132,9 +132,9 @@ <key>windows</key> <map> <key>md5sum</key> - <string>f5cf8d121b26f2e7944f7e63cdbff04d</string> + <string>4b84738eec2e21b0c096d53b79ee2681</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/ares-1.6.0-windows-20091105.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/ares-1.7.1-windows-20100611a.tar.bz2</uri> </map> </map> </map> @@ -254,9 +254,9 @@ <key>windows</key> <map> <key>md5sum</key> - <string>78ccac8aaf8ea5bec482dfbcdbeb1651</string> + <string>b28856d3d02ee680353ae440561a6579</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/curl-7.19.6-windows-20100414.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/curl-7.20.1-windows-20100611.tar.bz2</uri> </map> </map> </map> @@ -583,6 +583,39 @@ </map> </map> </map> + <key>google_breakpad</key> + <map> + <key>copyright</key> + <string>Copyright (c) 2006, Google Inc.</string> + <key>description</key> + <string>An open-source multi-platform crash reporting system </string> + <key>license</key> + <string>bsd</string> + <key>packages</key> + <map> + <key>darwin</key> + <map> + <key>md5sum</key> + <string>ced4010b59f1a579caa7fe3c18512499</string> + <key>url</key> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/google_breakpad-0.0.0-rev599-darwin-20100528a.tar.bz2</uri> + </map> + <key>linux</key> + <map> + <key>md5sum</key> + <string>29c3e7dad60bbf02c811786436d99523</string> + <key>url</key> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/google_breakpad-0.0.0-rev599-linux-20100521b.tar.bz2</uri> + </map> + <key>windows</key> + <map> + <key>md5sum</key> + <string>0859d47242990125f17eaab30bece2ff</string> + <key>url</key> + <uri>http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/google_breakpad-0.0.0-rev599-windows-20100524.tar.bz2</uri> + </map> + </map> + </map> <key>googlemock</key> <map> <key>copyright</key> @@ -962,9 +995,9 @@ anguage Infrstructure (CLI) international standard</string> <key>windows</key> <map> <key>md5sum</key> - <string>1d9697fed57084eea7b3dc250e9c66f7</string> + <string>d682ed6232193b4eab3170657a54ebf9</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-windows-qt4.6-20100525.tar.bz2</uri> + <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-windows-qt4.6-20100519.tar.bz2</uri> </map> </map> </map> |