diff options
Diffstat (limited to 'indra')
82 files changed, 1321 insertions, 449 deletions
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index db2cdb5ff8..dbe0cf5cd0 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -4,27 +4,28 @@ include(Variables) - # Portable compilation flags. - -if (EXISTS ${CMAKE_SOURCE_DIR}/llphysics) - # The release build should only offer to send crash reports if we're - # building from a Linden internal source tree. - set(release_crash_reports 1) -else (EXISTS ${CMAKE_SOURCE_DIR}/llphysics) - set(release_crash_reports 0) -endif (EXISTS ${CMAKE_SOURCE_DIR}/llphysics) - set(CMAKE_CXX_FLAGS_DEBUG "-D_DEBUG -DLL_DEBUG=1") set(CMAKE_CXX_FLAGS_RELEASE - "-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -D_SECURE_SCL=0 -DLL_SEND_CRASH_REPORTS=${release_crash_reports} -DNDEBUG") + "-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -D_SECURE_SCL=0 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO - "-DLL_RELEASE=1 -D_SECURE_SCL=0 -DLL_SEND_CRASH_REPORTS=0 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1") + "-DLL_RELEASE=1 -D_SECURE_SCL=0 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1") +# Configure crash reporting +set(RELEASE_CRASH_REPORTING OFF CACHE BOOL "Enable use of crash reporting in release builds") +set(NON_RELEASE_CRASH_REPORTING OFF CACHE BOOL "Enable use of crash reporting in developer builds") -# Don't bother with a MinSizeRel build. +if(RELEASE_CRASH_REPORTING) + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DLL_SEND_CRASH_REPORTS=1") +endif() + +if(NON_RELEASE_CRASH_REPORTING) + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DLL_SEND_CRASH_REPORTS=1") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DLL_SEND_CRASH_REPORTS=1") +endif() +# Don't bother with a MinSizeRel build. set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release;Debug" CACHE STRING "Supported build types." FORCE) diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index 1cc03bddb8..c9cb1cd6e7 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -1557,6 +1557,10 @@ bool LLAudioSource::hasPendingPreloads() const LLAudioData *adp = iter->second; // note: a bad UUID will forever be !hasDecodedData() // but also !hasValidData(), hence the check for hasValidData() + if (!adp) + { + continue; + } if (!adp->hasDecodedData() && adp->hasValidData()) { // This source is still waiting for a preload diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 84a6620a77..97e2bdeb57 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -475,7 +475,7 @@ void LLEventPump::stopListening(const std::string& name) *****************************************************************************/ bool LLEventStream::post(const LLSD& event) { - if (! mEnabled) + if (! mEnabled || !mSignal) { return false; } @@ -515,6 +515,8 @@ bool LLEventQueue::post(const LLSD& event) void LLEventQueue::flush() { + if(!mSignal) return; + // Consider the case when a given listener on this LLEventQueue posts yet // another event on the same queue. If we loop over mEventQueue directly, // we'll end up processing all those events during the same flush() call diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index e491b502ab..356e0f4c0f 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -28,7 +28,7 @@ #define LL_LLVERSIONVIEWER_H const S32 LL_VERSION_MAJOR = 2; -const S32 LL_VERSION_MINOR = 4; +const S32 LL_VERSION_MINOR = 5; const S32 LL_VERSION_PATCH = 0; const S32 LL_VERSION_BUILD = 0; diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index bda76eac80..a3caf79519 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -61,8 +61,6 @@ static const std::string INV_FOLDER_ID_LABEL_WS("category_id"); ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- -const U8 TASK_INVENTORY_ITEM_KEY = 0; -const U8 TASK_INVENTORY_ASSET_KEY = 1; const LLUUID MAGIC_ID("3c115e51-04f4-523c-9fa6-98aff1034730"); diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 7396117d84..03c28eb2a5 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -235,27 +235,21 @@ public: /*virtual*/ void error(U32 status, const std::string& reason) { - // We're going to construct a dummy record and cache it for a while, - // either briefly for a 503 Service Unavailable, or longer for other - // errors. - F64 retry_timestamp = errorRetryTimestamp(status); - - // *NOTE: "??" starts trigraphs in C/C++, escape the question marks. - const std::string DUMMY_NAME("\?\?\?"); - LLAvatarName av_name; - av_name.mUsername = DUMMY_NAME; - av_name.mDisplayName = DUMMY_NAME; - av_name.mIsDisplayNameDefault = false; - av_name.mIsDummy = true; - av_name.mExpires = retry_timestamp; + // If there's an error, it might be caused by PeopleApi, + // or when loading textures on startup and using a very slow + // network, this query may time out. Fallback to the legacy + // cache. + + llwarns << "LLAvatarNameResponder error " << status << " " << reason << llendl; // Add dummy records for all agent IDs in this request std::vector<LLUUID>::const_iterator it = mAgentIDs.begin(); for ( ; it != mAgentIDs.end(); ++it) { const LLUUID& agent_id = *it; - // cache it and fire signals - LLAvatarNameCache::processName(agent_id, av_name, true); + gCacheName->get(agent_id, false, // legacy compatibility + boost::bind(&LLAvatarNameCache::legacyNameCallback, + _1, _2, _3)); } } @@ -357,7 +351,7 @@ void LLAvatarNameCache::requestNamesViaCapability() if (url.size() > NAME_URL_SEND_THRESHOLD) { //llinfos << "requestNames " << url << llendl; - LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids)); + LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids));//, LLSD(), 10.0f); url.clear(); agent_ids.clear(); } @@ -366,7 +360,7 @@ void LLAvatarNameCache::requestNamesViaCapability() if (!url.empty()) { //llinfos << "requestNames " << url << llendl; - LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids)); + LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids));//, LLSD(), 10.0f); url.clear(); agent_ids.clear(); } diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 4ab6bd2438..479efabb5f 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -556,35 +556,43 @@ std::string LLCacheName::buildUsername(const std::string& full_name) //static std::string LLCacheName::buildLegacyName(const std::string& complete_name) { - // regexp doesn't play nice with unicode, chop off the display name + //boost::regexp was showing up in the crashreporter, so doing + //painfully manual parsing using substr. LF S32 open_paren = complete_name.rfind(" ("); + S32 close_paren = complete_name.rfind(')'); - if (open_paren == std::string::npos) + if (open_paren != std::string::npos && + close_paren == complete_name.length()-1) { - return complete_name; - } + S32 length = close_paren - open_paren - 2; + std::string legacy_name = complete_name.substr(open_paren+2, length); + + if (legacy_name.length() > 0) + { + std::string cap_letter = legacy_name.substr(0, 1); + LLStringUtil::toUpper(cap_letter); + legacy_name = cap_letter + legacy_name.substr(1); + + S32 separator = legacy_name.find('.'); - std::string username = complete_name.substr(open_paren); - boost::regex complete_name_regex("( \\()([a-z0-9]+)(.[a-z]+)*(\\))"); - boost::match_results<std::string::const_iterator> name_results; - if (!boost::regex_match(username, name_results, complete_name_regex)) return complete_name; + if (separator != std::string::npos) + { + std::string last_name = legacy_name.substr(separator+1); + legacy_name = legacy_name.substr(0, separator); - std::string legacy_name = name_results[2]; - // capitalize the first letter - std::string cap_letter = legacy_name.substr(0, 1); - LLStringUtil::toUpper(cap_letter); - legacy_name = cap_letter + legacy_name.substr(1); + if (last_name.length() > 0) + { + cap_letter = last_name.substr(0, 1); + LLStringUtil::toUpper(cap_letter); + legacy_name = legacy_name + " " + cap_letter + last_name.substr(1); + } + } - if (name_results[3].matched) - { - std::string last_name = name_results[3]; - std::string cap_letter = last_name.substr(1, 1); - LLStringUtil::toUpper(cap_letter); - last_name = cap_letter + last_name.substr(2); - legacy_name = legacy_name + " " + last_name; + return legacy_name; + } } - return legacy_name; + return complete_name; } // This is a little bit kludgy. LLCacheNameCallback is a slot instead of a function pointer. @@ -967,6 +975,10 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup) if (entry->mLastName.empty()) { full_name = cleanFullName(entry->mFirstName); + + //fix what we are putting in the cache + entry->mFirstName = full_name; + entry->mLastName = "Resident"; } else { diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 70014fe4f5..6b06040b8a 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -769,7 +769,8 @@ BOOL LLComboBox::handleKeyHere(KEY key, MASK mask) return FALSE; } // if selection has changed, pop open list - else if ((mList->getLastSelectedItem() != last_selected_item) || (key == KEY_DOWN) || (key == KEY_UP)) + else if (mList->getLastSelectedItem() != last_selected_item || + (key == KEY_DOWN || key == KEY_UP) && !mList->isEmpty()) { showList(); } diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp index d48674f306..f6f5a0beb3 100644 --- a/indra/llui/lldockcontrol.cpp +++ b/indra/llui/lldockcontrol.cpp @@ -220,10 +220,15 @@ void LLDockControl::moveDockable() case TOP: x = dockRect.getCenterX() - dockableRect.getWidth() / 2; y = dockRect.mTop + dockableRect.getHeight(); - // unique docking used with dock tongue, so add tongue height o the Y coordinate + // unique docking used with dock tongue, so add tongue height to the Y coordinate if (use_tongue) { y += mDockTongue->getHeight(); + + if ( y > rootRect.mTop) + { + y = rootRect.mTop; + } } // check is dockable inside root view rect @@ -257,7 +262,7 @@ void LLDockControl::moveDockable() case BOTTOM: x = dockRect.getCenterX() - dockableRect.getWidth() / 2; y = dockRect.mBottom; - // unique docking used with dock tongue, so add tongue height o the Y coordinate + // unique docking used with dock tongue, so add tongue height to the Y coordinate if (use_tongue) { y -= mDockTongue->getHeight(); @@ -292,9 +297,21 @@ void LLDockControl::moveDockable() break; } - // move dockable - dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(), - dockableRect.getHeight()); + S32 max_available_height = rootRect.getHeight() - mDockTongueY - mDockTongue->getHeight(); + + // A floater should be shrunk so it doesn't cover a part of its docking tongue and + // there is a space between a dockable floater and a control to which it is docked. + if (use_tongue && dockableRect.getHeight() >= max_available_height) + { + dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(), max_available_height); + mDockableFloater->reshape(dockableRect.getWidth(), dockableRect.getHeight()); + } + else + { + // move dockable + dockableRect.setLeftTopAndSize(x, y, dockableRect.getWidth(), + dockableRect.getHeight()); + } LLRect localDocableParentRect; mDockableFloater->getParent()->screenRectToLocal(dockableRect, &localDocableParentRect); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 7727e154da..1265733bf5 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -1,4 +1,5 @@ /** + * @file llfloater.cpp * @brief LLFloater base class * @@ -1189,7 +1190,7 @@ void LLFloater::setFocus( BOOL b ) last_focus->setFocus(TRUE); } } - updateTransparency(this, b ? TT_ACTIVE : TT_INACTIVE); + updateTransparency(b ? TT_ACTIVE : TT_INACTIVE); } // virtual @@ -1462,6 +1463,9 @@ void LLFloater::setFrontmost(BOOL take_focus) // there are more than one floater view // so we need to query our parent directly ((LLFloaterView*)getParent())->bringToFront(this, take_focus); + + // Make sure to set the appropriate transparency type (STORM-732). + updateTransparency(hasFocus() || getIsChrome() ? TT_ACTIVE : TT_INACTIVE); } } diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp index ac568a83e4..eed0085273 100644 --- a/indra/llui/llmenubutton.cpp +++ b/indra/llui/llmenubutton.cpp @@ -175,6 +175,13 @@ void LLMenuButton::updateMenuOrigin() mY = rect.mTop + mMenuHandle.get()->getRect().getHeight(); break; } + case MP_TOP_RIGHT: + { + const LLRect& menu_rect = mMenuHandle.get()->getRect(); + mX = rect.mRight - menu_rect.getWidth(); + mY = rect.mTop + menu_rect.getHeight(); + break; + } case MP_BOTTOM_LEFT: { mX = rect.mLeft; diff --git a/indra/llui/llmenubutton.h b/indra/llui/llmenubutton.h index 9e91b9e99d..7b657595da 100644 --- a/indra/llui/llmenubutton.h +++ b/indra/llui/llmenubutton.h @@ -47,6 +47,7 @@ public: typedef enum e_menu_position { MP_TOP_LEFT, + MP_TOP_RIGHT, MP_BOTTOM_LEFT } EMenuPosition; diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp index 2a4c1ca44c..696e4a2bb1 100644 --- a/indra/llui/llscrolllistcolumn.cpp +++ b/indra/llui/llscrolllistcolumn.cpp @@ -83,7 +83,14 @@ void LLScrollColumnHeader::draw() && (sort_column == mColumn->mSortingColumn || sort_column == mColumn->mName); BOOL is_ascending = mColumn->mParentCtrl->getSortAscending(); - setImageOverlay(is_ascending ? "up_arrow.tga" : "down_arrow.tga", LLFontGL::RIGHT, draw_arrow ? LLColor4::white : LLColor4::transparent); + if (draw_arrow) + { + setImageOverlay(is_ascending ? "up_arrow.tga" : "down_arrow.tga", LLFontGL::RIGHT, LLColor4::white); + } + else + { + setImageOverlay(LLUUID::null); + } // Draw children LLButton::draw(); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 679637caf6..1a3f274664 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1843,29 +1843,31 @@ if (PACKAGE) set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest) endif (LINUX) - if(CMAKE_CFG_INTDIR STREQUAL ".") + if(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) + if(CMAKE_CFG_INTDIR STREQUAL ".") set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE}) - else(CMAKE_CFG_INTDIR STREQUAL ".") + else(CMAKE_CFG_INTDIR STREQUAL ".") # set LLBUILD_CONFIG to be a shell variable evaluated at build time # reflecting the configuration we are currently building. set(LLBUILD_CONFIG ${CMAKE_CFG_INTDIR}) - endif(CMAKE_CFG_INTDIR STREQUAL ".") - add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" - COMMAND "${PYTHON_EXECUTABLE}" - ARGS - "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" - "${LLBUILD_CONFIG}" - "${VIEWER_DIST_DIR}" - "${VIEWER_EXE_GLOBS}" - "${VIEWER_LIB_GLOB}" - "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/bin/dump_syms" - "${VIEWER_SYMBOL_FILE}" - DEPENDS generate_breakpad_symbols.py - VERBATIM - ) - add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}") - add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}") - add_dependencies(package generate_breakpad_symbols) + endif(CMAKE_CFG_INTDIR STREQUAL ".") + add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" + COMMAND "${PYTHON_EXECUTABLE}" + ARGS + "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" + "${LLBUILD_CONFIG}" + "${VIEWER_DIST_DIR}" + "${VIEWER_EXE_GLOBS}" + "${VIEWER_LIB_GLOB}" + "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/bin/dump_syms" + "${VIEWER_SYMBOL_FILE}" + DEPENDS generate_breakpad_symbols.py + VERBATIM) + + add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}") + add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}") + add_dependencies(package generate_breakpad_symbols) + endif(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) endif (PACKAGE) if (LL_TESTS) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 402a0e85c4..ae66f5ec39 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9990,6 +9990,17 @@ <key>Value</key> <real>500.0</real> </map> + <key>UpdaterMaximumBandwidth</key> + <map> + <key>Comment</key> + <string>Maximum allowable downstream bandwidth for updater service (kilo bits per second)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>500.0</real> + </map> <key>ToolTipDelay</key> <map> <key>Comment</key> @@ -11090,16 +11101,16 @@ <key>Value</key> <integer>15</integer> </map> - <key>UpdaterServiceActive</key> + <key>UpdaterServiceSetting</key> <map> <key>Comment</key> - <string>Enable or disable the updater service.</string> + <string>Configure updater service.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Boolean</string> + <string>U32</string> <key>Value</key> - <integer>1</integer> + <integer>3</integer> </map> <key>UpdaterServiceCheckPeriod</key> <map> @@ -12241,6 +12252,7 @@ <key>Value</key> <array> <string>snapshot</string> + <string>postcard</string> <string>mini_map</string> </array> </map> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 6c07974f69..eb8d87e184 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -80,6 +80,7 @@ #include "llfeaturemanager.h" #include "llurlmatch.h" #include "lltextutil.h" +#include "lllogininstance.h" #include "llweb.h" #include "llsecondlifeurls.h" @@ -590,10 +591,14 @@ LLAppViewer::LLAppViewer() : setupErrorHandling(); sInstance = this; gLoggedInTime.stop(); + + LLLoginInstance::instance().setUpdaterService(mUpdater.get()); } LLAppViewer::~LLAppViewer() { + LLLoginInstance::instance().setUpdaterService(0); + destroyMainloopTimeout(); // If we got to this destructor somehow, the app didn't hang. @@ -2389,26 +2394,111 @@ bool LLAppViewer::initConfiguration() } namespace { - // *TODO - decide if there's a better place for this function. + // *TODO - decide if there's a better place for these functions. // do we need a file llupdaterui.cpp or something? -brad + + void apply_update_callback(LLSD const & notification, LLSD const & response) + { + lldebugs << "LLUpdate user response: " << response << llendl; + if(response["OK_okcancelbuttons"].asBoolean()) + { + llinfos << "LLUpdate restarting viewer" << llendl; + static const bool install_if_ready = true; + // *HACK - this lets us launch the installer immediately for now + LLUpdaterService().startChecking(install_if_ready); + } + } + + void apply_update_ok_callback(LLSD const & notification, LLSD const & response) + { + llinfos << "LLUpdate restarting viewer" << llendl; + static const bool install_if_ready = true; + // *HACK - this lets us launch the installer immediately for now + LLUpdaterService().startChecking(install_if_ready); + } + + void on_update_downloaded(LLSD const & data) + { + std::string notification_name; + void (*apply_callback)(LLSD const &, LLSD const &) = NULL; + + if(data["required"].asBoolean()) + { + apply_callback = &apply_update_ok_callback; + if(LLStartUp::getStartupState() <= STATE_LOGIN_WAIT) + { + // The user never saw the progress bar. + notification_name = "RequiredUpdateDownloadedVerboseDialog"; + } + else + { + notification_name = "RequiredUpdateDownloadedDialog"; + } + } + else + { + apply_callback = &apply_update_callback; + if(LLStartUp::getStartupState() < STATE_STARTED) + { + // CHOP-262 we need to use a different notification + // method prior to login. + notification_name = "DownloadBackgroundDialog"; + } + else + { + notification_name = "DownloadBackgroundTip"; + } + } + + LLSD substitutions; + substitutions["VERSION"] = data["version"]; + + // truncate version at the rightmost '.' + std::string version_short(data["version"]); + size_t short_length = version_short.rfind('.'); + if (short_length != std::string::npos) + { + version_short.resize(short_length); + } + + LLUIString relnotes_url("[RELEASE_NOTES_BASE_URL][CHANNEL_URL]/[VERSION_SHORT]"); + relnotes_url.setArg("[VERSION_SHORT]", version_short); + + // *TODO thread the update service's response through to this point + std::string const & channel = LLVersionInfo::getChannel(); + boost::shared_ptr<char> channel_escaped(curl_escape(channel.c_str(), channel.size()), &curl_free); + + relnotes_url.setArg("[CHANNEL_URL]", channel_escaped.get()); + relnotes_url.setArg("[RELEASE_NOTES_BASE_URL]", LLTrans::getString("RELEASE_NOTES_BASE_URL")); + substitutions["RELEASE_NOTES_FULL_URL"] = relnotes_url.getString(); + + LLNotificationsUtil::add(notification_name, substitutions, LLSD(), apply_callback); + } + bool notify_update(LLSD const & evt) { + std::string notification_name; switch (evt["type"].asInteger()) { case LLUpdaterService::DOWNLOAD_COMPLETE: - LLNotificationsUtil::add("DownloadBackground"); + on_update_downloaded(evt); break; case LLUpdaterService::INSTALL_ERROR: LLNotificationsUtil::add("FailedUpdateInstall"); break; default: - llinfos << "unhandled update event " << evt << llendl; break; } // let others also handle this event by default return false; } + + bool on_bandwidth_throttle(LLUpdaterService * updater, LLSD const & evt) + { + updater->setBandwidthLimit(evt.asInteger() * (1024/8)); + return false; // Let others receive this event. + }; }; void LLAppViewer::initUpdater() @@ -2431,7 +2521,10 @@ void LLAppViewer::initUpdater() channel, version); mUpdater->setCheckPeriod(check_period); - if(gSavedSettings.getBOOL("UpdaterServiceActive")) + mUpdater->setBandwidthLimit((int)gSavedSettings.getF32("UpdaterMaximumBandwidth") * (1024/8)); + gSavedSettings.getControl("UpdaterMaximumBandwidth")->getSignal()-> + connect(boost::bind(&on_bandwidth_throttle, mUpdater.get(), _2)); + if(gSavedSettings.getU32("UpdaterServiceSetting")) { bool install_if_ready = true; mUpdater->startChecking(install_if_ready); @@ -2858,8 +2951,10 @@ void LLAppViewer::handleViewerCrash() pApp->removeMarkerFile(false); } +#if LL_SEND_CRASH_REPORTS // Call to pure virtual, handled by platform specific llappviewer instance. pApp->handleCrashReporting(); +#endif return; } diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 3afddc1145..899e0431e7 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -224,7 +224,8 @@ void LLNearbyChatToastPanel::init(LLSD& notification) href = LLSLURL("object", mFromID, "inspect").getSLURLString(); } - style_params_name.color(textColor); + LLColor4 user_name_color = LLUIColorTable::instance().getColor("HTMLLinkColor"); + style_params_name.color(user_name_color); std::string font_name = LLFontGL::nameFromFont(messageFont); std::string font_style_size = LLFontGL::sizeFromFont(messageFont); diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index a1ba370c26..0c0fdd5572 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -368,14 +368,15 @@ LLFavoritesBarCtrl::Params::Params() LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p) : LLUICtrl(p), mFont(p.font.isProvided() ? p.font() : LLFontGL::getFontSansSerifSmall()), - mPopupMenuHandle(), - mInventoryItemsPopupMenuHandle(), + mOverflowMenuHandle(), + mContextMenuHandle(), mImageDragIndication(p.image_drag_indication), mShowDragMarker(FALSE), mLandingTab(NULL), mLastTab(NULL), mTabsHighlightEnabled(TRUE) , mUpdateDropDownItems(true) +, mRestoreOverflowMenu(false) { // Register callback for menus with current registrar (will be parent panel's registrar) LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Favorites.DoToSelected", @@ -402,8 +403,8 @@ LLFavoritesBarCtrl::~LLFavoritesBarCtrl() { gInventory.removeObserver(this); - LLView::deleteViewByHandle(mPopupMenuHandle); - LLView::deleteViewByHandle(mInventoryItemsPopupMenuHandle); + LLView::deleteViewByHandle(mOverflowMenuHandle); + LLView::deleteViewByHandle(mContextMenuHandle); } BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, @@ -520,7 +521,7 @@ void LLFavoritesBarCtrl::handleExistingFavoriteDragAndDrop(S32 x, S32 y) gInventory.saveItemsOrder(mItems); - LLToggleableMenu* menu = (LLToggleableMenu*) mPopupMenuHandle.get(); + LLToggleableMenu* menu = (LLToggleableMenu*) mOverflowMenuHandle.get(); if (menu && menu->getVisible()) { @@ -776,7 +777,7 @@ void LLFavoritesBarCtrl::updateButtons() mChevronButton->setVisible(TRUE); } // Update overflow menu - LLToggleableMenu* overflow_menu = static_cast <LLToggleableMenu*> (mPopupMenuHandle.get()); + LLToggleableMenu* overflow_menu = static_cast <LLToggleableMenu*> (mOverflowMenuHandle.get()); if (overflow_menu && overflow_menu->getVisible()) { overflow_menu->setVisible(FALSE); @@ -850,7 +851,7 @@ BOOL LLFavoritesBarCtrl::postBuild() menu = LLUICtrlFactory::getDefaultWidget<LLMenuGL>("inventory_menu"); } menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); - mInventoryItemsPopupMenuHandle = menu->getHandle(); + mContextMenuHandle = menu->getHandle(); return TRUE; } @@ -881,7 +882,7 @@ BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &it void LLFavoritesBarCtrl::showDropDownMenu() { - if (mPopupMenuHandle.isDead()) + if (mOverflowMenuHandle.isDead()) { LLToggleableMenu::Params menu_p; menu_p.name("favorites menu"); @@ -892,10 +893,10 @@ void LLFavoritesBarCtrl::showDropDownMenu() menu_p.preferred_width = DROP_DOWN_MENU_WIDTH; LLToggleableMenu* menu = LLUICtrlFactory::create<LLFavoriteLandmarkToggleableMenu>(menu_p); - mPopupMenuHandle = menu->getHandle(); + mOverflowMenuHandle = menu->getHandle(); } - LLToggleableMenu* menu = (LLToggleableMenu*)mPopupMenuHandle.get(); + LLToggleableMenu* menu = (LLToggleableMenu*)mOverflowMenuHandle.get(); if (menu) { @@ -973,11 +974,19 @@ void LLFavoritesBarCtrl::onButtonRightClick( LLUUID item_id,LLView* fav_button,S { mSelectedItemID = item_id; - LLMenuGL* menu = (LLMenuGL*)mInventoryItemsPopupMenuHandle.get(); + LLMenuGL* menu = (LLMenuGL*)mContextMenuHandle.get(); if (!menu) { return; } + + // Remember that the context menu was shown simultaneously with the overflow menu, + // so that we can restore the overflow menu when user clicks a context menu item + // (which hides the overflow menu). + { + LLView* overflow_menu = mOverflowMenuHandle.get(); + mRestoreOverflowMenu = overflow_menu && overflow_menu->getVisible(); + } // Release mouse capture so hover events go to the popup menu // because this is happening during a mouse down. @@ -1082,8 +1091,8 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata) // Pop-up the overflow menu again (it gets hidden whenever the user clicks a context menu item). // See EXT-4217 and STORM-207. - LLToggleableMenu* menu = (LLToggleableMenu*) mPopupMenuHandle.get(); - if (menu && !menu->getVisible()) + LLToggleableMenu* menu = (LLToggleableMenu*) mOverflowMenuHandle.get(); + if (mRestoreOverflowMenu && menu && !menu->getVisible()) { showDropDownMenu(); } @@ -1149,11 +1158,11 @@ void LLFavoritesBarCtrl::pastFromClipboard() const void LLFavoritesBarCtrl::onButtonMouseDown(LLUUID id, LLUICtrl* ctrl, S32 x, S32 y, MASK mask) { // EXT-6997 (Fav bar: Pop-up menu for LM in overflow dropdown is kept after LM was dragged away) - // mInventoryItemsPopupMenuHandle.get() - is a pop-up menu (of items) in already opened dropdown menu. + // mContextMenuHandle.get() - is a pop-up menu (of items) in already opened dropdown menu. // We have to check and set visibility of pop-up menu in such a way instead of using // LLMenuHolderGL::hideMenus() because it will close both menus(dropdown and pop-up), but // we need to close only pop-up menu while dropdown one should be still opened. - LLMenuGL* menu = (LLMenuGL*)mInventoryItemsPopupMenuHandle.get(); + LLMenuGL* menu = (LLMenuGL*)mContextMenuHandle.get(); if(menu && menu->getVisible()) { menu->setVisible(FALSE); diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index 37645523f6..1a28731c4f 100644 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -91,13 +91,14 @@ protected: void showDropDownMenu(); - LLHandle<LLView> mPopupMenuHandle; - LLHandle<LLView> mInventoryItemsPopupMenuHandle; + LLHandle<LLView> mOverflowMenuHandle; + LLHandle<LLView> mContextMenuHandle; LLUUID mFavoriteFolderId; const LLFontGL *mFont; S32 mFirstDropDownItem; bool mUpdateDropDownItems; + bool mRestoreOverflowMenu; LLUUID mSelectedItemID; diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp index f0c9d52ccd..054ab4538b 100644 --- a/indra/newview/llfloaterpostcard.cpp +++ b/indra/newview/llfloaterpostcard.cpp @@ -112,11 +112,14 @@ LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLView // Take the images from the caller // It's now our job to clean them up LLFloaterPostcard* instance = LLFloaterReg::showTypedInstance<LLFloaterPostcard>("postcard", LLSD(img->getID())); - - instance->mJPEGImage = jpeg; - instance->mViewerImage = img; - instance->mImageScale = image_scale; - instance->mPosTakenGlobal = pos_taken_global; + + if (instance) // may be 0 if we're in mouselook mode + { + instance->mJPEGImage = jpeg; + instance->mViewerImage = img; + instance->mImageScale = image_scale; + instance->mPosTakenGlobal = pos_taken_global; + } return instance; } diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 6a7b5171b5..338b6555ff 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -342,6 +342,8 @@ BOOL LLFloaterPreference::postBuild() gSavedSettings.getControl("ChatFontSize")->getSignal()->connect(boost::bind(&LLNearbyChat::processChatHistoryStyleUpdate, _2)); + gSavedSettings.getControl("ChatBubbleOpacity")->getSignal()->connect(boost::bind(&LLFloaterPreference::onNameTagOpacityChange, this, _2)); + LLTabContainer* tabcontainer = getChild<LLTabContainer>("pref core"); if (!tabcontainer->selectTab(gSavedSettings.getS32("LastPrefTab"))) tabcontainer->selectFirstTab(); @@ -745,6 +747,16 @@ void LLFloaterPreference::onLanguageChange() } } +void LLFloaterPreference::onNameTagOpacityChange(const LLSD& newvalue) +{ + LLColorSwatchCtrl* color_swatch = findChild<LLColorSwatchCtrl>("background"); + if (color_swatch) + { + LLColor4 new_color = color_swatch->get(); + color_swatch->set( new_color.setAlpha(newvalue.asReal()) ); + } +} + void LLFloaterPreference::onClickSetCache() { std::string cur_name(gSavedSettings.getString("CacheLocation")); diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index bb871e7e25..0f51189853 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -84,6 +84,7 @@ protected: void onClickBrowserClearCache(); void onLanguageChange(); + void onNameTagOpacityChange(const LLSD& newvalue); // set value of "BusyResponseChanged" in account settings depending on whether busy response // string differs from default after user changes. diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 2f40f51763..f5f59d5973 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -279,9 +279,27 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& void LLIMModel::LLIMSession::onAdHocNameCache(const LLAvatarName& av_name) { - LLStringUtil::format_map_t args; - args["[AGENT_NAME]"] = av_name.getCompleteName(); - LLTrans::findString(mName, "conference-title-incoming", args); + if (av_name.mIsDummy) + {
+ S32 separator_index = mName.rfind(" ");
+ std::string name = mName.substr(0, separator_index);
+ ++separator_index;
+ std::string conference_word = mName.substr(separator_index, mName.length());
+
+ // additional check that session name is what we expected
+ if ("Conference" == conference_word)
+ {
+ LLStringUtil::format_map_t args;
+ args["[AGENT_NAME]"] = name;
+ LLTrans::findString(mName, "conference-title-incoming", args);
+ }
+ } + else + { + LLStringUtil::format_map_t args; + args["[AGENT_NAME]"] = av_name.getCompleteName(); + LLTrans::findString(mName, "conference-title-incoming", args); + } } void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction) @@ -2170,7 +2188,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response) LLAvatarName av_name; if (LLAvatarNameCache::get(caller_id, &av_name)) { - correct_session_name = av_name.mDisplayName + " (" + av_name.mUsername + ")"; + correct_session_name = av_name.getCompleteName(); correct_session_name.append(ADHOC_NAME_SUFFIX); } } diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 52ce932241..8d9d7298f8 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -49,18 +49,421 @@ #include "llnotifications.h" #include "llwindow.h" #include "llviewerwindow.h" +#include "llprogressview.h" #if LL_LINUX || LL_SOLARIS #include "lltrans.h" #endif #include "llsecapi.h" #include "llstartup.h" #include "llmachineid.h" +#include "llupdaterservice.h" +#include "llevents.h" +#include "llnotificationsutil.h" +#include "llappviewer.h" + +#include <boost/scoped_ptr.hpp> +#include <sstream> + +class LLLoginInstance::Disposable { +public: + virtual ~Disposable() {} +}; + +namespace { + class MandatoryUpdateMachine: + public LLLoginInstance::Disposable + { + public: + MandatoryUpdateMachine(LLLoginInstance & loginInstance, LLUpdaterService & updaterService); + + void start(void); + + private: + class State; + class CheckingForUpdate; + class Error; + class ReadyToInstall; + class StartingUpdaterService; + class WaitingForDownload; + + LLLoginInstance & mLoginInstance; + boost::scoped_ptr<State> mState; + LLUpdaterService & mUpdaterService; + + void setCurrentState(State * newState); + }; + + + class MandatoryUpdateMachine::State { + public: + virtual ~State() {} + virtual void enter(void) {} + virtual void exit(void) {} + }; + + + class MandatoryUpdateMachine::CheckingForUpdate: + public MandatoryUpdateMachine::State + { + public: + CheckingForUpdate(MandatoryUpdateMachine & machine); + + virtual void enter(void); + virtual void exit(void); + + private: + LLTempBoundListener mConnection; + MandatoryUpdateMachine & mMachine; + LLProgressView * mProgressView; + + bool onEvent(LLSD const & event); + }; + + + class MandatoryUpdateMachine::Error: + public MandatoryUpdateMachine::State + { + public: + Error(MandatoryUpdateMachine & machine); + + virtual void enter(void); + virtual void exit(void); + void onButtonClicked(const LLSD &, const LLSD &); + + private: + MandatoryUpdateMachine & mMachine; + }; + + + class MandatoryUpdateMachine::ReadyToInstall: + public MandatoryUpdateMachine::State + { + public: + ReadyToInstall(MandatoryUpdateMachine & machine); + + virtual void enter(void); + virtual void exit(void); + + private: + MandatoryUpdateMachine & mMachine; + }; + + + class MandatoryUpdateMachine::StartingUpdaterService: + public MandatoryUpdateMachine::State + { + public: + StartingUpdaterService(MandatoryUpdateMachine & machine); + + virtual void enter(void); + virtual void exit(void); + void onButtonClicked(const LLSD & uiform, const LLSD & result); + private: + MandatoryUpdateMachine & mMachine; + }; + + + class MandatoryUpdateMachine::WaitingForDownload: + public MandatoryUpdateMachine::State + { + public: + WaitingForDownload(MandatoryUpdateMachine & machine); + + virtual void enter(void); + virtual void exit(void); + + private: + LLTempBoundListener mConnection; + MandatoryUpdateMachine & mMachine; + LLProgressView * mProgressView; + + bool onEvent(LLSD const & event); + }; +} static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback"; static const char * const TOS_LISTENER_NAME = "lllogininstance_tos"; std::string construct_start_string(); + + +// MandatoryUpdateMachine +//----------------------------------------------------------------------------- + + +MandatoryUpdateMachine::MandatoryUpdateMachine(LLLoginInstance & loginInstance, LLUpdaterService & updaterService): + mLoginInstance(loginInstance), + mUpdaterService(updaterService) +{ + ; // No op. +} + + +void MandatoryUpdateMachine::start(void) +{ + llinfos << "starting manditory update machine" << llendl; + + if(mUpdaterService.isChecking()) { + switch(mUpdaterService.getState()) { + case LLUpdaterService::UP_TO_DATE: + mUpdaterService.stopChecking(); + mUpdaterService.startChecking(); + // Fall through. + case LLUpdaterService::INITIAL: + case LLUpdaterService::CHECKING_FOR_UPDATE: + setCurrentState(new CheckingForUpdate(*this)); + break; + case LLUpdaterService::DOWNLOADING: + setCurrentState(new WaitingForDownload(*this)); + break; + case LLUpdaterService::TERMINAL: + if(LLUpdaterService::updateReadyToInstall()) { + setCurrentState(new ReadyToInstall(*this)); + } else { + setCurrentState(new Error(*this)); + } + break; + case LLUpdaterService::FAILURE: + setCurrentState(new Error(*this)); + break; + default: + llassert(!"unpossible case"); + break; + } + } else { + setCurrentState(new StartingUpdaterService(*this)); + } +} + + +void MandatoryUpdateMachine::setCurrentState(State * newStatePointer) +{ + { + boost::scoped_ptr<State> newState(newStatePointer); + if(mState != 0) mState->exit(); + mState.swap(newState); + + // Old state will be deleted on exit from this block before the new state + // is entered. + } + if(mState != 0) mState->enter(); +} + + + +// MandatoryUpdateMachine::CheckingForUpdate +//----------------------------------------------------------------------------- + + +MandatoryUpdateMachine::CheckingForUpdate::CheckingForUpdate(MandatoryUpdateMachine & machine): + mMachine(machine) +{ + ; // No op. +} + + +void MandatoryUpdateMachine::CheckingForUpdate::enter(void) +{ + llinfos << "entering checking for update" << llendl; + + mProgressView = gViewerWindow->getProgressView(); + mProgressView->setMessage("Looking for update..."); + mProgressView->setText("There is a required update for your Second Life installation."); + mProgressView->setPercent(0); + mProgressView->setVisible(true); + mConnection = LLEventPumps::instance().obtain(LLUpdaterService::pumpName()). + listen("MandatoryUpdateMachine::CheckingForUpdate", boost::bind(&MandatoryUpdateMachine::CheckingForUpdate::onEvent, this, _1)); +} + + +void MandatoryUpdateMachine::CheckingForUpdate::exit(void) +{ +} + + +bool MandatoryUpdateMachine::CheckingForUpdate::onEvent(LLSD const & event) +{ + if(event["type"].asInteger() == LLUpdaterService::STATE_CHANGE) { + switch(event["state"].asInteger()) { + case LLUpdaterService::DOWNLOADING: + mMachine.setCurrentState(new WaitingForDownload(mMachine)); + break; + case LLUpdaterService::UP_TO_DATE: + case LLUpdaterService::TERMINAL: + case LLUpdaterService::FAILURE: + mProgressView->setVisible(false); + mMachine.setCurrentState(new Error(mMachine)); + break; + case LLUpdaterService::INSTALLING: + llassert(!"can't possibly be installing"); + break; + default: + break; + } + } else { + ; // Ignore. + } + + return false; +} + + + +// MandatoryUpdateMachine::Error +//----------------------------------------------------------------------------- + + +MandatoryUpdateMachine::Error::Error(MandatoryUpdateMachine & machine): + mMachine(machine) +{ + ; // No op. +} + + +void MandatoryUpdateMachine::Error::enter(void) +{ + llinfos << "entering error" << llendl; + LLNotificationsUtil::add("FailedUpdateInstall", LLSD(), LLSD(), boost::bind(&MandatoryUpdateMachine::Error::onButtonClicked, this, _1, _2)); +} + + +void MandatoryUpdateMachine::Error::exit(void) +{ + LLAppViewer::instance()->forceQuit(); +} + + +void MandatoryUpdateMachine::Error::onButtonClicked(const LLSD &, const LLSD &) +{ + mMachine.setCurrentState(0); +} + + + +// MandatoryUpdateMachine::ReadyToInstall +//----------------------------------------------------------------------------- + + +MandatoryUpdateMachine::ReadyToInstall::ReadyToInstall(MandatoryUpdateMachine & machine): + mMachine(machine) +{ + ; // No op. +} + + +void MandatoryUpdateMachine::ReadyToInstall::enter(void) +{ + llinfos << "entering ready to install" << llendl; + // Open update ready dialog. +} + + +void MandatoryUpdateMachine::ReadyToInstall::exit(void) +{ + // Restart viewer. +} + + + +// MandatoryUpdateMachine::StartingUpdaterService +//----------------------------------------------------------------------------- + + +MandatoryUpdateMachine::StartingUpdaterService::StartingUpdaterService(MandatoryUpdateMachine & machine): + mMachine(machine) +{ + ; // No op. +} + + +void MandatoryUpdateMachine::StartingUpdaterService::enter(void) +{ + llinfos << "entering start update service" << llendl; + LLNotificationsUtil::add("UpdaterServiceNotRunning", LLSD(), LLSD(), boost::bind(&MandatoryUpdateMachine::StartingUpdaterService::onButtonClicked, this, _1, _2)); +} + + +void MandatoryUpdateMachine::StartingUpdaterService::exit(void) +{ + ; // No op. +} + + +void MandatoryUpdateMachine::StartingUpdaterService::onButtonClicked(const LLSD & uiform, const LLSD & result) +{ + if(result["OK_okcancelbuttons"].asBoolean()) { + mMachine.mUpdaterService.startChecking(false); + mMachine.setCurrentState(new CheckingForUpdate(mMachine)); + } else { + LLAppViewer::instance()->forceQuit(); + } +} + + + +// MandatoryUpdateMachine::WaitingForDownload +//----------------------------------------------------------------------------- + + +MandatoryUpdateMachine::WaitingForDownload::WaitingForDownload(MandatoryUpdateMachine & machine): + mMachine(machine), + mProgressView(0) +{ + ; // No op. +} + + +void MandatoryUpdateMachine::WaitingForDownload::enter(void) +{ + llinfos << "entering waiting for download" << llendl; + mProgressView = gViewerWindow->getProgressView(); + mProgressView->setMessage("Downloading update..."); + std::ostringstream stream; + stream << "There is a required update for your Second Life installation." << std::endl << + "Version " << mMachine.mUpdaterService.updatedVersion(); + mProgressView->setText(stream.str()); + mProgressView->setPercent(0); + mProgressView->setVisible(true); + mConnection = LLEventPumps::instance().obtain(LLUpdaterService::pumpName()). + listen("MandatoryUpdateMachine::CheckingForUpdate", boost::bind(&MandatoryUpdateMachine::WaitingForDownload::onEvent, this, _1)); +} + + +void MandatoryUpdateMachine::WaitingForDownload::exit(void) +{ + mProgressView->setVisible(false); +} + + +bool MandatoryUpdateMachine::WaitingForDownload::onEvent(LLSD const & event) +{ + switch(event["type"].asInteger()) { + case LLUpdaterService::DOWNLOAD_COMPLETE: + mMachine.setCurrentState(new ReadyToInstall(mMachine)); + break; + case LLUpdaterService::DOWNLOAD_ERROR: + mMachine.setCurrentState(new Error(mMachine)); + break; + case LLUpdaterService::PROGRESS: { + double downloadSize = event["download_size"].asReal(); + double bytesDownloaded = event["bytes_downloaded"].asReal(); + mProgressView->setPercent(100. * bytesDownloaded / downloadSize); + break; + } + default: + break; + } + + return false; +} + + + +// LLLoginInstance +//----------------------------------------------------------------------------- + + LLLoginInstance::LLLoginInstance() : mLoginModule(new LLLogin()), mNotifications(NULL), @@ -69,7 +472,8 @@ LLLoginInstance::LLLoginInstance() : mSkipOptionalUpdate(false), mAttemptComplete(false), mTransferRate(0.0f), - mDispatcher("LLLoginInstance", "change") + mDispatcher("LLLoginInstance", "change"), + mUpdaterService(0) { mLoginModule->getEventPump().listen("lllogininstance", boost::bind(&LLLoginInstance::handleLoginEvent, this, _1)); @@ -353,6 +757,15 @@ bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg) { + if(mandatory) + { + gViewerWindow->setShowProgress(false); + MandatoryUpdateMachine * machine = new MandatoryUpdateMachine(*this, *mUpdaterService); + mUpdateStateMachine.reset(machine); + machine->start(); + return; + } + // store off config state, as we might quit soon gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); LLUIColorTable::instance().saveUserSettings(); diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index 159e05046c..b872d7d1b1 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -34,12 +34,15 @@ class LLLogin; class LLEventStream; class LLNotificationsInterface; +class LLUpdaterService; // This class hosts the login module and is used to // negotiate user authentication attempts. class LLLoginInstance : public LLSingleton<LLLoginInstance> { public: + class Disposable; + LLLoginInstance(); ~LLLoginInstance(); @@ -75,6 +78,7 @@ public: typedef boost::function<void()> UpdaterLauncherCallback; void setUpdaterLauncher(const UpdaterLauncherCallback& ulc) { mUpdaterLauncher = ulc; } + void setUpdaterService(LLUpdaterService * updaterService) { mUpdaterService = updaterService; } private: void constructAuthParams(LLPointer<LLCredential> user_credentials); void updateApp(bool mandatory, const std::string& message); @@ -104,6 +108,8 @@ private: int mLastExecEvent; UpdaterLauncherCallback mUpdaterLauncher; LLEventDispatcher mDispatcher; + LLUpdaterService * mUpdaterService; + boost::scoped_ptr<Disposable> mUpdateStateMachine; }; #endif diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index dfbbaa0941..6f92dd6445 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -121,7 +121,7 @@ protected: if (!toast) return; LL_DEBUGS("NearbyChat") << "Pooling toast" << llendl; toast->setVisible(FALSE); - toast->stopFading(); + toast->stopTimer(); toast->setIsHidden(true); // Nearby chat toasts that are hidden, not destroyed. They are collected to the toast pool, so that @@ -165,20 +165,11 @@ public: : LLToast(p), mNearbyChatScreenChannelp(nc_channelp) { - updateTransparency(); - setMouseEnterCallback(boost::bind(&LLNearbyChatToast::updateTransparency, this)); - setMouseLeaveCallback(boost::bind(&LLNearbyChatToast::updateTransparency, this)); } /*virtual*/ void onClose(bool app_quitting); - /*virtual*/ void setBackgroundOpaque(BOOL b); - -protected: - /*virtual*/ void setTransparentState(bool transparent); private: - void updateTransparency(); - LLNearbyChatScreenChannel* mNearbyChatScreenChannelp; }; @@ -305,7 +296,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification) { panel->addMessage(notification); toast->reshapeToPanel(); - toast->startFading(); + toast->startTimer(); arrangeToasts(); return; @@ -350,7 +341,7 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification) panel->init(notification); toast->reshapeToPanel(); - toast->startFading(); + toast->startTimer(); m_active_toasts.push_back(toast->getHandle()); @@ -606,34 +597,4 @@ void LLNearbyChatToast::onClose(bool app_quitting) mNearbyChatScreenChannelp->onToastDestroyed(this, app_quitting); } -// virtual -void LLNearbyChatToast::setBackgroundOpaque(BOOL b) -{ - // We don't want background changes: transparency is handled differently. - LLToast::setBackgroundOpaque(TRUE); -} - -// virtual -void LLNearbyChatToast::setTransparentState(bool transparent) -{ - LLToast::setTransparentState(transparent); - updateTransparency(); -} - -void LLNearbyChatToast::updateTransparency() -{ - ETypeTransparency transparency_type; - - if (isHovered()) - { - transparency_type = TT_ACTIVE; - } - else - { - transparency_type = getTransparentState() ? TT_FADING : TT_INACTIVE; - } - - LLFloater::updateTransparency(transparency_type); -} - // EOF diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 57180f63b5..1249d5d856 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -34,6 +34,7 @@ #include "llcombobox.h" #include "lldateutil.h" // ageFromDate() #include "llimview.h" +#include "llmenubutton.h" #include "llnotificationsutil.h" #include "lltexteditor.h" #include "lltexturectrl.h" @@ -479,7 +480,6 @@ BOOL LLPanelAvatarProfile::postBuild() childSetCommitCallback("im",(boost::bind(&LLPanelAvatarProfile::onIMButtonClick,this)),NULL); childSetCommitCallback("call",(boost::bind(&LLPanelAvatarProfile::onCallButtonClick,this)),NULL); childSetCommitCallback("teleport",(boost::bind(&LLPanelAvatarProfile::onTeleportButtonClick,this)),NULL); - childSetCommitCallback("overflow_btn", boost::bind(&LLPanelAvatarProfile::onOverflowButtonClicked, this), NULL); childSetCommitCallback("share",(boost::bind(&LLPanelAvatarProfile::onShareButtonClick,this)),NULL); childSetCommitCallback("show_on_map_btn", (boost::bind( &LLPanelAvatarProfile::onMapButtonClick, this)), NULL); @@ -500,7 +500,8 @@ BOOL LLPanelAvatarProfile::postBuild() enable.add("Profile.EnableBlock", boost::bind(&LLPanelAvatarProfile::enableBlock, this)); enable.add("Profile.EnableUnblock", boost::bind(&LLPanelAvatarProfile::enableUnblock, this)); - mProfileMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_profile_overflow.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + LLToggleableMenu* profile_menu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_profile_overflow.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + getChild<LLMenuButton>("overflow_btn")->setMenu(profile_menu, LLMenuButton::MP_TOP_RIGHT); LLVoiceClient::getInstance()->addObserver((LLVoiceClientStatusObserver*)this); @@ -752,23 +753,6 @@ void LLPanelAvatarProfile::onShareButtonClick() //*TODO not implemented } -void LLPanelAvatarProfile::onOverflowButtonClicked() -{ - if (!mProfileMenu->toggleVisibility()) - return; - - LLView* btn = getChild<LLView>("overflow_btn"); - - if (mProfileMenu->getButtonRect().isEmpty()) - { - mProfileMenu->setButtonRect(btn); - } - mProfileMenu->updateParent(LLMenuGL::sMenuContainer); - - LLRect rect = btn->getRect(); - LLMenuGL::showPopup(this, mProfileMenu, rect.mRight, rect.mTop); -} - LLPanelAvatarProfile::~LLPanelAvatarProfile() { if(getAvatarId().notNull()) diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index 11c7716322..71d9d0a95a 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -34,7 +34,6 @@ class LLComboBox; class LLLineEditor; -class LLToggleableMenu; enum EOnlineStatus { @@ -207,14 +206,11 @@ protected: void onCallButtonClick(); void onTeleportButtonClick(); void onShareButtonClick(); - void onOverflowButtonClicked(); private: typedef std::map< std::string,LLUUID> group_map_t; group_map_t mGroups; - - LLToggleableMenu* mProfileMenu; }; /** diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index cf567fb208..302e4fa19d 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -73,7 +73,6 @@ #endif // LL_WINDOWS #include "llsdserialize.h" -#define USE_VIEWER_AUTH 0 const S32 BLACK_BORDER_HEIGHT = 160; const S32 MAX_PASSWORD = 16; @@ -189,10 +188,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, buildFromFile( "panel_login.xml"); -#if USE_VIEWER_AUTH - //leave room for the login menu bar - setRect(LLRect(0, rect.getHeight()-18, rect.getWidth(), 0)); -#endif // Legacy login web page is hidden under the menu bar. // Adjust reg-in-client web browser widget to not be hidden. if (gSavedSettings.getBOOL("RegInClient")) @@ -204,7 +199,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, reshape(rect.getWidth(), rect.getHeight()); } -#if !USE_VIEWER_AUTH getChild<LLLineEditor>("password_edit")->setKeystrokeCallback(onPassKey, this); // change z sort of clickable text to be behind buttons @@ -247,7 +241,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, LLTextBox* need_help_text = getChild<LLTextBox>("login_help"); need_help_text->setClickedCallback(onClickHelp, NULL); -#endif // get the web browser control LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html"); @@ -274,15 +267,9 @@ void LLPanelLogin::reshapeBrowser() LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html"); LLRect rect = gViewerWindow->getWindowRectScaled(); LLRect html_rect; -#if USE_VIEWER_AUTH - html_rect.setCenterAndSize( - rect.getCenterX() - 2, rect.getCenterY(), - rect.getWidth() + 6, rect.getHeight()); -#else html_rect.setCenterAndSize( rect.getCenterX() - 2, rect.getCenterY() + 40, rect.getWidth() + 6, rect.getHeight() - 78 ); -#endif web_browser->setRect( html_rect ); web_browser->reshape( html_rect.getWidth(), html_rect.getHeight(), TRUE ); reshape( rect.getWidth(), rect.getHeight(), 1 ); @@ -305,7 +292,6 @@ void LLPanelLogin::setSiteIsAlive( bool alive ) else // the site is not available (missing page, server down, other badness) { -#if !USE_VIEWER_AUTH if ( web_browser ) { // hide browser control (revealing default one) @@ -314,16 +300,6 @@ void LLPanelLogin::setSiteIsAlive( bool alive ) // mark as unavailable mHtmlAvailable = FALSE; } -#else - - if ( web_browser ) - { - web_browser->navigateToLocalPage( "loading-error" , "index.html" ); - - // mark as available - mHtmlAvailable = TRUE; - } -#endif } } @@ -363,7 +339,6 @@ void LLPanelLogin::draw() if ( mHtmlAvailable ) { -#if !USE_VIEWER_AUTH if (getChild<LLView>("login_widgets")->getVisible()) { // draw a background box in black @@ -372,7 +347,6 @@ void LLPanelLogin::draw() // just the blue background to the native client UI mLogoImage->draw(0, -264, width + 8, mLogoImage->getHeight()); } -#endif } else { @@ -418,12 +392,6 @@ void LLPanelLogin::setFocus(BOOL b) // static void LLPanelLogin::giveFocus() { -#if USE_VIEWER_AUTH - if (sInstance) - { - sInstance->setFocus(TRUE); - } -#else if( sInstance ) { // Grab focus and move cursor to first blank input field @@ -452,17 +420,18 @@ void LLPanelLogin::giveFocus() edit->selectAll(); } } -#endif } // static void LLPanelLogin::showLoginWidgets() { + // *NOTE: Mani - This may or may not be obselete code. + // It seems to be part of the defunct? reg-in-client project. sInstance->getChildView("login_widgets")->setVisible( true); LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html"); sInstance->reshapeBrowser(); // *TODO: Append all the usual login parameters, like first_login=Y etc. - std::string splash_screen_url = sInstance->getString("real_url"); + std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage(); web_browser->navigateTo( splash_screen_url, "text/html" ); LLUICtrl* username_edit = sInstance->getChild<LLUICtrl>("username_edit"); username_edit->setFocus(TRUE); @@ -832,73 +801,6 @@ void LLPanelLogin::loadLoginPage() curl_free(curl_grid); gViewerWindow->setMenuBackgroundColor(false, !LLGridManager::getInstance()->isInProductionGrid()); gLoginMenuBarView->setBackgroundColor(gMenuBarView->getBackgroundColor()); - - -#if USE_VIEWER_AUTH - LLURLSimString::sInstance.parse(); - - std::string location; - std::string region; - std::string password; - - if (LLURLSimString::parse()) - { - std::ostringstream oRegionStr; - location = "specify"; - oRegionStr << LLURLSimString::sInstance.mSimName << "/" << LLURLSimString::sInstance.mX << "/" - << LLURLSimString::sInstance.mY << "/" - << LLURLSimString::sInstance.mZ; - region = oRegionStr.str(); - } - else - { - location = gSavedSettings.getString("LoginLocation"); - } - - std::string username; - - if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3) - { - LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo"); - username = cmd_line_login[0].asString() + " " + cmd_line_login[1]; - password = cmd_line_login[2].asString(); - } - - - char* curl_region = curl_escape(region.c_str(), 0); - - oStr <<"username=" << username << - "&location=" << location << "®ion=" << curl_region; - - curl_free(curl_region); - - if (!password.empty()) - { - oStr << "&password=" << password; - } - else if (!(password = load_password_from_disk()).empty()) - { - oStr << "&password=$1$" << password; - } - if (gAutoLogin) - { - oStr << "&auto_login=TRUE"; - } - if (gSavedSettings.getBOOL("ShowStartLocation")) - { - oStr << "&show_start_location=TRUE"; - } - if (gSavedSettings.getBOOL("RememberPassword")) - { - oStr << "&remember_password=TRUE"; - } -#ifndef LL_RELEASE_FOR_DOWNLOAD - oStr << "&show_grid=TRUE"; -#else - if (gSavedSettings.getBOOL("ForceShowGrid")) - oStr << "&show_grid=TRUE"; -#endif -#endif LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html"); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 9e9bc5fc1a..54198d6aa4 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -231,7 +231,7 @@ public: virtual void setActive(bool) {} protected: - void updateList() + void update() { mCallback(); } @@ -239,6 +239,30 @@ protected: callback_t mCallback; }; +/** + * Update buttons on changes in our friend relations (STORM-557). + */ +class LLButtonsUpdater : public LLPanelPeople::Updater, public LLFriendObserver +{ +public: + LLButtonsUpdater(callback_t cb) + : LLPanelPeople::Updater(cb) + { + LLAvatarTracker::instance().addObserver(this); + } + + ~LLButtonsUpdater() + { + LLAvatarTracker::instance().removeObserver(this); + } + + /*virtual*/ void changed(U32 mask) + { + (void) mask; + update(); + } +}; + class LLAvatarListUpdater : public LLPanelPeople::Updater, public LLEventTimer { public: @@ -306,7 +330,7 @@ public: if (mMask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE)) { - updateList(); + update(); } // Stop updates. @@ -421,7 +445,7 @@ public: if (val) { // update immediately and start regular updates - updateList(); + update(); mEventTimer.start(); } else @@ -433,7 +457,7 @@ public: /*virtual*/ BOOL tick() { - updateList(); + update(); return FALSE; } private: @@ -450,7 +474,7 @@ public: LLRecentListUpdater(callback_t cb) : LLAvatarListUpdater(cb, 0) { - LLRecentPeople::instance().setChangedCallback(boost::bind(&LLRecentListUpdater::updateList, this)); + LLRecentPeople::instance().setChangedCallback(boost::bind(&LLRecentListUpdater::update, this)); } }; @@ -475,11 +499,13 @@ LLPanelPeople::LLPanelPeople() mFriendListUpdater = new LLFriendListUpdater(boost::bind(&LLPanelPeople::updateFriendList, this)); mNearbyListUpdater = new LLNearbyListUpdater(boost::bind(&LLPanelPeople::updateNearbyList, this)); mRecentListUpdater = new LLRecentListUpdater(boost::bind(&LLPanelPeople::updateRecentList, this)); + mButtonsUpdater = new LLButtonsUpdater(boost::bind(&LLPanelPeople::updateButtons, this)); mCommitCallbackRegistrar.add("People.addFriend", boost::bind(&LLPanelPeople::onAddFriendButtonClicked, this)); } LLPanelPeople::~LLPanelPeople() { + delete mButtonsUpdater; delete mNearbyListUpdater; delete mFriendListUpdater; delete mRecentListUpdater; diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 4412aed062..b496bb3779 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -152,6 +152,7 @@ private: Updater* mFriendListUpdater; Updater* mNearbyListUpdater; Updater* mRecentListUpdater; + Updater* mButtonsUpdater; LLMenuButton* mNearbyGearButton; LLMenuButton* mFriendsGearButton; diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index f0e60386b6..400a3dbbb3 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -39,6 +39,7 @@ #include "llfiltereditor.h" #include "llfirstuse.h" #include "llfloaterreg.h" +#include "llmenubutton.h" #include "llnotificationsutil.h" #include "lltabcontainer.h" #include "lltexteditor.h" @@ -282,8 +283,8 @@ BOOL LLPanelPlaces::postBuild() mCloseBtn = getChild<LLButton>("close_btn"); mCloseBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this)); - mOverflowBtn = getChild<LLButton>("overflow_btn"); - mOverflowBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onOverflowButtonClicked, this)); + mOverflowBtn = getChild<LLMenuButton>("overflow_btn"); + mOverflowBtn->setMouseDownCallback(boost::bind(&LLPanelPlaces::onOverflowButtonClicked, this)); mPlaceInfoBtn = getChild<LLButton>("profile_btn"); mPlaceInfoBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onProfileButtonClicked, this)); @@ -330,8 +331,7 @@ BOOL LLPanelPlaces::postBuild() mPlaceProfileBackBtn = mPlaceProfile->getChild<LLButton>("back_btn"); mPlaceProfileBackBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this)); - mLandmarkInfoBackBtn = mLandmarkInfo->getChild<LLButton>("back_btn"); - mLandmarkInfoBackBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this)); + mLandmarkInfo->getChild<LLButton>("back_btn")->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this)); LLLineEditor* title_editor = mLandmarkInfo->getChild<LLLineEditor>("title_editor"); title_editor->setKeystrokeCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this), NULL); @@ -384,12 +384,7 @@ void LLPanelPlaces::onOpen(const LLSD& key) mLandmarkInfo->displayParcelInfo(LLUUID(), mPosGlobal); - // Disabling "Save", "Close" and "Back" buttons to prevent closing "Create Landmark" - // panel before created landmark is loaded. - // These buttons will be enabled when created landmark is added to inventory. mSaveBtn->setEnabled(FALSE); - mCloseBtn->setEnabled(FALSE); - mLandmarkInfoBackBtn->setEnabled(FALSE); } else if (mPlaceInfoType == LANDMARK_INFO_TYPE) { @@ -497,8 +492,6 @@ void LLPanelPlaces::setItem(LLInventoryItem* item) mEditBtn->setEnabled(is_landmark_editable); mSaveBtn->setEnabled(is_landmark_editable); - mCloseBtn->setEnabled(TRUE); - mLandmarkInfoBackBtn->setEnabled(TRUE); if (is_landmark_editable) { @@ -783,16 +776,7 @@ void LLPanelPlaces::onOverflowButtonClicked() return; } - if (!menu->toggleVisibility()) - return; - - if (menu->getButtonRect().isEmpty()) - { - menu->setButtonRect(mOverflowBtn); - } - menu->updateParent(LLMenuGL::sMenuContainer); - LLRect rect = mOverflowBtn->getRect(); - LLMenuGL::showPopup(this, menu, rect.mRight, rect.mTop); + mOverflowBtn->setMenu(menu, LLMenuButton::MP_TOP_RIGHT); } void LLPanelPlaces::onProfileButtonClicked() @@ -1137,13 +1121,6 @@ void LLPanelPlaces::updateVerbs() { mTeleportBtn->setEnabled(have_3d_pos); } - - // Do not enable landmark info Back button when we are waiting - // for newly created landmark to load. - if (!is_create_landmark_visible) - { - mLandmarkInfoBackBtn->setEnabled(TRUE); - } } else { diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index c3b2ab806f..b335f88a48 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -47,6 +47,7 @@ class LLPlacesParcelObserver; class LLRemoteParcelInfoObserver; class LLTabContainer; class LLToggleableMenu; +class LLMenuButton; typedef std::pair<LLUUID, std::string> folder_pair_t; @@ -116,14 +117,13 @@ private: LLToggleableMenu* mLandmarkMenu; LLButton* mPlaceProfileBackBtn; - LLButton* mLandmarkInfoBackBtn; LLButton* mTeleportBtn; LLButton* mShowOnMapBtn; LLButton* mEditBtn; LLButton* mSaveBtn; LLButton* mCancelBtn; LLButton* mCloseBtn; - LLButton* mOverflowBtn; + LLMenuButton* mOverflowBtn; LLButton* mPlaceInfoBtn; LLPlacesInventoryObserver* mInventoryObserver; diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index fff8ccb912..9b35e78134 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -181,9 +181,11 @@ void LLTeleportHistoryFlatItem::setRegionName(const std::string& name) void LLTeleportHistoryFlatItem::updateTitle() { + static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", LLColor4U(255, 255, 255)); + LLTextUtil::textboxSetHighlightedVal( mTitle, - LLStyle::Params(), + LLStyle::Params().color(sFgColor), mRegionName, mHighlight); } diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index e9504cbba0..250dfc5713 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -133,13 +133,13 @@ void LLProgressView::setVisible(BOOL visible) mFadeTimer.start(); } // showing progress view - else if (!getVisible() && visible) + else if (visible && (!getVisible() || mFadeTimer.getStarted())) { setFocus(TRUE); mFadeTimer.stop(); mProgressTimer.start(); LLPanel::setVisible(TRUE); - } + } } diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 61f4897ed0..1645334b38 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -253,8 +253,8 @@ void LLScreenChannel::addToast(const LLToast::Params& p) if(mControlHovering) { new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2)); - new_toast_elem.toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopFadingToast, this, new_toast_elem.toast)); - new_toast_elem.toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startFadingToast, this, new_toast_elem.toast)); + new_toast_elem.toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopToastTimer, this, new_toast_elem.toast)); + new_toast_elem.toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startToastTimer, this, new_toast_elem.toast)); } if(show_toast) @@ -369,7 +369,7 @@ void LLScreenChannel::loadStoredToastsToChannel() for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it) { (*it).toast->setIsHidden(false); - (*it).toast->startFading(); + (*it).toast->startTimer(); mToastList.push_back((*it)); } @@ -394,7 +394,7 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id) } toast->setIsHidden(false); - toast->startFading(); + toast->startTimer(); mToastList.push_back((*it)); redrawToasts(); @@ -477,7 +477,7 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel) toast->removeChild(old_panel); delete old_panel; toast->insertPanel(panel); - toast->startFading(); + toast->startTimer(); redrawToasts(); } } @@ -588,7 +588,7 @@ void LLScreenChannel::showToastsBottom() mHiddenToastsNum = 0; for(; it != mToastList.rend(); it++) { - (*it).toast->stopFading(); + (*it).toast->stopTimer(); (*it).toast->setVisible(FALSE); mHiddenToastsNum++; } @@ -697,15 +697,15 @@ void LLScreenChannel::closeStartUpToast() } } -void LLNotificationsUI::LLScreenChannel::stopFadingToast(LLToast* toast) +void LLNotificationsUI::LLScreenChannel::stopToastTimer(LLToast* toast) { if (!toast || toast != mHoveredToast) return; // Pause fade timer of the hovered toast. - toast->stopFading(); + toast->stopTimer(); } -void LLNotificationsUI::LLScreenChannel::startFadingToast(LLToast* toast) +void LLNotificationsUI::LLScreenChannel::startToastTimer(LLToast* toast) { if (!toast || toast == mHoveredToast) { @@ -713,7 +713,7 @@ void LLNotificationsUI::LLScreenChannel::startFadingToast(LLToast* toast) } // Reset its fade timer. - toast->startFading(); + toast->startTimer(); } //-------------------------------------------------------------------------- diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index a1fdd6e32c..c9e511fb09 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -194,10 +194,10 @@ public: /** Stop fading given toast */ - virtual void stopFadingToast(LLToast* toast); + virtual void stopToastTimer(LLToast* toast); /** Start fading given toast */ - virtual void startFadingToast(LLToast* toast); + virtual void startToastTimer(LLToast* toast); // get StartUp Toast's state static bool getStartUpToastShown() { return mWasStartUpToastShown; } diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 1999f14828..b316171604 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -183,12 +183,15 @@ void LLSidepanelAppearance::onOpen(const LLSD& key) void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility) { - updateToVisibility(new_visibility); + LLSD visibility; + visibility["visible"] = new_visibility.asBoolean(); + visibility["reset_accordion"] = true; + updateToVisibility(visibility); } void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility) { - if (new_visibility.asBoolean()) + if (new_visibility["visible"].asBoolean()) { bool is_outfit_edit_visible = mOutfitEdit && mOutfitEdit->getVisible(); bool is_wearable_edit_visible = mEditWearable && mEditWearable->getVisible(); @@ -209,7 +212,7 @@ void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility) } } - if (is_outfit_edit_visible) + if (is_outfit_edit_visible && new_visibility["reset_accordion"].asBoolean()) { mOutfitEdit->resetAccordionState(); } diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 3f8aeaf400..9c8557c017 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -301,7 +301,11 @@ static void on_minimize(LLSidepanelAppearance* panel, LLSD minimized) { if (!panel) return; bool visible = !minimized.asBoolean(); - panel->updateToVisibility(LLSD(visible)); + LLSD visibility; + visibility["visible"] = visible; + // Do not reset accordion state on minimize (STORM-375) + visibility["reset_accordion"] = false; + panel->updateToVisibility(visibility); } void LLSideTrayTab::undock(LLFloater* floater_tab) diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 8916469e67..fd5582d6f7 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -113,7 +113,7 @@ LLToast::LLToast(const LLToast::Params& p) mHideBtnPressed(false), mIsTip(p.is_tip), mWrapperPanel(NULL), - mIsTransparent(false) + mIsFading(false) { mTimer.reset(new LLToastLifeTimer(this, p.lifetime_secs)); @@ -125,6 +125,9 @@ LLToast::LLToast(const LLToast::Params& p) mWrapperPanel->setMouseEnterCallback(boost::bind(&LLToast::onToastMouseEnter, this)); mWrapperPanel->setMouseLeaveCallback(boost::bind(&LLToast::onToastMouseLeave, this)); + setBackgroundOpaque(TRUE); // *TODO: obsolete + updateTransparency(); + if(mPanel) { insertPanel(mPanel); @@ -179,7 +182,7 @@ LLToast::~LLToast() void LLToast::hide() { setVisible(FALSE); - setTransparentState(false); + setFading(false); mTimer->stop(); mIsHidden = true; mOnFadeSignal(this); @@ -190,7 +193,7 @@ void LLToast::onFocusLost() if(mWrapperPanel && !isBackgroundVisible()) { // Lets make wrapper panel behave like a floater - setBackgroundOpaque(FALSE); + updateTransparency(); } } @@ -199,7 +202,7 @@ void LLToast::onFocusReceived() if(mWrapperPanel && !isBackgroundVisible()) { // Lets make wrapper panel behave like a floater - setBackgroundOpaque(TRUE); + updateTransparency(); } } @@ -244,22 +247,24 @@ void LLToast::expire() { if (mCanFade) { - if (mIsTransparent) + if (mIsFading) { + // Fade timer expired. Time to hide. hide(); } else { - setTransparentState(true); + // "Life" time has ended. Time to fade. + setFading(true); mTimer->restart(); } } } -void LLToast::setTransparentState(bool transparent) +void LLToast::setFading(bool transparent) { - setBackgroundOpaque(!transparent); - mIsTransparent = transparent; + mIsFading = transparent; + updateTransparency(); if (transparent) { @@ -275,7 +280,7 @@ F32 LLToast::getTimeLeftToLive() { F32 time_to_live = mTimer->getRemainingTimeF32(); - if (!mIsTransparent) + if (!mIsFading) { time_to_live += mToastFadingTime; } @@ -347,7 +352,6 @@ void LLToast::setVisible(BOOL show) if(show) { - setBackgroundOpaque(TRUE); if(!mTimer->getStarted() && mCanFade) { mTimer->start(); @@ -389,7 +393,7 @@ void LLToast::onToastMouseEnter() { mOnToastHoverSignal(this, MOUSE_ENTER); - setBackgroundOpaque(TRUE); + updateTransparency(); //toasts fading is management by Screen Channel @@ -418,6 +422,8 @@ void LLToast::onToastMouseLeave() { mOnToastHoverSignal(this, MOUSE_LEAVE); + updateTransparency(); + //toasts fading is management by Screen Channel if(mHideBtn && mHideBtn->getEnabled()) @@ -445,20 +451,45 @@ void LLToast::setBackgroundOpaque(BOOL b) } } -void LLNotificationsUI::LLToast::stopFading() +void LLToast::updateTransparency() +{ + ETypeTransparency transparency_type; + + if (mCanFade) + { + // Notification toasts (including IM/chat toasts) change their transparency on hover. + if (isHovered()) + { + transparency_type = TT_ACTIVE; + } + else + { + transparency_type = mIsFading ? TT_FADING : TT_INACTIVE; + } + } + else + { + // Transparency of alert toasts depends on focus. + transparency_type = hasFocus() ? TT_ACTIVE : TT_INACTIVE; + } + + LLFloater::updateTransparency(transparency_type); +} + +void LLNotificationsUI::LLToast::stopTimer() { if(mCanFade) { - setTransparentState(false); + setFading(false); mTimer->stop(); } } -void LLNotificationsUI::LLToast::startFading() +void LLNotificationsUI::LLToast::startTimer() { if(mCanFade) { - setTransparentState(false); + setFading(false); mTimer->start(); } } diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index d23e858c5c..242f786bf2 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -114,11 +114,11 @@ public: //Fading - /** Stop fading timer */ - virtual void stopFading(); + /** Stop lifetime/fading timer */ + virtual void stopTimer(); - /** Start fading timer */ - virtual void startFading(); + /** Start lifetime/fading timer */ + virtual void startTimer(); bool isHovered(); @@ -141,7 +141,7 @@ public: // virtual void setVisible(BOOL show); - virtual void setBackgroundOpaque(BOOL b); + /*virtual*/ void setBackgroundOpaque(BOOL b); // virtual void hide(); @@ -198,9 +198,8 @@ public: LLHandle<LLToast> getHandle() { mHandle.bind(this); return mHandle; } - bool getTransparentState() const { return mIsTransparent; } - virtual void setTransparentState(bool transparent); - +protected: + void updateTransparency(); private: @@ -210,6 +209,8 @@ private: void expire(); + void setFading(bool fading); + LLUUID mNotificationID; LLUUID mSessionID; LLNotificationPtr mNotification; @@ -234,7 +235,7 @@ private: bool mHideBtnPressed; bool mIsHidden; // this flag is TRUE when a toast has faded or was hidden with (x) button (EXT-1849) bool mIsTip; - bool mIsTransparent; + bool mIsFading; commit_signal_t mToastMouseEnterSignal; commit_signal_t mToastMouseLeaveSignal; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 622d09c600..2c75551285 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -504,7 +504,7 @@ bool toggle_show_object_render_cost(const LLSD& newvalue) void toggle_updater_service_active(LLControlVariable* control, const LLSD& new_value) { - if(new_value.asBoolean()) + if(new_value.asInteger()) { LLUpdaterService().startChecking(); } @@ -661,7 +661,7 @@ void settings_setup_listeners() gSavedSettings.getControl("ShowNavbarFavoritesPanel")->getSignal()->connect(boost::bind(&toggle_show_favorites_panel, _2)); gSavedSettings.getControl("ShowMiniLocationPanel")->getSignal()->connect(boost::bind(&toggle_show_mini_location_panel, _2)); gSavedSettings.getControl("ShowObjectRenderingCost")->getSignal()->connect(boost::bind(&toggle_show_object_render_cost, _2)); - gSavedSettings.getControl("UpdaterServiceActive")->getSignal()->connect(&toggle_updater_service_active); + gSavedSettings.getControl("UpdaterServiceSetting")->getSignal()->connect(&toggle_updater_service_active); gSavedSettings.getControl("ForceShowGrid")->getSignal()->connect(boost::bind(&handleForceShowGrid, _2)); gSavedSettings.getControl("RenderTransparentWater")->getSignal()->connect(boost::bind(&handleRenderTransparentWaterChanged, _2)); } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 0250627d1b..5f9e343907 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -783,11 +783,19 @@ void LLVOAvatarSelf::removeMissingBakedTextures() for (U32 i = 0; i < mBakedTextureDatas.size(); i++) { const S32 te = mBakedTextureDatas[i].mTextureIndex; - LLViewerTexture* tex = getTEImage(te) ; + const LLViewerTexture* tex = getTEImage(te); + + // Replace with default if we can't find the asset, assuming the + // default is actually valid (which it should be unless something + // is seriously wrong). if (!tex || tex->isMissingAsset()) { - setTEImage(te, LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR)); - removed = TRUE; + LLViewerTexture *imagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR); + if (imagep) + { + setTEImage(te, imagep); + removed = TRUE; + } } } @@ -823,7 +831,6 @@ void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp) // << llendl; } - if (!regionp || (regionp->getHandle() != mLastRegionHandle)) { if (mLastRegionHandle != 0) diff --git a/indra/newview/skins/default/xui/da/panel_places.xml b/indra/newview/skins/default/xui/da/panel_places.xml index ca3d7c71bb..fe8ca69f34 100644 --- a/indra/newview/skins/default/xui/da/panel_places.xml +++ b/indra/newview/skins/default/xui/da/panel_places.xml @@ -21,7 +21,7 @@ <button label="Redigér" name="edit_btn" tool_tip="Redigér landemærke information"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="Vis flere valg"/> + <menu_button label="▼" name="overflow_btn" tool_tip="Vis flere valg"/> </layout_panel> </layout_stack> <layout_stack name="bottom_bar_ls3"> diff --git a/indra/newview/skins/default/xui/da/panel_profile.xml b/indra/newview/skins/default/xui/da/panel_profile.xml index b2d1e9791a..b8b99a9c21 100644 --- a/indra/newview/skins/default/xui/da/panel_profile.xml +++ b/indra/newview/skins/default/xui/da/panel_profile.xml @@ -42,7 +42,7 @@ <button label="Teleportér" name="teleport" tool_tip="Tilbyd teleport"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="Betal eller del beholdning med denne beboer"/> + <menu_button label="▼" name="overflow_btn" tool_tip="Betal eller del beholdning med denne beboer"/> </layout_panel> </layout_stack> </layout_panel> diff --git a/indra/newview/skins/default/xui/de/panel_places.xml b/indra/newview/skins/default/xui/de/panel_places.xml index 0e85829a0b..36c77d4fe1 100644 --- a/indra/newview/skins/default/xui/de/panel_places.xml +++ b/indra/newview/skins/default/xui/de/panel_places.xml @@ -21,7 +21,7 @@ <button label="Bearbeiten" name="edit_btn" tool_tip="Landmarken-Info bearbeiten"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="Zusätzliche Optionen anzeigen"/> + <menu_button label="▼" name="overflow_btn" tool_tip="Zusätzliche Optionen anzeigen"/> </layout_panel> </layout_stack> <layout_stack name="bottom_bar_ls3"> diff --git a/indra/newview/skins/default/xui/de/panel_profile.xml b/indra/newview/skins/default/xui/de/panel_profile.xml index 40fa2f922a..938631f65d 100644 --- a/indra/newview/skins/default/xui/de/panel_profile.xml +++ b/indra/newview/skins/default/xui/de/panel_profile.xml @@ -57,7 +57,7 @@ <button label="Teleportieren" name="teleport" tool_tip="Teleport anbieten"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="Dem Einwohner Geld geben oder Inventar an den Einwohner schicken"/> + <menu_button label="▼" name="overflow_btn" tool_tip="Dem Einwohner Geld geben oder Inventar an den Einwohner schicken"/> </layout_panel> </layout_stack> </layout_panel> diff --git a/indra/newview/skins/default/xui/en/floater_env_settings.xml b/indra/newview/skins/default/xui/en/floater_env_settings.xml index 14f9e2db95..8df5e232d9 100644 --- a/indra/newview/skins/default/xui/en/floater_env_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_env_settings.xml @@ -44,6 +44,7 @@ left="85" name="EnvDayCycle" top="30" + use_draw_context_alpha="false" width="200" /> <slider control_name="EnvTimeSlider" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 27ab7c4fbd..907f68dc06 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -990,6 +990,14 @@ function="ShowHelp" parameter="f1_help" /> </menu_item_call> + <menu_item_check + label="Enable Hints" + name="Enable Hints"> + <on_check + control="EnableUIHints"/> + <on_click + function="ToggleUIHints"/> + </menu_item_check> <!-- <menu_item_call label="Tutorial" name="Tutorial"> @@ -1023,14 +1031,6 @@ function="Floater.Show" parameter="sl_about" /> </menu_item_call> - <menu_item_check - label="Enable Hints" - name="Enable Hints"> - <on_check - control="EnableUIHints"/> - <on_click - function="ToggleUIHints"/> - </menu_item_check> </menu> <menu create_jump_keys="true" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 60b876d163..b0bb93c13a 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2887,12 +2887,66 @@ http://secondlife.com/download. name="okbutton" yestext="OK"/> </notification> + <notification - icon="notifytip.tga" - name="DownloadBackground" - type="notifytip"> -An updated version of [APP_NAME] has been downloaded. -It will be applied the next time you restart [APP_NAME] + icon="alertmodal.tga" + name="UpdaterServiceNotRunning" + type="alertmodal"> +There is a required update for your Second Life Installation. + +You may download this update from http://www.secondlife.com/downloads +or you can install it now. + <usetemplate + name="okcancelbuttons" + notext="Quit Second Life" + yestext="Download and install now"/> + </notification> + + <notification + icon="notify.tga" + name="DownloadBackgroundTip" + type="notify"> +We have downloaded an update to your [APP_NAME] installation. +Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update] + <usetemplate + name="okcancelbuttons" + notext="Later..." + yestext="Install now and restart [APP_NAME]"/> + </notification> + + <notification + icon="alertmodal.tga" + name="DownloadBackgroundDialog" + type="alertmodal"> +We have downloaded an update to your [APP_NAME] installation. +Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update] + <usetemplate + name="okcancelbuttons" + notext="Later..." + yestext="Install now and restart [APP_NAME]"/> + </notification> + + <notification + icon="alertmodal.tga" + name="RequiredUpdateDownloadedVerboseDialog" + type="alertmodal"> +We have downloaded a required software update. +Version [VERSION] + +We must restart [APP_NAME] to install the update. + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="alertmodal.tga" + name="RequiredUpdateDownloadedDialog" + type="alertmodal"> +We must restart [APP_NAME] to install the update. + <usetemplate + name="okbutton" + yestext="OK"/> </notification> <notification diff --git a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml index 6f3629cc8f..4b21ffa1f9 100644 --- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml @@ -62,7 +62,7 @@ name="avatar_name" top="6" use_ellipses="true" - value="Unknown" + value="(loading)" width="180" /> <text follows="right" diff --git a/indra/newview/skins/default/xui/en/panel_edit_alpha.xml b/indra/newview/skins/default/xui/en/panel_edit_alpha.xml index 7bcd4962d2..813aa5d7a9 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_alpha.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_alpha.xml @@ -8,6 +8,17 @@ name="edit_alpha_panel" top_pad="10" width="333" > + <scroll_container + color="DkGray2" + follows="all" + height="400" + layout="topleft" + left="10" + top_pad="0" + name="avatar_alpha_color_panel_scroll" + reserve_scroll_corner="false" + opaque="true" + width="313"> <panel border="false" bg_alpha_color="DkGray2" @@ -16,14 +27,14 @@ background_opaque="true" follows="top|left|right" height="400" - left="10" + left="0" layout="topleft" name="avatar_alpha_color_panel" top="0" width="313" > <check_box control_name="LowerAlphaTextureInvisible" - follows="left" + follows="left|top" height="16" layout="topleft" left="5" @@ -48,7 +59,7 @@ <check_box control_name="UpperAlphaTextureInvisible" - follows="left" + follows="left|top" height="16" layout="topleft" left_pad="20" @@ -73,7 +84,7 @@ <check_box control_name="HeadAlphaTextureInvisible" - follows="left" + follows="left|top" height="16" layout="topleft" left="5" @@ -98,7 +109,7 @@ <check_box control_name="Eye AlphaTextureInvisible" - follows="left" + follows="left|top" height="16" layout="topleft" left_pad="20" @@ -123,7 +134,7 @@ <check_box control_name="HairAlphaTextureInvisible" - follows="left" + follows="left|top" height="16" layout="topleft" left="5" @@ -147,5 +158,6 @@ </texture_picker> </panel> + </scroll_container> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_edit_tattoo.xml b/indra/newview/skins/default/xui/en/panel_edit_tattoo.xml index 23a08344ea..97f1a1a658 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_tattoo.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_tattoo.xml @@ -14,7 +14,7 @@ bg_opaque_color="DkGray2" background_visible="true" background_opaque="true" - follows="top|left|right" + follows="all" height="400" left="10" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_group_list_item.xml b/indra/newview/skins/default/xui/en/panel_group_list_item.xml index 0b84ac03c5..7d0b0890f0 100644 --- a/indra/newview/skins/default/xui/en/panel_group_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_group_list_item.xml @@ -34,6 +34,7 @@ mouse_opaque="true" left="5" top="2" + use_draw_context_alpha="false" width="20" /> <text parse_urls="false" diff --git a/indra/newview/skins/default/xui/en/panel_landmarks.xml b/indra/newview/skins/default/xui/en/panel_landmarks.xml index 2a5933e3e9..23d8cb11ca 100644 --- a/indra/newview/skins/default/xui/en/panel_landmarks.xml +++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml @@ -114,6 +114,7 @@ height="25" layout="topleft" name="options_gear_btn_panel" + user_resize="false" width="32"> <menu_button follows="bottom|left" @@ -134,6 +135,7 @@ height="25" layout="topleft" name="add_btn_panel" + user_resize="false" width="32"> <button follows="bottom|left" @@ -154,6 +156,7 @@ height="25" layout="topleft" name="dummy_panel" + user_resize="false" width="212"> <icon follows="bottom|left|right" @@ -170,6 +173,7 @@ height="25" layout="topleft" name="trash_btn_panel" + user_resize="false" width="31"> <dnd_button follows="bottom|left" diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index 89feba7c3c..00ab17d4a2 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -11,11 +11,7 @@ top="600" name="create_account_url"> http://join.secondlife.com/ </panel.string> -<panel.string - name="real_url" translate="false"> - http://secondlife.com/app/login/ -</panel.string> - <string name="reg_in_client_url" translate="false"> +<string name="reg_in_client_url" translate="false"> http://secondlife.eniac15.lindenlab.com/reg-in-client/ </string> <panel.string diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index 2b6e082542..96633cb5b4 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -118,6 +118,7 @@ height="25" layout="topleft" name="options_gear_btn_panel" + user_resize="false" width="32"> <menu_button follows="bottom|left" @@ -138,6 +139,7 @@ height="25" layout="topleft" name="add_btn_panel" + user_resize="false" width="32"> <button follows="bottom|left" @@ -158,6 +160,7 @@ height="25" layout="topleft" name="dummy_panel" + user_resize="false" width="212"> <icon follows="bottom|left|right" @@ -174,6 +177,7 @@ height="25" layout="topleft" name="trash_btn_panel" + user_resize="false" width="31"> <dnd_button follows="bottom|left" diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml index 21314703b0..d9c357f277 100644 --- a/indra/newview/skins/default/xui/en/panel_places.xml +++ b/indra/newview/skins/default/xui/en/panel_places.xml @@ -211,7 +211,7 @@ background_visible="true" user_resize="false" auto_resize="true" width="24"> - <button + <menu_button follows="bottom|left|right" height="23" label="▼" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_colors.xml b/indra/newview/skins/default/xui/en/panel_preferences_colors.xml index 5797a63f4e..8a37822413 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_colors.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_colors.xml @@ -275,9 +275,9 @@ height="12" name="bubble_chat" top_pad="20" - width="140" + width="450" > - Bubble chat background: + Name tag background color (also affects Bubble Chat): </text> <color_swatch can_apply_immediately="true" @@ -290,7 +290,7 @@ left_delta="10" top_pad="5" name="background" - tool_tip="Choose color for bubble chat" + tool_tip="Choose name tag color" width="44"> <color_swatch.init_callback function="Pref.getUIColor" @@ -310,6 +310,7 @@ left_pad="10" label_width="70" name="bubble_chat_opacity" + tool_tip="Choose name tag opacity" top_delta = "6" width="378" /> <text diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index 584bd1ea9d..542b6bcf6b 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -142,7 +142,7 @@ layout="topleft" left="80" name="Cache location" - top_delta="40" + top_delta="20" width="300"> Cache location: </text> @@ -341,20 +341,39 @@ name="web_proxy_port" top_delta="0" width="145" /> - - <check_box - top_delta="2" - enabled="true" - follows="left|top" - height="18" - initial_value="true" - control_name="UpdaterServiceActive" - label="Automatically download and install [APP_NAME] updates" - left="30" - mouse_opaque="true" - name="updater_service_active" - radio_style="false" - width="400" - top_pad="10"/> - + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left="30" + name="Software updates:" + mouse_opaque="false" + top_pad="5" + width="300"> + Software updates: + </text> + <combo_box + control_name="UpdaterServiceSetting" + follows="left|top" + height="23" + layout="topleft" + left_delta="50" + top_pad="5" + name="updater_service_combobox" + width="300"> + <combo_box.item + label="Install automatically" + name="Install_automatically" + value="3" /> + <combo_box.item + label="Ask before installing" + name="Install_ask" + value="1" /> + <combo_box.item + label="Download and install updates manually" + name="Install_manual" + value="0" /> + </combo_box> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index efc37c2127..7caf425058 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -432,7 +432,7 @@ user_resize="false" auto_resize="false" width="24"> - <button + <menu_button follows="bottom|left|right" height="23" label="▼" diff --git a/indra/newview/skins/default/xui/en/widgets/group_icon.xml b/indra/newview/skins/default/xui/en/widgets/group_icon.xml index 58d5e19fcc..36ee6dd7eb 100644 --- a/indra/newview/skins/default/xui/en/widgets/group_icon.xml +++ b/indra/newview/skins/default/xui/en/widgets/group_icon.xml @@ -2,4 +2,5 @@ <group_icon default_icon_name="Generic_Group" image_name="Generic_Group" - name="group_icon" /> + name="group_icon" + use_draw_context_alpha="false" /> diff --git a/indra/newview/skins/default/xui/es/panel_places.xml b/indra/newview/skins/default/xui/es/panel_places.xml index 2e349c7fe2..4c90a7e6b4 100644 --- a/indra/newview/skins/default/xui/es/panel_places.xml +++ b/indra/newview/skins/default/xui/es/panel_places.xml @@ -21,7 +21,7 @@ <button label="Editar" name="edit_btn" tool_tip="Editar la información del hito"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="Ver más opciones"/> + <menu_button label="▼" name="overflow_btn" tool_tip="Ver más opciones"/> </layout_panel> </layout_stack> <layout_stack name="bottom_bar_ls3"> diff --git a/indra/newview/skins/default/xui/es/panel_profile.xml b/indra/newview/skins/default/xui/es/panel_profile.xml index 5cfe83cd61..339a1f236b 100644 --- a/indra/newview/skins/default/xui/es/panel_profile.xml +++ b/indra/newview/skins/default/xui/es/panel_profile.xml @@ -53,7 +53,7 @@ <button label="Teleporte" name="teleport" tool_tip="Ofrecer teleporte"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="Pagar dinero al Residente o compartir algo del inventario con él"/> + <menu_button label="▼" name="overflow_btn" tool_tip="Pagar dinero al Residente o compartir algo del inventario con él"/> </layout_panel> </layout_stack> </layout_panel> diff --git a/indra/newview/skins/default/xui/fr/panel_places.xml b/indra/newview/skins/default/xui/fr/panel_places.xml index 7f3601b90d..e252c224f8 100644 --- a/indra/newview/skins/default/xui/fr/panel_places.xml +++ b/indra/newview/skins/default/xui/fr/panel_places.xml @@ -21,7 +21,7 @@ <button label="Modifier" name="edit_btn" tool_tip="Modifier les informations du repère"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="Afficher d'autres options"/> + <menu_button label="▼" name="overflow_btn" tool_tip="Afficher d'autres options"/> </layout_panel> </layout_stack> <layout_stack name="bottom_bar_ls3"> diff --git a/indra/newview/skins/default/xui/fr/panel_profile.xml b/indra/newview/skins/default/xui/fr/panel_profile.xml index 4606f5a0c6..6b611923af 100644 --- a/indra/newview/skins/default/xui/fr/panel_profile.xml +++ b/indra/newview/skins/default/xui/fr/panel_profile.xml @@ -57,7 +57,7 @@ <button label="Téléporter" name="teleport" tool_tip="Proposer une téléportation"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="Payer le résident ou partager l'inventaire avec lui"/> + <menu_button label="▼" name="overflow_btn" tool_tip="Payer le résident ou partager l'inventaire avec lui"/> </layout_panel> </layout_stack> </layout_panel> diff --git a/indra/newview/skins/default/xui/it/panel_places.xml b/indra/newview/skins/default/xui/it/panel_places.xml index e33f8190eb..61830f186f 100644 --- a/indra/newview/skins/default/xui/it/panel_places.xml +++ b/indra/newview/skins/default/xui/it/panel_places.xml @@ -21,7 +21,7 @@ <button label="Modifica" name="edit_btn" tool_tip="Modifica le informazioni del punto di riferimento"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="Mostra ulteriori opzioni"/> + <menu_button label="▼" name="overflow_btn" tool_tip="Mostra ulteriori opzioni"/> </layout_panel> </layout_stack> <layout_stack name="bottom_bar_ls3"> diff --git a/indra/newview/skins/default/xui/it/panel_profile.xml b/indra/newview/skins/default/xui/it/panel_profile.xml index 8a8d8f5846..c11adeda3d 100644 --- a/indra/newview/skins/default/xui/it/panel_profile.xml +++ b/indra/newview/skins/default/xui/it/panel_profile.xml @@ -53,7 +53,7 @@ <button label="Teleport" name="teleport" tool_tip="Offri teleport"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="Paga del denaro o condividi qualcosa dall'inventario con il residente"/> + <menu_button label="▼" name="overflow_btn" tool_tip="Paga del denaro o condividi qualcosa dall'inventario con il residente"/> </layout_panel> </layout_stack> </layout_panel> diff --git a/indra/newview/skins/default/xui/ja/panel_places.xml b/indra/newview/skins/default/xui/ja/panel_places.xml index 3e364c9b3a..e19b86e552 100644 --- a/indra/newview/skins/default/xui/ja/panel_places.xml +++ b/indra/newview/skins/default/xui/ja/panel_places.xml @@ -21,7 +21,7 @@ <button label="編集" name="edit_btn" tool_tip="ランドマークの情報を編集します"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="オプションを表示します"/> + <menu_button label="▼" name="overflow_btn" tool_tip="オプションを表示します"/> </layout_panel> </layout_stack> <layout_stack name="bottom_bar_ls3"> diff --git a/indra/newview/skins/default/xui/ja/panel_profile.xml b/indra/newview/skins/default/xui/ja/panel_profile.xml index 860020c87c..c2ffd74ec0 100644 --- a/indra/newview/skins/default/xui/ja/panel_profile.xml +++ b/indra/newview/skins/default/xui/ja/panel_profile.xml @@ -57,7 +57,7 @@ <button label="テレポート" name="teleport" tool_tip="テレポートを送ります"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="住人にお金を渡すか持ち物を共有します"/> + <menu_button label="▼" name="overflow_btn" tool_tip="住人にお金を渡すか持ち物を共有します"/> </layout_panel> </layout_stack> </layout_panel> diff --git a/indra/newview/skins/default/xui/pl/panel_places.xml b/indra/newview/skins/default/xui/pl/panel_places.xml index e0a0cfd96a..34c105225d 100644 --- a/indra/newview/skins/default/xui/pl/panel_places.xml +++ b/indra/newview/skins/default/xui/pl/panel_places.xml @@ -21,7 +21,7 @@ <button label="Edytuj" name="edit_btn" tool_tip="Edytuj informacje landmarka"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="Pokaż opcje dodatkowe"/> + <menu_button label="▼" name="overflow_btn" tool_tip="Pokaż opcje dodatkowe"/> </layout_panel> </layout_stack> <layout_stack name="bottom_bar_ls3"> diff --git a/indra/newview/skins/default/xui/pl/panel_profile.xml b/indra/newview/skins/default/xui/pl/panel_profile.xml index f4a5699f8d..4152c00386 100644 --- a/indra/newview/skins/default/xui/pl/panel_profile.xml +++ b/indra/newview/skins/default/xui/pl/panel_profile.xml @@ -42,7 +42,7 @@ <button label="Teleportuj" name="teleport" tool_tip="Teleportuj"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="Zapłać lub udostępnij obiekt Rezydentowi"/> + <menu_button label="▼" name="overflow_btn" tool_tip="Zapłać lub udostępnij obiekt Rezydentowi"/> </layout_panel> </layout_stack> </layout_panel> diff --git a/indra/newview/skins/default/xui/pt/panel_places.xml b/indra/newview/skins/default/xui/pt/panel_places.xml index 2e443bc057..828ef3e469 100644 --- a/indra/newview/skins/default/xui/pt/panel_places.xml +++ b/indra/newview/skins/default/xui/pt/panel_places.xml @@ -21,7 +21,7 @@ <button label="Editar" name="edit_btn" tool_tip="Editar dados do marco"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="Mostrar opções adicionais"/> + <menu_button label="▼" name="overflow_btn" tool_tip="Mostrar opções adicionais"/> </layout_panel> </layout_stack> <layout_stack name="bottom_bar_ls3"> diff --git a/indra/newview/skins/default/xui/pt/panel_profile.xml b/indra/newview/skins/default/xui/pt/panel_profile.xml index e4200ae5da..f984ed6a7b 100644 --- a/indra/newview/skins/default/xui/pt/panel_profile.xml +++ b/indra/newview/skins/default/xui/pt/panel_profile.xml @@ -53,7 +53,7 @@ <button label="Teletransportar" name="teleport" tool_tip="Oferecer teletransporte"/> </layout_panel> <layout_panel name="overflow_btn_lp"> - <button label="▼" name="overflow_btn" tool_tip="Pagar ou compartilhar inventário com o residente"/> + <menu_button label="▼" name="overflow_btn" tool_tip="Pagar ou compartilhar inventário com o residente"/> </layout_panel> </layout_stack> </layout_panel> diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index 309e9e9ee3..9e321db889 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -40,6 +40,7 @@ #if defined(LL_WINDOWS) #pragma warning(disable: 4355) // using 'this' in base-class ctor initializer expr +#pragma warning(disable: 4702) // disable 'unreachable code' so we can safely use skip(). #endif // Constants @@ -68,6 +69,7 @@ static bool gDisconnectCalled = false; #include "../llviewerwindow.h" void LLViewerWindow::setShowProgress(BOOL show) {} +LLProgressView * LLViewerWindow::getProgressView(void) const { return 0; } LLViewerWindow* gViewerWindow; @@ -185,6 +187,41 @@ const std::string &LLVersionInfo::getChannelAndVersion() { return VIEWERLOGIN_VE const std::string &LLVersionInfo::getChannel() { return VIEWERLOGIN_CHANNEL; } //----------------------------------------------------------------------------- +#include "../llappviewer.h" +void LLAppViewer::forceQuit(void) {} +LLAppViewer * LLAppViewer::sInstance = 0; + +//----------------------------------------------------------------------------- +#include "llnotificationsutil.h" +LLNotificationPtr LLNotificationsUtil::add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + boost::function<void (const LLSD&, const LLSD&)> functor) { return LLNotificationPtr((LLNotification*)0); } + + +//----------------------------------------------------------------------------- +#include "llupdaterservice.h" + +std::string const & LLUpdaterService::pumpName(void) +{ + static std::string wakka = "wakka wakka wakka"; + return wakka; +} +bool LLUpdaterService::updateReadyToInstall(void) { return false; } +void LLUpdaterService::initialize(const std::string& protocol_version, + const std::string& url, + const std::string& path, + const std::string& channel, + const std::string& version) {} + +void LLUpdaterService::setCheckPeriod(unsigned int seconds) {} +void LLUpdaterService::startChecking(bool install_if_ready) {} +void LLUpdaterService::stopChecking() {} +bool LLUpdaterService::isChecking() { return false; } +LLUpdaterService::eUpdaterState LLUpdaterService::getState() { return INITIAL; } +std::string LLUpdaterService::updatedVersion() { return ""; } + +//----------------------------------------------------------------------------- #include "llnotifications.h" #include "llfloaterreg.h" static std::string gTOSType; @@ -198,6 +235,12 @@ LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, return NULL; } +//---------------------------------------------------------------------------- +#include "../llprogressview.h" +void LLProgressView::setText(std::string const &){} +void LLProgressView::setPercent(float){} +void LLProgressView::setMessage(std::string const &){} + //----------------------------------------------------------------------------- // LLNotifications class MockNotifications : public LLNotificationsInterface @@ -435,6 +478,8 @@ namespace tut template<> template<> void lllogininstance_object::test<3>() { + skip(); + set_test_name("Test Mandatory Update User Accepts"); // Part 1 - Mandatory Update, with User accepts response. @@ -462,6 +507,8 @@ namespace tut template<> template<> void lllogininstance_object::test<4>() { + skip(); + set_test_name("Test Mandatory Update User Decline"); // Test connect with update needed. diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index c17a50e242..f259e06476 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -24,17 +24,20 @@ */ #include "linden_common.h" + +#include "llupdatedownloader.h" + #include <stdexcept> #include <boost/format.hpp> #include <boost/lexical_cast.hpp> #include <curl/curl.h> #include "lldir.h" +#include "llevents.h" #include "llfile.h" #include "llmd5.h" #include "llsd.h" #include "llsdserialize.h" #include "llthread.h" -#include "llupdatedownloader.h" #include "llupdaterservice.h" @@ -45,18 +48,25 @@ public: Implementation(LLUpdateDownloader::Client & client); ~Implementation(); void cancel(void); - void download(LLURI const & uri, std::string const & hash); + void download(LLURI const & uri, + std::string const & hash, + std::string const & updateVersion, + bool required); bool isDownloading(void); size_t onHeader(void * header, size_t size); size_t onBody(void * header, size_t size); + int onProgress(double downloadSize, double bytesDownloaded); void resume(void); + void setBandwidthLimit(U64 bytesPerSecond); private: + curl_off_t mBandwidthLimit; bool mCancelled; LLUpdateDownloader::Client & mClient; CURL * mCurl; LLSD mDownloadData; llofstream mDownloadStream; + unsigned char mDownloadPercent; std::string mDownloadRecordPath; curl_slist * mHeaderList; @@ -113,9 +123,12 @@ void LLUpdateDownloader::cancel(void) } -void LLUpdateDownloader::download(LLURI const & uri, std::string const & hash) +void LLUpdateDownloader::download(LLURI const & uri, + std::string const & hash, + std::string const & updateVersion, + bool required) { - mImplementation->download(uri, hash); + mImplementation->download(uri, hash, updateVersion, required); } @@ -131,6 +144,12 @@ void LLUpdateDownloader::resume(void) } +void LLUpdateDownloader::setBandwidthLimit(U64 bytesPerSecond) +{ + mImplementation->setBandwidthLimit(bytesPerSecond); +} + + // LLUpdateDownloader::Implementation //----------------------------------------------------------------------------- @@ -149,14 +168,27 @@ namespace { size_t bytes = blockSize * blocks; return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)->onHeader(data, bytes); } + + + int progress_callback(void * downloader, + double dowloadTotal, + double downloadNow, + double uploadTotal, + double uploadNow) + { + return reinterpret_cast<LLUpdateDownloader::Implementation *>(downloader)-> + onProgress(dowloadTotal, downloadNow); + } } LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client): LLThread("LLUpdateDownloader"), + mBandwidthLimit(0), mCancelled(false), mClient(client), mCurl(0), + mDownloadPercent(0), mHeaderList(0) { CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case. @@ -182,12 +214,17 @@ void LLUpdateDownloader::Implementation::cancel(void) } -void LLUpdateDownloader::Implementation::download(LLURI const & uri, std::string const & hash) +void LLUpdateDownloader::Implementation::download(LLURI const & uri, + std::string const & hash, + std::string const & updateVersion, + bool required) { if(isDownloading()) mClient.downloadError("download in progress"); mDownloadRecordPath = downloadMarkerPath(); mDownloadData = LLSD(); + mDownloadData["required"] = required; + mDownloadData["update_version"] = updateVersion; try { startDownloading(uri, hash); } catch(DownloadError const & e) { @@ -233,12 +270,18 @@ void LLUpdateDownloader::Implementation::resume(void) resumeDownloading(fileStatus.st_size); } else if(!validateDownload()) { LLFile::remove(filePath); - download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString()); + download(LLURI(mDownloadData["url"].asString()), + mDownloadData["hash"].asString(), + mDownloadData["update_version"].asString(), + mDownloadData["required"].asBoolean()); } else { mClient.downloadComplete(mDownloadData); } } else { - download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString()); + download(LLURI(mDownloadData["url"].asString()), + mDownloadData["hash"].asString(), + mDownloadData["update_version"].asString(), + mDownloadData["required"].asBoolean()); } } catch(DownloadError & e) { mClient.downloadError(e.what()); @@ -246,6 +289,20 @@ void LLUpdateDownloader::Implementation::resume(void) } +void LLUpdateDownloader::Implementation::setBandwidthLimit(U64 bytesPerSecond) +{ + if((mBandwidthLimit != bytesPerSecond) && isDownloading() && !mDownloadData["required"].asBoolean()) { + llassert(mCurl != 0); + mBandwidthLimit = bytesPerSecond; + CURLcode code = curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit); + if(code != CURLE_OK) LL_WARNS("UpdateDownload") << + "unable to change dowload bandwidth" << LL_ENDL; + } else { + mBandwidthLimit = bytesPerSecond; + } +} + + size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) { char const * headerPtr = reinterpret_cast<const char *> (buffer); @@ -290,6 +347,30 @@ size_t LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size) } +int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double bytesDownloaded) +{ + int downloadPercent = static_cast<int>(100. * (bytesDownloaded / downloadSize)); + if(downloadPercent > mDownloadPercent) { + mDownloadPercent = downloadPercent; + + LLSD event; + event["pump"] = LLUpdaterService::pumpName(); + LLSD payload; + payload["type"] = LLSD(LLUpdaterService::PROGRESS); + payload["download_size"] = downloadSize; + payload["bytes_downloaded"] = bytesDownloaded; + event["payload"] = payload; + LLEventPumps::instance().obtain("mainlooprepeater").post(event); + + LL_INFOS("UpdateDownload") << "progress event " << payload << LL_ENDL; + } else { + ; // Keep events to a reasonalbe number. + } + + return 0; +} + + void LLUpdateDownloader::Implementation::run(void) { CURLcode code = curl_easy_perform(mCurl); @@ -343,6 +424,16 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u } throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPGET, true)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str())); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_PROGRESSFUNCTION, &progress_callback)); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_PROGRESSDATA, this)); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOPROGRESS, false)); + if((mBandwidthLimit != 0) && !mDownloadData["required"].asBoolean()) { + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, mBandwidthLimit)); + } else { + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, -1)); + } + + mDownloadPercent = 0; } diff --git a/indra/viewer_components/updater/llupdatedownloader.h b/indra/viewer_components/updater/llupdatedownloader.h index 1b3d7480fd..0d635640cf 100644 --- a/indra/viewer_components/updater/llupdatedownloader.h +++ b/indra/viewer_components/updater/llupdatedownloader.h @@ -52,7 +52,10 @@ public: void cancel(void); // Start a new download. - void download(LLURI const & uri, std::string const & hash); + void download(LLURI const & uri, + std::string const & hash, + std::string const & updateVersion, + bool required=false); // Returns true if a download is in progress. bool isDownloading(void); @@ -60,6 +63,9 @@ public: // Resume a partial download. void resume(void); + // Set a limit on the dowload rate. + void setBandwidthLimit(U64 bytesPerSecond); + private: boost::shared_ptr<Implementation> mImplementation; }; @@ -76,6 +82,7 @@ public: // url - source (remote) location // hash - the md5 sum that should match the installer file. // path - destination (local) location + // required - boolean indicating if this is a required update. // size - the size of the installer in bytes virtual void downloadComplete(LLSD const & data) = 0; diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index cc60eaead2..df1a963f81 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -25,10 +25,11 @@ #include "linden_common.h" +#include "llupdaterservice.h" + #include "llupdatedownloader.h" #include "llevents.h" #include "lltimer.h" -#include "llupdaterservice.h" #include "llupdatechecker.h" #include "llupdateinstaller.h" #include "llversionviewer.h" @@ -98,6 +99,8 @@ class LLUpdaterServiceImpl : LLUpdaterService::app_exit_callback_t mAppExitCallback; + LLUpdaterService::eUpdaterState mState; + LOG_CLASS(LLUpdaterServiceImpl); public: @@ -111,12 +114,15 @@ public: const std::string& version); void setCheckPeriod(unsigned int seconds); + void setBandwidthLimit(U64 bytesPerSecond); void startChecking(bool install_if_ready); void stopChecking(); bool isChecking(); + LLUpdaterService::eUpdaterState getState(); void setAppExitCallback(LLUpdaterService::app_exit_callback_t aecb) { mAppExitCallback = aecb;} + std::string updatedVersion(void); bool checkForInstall(bool launchInstaller); // Test if a local install is ready. bool checkForResume(); // Test for resumeable d/l. @@ -138,7 +144,10 @@ public: bool onMainLoop(LLSD const & event); private: + std::string mNewVersion; + void restartTimer(unsigned int seconds); + void setState(LLUpdaterService::eUpdaterState state); void stopTimer(); }; @@ -149,7 +158,8 @@ LLUpdaterServiceImpl::LLUpdaterServiceImpl() : mIsDownloading(false), mCheckPeriod(0), mUpdateChecker(*this), - mUpdateDownloader(*this) + mUpdateDownloader(*this), + mState(LLUpdaterService::INITIAL) { } @@ -183,6 +193,11 @@ void LLUpdaterServiceImpl::setCheckPeriod(unsigned int seconds) mCheckPeriod = seconds; } +void LLUpdaterServiceImpl::setBandwidthLimit(U64 bytesPerSecond) +{ + mUpdateDownloader.setBandwidthLimit(bytesPerSecond); +} + void LLUpdaterServiceImpl::startChecking(bool install_if_ready) { if(mUrl.empty() || mChannel.empty() || mVersion.empty()) @@ -201,10 +216,16 @@ void LLUpdaterServiceImpl::startChecking(bool install_if_ready) if(!mIsDownloading) { + setState(LLUpdaterService::CHECKING_FOR_UPDATE); + // Checking can only occur during the mainloop. // reset the timer to 0 so that the next mainloop event // triggers a check; restartTimer(0); + } + else + { + setState(LLUpdaterService::DOWNLOADING); } } } @@ -222,6 +243,8 @@ void LLUpdaterServiceImpl::stopChecking() mUpdateDownloader.cancel(); mIsDownloading = false; } + + setState(LLUpdaterService::TERMINAL); } bool LLUpdaterServiceImpl::isChecking() @@ -229,6 +252,16 @@ bool LLUpdaterServiceImpl::isChecking() return mIsChecking; } +LLUpdaterService::eUpdaterState LLUpdaterServiceImpl::getState() +{ + return mState; +} + +std::string LLUpdaterServiceImpl::updatedVersion(void) +{ + return mNewVersion; +} + bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller) { bool foundInstall = false; // return true if install is found. @@ -266,6 +299,8 @@ bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller) { if(launchInstaller) { + setState(LLUpdaterService::INSTALLING); + LLFile::remove(update_marker_path()); int result = ll_install_update(install_script_path(), @@ -304,6 +339,7 @@ bool LLUpdaterServiceImpl::checkForResume() if(download_info["current_version"].asString() == ll_get_version()) { mIsDownloading = true; + mNewVersion = download_info["update_version"].asString(); mUpdateDownloader.resume(); result = true; } @@ -333,8 +369,11 @@ void LLUpdaterServiceImpl::optionalUpdate(std::string const & newVersion, std::string const & hash) { stopTimer(); + mNewVersion = newVersion; mIsDownloading = true; - mUpdateDownloader.download(uri, hash); + mUpdateDownloader.download(uri, hash, newVersion, false); + + setState(LLUpdaterService::DOWNLOADING); } void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion, @@ -342,8 +381,11 @@ void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion, std::string const & hash) { stopTimer(); + mNewVersion = newVersion; mIsDownloading = true; - mUpdateDownloader.download(uri, hash); + mUpdateDownloader.download(uri, hash, newVersion, true); + + setState(LLUpdaterService::DOWNLOADING); } void LLUpdaterServiceImpl::upToDate(void) @@ -352,6 +394,8 @@ void LLUpdaterServiceImpl::upToDate(void) { restartTimer(mCheckPeriod); } + + setState(LLUpdaterService::UP_TO_DATE); } void LLUpdaterServiceImpl::downloadComplete(LLSD const & data) @@ -367,8 +411,12 @@ void LLUpdaterServiceImpl::downloadComplete(LLSD const & data) event["pump"] = LLUpdaterService::pumpName(); LLSD payload; payload["type"] = LLSD(LLUpdaterService::DOWNLOAD_COMPLETE); + payload["required"] = data["required"]; + payload["version"] = mNewVersion; event["payload"] = payload; LLEventPumps::instance().obtain("mainlooprepeater").post(event); + + setState(LLUpdaterService::TERMINAL); } void LLUpdaterServiceImpl::downloadError(std::string const & message) @@ -390,6 +438,8 @@ void LLUpdaterServiceImpl::downloadError(std::string const & message) payload["message"] = message; event["payload"] = payload; LLEventPumps::instance().obtain("mainlooprepeater").post(event); + + setState(LLUpdaterService::FAILURE); } void LLUpdaterServiceImpl::restartTimer(unsigned int seconds) @@ -402,6 +452,28 @@ void LLUpdaterServiceImpl::restartTimer(unsigned int seconds) sListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1)); } +void LLUpdaterServiceImpl::setState(LLUpdaterService::eUpdaterState state) +{ + if(state != mState) + { + mState = state; + + LLSD event; + event["pump"] = LLUpdaterService::pumpName(); + LLSD payload; + payload["type"] = LLSD(LLUpdaterService::STATE_CHANGE); + payload["state"] = state; + event["payload"] = payload; + LLEventPumps::instance().obtain("mainlooprepeater").post(event); + + LL_INFOS("UpdaterService") << "setting state to " << state << LL_ENDL; + } + else + { + ; // State unchanged; noop. + } +} + void LLUpdaterServiceImpl::stopTimer() { mTimer.stop(); @@ -425,10 +497,13 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event) LLSD event; event["type"] = LLSD(LLUpdaterService::INSTALL_ERROR); LLEventPumps::instance().obtain(LLUpdaterService::pumpName()).post(event); + + setState(LLUpdaterService::TERMINAL); } else { mUpdateChecker.check(mProtocolVersion, mUrl, mPath, mChannel, mVersion); + setState(LLUpdaterService::CHECKING_FOR_UPDATE); } } else @@ -449,6 +524,11 @@ std::string const & LLUpdaterService::pumpName(void) return name; } +bool LLUpdaterService::updateReadyToInstall(void) +{ + return LLFile::isfile(update_marker_path()); +} + LLUpdaterService::LLUpdaterService() { if(gUpdater.expired()) @@ -480,6 +560,11 @@ void LLUpdaterService::setCheckPeriod(unsigned int seconds) { mImpl->setCheckPeriod(seconds); } + +void LLUpdaterService::setBandwidthLimit(U64 bytesPerSecond) +{ + mImpl->setBandwidthLimit(bytesPerSecond); +} void LLUpdaterService::startChecking(bool install_if_ready) { @@ -496,11 +581,21 @@ bool LLUpdaterService::isChecking() return mImpl->isChecking(); } +LLUpdaterService::eUpdaterState LLUpdaterService::getState() +{ + return mImpl->getState(); +} + void LLUpdaterService::setImplAppExitCallback(LLUpdaterService::app_exit_callback_t aecb) { return mImpl->setAppExitCallback(aecb); } +std::string LLUpdaterService::updatedVersion(void) +{ + return mImpl->updatedVersion(); +} + std::string const & ll_get_version(void) { static std::string version(""); diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 752a6f834b..421481bc43 100644 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -43,12 +43,27 @@ public: // Name of the event pump through which update events will be delivered. static std::string const & pumpName(void); + // Returns true if an update has been completely downloaded and is now ready to install. + static bool updateReadyToInstall(void); + // Type codes for events posted by this service. Stored the event's 'type' element. - enum eUpdateEvent { + enum eUpdaterEvent { INVALID, DOWNLOAD_COMPLETE, DOWNLOAD_ERROR, - INSTALL_ERROR + INSTALL_ERROR, + PROGRESS, + STATE_CHANGE + }; + + enum eUpdaterState { + INITIAL, + CHECKING_FOR_UPDATE, + DOWNLOADING, + INSTALLING, + UP_TO_DATE, + TERMINAL, + FAILURE }; LLUpdaterService(); @@ -61,10 +76,12 @@ public: const std::string& version); void setCheckPeriod(unsigned int seconds); + void setBandwidthLimit(U64 bytesPerSecond); void startChecking(bool install_if_ready = false); void stopChecking(); bool isChecking(); + eUpdaterState getState(); typedef boost::function<void (void)> app_exit_callback_t; template <typename F> @@ -73,6 +90,11 @@ public: app_exit_callback_t aecb = callable; setImplAppExitCallback(aecb); } + + // If an update is or has been downloaded, this method will return the + // version string for that update. An empty string will be returned + // otherwise. + std::string updatedVersion(void); private: boost::shared_ptr<LLUpdaterServiceImpl> mImpl; diff --git a/indra/viewer_components/updater/scripts/darwin/update_install b/indra/viewer_components/updater/scripts/darwin/update_install index 9df382f119..9df382f119 100755..100644 --- a/indra/viewer_components/updater/scripts/darwin/update_install +++ b/indra/viewer_components/updater/scripts/darwin/update_install diff --git a/indra/viewer_components/updater/scripts/linux/update_install b/indra/viewer_components/updater/scripts/linux/update_install index a271926e25..a271926e25 100755..100644 --- a/indra/viewer_components/updater/scripts/linux/update_install +++ b/indra/viewer_components/updater/scripts/linux/update_install diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index 04ed4e6364..be5a5da50d 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -48,7 +48,7 @@ void LLUpdateChecker::check(std::string const & protocolVersion, std::string con std::string const & servicePath, std::string channel, std::string version)
{}
LLUpdateDownloader::LLUpdateDownloader(Client & ) {}
-void LLUpdateDownloader::download(LLURI const & , std::string const &){}
+void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, bool){}
class LLDir_Mock : public LLDir
{
@@ -101,6 +101,7 @@ std::string LLUpdateDownloader::downloadMarkerPath(void) void LLUpdateDownloader::resume(void) {}
void LLUpdateDownloader::cancel(void) {}
+void LLUpdateDownloader::setBandwidthLimit(U64 bytesPerSecond) {}
int ll_install_update(std::string const &, std::string const &, LLInstallScriptMode)
{
|