diff options
Diffstat (limited to 'indra')
139 files changed, 2601 insertions, 1065 deletions
diff --git a/indra/cmake/BuildVersion.cmake b/indra/cmake/BuildVersion.cmake index b9ec8f5266..af2063ce6d 100755 --- a/indra/cmake/BuildVersion.cmake +++ b/indra/cmake/BuildVersion.cmake @@ -18,7 +18,7 @@ if (NOT DEFINED VIEWER_SHORT_VERSION) # will be true in indra/, false in indra/n find_program(MERCURIAL hg) if (DEFINED MERCURIAL) execute_process( - COMMAND ${MERCURIAL} log -r tip --template "{p1rev}" + COMMAND ${MERCURIAL} log -r tip --template "{rev}" OUTPUT_VARIABLE VIEWER_VERSION_REVISION OUTPUT_STRIP_TRAILING_WHITESPACE ) diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt index e003ed7788..774e8c0676 100755 --- a/indra/edit-me-to-trigger-new-build.txt +++ b/indra/edit-me-to-trigger-new-build.txt @@ -3,3 +3,4 @@ Wed Nov 7 00:25:19 UTC 2012 + diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py index 9cb830a2db..54049b5545 100755 --- a/indra/lib/python/indra/util/llmanifest.py +++ b/indra/lib/python/indra/util/llmanifest.py @@ -392,11 +392,21 @@ class LLManifest(object): raise ManifestError, "Should be something at path " + path self.created_paths.append(path) - def put_in_file(self, contents, dst): + def put_in_file(self, contents, dst, src=None): # write contents as dst - f = open(self.dst_path_of(dst), "wb") - f.write(contents) - f.close() + dst_path = self.dst_path_of(dst) + f = open(dst_path, "wb") + try: + f.write(contents) + finally: + f.close() + + # Why would we create a file in the destination tree if not to include + # it in the installer? The default src=None (plus the fact that the + # src param is last) is to preserve backwards compatibility. + if src: + self.file_list.append([src, dst_path]) + return dst_path def replace_in(self, src, dst=None, searchdict={}): if dst == None: diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp index f188865eb0..3e68ef068e 100755 --- a/indra/llcommon/tests/llprocess_test.cpp +++ b/indra/llcommon/tests/llprocess_test.cpp @@ -608,9 +608,6 @@ namespace tut void object::test<5>() { set_test_name("exit(2)"); -#if LL_WINDOWS - skip("MAINT-2302: This frequently (though not always) fails on Windows."); -#endif PythonProcessLauncher py(get_test_name(), "import sys\n" "sys.exit(2)\n"); @@ -622,10 +619,7 @@ namespace tut template<> template<> void object::test<6>() { - set_test_name("syntax_error:"); -#if LL_WINDOWS - skip("MAINT-2302: This frequently (though not always) fails on Windows."); -#endif + set_test_name("syntax_error"); PythonProcessLauncher py(get_test_name(), "syntax_error:\n"); py.mParams.files.add(LLProcess::FileParam()); // inherit stdin @@ -647,9 +641,6 @@ namespace tut void object::test<7>() { set_test_name("explicit kill()"); -#if LL_WINDOWS - skip("MAINT-2302: This frequently (though not always) fails on Windows."); -#endif PythonProcessLauncher py(get_test_name(), "from __future__ import with_statement\n" "import sys, time\n" @@ -694,9 +685,6 @@ namespace tut void object::test<8>() { set_test_name("implicit kill()"); -#if LL_WINDOWS - skip("MAINT-2302: This frequently (though not always) fails on Windows."); -#endif NamedTempFile out("out", "not started"); LLProcess::handle phandle(0); { diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index a8149a9a1d..44f2c1efe9 100755 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -644,7 +644,7 @@ void LLButton::draw() // Cancel sticking of color, if the button is pressed, // or when a flashing of the previously selected button is ended if (mFlashingTimer - && ((selected && !mFlashingTimer->isFlashingInProgress()) || pressed)) + && ((selected && !mFlashingTimer->isFlashingInProgress() && !mForceFlashing) || pressed)) { mFlashing = false; } @@ -971,8 +971,9 @@ void LLButton::setToggleState(BOOL b) } } -void LLButton::setFlashing(bool b) +void LLButton::setFlashing(bool b, bool force_flashing/* = false */) { + mForceFlashing = force_flashing; if (mFlashingTimer) { mFlashing = b; diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 060db59a8a..7b4719866d 100755 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -201,7 +201,7 @@ public: void setToggleState(BOOL b); void setHighlight(bool b); - void setFlashing( bool b ); + void setFlashing( bool b, bool force_flashing = false ); BOOL getFlashing() const { return mFlashing; } LLFlashTimer* getFlashTimer() {return mFlashingTimer;} @@ -378,7 +378,7 @@ protected: LLFrameTimer mFrameTimer; LLFlashTimer * mFlashingTimer; - + bool mForceFlashing; // Stick flashing color even if button is pressed bool mHandleRightMouse; }; diff --git a/indra/llui/llchatentry.cpp b/indra/llui/llchatentry.cpp index f6c4b69308..c04b70eb64 100755 --- a/indra/llui/llchatentry.cpp +++ b/indra/llui/llchatentry.cpp @@ -62,9 +62,9 @@ void LLChatEntry::draw() { if(mIsExpandable) { + reflow(); expandText(); } - LLTextEditor::draw(); } @@ -158,11 +158,23 @@ void LLChatEntry::onValueChange(S32 start, S32 end) resetLabel(); } -bool LLChatEntry::useLabel() +bool LLChatEntry::useLabel() const { return !getLength() && !mLabel.empty(); } +void LLChatEntry::onFocusReceived() +{ + LLUICtrl::onFocusReceived(); + updateAllowingLanguageInput(); +} + +void LLChatEntry::onFocusLost() +{ + LLTextEditor::focusLostHelper(); + LLUICtrl::onFocusLost(); +} + BOOL LLChatEntry::handleSpecialKey(const KEY key, const MASK mask) { BOOL handled = FALSE; diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h index a20a505ae1..3f13691a30 100755 --- a/indra/llui/llchatentry.h +++ b/indra/llui/llchatentry.h @@ -56,12 +56,14 @@ protected: LLChatEntry(const Params& p); /*virtual*/ void beforeValueChange(); /*virtual*/ void onValueChange(S32 start, S32 end); - /*virtual*/ bool useLabel(); + /*virtual*/ bool useLabel() const; public: virtual void draw(); virtual void onCommit(); + /*virtual*/ void onFocusReceived(); + /*virtual*/ void onFocusLost(); void enableSingleLineMode(bool single_line_mode); boost::signals2::connection setTextExpandedCallback(const commit_signal_t::slot_type& cb); diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index db9b6b78d2..6ea0080f6c 100755 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -509,8 +509,8 @@ LLFloater::~LLFloater() if( gFocusMgr.childHasKeyboardFocus(this)) { - // Just in case we might still have focus here, release it. - releaseFocus(); + // Just in case we might still have focus here, release it. + releaseFocus(); } // This is important so that floaters with persistent rects (i.e., those @@ -1475,6 +1475,7 @@ void LLFloater::moveResizeHandlesToFront() } } +/*virtual*/ BOOL LLFloater::isFrontmost() { LLFloaterView* floater_view = getParentByType<LLFloaterView>(); @@ -1493,7 +1494,7 @@ void LLFloater::addDependentFloater(LLFloater* floaterp, BOOL reposition) floaterp->setRect(gFloaterView->findNeighboringPosition(this, floaterp)); floaterp->setSnapTarget(getHandle()); } - gFloaterView->adjustToFitScreen(floaterp, FALSE); + gFloaterView->adjustToFitScreen(floaterp, FALSE, TRUE); if (floaterp->isFrontmost()) { // make sure to bring self and sibling floaters to front @@ -2724,7 +2725,7 @@ void LLFloaterView::refresh() const S32 FLOATER_MIN_VISIBLE_PIXELS = 16; -void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside) +void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside, BOOL snap_in_toolbars/* = false*/) { if (floater->getParent() != this) { @@ -2777,7 +2778,7 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out } // move window fully onscreen - if (floater->translateIntoRect( gFloaterView->getRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX )) + if (floater->translateIntoRect( snap_in_toolbars ? getSnapRect() : gFloaterView->getRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX )) { floater->clearSnapTarget(); } diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 26ac4a98ad..3482314698 100755 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -262,7 +262,7 @@ public: static bool isVisible(const LLFloater* floater); static bool isMinimized(const LLFloater* floater); BOOL isFirstLook() { return mFirstLook; } // EXT-2653: This function is necessary to prevent overlapping for secondary showed toasts - BOOL isFrontmost(); + virtual BOOL isFrontmost(); BOOL isDependent() { return !mDependeeHandle.isDead(); } void setCanMinimize(BOOL can_minimize); void setCanClose(BOOL can_close); @@ -529,7 +529,7 @@ public: LLRect findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor ); // Given a child of gFloaterView, make sure this view can fit entirely onscreen. - void adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside); + void adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside, BOOL snap_in_toolbars = false); void setMinimizePositionVerticalOffset(S32 offset) { mMinimizePositionVOffset = offset; } void getMinimizePosition( S32 *left, S32 *bottom); diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp index 1cdddf0d5b..b1b75776a7 100755 --- a/indra/llui/llfloaterreg.cpp +++ b/indra/llui/llfloaterreg.cpp @@ -356,8 +356,8 @@ std::string LLFloaterReg::declareRectControl(const std::string& name) { std::string controlname = getRectControlName(name); LLFloater::getControlGroup()->declareRect(controlname, LLRect(), - llformat("Window Size for %s", name.c_str()), - TRUE); + llformat("Window Size for %s", name.c_str()), + LLControlVariable::PERSIST_NONDFT); return controlname; } @@ -367,7 +367,7 @@ std::string LLFloaterReg::declarePosXControl(const std::string& name) LLFloater::getControlGroup()->declareF32(controlname, 10.f, llformat("Window X Position for %s", name.c_str()), - TRUE); + LLControlVariable::PERSIST_NONDFT); return controlname; } @@ -377,7 +377,7 @@ std::string LLFloaterReg::declarePosYControl(const std::string& name) LLFloater::getControlGroup()->declareF32(controlname, 10.f, llformat("Window Y Position for %s", name.c_str()), - TRUE); + LLControlVariable::PERSIST_NONDFT); return controlname; } @@ -404,7 +404,7 @@ std::string LLFloaterReg::declareVisibilityControl(const std::string& name) std::string controlname = getVisibilityControlName(name); LLFloater::getControlGroup()->declareBOOL(controlname, FALSE, llformat("Window Visibility for %s", name.c_str()), - TRUE); + LLControlVariable::PERSIST_NONDFT); return controlname; } @@ -414,7 +414,7 @@ std::string LLFloaterReg::declareDockStateControl(const std::string& name) std::string controlname = getDockStateControlName(name); LLFloater::getControlGroup()->declareBOOL(controlname, TRUE, llformat("Window Docking state for %s", name.c_str()), - TRUE); + LLControlVariable::PERSIST_NONDFT); return controlname; } diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 20eade892d..f32a52e6c6 100755 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -1613,7 +1613,7 @@ void LLFolderView::update() { getFolderViewModel()->getFilter().clearModified(); } - + // automatically show matching items, and select first one if we had a selection if (mNeedsAutoSelect) { @@ -1652,14 +1652,14 @@ void LLFolderView::update() } BOOL is_visible = isInVisibleChain(); - - // Puts folders/items in proper positions + + //Puts folders/items in proper positions // arrange() takes the model filter flag into account and call sort() if necessary (CHUI-849) // It also handles the open/close folder animation - if (is_visible) + if ( is_visible ) { sanitizeSelection(); - if (needsArrange()) + if( needsArrange() ) { S32 height = 0; S32 width = 0; diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 1789f003b9..a1853ca1f7 100755 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -214,7 +214,7 @@ LLNotificationForm::LLNotificationForm(const std::string& name, const LLNotifica } else { - LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Show notification with this name", TRUE); + LLUI::sSettingGroups["ignores"]->declareBOOL(name, show_notification, "Show notification with this name", LLControlVariable::PERSIST_NONDFT); mIgnoreSetting = LLUI::sSettingGroups["ignores"]->getControl(name); } } diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 4adfd42edd..6e03f604a2 100755 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -1183,10 +1183,10 @@ LLScrollListItem* LLScrollListCtrl::addSeparator(EAddPosition pos) // Selects first enabled item of the given name. // Returns false if item not found. // Calls getItemByLabel in order to combine functionality -BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sensitive) +BOOL LLScrollListCtrl::selectItemByLabel(const std::string& label, BOOL case_sensitive, S32 column/* = 0*/) { deselectAllItems(TRUE); // ensure that no stale items are selected, even if we don't find a match - LLScrollListItem* item = getItemByLabel(label, case_sensitive); + LLScrollListItem* item = getItemByLabel(label, case_sensitive, column); bool found = NULL != item; if(found) diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 7bc558f742..c61e281a31 100755 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -241,7 +241,7 @@ public: // one of which can be selected at a time. virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD()); - BOOL selectItemByLabel( const std::string& item, BOOL case_sensitive = TRUE ); // FALSE if item not found + BOOL selectItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 ); // FALSE if item not found BOOL selectItemByPrefix(const std::string& target, BOOL case_sensitive = TRUE); BOOL selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE); LLScrollListItem* getItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 ); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index c2ab01de3a..3c284b3f03 100755 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -180,6 +180,7 @@ LLTextBase::Params::Params() LLTextBase::LLTextBase(const LLTextBase::Params &p) : LLUICtrl(p, LLTextViewModelPtr(new LLTextViewModel)), mURLClickSignal(NULL), + mIsFriendSignal(NULL), mMaxTextByteLength( p.max_text_length ), mFont(p.font), mFontShadow(p.font_shadow), @@ -1854,7 +1855,17 @@ LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index) static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment(); - if (index > getLength()) { return mSegments.end(); } + S32 text_len = 0; + if (!useLabel()) + { + text_len = getLength(); + } + else + { + text_len = mLabel.getWString().length(); + } + + if (index > text_len) { return mSegments.end(); } // when there are no segments, we return the end iterator, which must be checked by caller if (mSegments.size() <= 1) { return mSegments.begin(); } @@ -1870,7 +1881,17 @@ LLTextBase::segment_set_t::const_iterator LLTextBase::getSegIterContaining(S32 i { static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment(); - if (index > getLength()) { return mSegments.end(); } + S32 text_len = 0; + if (!useLabel()) + { + text_len = getLength(); + } + else + { + text_len = mLabel.getWString().length(); + } + + if (index > text_len) { return mSegments.end(); } // when there are no segments, we return the end iterator, which must be checked by caller if (mSegments.size() <= 1) { return mSegments.begin(); } @@ -1920,9 +1941,12 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) registrar.add("Url.OpenInternal", boost::bind(&LLUrlAction::openURLInternal, url)); registrar.add("Url.OpenExternal", boost::bind(&LLUrlAction::openURLExternal, url)); registrar.add("Url.Execute", boost::bind(&LLUrlAction::executeSLURL, url)); + registrar.add("Url.Block", boost::bind(&LLUrlAction::blockObject, url)); registrar.add("Url.Teleport", boost::bind(&LLUrlAction::teleportToLocation, url)); registrar.add("Url.ShowProfile", boost::bind(&LLUrlAction::showProfile, url)); registrar.add("Url.AddFriend", boost::bind(&LLUrlAction::addFriend, url)); + registrar.add("Url.RemoveFriend", boost::bind(&LLUrlAction::removeFriend, url)); + registrar.add("Url.SendIM", boost::bind(&LLUrlAction::sendIM, url)); registrar.add("Url.ShowOnMap", boost::bind(&LLUrlAction::showLocationOnMap, url)); registrar.add("Url.CopyLabel", boost::bind(&LLUrlAction::copyLabelToClipboard, url)); registrar.add("Url.CopyUrl", boost::bind(&LLUrlAction::copyURLToClipboard, url)); @@ -1931,6 +1955,19 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) delete mPopupMenu; mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(xui_file, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if (mIsFriendSignal) + { + bool isFriend = *(*mIsFriendSignal)(LLUUID(LLUrlAction::getUserID(url))); + LLView* addFriendButton = mPopupMenu->getChild<LLView>("add_friend"); + LLView* removeFriendButton = mPopupMenu->getChild<LLView>("remove_friend"); + + if (addFriendButton && removeFriendButton) + { + addFriendButton->setEnabled(!isFriend); + removeFriendButton->setEnabled(isFriend); + } + } + if (mPopupMenu) { mPopupMenu->show(x, y); @@ -2100,7 +2137,7 @@ void LLTextBase::resetLabel() } } -bool LLTextBase::useLabel() +bool LLTextBase::useLabel() const { return !getLength() && !mLabel.empty() && !hasFocus(); } @@ -2911,6 +2948,15 @@ boost::signals2::connection LLTextBase::setURLClickedCallback(const commit_signa return mURLClickSignal->connect(cb); } +boost::signals2::connection LLTextBase::setIsFriendCallback(const is_friend_signal_t::slot_type& cb) +{ + if (!mIsFriendSignal) + { + mIsFriendSignal = new is_friend_signal_t(); + } + return mIsFriendSignal->connect(cb); +} + // // LLTextSegment // @@ -3204,7 +3250,7 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin : LLFontGL::ONLY_WORD_BOUNDARIES; - LLWString offsetString(text.c_str() + segment_offset + mStart); + S32 offsetLength = text.length() - (segment_offset + mStart); if(getLength() < segment_offset + mStart) { @@ -3212,13 +3258,13 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin << segment_offset << "\tmStart:\t" << mStart << "\tsegments\t" << mEditor.mSegments.size() << "\tmax_chars\t" << max_chars << llendl; } - if(offsetString.length() + 1 < max_chars) + if( (offsetLength + 1) < max_chars) { - llinfos << "offsetString.length() + 1 < max_chars\t max_chars:\t" << max_chars << "\toffsetString.length():\t" << offsetString.length() << " getLength() : " + llinfos << "offsetString.length() + 1 < max_chars\t max_chars:\t" << max_chars << "\toffsetLength:\t" << offsetLength << " getLength() : " << getLength() << "\tsegment_offset:\t" << segment_offset << "\tmStart:\t" << mStart << "\tsegments\t" << mEditor.mSegments.size() << llendl; } - S32 num_chars = mStyle->getFont()->maxDrawableChars(offsetString.c_str(), + S32 num_chars = mStyle->getFont()->maxDrawableChars( text.c_str() + (segment_offset + mStart), (F32)num_pixels, max_chars, word_wrap_style); diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 20a73387b5..a74e97cac8 100755 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -258,6 +258,8 @@ public: friend class LLNormalTextSegment; friend class LLUICtrlFactory; + typedef boost::signals2::signal<bool (const LLUUID& user_id)> is_friend_signal_t; + struct LineSpacingParams : public LLInitParam::ChoiceBlock<LineSpacingParams> { Alternative<F32> multiple; @@ -434,6 +436,7 @@ public: virtual void appendImageSegment(const LLStyle::Params& style_params); virtual void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo); boost::signals2::connection setURLClickedCallback(const commit_signal_t::slot_type& cb); + boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb); void setWordWrap(bool wrap); LLScrollContainer* getScrollContainer() const { return mScroller; } @@ -507,7 +510,7 @@ protected: void initFromParams(const Params& p); virtual void beforeValueChange(); virtual void onValueChange(S32 start, S32 end); - virtual bool useLabel(); + virtual bool useLabel() const; // draw methods void drawSelectionBackground(); // draws the black box behind the selected text @@ -648,6 +651,9 @@ protected: // Fired when a URL link is clicked commit_signal_t* mURLClickSignal; + // Used to check if user with given ID is avatar's friend + is_friend_signal_t* mIsFriendSignal; + LLUIString mLabel; // text label that is visible when no user text provided }; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 834f213097..0c16e06109 100755 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1125,7 +1125,8 @@ void LLTextEditor::addChar(llwchar wc) } } -void LLTextEditor::addLineBreakChar() + +void LLTextEditor::addLineBreakChar(BOOL group_together) { if( !getEnabled() ) { @@ -1143,7 +1144,7 @@ void LLTextEditor::addLineBreakChar() LLStyleConstSP sp(new LLStyle(LLStyle::Params())); LLTextSegmentPtr segment = new LLLineBreakTextSegment(sp, mCursorPos); - S32 pos = execute(new TextCmdAddChar(mCursorPos, FALSE, '\n', segment)); + S32 pos = execute(new TextCmdAddChar(mCursorPos, group_together, '\n', segment)); setCursorPos(mCursorPos + pos); } @@ -1484,21 +1485,28 @@ void LLTextEditor::pasteTextWithLinebreaks(LLWString & clean_string) std::basic_string<llwchar>::size_type start = 0; std::basic_string<llwchar>::size_type pos = clean_string.find('\n',start); - while(pos!=-1) + while((pos != -1) && (pos != clean_string.length() -1)) { if(pos!=start) { std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,pos-start); - setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr())); + setCursorPos(mCursorPos + insert(mCursorPos, str, TRUE, LLTextSegmentPtr())); } - addLineBreakChar(); - + addLineBreakChar(TRUE); // Add a line break and group with the next addition. + start = pos+1; pos = clean_string.find('\n',start); } - std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,clean_string.length()-start); - setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr())); + if (pos != start) + { + std::basic_string<llwchar> str = std::basic_string<llwchar>(clean_string,start,clean_string.length()-start); + setCursorPos(mCursorPos + insert(mCursorPos, str, FALSE, LLTextSegmentPtr())); + } + else + { + addLineBreakChar(FALSE); // Add a line break and end the grouping. + } } // copy selection to primary @@ -1964,8 +1972,7 @@ void LLTextEditor::onFocusReceived() updateAllowingLanguageInput(); } -// virtual, from LLView -void LLTextEditor::onFocusLost() +void LLTextEditor::focusLostHelper() { updateAllowingLanguageInput(); @@ -1982,7 +1989,11 @@ void LLTextEditor::onFocusLost() // Make sure cursor is shown again getWindow()->showCursorFromMouseMove(); +} +void LLTextEditor::onFocusLost() +{ + focusLostHelper(); LLTextBase::onFocusLost(); } @@ -2128,12 +2139,17 @@ void LLTextEditor::drawPreeditMarker() continue; } - S32 preedit_left = mVisibleTextRect.mLeft; + line_info& line = mLineInfoList[cur_line]; + LLRect text_rect(line.mRect); + text_rect.mRight = mDocumentView->getRect().getWidth(); // clamp right edge to document extents + text_rect.translate(mDocumentView->getRect().mLeft, mDocumentView->getRect().mBottom); // adjust by scroll position + + S32 preedit_left = text_rect.mLeft; if (left > line_start) { preedit_left += mFont->getWidth(text, line_start, left - line_start); } - S32 preedit_right = mVisibleTextRect.mLeft; + S32 preedit_right = text_rect.mLeft; if (right < line_end) { preedit_right += mFont->getWidth(text, line_start, right - line_start); @@ -2146,18 +2162,18 @@ void LLTextEditor::drawPreeditMarker() if (mPreeditStandouts[i]) { gl_rect_2d(preedit_left + preedit_standout_gap, - line_y + preedit_standout_position, - preedit_right - preedit_standout_gap - 1, - line_y + preedit_standout_position - preedit_standout_thickness, - (mCursorColor.get() * preedit_standout_brightness + mWriteableBgColor.get() * (1 - preedit_standout_brightness)).setAlpha(1.0f)); + text_rect.mBottom + mFont->getDescenderHeight() - 1, + preedit_right - preedit_standout_gap - 1, + text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_standout_thickness, + (mCursorColor.get() * preedit_standout_brightness + mWriteableBgColor.get() * (1 - preedit_standout_brightness)).setAlpha(1.0f)); } else { gl_rect_2d(preedit_left + preedit_marker_gap, - line_y + preedit_marker_position, - preedit_right - preedit_marker_gap - 1, - line_y + preedit_marker_position - preedit_marker_thickness, - (mCursorColor.get() * preedit_marker_brightness + mWriteableBgColor.get() * (1 - preedit_marker_brightness)).setAlpha(1.0f)); + text_rect.mBottom + mFont->getDescenderHeight() - 1, + preedit_right - preedit_marker_gap - 1, + text_rect.mBottom + mFont->getDescenderHeight() - 1 - preedit_marker_thickness, + (mCursorColor.get() * preedit_marker_brightness + mWriteableBgColor.get() * (1 - preedit_marker_brightness)).setAlpha(1.0f)); } } } @@ -2240,12 +2256,13 @@ void LLTextEditor::draw() LLRect clip_rect(mVisibleTextRect); clip_rect.stretch(1); LLLocalClipRect clip(clip_rect); - drawPreeditMarker(); } LLTextBase::draw(); drawLineNumbers(); + drawPreeditMarker(); + //RN: the decision was made to always show the orange border for keyboard focus but do not put an insertion caret // when in readonly mode mBorder->setKeyboardFocusHighlight( hasFocus() );// && !mReadOnly); @@ -2695,14 +2712,20 @@ BOOL LLTextEditor::hasPreeditString() const void LLTextEditor::resetPreedit() { + if (hasSelection()) + { + if (hasPreeditString()) + { + llwarns << "Preedit and selection!" << llendl; + deselect(); + } + else + { + deleteSelection(TRUE); + } + } if (hasPreeditString()) { - if (hasSelection()) - { - llwarns << "Preedit and selection!" << llendl; - deselect(); - } - setCursorPos(mPreeditPositions.front()); removeStringNoUndo(mCursorPos, mPreeditPositions.back() - mCursorPos); insertStringNoUndo(mCursorPos, mPreeditOverwrittenWString); @@ -2750,7 +2773,10 @@ void LLTextEditor::updatePreedit(const LLWString &preedit_string, { mPreeditOverwrittenWString.clear(); } - insertStringNoUndo(insert_preedit_at, mPreeditWString); + + segment_vec_t segments; + //pass empty segments to let "insertStringNoUndo" make new LLNormalTextSegment and insert it, if needed. + insertStringNoUndo(insert_preedit_at, mPreeditWString, &segments); mPreeditStandouts = preedit_standouts; diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 969e072704..32b543ec0e 100755 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -248,13 +248,14 @@ protected: // Undoable operations void addChar(llwchar c); // at mCursorPos S32 addChar(S32 pos, llwchar wc); - void addLineBreakChar(); + void addLineBreakChar(BOOL group_together = FALSE); S32 overwriteChar(S32 pos, llwchar wc); void removeChar(); S32 removeChar(S32 pos); S32 insert(S32 pos, const LLWString &wstr, bool group_with_next_op, LLTextSegmentPtr segment); S32 remove(S32 pos, S32 length, bool group_with_next_op); + void focusLostHelper(); void updateAllowingLanguageInput(); BOOL hasPreeditString() const; diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 3d9f5cbbc2..928e82cb8c 100755 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -381,7 +381,7 @@ bool LLToolBar::stopCommandInProgress(const LLCommandId& commandId) return (command_button != NULL); } -bool LLToolBar::flashCommand(const LLCommandId& commandId, bool flash) +bool LLToolBar::flashCommand(const LLCommandId& commandId, bool flash, bool force_flashing/* = false */) { LLButton * command_button = NULL; @@ -391,7 +391,7 @@ bool LLToolBar::flashCommand(const LLCommandId& commandId, bool flash) if (it != mButtonMap.end()) { command_button = it->second; - command_button->setFlashing(flash ? TRUE : FALSE); + command_button->setFlashing((BOOL)(flash),(BOOL)(force_flashing)); } } diff --git a/indra/llui/lltoolbar.h b/indra/llui/lltoolbar.h index 31424a36d4..743951a41f 100755 --- a/indra/llui/lltoolbar.h +++ b/indra/llui/lltoolbar.h @@ -192,7 +192,7 @@ public: bool hasCommand(const LLCommandId& commandId) const; // is this command bound to a button in this toolbar bool enableCommand(const LLCommandId& commandId, bool enabled); // enable/disable button bound to the specified command, if it exists in this toolbar bool stopCommandInProgress(const LLCommandId& commandId); // stop command if it is currently active - bool flashCommand(const LLCommandId& commandId, bool flash); // flash button associated with given command, if in this toolbar + bool flashCommand(const LLCommandId& commandId, bool flash, bool force_flashing = false); // flash button associated with given command, if in this toolbar void setStartDragCallback(tool_startdrag_callback_t cb) { mStartDragItemCallback = cb; } // connects drag and drop behavior to external logic void setHandleDragCallback(tool_handledrag_callback_t cb) { mHandleDragItemCallback = cb; } diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp index f51aeaec13..23e574cb74 100755 --- a/indra/llui/llurlaction.cpp +++ b/indra/llui/llurlaction.cpp @@ -170,6 +170,30 @@ std::string LLUrlAction::getUserID(std::string url) return id_str; } +std::string LLUrlAction::getObjectId(std::string url) +{ + LLURI uri(url); + LLSD path_array = uri.pathArray(); + std::string id_str; + if (path_array.size() >= 3) + { + id_str = path_array.get(2).asString(); + } + return id_str; +} + +std::string LLUrlAction::getObjectName(std::string url) +{ + LLURI uri(url); + LLSD query_map = uri.queryMap(); + std::string name; + if (query_map.has("name")) + { + name = query_map["name"].asString(); + } + return name; +} + void LLUrlAction::sendIM(std::string url) { std::string id_str = getUserID(url); @@ -188,3 +212,21 @@ void LLUrlAction::addFriend(std::string url) } } +void LLUrlAction::removeFriend(std::string url) +{ + std::string id_str = getUserID(url); + if (LLUUID::validate(id_str)) + { + executeSLURL("secondlife:///app/agent/" + id_str + "/removefriend"); + } +} + +void LLUrlAction::blockObject(std::string url) +{ + std::string object_id = getObjectId(url); + std::string object_name = getObjectName(url); + if (LLUUID::validate(object_id)) + { + executeSLURL("secondlife:///app/agent/" + object_id + "/block/" + object_name); + } +} diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h index e31cd71a20..e731376b95 100755 --- a/indra/llui/llurlaction.h +++ b/indra/llui/llurlaction.h @@ -77,8 +77,12 @@ public: /// if the Url specifies an SL command in the form like 'app/{cmd}/{id}/*', show its profile static void showProfile(std::string url); static std::string getUserID(std::string url); + static std::string getObjectName(std::string url); + static std::string getObjectId(std::string url); static void sendIM(std::string url); static void addFriend(std::string url); + static void removeFriend(std::string url); + static void blockObject(std::string url); /// specify the callbacks to enable this class's functionality typedef boost::function<void (const std::string&)> url_callback_t; diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index 99ee688888..b1cc502c4b 100755 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -504,6 +504,10 @@ std::string localize_slapp_label(const std::string& url, const std::string& full { return LLTrans::getString("SLappAgentRequestFriend") + " " + full_name; } + if (LLStringUtil::endsWith(url, "/removefriend")) + { + return LLTrans::getString("SLappAgentRemoveFriend") + " " + full_name; + } return full_name; } diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index cc10ed5bbd..e02bf552aa 100755 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -32,7 +32,7 @@ #define MAX_PATH MAXPATHLEN #endif -// these numbers *may* get serialized (really??), so we need to be explicit +// these numbers are read from settings_files.xml, so we need to be explicit typedef enum ELLPath { LL_PATH_NONE = 0, diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index ca9410de2e..30f5526500 100755 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -3499,19 +3499,11 @@ void LLWindowWin32::updateLanguageTextInputArea() void LLWindowWin32::interruptLanguageTextInput() { - if (mPreeditor) + if (mPreeditor && LLWinImm::isAvailable()) { - if (LLWinImm::isAvailable()) - { - HIMC himc = LLWinImm::getContext(mWindowHandle); - LLWinImm::notifyIME(himc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); - LLWinImm::releaseContext(mWindowHandle, himc); - } - - // Win32 document says there will be no composition string - // after NI_COMPOSITIONSTR returns. The following call to - // resetPreedit should be a NOP unless IME goes mad... - mPreeditor->resetPreedit(); + HIMC himc = LLWinImm::getContext(mWindowHandle); + LLWinImm::notifyIME(himc, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); + LLWinImm::releaseContext(mWindowHandle, himc); } } diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 666c03e9ff..16f2290787 100755 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -132,14 +132,14 @@ bool LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b) LLControlVariable::LLControlVariable(const std::string& name, eControlType type, LLSD initial, const std::string& comment, - bool persist, bool hidefromsettingseditor) + ePersist persist, bool hidefromsettingseditor) : mName(name), mComment(comment), mType(type), mPersist(persist), mHideFromSettingsEditor(hidefromsettingseditor) { - if (mPersist && mComment.empty()) + if ((persist != PERSIST_NO) && mComment.empty()) { llerrs << "Must supply a comment for control " << mName << llendl; } @@ -260,7 +260,7 @@ void LLControlVariable::setDefaultValue(const LLSD& value) } } -void LLControlVariable::setPersist(bool state) +void LLControlVariable::setPersist(ePersist state) { mPersist = state; } @@ -292,10 +292,29 @@ void LLControlVariable::resetToDefault(bool fire_signal) } } -bool LLControlVariable::isSaveValueDefault() -{ - return (mValues.size() == 1) - || ((mValues.size() > 1) && llsd_compare(mValues[1], mValues[0])); +bool LLControlVariable::shouldSave(bool nondefault_only) +{ + // This method is used to decide whether we should save a given + // variable. Two of the three values of mPersist are easy. + if (mPersist == PERSIST_NO) + return false; + + if (mPersist == PERSIST_ALWAYS) + return true; + + // PERSIST_NONDFT + // If caller doesn't need us to filter, just save. + if (! nondefault_only) + return true; + + // PERSIST_NONDFT: caller only wants us to save this variable if its value + // differs from default. + if (isDefault()) // never been altered + return false; + + // We've set at least one other value: compare it to default. Save only if + // they differ. + return ! llsd_compare(getSaveValue(), getDefault()); } LLSD LLControlVariable::getSaveValue() const @@ -355,12 +374,12 @@ std::string LLControlGroup::typeEnumToString(eControlType typeenum) return mTypeString[typeenum]; } -BOOL LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor) +LLControlVariable* LLControlGroup::declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, LLControlVariable::ePersist persist, BOOL hidefromsettingseditor) { LLControlVariable* existing_control = getControl(name); if (existing_control) { - if (persist && existing_control->isType(type)) + if ((persist != LLControlVariable::PERSIST_NO) && existing_control->isType(type)) { if (!existing_control->llsd_compare(existing_control->getDefault(), initial_val)) { @@ -374,66 +393,66 @@ BOOL LLControlGroup::declareControl(const std::string& name, eControlType type, { llwarns << "Control named " << name << " already exists, ignoring new declaration." << llendl; } - return TRUE; + return existing_control; } // if not, create the control and add it to the name table LLControlVariable* control = new LLControlVariable(name, type, initial_val, comment, persist, hidefromsettingseditor); mNameTable[name] = control; - return TRUE; + return control; } -BOOL LLControlGroup::declareU32(const std::string& name, const U32 initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareU32(const std::string& name, const U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return declareControl(name, TYPE_U32, (LLSD::Integer) initial_val, comment, persist); } -BOOL LLControlGroup::declareS32(const std::string& name, const S32 initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareS32(const std::string& name, const S32 initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return declareControl(name, TYPE_S32, initial_val, comment, persist); } -BOOL LLControlGroup::declareF32(const std::string& name, const F32 initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareF32(const std::string& name, const F32 initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return declareControl(name, TYPE_F32, initial_val, comment, persist); } -BOOL LLControlGroup::declareBOOL(const std::string& name, const BOOL initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareBOOL(const std::string& name, const BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return declareControl(name, TYPE_BOOLEAN, initial_val, comment, persist); } -BOOL LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return declareControl(name, TYPE_STRING, initial_val, comment, persist); } -BOOL LLControlGroup::declareVec3(const std::string& name, const LLVector3 &initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareVec3(const std::string& name, const LLVector3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return declareControl(name, TYPE_VEC3, initial_val.getValue(), comment, persist); } -BOOL LLControlGroup::declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return declareControl(name, TYPE_VEC3D, initial_val.getValue(), comment, persist); } -BOOL LLControlGroup::declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return declareControl(name, TYPE_RECT, initial_val.getValue(), comment, persist); } -BOOL LLControlGroup::declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist ) +LLControlVariable* LLControlGroup::declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, LLControlVariable::ePersist persist ) { return declareControl(name, TYPE_COL4, initial_val.getValue(), comment, persist); } -BOOL LLControlGroup::declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, BOOL persist ) +LLControlVariable* LLControlGroup::declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist ) { return declareControl(name, TYPE_COL3, initial_val.getValue(), comment, persist); } -BOOL LLControlGroup::declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, BOOL persist ) +LLControlVariable* LLControlGroup::declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, LLControlVariable::ePersist persist ) { return declareControl(name, TYPE_LLSD, initial_val, comment, persist); } @@ -664,11 +683,11 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require switch(declare_as) { case TYPE_COL4: - declareColor4(name, LLColor4::white, LLStringUtil::null, NO_PERSIST); + declareColor4(name, LLColor4::white, LLStringUtil::null, LLControlVariable::PERSIST_NO); break; case TYPE_STRING: default: - declareString(name, LLStringUtil::null, LLStringUtil::null, NO_PERSIST); + declareString(name, LLStringUtil::null, LLStringUtil::null, LLControlVariable::PERSIST_NO); break; } } @@ -805,21 +824,12 @@ U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only { llwarns << "Tried to save invalid control: " << iter->first << llendl; } - - if( control && control->isPersisted() ) + else if( control->shouldSave(nondefault_only) ) { - if (!(nondefault_only && (control->isSaveValueDefault()))) - { - settings[iter->first]["Type"] = typeEnumToString(control->type()); - settings[iter->first]["Comment"] = control->getComment(); - settings[iter->first]["Value"] = control->getSaveValue(); - ++num_saved; - } - else - { - // Debug spam - // llinfos << "Skipping " << control->getName() << llendl; - } + settings[iter->first]["Type"] = typeEnumToString(control->type()); + settings[iter->first]["Comment"] = control->getComment(); + settings[iter->first]["Value"] = control->getSaveValue(); + ++num_saved; } } llofstream file; @@ -862,13 +872,14 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr) { - bool persist = true; + LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT; std::string const & name = itr->first; LLSD const & control_map = itr->second; if(control_map.has("Persist")) { - persist = control_map["Persist"].asInteger(); + persist = control_map["Persist"].asInteger()? + LLControlVariable::PERSIST_NONDFT : LLControlVariable::PERSIST_NO; } // Sometimes we want to use the settings system to provide cheap persistence, but we @@ -887,6 +898,8 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v LLControlVariable* existing_control = getControl(name); if(existing_control) { + // set_default_values is true when we're loading the initial, + // immutable files from app_settings, e.g. settings.xml. if(set_default_values) { // Override all previously set properties of this control. @@ -908,6 +921,9 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v } else if(existing_control->isPersisted()) { + // save_values is specifically false for (e.g.) + // SessionSettingsFile and UserSessionSettingsFile -- in other + // words, for a file that's supposed to be transient. existing_control->setValue(control_map["Value"], save_values); } // *NOTE: If not persisted and not setting defaults, @@ -915,6 +931,39 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v } else { + // We've never seen this control before. Either we're loading up + // the initial set of default settings files (set_default_values) + // -- or we're loading user settings last saved by a viewer that + // supports a superset of the variables we know. + // CHOP-962: if we're loading an unrecognized user setting, make + // sure we save it later. If you try an experimental viewer, tweak + // a new setting, briefly revert to an old viewer, then return to + // the new one, we don't want the old viewer to discard the + // setting you changed. + if (! set_default_values) + { + // Using PERSIST_ALWAYS insists that saveToFile() (which calls + // LLControlVariable::shouldSave()) must save this control + // variable regardless of its value. We can safely set this + // LLControlVariable persistent because the 'persistent' flag + // is not itself persisted! + persist = LLControlVariable::PERSIST_ALWAYS; + // We want to mention unrecognized user settings variables + // (e.g. from a newer version of the viewer) in the log. But + // we also arrive here for Boolean variables generated by + // the notifications subsystem when the user checks "Don't + // show me this again." These aren't declared in settings.xml; + // they're actually named for the notification they suppress. + // We don't want to mention those. Apologies, this is a bit of + // a hack: we happen to know that user settings go into an + // LLControlGroup whose name is "Global". + if (getKey() == "Global") + { + LL_INFOS("LLControlGroup") << "preserving unrecognized " << getKey() + << " settings variable " << name << LL_ENDL; + } + } + declareControl(name, typeStringToEnum(control_map["Type"].asString()), control_map["Value"], @@ -923,7 +972,7 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v hidefromsettingseditor ); } - + ++validitems; } diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index ee7d1d50b7..e1f9be80dd 100755 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -72,8 +72,6 @@ class LLVector3d; class LLColor4; class LLColor3; -const BOOL NO_PERSIST = FALSE; - typedef enum e_control_type { TYPE_U32 = 0, @@ -100,21 +98,28 @@ public: typedef boost::signals2::signal<bool(LLControlVariable* control, const LLSD&), boost_boolean_combiner> validate_signal_t; typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&, const LLSD&)> commit_signal_t; + enum ePersist + { + PERSIST_NO, // don't save this var + PERSIST_NONDFT, // save this var if differs from default + PERSIST_ALWAYS // save this var even if has default value + }; + private: std::string mName; std::string mComment; eControlType mType; - bool mPersist; + ePersist mPersist; bool mHideFromSettingsEditor; std::vector<LLSD> mValues; - + commit_signal_t mCommitSignal; validate_signal_t mValidateSignal; public: LLControlVariable(const std::string& name, eControlType type, LLSD initial, const std::string& comment, - bool persist = true, bool hidefromsettingseditor = false); + ePersist persist = PERSIST_NONDFT, bool hidefromsettingseditor = false); virtual ~LLControlVariable(); @@ -131,8 +136,8 @@ public: validate_signal_t* getValidateSignal() { return &mValidateSignal; } bool isDefault() { return (mValues.size() == 1); } - bool isSaveValueDefault(); - bool isPersisted() { return mPersist; } + bool shouldSave(bool nondefault_only); + bool isPersisted() { return mPersist != PERSIST_NO; } bool isHiddenFromSettingsEditor() { return mHideFromSettingsEditor; } LLSD get() const { return getValue(); } LLSD getValue() const { return mValues.back(); } @@ -142,7 +147,7 @@ public: void set(const LLSD& val) { setValue(val); } void setValue(const LLSD& value, bool saved_value = TRUE); void setDefaultValue(const LLSD& value); - void setPersist(bool state); + void setPersist(ePersist); void setHiddenFromSettingsEditor(bool hide); void setComment(const std::string& comment); @@ -207,19 +212,19 @@ public: virtual void apply(const std::string& name, LLControlVariable* control) = 0; }; void applyToAll(ApplyFunctor* func); - - BOOL declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor = FALSE); - BOOL declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist = TRUE); - BOOL declareS32(const std::string& name, S32 initial_val, const std::string& comment, BOOL persist = TRUE); - BOOL declareF32(const std::string& name, F32 initial_val, const std::string& comment, BOOL persist = TRUE); - BOOL declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist = TRUE); - BOOL declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist = TRUE); - BOOL declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment, BOOL persist = TRUE); - BOOL declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, BOOL persist = TRUE); - BOOL declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, BOOL persist = TRUE); - BOOL declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist = TRUE); - BOOL declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, BOOL persist = TRUE); - BOOL declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, BOOL persist = TRUE); + + LLControlVariable* declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, LLControlVariable::ePersist persist, BOOL hidefromsettingseditor = FALSE); + LLControlVariable* declareU32(const std::string& name, U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); + LLControlVariable* declareS32(const std::string& name, S32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); + LLControlVariable* declareF32(const std::string& name, F32 initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); + LLControlVariable* declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); + LLControlVariable* declareString(const std::string& name, const std::string &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); + LLControlVariable* declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); + LLControlVariable* declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); + LLControlVariable* declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); + LLControlVariable* declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); + LLControlVariable* declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); + LLControlVariable* declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, LLControlVariable::ePersist persist = LLControlVariable::PERSIST_NONDFT); std::string getString(const std::string& name); std::string getText(const std::string& name); @@ -368,7 +373,7 @@ private: init_value = convert_to_llsd(default_value); if(type < TYPE_COUNT) { - group.declareControl(name, type, init_value, comment, FALSE); + group.declareControl(name, type, init_value, comment, LLControlVariable::PERSIST_NO); return true; } return false; diff --git a/indra/llxml/tests/llcontrol_test.cpp b/indra/llxml/tests/llcontrol_test.cpp index ede81956ec..c273773c9b 100755 --- a/indra/llxml/tests/llcontrol_test.cpp +++ b/indra/llxml/tests/llcontrol_test.cpp @@ -128,7 +128,11 @@ namespace tut template<> template<> void control_group_t::test<3>() { - int results = mCG->loadFromFile(mTestConfigFile.c_str()); + // Pass default_values = true. This tells loadFromFile() we're loading + // a default settings file that declares variables, rather than a user + // settings file. When loadFromFile() encounters an unrecognized user + // settings variable, it forcibly preserves it (CHOP-962). + int results = mCG->loadFromFile(mTestConfigFile.c_str(), true); LLControlVariable* control = mCG->getControl("TestSetting"); LLSD new_value = 13; control->setValue(new_value, FALSE); diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 2a969e0d40..22ebcf7cae 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -230,6 +230,7 @@ set(viewer_SOURCE_FILES llfloaterfonttest.cpp llfloatergesture.cpp llfloatergodtools.cpp + llfloatergotoline.cpp llfloatergroupinvite.cpp llfloatergroups.cpp llfloaterhandler.cpp @@ -816,6 +817,7 @@ set(viewer_HEADER_FILES llfloaterfonttest.h llfloatergesture.h llfloatergodtools.h + llfloatergotoline.h llfloatergroupinvite.h llfloatergroups.h llfloaterhandler.h diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 0f44168a4d..d15b8b06fa 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -3.6.4 +3.6.5 diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index 7ab7787d77..a9f6079630 100755 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -22,7 +22,8 @@ <map> <key>count</key> <integer>1</integer> - <!-- Special case. Not mapped to a setting. --> + <key>map-to</key> + <string>CmdLineChannel</string> </map> <key>console</key> @@ -96,6 +97,8 @@ 0 - low, 1 - medium, 2 - high, 3 - ultra</string> <key>count</key> <integer>1</integer> + <key>map-to</key> + <string>RenderQualityPerformance</string> </map> <key>grid</key> @@ -108,6 +111,16 @@ <string>CmdLineGridChoice</string> </map> + <key>update-service</key> + <map> + <key>desc</key> + <string>Override the url base for the update query.</string> + <key>count</key> + <integer>1</integer> + <key>map-to</key> + <string>CmdLineUpdateService</string> + </map> + <key>help</key> <map> <key>desc</key> @@ -370,7 +383,8 @@ <boolean>true</boolean> <key>last_option</key> <boolean>true</boolean> - <!-- Special case. Not mapped to a setting. --> + <key>map-to</key> + <string>CmdLineLoginLocation</string> </map> <key>url</key> @@ -381,7 +395,8 @@ <integer>1</integer> <key>last_option</key> <boolean>true</boolean> - <!-- Special case. Not mapped to a setting. --> + <key>map-to</key> + <string>CmdLineLoginLocation</string> </map> <key>usersessionsettings</key> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 7d6fb6c061..098693eb98 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -126,6 +126,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>AnalyzePerformance</key> + <map> + <key>Comment</key> + <string>Request performance analysis for a particular viewer run</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>AnimateTextures</key> <map> <key>Comment</key> @@ -1738,6 +1749,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>CmdLineChannel</key> + <map> + <key>Comment</key> + <string>Command line specified channel name</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string /> + </map> <key>CmdLineDisableVoice</key> <map> <key>Comment</key> @@ -1760,6 +1782,17 @@ <key>Value</key> <string /> </map> + <key>CmdLineUpdateService</key> + <map> + <key>Comment</key> + <string>Override the url base for the update query.</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string /> + </map> <key>CmdLineHelperURI</key> <map> <key>Comment</key> @@ -1784,6 +1817,17 @@ <string /> </array> </map> + <key>CmdLineLoginLocation</key> + <map> + <key>Comment</key> + <string>Startup destination requested on command line</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string/> + </map> <key>ConnectAsGod</key> <map> <key>Comment</key> @@ -1916,6 +1960,17 @@ <key>Value</key> <integer>262144</integer> </map> + <key>CrashOnStartup</key> + <map> + <key>Comment</key> + <string>User-requested crash on viewer startup</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>CreateToolCopyCenters</key> <map> <key>Comment</key> @@ -2158,6 +2213,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>DebugSession</key> + <map> + <key>Comment</key> + <string>Request debugging for a particular viewer session</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>DebugShowColor</key> <map> <key>Comment</key> @@ -2972,6 +3038,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>DisableCrashLogger</key> + <map> + <key>Comment</key> + <string>Do not send crash report to Linden server</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>DisableMouseWarp</key> <map> <key>Comment</key> @@ -5239,6 +5316,28 @@ <key>Value</key> <integer>0</integer> </map> + <key>LogMetrics</key> + <map> + <key>Comment</key> + <string>Log viewer metrics</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string/> + </map> + <key>LogPerformance</key> + <map> + <key>Comment</key> + <string>Log performance analysis for a particular viewer run</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>LogTextureNetworkTraffic</key> <map> <key>Comment</key> @@ -6416,6 +6515,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>NoQuickTime</key> + <map> + <key>Comment</key> + <string>Disable QuickTime for a particular viewer run</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>NoVerifySSLCert</key> <map> <key>Comment</key> @@ -6452,7 +6562,10 @@ <key>NotificationConferenceIMOptions</key> <map> <key>Comment</key> - <string>Specifies how the UI responds to Conference IM Notifications.</string> + <string> + Specifies how the UI responds to Conference IM Notifications. + Allowed values: [openconversations,toast,flash,noaction] + </string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -6463,7 +6576,10 @@ <key>NotificationFriendIMOptions</key> <map> <key>Comment</key> - <string>Specifies how the UI responds to Friend IM Notifications.</string> + <string> + Specifies how the UI responds to Friend IM Notifications. + Allowed values: [openconversations,toast,flash,noaction] + </string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -6474,7 +6590,10 @@ <key>NotificationGroupChatOptions</key> <map> <key>Comment</key> - <string>Specifies how the UI responds to Group Chat Notifications.</string> + <string> + Specifies how the UI responds to Group Chat Notifications. + Allowed values: [openconversations,toast,flash,noaction] + </string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -6485,7 +6604,10 @@ <key>NotificationNearbyChatOptions</key> <map> <key>Comment</key> - <string>Specifies how the UI responds to Nearby Chat Notifications.</string> + <string> + Specifies how the UI responds to Nearby Chat Notifications. + Allowed values: [openconversations,toast,flash,noaction] + </string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -6496,7 +6618,24 @@ <key>NotificationNonFriendIMOptions</key> <map> <key>Comment</key> - <string>Specifies how the UI responds to Non Friend IM Notifications.</string> + <string> + Specifies how the UI responds to Non Friend IM Notifications. + Allowed values: [openconversations,toast,flash,noaction] + </string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string>toast</string> + </map> + <key>NotificationObjectIMOptions</key> + <map> + <key>Comment</key> + <string> + Specifies how the UI responds to Object IM Notifications. + Allowed values: [openconversations,toast,flash,noaction] + </string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -7009,6 +7148,17 @@ <key>Value</key> <real>90.0</real> </map> + <key>PlayChatAnim</key> + <map> + <key>Comment</key> + <string>Your avatar plays the chat animation whenever you say, shout or whisper something in nearby chat</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>PlayTypingAnim</key> <map> <key>Comment</key> @@ -7042,6 +7192,72 @@ <key>Value</key> <integer>0</integer> </map> + <key>PlaySoundFriendIM</key> + <map> + <key>Comment</key> + <string>Plays a sound when friend's IM received.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>PlaySoundNonFriendIM</key> + <map> + <key>Comment</key> + <string>Plays a sound when non-friend's IM received.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>PlaySoundConferenceIM</key> + <map> + <key>Comment</key> + <string>Plays a sound when conference IM received.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>PlaySoundGroupChatIM</key> + <map> + <key>Comment</key> + <string>Plays a sound when group chat IM received.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>PlaySoundNearbyChatIM</key> + <map> + <key>Comment</key> + <string>Plays a sound when nearby chat IM received.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>PlaySoundObjectIM</key> + <map> + <key>Comment</key> + <string>Plays a sound when IM fom an object received.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>PlaySoundNewConversation</key> <map> <key>Comment</key> @@ -9676,6 +9892,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>ReplaySession</key> + <map> + <key>Comment</key> + <string>Request replay of previously-recorded pilot file</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>RotateRight</key> <map> <key>Comment</key> @@ -12903,12 +13130,13 @@ <key>UserLoginInfo</key> <map> <key>Comment</key> - <string>Users loging data.</string> + <string>User login data.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> <string>LLSD</string> <key>Value</key> + <string/> </map> <key>VFSOldSize</key> <map> diff --git a/indra/newview/app_settings/settings_files.xml b/indra/newview/app_settings/settings_files.xml index bfc09286e3..4a9e522a96 100755 --- a/indra/newview/app_settings/settings_files.xml +++ b/indra/newview/app_settings/settings_files.xml @@ -4,6 +4,9 @@ <file name="Global" file_name="settings.xml" required="true"/> + <file name="Global" + file_name="settings_install.xml" + required="false"/> <file name="PerAccount" file_name="settings_per_account.xml" required="true"/> diff --git a/indra/newview/app_settings/settings_minimal.xml b/indra/newview/app_settings/settings_minimal.xml index 01a70f2671..e660c1a33b 100755 --- a/indra/newview/app_settings/settings_minimal.xml +++ b/indra/newview/app_settings/settings_minimal.xml @@ -1 +1,4 @@ -<llsd/>
\ No newline at end of file +<?xml version="1.0"?> +<llsd> + <undef/> +</llsd> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 590f41283b..636caf5ef3 100755 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -109,18 +109,7 @@ <string>Boolean</string> <key>Value</key> <integer>0</integer> - </map> - <key>DisplayDestinationsOnInitialRun</key> - <map> - <key>Comment</key> - <string>Display the destinations guide when a user first launches Second Life.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>1</integer> - </map> + </map> <key>LastInventoryInboxActivity</key> <map> <key>Comment</key> diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index d8440eebf1..c23401d5a6 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -121,37 +121,21 @@ export SAVED_LD_LIBRARY_PATH="${LD_LIBRARY_PATH}" export LD_LIBRARY_PATH="$PWD/lib:${LD_LIBRARY_PATH}" -# Have to deal specially with gridargs.dat; typical contents look like: -# --channel "Second Life Test" --settings settings_test.xml -# Simply embedding $(<etc/gridargs.dat) into a command line treats each of -# Second, Life and Developer as separate args -- no good. We need bash to -# process quotes using eval. -# First, check if we have been instructed to skip reading in gridargs.dat: -skip_gridargs=false -argnum=0 +# Copy "$@" to ARGS array specifically to delete the --skip-gridargs switch. +# The gridargs.dat file is no more, but we still want to avoid breaking +# scripts that invoke this one with --skip-gridargs. +ARGS=() for ARG in "$@"; do - if [ "--skip-gridargs" == "$ARG" ]; then - skip_gridargs=true - else - ARGS[$argnum]="$ARG" - argnum=$(($argnum+1)) + if [ "--skip-gridargs" != "$ARG" ]; then + ARGS[${#ARGS[*]}]="$ARG" fi done -# Second, read it without scanning, then scan that string. Break quoted words -# into a bash array. Note that if gridargs.dat is empty, or contains only -# whitespace, the resulting gridargs array will be empty -- zero entries -- -# therefore "${gridargs[@]}" entirely vanishes from the command line below, -# just as we want. -if ! $skip_gridargs ; then - eval gridargs=("$(<etc/gridargs.dat)") -fi - # Run the program. # Don't quote $LL_WRAPPER because, if empty, it should simply vanish from the -# command line. But DO quote "$@": preserve separate args as individually -# quoted. Similar remarks about the contents of gridargs. -$LL_WRAPPER bin/do-not-directly-run-secondlife-bin "${gridargs[@]}" "${ARGS[@]}" +# command line. But DO quote "${ARGS[@]}": preserve separate args as +# individually quoted. +$LL_WRAPPER bin/do-not-directly-run-secondlife-bin "${ARGS[@]}" LL_RUN_ERR=$? # Handle any resulting errors diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index f960b31cc7..f4ce3c9118 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -435,7 +435,7 @@ void LLAgent::init() { mMoveTimer.start(); - gSavedSettings.declareBOOL("SlowMotionAnimation", FALSE, "Declared in code", FALSE); + gSavedSettings.declareBOOL("SlowMotionAnimation", FALSE, "Declared in code", LLControlVariable::PERSIST_NO); gSavedSettings.getControl("SlowMotionAnimation")->getSignal()->connect(boost::bind(&handleSlowMotionAnimation, _2)); // *Note: this is where LLViewerCamera::getInstance() used to be constructed. diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index fe357ed8b3..08ea7907b9 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -668,7 +668,6 @@ LLAppViewer::LLAppViewer() : mSecondInstance(false), mSavedFinalSnapshot(false), mSavePerAccountSettings(false), // don't save settings on logout unless login succeeded. - mForceGraphicsDetail(false), mQuitRequested(false), mLogoutRequestSent(false), mYieldTime(-1), @@ -2307,17 +2306,24 @@ void LLAppViewer::loadColorSettings() LLUIColorTable::instance().loadFromSettings(); } +namespace +{ + void handleCommandLineError(LLControlGroupCLP& clp) + { + llwarns << "Error parsing command line options. Command Line options ignored." << llendl; + + llinfos << "Command line usage:\n" << clp << llendl; + + OSMessageBox(STRINGIZE(LLTrans::getString("MBCmdLineError") << clp.getErrorMessage()), + LLStringUtil::null, + OSMB_OK); + } +} // anonymous namespace + bool LLAppViewer::initConfiguration() { //Load settings files list std::string settings_file_list = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "settings_files.xml"); - //LLControlGroup settings_control("SettingsFiles"); - //llinfos << "Loading settings file list " << settings_file_list << llendl; - //if (0 == settings_control.loadFromFile(settings_file_list)) - //{ - // llerrs << "Cannot load default configuration file " << settings_file_list << llendl; - //} - LLXMLNodePtr root; BOOL success = LLXMLNode::parseFile(settings_file_list, root, NULL); if (!success) @@ -2376,9 +2382,7 @@ bool LLAppViewer::initConfiguration() { c->setValue(true, false); } -#endif -#ifndef LL_RELEASE_FOR_DOWNLOAD gSavedSettings.setBOOL("QAMode", TRUE ); gSavedSettings.setS32("WatchdogEnabled", 0); #endif @@ -2414,13 +2418,7 @@ bool LLAppViewer::initConfiguration() if(!initParseCommandLine(clp)) { - llwarns << "Error parsing command line options. Command Line options ignored." << llendl; - - llinfos << "Command line usage:\n" << clp << llendl; - - std::ostringstream msg; - msg << LLTrans::getString("MBCmdLineError") << clp.getErrorMessage(); - OSMessageBox(msg.str(),LLStringUtil::null,OSMB_OK); + handleCommandLineError(clp); return false; } @@ -2467,12 +2465,16 @@ bool LLAppViewer::initConfiguration() loadSettingsFromDirectory("UserSession"); // - apply command line settings - clp.notify(); + if (! clp.notify()) + { + handleCommandLineError(clp); + return false; + } // Register the core crash option as soon as we can // if we want gdb post-mortem on cores we need to be up and running // ASAP or we might miss init issue etc. - if(clp.hasOption("disablecrashlogger")) + if(gSavedSettings.getBOOL("DisableCrashLogger")) { llwarns << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << llendl; LLAppViewer::instance()->disableCrashlogger(); @@ -2545,91 +2547,52 @@ bool LLAppViewer::initConfiguration() } } - if(clp.hasOption("channel")) + std::string CmdLineChannel(gSavedSettings.getString("CmdLineChannel")); + if(! CmdLineChannel.empty()) { - LLVersionInfo::resetChannel(clp.getOption("channel")[0]); + LLVersionInfo::resetChannel(CmdLineChannel); } // If we have specified crash on startup, set the global so we'll trigger the crash at the right time - if(clp.hasOption("crashonstartup")) - { - gCrashOnStartup = TRUE; - } + gCrashOnStartup = gSavedSettings.getBOOL("CrashOnStartup"); - if (clp.hasOption("logperformance")) + if (gSavedSettings.getBOOL("LogPerformance")) { LLFastTimer::sLog = TRUE; LLFastTimer::sLogName = std::string("performance"); } - if (clp.hasOption("logmetrics")) + std::string test_name(gSavedSettings.getString("LogMetrics")); + if (! test_name.empty()) { LLFastTimer::sMetricLog = TRUE ; - // '--logmetrics' can be specified with a named test metric argument so the data gathering is done only on that test - // In the absence of argument, every metric is gathered (makes for a rather slow run and hard to decipher report...) - std::string test_name = clp.getOption("logmetrics")[0]; + // '--logmetrics' is specified with a named test metric argument so the data gathering is done only on that test + // In the absence of argument, every metric would be gathered (makes for a rather slow run and hard to decipher report...) llinfos << "'--logmetrics' argument : " << test_name << llendl; - if (test_name == "") - { - llwarns << "No '--logmetrics' argument given, will output all metrics to " << DEFAULT_METRIC_NAME << llendl; - LLFastTimer::sLogName = DEFAULT_METRIC_NAME; - } - else - { LLFastTimer::sLogName = test_name; } - } if (clp.hasOption("graphicslevel")) { - const LLCommandLineParser::token_vector_t& value = clp.getOption("graphicslevel"); - if(value.size() != 1) + // User explicitly requested --graphicslevel on the command line. We + // expect this switch has already set RenderQualityPerformance. Check + // that value for validity. + U32 graphicslevel = gSavedSettings.getU32("RenderQualityPerformance"); + if (LLFeatureManager::instance().isValidGraphicsLevel(graphicslevel)) { - llwarns << "Usage: -graphicslevel <0-3>" << llendl; - } - else - { - std::string detail = value.front(); - mForceGraphicsDetail = TRUE; - - switch (detail.c_str()[0]) - { - case '0': - gSavedSettings.setU32("RenderQualityPerformance", 0); - break; - case '1': - gSavedSettings.setU32("RenderQualityPerformance", 1); - break; - case '2': - gSavedSettings.setU32("RenderQualityPerformance", 2); - break; - case '3': - gSavedSettings.setU32("RenderQualityPerformance", 3); - break; - default: - mForceGraphicsDetail = FALSE; - llwarns << "Usage: -graphicslevel <0-3>" << llendl; - break; - } + // graphicslevel is valid: save it and engage it later. Capture + // the requested value separately from the settings variable + // because, if this is the first run, LLViewerWindow's constructor + // will call LLFeatureManager::applyRecommendedSettings(), which + // overwrites this settings variable! + mForceGraphicsLevel = graphicslevel; } } - if (clp.hasOption("analyzeperformance")) - { - LLFastTimerView::sAnalyzePerformance = TRUE; - } - - if (clp.hasOption("replaysession")) - { - gAgentPilot.setReplaySession(TRUE); - } + LLFastTimerView::sAnalyzePerformance = gSavedSettings.getBOOL("AnalyzePerformance"); + gAgentPilot.setReplaySession(gSavedSettings.getBOOL("ReplaySession")); - if (clp.hasOption("nonotifications")) - { - gSavedSettings.getControl("IgnoreAllNotifications")->setValue(true, false); - } - - if (clp.hasOption("debugsession")) + if (gSavedSettings.getBOOL("DebugSession")) { gDebugSession = TRUE; gDebugGL = TRUE; @@ -2654,38 +2617,32 @@ bool LLAppViewer::initConfiguration() // What can happen is that someone can use IE (or potentially // other browsers) and do the rough equivalent of command // injection and steal passwords. Phoenix. SL-55321 - - LLSLURL option_slurl; - - if(clp.hasOption("url")) + LLSLURL start_slurl; + std::string CmdLineLoginLocation(gSavedSettings.getString("CmdLineLoginLocation")); + if(! CmdLineLoginLocation.empty()) { - option_slurl = LLSLURL(clp.getOption("url")[0]); - LLStartUp::setStartSLURL(option_slurl); - if(LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION) + start_slurl = CmdLineLoginLocation; + LLStartUp::setStartSLURL(start_slurl); + if(start_slurl.getType() == LLSLURL::LOCATION) { - LLGridManager::getInstance()->setGridChoice(LLStartUp::getStartSLURL().getGrid()); - } + LLGridManager::getInstance()->setGridChoice(start_slurl.getGrid()); } - else if(clp.hasOption("slurl")) - { - option_slurl = LLSLURL(clp.getOption("slurl")[0]); - LLStartUp::setStartSLURL(option_slurl); } - + //RN: if we received a URL, hand it off to the existing instance. // don't call anotherInstanceRunning() when doing URL handoff, as // it relies on checking a marker file which will not work when running // out of different directories - if (option_slurl.isValid() && + if (start_slurl.isValid() && (gSavedSettings.getBOOL("SLURLPassToOtherInstance"))) { - if (sendURLToOtherInstance(option_slurl.getSLURLString())) + if (sendURLToOtherInstance(start_slurl.getSLURLString())) { // successfully handed off URL to existing instance, exit return false; } - } + } const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent"); if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString()) @@ -2829,8 +2786,7 @@ bool LLAppViewer::initConfiguration() LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation)); } else if ( ( clp.hasOption("login") || clp.hasOption("autologin")) - && !clp.hasOption("url") - && !clp.hasOption("slurl")) + && gSavedSettings.getString("CmdLineLoginLocation").empty()) { // If automatic login from command line with --login switch // init StartSLURL location. @@ -3066,13 +3022,19 @@ namespace { void LLAppViewer::initUpdater() { // Initialize the updater service. - // Generate URL to the udpater service // Get Channel // Get Version - std::string url = gSavedSettings.getString("UpdaterServiceURL"); + + /***************************************************************** + * Previously, the url was derived from the settings + * UpdaterServiceURL + * UpdaterServicePath + * it is now obtained from the grid manager. The settings above + * are no longer used. + *****************************************************************/ std::string channel = LLVersionInfo::getChannel(); std::string version = LLVersionInfo::getVersion(); - std::string service_path = gSavedSettings.getString("UpdaterServicePath"); + U32 check_period = gSavedSettings.getU32("UpdaterServiceCheckPeriod"); bool willing_to_test; LL_DEBUGS("UpdaterService") << "channel " << channel << LL_ENDL; @@ -3097,9 +3059,7 @@ void LLAppViewer::initUpdater() } mUpdater->setAppExitCallback(boost::bind(&LLAppViewer::forceQuit, this)); - mUpdater->initialize(url, - service_path, - channel, + mUpdater->initialize(channel, version, gPlatform, getOSInfo().getOSVersionString(), @@ -3204,9 +3164,10 @@ bool LLAppViewer::initWindow() // Initialize GL stuff // - if (mForceGraphicsDetail) + if (mForceGraphicsLevel) { - LLFeatureManager::getInstance()->setGraphicsLevel(gSavedSettings.getU32("RenderQualityPerformance"), false); + LLFeatureManager::getInstance()->setGraphicsLevel(*mForceGraphicsLevel, false); + gSavedSettings.setU32("RenderQualityPerformance", *mForceGraphicsLevel); } // Set this flag in case we crash while initializing GL diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index cd91ae8b2b..3af360b529 100755 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -32,6 +32,7 @@ #include "llsys.h" // for LLOSInfo #include "lltimer.h" #include "llappcorehttp.h" +#include <boost/optional.hpp> class LLCommandLineParser; class LLFrameTimer; @@ -258,7 +259,7 @@ private: bool mSavedFinalSnapshot; bool mSavePerAccountSettings; // only save per account settings if login succeeded - bool mForceGraphicsDetail; + boost::optional<U32> mForceGraphicsLevel; bool mQuitRequested; // User wants to quit, may have modified documents open. bool mLogoutRequestSent; // Disconnect message sent to simulator, no longer safe to send messages to the sim. diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp index 4d340cafa9..c7b437598c 100755 --- a/indra/newview/llappviewermacosx.cpp +++ b/indra/newview/llappviewermacosx.cpp @@ -148,28 +148,13 @@ bool LLAppViewerMacOSX::initParseCommandLine(LLCommandLineParser& clp) // The next two lines add the support for parsing the mac -psn_XXX arg. clp.addOptionDesc("psn", NULL, 1, "MacOSX process serial number"); clp.setCustomParser(parse_psn); - - // First read in the args from arguments txt. - const char* filename = "arguments.txt"; - llifstream ifs(filename, llifstream::binary); - if (!ifs.is_open()) - { - llwarns << "Unable to open file" << filename << llendl; - return false; - } - - if(clp.parseCommandLineFile(ifs) == false) - { - return false; - } - // Then parse the user's command line, so that any --url arg can appear last - // Succesive calls to clp.parse... will NOT override earlier options. + // parse the user's command line if(clp.parseCommandLine(gArgC, gArgV) == false) { return false; } - + // Get the user's preferred language string based on the Mac OS localization mechanism. // To add a new localization: // go to the "Resources" section of the project diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp index 43757d0174..8b2d9e639f 100755 --- a/indra/newview/llchannelmanager.cpp +++ b/indra/newview/llchannelmanager.cpp @@ -139,8 +139,6 @@ void LLChannelManager::onLoginCompleted() } LLPersistentNotificationStorage::getInstance()->loadNotifications(); - - LLDoNotDisturbNotificationStorage::getInstance()->initialize(); LLDoNotDisturbNotificationStorage::getInstance()->loadNotifications(); } diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 7d0331757b..b3bc0ba966 100755 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -381,7 +381,7 @@ void LLChatBar::sendChat( EChatType type ) if (!utf8_revised_text.empty()) { // Chat with animation - sendChatFromViewer(utf8_revised_text, type, TRUE); + sendChatFromViewer(utf8_revised_text, type, gSavedSettings.getBOOL("PlayChatAnim")); } } } diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 0f138873ac..af3c6eff11 100755 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -628,6 +628,7 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) editor_params.enabled = false; // read only editor_params.show_context_menu = "true"; mEditor = LLUICtrlFactory::create<LLTextEditor>(editor_params, this); + mEditor->setIsFriendCallback(LLAvatarActions::isFriend); } LLSD LLChatHistory::getValue() const diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index a1a9463d43..fd4f17b694 100755 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -323,12 +323,11 @@ BOOL LLFloaterIMNearbyChatToastPanel::handleMouseUp (S32 x, S32 y, MASK mask) return TRUE; else { - (LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->showHistory(); + LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")->showHistory(); return FALSE; } } - - (LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"))->showHistory(); + LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat")->showHistory(); return LLPanel::handleMouseUp(x,y,mask); } diff --git a/indra/newview/llcommandlineparser.cpp b/indra/newview/llcommandlineparser.cpp index 17d403bbe1..a6384ded12 100755 --- a/indra/newview/llcommandlineparser.cpp +++ b/indra/newview/llcommandlineparser.cpp @@ -38,16 +38,23 @@ #endif #include <boost/program_options.hpp> +#include <boost/lexical_cast.hpp> #include <boost/bind.hpp> -#include<boost/tokenizer.hpp> +#include <boost/tokenizer.hpp> +#include <boost/assign/list_of.hpp> #if _MSC_VER # pragma warning(pop) #endif #include "llsdserialize.h" +#include "llerror.h" +#include "stringize.h" +#include <string> +#include <set> #include <iostream> #include <sstream> +#include <typeinfo> #include "llcontrol.h" @@ -63,10 +70,22 @@ namespace po = boost::program_options; // This could be good or bad, and probably won't matter for most use cases. namespace { + // List of command-line switches that can't map-to settings variables. + // Going forward, we want every new command-line switch to map-to some + // settings variable. This list is used to validate that. + const std::set<std::string> unmapped_options = boost::assign::list_of + ("help") + ("set") + ("setdefault") + ("settings") + ("sessionsettings") + ("usersessionsettings") + ; + po::options_description gOptionsDesc; po::positional_options_description gPositionalOptions; po::variables_map gVariableMap; - + const LLCommandLineParser::token_vector_t gEmptyValue; void read_file_into_string(std::string& str, const std::basic_istream < char >& file) @@ -384,9 +403,19 @@ bool LLCommandLineParser::parseCommandLineFile(const std::basic_istream < char > return parseCommandLineString(args); } -void LLCommandLineParser::notify() +bool LLCommandLineParser::notify() { - po::notify(gVariableMap); + try + { + po::notify(gVariableMap); + return true; + } + catch (const LLCLPError& e) + { + llwarns << "Caught Error: " << e.what() << llendl; + mErrorMsg = e.what(); + return false; + } } void LLCommandLineParser::printOptions() const @@ -428,43 +457,129 @@ const LLCommandLineParser::token_vector_t& LLCommandLineParser::getOption(const //---------------------------------------------------------------------------- // LLControlGroupCLP defintions //---------------------------------------------------------------------------- +namespace { +LLCommandLineParser::token_vector_t::value_type +onevalue(const std::string& option, + const LLCommandLineParser::token_vector_t& value) +{ + if (value.empty()) + { + // What does it mean when the user specifies a command-line switch + // that requires a value, but omits the value? Complain. + throw LLCLPError(STRINGIZE("No value specified for --" << option << "!")); + } + else if (value.size() > 1) + { + llwarns << "Ignoring extra tokens specified for --" + << option << "." << llendl; + } + return value[0]; +} + +void badvalue(const std::string& option, + const std::string& varname, + const std::string& type, + const std::string& value) +{ + // If the user passes an unusable value for a command-line switch, it + // seems like a really bad idea to just ignore it, even with a log + // warning. + throw LLCLPError(STRINGIZE("Invalid value specified by command-line switch '" << option + << "' for variable '" << varname << "' of type " << type + << ": '" << value << "'")); +} + +template <typename T> +T convertTo(const std::string& option, + const std::string& varname, + const LLCommandLineParser::token_vector_t::value_type& value) +{ + try + { + return boost::lexical_cast<T>(value); + } + catch (const boost::bad_lexical_cast&) + { + badvalue(option, varname, typeid(T).name(), value); + // bogus return; compiler unaware that badvalue() won't return + return T(); + } +} + void setControlValueCB(const LLCommandLineParser::token_vector_t& value, - const std::string& opt_name, - LLControlGroup* ctrlGroup) + const std::string& option, + LLControlVariable* ctrl) { - // *FIX: Do sematic conversion here. + // *FIX: Do semantic conversion here. // LLSD (ImplString) Is no good for doing string to type conversion for... // booleans // compound types // ?... - LLControlVariable* ctrl = ctrlGroup->getControl(opt_name); if(NULL != ctrl) { switch(ctrl->type()) { case TYPE_BOOLEAN: - if(value.size() > 1) + if (value.empty()) { - llwarns << "Ignoring extra tokens." << llendl; + // Boolean-valued command-line switches are unusual. If you + // simply specify the switch without an explicit value, we can + // infer you mean 'true'. + ctrl->setValue(LLSD(true), false); } - - if(value.size() > 0) + else { + // Only call onevalue() AFTER handling value.empty() case! + std::string token(onevalue(option, value)); + // There's a token. check the string for true/false/1/0 etc. BOOL result = false; - BOOL gotSet = LLStringUtil::convertToBOOL(value[0], result); - if(gotSet) + BOOL gotSet = LLStringUtil::convertToBOOL(token, result); + if (gotSet) { ctrl->setValue(LLSD(result), false); } + else + { + badvalue(option, ctrl->getName(), "bool", token); + } + } + break; + + case TYPE_U32: + { + std::string token(onevalue(option, value)); + // To my surprise, for an unsigned target, lexical_cast() doesn't + // complain about an input string such as "-17". In that case, you + // get a very large positive result. So for U32, make sure there's + // no minus sign! + if (token.find('-') == std::string::npos) + { + ctrl->setValue(LLSD::Integer(convertTo<U32>(option, ctrl->getName(), token)), + false); } else { - ctrl->setValue(LLSD(true), false); + badvalue(option, ctrl->getName(), "unsigned", token); } break; + } + + case TYPE_S32: + ctrl->setValue(convertTo<S32>(option, ctrl->getName(), + onevalue(option, value)), false); + break; + + case TYPE_F32: + ctrl->setValue(convertTo<F32>(option, ctrl->getName(), + onevalue(option, value)), false); + break; + // It appears that no one has yet tried to define a command-line + // switch mapped to a settings variable of TYPE_VEC3, TYPE_VEC3D, + // TYPE_RECT, TYPE_COL4, TYPE_COL3. Such types would certainly seem to + // call for a bit of special handling here... default: { // For the default types, let llsd do the conversion. @@ -481,16 +596,9 @@ void setControlValueCB(const LLCommandLineParser::token_vector_t& value, ctrl->setValue(llsdArray, false); } - else if(value.size() > 0) + else { - if(value.size() > 1) - { - llwarns << "Ignoring extra tokens mapped to the setting: " << opt_name << "." << llendl; - } - - LLSD llsdValue; - llsdValue.assign(LLSD::String(value[0])); - ctrl->setValue(llsdValue, false); + ctrl->setValue(onevalue(option, value), false); } } break; @@ -498,12 +606,14 @@ void setControlValueCB(const LLCommandLineParser::token_vector_t& value, } else { - llwarns << "Command Line option mapping '" - << opt_name - << "' not found! Ignoring." - << llendl; + // This isn't anything a user can affect -- it's a misconfiguration on + // the part of the coder. Rub the coder's nose in the problem right + // away so even preliminary testing will surface it. + llerrs << "Command Line option --" << option + << " maps to unknown setting!" << llendl; } } +} // anonymous namespace void LLControlGroupCLP::configure(const std::string& config_filename, LLControlGroup* controlGroup) { @@ -561,11 +671,37 @@ void LLControlGroupCLP::configure(const std::string& config_filename, LLControlG } boost::function1<void, const token_vector_t&> callback; - if(option_params.has("map-to") && (NULL != controlGroup)) + if (! option_params.has("map-to")) + { + // If this option isn't mapped to a settings variable, is it + // one of the ones for which that's unreasonable, or did + // someone carelessly add a new option? (Make all these + // configuration errors fatal so a maintainer will catch them + // right away.) + std::set<std::string>::const_iterator found = unmapped_options.find(long_name); + if (found == unmapped_options.end()) + { + llerrs << "New command-line option " << long_name + << " should map-to a variable in settings.xml" << llendl; + } + } + else // option specifies map-to { std::string controlName = option_params["map-to"].asString(); - callback = boost::bind(setControlValueCB, _1, - controlName, controlGroup); + if (! controlGroup) + { + llerrs << "Must pass gSavedSettings to LLControlGroupCLP::configure() for " + << long_name << " (map-to " << controlName << ")" << llendl; + } + + LLControlVariable* ctrl = controlGroup->getControl(controlName); + if (! ctrl) + { + llerrs << "Option " << long_name << " specifies map-to " << controlName + << " which does not exist" << llendl; + } + + callback = boost::bind(setControlValueCB, _1, long_name, ctrl); } this->addOptionDesc( diff --git a/indra/newview/llcommandlineparser.h b/indra/newview/llcommandlineparser.h index 44f2a26843..71388b8217 100755 --- a/indra/newview/llcommandlineparser.h +++ b/indra/newview/llcommandlineparser.h @@ -86,7 +86,7 @@ public: * * Use this to handle the results of parsing. */ - void notify(); + bool notify(); /** @brief Print a description of the configured options. * diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 6e95df8383..192a594c9d 100755 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -363,7 +363,10 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags) lldebugs << "LLConversationItemParticipant::buildContextMenu()" << llendl; menuentry_vec_t items; menuentry_vec_t disabled_items; - + if((flags & ITEM_IN_MULTI_SELECTION) && (this->getType() != CONV_SESSION_NEARBY)) + { + items.push_back(std::string("close_selected_conversations")); + } if(this->getType() == CONV_SESSION_1_ON_1) { items.push_back(std::string("close_conversation")); diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index 42104ea20a..9faa12b2ee 100755 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp @@ -127,7 +127,10 @@ void LLConversationViewSession::setHighlightState(bool hihglight_state) void LLConversationViewSession::startFlashing() { - if (isInVisibleChain() && mFlashStateOn && !mFlashStarted) + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + + // Need to start flashing only when "Conversations" is opened or brought on top + if (isInVisibleChain() && !im_box->isMinimized() && mFlashStateOn && !mFlashStarted) { mFlashStarted = true; mFlashTimer->startFlashing(); @@ -270,6 +273,29 @@ BOOL LLConversationViewSession::handleMouseDown( S32 x, S32 y, MASK mask ) return result; } +BOOL LLConversationViewSession::handleMouseUp( S32 x, S32 y, MASK mask ) +{ + BOOL result = LLFolderViewFolder::handleMouseUp(x, y, mask); + + LLFloater* volume_floater = LLFloaterReg::findInstance("floater_voice_volume"); + LLFloater* chat_volume_floater = LLFloaterReg::findInstance("chat_voice"); + if (result + && getRoot() + && !(volume_floater && volume_floater->isShown() && volume_floater->hasFocus()) + && !(chat_volume_floater && chat_volume_floater->isShown() && chat_volume_floater->hasFocus())) + { + LLConversationItem* item = dynamic_cast<LLConversationItem *>(getViewModelItem()); + LLUUID session_id = item? item->getUUID() : LLUUID(); + LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(session_id); + if(!session_floater->hasFocus()) + { + session_floater->setFocus(true); + } + } + + return result; +} + BOOL LLConversationViewSession::handleRightMouseDown( S32 x, S32 y, MASK mask ) { BOOL result = LLFolderViewFolder::handleRightMouseDown(x, y, mask); diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 879d496dc7..5a74974302 100755 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h @@ -69,6 +69,7 @@ public: /*virtual*/ void draw(); /*virtual*/ BOOL handleMouseDown( S32 x, S32 y, MASK mask ); /*virtual*/ BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); + /*virtual*/ BOOL handleMouseUp( S32 x, S32 y, MASK mask ); /*virtual*/ S32 arrange(S32* width, S32* height); diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp index 71bc4f15d2..495cd01349 100755 --- a/indra/newview/lldonotdisturbnotificationstorage.cpp +++ b/indra/newview/lldonotdisturbnotificationstorage.cpp @@ -70,7 +70,7 @@ BOOL LLDoNotDisturbNotificationStorageTimer::tick() LLDoNotDisturbNotificationStorage::LLDoNotDisturbNotificationStorage() : LLSingleton<LLDoNotDisturbNotificationStorage>() - , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml")) + , LLNotificationStorage("") , mDirty(false) { nameToPayloadParameterMap[toastName] = "SESSION_ID"; @@ -83,6 +83,7 @@ LLDoNotDisturbNotificationStorage::~LLDoNotDisturbNotificationStorage() void LLDoNotDisturbNotificationStorage::initialize() { + setFileName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "dnd_notifications.xml")); getCommunicationChannel()->connectFailedFilter(boost::bind(&LLDoNotDisturbNotificationStorage::onChannelChanged, this, _1)); } diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 6d90667194..b35ef3a961 100755 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -400,6 +400,8 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p) mMoreTextBox->setClickedCallback(boost::bind(&LLFavoritesBarCtrl::showDropDownMenu, this)); addChild(mMoreTextBox); + mDropDownItemsCount = 0; + LLTextBox::Params label_param(p.label); mBarLabel = LLUICtrlFactory::create<LLTextBox> (label_param); addChild(mBarLabel); @@ -820,11 +822,13 @@ void LLFavoritesBarCtrl::updateButtons() } // Update overflow menu LLToggleableMenu* overflow_menu = static_cast <LLToggleableMenu*> (mOverflowMenuHandle.get()); - if (overflow_menu && overflow_menu->getVisible()) + if (overflow_menu && overflow_menu->getVisible() && (overflow_menu->getItemCount() != mDropDownItemsCount)) { overflow_menu->setVisible(FALSE); if (mUpdateDropDownItems) + { showDropDownMenu(); + } } } else @@ -940,6 +944,7 @@ void LLFavoritesBarCtrl::showDropDownMenu() menu->updateParent(LLMenuGL::sMenuContainer); menu->setButtonRect(mMoreTextBox->getRect(), this); positionAndShowMenu(menu); + mDropDownItemsCount = menu->getItemCount(); } } diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h index f06e9b9b64..211d3c4ce3 100755 --- a/indra/newview/llfavoritesbar.h +++ b/indra/newview/llfavoritesbar.h @@ -101,6 +101,7 @@ protected: LLUUID mFavoriteFolderId; const LLFontGL *mFont; S32 mFirstDropDownItem; + S32 mDropDownItemsCount; bool mUpdateDropDownItems; bool mRestoreOverflowMenu; diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index ddb9d3bc43..9d292ce7bb 100755 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -30,6 +30,7 @@ #include <fstream> #include <boost/regex.hpp> +#include <boost/assign/list_of.hpp> #include "llfeaturemanager.h" #include "lldir.h" @@ -52,6 +53,8 @@ #include "llboost.h" #include "llweb.h" #include "llviewershadermgr.h" +#include "llstring.h" +#include "stringize.h" #if LL_WINDOWS #include "lldxhardware.h" @@ -187,6 +190,55 @@ void LLFeatureList::dump() LL_DEBUGS("RenderInit") << LL_ENDL; } +static const std::vector<std::string> sGraphicsLevelNames = boost::assign::list_of + ("Low") + ("LowMid") + ("Mid") + ("MidHigh") + ("High") + ("HighUltra") + ("Ultra") +; + +U32 LLFeatureManager::getMaxGraphicsLevel() const +{ + return sGraphicsLevelNames.size() - 1; +} + +bool LLFeatureManager::isValidGraphicsLevel(U32 level) const +{ + return (level <= getMaxGraphicsLevel()); +} + +std::string LLFeatureManager::getNameForGraphicsLevel(U32 level) const +{ + if (isValidGraphicsLevel(level)) + { + return sGraphicsLevelNames[level]; + } + return STRINGIZE("Invalid graphics level " << level << ", valid are 0 .. " + << getMaxGraphicsLevel()); +} + +S32 LLFeatureManager::getGraphicsLevelForName(const std::string& name) const +{ + const std::string FixedFunction("FixedFunction"); + std::string rname(name); + if (LLStringUtil::endsWith(rname, FixedFunction)) + { + // chop off any "FixedFunction" suffix + rname = rname.substr(0, rname.length() - FixedFunction.length()); + } + for (S32 i(0), iend(getMaxGraphicsLevel()); i <= iend; ++i) + { + if (sGraphicsLevelNames[i] == rname) + { + return i; + } + } + return -1; +} + LLFeatureList *LLFeatureManager::findMask(const std::string& name) { if (mMaskList.count(name)) @@ -620,7 +672,7 @@ void LLFeatureManager::applyRecommendedSettings() { // apply saved settings // cap the level at 2 (high) - S32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5)); + U32 level = llmax(GPU_CLASS_0, llmin(mGPUClass, GPU_CLASS_5)); llinfos << "Applying Recommended Features" << llendl; @@ -696,62 +748,33 @@ void LLFeatureManager::applyFeatures(bool skipFeatures) } } -void LLFeatureManager::setGraphicsLevel(S32 level, bool skipFeatures) +void LLFeatureManager::setGraphicsLevel(U32 level, bool skipFeatures) { LLViewerShaderMgr::sSkipReload = true; applyBaseMasks(); - - switch (level) + + // if we're passed an invalid level, default to "Low" + std::string features(isValidGraphicsLevel(level)? getNameForGraphicsLevel(level) : "Low"); + if (features == "Low") { - case 0: #if LL_DARWIN - // This Mac-specific change is to insure that we force 'Basic Shaders' for all Mac - // systems which support them instead of falling back to fixed-function unnecessarily - // MAINT-2157 - // - if (gGLManager.mGLVersion < 2.1f) - { - maskFeatures("LowFixedFunction"); - } - else - { //same as low, but with "Basic Shaders" enabled - maskFeatures("Low"); - } + // This Mac-specific change is to insure that we force 'Basic Shaders' for all Mac + // systems which support them instead of falling back to fixed-function unnecessarily + // MAINT-2157 + if (gGLManager.mGLVersion < 2.1f) #else - if (gGLManager.mGLVersion < 3.f || gGLManager.mIsIntel) - { //only use fixed function by default if GL version < 3.0 or this is an intel graphics chip - maskFeatures("LowFixedFunction"); - } - else - { //same as low, but with "Basic Shaders" enabled - maskFeatures("Low"); - } + // only use fixed function by default if GL version < 3.0 or this is an intel graphics chip + if (gGLManager.mGLVersion < 3.f || gGLManager.mIsIntel) #endif - break; - case 1: - maskFeatures("LowMid"); - break; - case 2: - maskFeatures("Mid"); - break; - case 3: - maskFeatures("MidHigh"); - break; - case 4: - maskFeatures("High"); - break; - case 5: - maskFeatures("HighUltra"); - break; - case 6: - maskFeatures("Ultra"); - break; - default: - maskFeatures("Low"); - break; + { + // same as Low, but with "Basic Shaders" disabled + features = "LowFixedFunction"; + } } + maskFeatures(features); + applyFeatures(skipFeatures); LLViewerShaderMgr::sSkipReload = false; diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h index ad72c16743..3b8d251236 100755 --- a/indra/newview/llfeaturemanager.h +++ b/indra/newview/llfeaturemanager.h @@ -134,8 +134,18 @@ public: // skipFeatures forces skipping of mostly hardware settings // that we don't want to change when we change graphics // settings - void setGraphicsLevel(S32 level, bool skipFeatures); - + void setGraphicsLevel(U32 level, bool skipFeatures); + + // What 'level' values are valid to pass to setGraphicsLevel()? + // 0 is the low end... + U32 getMaxGraphicsLevel() const; + bool isValidGraphicsLevel(U32 level) const; + + // setGraphicsLevel() levels have names. + std::string getNameForGraphicsLevel(U32 level) const; + // returns -1 for unrecognized name (hence S32 rather than U32) + S32 getGraphicsLevelForName(const std::string& name) const; + void applyBaseMasks(); void applyRecommendedSettings(); diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 83fb887d81..fea8e34729 100755 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -33,8 +33,10 @@ // Viewer includes #include "llagent.h" +#include "llagentui.h" #include "llappviewer.h" #include "llsecondlifeurls.h" +#include "llslurl.h" #include "llvoiceclient.h" #include "lluictrlfactory.h" #include "llviewertexteditor.h" @@ -250,12 +252,16 @@ LLSD LLFloaterAbout::getInfo() LLViewerRegion* region = gAgent.getRegion(); if (region) { - const LLVector3d &pos = gAgent.getPositionGlobal(); + LLVector3d pos = gAgent.getPositionGlobal(); info["POSITION"] = ll_sd_from_vector3d(pos); + info["POSITION_LOCAL"] = ll_sd_from_vector3(gAgent.getPosAgentFromGlobal(pos)); info["REGION"] = gAgent.getRegion()->getName(); info["HOSTNAME"] = gAgent.getRegion()->getHost().getHostName(); info["HOSTIP"] = gAgent.getRegion()->getHost().getString(); info["SERVER_VERSION"] = gLastVersionChannel; + LLSLURL slurl; + LLAgentUI::buildSLURL(slurl); + info["SLURL"] = slurl.getSLURLString(); } // CPU @@ -307,12 +313,12 @@ LLSD LLFloaterAbout::getInfo() static std::string get_viewer_release_notes_url() { // return a URL to the release notes for this viewer, such as: - // http://wiki.secondlife.com/wiki/Release_Notes/Second Life Beta Viewer/2.1.0 + // http://wiki.secondlife.com/wiki/Release_Notes/Second Life Beta Viewer/2.1.0.123456 std::string url = LLTrans::getString("RELEASE_NOTES_BASE_URL"); if (! LLStringUtil::endsWith(url, "/")) url += "/"; url += LLVersionInfo::getChannel() + "/"; - url += LLVersionInfo::getShortVersion(); + url += LLVersionInfo::getVersion(); return LLWeb::escapeURL(url); } diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 113aa9a8f2..c0afb72cff 100755 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -513,6 +513,7 @@ void LLFloaterAvatarPicker::find() url += "/"; } url += "?page_size=100&names="; + std::replace(text.begin(), text.end(), '.', ' '); url += LLURI::escape(text); llinfos << "avatar picker " << url << llendl; LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID, getKey().asString())); @@ -748,7 +749,12 @@ void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD& { getChildView("ok_btn")->setEnabled(true); search_results->setEnabled(true); - search_results->selectFirstItem(); + search_results->sortByColumnIndex(1, TRUE); + std::string text = getChild<LLUICtrl>("Edit")->getValue().asString(); + if (!search_results->selectItemByLabel(text, TRUE, 1)) + { + search_results->selectFirstItem(); + } onList(); search_results->setFocus(TRUE); } diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp index 39b6e465f3..76f62a7880 100755 --- a/indra/newview/llfloaterbulkpermission.cpp +++ b/indra/newview/llfloaterbulkpermission.cpp @@ -57,6 +57,7 @@ LLFloaterBulkPermission::LLFloaterBulkPermission(const LLSD& seed) mDone(FALSE) { mID.generate(); + mCommitCallbackRegistrar.add("BulkPermission.Ok", boost::bind(&LLFloaterBulkPermission::onOkBtn, this)); mCommitCallbackRegistrar.add("BulkPermission.Apply", boost::bind(&LLFloaterBulkPermission::onApplyBtn, this)); mCommitCallbackRegistrar.add("BulkPermission.Close", boost::bind(&LLFloaterBulkPermission::onCloseBtn, this)); mCommitCallbackRegistrar.add("BulkPermission.CheckAll", boost::bind(&LLFloaterBulkPermission::onCheckAll, this)); @@ -66,6 +67,21 @@ LLFloaterBulkPermission::LLFloaterBulkPermission(const LLSD& seed) BOOL LLFloaterBulkPermission::postBuild() { + mBulkChangeIncludeAnimations = gSavedSettings.getBOOL("BulkChangeIncludeAnimations"); + mBulkChangeIncludeBodyParts = gSavedSettings.getBOOL("BulkChangeIncludeBodyParts"); + mBulkChangeIncludeClothing = gSavedSettings.getBOOL("BulkChangeIncludeClothing"); + mBulkChangeIncludeGestures = gSavedSettings.getBOOL("BulkChangeIncludeGestures"); + mBulkChangeIncludeNotecards = gSavedSettings.getBOOL("BulkChangeIncludeNotecards"); + mBulkChangeIncludeObjects = gSavedSettings.getBOOL("BulkChangeIncludeObjects"); + mBulkChangeIncludeScripts = gSavedSettings.getBOOL("BulkChangeIncludeScripts"); + mBulkChangeIncludeSounds = gSavedSettings.getBOOL("BulkChangeIncludeSounds"); + mBulkChangeIncludeTextures = gSavedSettings.getBOOL("BulkChangeIncludeTextures"); + mBulkChangeShareWithGroup = gSavedSettings.getBOOL("BulkChangeShareWithGroup"); + mBulkChangeEveryoneCopy = gSavedSettings.getBOOL("BulkChangeEveryoneCopy"); + mBulkChangeNextOwnerModify = gSavedSettings.getBOOL("BulkChangeNextOwnerModify"); + mBulkChangeNextOwnerCopy = gSavedSettings.getBOOL("BulkChangeNextOwnerCopy"); + mBulkChangeNextOwnerTransfer = gSavedSettings.getBOOL("BulkChangeNextOwnerTransfer"); + return TRUE; } @@ -144,6 +160,12 @@ void LLFloaterBulkPermission::inventoryChanged(LLViewerObject* viewer_object, } } +void LLFloaterBulkPermission::onOkBtn() +{ + doApply(); + closeFloater(); +} + void LLFloaterBulkPermission::onApplyBtn() { doApply(); @@ -151,6 +173,20 @@ void LLFloaterBulkPermission::onApplyBtn() void LLFloaterBulkPermission::onCloseBtn() { + gSavedSettings.setBOOL("BulkChangeIncludeAnimations", mBulkChangeIncludeAnimations); + gSavedSettings.setBOOL("BulkChangeIncludeBodyParts", mBulkChangeIncludeBodyParts); + gSavedSettings.setBOOL("BulkChangeIncludeClothing", mBulkChangeIncludeClothing); + gSavedSettings.setBOOL("BulkChangeIncludeGestures", mBulkChangeIncludeGestures); + gSavedSettings.setBOOL("BulkChangeIncludeNotecards", mBulkChangeIncludeNotecards); + gSavedSettings.setBOOL("BulkChangeIncludeObjects", mBulkChangeIncludeObjects); + gSavedSettings.setBOOL("BulkChangeIncludeScripts", mBulkChangeIncludeScripts); + gSavedSettings.setBOOL("BulkChangeIncludeSounds", mBulkChangeIncludeSounds); + gSavedSettings.setBOOL("BulkChangeIncludeTextures", mBulkChangeIncludeTextures); + gSavedSettings.setBOOL("BulkChangeShareWithGroup", mBulkChangeShareWithGroup); + gSavedSettings.setBOOL("BulkChangeEveryoneCopy", mBulkChangeEveryoneCopy); + gSavedSettings.setBOOL("BulkChangeNextOwnerModify", mBulkChangeNextOwnerModify); + gSavedSettings.setBOOL("BulkChangeNextOwnerCopy", mBulkChangeNextOwnerCopy); + gSavedSettings.setBOOL("BulkChangeNextOwnerTransfer", mBulkChangeNextOwnerTransfer); closeFloater(); } diff --git a/indra/newview/llfloaterbulkpermission.h b/indra/newview/llfloaterbulkpermission.h index 7dd05df7ee..25e76eca65 100755 --- a/indra/newview/llfloaterbulkpermission.h +++ b/indra/newview/llfloaterbulkpermission.h @@ -72,6 +72,7 @@ private: bool is_new); void onCloseBtn(); + void onOkBtn(); void onApplyBtn(); void onCommitCopy(); void onCheckAll() { doCheckUncheckAll(TRUE); } @@ -94,6 +95,21 @@ private: LLUUID mCurrentObjectID; BOOL mDone; + bool mBulkChangeIncludeAnimations; + bool mBulkChangeIncludeBodyParts; + bool mBulkChangeIncludeClothing; + bool mBulkChangeIncludeGestures; + bool mBulkChangeIncludeNotecards; + bool mBulkChangeIncludeObjects; + bool mBulkChangeIncludeScripts; + bool mBulkChangeIncludeSounds; + bool mBulkChangeIncludeTextures; + bool mBulkChangeShareWithGroup; + bool mBulkChangeEveryoneCopy; + bool mBulkChangeNextOwnerModify; + bool mBulkChangeNextOwnerCopy; + bool mBulkChangeNextOwnerTransfer; + LLUUID mID; const char* mStartString; diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index a3d715530d..b570de14aa 100755 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -50,6 +50,7 @@ LLFloaterConversationPreview::LLFloaterConversationPreview(const LLSD& session_i BOOL LLFloaterConversationPreview::postBuild() { mChatHistory = getChild<LLChatHistory>("chat_history"); + LLLoadHistoryThread::setLoadEndSignal(boost::bind(&LLFloaterConversationPreview::SetPages, this, _1, _2)); const LLConversation* conv = LLConversationLog::instance().getConversation(mSessionID); std::string name; @@ -70,7 +71,7 @@ BOOL LLFloaterConversationPreview::postBuild() name = LLTrans::getString("NearbyChatTitle"); file = "chat"; } - + mChatHistoryFileName = file; LLStringUtil::format_map_t args; args["[NAME]"] = name; std::string title = getString("Title", args); @@ -80,23 +81,46 @@ BOOL LLFloaterConversationPreview::postBuild() load_params["load_all_history"] = true; load_params["cut_off_todays_date"] = false; - LLLogChat::loadChatHistory(file, mMessages, load_params); - mCurrentPage = mMessages.size() / mPageSize; + LLSD loading; + loading[LL_IM_TEXT] = LLTrans::getString("loading_chat_logs"); + mMessages.push_back(loading); mPageSpinner = getChild<LLSpinCtrl>("history_page_spin"); mPageSpinner->setCommitCallback(boost::bind(&LLFloaterConversationPreview::onMoreHistoryBtnClick, this)); mPageSpinner->setMinValue(1); - mPageSpinner->setMaxValue(mCurrentPage + 1); - mPageSpinner->set(mCurrentPage + 1); - - std::string total_page_num = llformat("/ %d", mCurrentPage + 1); - getChild<LLTextBox>("page_num_label")->setValue(total_page_num); - + mPageSpinner->set(1); + mPageSpinner->setEnabled(false); + mChatHistoryLoaded = false; + LLLogChat::startChatHistoryThread(file, load_params); return LLFloater::postBuild(); } +void LLFloaterConversationPreview::SetPages(std::list<LLSD>& messages, const std::string& file_name) +{ + if(file_name == mChatHistoryFileName) + { + mMessages = messages; + + + mCurrentPage = mMessages.size() / mPageSize; + mPageSpinner->setEnabled(true); + mPageSpinner->setMaxValue(mCurrentPage+1); + mPageSpinner->set(mCurrentPage+1); + + std::string total_page_num = llformat("/ %d", mCurrentPage+1); + getChild<LLTextBox>("page_num_label")->setValue(total_page_num); + mChatHistoryLoaded = true; + + } + +} void LLFloaterConversationPreview::draw() { + if(mChatHistoryLoaded) + { + showHistory(); + mChatHistoryLoaded = false; + } LLFloater::draw(); } @@ -128,6 +152,11 @@ void LLFloaterConversationPreview::showHistory() for (int msg_num = 0; (iter != mMessages.end() && msg_num < mPageSize); ++iter, ++msg_num) { + if (iter->size() == 0) + { + continue; + } + LLSD msg = *iter; LLUUID from_id = LLUUID::null; diff --git a/indra/newview/llfloaterconversationpreview.h b/indra/newview/llfloaterconversationpreview.h index b17ae84b63..389f3dfd09 100755 --- a/indra/newview/llfloaterconversationpreview.h +++ b/indra/newview/llfloaterconversationpreview.h @@ -42,6 +42,7 @@ public: virtual ~LLFloaterConversationPreview(){}; virtual BOOL postBuild(); + void SetPages(std::list<LLSD>& messages,const std::string& file_name); virtual void draw(); virtual void onOpen(const LLSD& key); @@ -59,6 +60,8 @@ private: std::list<LLSD> mMessages; std::string mAccountName; std::string mCompleteName; + std::string mChatHistoryFileName; + bool mChatHistoryLoaded; }; #endif /* LLFLOATERCONVERSATIONPREVIEW_H_ */ diff --git a/indra/newview/llfloatergotoline.cpp b/indra/newview/llfloatergotoline.cpp new file mode 100644 index 0000000000..d66e418926 --- /dev/null +++ b/indra/newview/llfloatergotoline.cpp @@ -0,0 +1,160 @@ +/** + * @file llfloatergotoline.h + * @author MartinRJ + * @brief LLFloaterGotoLine class implementation + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llfloatergotoline.h" +#include "llpreviewscript.h" +#include "llfloaterreg.h" +#include "lllineeditor.h" +#include "llviewertexteditor.h" +#include "llviewerwindow.h" + +LLFloaterGotoLine* LLFloaterGotoLine::sInstance = NULL; + +LLFloaterGotoLine::LLFloaterGotoLine(LLScriptEdCore* editor_core) +: LLFloater(LLSD()), + mGotoBox(NULL), + mEditorCore(editor_core) +{ + buildFromFile("floater_goto_line.xml"); + + sInstance = this; + + // find floater in which script panel is embedded + LLView* viewp = (LLView*)editor_core; + while(viewp) + { + LLFloater* floaterp = dynamic_cast<LLFloater*>(viewp); + if (floaterp) + { + floaterp->addDependentFloater(this); + break; + } + viewp = viewp->getParent(); + } +} + +BOOL LLFloaterGotoLine::postBuild() +{ + mGotoBox = getChild<LLLineEditor>("goto_line"); + mGotoBox->setCommitCallback(boost::bind(&LLFloaterGotoLine::onGotoBoxCommit, this)); + mGotoBox->setCommitOnFocusLost(FALSE); + getChild<LLLineEditor>("goto_line")->setPrevalidate(LLTextValidate::validateNonNegativeS32); + childSetAction("goto_btn", onBtnGoto,this); + setDefaultBtn("goto_btn"); + + return TRUE; +} + +//static +void LLFloaterGotoLine::show(LLScriptEdCore* editor_core) +{ + if (sInstance && sInstance->mEditorCore && sInstance->mEditorCore != editor_core) + { + sInstance->closeFloater(); + delete sInstance; + } + + if (!sInstance) + { + // sInstance will be assigned in the constructor. + new LLFloaterGotoLine(editor_core); + } + + sInstance->openFloater(); +} + +LLFloaterGotoLine::~LLFloaterGotoLine() +{ + sInstance = NULL; +} + +// static +void LLFloaterGotoLine::onBtnGoto(void *userdata) +{ + LLFloaterGotoLine* self = (LLFloaterGotoLine*)userdata; + self->handleBtnGoto(); +} + +void LLFloaterGotoLine::handleBtnGoto() +{ + S32 row = 0; + S32 column = 0; + row = getChild<LLUICtrl>("goto_line")->getValue().asInteger(); + if (row >= 0) + { + if (mEditorCore && mEditorCore->mEditor) + { + mEditorCore->mEditor->deselect(); + mEditorCore->mEditor->setCursor(row, column); + mEditorCore->mEditor->setFocus(TRUE); + } + } +} + +bool LLFloaterGotoLine::hasAccelerators() const +{ + if (mEditorCore) + { + return mEditorCore->hasAccelerators(); + } + return FALSE; +} + +BOOL LLFloaterGotoLine::handleKeyHere(KEY key, MASK mask) +{ + if (mEditorCore) + { + return mEditorCore->handleKeyHere(key, mask); + } + + return FALSE; +} + +void LLFloaterGotoLine::onGotoBoxCommit() +{ + S32 row = 0; + S32 column = 0; + row = getChild<LLUICtrl>("goto_line")->getValue().asInteger(); + if (row >= 0) + { + if (mEditorCore && mEditorCore->mEditor) + { + mEditorCore->mEditor->setCursor(row, column); + + S32 rownew = 0; + S32 columnnew = 0; + mEditorCore->mEditor->getCurrentLineAndColumn( &rownew, &columnnew, FALSE ); // don't include wordwrap + if (rownew == row && columnnew == column) + { + mEditorCore->mEditor->deselect(); + mEditorCore->mEditor->setFocus(TRUE); + sInstance->closeFloater(); + } //else do nothing (if the cursor-position didn't change) + } + } +} diff --git a/indra/newview/llfloatergotoline.h b/indra/newview/llfloatergotoline.h new file mode 100644 index 0000000000..058d601752 --- /dev/null +++ b/indra/newview/llfloatergotoline.h @@ -0,0 +1,66 @@ +/** + * @file llfloatergotoline.h + * @author MartinRJ + * @brief LLFloaterGotoLine class definition + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATERGOTOLINE_H +#define LL_LLFLOATERGOTOLINE_H + +#include "llfloater.h" +#include "lllineeditor.h" +#include "llpreviewscript.h" + +class LLScriptEdCore; + +class LLFloaterGotoLine : public LLFloater +{ +public: + LLFloaterGotoLine(LLScriptEdCore* editor_core); + ~LLFloaterGotoLine(); + + /*virtual*/ BOOL postBuild(); + static void show(LLScriptEdCore* editor_core); + + static void onBtnGoto(void* userdata); + void handleBtnGoto(); + + LLScriptEdCore* getEditorCore() { return mEditorCore; } + static LLFloaterGotoLine* getInstance() { return sInstance; } + + virtual bool hasAccelerators() const; + virtual BOOL handleKeyHere(KEY key, MASK mask); + +private: + + LLScriptEdCore* mEditorCore; + + static LLFloaterGotoLine* sInstance; + +protected: + LLLineEditor* mGotoBox; + void onGotoBoxCommit(); +}; + +#endif // LL_LLFLOATERGOTOLINE_H diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 4131ff314c..cc73ae031b 100755 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -47,6 +47,7 @@ #include "llfloaterpreference.h" #include "llimview.h" #include "llnotificationsutil.h" +#include "lltoolbarview.h" #include "lltransientfloatermgr.h" #include "llviewercontrol.h" #include "llconversationview.h" @@ -115,6 +116,10 @@ void LLFloaterIMContainer::sessionAdded(const LLUUID& session_id, const std::str void LLFloaterIMContainer::sessionActivated(const LLUUID& session_id, const std::string& name, const LLUUID& other_participant_id) { + if(!isInVisibleChain()) + { + setVisibleAndFrontmost(false); + } selectConversationPair(session_id, true); collapseMessagesPane(false); } @@ -262,7 +267,6 @@ BOOL LLFloaterIMContainer::postBuild() void LLFloaterIMContainer::onOpen(const LLSD& key) { LLMultiFloater::onOpen(key); - openNearbyChat(); reSelectConversation(); assignResizeLimits(); } @@ -346,11 +350,8 @@ void LLFloaterIMContainer::onStubCollapseButtonClicked() void LLFloaterIMContainer::onSpeakButtonClicked() { - //LLAgent::toggleMicrophone("speak"); - //updateSpeakBtnState(); - - LLParticipantList* session_model = dynamic_cast<LLParticipantList*>(mConversationsItems[LLUUID(NULL)]); - session_model->addTestAvatarAgents(); + LLAgent::toggleMicrophone("speak"); + updateSpeakBtnState(); } void LLFloaterIMContainer::onExpandCollapseButtonClicked() { @@ -600,6 +601,7 @@ void LLFloaterIMContainer::setMinimized(BOOL b) //Switching from minimized to un-minimized if(was_minimized && !b) { + gToolBarView->flashCommand(LLCommandId("chat"), false); LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(mSelectedSession); if(session_floater && !session_floater->isTornOff()) @@ -628,7 +630,6 @@ void LLFloaterIMContainer::setVisible(BOOL visible) LLFloaterReg::toggleInstanceOrBringToFront(name); selectConversationPair(LLUUID(NULL), false, false); } - openNearbyChat(); flashConversationItemWidget(mSelectedSession,false); LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(mSelectedSession); @@ -658,9 +659,13 @@ void LLFloaterIMContainer::setVisible(BOOL visible) LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second); if (widget) { + LLFloater* session_floater = widget->getSessionFloater(); + if (session_floater != nearby_chat) + { widget->setVisibleIfDetached(visible); } } + } // Now, do the normal multifloater show/hide LLMultiFloater::setVisible(visible); @@ -686,12 +691,17 @@ void LLFloaterIMContainer::getDetachedConversationFloaters(floater_list_t& float void LLFloaterIMContainer::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key) { LLMultiFloater::setVisibleAndFrontmost(take_focus, key); + // Do not select "Nearby Chat" conversation, since it will bring its window to front + // Only select other sessions + if (!getSelectedSession().isNull()) + { selectConversationPair(getSelectedSession(), false, take_focus); + } if (mInitialized && mIsFirstLaunch) { collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); mIsFirstLaunch = false; - } +} } void LLFloaterIMContainer::updateResizeLimits() @@ -819,7 +829,7 @@ void LLFloaterIMContainer::assignResizeLimits() S32 conv_pane_target_width = is_conv_pane_expanded ? ( is_msg_pane_expanded?mConversationsPane->getRect().getWidth():mConversationsPane->getExpandedMinDim() ) - : mConversationsPane->getMinDim(); + : mConversationsPane->getMinDim(); S32 msg_pane_min_width = is_msg_pane_expanded ? mMessagesPane->getExpandedMinDim() : 0; S32 new_min_width = conv_pane_target_width + msg_pane_min_width + summary_width_of_visible_borders; @@ -984,7 +994,7 @@ void LLFloaterIMContainer::setSortOrder(const LLConversationSort& order) gSavedSettings.setU32("ConversationSortOrder", (U32)order); } -void LLFloaterIMContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids) +void LLFloaterIMContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids, bool participant_uuids/* = true*/) { const std::set<LLFolderViewItem*> selectedItems = mConversationsRoot->getSelectionList(); @@ -997,7 +1007,7 @@ void LLFloaterIMContainer::getSelectedUUIDs(uuid_vec_t& selected_uuids) conversationItem = static_cast<LLConversationItem *>((*it)->getViewModelItem()); //When a one-on-one conversation exists, retrieve the participant id from the conversation floater - if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1) + if(conversationItem->getType() == LLConversationItem::CONV_SESSION_1_ON_1 && participant_uuids) { LLFloaterIMSession * conversation_floaterp = LLFloaterIMSession::findInstance(conversationItem->getUUID()); LLUUID participant_id = conversation_floaterp->getOtherParticipantUUID(); @@ -1152,6 +1162,11 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command, { LLFloater::onClickClose(conversationFloater); } + else if("close_selected_conversations" == command) + { + getSelectedUUIDs(selectedIDS,false); + closeSelectedConversations(selectedIDS); + } else if("open_voice_conversation" == command) { gIMMgr->startCall(conversationItem->getUUID()); @@ -1162,7 +1177,7 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command, } else if("chat_history" == command) { - if (selectedIDS.size() > 0) + if (selectedIDS.size() > 0) { LLAvatarActions::viewChatHistory(selectedIDS.front()); } @@ -1184,7 +1199,7 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command, { LLFloaterReg::showInstance("preview_conversation", LLSD(LLUUID::null), true); } - } +} } } @@ -1928,13 +1943,6 @@ void LLFloaterIMContainer::openNearbyChat() } } -void LLFloaterIMContainer::onNearbyChatClosed() -{ - // If nearby chat is the only remaining conversation and it is closed, close whole conversation floater as well - if (mConversationsItems.size() == 1) - closeFloater(); -} - void LLFloaterIMContainer::reSelectConversation() { LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(mSelectedSession); @@ -2070,6 +2078,19 @@ void LLFloaterIMContainer::expandConversation() } } +// By default, if torn off session is currently frontmost, LLFloater::isFrontmost() will return FALSE, which can lead to some bugs +// So LLFloater::isFrontmost() is overriden here to check both selected session and the IM floater itself +// Exclude "Nearby Chat" session from the check, as "Nearby Chat" window and "Conversations" floater can be brought +// to front independently +/*virtual*/ +BOOL LLFloaterIMContainer::isFrontmost() +{ + LLFloaterIMSessionTab* selected_session = LLFloaterIMSessionTab::getConversation(mSelectedSession); + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); + return (selected_session && selected_session->isFrontmost() && (selected_session != nearby_chat)) + || LLFloater::isFrontmost(); +} + // For conversations, closeFloater() (linked to Ctrl-W) does not actually close the floater but the active conversation. // This is intentional so it doesn't confuse the user. onClickCloseBtn() closes the whole floater. void LLFloaterIMContainer::onClickCloseBtn() @@ -2084,21 +2105,70 @@ void LLFloaterIMContainer::onClickCloseBtn() LLFloater::closeFloater(); } +void LLFloaterIMContainer::closeHostedFloater() +{ + onClickCloseBtn(); +} + +void LLFloaterIMContainer::closeAllConversations() +{ + LLDynamicArray<LLUUID> ids; + for (conversations_items_map::iterator it_session = mConversationsItems.begin(); it_session != mConversationsItems.end(); it_session++) + { + LLUUID session_id = it_session->first; + if (session_id != LLUUID()) + { + ids.push_back(session_id); + } + } + + for (LLDynamicArray<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); ++it) + { + LLFloaterIMSession *conversationFloater = LLFloaterIMSession::findInstance(*it); + LLFloater::onClickClose(conversationFloater); + } +} + +void LLFloaterIMContainer::closeSelectedConversations(const uuid_vec_t& ids) +{ + for (uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); ++it) + { + //We don't need to close Nearby chat, so skip it + if (*it != LLUUID()) + { + LLFloaterIMSession *conversationFloater = LLFloaterIMSession::findInstance(*it); + if(conversationFloater) + { + LLFloater::onClickClose(conversationFloater); + } + } + } +} void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/) { - // Check for currently active session - LLUUID session_id = getSelectedSession(); - // If current session is Nearby Chat or there is only one session remaining, close the floater - if (mConversationsItems.size() == 1 || session_id == LLUUID() || app_quitting) + if(app_quitting) { + closeAllConversations(); onClickCloseBtn(); } - - // Otherwise, close current conversation - LLFloaterIMSessionTab* active_conversation = LLFloaterIMSessionTab::getConversation(session_id); - if (active_conversation) + else { - active_conversation->closeFloater(); + // Check for currently active session + LLUUID session_id = getSelectedSession(); + // If current session is Nearby Chat or there is only one session remaining, close the floater + if (mConversationsItems.size() == 1 || session_id == LLUUID() || app_quitting) + { + onClickCloseBtn(); + } + else + { + // Otherwise, close current conversation + LLFloaterIMSessionTab* active_conversation = LLFloaterIMSessionTab::getConversation(session_id); + if (active_conversation) + { + active_conversation->closeFloater(); + } + } } } diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h index 74c3640bad..36da457cac 100755 --- a/indra/newview/llfloaterimcontainer.h +++ b/indra/newview/llfloaterimcontainer.h @@ -107,8 +107,6 @@ public: LLConversationItem* getSessionModel(const LLUUID& session_id) { return get_ptr_in_map(mConversationsItems,session_id); } LLConversationSort& getSortOrder() { return mConversationViewModel.getSorter(); } - void onNearbyChatClosed(); - // Handling of lists of participants is public so to be common with llfloatersessiontab // *TODO : Find a better place for this. bool checkContextMenuItem(const std::string& item, uuid_vec_t& selectedIDS); @@ -118,6 +116,10 @@ public: void assignResizeLimits(); virtual BOOL handleKeyHere(KEY key, MASK mask ); /*virtual*/ void closeFloater(bool app_quitting = false); + void closeAllConversations(); + void closeSelectedConversations(const uuid_vec_t& ids); + /*virtual*/ BOOL isFrontmost(); + private: typedef std::map<LLUUID,LLFloater*> avatarID_panel_map_t; @@ -133,6 +135,7 @@ private: void processParticipantsStyleUpdate(); void onSpeakButtonClicked(); /*virtual*/ void onClickCloseBtn(); + /*virtual*/ void closeHostedFloater(); void collapseConversationsPane(bool collapse, bool save_is_allowed=true); @@ -147,7 +150,7 @@ private: void setSortOrderParticipants(const LLConversationFilter::ESortOrderType order); void setSortOrder(const LLConversationSort& order); - void getSelectedUUIDs(uuid_vec_t& selected_uuids); + void getSelectedUUIDs(uuid_vec_t& selected_uuids, bool participant_uuids = true); const LLConversationItem * getCurSelectedViewModelItem(); void getParticipantUUIDs(uuid_vec_t& selected_uuids); void doToSelected(const LLSD& userdata); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index b3a43f6ac5..3d77ea4f0b 100755 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -125,7 +125,7 @@ BOOL LLFloaterIMNearbyChat::postBuild() setTitle(LLTrans::getString("NearbyChatTitle")); // obsolete, but may be needed for backward compatibility? - gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", true); + gSavedSettings.declareS32("nearbychat_showicons_and_names", 2, "NearByChat header settings", LLControlVariable::PERSIST_NONDFT); if (gSavedPerAccountSettings.getBOOL("LogShowHistory")) { @@ -138,19 +138,28 @@ BOOL LLFloaterIMNearbyChat::postBuild() // virtual void LLFloaterIMNearbyChat::closeHostedFloater() { - // Should check how many conversations are ongoing. Close all if 1 only (the Nearby Chat), select next one otherwise + // If detached from conversations window close anyway + if (!getHost()) + { + setVisible(FALSE); + } + + // Should check how many conversations are ongoing. Select next to "Nearby Chat" in case there are some other besides. + // Close conversations window in case "Nearby Chat" is attached and the only conversation LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance(); if (floater_container->getConversationListItemSize() == 1) { - floater_container->closeFloater(); + if (getHost()) + { + floater_container->closeFloater(); + } } else { if (!getHost()) { - setVisible(FALSE); + floater_container->selectNextConversationByID(LLUUID()); } - floater_container->selectNextConversationByID(LLUUID()); } } @@ -262,7 +271,7 @@ void LLFloaterIMNearbyChat::setVisibleAndFrontmost(BOOL take_focus, const LLSD& { LLFloaterIMSessionTab::setVisibleAndFrontmost(take_focus, key); - if(!isTornOff() && matchesKey(key)) + if(matchesKey(key)) { LLFloaterIMContainer::getInstance()->selectConversationPair(mSessionID, true, take_focus); } @@ -296,7 +305,6 @@ void LLFloaterIMNearbyChat::onClose(bool app_quitting) { // Override LLFloaterIMSessionTab::onClose() so that Nearby Chat is not removed from the conversation floater LLFloaterIMSessionTab::restoreFloater(); - onClickCloseBtn(); } // virtual @@ -306,13 +314,7 @@ void LLFloaterIMNearbyChat::onClickCloseBtn() { return; } - LLFloaterIMSessionTab::onTearOffClicked(); - - LLFloaterIMContainer *im_box = LLFloaterIMContainer::findInstance(); - if (im_box) - { - im_box->onNearbyChatClosed(); - } + closeHostedFloater(); } void LLFloaterIMNearbyChat::onChatFontChange(LLFontGL* fontp) @@ -350,11 +352,17 @@ bool LLFloaterIMNearbyChat::isChatVisible() const void LLFloaterIMNearbyChat::showHistory() { openFloater(); + LLFloaterIMContainer::getInstance()->selectConversation(LLUUID(NULL)); + if(!isMessagePaneExpanded()) { restoreFloater(); setFocus(true); } + else + { + LLFloaterIMContainer::getInstance()->setFocus(TRUE); + } setResizeLimits(getMinWidth(), EXPANDED_MIN_HEIGHT); } @@ -585,7 +593,7 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type ) if (!utf8_revised_text.empty()) { // Chat with animation - sendChatFromViewer(utf8_revised_text, type, TRUE); + sendChatFromViewer(utf8_revised_text, type, gSavedSettings.getBOOL("PlayChatAnim")); } } @@ -639,10 +647,7 @@ void LLFloaterIMNearbyChat::addMessage(const LLChat& chat,bool archive,const LLS void LLFloaterIMNearbyChat::onChatBoxCommit() { - if (mInputEditor->getText().length() > 0) - { - sendChat(CHAT_TYPE_NORMAL); - } + sendChat(CHAT_TYPE_NORMAL); gAgent.stopTyping(); } diff --git a/indra/newview/llfloaterimnearbychathandler.cpp b/indra/newview/llfloaterimnearbychathandler.cpp index 9ce5e12897..cc00b6fd10 100755 --- a/indra/newview/llfloaterimnearbychathandler.cpp +++ b/indra/newview/llfloaterimnearbychathandler.cpp @@ -606,6 +606,7 @@ void LLFloaterIMNearbyChatHandler::processChat(const LLChat& chat_msg, //Don't show nearby toast, if conversation is visible and selected if ((nearby_chat->hasFocus()) || + (LLFloater::isVisible(nearby_chat) && nearby_chat->isTornOff() && !nearby_chat->isMinimized()) || ((im_box->getSelectedSession().isNull() && ((LLFloater::isVisible(im_box) && !im_box->isMinimized() && im_box->isFrontmost()) || (LLFloater::isVisible(nearby_chat) && !nearby_chat->isMinimized() && nearby_chat->isFrontmost()))))) diff --git a/indra/newview/llfloaterimnearbychatlistener.cpp b/indra/newview/llfloaterimnearbychatlistener.cpp index 14a22bcd84..5a5f6c72c8 100755 --- a/indra/newview/llfloaterimnearbychatlistener.cpp +++ b/indra/newview/llfloaterimnearbychatlistener.cpp @@ -33,7 +33,7 @@ #include "llagent.h" #include "llchat.h" - +#include "llviewercontrol.h" LLFloaterIMNearbyChatListener::LLFloaterIMNearbyChatListener(LLFloaterIMNearbyChat & chatbar) @@ -95,6 +95,6 @@ void LLFloaterIMNearbyChatListener::sendChat(LLSD const & chat_data) const } // Send it as if it was typed in - mChatbar.sendChatFromViewer(chat_to_send, type_o_chat, (BOOL)(channel == 0)); + mChatbar.sendChatFromViewer(chat_to_send, type_o_chat, ((BOOL)(channel == 0)) && gSavedSettings.getBOOL("PlayChatAnim")); } diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 848d5c34d2..5cb9df5625 100755 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -109,18 +109,6 @@ void LLFloaterIMSession::refresh() void LLFloaterIMSession::onTearOffClicked() { LLFloaterIMSessionTab::onTearOffClicked(); - - if(mIsP2PChat) - { - if(isTornOff()) - { - mSpeakingIndicator->setSpeakerId(mOtherParticipantUUID, mSessionID); - } - else - { - mSpeakingIndicator->setSpeakerId(LLUUID::null); - } - } } // virtual diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index cc2859c099..0ccfdb9a7b 100755 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -55,7 +55,6 @@ LLFloaterIMSessionTab::LLFloaterIMSessionTab(const LLSD& session_id) , mSessionID(session_id.asUUID()) , mConversationsRoot(NULL) , mScroller(NULL) - , mSpeakingIndicator(NULL) , mChatHistory(NULL) , mInputEditor(NULL) , mInputEditorPad(0) @@ -259,8 +258,6 @@ BOOL LLFloaterIMSessionTab::postBuild() scroller_params.rect(scroller_view_rect); mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params); mScroller->setFollowsAll(); - - mSpeakingIndicator = getChild<LLOutputMonitorCtrl>("speaking_indicator"); // Insert that scroller into the panel widgets hierarchy mParticipantListPanel->addChild(mScroller); @@ -273,6 +270,7 @@ BOOL LLFloaterIMSessionTab::postBuild() mInputPanels = getChild<LLLayoutStack>("input_panels"); mInputEditor->setTextExpandedCallback(boost::bind(&LLFloaterIMSessionTab::reshapeChatLayoutPanel, this)); + mInputEditor->setMouseUpCallback(boost::bind(&LLFloaterIMSessionTab::onInputEditorClicked, this)); mInputEditor->setCommitOnFocusLost( FALSE ); mInputEditor->setPassDelete(TRUE); mInputEditor->setFont(LLViewerChat::getChatFont()); @@ -402,6 +400,16 @@ void LLFloaterIMSessionTab::onFocusLost() LLTransientDockableFloater::onFocusLost(); } +void LLFloaterIMSessionTab::onInputEditorClicked() +{ + LLFloaterIMContainer* im_box = LLFloaterIMContainer::findInstance(); + if (im_box) + { + im_box->flashConversationItemWidget(mSessionID,false); + } + gToolBarView->flashCommand(LLCommandId("chat"), false); +} + std::string LLFloaterIMSessionTab::appendTime() { time_t utc_time; diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h index ba80d2369a..e7b05a584b 100755 --- a/indra/newview/llfloaterimsessiontab.h +++ b/indra/newview/llfloaterimsessiontab.h @@ -171,8 +171,7 @@ protected: LLFolderView* mConversationsRoot; LLScrollContainer* mScroller; - LLOutputMonitorCtrl* mSpeakingIndicator; - LLChatHistory* mChatHistory; + LLChatHistory* mChatHistory; LLChatEntry* mInputEditor; LLLayoutPanel * mChatLayoutPanel; LLLayoutStack * mInputPanels; @@ -204,6 +203,8 @@ private: */ void reshapeChatLayoutPanel(); + void onInputEditorClicked(); + bool checkIfTornOff(); bool mIsHostAttached; bool mHasVisibleBeenInitialized; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 55b03986d0..4ebe813be6 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -452,6 +452,7 @@ BOOL LLFloaterPreference::postBuild() getChild<LLComboBox>("ConferenceIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"ConferenceIMOptions")); getChild<LLComboBox>("GroupChatOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"GroupChatOptions")); getChild<LLComboBox>("NearbyChatOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"NearbyChatOptions")); + getChild<LLComboBox>("ObjectIMOptions")->setCommitCallback(boost::bind(&LLFloaterPreference::onNotificationsChange, this,"ObjectIMOptions")); // if floater is opened before login set default localized do not disturb message if (LLStartUp::getStartupState() < STATE_STARTED) @@ -721,6 +722,7 @@ void LLFloaterPreference::onOpen(const LLSD& key) onNotificationsChange("ConferenceIMOptions"); onNotificationsChange("GroupChatOptions"); onNotificationsChange("NearbyChatOptions"); + onNotificationsChange("ObjectIMOptions"); LLPanelLogin::setAlwaysRefresh(true); refresh(); @@ -928,7 +930,7 @@ void LLFloaterPreference::onNotificationsChange(const std::string& OptionName) bool show_notifications_alert = true; for (notifications_map::iterator it_notification = mNotificationOptions.begin(); it_notification != mNotificationOptions.end(); it_notification++) { - if(it_notification->second != "None") + if(it_notification->second != "No action") { show_notifications_alert = false; break; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 515b669853..3cd64618aa 100755 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -130,10 +130,10 @@ void process_dnd_im(const LLSD& notification) fromID, false, false); //will need slight refactor to retrieve whether offline message or not (assume online for now) - } + } notify_of_message(data, true); -} + } @@ -155,73 +155,104 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id, void notify_of_message(const LLSD& msg, bool is_dnd_msg) { - std::string user_preferences; + std::string user_preferences; LLUUID participant_id = msg[is_dnd_msg ? "FROM_ID" : "from_id"].asUUID(); LLUUID session_id = msg[is_dnd_msg ? "SESSION_ID" : "session_id"].asUUID(); - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id); - // do not show notification which goes from agent - if (gAgent.getID() == participant_id) - { - return; - } + // do not show notification which goes from agent + if (gAgent.getID() == participant_id) + { + return; + } - // determine state of conversations floater - enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status; + // determine state of conversations floater + enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status; - LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); + LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container"); LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::getConversation(session_id); bool store_dnd_message = false; // flag storage of a dnd message - + bool is_session_focused = session_floater->isTornOff() && session_floater->hasFocus(); if (!LLFloater::isVisible(im_box) || im_box->isMinimized()) { conversations_floater_status = CLOSED; } else if (!im_box->hasFocus() && - !(session_floater && LLFloater::isVisible(session_floater) - && !session_floater->isMinimized() && session_floater->hasFocus())) + !(session_floater && LLFloater::isVisible(session_floater) + && !session_floater->isMinimized() && session_floater->hasFocus())) { conversations_floater_status = NOT_ON_TOP; } else if (im_box->getSelectedSession() != session_id) { conversations_floater_status = ON_TOP; - } + } else { conversations_floater_status = ON_TOP_AND_ITEM_IS_SELECTED; } - // determine user prefs for this session - if (session_id.isNull()) - { - user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions"); - } - else if(session->isP2PSessionType()) - { - if (LLAvatarTracker::instance().isBuddy(participant_id)) + // determine user prefs for this session + if (session_id.isNull()) + { + if (msg["source_type"].asInteger() == CHAT_SOURCE_OBJECT) { - user_preferences = gSavedSettings.getString("NotificationFriendIMOptions"); + user_preferences = gSavedSettings.getString("NotificationObjectIMOptions"); + if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundObjectIM") == TRUE)) + { + make_ui_sound("UISndNewIncomingIMSession"); + } } else { - user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions"); + user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions"); + if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNearbyChatIM") == TRUE)) + { + make_ui_sound("UISndNewIncomingIMSession"); + } } } - else if(session->isAdHocSessionType()) - { - user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions"); + else if(session->isP2PSessionType()) + { + if (LLAvatarTracker::instance().isBuddy(participant_id)) + { + user_preferences = gSavedSettings.getString("NotificationFriendIMOptions"); + if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundFriendIM") == TRUE)) + { + make_ui_sound("UISndNewIncomingIMSession"); + } + } + else + { + user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions"); + if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNonFriendIM") == TRUE)) + { + make_ui_sound("UISndNewIncomingIMSession"); + } + } } - else if(session->isGroupSessionType()) - { - user_preferences = gSavedSettings.getString("NotificationGroupChatOptions"); + else if(session->isAdHocSessionType()) + { + user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions"); + if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundConferenceIM") == TRUE)) + { + make_ui_sound("UISndNewIncomingIMSession"); + } } + else if(session->isGroupSessionType()) + { + user_preferences = gSavedSettings.getString("NotificationGroupChatOptions"); + if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundGroupChatIM") == TRUE)) + { + make_ui_sound("UISndNewIncomingIMSession"); + } + } - // actions: + // actions: // 0. nothing - exit - if (("none" == user_preferences || + if (("noaction" == user_preferences || ON_TOP_AND_ITEM_IS_SELECTED == conversations_floater_status) && session_floater->isMessagePaneExpanded()) { @@ -256,22 +287,23 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg) } } } - else - { + else + { store_dnd_message = true; - } + } - } + } - // 2. Flash line item - if ("openconversations" == user_preferences - || ON_TOP == conversations_floater_status - || ("toast" == user_preferences && ON_TOP != conversations_floater_status) - || ("flash" == user_preferences && CLOSED == conversations_floater_status) + // 2. Flash line item + if ("openconversations" == user_preferences + || ON_TOP == conversations_floater_status + || ("toast" == user_preferences && ON_TOP != conversations_floater_status) + || ("flash" == user_preferences && (CLOSED == conversations_floater_status + || NOT_ON_TOP == conversations_floater_status)) || is_dnd_msg) - { - if(!LLMuteList::getInstance()->isMuted(participant_id)) - { + { + if(!LLMuteList::getInstance()->isMuted(participant_id)) + { if(gAgent.isDoNotDisturb()) { store_dnd_message = true; @@ -286,41 +318,43 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg) } else { - im_box->flashConversationItemWidget(session_id, true); - } - } + im_box->flashConversationItemWidget(session_id, true); + } + } } } - // 3. Flash FUI button - if (("toast" == user_preferences || "flash" == user_preferences) && - (CLOSED == conversations_floater_status + // 3. Flash FUI button + if (("toast" == user_preferences || "flash" == user_preferences) && + (CLOSED == conversations_floater_status || NOT_ON_TOP == conversations_floater_status) + && !is_session_focused && !is_dnd_msg) //prevent flashing FUI button because the conversation floater will have already opened { if(!LLMuteList::getInstance()->isMuted(participant_id)) - { + { if(!gAgent.isDoNotDisturb()) - { - gToolBarView->flashCommand(LLCommandId("chat"), true); - } + { + gToolBarView->flashCommand(LLCommandId("chat"), true, im_box->isMinimized()); + } else { store_dnd_message = true; } - } + } } - // 4. Toast - if ((("toast" == user_preferences) && - (ON_TOP_AND_ITEM_IS_SELECTED != conversations_floater_status)) - || !session_floater->isMessagePaneExpanded()) + // 4. Toast + if ((("toast" == user_preferences) && + (ON_TOP_AND_ITEM_IS_SELECTED != conversations_floater_status) && + (!session_floater->isTornOff() || !LLFloater::isVisible(session_floater))) + || !session_floater->isMessagePaneExpanded()) - { - //Show IM toasts (upper right toasts) - // Skip toasting for system messages and for nearby chat - if(session_id.notNull() && participant_id.notNull()) - { + { + //Show IM toasts (upper right toasts) + // Skip toasting for system messages and for nearby chat + if(session_id.notNull() && participant_id.notNull()) + { if(!is_dnd_msg) { if(gAgent.isDoNotDisturb()) @@ -329,10 +363,10 @@ void notify_of_message(const LLSD& msg, bool is_dnd_msg) } else { - LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); - } - } - } + LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg)); + } + } +} } if (store_dnd_message) { @@ -2635,6 +2669,13 @@ void LLIMMgr::addMessage( fixed_session_name = session_name; name_is_setted = true; } + bool skip_message = false; + if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly")) + { + // Evaluate if we need to skip this message when that setting is true (default is false) + skip_message = (LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL); // Skip non friends... + skip_message &= !(other_participant_id == gAgentID); // You are your best friend... Don't skip yourself + } bool new_session = !hasSession(new_session_id); if (new_session) @@ -2646,6 +2687,12 @@ void LLIMMgr::addMessage( } LLIMModel::getInstance()->newSession(new_session_id, fixed_session_name, dialog, other_participant_id, false, is_offline_msg); + LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(new_session_id); + skip_message &= !session->isGroupSessionType(); // Do not skip group chats... + if(skip_message) + { + gIMMgr->leaveSession(new_session_id); + } // When we get a new IM, and if you are a god, display a bit // of information about the source. This is to help liaisons // when answering questions. @@ -2686,23 +2733,13 @@ void LLIMMgr::addMessage( } } - bool skip_message = false; - if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly")) - { - // Evaluate if we need to skip this message when that setting is true (default is false) - LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(new_session_id); - skip_message = (LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL); // Skip non friends... - skip_message &= !session->isGroupSessionType(); // Do not skip group chats... - skip_message &= !(other_participant_id == gAgentID); // You are your best friend... Don't skip yourself - } - if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !skip_message) { LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg); } // Open conversation floater if offline messages are present - if (is_offline_msg) + if (is_offline_msg && !skip_message) { LLFloaterReg::showInstance("im_container"); LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container")-> @@ -3009,10 +3046,9 @@ void LLIMMgr::inviteToSession( { bool isRejectGroupCall = (gSavedSettings.getBOOL("VoiceCallsRejectGroup") && (notify_box_type == "VoiceInviteGroup")); bool isRejectNonFriendCall = (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && (LLAvatarTracker::instance().getBuddyInfo(caller_id) == NULL)); - bool isRejectDoNotDisturb = (gAgent.isDoNotDisturb() && !hasSession(session_id)); - if (isRejectGroupCall || isRejectNonFriendCall || isRejectDoNotDisturb) + if (isRejectGroupCall || isRejectNonFriendCall || gAgent.isDoNotDisturb()) { - if (isRejectDoNotDisturb && !isRejectGroupCall && !isRejectNonFriendCall) + if (gAgent.isDoNotDisturb() && !isRejectGroupCall && !isRejectNonFriendCall) { LLSD args; addSystemMessage(session_id, "you_auto_rejected_call", args); diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index 379bbc5f8d..90b169ecd3 100755 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -25,7 +25,7 @@ */ #include "llviewerprecompiledheaders.h" - +#include "llfloaterconversationpreview.h" #include "llagent.h" #include "llagentui.h" #include "llavatarnamecache.h" @@ -206,6 +206,7 @@ private: }; LLLogChat::save_history_signal_t * LLLogChat::sSaveHistorySignal = NULL; +LLLoadHistoryThread::load_end_signal_t * LLLoadHistoryThread::mLoadEndSignal = NULL; //static std::string LLLogChat::makeLogFileName(std::string filename) @@ -336,75 +337,83 @@ void LLLogChat::saveHistory(const std::string& filename, void LLLogChat::loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params) { if (file_name.empty()) - { - llwarns << "Session name is Empty!" << llendl; - return ; - } + { + LL_WARNS("LLLogChat::loadChatHistory") << "Session name is Empty!" << LL_ENDL; + return ; + } - bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false; + bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false; - LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r");/*Flawfinder: ignore*/ - if (!fptr) - { - fptr = LLFile::fopen(oldLogFileName(file_name), "r");/*Flawfinder: ignore*/ - if (!fptr) - { - return; //No previous conversation with this name. - } - } - - char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/ - char *bptr; - S32 len; - bool firstline = TRUE; - - if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END)) - { //We need to load the whole historyFile or it's smaller than recall size, so get it all. - firstline = FALSE; - if (fseek(fptr, 0, SEEK_SET)) - { - fclose(fptr); - return; - } - } + LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");/*Flawfinder: ignore*/ + if (!fptr) + { + fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/ + if (!fptr) + { + return; //No previous conversation with this name. + } + } - while (fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr)) - { - len = strlen(buffer) - 1; /*Flawfinder: ignore*/ - for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--) *bptr='\0'; - - if (firstline) - { - firstline = FALSE; - continue; - } + char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/ + char *bptr; + S32 len; + bool firstline = TRUE; + + if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END)) + { //We need to load the whole historyFile or it's smaller than recall size, so get it all. + firstline = FALSE; + if (fseek(fptr, 0, SEEK_SET)) + { + fclose(fptr); + return; + } + } + while (fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr)) + { + len = strlen(buffer) - 1; /*Flawfinder: ignore*/ + for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--) *bptr='\0'; + + if (firstline) + { + firstline = FALSE; + continue; + } + + std::string line(buffer); + + //updated 1.23 plain text log format requires a space added before subsequent lines in a multilined message + if (' ' == line[0]) + { + line.erase(0, MULTI_LINE_PREFIX.length()); + append_to_last_message(messages, '\n' + line); + } + else if (0 == len && ('\n' == line[0] || '\r' == line[0])) + { + //to support old format's multilined messages with new lines used to divide paragraphs + append_to_last_message(messages, line); + } + else + { + LLSD item; + if (!LLChatLogParser::parse(line, item, load_params)) + { + item[LL_IM_TEXT] = line; + } + messages.push_back(item); + } + } + fclose(fptr); - std::string line(buffer); - //updated 1.23 plaint text log format requires a space added before subsequent lines in a multilined message - if (' ' == line[0]) - { - line.erase(0, MULTI_LINE_PREFIX.length()); - append_to_last_message(messages, '\n' + line); - } - else if (0 == len && ('\n' == line[0] || '\r' == line[0])) - { - //to support old format's multilined messages with new lines used to divide paragraphs - append_to_last_message(messages, line); - } - else - { - LLSD item; - if (!LLChatLogParser::parse(line, item, load_params)) - { - item[LL_IM_TEXT] = line; - } - messages.push_back(item); - } - } - fclose(fptr); } +void LLLogChat::startChatHistoryThread(const std::string& file_name, const LLSD& load_params) +{ + + LLLoadHistoryThread* mThread = new LLLoadHistoryThread(); + mThread->start(); + mThread->setHistoryParams(file_name, load_params); +} // static std::string LLLogChat::oldLogFileName(std::string filename) { @@ -461,6 +470,13 @@ void LLLogChat::findTranscriptFiles(std::string pattern, std::vector<std::string LLFILE * filep = LLFile::fopen(fullname, "rb"); if (NULL != filep) { + if(makeLogFileName("chat")== fullname) + { + //Add Nearby chat history to the list of transcriptions + list_of_transcriptions.push_back(gDirUtilp->add(dirname, filename)); + LLFile::close(filep); + return; + } char buffer[LOG_RECALL_SIZE]; fseek(filep, 0, SEEK_END); // seek to end of file @@ -828,3 +844,116 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params im[LL_IM_TEXT] = name_and_text[IDX_TEXT]; return true; //parsed name and message text, maybe have a timestamp too } + + + + LLLoadHistoryThread::LLLoadHistoryThread() : LLThread("load chat history") + { + mNewLoad = false; + } + + void LLLoadHistoryThread::run() + { + while (!LLApp::isQuitting()) + { + if(mNewLoad) + { + loadHistory(mFileName,mMessages,mLoadParams); + shutdown(); + } + } + } + void LLLoadHistoryThread::setHistoryParams(const std::string& file_name, const LLSD& load_params) + { + mFileName = file_name; + mLoadParams = load_params; + mNewLoad = true; + } + void LLLoadHistoryThread::loadHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params) + { + + if (file_name.empty()) + { + LL_WARNS("LLLogChat::loadHistory") << "Session name is Empty!" << LL_ENDL; + return ; + } + + bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false; + + LLFILE* fptr = LLFile::fopen(LLLogChat::makeLogFileName(file_name), "r");/*Flawfinder: ignore*/ + if (!fptr) + { + fptr = LLFile::fopen(LLLogChat::oldLogFileName(file_name), "r");/*Flawfinder: ignore*/ + if (!fptr) + { + mNewLoad = false; + (*mLoadEndSignal)(messages, file_name); + return; //No previous conversation with this name. + } + } + + char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/ + char *bptr; + S32 len; + bool firstline = TRUE; + + if (load_all_history || fseek(fptr, (LOG_RECALL_SIZE - 1) * -1 , SEEK_END)) + { //We need to load the whole historyFile or it's smaller than recall size, so get it all. + firstline = FALSE; + if (fseek(fptr, 0, SEEK_SET)) + { + fclose(fptr); + mNewLoad = false; + (*mLoadEndSignal)(messages, file_name); + return; + } + } + while (fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr)) + { + len = strlen(buffer) - 1; /*Flawfinder: ignore*/ + for (bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--) *bptr='\0'; + + if (firstline) + { + firstline = FALSE; + continue; + } + + std::string line(buffer); + + //updated 1.23 plaint text log format requires a space added before subsequent lines in a multilined message + if (' ' == line[0]) + { + line.erase(0, MULTI_LINE_PREFIX.length()); + append_to_last_message(messages, '\n' + line); + } + else if (0 == len && ('\n' == line[0] || '\r' == line[0])) + { + //to support old format's multilined messages with new lines used to divide paragraphs + append_to_last_message(messages, line); + } + else + { + LLSD item; + if (!LLChatLogParser::parse(line, item, load_params)) + { + item[LL_IM_TEXT] = line; + } + messages.push_back(item); + } + } + fclose(fptr); + mNewLoad = false; + (*mLoadEndSignal)(messages, file_name); + } + + //static + boost::signals2::connection LLLoadHistoryThread::setLoadEndSignal(const load_end_signal_t::slot_type& cb) + { + if (NULL == mLoadEndSignal) + { + mLoadEndSignal = new load_end_signal_t(); + } + + return mLoadEndSignal->connect(cb); + } diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h index bd70dbaac9..acee99afa2 100755 --- a/indra/newview/lllogchat.h +++ b/indra/newview/lllogchat.h @@ -28,6 +28,24 @@ #define LL_LLLOGCHAT_H class LLChat; +class LLLoadHistoryThread : public LLThread +{ +private: + std::string mFileName; + std::list<LLSD> mMessages; + LLSD mLoadParams; + bool mNewLoad; +public: + LLLoadHistoryThread(); + + void setHistoryParams(const std::string& file_name, const LLSD& load_params); + virtual void loadHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params); + virtual void run(); + + typedef boost::signals2::signal<void (std::list<LLSD>& messages,const std::string& file_name)> load_end_signal_t; + static load_end_signal_t * mLoadEndSignal; + static boost::signals2::connection setLoadEndSignal(const load_end_signal_t::slot_type& cb); +}; class LLLogChat { @@ -39,6 +57,7 @@ public: LOG_LLSD, LOG_END }; + static std::string timestamp(bool withdate = false); static std::string makeLogFileName(std::string(filename)); /** @@ -54,6 +73,7 @@ public: static void getListOfTranscriptBackupFiles(std::vector<std::string>& list_of_transcriptions); static void loadChatHistory(const std::string& file_name, std::list<LLSD>& messages, const LLSD& load_params = LLSD()); + static void startChatHistoryThread(const std::string& file_name, const LLSD& load_params); typedef boost::signals2::signal<void ()> save_history_signal_t; static boost::signals2::connection setSaveHistorySignal(const save_history_signal_t::slot_type& cb); @@ -127,6 +147,7 @@ protected: virtual ~LLChatLogParser() {}; }; + // LLSD map lookup constants extern const std::string LL_IM_TIME; //("time"); extern const std::string LL_IM_TEXT; //("message"); diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index d79f1040bb..4cbdfde868 100755 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -1376,74 +1376,28 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y ) BOOL hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis); projected_mouse -= snap_plane_center; - S32 snap_plane = 0; - - F32 dot = cam_to_snap_plane * constraint_axis; - if (llabs(dot) < 0.01f) - { - // looking at ring edge on, project onto view plane and check if mouse is past ring - getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane); - projected_mouse -= snap_plane_center; - dot = projected_mouse * constraint_axis; - if (projected_mouse * constraint_axis > 0) - { - snap_plane = 1; - } - projected_mouse -= dot * constraint_axis; - } - else if (dot > 0.f) - { - // look for mouse position outside and in front of snap circle - if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f) - { - snap_plane = 1; - } - } - else - { - // look for mouse position inside or in back of snap circle - if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit) - { - snap_plane = 1; - } - } - - if (snap_plane == 0) - { - // try other plane - snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f)); - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - cam_to_snap_plane.setVec(1.f, 0.f, 0.f); - } - else - { - cam_to_snap_plane = snap_plane_center - gAgentCamera.getCameraPositionAgent(); - cam_to_snap_plane.normVec(); - } - - hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis); - projected_mouse -= snap_plane_center; - - dot = cam_to_snap_plane * constraint_axis; + if (gSavedSettings.getBOOL("SnapEnabled")) { + S32 snap_plane = 0; + + F32 dot = cam_to_snap_plane * constraint_axis; if (llabs(dot) < 0.01f) { // looking at ring edge on, project onto view plane and check if mouse is past ring getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane); projected_mouse -= snap_plane_center; dot = projected_mouse * constraint_axis; - if (projected_mouse * constraint_axis < 0) + if (projected_mouse * constraint_axis > 0) { - snap_plane = 2; + snap_plane = 1; } projected_mouse -= dot * constraint_axis; } - else if (dot < 0.f) + else if (dot > 0.f) { // look for mouse position outside and in front of snap circle if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f) { - snap_plane = 2; + snap_plane = 1; } } else @@ -1451,78 +1405,136 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y ) // look for mouse position inside or in back of snap circle if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit) { - snap_plane = 2; + snap_plane = 1; } } - } - - if (snap_plane > 0) - { - LLVector3 cam_at_axis; - if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) - { - cam_at_axis.setVec(1.f, 0.f, 0.f); - } - else - { - cam_at_axis = snap_plane_center - gAgentCamera.getCameraPositionAgent(); - cam_at_axis.normVec(); - } - - // first, project mouse onto screen plane at point tangent to rotation radius. - getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_at_axis); - // project that point onto rotation plane - projected_mouse -= snap_plane_center; - projected_mouse -= projected_vec(projected_mouse, constraint_axis); - - F32 mouse_lateral_dist = llmin(SNAP_GUIDE_INNER_RADIUS * mRadiusMeters, projected_mouse.magVec()); - F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters; - if (llabs(mouse_lateral_dist) > 0.01f) - { - mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) - - (mouse_lateral_dist * mouse_lateral_dist)); - } - LLVector3 projected_camera_at = cam_at_axis - projected_vec(cam_at_axis, constraint_axis); - projected_mouse -= mouse_depth * projected_camera_at; - - if (!mInSnapRegime) + + if (snap_plane == 0) { - mSmoothRotate = TRUE; + // try other plane + snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f)); + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + cam_to_snap_plane.setVec(1.f, 0.f, 0.f); + } + else + { + cam_to_snap_plane = snap_plane_center - gAgentCamera.getCameraPositionAgent(); + cam_to_snap_plane.normVec(); + } + + hit = getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, constraint_axis); + projected_mouse -= snap_plane_center; + + dot = cam_to_snap_plane * constraint_axis; + if (llabs(dot) < 0.01f) + { + // looking at ring edge on, project onto view plane and check if mouse is past ring + getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_to_snap_plane); + projected_mouse -= snap_plane_center; + dot = projected_mouse * constraint_axis; + if (projected_mouse * constraint_axis < 0) + { + snap_plane = 2; + } + projected_mouse -= dot * constraint_axis; + } + else if (dot < 0.f) + { + // look for mouse position outside and in front of snap circle + if (hit && projected_mouse.magVec() > SNAP_GUIDE_INNER_RADIUS * mRadiusMeters && projected_mouse * cam_to_snap_plane < 0.f) + { + snap_plane = 2; + } + } + else + { + // look for mouse position inside or in back of snap circle + if (projected_mouse.magVec() < SNAP_GUIDE_INNER_RADIUS * mRadiusMeters || projected_mouse * cam_to_snap_plane > 0.f || !hit) + { + snap_plane = 2; + } + } } - mInSnapRegime = TRUE; - // 0 to 360 deg - F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f); - F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT); - //fmodf(llround(mouse_angle * RAD_TO_DEG, 7.5f) + 360.f, 360.f); - - LLVector3 object_axis; - getObjectAxisClosestToMouse(object_axis); - object_axis = object_axis * first_object_node->mSavedRotation; - - // project onto constraint plane - object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis(); - object_axis.normVec(); - - if (relative_mouse_angle < SNAP_ANGLE_DETENTE) + if (snap_plane > 0) { - F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f)); - angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); + LLVector3 cam_at_axis; + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) + { + cam_at_axis.setVec(1.f, 0.f, 0.f); + } + else + { + cam_at_axis = snap_plane_center - gAgentCamera.getCameraPositionAgent(); + cam_at_axis.normVec(); + } + + // first, project mouse onto screen plane at point tangent to rotation radius. + getMousePointOnPlaneAgent(projected_mouse, x, y, snap_plane_center, cam_at_axis); + // project that point onto rotation plane + projected_mouse -= snap_plane_center; + projected_mouse -= projected_vec(projected_mouse, constraint_axis); + + F32 mouse_lateral_dist = llmin(SNAP_GUIDE_INNER_RADIUS * mRadiusMeters, projected_mouse.magVec()); + F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters; + if (llabs(mouse_lateral_dist) > 0.01f) + { + mouse_depth = sqrtf((SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) * (SNAP_GUIDE_INNER_RADIUS * mRadiusMeters) - + (mouse_lateral_dist * mouse_lateral_dist)); + } + LLVector3 projected_camera_at = cam_at_axis - projected_vec(cam_at_axis, constraint_axis); + projected_mouse -= mouse_depth * projected_camera_at; + + if (!mInSnapRegime) + { + mSmoothRotate = TRUE; + } + mInSnapRegime = TRUE; + // 0 to 360 deg + F32 mouse_angle = fmodf(atan2(projected_mouse * axis1, projected_mouse * axis2) * RAD_TO_DEG + 360.f, 360.f); + + F32 relative_mouse_angle = fmodf(mouse_angle + (SNAP_ANGLE_DETENTE / 2), SNAP_ANGLE_INCREMENT); + //fmodf(llround(mouse_angle * RAD_TO_DEG, 7.5f) + 360.f, 360.f); + + LLVector3 object_axis; + getObjectAxisClosestToMouse(object_axis); + object_axis = object_axis * first_object_node->mSavedRotation; + + // project onto constraint plane + object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis(); + object_axis.normVec(); + + if (relative_mouse_angle < SNAP_ANGLE_DETENTE) + { + F32 quantized_mouse_angle = mouse_angle - (relative_mouse_angle - (SNAP_ANGLE_DETENTE * 0.5f)); + angle = (quantized_mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); + } + else + { + angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); + } + return LLQuaternion( -angle, constraint_axis ); } else { - angle = (mouse_angle * DEG_TO_RAD) - atan2(object_axis * axis1, object_axis * axis2); + if (mInSnapRegime) + { + mSmoothRotate = TRUE; + } + mInSnapRegime = FALSE; } - return LLQuaternion( -angle, constraint_axis ); } - else - { + else { if (mInSnapRegime) { mSmoothRotate = TRUE; } mInSnapRegime = FALSE; - + } + + if (!mInSnapRegime) + { LLVector3 up_from_axis = mCenterToCamNorm % constraint_axis; up_from_axis.normVec(); LLVector3 cur_intersection; diff --git a/indra/newview/llnotificationstorage.h b/indra/newview/llnotificationstorage.h index 7aabf7d09e..53fd898ea4 100755 --- a/indra/newview/llnotificationstorage.h +++ b/indra/newview/llnotificationstorage.h @@ -44,6 +44,7 @@ public: protected: bool writeNotifications(const LLSD& pNotificationData) const; bool readNotifications(LLSD& pNotificationData) const; + void setFileName(std::string pFileName) {mFileName = pFileName;} LLNotificationResponderInterface* createResponder(const std::string& pNotificationName, const LLSD& pParams) const; diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp index a85335f1ba..4ca961c1f9 100755 --- a/indra/newview/llnotificationtiphandler.cpp +++ b/indra/newview/llnotificationtiphandler.cpp @@ -83,13 +83,6 @@ bool LLTipHandler::processNotification(const LLNotificationPtr& notification) if (notification->canLogToChat()) { LLHandlerUtil::logToNearbyChat(notification, CHAT_SOURCE_SYSTEM); - - // don't show toast if Nearby Chat is opened - LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); - if (nearby_chat->isChatVisible()) - { - return false; - } } std::string session_name = notification->getPayload()["SESSION_NAME"]; diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index cfdac11d26..fdcd1f5ebb 100755 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -1101,27 +1101,61 @@ void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata) } void LLPanelGroupMembersSubTab::handleEjectMembers() -{ - //send down an eject message - uuid_vec_t selected_members; - +{ std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected(); if (selection.empty()) return; - - std::vector<LLScrollListItem*>::iterator itor; - for (itor = selection.begin() ; - itor != selection.end(); ++itor) + + S32 selection_count = selection.size(); + if (selection_count == 1) { - LLUUID member_id = (*itor)->getUUID(); - selected_members.push_back( member_id ); + LLSD args; + LLUUID selected_avatar = mMembersList->getValue().asUUID(); + std::string fullname = LLSLURL("agent", selected_avatar, "inspect").getSLURLString(); + args["AVATAR_NAME"] = fullname; + LLSD payload; + LLNotificationsUtil::add("EjectGroupMemberWarning", + args, + payload, + boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2)); } + else + { + LLSD args; + args["COUNT"] = llformat("%d", selection_count); + LLSD payload; + LLNotificationsUtil::add("EjectGroupMembersWarning", + args, + payload, + boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2)); + } +} - mMembersList->deleteSelectedItems(); - - sendEjectNotifications(mGroupID, selected_members); - - LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID, - selected_members); +bool LLPanelGroupMembersSubTab::handleEjectCallback(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (0 == option) // Eject button + { + //send down an eject message + uuid_vec_t selected_members; + + std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected(); + if (selection.empty()) return false; + + std::vector<LLScrollListItem*>::iterator itor; + for (itor = selection.begin() ; + itor != selection.end(); ++itor) + { + LLUUID member_id = (*itor)->getUUID(); + selected_members.push_back( member_id ); + } + + mMembersList->deleteSelectedItems(); + + sendEjectNotifications(mGroupID, selected_members); + + LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID, selected_members); + } + return false; } void LLPanelGroupMembersSubTab::sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members) diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h index 78bb3c57a1..0cf272f3ee 100755 --- a/indra/newview/llpanelgrouproles.h +++ b/indra/newview/llpanelgrouproles.h @@ -167,6 +167,7 @@ public: static void onEjectMembers(void*); void handleEjectMembers(); void sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members); + bool handleEjectCallback(const LLSD& notification, const LLSD& response); static void onRoleCheck(LLUICtrl* check, void* user_data); void handleRoleCheck(const LLUUID& role_id, diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index bcb90bcb56..911ecaad9d 100755 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -82,10 +82,6 @@ const S32 MAX_PASSWORD = 16; LLPanelLogin *LLPanelLogin::sInstance = NULL; BOOL LLPanelLogin::sCapslockDidNotification = FALSE; -// Helper for converting a user name into the canonical "Firstname Lastname" form. -// For new accounts without a last name "Resident" is added as a last name. -static std::string canonicalize_username(const std::string& name); - class LLLoginRefreshHandler : public LLCommandHandler { public: @@ -266,7 +262,6 @@ void LLPanelLogin::addFavoritesToStartLocation() // Load favorites into the combo. std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple(); - std::string canonical_user_name = canonicalize_username(user_defined_name); std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml"); LLSD fav_llsd; llifstream file; @@ -279,7 +274,7 @@ void LLPanelLogin::addFavoritesToStartLocation() // The account name in stored_favorites.xml has Resident last name even if user has // a single word account name, so it can be compared case-insensitive with the // user defined "firstname lastname". - S32 res = LLStringUtil::compareInsensitive(canonical_user_name, iter->first); + S32 res = LLStringUtil::compareInsensitive(user_defined_name, iter->first); if (res != 0) { lldebugs << "Skipping favorites for " << iter->first << llendl; @@ -1012,29 +1007,3 @@ void LLPanelLogin::onLocationSLURL() LLStartUp::setStartSLURL(location); // calls onUpdateStartSLURL, above } - - -std::string canonicalize_username(const std::string& name) -{ - std::string cname = name; - LLStringUtil::trim(cname); - - // determine if the username is a first/last form or not. - size_t separator_index = cname.find_first_of(" ._"); - std::string first = cname.substr(0, separator_index); - std::string last; - if (separator_index != cname.npos) - { - last = cname.substr(separator_index+1, cname.npos); - LLStringUtil::trim(last); - } - else - { - // ...on Linden grids, single username users as considered to have - // last name "Resident" - last = "Resident"; - } - - // Username in traditional "firstname lastname" form. - return first + ' ' + last; -} diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 72953ec6d3..f551fc96ee 100755 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -86,6 +86,8 @@ static const std::string BLOCKED_TAB_NAME = "blocked_panel"; // blocked avatars static const std::string COLLAPSED_BY_USER = "collapsed_by_user"; +extern S32 gMaxAgentGroups; + /** Comparator for comparing avatar items by last interaction date */ class LLAvatarItemRecentComparator : public LLAvatarItemComparator { @@ -900,6 +902,8 @@ void LLPanelPeople::updateButtons() LLPanel* groups_panel = mTabContainer->getCurrentPanel(); groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); // a real group selected + groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.count())); + groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[REMAINING]", llformat("%d",(gMaxAgentGroups-gAgent.mGroups.count()))); } else { diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index e2e7006773..5acc98904b 100755 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -36,6 +36,8 @@ #include "lltabcontainer.h" #include "llviewercontrol.h" #include "llviewernetwork.h" +#include "llmutelist.h" +#include "llpanelblockedlist.h" static const std::string PANEL_PICKS = "panel_picks"; @@ -137,6 +139,12 @@ public: return true; } + if (verb == "removefriend") + { + LLAvatarActions::removeFriendDialog(avatar_id); + return true; + } + if (verb == "mute") { if (! LLAvatarActions::isBlocked(avatar_id)) @@ -155,6 +163,18 @@ public: return true; } + if (verb == "block") + { + if (params.size() > 2) + { + const std::string object_name = params[2].asString(); + LLMute mute(avatar_id, object_name, LLMute::OBJECT); + LLMuteList::getInstance()->add(mute); + LLPanelBlockedList::showPanelAndSelect(mute.mID); + } + return true; + } + return false; } }; diff --git a/indra/newview/llpersistentnotificationstorage.cpp b/indra/newview/llpersistentnotificationstorage.cpp index 666f10df96..076c3e0235 100755 --- a/indra/newview/llpersistentnotificationstorage.cpp +++ b/indra/newview/llpersistentnotificationstorage.cpp @@ -38,7 +38,8 @@ LLPersistentNotificationStorage::LLPersistentNotificationStorage() : LLSingleton<LLPersistentNotificationStorage>() - , LLNotificationStorage(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml")) + , LLNotificationStorage("") + , mLoaded(false) { } @@ -89,8 +90,13 @@ void LLPersistentNotificationStorage::loadNotifications() LL_INFOS("LLPersistentNotificationStorage") << "start loading notifications" << LL_ENDL; - LLNotifications::instance().getChannel("Persistent")-> - connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1)); + if (mLoaded) + { + LL_INFOS("LLPersistentNotificationStorage") << "notifications already loaded, exiting" << LL_ENDL; + return; + } + + mLoaded = true; LLSD input; if (!readNotifications(input) ||input.isUndefined()) @@ -135,8 +141,20 @@ void LLPersistentNotificationStorage::loadNotifications() LL_INFOS("LLPersistentNotificationStorage") << "finished loading notifications" << LL_ENDL; } +void LLPersistentNotificationStorage::initialize() +{ + setFileName(gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml")); + LLNotifications::instance().getChannel("Persistent")-> + connectChanged(boost::bind(&LLPersistentNotificationStorage::onPersistentChannelChanged, this, _1)); +} + bool LLPersistentNotificationStorage::onPersistentChannelChanged(const LLSD& payload) { + // In case we received channel changed signal but haven't yet loaded notifications, do it + if (!mLoaded) + { + loadNotifications(); + } // we ignore "load" messages, but rewrite the persistence file on any other const std::string sigtype = payload["sigtype"].asString(); if ("load" != sigtype) diff --git a/indra/newview/llpersistentnotificationstorage.h b/indra/newview/llpersistentnotificationstorage.h index 98a825d2c1..bf0306380e 100755 --- a/indra/newview/llpersistentnotificationstorage.h +++ b/indra/newview/llpersistentnotificationstorage.h @@ -53,10 +53,13 @@ public: void saveNotifications(); void loadNotifications(); + void initialize(); + protected: private: bool onPersistentChannelChanged(const LLSD& payload); + bool mLoaded; }; #endif // LL_LLPERSISTENTNOTIFICATIONSTORAGE_H diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 968a912ea2..e533be7f24 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -86,6 +86,7 @@ #include "lltrans.h" #include "llviewercontrol.h" #include "llappviewer.h" +#include "llfloatergotoline.h" const std::string HELLO_LSL = "default\n" @@ -193,12 +194,17 @@ private: LLScriptEdCore* mEditorCore; static LLFloaterScriptSearch* sInstance; + +protected: + LLLineEditor* mSearchBox; + void onSearchBoxCommit(); }; LLFloaterScriptSearch* LLFloaterScriptSearch::sInstance = NULL; LLFloaterScriptSearch::LLFloaterScriptSearch(LLScriptEdCore* editor_core) : LLFloater(LLSD()), + mSearchBox(NULL), mEditorCore(editor_core) { buildFromFile("floater_script_search.xml"); @@ -221,6 +227,9 @@ LLFloaterScriptSearch::LLFloaterScriptSearch(LLScriptEdCore* editor_core) BOOL LLFloaterScriptSearch::postBuild() { + mSearchBox = getChild<LLLineEditor>("search_text"); + mSearchBox->setCommitCallback(boost::bind(&LLFloaterScriptSearch::onSearchBoxCommit, this)); + mSearchBox->setCommitOnFocusLost(FALSE); childSetAction("search_btn", onBtnSearch,this); childSetAction("replace_btn", onBtnReplace,this); childSetAction("replace_all_btn", onBtnReplaceAll,this); @@ -315,6 +324,15 @@ BOOL LLFloaterScriptSearch::handleKeyHere(KEY key, MASK mask) return FALSE; } +void LLFloaterScriptSearch::onSearchBoxCommit() +{ + if (mEditorCore && mEditorCore->mEditor) + { + LLCheckBoxCtrl* caseChk = getChild<LLCheckBoxCtrl>("case_text"); + mEditorCore->mEditor->selectNext(getChild<LLUICtrl>("search_text")->getValue().asString(), caseChk->get()); + } +} + /// --------------------------------------------------------------------------- /// LLScriptEdCore /// --------------------------------------------------------------------------- @@ -503,6 +521,9 @@ void LLScriptEdCore::initMenu() menuItem = getChild<LLMenuItemCallGL>("Search / Replace..."); menuItem->setClickCallback(boost::bind(&LLFloaterScriptSearch::show, this)); + menuItem = getChild<LLMenuItemCallGL>("Go to line..."); + menuItem->setClickCallback(boost::bind(&LLFloaterGotoLine::show, this)); + menuItem = getChild<LLMenuItemCallGL>("Help..."); menuItem->setClickCallback(boost::bind(&LLScriptEdCore::onBtnHelp, this)); diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index 7563cecd9d..9fb0a4fb63 100755 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -34,6 +34,7 @@ #include "llcombobox.h" #include "lliconctrl.h" #include "llframetimer.h" +#include "llfloatergotoline.h" class LLLiveLSLFile; class LLMessageSystem; @@ -49,6 +50,7 @@ class LLKeywordToken; class LLVFS; class LLViewerInventoryItem; class LLScriptEdContainer; +class LLFloaterGotoLine; // Inner, implementation class. LLPreviewScript and LLLiveLSLEditor each own one of these. class LLScriptEdCore : public LLPanel @@ -58,6 +60,7 @@ class LLScriptEdCore : public LLPanel friend class LLLiveLSLEditor; friend class LLFloaterScriptSearch; friend class LLScriptEdContainer; + friend class LLFloaterGotoLine; protected: // Supposed to be invoked only by the container. diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index cff3a7e02a..67a76460a7 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -51,6 +51,7 @@ #include "lllandmark.h" #include "llcachename.h" #include "lldir.h" +#include "lldonotdisturbnotificationstorage.h" #include "llerrorcontrol.h" #include "llfloaterreg.h" #include "llfocusmgr.h" @@ -68,6 +69,7 @@ #include "llfloaterimnearbychat.h" #include "llnotifications.h" #include "llnotificationsutil.h" +#include "llpersistentnotificationstorage.h" #include "llteleporthistory.h" #include "llregionhandle.h" #include "llsd.h" @@ -900,6 +902,10 @@ bool idle_startup() gDirUtilp->setLindenUserDir(userid); LLFile::mkdir(gDirUtilp->getLindenUserDir()); + // As soon as directories are ready initialize notification storages + LLPersistentNotificationStorage::getInstance()->initialize(); + LLDoNotDisturbNotificationStorage::getInstance()->initialize(); + // Set PerAccountSettingsFile to the default value. gSavedSettings.setString("PerAccountSettingsFile", gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp index e92bd766ca..1a3add2bfb 100755 --- a/indra/newview/llsyswellwindow.cpp +++ b/indra/newview/llsyswellwindow.cpp @@ -423,9 +423,18 @@ void LLNotificationWellWindow::onItemClick(LLSysWellItem* item) void LLNotificationWellWindow::onItemClose(LLSysWellItem* item) { LLUUID id = item->getID(); - removeItemByID(id); + if(mChannel) + { + // removeItemByID() is invoked from killToastByNotificationID() and item will removed; mChannel->killToastByNotificationID(id); + } + else + { + // removeItemByID() should be called one time for each item to remove it from notification well + removeItemByID(id); + } + } void LLNotificationWellWindow::onAdd( LLNotificationPtr notify ) diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp index 025ef3945d..bdbd8f1f83 100755 --- a/indra/newview/lltoastimpanel.cpp +++ b/indra/newview/lltoastimpanel.cpp @@ -63,7 +63,7 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif style_params.font.size(font_size); LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(p.session_id); - mIsGroupMsg = (im_session->mSessionType == LLIMModel::LLIMSession::GROUP_SESSION); + mIsGroupMsg = (im_session && im_session->mSessionType == LLIMModel::LLIMSession::GROUP_SESSION); if(mIsGroupMsg) { mAvatarName->setValue(im_session->mName); @@ -93,7 +93,7 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif if(!mIsGroupMsg) { - mAvatarName->setValue(p.from); + mAvatarName->setValue(p.from); } mTime->setValue(p.time); mSessionID = p.session_id; @@ -164,7 +164,7 @@ void LLToastIMPanel::spawnNameToolTip() params.background_visible(false); if(!mIsGroupMsg) { - params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE)); + params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE)); } else { diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp index b2318f9158..78a555d67d 100755 --- a/indra/newview/lltoolbarview.cpp +++ b/indra/newview/lltoolbarview.cpp @@ -51,8 +51,6 @@ LLToolBarView* gToolBarView = NULL; static LLDefaultChildRegistry::Register<LLToolBarView> r("toolbar_view"); -void handleLoginToolbarSetup(); - bool isToolDragged() { return (LLToolDragAndDrop::getInstance()->getSource() == LLToolDragAndDrop::SOURCE_VIEWER); @@ -111,8 +109,6 @@ BOOL LLToolBarView::postBuild() mToolbars[i]->setButtonAddCallback(boost::bind(LLToolBarView::onToolBarButtonAdded,_1)); mToolbars[i]->setButtonRemoveCallback(boost::bind(LLToolBarView::onToolBarButtonRemoved,_1)); } - - LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&handleLoginToolbarSetup)); return TRUE; } @@ -180,13 +176,13 @@ S32 LLToolBarView::stopCommandInProgress(const LLCommandId& commandId) return command_location; } -S32 LLToolBarView::flashCommand(const LLCommandId& commandId, bool flash) +S32 LLToolBarView::flashCommand(const LLCommandId& commandId, bool flash, bool force_flashing/* = false */) { S32 command_location = hasCommand(commandId); if (command_location != TOOLBAR_NONE) { - mToolbars[command_location]->flashCommand(commandId, flash); + mToolbars[command_location]->flashCommand(commandId, flash, force_flashing); } return command_location; @@ -696,18 +692,3 @@ bool LLToolBarView::isModified() const } -// -// HACK to bring up destinations guide at startup -// - -void handleLoginToolbarSetup() -{ - // Open the destinations guide by default on first login, per Rhett - if (gSavedPerAccountSettings.getBOOL("DisplayDestinationsOnInitialRun") || gAgent.isFirstLogin()) - { - LLFloaterReg::showInstance("destinations"); - - gSavedPerAccountSettings.setBOOL("DisplayDestinationsOnInitialRun", FALSE); - } -} - diff --git a/indra/newview/lltoolbarview.h b/indra/newview/lltoolbarview.h index 7125dd9990..dcc3862074 100755 --- a/indra/newview/lltoolbarview.h +++ b/indra/newview/lltoolbarview.h @@ -90,7 +90,7 @@ public: S32 removeCommand(const LLCommandId& commandId, int& rank); // Sets the rank the removed command was at, RANK_NONE if not found S32 enableCommand(const LLCommandId& commandId, bool enabled); S32 stopCommandInProgress(const LLCommandId& commandId); - S32 flashCommand(const LLCommandId& commandId, bool flash); + S32 flashCommand(const LLCommandId& commandId, bool flash, bool force_flashing = false); // Loads the toolbars from the existing user or default settings bool loadToolbars(bool force_default = false); // return false if load fails diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index afbb59e723..744ec4de2b 100755 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -83,7 +83,9 @@ BOOL gHackGodmode = FALSE; #endif - +// Should you contemplate changing the name "Global", please first grep for +// that string literal. There are at least a couple other places in the C++ +// code that assume the LLControlGroup named "Global" is gSavedSettings. LLControlGroup gSavedSettings("Global"); // saved at end of session LLControlGroup gSavedPerAccountSettings("PerAccount"); // saved at end of session LLControlGroup gCrashSettings("CrashSettings"); // saved at end of session diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 4d57fbc891..e3335c9cd8 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -259,11 +259,15 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response) break; } - LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); - modified_form->setElementEnabled("Accept", false); - modified_form->setElementEnabled("Decline", false); - notification_ptr->updateForm(modified_form); - notification_ptr->repost(); + // TODO: this set of calls has undesirable behavior under Windows OS (CHUI-985): + // here appears three additional toasts instead one modified + // need investigation and fix + + // LLNotificationFormPtr modified_form(new LLNotificationForm(*notification_ptr->getForm())); + // modified_form->setElementEnabled("Accept", false); + // modified_form->setElementEnabled("Decline", false); + // notification_ptr->updateForm(modified_form); + // notification_ptr->repost(); } return false; @@ -3674,6 +3678,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) LLSD msg_notify = LLSD(LLSD::emptyMap()); msg_notify["session_id"] = LLUUID(); msg_notify["from_id"] = chat.mFromID; + msg_notify["source_type"] = chat.mSourceType; on_new_message(msg_notify); } } @@ -5931,6 +5936,15 @@ bool attempt_standard_notification(LLMessageSystem* msgsystem) return true; } } + // HACK -- handle callbacks for specific alerts. + if( notificationID == "HomePositionSet" ) + { + // save the home location image to disk + std::string snap_filename = gDirUtilp->getLindenUserDir(); + snap_filename += gDirUtilp->getDirDelimiter(); + snap_filename += SCREEN_HOME_FILENAME; + gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, FALSE); + } LLNotificationsUtil::add(notificationID, llsdBlock); return true; @@ -6006,14 +6020,6 @@ void process_alert_core(const std::string& message, BOOL modal) { LLViewerStats::getInstance()->incStat(LLViewerStats::ST_KILLED_COUNT); } - else if( message == "Home position set." ) - { - // save the home location image to disk - std::string snap_filename = gDirUtilp->getLindenUserDir(); - snap_filename += gDirUtilp->getDirDelimiter(); - snap_filename += SCREEN_HOME_FILENAME; - gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, FALSE); - } const std::string ALERT_PREFIX("ALERT: "); const std::string NOTIFY_PREFIX("NOTIFY: "); diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index 97f4c3e5fe..e7821d4b9e 100755 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -43,6 +43,8 @@ const std::string GRID_LABEL_VALUE = "label"; const std::string GRID_ID_VALUE = "grid_login_id"; /// the url for the login cgi script const std::string GRID_LOGIN_URI_VALUE = "login_uri"; +/// url base for update queries +const std::string GRID_UPDATE_SERVICE_URL = "update_query_url_base"; /// const std::string GRID_HELPER_URI_VALUE = "helper_uri"; /// the splash page url @@ -63,6 +65,8 @@ const std::string DEFAULT_LOGIN_PAGE = "http://viewer-login.agni.lindenlab.com/" const std::string MAIN_GRID_LOGIN_URI = "https://login.agni.lindenlab.com/cgi-bin/login.cgi"; +const std::string SL_UPDATE_QUERY_URL = "https://update.secondlife.com/update"; + const std::string MAIN_GRID_SLURL_BASE = "http://maps.secondlife.com/secondlife/"; const std::string SYSTEM_GRID_APP_SLURL_BASE = "secondlife:///app"; @@ -120,12 +124,14 @@ void LLGridManager::initialize(const std::string& grid_file) MAIN_GRID_LOGIN_URI, "https://secondlife.com/helpers/", DEFAULT_LOGIN_PAGE, + SL_UPDATE_QUERY_URL, "Agni"); addSystemGrid("Second Life Beta Test Grid (Aditi)", "util.aditi.lindenlab.com", "https://login.aditi.lindenlab.com/cgi-bin/login.cgi", "http://aditi-secondlife.webdev.lindenlab.com/helpers/", DEFAULT_LOGIN_PAGE, + SL_UPDATE_QUERY_URL, "Aditi"); LLSD other_grids; @@ -332,6 +338,7 @@ void LLGridManager::addSystemGrid(const std::string& label, const std::string& login_uri, const std::string& helper, const std::string& login_page, + const std::string& update_url_base, const std::string& login_id) { LLSD grid = LLSD::emptyMap(); @@ -341,6 +348,7 @@ void LLGridManager::addSystemGrid(const std::string& label, grid[GRID_LOGIN_URI_VALUE] = LLSD::emptyArray(); grid[GRID_LOGIN_URI_VALUE].append(login_uri); grid[GRID_LOGIN_PAGE_VALUE] = login_page; + grid[GRID_UPDATE_SERVICE_URL] = update_url_base; grid[GRID_IS_SYSTEM_GRID_VALUE] = true; grid[GRID_LOGIN_IDENTIFIER_TYPES] = LLSD::emptyArray(); grid[GRID_LOGIN_IDENTIFIER_TYPES].append(CRED_IDENTIFIER_TYPE_AGENT); @@ -537,6 +545,30 @@ std::string LLGridManager::getGridLoginID() return mGridList[mGrid][GRID_ID_VALUE]; } +std::string LLGridManager::getUpdateServiceURL() +{ + std::string update_url_base = gSavedSettings.getString("CmdLineUpdateService");; + if ( !update_url_base.empty() ) + { + LL_INFOS2("UpdaterService","GridManager") + << "Update URL base overridden from command line: " << update_url_base + << LL_ENDL; + } + else if ( mGridList[mGrid].has(GRID_UPDATE_SERVICE_URL) ) + { + update_url_base = mGridList[mGrid][GRID_UPDATE_SERVICE_URL].asString(); + } + else + { + LL_WARNS2("UpdaterService","GridManager") + << "The grid property '" << GRID_UPDATE_SERVICE_URL + << "' is not defined for the grid '" << mGrid << "'" + << LL_ENDL; + } + + return update_url_base; +} + void LLGridManager::updateIsInProductionGrid() { mIsInProductionGrid = false; diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h index 3f56103b2e..8526c0ba7f 100755 --- a/indra/newview/llviewernetwork.h +++ b/indra/newview/llviewernetwork.h @@ -140,6 +140,14 @@ class LLGridManager : public LLSingleton<LLGridManager> */ //@} + /* ================================================================ + * @name Update Related Properties + * @{ + */ + /// Get the update service URL base (host and path) for the selected grid + std::string getUpdateServiceURL(); + + //@} /* ================================================================ * @name URL Construction Properties @@ -207,6 +215,7 @@ class LLGridManager : public LLSingleton<LLGridManager> const std::string& login, const std::string& helper, const std::string& login_page, + const std::string& update_url_base, const std::string& login_id = ""); diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml index fc8bc33096..9206690c8f 100755 --- a/indra/newview/skins/default/xui/da/floater_about.xml +++ b/indra/newview/skins/default/xui/da/floater_about.xml @@ -8,7 +8,7 @@ Bygget med [COMPILER] version [COMPILER_VERSION] </floater.string> <floater.string name="AboutPosition"> - Du er ved [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] i regionen [REGION] lokaliseret ved <nolink>[HOSTNAME]</nolink> ([HOSTIP]) + Du er ved [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] i regionen [REGION] lokaliseret ved <nolink>[HOSTNAME]</nolink> ([HOSTIP]) [SERVER_VERSION] [SERVER_RELEASE_NOTES_URL] </floater.string> diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml index 4387a61963..5245467183 100755 --- a/indra/newview/skins/default/xui/de/floater_about.xml +++ b/indra/newview/skins/default/xui/de/floater_about.xml @@ -8,7 +8,7 @@ Kompiliert mit [COMPILER] version [COMPILER_VERSION] </floater.string> <floater.string name="AboutPosition"> - Sie befinden sich in [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] auf <nolink>[HOSTNAME]</nolink> ([HOSTIP]) + Sie befinden sich in [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] auf <nolink>[HOSTNAME]</nolink> ([HOSTIP]) [SERVER_VERSION] [SERVER_RELEASE_NOTES_URL] </floater.string> diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml index 63eb87f27a..703015af20 100755 --- a/indra/newview/skins/default/xui/en/floater_about.xml +++ b/indra/newview/skins/default/xui/en/floater_about.xml @@ -22,7 +22,9 @@ Built with [COMPILER] version [COMPILER_VERSION] </floater.string> <floater.string name="AboutPosition"> -You are at [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] located at <nolink>[HOSTNAME]</nolink> ([HOSTIP]) +You are at [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] located at <nolink>[HOSTNAME]</nolink> ([HOSTIP]) +SLURL: <nolink>[SLURL]</nolink> +(global coordinates [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1]) [SERVER_VERSION] [SERVER_RELEASE_NOTES_URL] diff --git a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml index 4e0cfb0cd4..e7ab3cacdc 100755 --- a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml +++ b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml @@ -6,7 +6,7 @@ layout="topleft" name="floaterbulkperms" help_topic="floaterbulkperms" - title="EDIT CONTENT PERMISSIONS" + title="ADJUST CONTENT PERMISSIONS" width="410"> <floater.string name="nothing_to_modify_text"> @@ -192,7 +192,7 @@ name="newperms" top="90" width="250"> - New Content Permissions + Adjust Content Permissions To </text> <text type="string" @@ -292,11 +292,22 @@ height="23" label="OK" layout="topleft" - left="205" - name="apply" + left="110" + name="ok" top_pad="10" width="90"> <button.commit_callback + function="BulkPermission.Ok"/> + </button> + <button + follows="left|top" + height="23" + label="Apply" + layout="topleft" + left_pad="5" + name="apply" + width="90"> + <button.commit_callback function="BulkPermission.Apply"/> </button> <button diff --git a/indra/newview/skins/default/xui/en/floater_goto_line.xml b/indra/newview/skins/default/xui/en/floater_goto_line.xml new file mode 100644 index 0000000000..b236888219 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_goto_line.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + default_tab_group="1" + height="90" + layout="topleft" + name="script goto" + help_topic="script_goto" + title="GO TO LINE" + width="200"> + <button + height="24" + label="OK" + label_selected="OK" + layout="topleft" + left="55" + name="goto_btn" + top="53" + width="90" /> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + left="10" + name="txt" + top="21" + width="65"> + Go to line + </text> + <line_editor + border_style="line" + border_thickness="1" + follows="left|top" + height="16" + layout="topleft" + left="75" + max_length_bytes="9" + name="goto_line" + tab_group="1" + top="21" + width="85" /> +</floater>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml index da016462db..1215efb7f9 100755 --- a/indra/newview/skins/default/xui/en/floater_im_container.xml +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -4,6 +4,7 @@ can_minimize="true" can_resize="true" height="210" + min_height="210" layout="topleft" name="floater_im_box" help_topic="floater_im_box" diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 8da4213c65..43d0f2fb18 100755 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -142,19 +142,7 @@ left_pad="2" name="voice_call_btn" tool_tip="Open voice connection" - width="31"/> - <output_monitor - auto_update="true" - follows="top|left" - draw_border="false" - height="16" - layout="topleft" - top="10" - left_pad="10" - mouse_opaque="true" - name="speaking_indicator" - visible="false" - width="20" /> + width="31"/> <button follows="right|top" height="25" diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml index 5a13ef0a59..b3d28788da 100755 --- a/indra/newview/skins/default/xui/en/menu_conversation.xml +++ b/indra/newview/skins/default/xui/en/menu_conversation.xml @@ -11,7 +11,7 @@ layout="topleft" name="close_conversation"> <on_click function="Avatar.DoToSelected" parameter="close_conversation"/> - </menu_item_call> + </menu_item_call> <menu_item_call label="Open voice conversation" layout="topleft" @@ -25,6 +25,12 @@ <on_click function="Avatar.DoToSelected" parameter="disconnect_from_voice"/> </menu_item_call> <menu_item_separator layout="topleft" name="separator_disconnect_from_voice"/> + <menu_item_call + label="Close Selected" + layout="topleft" + name="close_selected_conversations"> + <on_click function="Avatar.DoToSelected" parameter="close_selected_conversations"/> + </menu_item_call> <menu_item_call label="View Profile" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml index dde9432867..8790fde7c5 100755 --- a/indra/newview/skins/default/xui/en/menu_people_friends_view.xml +++ b/indra/newview/skins/default/xui/en/menu_people_friends_view.xml @@ -44,6 +44,8 @@ <menu_item_check.on_check function="Floater.Visible" parameter="conversation" /> + <menu_item_check.on_enable + function="Conversation.IsConversationLoggingAllowed" /> <menu_item_check.on_click function="Floater.Toggle" parameter="conversation" /> diff --git a/indra/newview/skins/default/xui/en/menu_url_agent.xml b/indra/newview/skins/default/xui/en/menu_url_agent.xml index 7cd56f257a..e8b6116026 100755 --- a/indra/newview/skins/default/xui/en/menu_url_agent.xml +++ b/indra/newview/skins/default/xui/en/menu_url_agent.xml @@ -21,8 +21,15 @@ layout="topleft" name="add_friend"> <menu_item_call.on_click - function="Url.AddFriend" /> + function="Url.AddFriend" /> </menu_item_call> + <menu_item_call + label="Remove Friend..." + layout="topleft" + name="remove_friend"> + <menu_item_call.on_click + function="Url.RemoveFriend" /> + </menu_item_call> <menu_item_separator layout="topleft" /> <menu_item_call diff --git a/indra/newview/skins/default/xui/en/menu_url_objectim.xml b/indra/newview/skins/default/xui/en/menu_url_objectim.xml index 87ab58e622..b9d003b841 100755 --- a/indra/newview/skins/default/xui/en/menu_url_objectim.xml +++ b/indra/newview/skins/default/xui/en/menu_url_objectim.xml @@ -9,6 +9,13 @@ <menu_item_call.on_click function="Url.Execute" /> </menu_item_call> + <menu_item_call + label="Block..." + layout="topleft" + name="block_object"> + <menu_item_call.on_click + function="Url.Block" /> + </menu_item_call> <menu_item_separator layout="topleft" /> <menu_item_call diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 6da4b3d234..1b0b857c22 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -882,6 +882,15 @@ function="Tools.EnableSelectNextPart" /> </menu_item_call> </menu> + <menu_item_call + label="Linksets..." + name="pathfinding_linkset_menu_item"> + <menu_item_call.on_click + function="Floater.ToggleOrBringToFront" + parameter="pathfinding_linksets" /> + <menu_item_call.on_enable + function="Tools.EnablePathfinding" /> + </menu_item_call> <menu_item_separator/> <menu_item_call @@ -904,7 +913,7 @@ <menu_item_call.on_enable function="Tools.SomethingSelectedNoHUD" /> </menu_item_call> - + <menu_item_separator/> <menu diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 6da25ef210..e8d3b85221 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -506,6 +506,33 @@ Add this Ability to '[ROLE_NAME]'? notext="No" yestext="Yes"/> </notification> + + <notification + icon="alertmodal.tga" + name="EjectGroupMemberWarning" + type="alertmodal"> + You are about to eject [AVATAR_NAME] from the group. + <tag>group</tag> + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm ejecting a participant from group" + name="okcancelignore" + notext="Cancel" + yestext="Eject"/> + </notification> + <notification + icon="alertmodal.tga" + name="EjectGroupMembersWarning" + type="alertmodal"> + You are about to eject [COUNT] members from the group. + <tag>group</tag> + <tag>confirm</tag> + <usetemplate + ignoretext="Confirm ejecting multiple members from group" + name="okcancelignore" + notext="Cancel" + yestext="Eject"/> + </notification> <notification icon="alertmodal.tga" @@ -2682,7 +2709,7 @@ Please enter a higher price. icon="alertmodal.tga" name="ConfirmItemDeleteHasLinks" type="alertmodal"> -At least one of the items you has link items that point to it. If you delete this item, its links will permanently stop working. It is strongly advised to delete the links first. +At least one of the items has links that point to it. If you delete this item, its links will permanently stop working. It is strongly advised to delete the links first. Are you sure you want to delete these items? <tag>confirm</tag> @@ -2724,7 +2751,7 @@ Are you sure you want to delete these items? icon="alertmodal.tga" name="ConfirmObjectDeleteNoOwn" type="alertmodal"> -You do not own least one of the items you have selected. +You do not own at least one of the items you have selected. Are you sure you want to delete these items? <tag>confirm</tag> @@ -2754,7 +2781,7 @@ Are you sure you want to delete these items? name="ConfirmObjectDeleteLockNoOwn" type="alertmodal"> At least one object is locked. -You do not own least one object. +You do not own at least one object. Are you sure you want to delete these items? <tag>confirm</tag> @@ -2769,7 +2796,7 @@ Are you sure you want to delete these items? name="ConfirmObjectDeleteNoCopyNoOwn" type="alertmodal"> At least one object is not copyable. -You do not own least one object. +You do not own at least one object. Are you sure you want to delete these items? <tag>confirm</tag> @@ -2785,13 +2812,13 @@ Are you sure you want to delete these items? type="alertmodal"> At least one object is locked. At least one object is not copyable. -You do not own least one object. +You do not own at least one object. Are you sure you want to delete these items? <tag>confirm</tag> <usetemplate name="okcancelbuttons" - notext="cancel" + notext="Cancel" yestext="OK"/> </notification> @@ -5954,9 +5981,7 @@ Your calling card was declined. icon="notifytip.tga" name="TeleportToPerson" type="notifytip"> - To contact Residents like '[NAME]', click on the "People" button , select a Resident from the window that opens, then click 'IM' at the - bottom of the window. - (You can also double-click on their name in the list, or right-click and choose 'IM'). + To open a private conversation with someone, right-click on their avatar and choose 'IM' from the menu. </notification> <notification diff --git a/indra/newview/skins/default/xui/en/panel_group_notices.xml b/indra/newview/skins/default/xui/en/panel_group_notices.xml index 6d5fb51e85..c8ce5cdebf 100755 --- a/indra/newview/skins/default/xui/en/panel_group_notices.xml +++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml @@ -202,14 +202,14 @@ Maximum 200 per group daily Drag and drop item here to attach it: </text> <icon - height="72" + height="48" image_name="DropTarget" layout="topleft" left_pad="10" mouse_opaque="true" name="drop_icon" top_delta="-10" - width="72" /> + width="110" /> <button follows="left|top" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index 1b394a3dca..dc0e4a5947 100755 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -497,10 +497,22 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M function="People.Group.Minus" /> </dnd_button> </panel> + <text + type="string" + length="1" + follows="all" + height="14" + layout="topleft" + right="-10" + top_pad="4" + left="3" + name="groupcount"> + You belong to [COUNT] groups, and can join [REMAINING] more. + </text> <group_list allow_select="true" follows="all" - height="406" + height="388" layout="topleft" left="3" name="group_list" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml index 2cc9d9c1b0..50fd57494f 100755 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -138,7 +138,7 @@ initial_value="1" layout="topleft" left_pad="0" - max_val="1.4" + max_val="1.5" min_val="0.75" name="ui_scale_slider" top_pad="-14" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml index bd096ebb88..8e867259c5 100755 --- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml @@ -14,6 +14,7 @@ border="false" height="60" layout="topleft" + name="general_chat_settings" top="10" left="13" width="517"> @@ -97,20 +98,13 @@ border="false" height="165" layout="topleft" + name="im_notification_settings" left="13" width="517"> <text layout="topleft" height="12" - name="notifications" - left="0" - width="120"> - Notifications - </text> - <text - layout="topleft" - height="12" name="friend_ims" width="145" left="0" @@ -138,17 +132,27 @@ name="FlashToolbarButton" value="flash"/> <item - label="None" - name="None" - value="none"/> + label="No action" + name="NoAction" + value="noaction"/> </combo_box> + <check_box + control_name="PlaySoundFriendIM" + height="23" + label="Play sound" + layout="topleft" + name="play_sound_friend_im" + left_pad="7" + top_delta="-3" + width="28"> + </check_box> <text layout="topleft" height="12" name="non_friend_ims" width="145" left="0" - top_pad="9"> + top_pad="11"> Non-friend IMs: </text> <combo_box @@ -172,17 +176,27 @@ name="FlashToolbarButton" value="flash"/> <item - label="None" - name="None" - value="none"/> + label="No action" + name="NoAction" + value="noaction"/> </combo_box> + <check_box + control_name="PlaySoundNonFriendIM" + height="23" + label="Play sound" + layout="topleft" + name="play_sound_non_friend_im" + left_pad="7" + top_delta="-3" + width="28"> + </check_box> <text layout="topleft" left="0" height="13" name="conference_ims" width="145" - top_pad="9"> + top_pad="11"> Conference IMs: </text> <combo_box @@ -206,17 +220,27 @@ name="FlashToolbarButton" value="flash"/> <item - label="None" - name="None" - value="none"/> + label="No action" + name="NoAction" + value="noaction"/> </combo_box> + <check_box + control_name="PlaySoundConferenceIM" + height="23" + label="Play sound" + layout="topleft" + name="play_sound_conference_im" + left_pad="7" + top_delta="-3" + width="28"> + </check_box> <text layout="topleft" left="0" height="13" name="group_chat" width="145" - top_pad="9"> + top_pad="11"> Group chat: </text> <combo_box @@ -240,17 +264,27 @@ name="FlashToolbarButton" value="flash"/> <item - label="None" - name="None" - value="none"/> + label="No action" + name="NoAction" + value="noaction"/> </combo_box> + <check_box + control_name="PlaySoundGroupChatIM" + height="23" + label="Play sound" + layout="topleft" + name="play_sound_group_chat_im" + left_pad="7" + top_delta="-3" + width="28"> + </check_box> <text layout="topleft" left="0" height="12" name="nearby_chat" width="145" - top_pad="9"> + top_pad="11"> Nearby chat: </text> <combo_box @@ -274,10 +308,64 @@ name="FlashToolBarButton" value="flash"/> <item - label="None" - name="None" - value="none"/> + label="No action" + name="NoAction" + value="noaction"/> </combo_box> + <check_box + control_name="PlaySoundNearbyChatIM" + height="23" + label="Play sound" + layout="topleft" + name="play_sound_nearby_chat_im" + left_pad="7" + top_delta="-3" + width="28"> + </check_box> + <text + layout="topleft" + left="0" + height="12" + name="object_ims" + width="145" + top_pad="11"> + Object IMs: + </text> + <combo_box + control_name="NotificationObjectIMOptions" + height="23" + layout="topleft" + left_pad="5" + top_delta="-6" + name="ObjectIMOptions" + width="223"> + <item + label="Open Conversations window" + name="OpenConversationsWindow" + value="openconversations"/> + <item + label="Pop up the message" + name="PopUpMessage" + value="toast"/> + <item + label="Flash toolbar button" + name="FlashToolBarButton" + value="flash"/> + <item + label="No action" + name="NoAction" + value="noaction"/> + </combo_box> + <check_box + control_name="PlaySoundObjectIM" + height="23" + label="Play sound" + layout="topleft" + name="play_sound_object_im" + left_pad="7" + top_delta="-3" + width="28"> + </check_box> <text layout="topleft" left="0" @@ -296,6 +384,7 @@ border="false" height="50" layout="topleft" + name="play_sound_settings" left="13" top_pad="10" width="517"> @@ -358,6 +447,7 @@ <panel height="50" layout="topleft" + name="log_settings" left="13" top_pad="10" width="505"> diff --git a/indra/newview/skins/default/xui/en/panel_script_ed.xml b/indra/newview/skins/default/xui/en/panel_script_ed.xml index 765b07ed8b..bcdef96138 100755 --- a/indra/newview/skins/default/xui/en/panel_script_ed.xml +++ b/indra/newview/skins/default/xui/en/panel_script_ed.xml @@ -125,6 +125,10 @@ label="Search / Replace..." layout="topleft" name="Search / Replace..." /> + <menu_item_call + label="Go to line..." + layout="topleft" + name="Go to line..." /> </menu> <menu top="0" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 7f6701368a..518393f778 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -217,7 +217,8 @@ Please try logging in again in a minute.</string> <string name="SLappAgentIM">IM</string> <string name="SLappAgentPay">Pay</string> <string name="SLappAgentOfferTeleport">Offer Teleport to </string> - <string name="SLappAgentRequestFriend">Friend Request </string> + <string name="SLappAgentRequestFriend">Friend Request</string> + <string name="SLappAgentRemoveFriend">Friend Removal</string> <!-- ButtonToolTips, llfloater.cpp --> <string name="BUTTON_CLOSE_DARWIN">Close (⌘W)</string> @@ -3942,5 +3943,8 @@ Try enclosing path to the editor with double quotes. <string name="logging_calls_enabled_log_empty"> There are no logged conversations. After you contact someone, or someone contacts you, a log entry will be shown here. </string> + <string name="loading_chat_logs"> + Loading... + </string> </strings> diff --git a/indra/newview/skins/default/xui/es/floater_about.xml b/indra/newview/skins/default/xui/es/floater_about.xml index 3696c7e12c..7ca1e3721f 100755 --- a/indra/newview/skins/default/xui/es/floater_about.xml +++ b/indra/newview/skins/default/xui/es/floater_about.xml @@ -8,7 +8,7 @@ Compilado con [COMPILER], versión [COMPILER_VERSION] </floater.string> <floater.string name="AboutPosition"> - Estás en la posición [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1], de [REGION], alojada en <nolink>[HOSTNAME]</nolink> ([HOSTIP]) + Estás en la posición [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1], de [REGION], alojada en <nolink>[HOSTNAME]</nolink> ([HOSTIP]) [SERVER_VERSION] [SERVER_RELEASE_NOTES_URL] </floater.string> diff --git a/indra/newview/skins/default/xui/fr/floater_about.xml b/indra/newview/skins/default/xui/fr/floater_about.xml index a659cb4245..d45bdccf3e 100755 --- a/indra/newview/skins/default/xui/fr/floater_about.xml +++ b/indra/newview/skins/default/xui/fr/floater_about.xml @@ -8,7 +8,7 @@ Compilé avec [COMPILER] version [COMPILER_VERSION] </floater.string> <floater.string name="AboutPosition"> - Vous êtes à [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] dans [REGION], se trouvant à <nolink>[HOSTNAME]</nolink> ([HOSTIP]) + Vous êtes à [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] dans [REGION], se trouvant à <nolink>[HOSTNAME]</nolink> ([HOSTIP]) [SERVER_VERSION] [SERVER_RELEASE_NOTES_URL] </floater.string> diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml index c672511fc5..b0fb585fa2 100755 --- a/indra/newview/skins/default/xui/it/floater_about.xml +++ b/indra/newview/skins/default/xui/it/floater_about.xml @@ -8,7 +8,7 @@ Generato con [COMPILER] versione [COMPILER_VERSION] </floater.string> <floater.string name="AboutPosition"> - Tu sei [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] in [REGION] che si trova a <nolink>[HOSTNAME]</nolink> ([HOSTIP]) + Tu sei [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] che si trova a <nolink>[HOSTNAME]</nolink> ([HOSTIP]) [SERVER_VERSION] [SERVER_RELEASE_NOTES_URL] </floater.string> diff --git a/indra/newview/skins/default/xui/ja/floater_about.xml b/indra/newview/skins/default/xui/ja/floater_about.xml index 6d5df75645..eae52c98ec 100755 --- a/indra/newview/skins/default/xui/ja/floater_about.xml +++ b/indra/newview/skins/default/xui/ja/floater_about.xml @@ -8,7 +8,7 @@ コンパイラー [COMPILER] [COMPILER_VERSION] バージョン </floater.string> <floater.string name="AboutPosition"> - あなたの現在地は、[POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] の [REGION] です。位置は <nolink>[HOSTNAME]</nolink> です。([HOSTIP]) + あなたの現在地は、[POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] の [REGION] です。位置は <nolink>[HOSTNAME]</nolink> です。([HOSTIP]) [SERVER_VERSION] [SERVER_RELEASE_NOTES_URL] </floater.string> diff --git a/indra/newview/skins/default/xui/pl/floater_about.xml b/indra/newview/skins/default/xui/pl/floater_about.xml index 409429ffaa..61a72ff27d 100755 --- a/indra/newview/skins/default/xui/pl/floater_about.xml +++ b/indra/newview/skins/default/xui/pl/floater_about.xml @@ -8,7 +8,7 @@ Buduj z [COMPILER] wersją [COMPILER_VERSION] </floater.string> <floater.string name="AboutPosition"> - Położenie [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] w [REGION] zlokalizowanym w <nolink>[HOSTNAME]</nolink> ([HOSTIP]) + Położenie [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] w [REGION] zlokalizowanym w <nolink>[HOSTNAME]</nolink> ([HOSTIP]) [SERVER_VERSION] [SERVER_RELEASE_NOTES_URL] </floater.string> diff --git a/indra/newview/skins/default/xui/pt/floater_about.xml b/indra/newview/skins/default/xui/pt/floater_about.xml index 299f88b22a..d089266342 100755 --- a/indra/newview/skins/default/xui/pt/floater_about.xml +++ b/indra/newview/skins/default/xui/pt/floater_about.xml @@ -7,7 +7,7 @@ Construído com [COMPILER] versão [COMPILER_VERSION] </floater.string> <floater.string name="AboutPosition"> - Você está em [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] em [REGION] localizado em [HOSTNAME]</nolink>([HOSTIP]) + Você está em [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] em [REGION] localizado em [HOSTNAME]</nolink>([HOSTIP]) [SERVER_VERSION] [SERVER_RELEASE_NOTES_URL] </floater.string> diff --git a/indra/newview/skins/default/xui/ru/floater_about.xml b/indra/newview/skins/default/xui/ru/floater_about.xml index bb6266ac9a..2b2b3cf453 100755 --- a/indra/newview/skins/default/xui/ru/floater_about.xml +++ b/indra/newview/skins/default/xui/ru/floater_about.xml @@ -8,7 +8,7 @@ Использован компилятор [COMPILER], версия [COMPILER_VERSION] </floater.string> <floater.string name="AboutPosition"> - Вы в точке [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] в регионе «[REGION]», расположенном на <nolink>[HOSTNAME]</nolink> ([HOSTIP]) + Вы в точке [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] в регионе «[REGION]», расположенном на <nolink>[HOSTNAME]</nolink> ([HOSTIP]) [SERVER_VERSION] [SERVER_RELEASE_NOTES_URL] </floater.string> diff --git a/indra/newview/skins/default/xui/tr/floater_about.xml b/indra/newview/skins/default/xui/tr/floater_about.xml index 9cc9c7a220..4dcf6200c6 100755 --- a/indra/newview/skins/default/xui/tr/floater_about.xml +++ b/indra/newview/skins/default/xui/tr/floater_about.xml @@ -8,7 +8,7 @@ [COMPILER] [COMPILER_VERSION] sürümü ile oluşturuldu </floater.string> <floater.string name="AboutPosition"> - <nolink>[HOSTNAME]</nolink> ([HOSTIP]) üzerinde bulunan [REGION] içerisinde [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] konumundasınız + <nolink>[HOSTNAME]</nolink> ([HOSTIP]) üzerinde bulunan [REGION] içerisinde [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] konumundasınız [SERVER_VERSION] [SERVER_RELEASE_NOTES_URL] </floater.string> diff --git a/indra/newview/skins/default/xui/zh/floater_about.xml b/indra/newview/skins/default/xui/zh/floater_about.xml index 643881e416..1193243c7e 100755 --- a/indra/newview/skins/default/xui/zh/floater_about.xml +++ b/indra/newview/skins/default/xui/zh/floater_about.xml @@ -8,7 +8,7 @@ 以 [COMPILER_VERSION] 版本 [COMPILER] 建置 </floater.string> <floater.string name="AboutPosition"> - 你的方位是 [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1],地區名:[REGION],主機:<nolink>[HOSTNAME]</nolink> ([HOSTIP]) + 你的方位是 [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1],地區名:[REGION],主機:<nolink>[HOSTNAME]</nolink> ([HOSTIP]) [SERVER_VERSION] [SERVER_RELEASE_NOTES_URL] </floater.string> diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp index 3ba25f3c10..a40b5c9a3d 100755 --- a/indra/newview/tests/llagentaccess_test.cpp +++ b/indra/newview/tests/llagentaccess_test.cpp @@ -49,10 +49,10 @@ LLControlGroup::~LLControlGroup() } // Implementation of just the LLControlGroup methods we requre -BOOL LLControlGroup::declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist) +LLControlVariable* LLControlGroup::declareU32(const std::string& name, U32 initial_val, const std::string& comment, LLControlVariable::ePersist persist) { test_preferred_maturity = initial_val; - return true; + return NULL; } void LLControlGroup::setU32(const std::string& name, U32 val) @@ -80,7 +80,7 @@ namespace tut void agentaccess_object_t::test<1>() { LLControlGroup cgr("test"); - cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); + cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO); LLAgentAccess aa(cgr); cgr.setU32("PreferredMaturity", SIM_ACCESS_PG); @@ -109,7 +109,7 @@ namespace tut void agentaccess_object_t::test<2>() { LLControlGroup cgr("test"); - cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); + cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO); LLAgentAccess aa(cgr); // make sure default is PG @@ -157,7 +157,7 @@ namespace tut void agentaccess_object_t::test<3>() { LLControlGroup cgr("test"); - cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); + cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO); LLAgentAccess aa(cgr); #ifndef HACKED_GODLIKE_VIEWER @@ -195,7 +195,7 @@ namespace tut void agentaccess_object_t::test<4>() { LLControlGroup cgr("test"); - cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); + cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO); LLAgentAccess aa(cgr); #ifndef HACKED_GODLIKE_VIEWER @@ -272,7 +272,7 @@ namespace tut void agentaccess_object_t::test<5>() { LLControlGroup cgr("test"); - cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); + cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", LLControlVariable::PERSIST_NO); LLAgentAccess aa(cgr); cgr.setU32("PreferredMaturity", SIM_ACCESS_ADULT); diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index f038112fd0..adeb848e03 100755 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -135,6 +135,7 @@ void LLGridManager::addSystemGrid(const std::string& label, const std::string& login, const std::string& helper, const std::string& login_page, + const std::string& update_url_base, const std::string& login_id) { } @@ -175,8 +176,8 @@ F32 LLControlGroup::getF32(const std::string& name) { return 0.0f; } U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only) { return 1; } void LLControlGroup::setString(const std::string& name, const std::string& val) {} std::string LLControlGroup::getString(const std::string& name) { return "test_string"; } -BOOL LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist) { return TRUE; } -BOOL LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist) { return TRUE; } +LLControlVariable* LLControlGroup::declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return NULL; } +LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string &initial_val, const std::string& comment, LLControlVariable::ePersist persist) { return NULL; } #include "lluicolortable.h" void LLUIColorTable::saveUserSettings(void)const {} @@ -208,9 +209,7 @@ std::string const & LLUpdaterService::pumpName(void) return wakka; } bool LLUpdaterService::updateReadyToInstall(void) { return false; } -void LLUpdaterService::initialize(const std::string& url, - const std::string& path, - const std::string& channel, +void LLUpdaterService::initialize(const std::string& channel, const std::string& version, const std::string& platform, const std::string& platform_version, @@ -344,13 +343,13 @@ namespace tut gTOSReplyPump = 0; // clear the callback. - gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", FALSE); - gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", FALSE); - gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", FALSE); - gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", FALSE); - gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", FALSE); - gSavedSettings.declareString("NextLoginLocation", "", "", FALSE); - gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", FALSE); + gSavedSettings.declareBOOL("NoInventoryLibrary", FALSE, "", LLControlVariable::PERSIST_NO); + gSavedSettings.declareBOOL("ConnectAsGod", FALSE, "", LLControlVariable::PERSIST_NO); + gSavedSettings.declareBOOL("UseDebugMenus", FALSE, "", LLControlVariable::PERSIST_NO); + gSavedSettings.declareBOOL("ForceMandatoryUpdate", FALSE, "", LLControlVariable::PERSIST_NO); + gSavedSettings.declareString("ClientSettingsFile", "test_settings.xml", "", LLControlVariable::PERSIST_NO); + gSavedSettings.declareString("NextLoginLocation", "", "", LLControlVariable::PERSIST_NO); + gSavedSettings.declareBOOL("LoginLastLocation", FALSE, "", LLControlVariable::PERSIST_NO); LLSD authenticator = LLSD::emptyMap(); LLSD identifier = LLSD::emptyMap(); diff --git a/indra/newview/tests/llsecapi_test.cpp b/indra/newview/tests/llsecapi_test.cpp index 703603e2db..d7e87ed52e 100755 --- a/indra/newview/tests/llsecapi_test.cpp +++ b/indra/newview/tests/llsecapi_test.cpp @@ -39,10 +39,10 @@ LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker<LLControlGroup, std::string>(name) {} LLControlGroup::~LLControlGroup() {} -BOOL LLControlGroup::declareString(const std::string& name, +LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, - BOOL persist) {return TRUE;} + LLControlVariable::ePersist persist) {return NULL;} void LLControlGroup::setString(const std::string& name, const std::string& val){} std::string LLControlGroup::getString(const std::string& name) { diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp index 0235400976..2a8dc15346 100755 --- a/indra/newview/tests/llsechandler_basic_test.cpp +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -71,10 +71,10 @@ std::string gLastName; LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker<LLControlGroup, std::string>(name) {} LLControlGroup::~LLControlGroup() {} -BOOL LLControlGroup::declareString(const std::string& name, +LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, - BOOL persist) {return TRUE;} + LLControlVariable::ePersist persist) {return NULL;} void LLControlGroup::setString(const std::string& name, const std::string& val){} std::string LLControlGroup::getString(const std::string& name) { diff --git a/indra/newview/tests/llslurl_test.cpp b/indra/newview/tests/llslurl_test.cpp index 09343ef227..86229ad636 100755 --- a/indra/newview/tests/llslurl_test.cpp +++ b/indra/newview/tests/llslurl_test.cpp @@ -37,10 +37,10 @@ LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker<LLControlGroup, std::string>(name) {} LLControlGroup::~LLControlGroup() {} -BOOL LLControlGroup::declareString(const std::string& name, +LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, - BOOL persist) {return TRUE;} + LLControlVariable::ePersist persist) {return NULL;} void LLControlGroup::setString(const std::string& name, const std::string& val){} std::string gCmdLineLoginURI; diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp index 710881d811..f6456a2839 100755 --- a/indra/newview/tests/llviewerhelputil_test.cpp +++ b/indra/newview/tests/llviewerhelputil_test.cpp @@ -49,10 +49,10 @@ static std::string gOS; LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker<LLControlGroup, std::string>(name) {} LLControlGroup::~LLControlGroup() {} -BOOL LLControlGroup::declareString(const std::string& name, +LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, - BOOL persist) {return TRUE;} + LLControlVariable::ePersist persist) {return NULL;} void LLControlGroup::setString(const std::string& name, const std::string& val){} std::string LLControlGroup::getString(const std::string& name) { diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp index a1e97ea17e..7ad7947ca4 100755 --- a/indra/newview/tests/llviewernetwork_test.cpp +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -37,10 +37,10 @@ LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker<LLControlGroup, std::string>(name) {} LLControlGroup::~LLControlGroup() {} -BOOL LLControlGroup::declareString(const std::string& name, +LLControlVariable* LLControlGroup::declareString(const std::string& name, const std::string& initial_val, const std::string& comment, - BOOL persist) {return TRUE;} + LLControlVariable::ePersist persist) {return NULL;} void LLControlGroup::setString(const std::string& name, const std::string& val){} std::string gCmdLineLoginURI; @@ -127,6 +127,7 @@ const char *gSampleGridFile = " <array>" " <string>myloginuri</string>" " </array>" + " <key>update_query_url_base</key><string>https://update.secondlife.com/update</string>" " <key>keyname</key><string>util.foobar.lindenlab.com</string>" " </map>" " </map>" @@ -185,6 +186,9 @@ namespace tut ensure_equals("id for agni", std::string("Agni"), LLGridManager::getInstance()->getGridId("util.agni.lindenlab.com")); + ensure_equals("update url base for Agni", // relies on agni being the default + std::string("https://update.secondlife.com/update"), + LLGridManager::getInstance()->getUpdateServiceURL()); ensure_equals("label for agni", LLGridManager::getInstance()->getGridLabel("util.agni.lindenlab.com"), std::string("Second Life Main Grid (Agni)")); @@ -256,6 +260,9 @@ namespace tut ensure_equals("id for agni", LLGridManager::getInstance()->getGridId("util.agni.lindenlab.com"), std::string("Agni")); + ensure_equals("update url base for Agni", // relies on agni being the default + std::string("https://update.secondlife.com/update"), + LLGridManager::getInstance()->getUpdateServiceURL()); ensure_equals("label for agni", LLGridManager::getInstance()->getGridLabel("util.agni.lindenlab.com"), std::string("Second Life Main Grid (Agni)")); @@ -384,6 +391,9 @@ namespace tut ensure_equals("getLoginPage", LLGridManager::getInstance()->getLoginPage(), std::string("http://viewer-login.agni.lindenlab.com/")); + ensure_equals("update url base for Agni", // relies on agni being the default + std::string("https://update.secondlife.com/update"), + LLGridManager::getInstance()->getUpdateServiceURL()); ensure("Is Agni a production grid", LLGridManager::getInstance()->isInProductionGrid()); std::vector<std::string> uris; LLGridManager::getInstance()->getLoginURIs(uris); diff --git a/indra/newview/tests/llxmlrpclistener_test.cpp b/indra/newview/tests/llxmlrpclistener_test.cpp index 711c2a3d51..20f913b670 100755 --- a/indra/newview/tests/llxmlrpclistener_test.cpp +++ b/indra/newview/tests/llxmlrpclistener_test.cpp @@ -62,8 +62,8 @@ namespace tut // These variables are required by machinery used by // LLXMLRPCTransaction. The values reflect reality for this test // executable; hopefully these values are correct. - gSavedSettings.declareBOOL("BrowserProxyEnabled", FALSE, "", FALSE); // don't persist - gSavedSettings.declareBOOL("NoVerifySSLCert", TRUE, "", FALSE); // don't persist + gSavedSettings.declareBOOL("BrowserProxyEnabled", FALSE, "", LLControlVariable::PERSIST_NO); // don't persist + gSavedSettings.declareBOOL("NoVerifySSLCert", TRUE, "", LLControlVariable::PERSIST_NO); // don't persist } // LLEventPump listener signature diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 5e08e54b7c..19863dd845 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -34,9 +34,15 @@ import tarfile import time import random viewer_dir = os.path.dirname(__file__) -# add llmanifest library to our path so we don't have to muck with PYTHONPATH -sys.path.append(os.path.join(viewer_dir, '../lib/python/indra/util')) -from llmanifest import LLManifest, main, proper_windows_path, path_ancestors +# Add indra/lib/python to our path so we don't have to muck with PYTHONPATH. +# Put it FIRST because some of our build hosts have an ancient install of +# indra.util.llmanifest under their system Python! +sys.path.insert(0, os.path.join(viewer_dir, os.pardir, "lib", "python")) +from indra.util.llmanifest import LLManifest, main, proper_windows_path, path_ancestors +try: + from llbase import llsd +except ImportError: + from indra.base import llsd class ViewerManifest(LLManifest): def is_packaging_viewer(self): @@ -65,13 +71,13 @@ class ViewerManifest(LLManifest): # include the entire shaders directory recursively self.path("shaders") # include the extracted list of contributors - contributor_names = self.extract_names("../../doc/contributions.txt") - self.put_in_file(contributor_names, "contributors.txt") - self.file_list.append(["../../doc/contributions.txt",self.dst_path_of("contributors.txt")]) + contributions_path = "../../doc/contributions.txt" + contributor_names = self.extract_names(contributions_path) + self.put_in_file(contributor_names, "contributors.txt", src=contributions_path) # include the extracted list of translators - translator_names = self.extract_names("../../doc/translations.txt") - self.put_in_file(translator_names, "translators.txt") - self.file_list.append(["../../doc/translations.txt",self.dst_path_of("translators.txt")]) + translations_path = "../../doc/translations.txt" + translator_names = self.extract_names(translations_path) + self.put_in_file(translator_names, "translators.txt", src=translations_path) # include the list of Lindens (if any) # see https://wiki.lindenlab.com/wiki/Generated_Linden_Credits linden_names_path = os.getenv("LINDEN_CREDITS") @@ -85,10 +91,9 @@ class ViewerManifest(LLManifest): else: # all names should be one line, but the join below also converts to a string linden_names = ', '.join(linden_file.readlines()) - self.put_in_file(linden_names, "lindens.txt") + self.put_in_file(linden_names, "lindens.txt", src=linden_names_path) linden_file.close() print "Linden names extracted from '%s'" % linden_names_path - self.file_list.append([linden_names_path,self.dst_path_of("lindens.txt")]) # ... and the entire windlight directory self.path("windlight") @@ -99,6 +104,27 @@ class ViewerManifest(LLManifest): self.path("dictionaries") self.end_prefix(pkgdir) + # CHOP-955: If we have "sourceid" in the build process + # environment, generate it into settings_install.xml. + try: + sourceid = os.environ["sourceid"] + except KeyError: + # no sourceid, no settings_install.xml file + pass + else: + if sourceid: + # Single-entry subset of the LLSD content of settings.xml + content = dict(sourceid=dict(Comment='Identify referring agency to Linden web servers', + Persist=1, + Type='String', + Value=sourceid)) + # put_in_file(src=) need not be an actual pathname; it + # only needs to be non-empty + settings_install = self.put_in_file(llsd.format_pretty_xml(content), + "settings_install.xml", + src="environment") + print "Put sourceid '%s' in %s" % (sourceid, settings_install) + self.end_prefix("app_settings") if self.prefix(src="character"): @@ -196,24 +222,26 @@ class ViewerManifest(LLManifest): """ Convenience function that returns the command-line flags for the grid""" - # Set command line flags relating to the target grid - grid_flags = '' - if not self.default_grid(): - grid_flags = "--grid %(grid)s "\ - "--helperuri http://preview-%(grid)s.secondlife.com/helpers/" %\ - {'grid':self.grid()} - - # Deal with settings - setting_flags = '' - if not self.default_channel() or not self.default_grid(): - if self.default_grid(): - setting_flags = '--settings settings_%s.xml'\ - % self.channel_lowerword() - else: - setting_flags = '--settings settings_%s_%s.xml'\ - % (self.grid(), self.channel_lowerword()) - - return " ".join((grid_flags, setting_flags)).strip() + # The original role of this method seems to have been to build a + # grid-specific viewer: one that would, on launch, preselect a + # particular grid. (Apparently that dates back to when the protocol + # between viewer and simulator required them to be updated in + # lockstep, so that "the beta grid" required "a beta viewer.") But + # those viewer command-line switches no longer work without tweaking + # user_settings/grids.xml. In fact, going forward, it's unclear what + # use case that would address. + + # This method also set a channel-specific (or grid-and-channel- + # specific) user_settings/settings_something.xml file. It has become + # clear that saving user settings in a channel-specific file causes + # more problems (confusion) than it solves, so we've discontinued that. + + # In fact we now avoid forcing viewer command-line switches at all, + # instead introducing a settings_install.xml file. Command-line + # switches don't aggregate well; for instance the generated --channel + # switch actually prevented the user specifying --channel on the + # command line. Settings files have well-defined override semantics. + return None def extract_names(self,src): try: @@ -530,8 +558,7 @@ class WindowsManifest(ViewerManifest): 'final_exe' : self.final_exe(), 'grid':self.args['grid'], 'grid_caps':self.args['grid'].upper(), - # escape quotes becase NSIS doesn't handle them well - 'flags':self.flags_list().replace('"', '$\\"'), + 'flags':'', 'channel':self.channel(), 'channel_oneword':self.channel_oneword(), 'channel_unique':self.channel_unique(), @@ -759,9 +786,6 @@ class DarwinManifest(ViewerManifest): self.end_prefix("llplugin") - # command line arguments for connecting to the proper grid - self.put_in_file(self.flags_list(), 'arguments.txt') - self.end_prefix("Resources") self.end_prefix("Contents") @@ -807,10 +831,6 @@ class DarwinManifest(ViewerManifest): 'bundle': self.get_dst_prefix() }) - channel_standin = 'Second Life Viewer' # hah, our default channel is not usable on its own - if not self.default_channel(): - channel_standin = self.channel() - imagename="SecondLife_" + '_'.join(self.args['version']) # MBW -- If the mounted volume name changes, it breaks the .DS_Store's background image and icon positioning. @@ -928,9 +948,6 @@ class LinuxManifest(ViewerManifest): self.path("install.sh") self.end_prefix("linux_tools") - # Create an appropriate gridargs.dat for this package, denoting required grid. - self.put_in_file(self.flags_list(), 'etc/gridargs.dat') - if self.prefix(src="", dst="bin"): self.path("secondlife-bin","do-not-directly-run-secondlife-bin") self.path("../linux_crash_logger/linux-crash-logger","linux-crash-logger.bin") diff --git a/indra/viewer_components/updater/llupdatechecker.cpp b/indra/viewer_components/updater/llupdatechecker.cpp index 1e768f52d9..91a5f9246e 100755 --- a/indra/viewer_components/updater/llupdatechecker.cpp +++ b/indra/viewer_components/updater/llupdatechecker.cpp @@ -62,8 +62,7 @@ LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client): } -void LLUpdateChecker::checkVersion(std::string const & hostUrl, - std::string const & servicePath, +void LLUpdateChecker::checkVersion(std::string const & urlBase, std::string const & channel, std::string const & version, std::string const & platform, @@ -71,7 +70,7 @@ void LLUpdateChecker::checkVersion(std::string const & hostUrl, unsigned char uniqueid[MD5HEX_STR_SIZE], bool willing_to_test) { - mImplementation->checkVersion(hostUrl, servicePath, channel, version, platform, platform_version, uniqueid, willing_to_test); + mImplementation->checkVersion(urlBase, channel, version, platform, platform_version, uniqueid, willing_to_test); } @@ -99,8 +98,7 @@ LLUpdateChecker::Implementation::~Implementation() } -void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl, - std::string const & servicePath, +void LLUpdateChecker::Implementation::checkVersion(std::string const & urlBase, std::string const & channel, std::string const & version, std::string const & platform, @@ -112,8 +110,7 @@ void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl, { mInProgress = true; - mHostUrl = hostUrl; - mServicePath = servicePath; + mUrlBase = urlBase; mChannel = channel; mVersion = version; mPlatform = platform; @@ -123,7 +120,7 @@ void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl, mProtocol = sProtocolVersion; - std::string checkUrl = buildUrl(hostUrl, servicePath, channel, version, platform, platform_version, uniqueid, willing_to_test); + std::string checkUrl = buildUrl(urlBase, channel, version, platform, platform_version, uniqueid, willing_to_test); LL_INFOS("UpdaterService") << "checking for updates at " << checkUrl << LL_ENDL; mHttpClient.get(checkUrl, this); @@ -158,7 +155,7 @@ void LLUpdateChecker::Implementation::completed(U32 status, if (mProtocol == sProtocolVersion) { mProtocol = sLegacyProtocolVersion; - std::string retryUrl = buildUrl(mHostUrl, mServicePath, mChannel, mVersion, mPlatform, mPlatformVersion, mUniqueId, mWillingToTest); + std::string retryUrl = buildUrl(mUrlBase, mChannel, mVersion, mPlatform, mPlatformVersion, mUniqueId, mWillingToTest); LL_WARNS("UpdaterService") << "update response using " << sProtocolVersion @@ -203,8 +200,7 @@ void LLUpdateChecker::Implementation::error(U32 status, const std::string & reas } -std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUrl, - std::string const & servicePath, +std::string LLUpdateChecker::Implementation::buildUrl(std::string const & urlBase, std::string const & channel, std::string const & version, std::string const & platform, @@ -213,7 +209,6 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUr bool willing_to_test) { LLSD path; - path.append(servicePath); path.append(mProtocol); path.append(channel); path.append(version); @@ -224,5 +219,5 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUr path.append(willing_to_test ? "testok" : "testno"); path.append((char*)uniqueid); } - return LLURI::buildHTTP(hostUrl, path).asString(); + return LLURI::buildHTTP(urlBase, path).asString(); } diff --git a/indra/viewer_components/updater/llupdatechecker.h b/indra/viewer_components/updater/llupdatechecker.h index 8e85587490..4244007340 100755 --- a/indra/viewer_components/updater/llupdatechecker.h +++ b/indra/viewer_components/updater/llupdatechecker.h @@ -43,8 +43,7 @@ public: public: Implementation(Client & client); ~Implementation(); - void checkVersion(std::string const & hostUrl, - std::string const & servicePath, + void checkVersion(std::string const & urlBase, std::string const & channel, std::string const & version, std::string const & platform, @@ -68,16 +67,14 @@ public: LLHTTPClient mHttpClient; bool mInProgress; std::string mVersion; - std::string mHostUrl; - std::string mServicePath; + std::string mUrlBase; std::string mChannel; std::string mPlatform; std::string mPlatformVersion; unsigned char mUniqueId[MD5HEX_STR_SIZE]; bool mWillingToTest; - std::string buildUrl(std::string const & hostUrl, - std::string const & servicePath, + std::string buildUrl(std::string const & urlBase, std::string const & channel, std::string const & version, std::string const & platform, @@ -95,8 +92,7 @@ public: LLUpdateChecker(Client & client); // Check status of current app on the given host for the channel and version provided. - void checkVersion(std::string const & hostUrl, - std::string const & servicePath, + void checkVersion(std::string const & urlBase, std::string const & channel, std::string const & version, std::string const & platform, diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 1bd9fa4fc0..16950e1d62 100755 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -38,6 +38,7 @@ #include "lldir.h" #include "llsdserialize.h" #include "llfile.h" +#include "llviewernetwork.h" #if LL_WINDOWS #pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally @@ -93,8 +94,6 @@ class LLUpdaterServiceImpl : static const std::string sListenerName; std::string mProtocolVersion; - std::string mUrl; - std::string mPath; std::string mChannel; std::string mVersion; std::string mPlatform; @@ -120,9 +119,7 @@ public: LLUpdaterServiceImpl(); virtual ~LLUpdaterServiceImpl(); - void initialize(const std::string& url, - const std::string& path, - const std::string& channel, + void initialize(const std::string& channel, const std::string& version, const std::string& platform, const std::string& platform_version, @@ -183,9 +180,7 @@ LLUpdaterServiceImpl::~LLUpdaterServiceImpl() LLEventPumps::instance().obtain("mainloop").stopListening(sListenerName); } -void LLUpdaterServiceImpl::initialize(const std::string& url, - const std::string& path, - const std::string& channel, +void LLUpdaterServiceImpl::initialize(const std::string& channel, const std::string& version, const std::string& platform, const std::string& platform_version, @@ -198,8 +193,6 @@ void LLUpdaterServiceImpl::initialize(const std::string& url, "while updater is running."); } - mUrl = url; - mPath = path; mChannel = channel; mVersion = version; mPlatform = platform; @@ -207,8 +200,6 @@ void LLUpdaterServiceImpl::initialize(const std::string& url, memcpy(mUniqueId, uniqueid, MD5HEX_STR_SIZE); mWillingToTest = willing_to_test; LL_DEBUGS("UpdaterService") - << "\n url: " << mUrl - << "\n path: " << mPath << "\n channel: " << mChannel << "\n version: " << mVersion << "\n uniqueid: " << mUniqueId @@ -228,7 +219,7 @@ void LLUpdaterServiceImpl::setBandwidthLimit(U64 bytesPerSecond) void LLUpdaterServiceImpl::startChecking(bool install_if_ready) { - if(mUrl.empty() || mChannel.empty() || mVersion.empty()) + if(mChannel.empty() || mVersion.empty()) { throw LLUpdaterService::UsageError("Set params before call to " "LLUpdaterService::startCheck()."); @@ -415,7 +406,7 @@ void LLUpdaterServiceImpl::response(LLSD const & content) setState(LLUpdaterService::UP_TO_DATE); } - else + else if ( content.isMap() && content.has("url") ) { // there is an update available... stopTimer(); @@ -439,6 +430,12 @@ void LLUpdaterServiceImpl::response(LLSD const & content) << LL_ENDL; mUpdateDownloader.download(url, content["hash"].asString(), mNewChannel, mNewVersion, more_info, required); } + else + { + LL_WARNS("UpdaterService") << "Invalid update query response ignored; retry in " + << mCheckPeriod << " seconds" << LL_ENDL; + restartTimer(mCheckPeriod); + } } void LLUpdaterServiceImpl::downloadComplete(LLSD const & data) @@ -565,8 +562,26 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event) } else { - mUpdateChecker.checkVersion(mUrl, mPath, mChannel, mVersion, mPlatform, mPlatformVersion, mUniqueId, mWillingToTest); - setState(LLUpdaterService::CHECKING_FOR_UPDATE); + std::string query_url = LLGridManager::getInstance()->getUpdateServiceURL(); + if ( !query_url.empty() ) + { + mUpdateChecker.checkVersion(query_url, mChannel, mVersion, + mPlatform, mPlatformVersion, mUniqueId, + mWillingToTest); + setState(LLUpdaterService::CHECKING_FOR_UPDATE); + } + else + { + LL_WARNS("UpdaterService") + << "No updater service defined for grid '" << LLGridManager::getInstance()->getGrid() + << "' will check again in " << mCheckPeriod << " seconds" + << LL_ENDL; + // Because the grid can be changed after the viewer is started (when the first check takes place) + // but before the user logs in, the next check may be on a different grid, so set the retry timer + // even though this check did not happen. The default time is once an hour, and if we're not + // doing the check anyway the performance impact is completely insignificant. + restartTimer(mCheckPeriod); + } } } else @@ -610,9 +625,7 @@ LLUpdaterService::~LLUpdaterService() { } -void LLUpdaterService::initialize(const std::string& url, - const std::string& path, - const std::string& channel, +void LLUpdaterService::initialize(const std::string& channel, const std::string& version, const std::string& platform, const std::string& platform_version, @@ -620,7 +633,7 @@ void LLUpdaterService::initialize(const std::string& url, const bool& willing_to_test ) { - mImpl->initialize(url, path, channel, version, platform, platform_version, uniqueid, willing_to_test); + mImpl->initialize(channel, version, platform, platform_version, uniqueid, willing_to_test); } void LLUpdaterService::setCheckPeriod(unsigned int seconds) diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 982f99b861..0ddf24935b 100755 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -71,9 +71,7 @@ public: LLUpdaterService(); ~LLUpdaterService(); - void initialize(const std::string& url, - const std::string& path, - const std::string& channel, + void initialize(const std::string& channel, const std::string& version, const std::string& platform, const std::string& platform_version, diff --git a/indra/viewer_components/updater/scripts/linux/update_install b/indra/viewer_components/updater/scripts/linux/update_install index a9df9042fd..03089f192e 100755 --- a/indra/viewer_components/updater/scripts/linux/update_install +++ b/indra/viewer_components/updater/scripts/linux/update_install @@ -69,8 +69,11 @@ then # zenity on PATH and is executable # clear any previous message clear_message # put up a new zenity box and capture its pid - "$zenpath" --info --title "Second Life Viewer Updater" \ - --width=320 --height=120 --text="$*" & +## "$zenpath" --info --title "Second Life Viewer Updater" \ +## --width=320 --height=120 --text="$*" & + # MAINT-2333: use bouncing progress bar + "$zenpath" --progress --pulsate --no-cancel --title "Second Life Viewer Updater" \ + --width=320 --height=120 --text "$*" </dev/null & statuspid=$! } diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index 4812272ebc..759e41ef4c 100755 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -44,8 +44,7 @@ *****************************************************************************/ LLUpdateChecker::LLUpdateChecker(LLUpdateChecker::Client & client) {} -void LLUpdateChecker::checkVersion(std::string const & hostUrl, - std::string const & servicePath, +void LLUpdateChecker::checkVersion(std::string const & urlBase, std::string const & channel, std::string const & version, std::string const & platform, @@ -91,6 +90,21 @@ bool LLDir::setCacheDir(const std::string &path){ return true; } void LLDir::dumpCurrentDirectories() {} void LLDir::updatePerAccountChatLogsDir() {} +#include "llviewernetwork.h" +LLGridManager::LLGridManager() : + mGrid("test.grid.lindenlab.com"), + mIsInProductionGrid(false) +{ +} +std::string LLGridManager::getUpdateServiceURL() +{ + return "https://update.secondlife.com/update"; +} +LLGridManager::~LLGridManager() +{ +} + + std::string LLDir::getExpandedFilename(ELLPath location, const std::string &filename) const { @@ -179,10 +193,10 @@ namespace tut try { unsigned char id1[MD5HEX_STR_SIZE] = "11111111111111111111111111111111"; - updater.initialize(test_url, "update" ,test_channel, test_version, "win", "1.2.3", id1, true); + updater.initialize(test_channel, test_version, "win", "1.2.3", id1, true); updater.startChecking(); unsigned char id2[MD5HEX_STR_SIZE] = "22222222222222222222222222222222"; - updater.initialize("other_url", "update", test_channel, test_version, "win", "4.5.6", id2, true); + updater.initialize(test_channel, test_version, "win", "4.5.6", id2, true); } catch(LLUpdaterService::UsageError) { @@ -197,7 +211,7 @@ namespace tut DEBUG; LLUpdaterService updater; unsigned char id[MD5HEX_STR_SIZE] = "33333333333333333333333333333333"; - updater.initialize(test_url, "update", test_channel, test_version, "win", "7.8.9", id, true); + updater.initialize(test_channel, test_version, "win", "7.8.9", id, true); updater.startChecking(); ensure(updater.isChecking()); updater.stopChecking(); |