summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rwxr-xr-xindra/cmake/BuildVersion.cmake2
-rwxr-xr-xindra/edit-me-to-trigger-new-build.txt1
-rwxr-xr-xindra/lib/python/indra/util/llmanifest.py18
-rwxr-xr-xindra/llcommon/tests/llprocess_test.cpp14
-rwxr-xr-xindra/llui/llbutton.cpp5
-rwxr-xr-xindra/llui/llbutton.h4
-rwxr-xr-xindra/llui/llchatentry.cpp10
-rwxr-xr-xindra/llui/llchatentry.h6
-rwxr-xr-xindra/llui/llfloater.cpp33
-rwxr-xr-xindra/llui/llfloater.h5
-rwxr-xr-xindra/llui/llfloaterreg.cpp12
-rwxr-xr-xindra/llui/llfolderview.cpp26
-rwxr-xr-xindra/llui/llfolderviewitem.cpp30
-rwxr-xr-xindra/llui/llfolderviewitem.h1
-rwxr-xr-xindra/llui/llfolderviewmodel.cpp2
-rwxr-xr-xindra/llui/llfolderviewmodel.h31
-rwxr-xr-xindra/llui/lllayoutstack.cpp102
-rwxr-xr-xindra/llui/lllayoutstack.h10
-rwxr-xr-xindra/llui/llmenugl.cpp12
-rwxr-xr-xindra/llui/llnotifications.cpp2
-rwxr-xr-xindra/llui/llresizebar.cpp110
-rwxr-xr-xindra/llui/llresizebar.h52
-rwxr-xr-xindra/llui/llscrolllistctrl.cpp4
-rwxr-xr-xindra/llui/llscrolllistctrl.h2
-rwxr-xr-xindra/llui/lltextbase.cpp89
-rwxr-xr-xindra/llui/lltextbase.h8
-rwxr-xr-xindra/llui/lltexteditor.cpp82
-rwxr-xr-xindra/llui/lltexteditor.h3
-rwxr-xr-xindra/llui/lltoolbar.cpp4
-rwxr-xr-xindra/llui/lltoolbar.h2
-rwxr-xr-xindra/llui/llurlaction.cpp42
-rwxr-xr-xindra/llui/llurlaction.h4
-rwxr-xr-xindra/llui/llurlentry.cpp4
-rwxr-xr-xindra/llvfs/lldir.h2
-rwxr-xr-xindra/llwindow/llwindowwin32.cpp19
-rwxr-xr-xindra/llxml/llcontrol.cpp131
-rwxr-xr-xindra/llxml/llcontrol.h49
-rwxr-xr-xindra/llxml/tests/llcontrol_test.cpp6
-rwxr-xr-xindra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rwxr-xr-xindra/newview/app_settings/cmd_line.xml21
-rwxr-xr-xindra/newview/app_settings/settings.xml269
-rwxr-xr-xindra/newview/app_settings/settings_files.xml3
-rwxr-xr-xindra/newview/app_settings/settings_minimal.xml5
-rwxr-xr-xindra/newview/app_settings/settings_per_account.xml13
-rwxr-xr-xindra/newview/linux_tools/wrapper.sh34
-rwxr-xr-xindra/newview/llagent.cpp15
-rwxr-xr-xindra/newview/llappviewer.cpp189
-rwxr-xr-xindra/newview/llappviewer.h3
-rwxr-xr-xindra/newview/llappviewermacosx.cpp19
-rwxr-xr-xindra/newview/llchannelmanager.cpp2
-rwxr-xr-xindra/newview/llchatbar.cpp2
-rwxr-xr-xindra/newview/llchathistory.cpp1
-rwxr-xr-xindra/newview/llchatitemscontainerctrl.cpp5
-rwxr-xr-xindra/newview/llcommandlineparser.cpp198
-rwxr-xr-xindra/newview/llcommandlineparser.h2
-rwxr-xr-xindra/newview/llconversationmodel.cpp9
-rwxr-xr-xindra/newview/llconversationmodel.h9
-rwxr-xr-xindra/newview/llconversationview.cpp49
-rwxr-xr-xindra/newview/llconversationview.h4
-rwxr-xr-xindra/newview/lldonotdisturbnotificationstorage.cpp19
-rwxr-xr-xindra/newview/llfavoritesbar.cpp7
-rwxr-xr-xindra/newview/llfavoritesbar.h1
-rwxr-xr-xindra/newview/llfeaturemanager.cpp117
-rwxr-xr-xindra/newview/llfeaturemanager.h14
-rwxr-xr-xindra/newview/llfloaterabout.cpp12
-rwxr-xr-xindra/newview/llfloateravatarpicker.cpp8
-rwxr-xr-xindra/newview/llfloaterbulkpermission.cpp36
-rwxr-xr-xindra/newview/llfloaterbulkpermission.h16
-rwxr-xr-xindra/newview/llfloaterconversationpreview.cpp47
-rwxr-xr-xindra/newview/llfloaterconversationpreview.h3
-rw-r--r--indra/newview/llfloatergotoline.cpp160
-rw-r--r--indra/newview/llfloatergotoline.h66
-rwxr-xr-xindra/newview/llfloaterimcontainer.cpp231
-rwxr-xr-xindra/newview/llfloaterimcontainer.h17
-rwxr-xr-xindra/newview/llfloaterimnearbychat.cpp48
-rwxr-xr-xindra/newview/llfloaterimnearbychathandler.cpp1
-rwxr-xr-xindra/newview/llfloaterimnearbychatlistener.cpp4
-rwxr-xr-xindra/newview/llfloaterimsession.cpp30
-rwxr-xr-xindra/newview/llfloaterimsessiontab.cpp58
-rwxr-xr-xindra/newview/llfloaterimsessiontab.h8
-rwxr-xr-xindra/newview/llfloaterpreference.cpp4
-rwxr-xr-xindra/newview/llfolderviewmodelinventory.cpp69
-rwxr-xr-xindra/newview/llfolderviewmodelinventory.h3
-rwxr-xr-xindra/newview/llgroupactions.cpp125
-rwxr-xr-xindra/newview/llgroupactions.h8
-rwxr-xr-xindra/newview/llimview.cpp300
-rwxr-xr-xindra/newview/llinventoryfilter.cpp42
-rwxr-xr-xindra/newview/llinventoryfilter.h17
-rwxr-xr-xindra/newview/llinventorypanel.cpp3
-rwxr-xr-xindra/newview/lllogchat.cpp300
-rwxr-xr-xindra/newview/lllogchat.h24
-rwxr-xr-xindra/newview/llmaniprotate.cpp232
-rwxr-xr-xindra/newview/llnotificationstorage.h1
-rwxr-xr-xindra/newview/llnotificationtiphandler.cpp7
-rwxr-xr-xindra/newview/llpanellogin.cpp33
-rwxr-xr-xindra/newview/llpanelmaininventory.cpp7
-rwxr-xr-xindra/newview/llpanelmaininventory.h1
-rwxr-xr-xindra/newview/llpanelpeople.cpp4
-rwxr-xr-xindra/newview/llpanelprofile.cpp20
-rwxr-xr-xindra/newview/llpersistentnotificationstorage.cpp24
-rwxr-xr-xindra/newview/llpersistentnotificationstorage.h3
-rwxr-xr-xindra/newview/llpreviewscript.cpp21
-rwxr-xr-xindra/newview/llpreviewscript.h3
-rwxr-xr-xindra/newview/llstartup.cpp6
-rwxr-xr-xindra/newview/llsyswellwindow.cpp11
-rwxr-xr-xindra/newview/lltoastimpanel.cpp26
-rwxr-xr-xindra/newview/lltoastimpanel.h2
-rwxr-xr-xindra/newview/lltoolbarview.cpp23
-rwxr-xr-xindra/newview/lltoolbarview.h2
-rwxr-xr-xindra/newview/llviewercontrol.cpp4
-rwxr-xr-xindra/newview/llviewermessage.cpp35
-rwxr-xr-xindra/newview/llviewernetwork.cpp32
-rwxr-xr-xindra/newview/llviewernetwork.h9
-rwxr-xr-xindra/newview/llviewerwindow.cpp1
-rwxr-xr-xindra/newview/skins/default/colors.xml15
-rwxr-xr-xindra/newview/skins/default/textures/textures.xml3
-rw-r--r--indra/newview/skins/default/textures/widgets/horizontal_drag_handle.pngbin0 -> 197 bytes
-rw-r--r--indra/newview/skins/default/textures/widgets/vertical_drag_handle.pngbin0 -> 196 bytes
-rwxr-xr-xindra/newview/skins/default/xui/da/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/de/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_about.xml4
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_bulk_perms.xml19
-rw-r--r--indra/newview/skins/default/xui/en/floater_goto_line.xml44
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_im_container.xml103
-rwxr-xr-xindra/newview/skins/default/xui/en/floater_im_session.xml100
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_conversation.xml8
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_people_friends_view.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_url_agent.xml9
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_url_objectim.xml7
-rwxr-xr-xindra/newview/skins/default/xui/en/menu_viewer.xml11
-rwxr-xr-xindra/newview/skins/default/xui/en/notifications.xml17
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_group_notices.xml4
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_people.xml14
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_preferences_advanced.xml2
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_preferences_chat.xml144
-rwxr-xr-xindra/newview/skins/default/xui/en/panel_script_ed.xml4
-rwxr-xr-xindra/newview/skins/default/xui/en/strings.xml6
-rwxr-xr-xindra/newview/skins/default/xui/es/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/fr/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/it/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/ja/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pt/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/ru/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/tr/floater_about.xml2
-rwxr-xr-xindra/newview/skins/default/xui/zh/floater_about.xml2
-rwxr-xr-xindra/newview/tests/llagentaccess_test.cpp14
-rwxr-xr-xindra/newview/tests/lllogininstance_test.cpp23
-rwxr-xr-xindra/newview/tests/llsecapi_test.cpp4
-rwxr-xr-xindra/newview/tests/llsechandler_basic_test.cpp4
-rwxr-xr-xindra/newview/tests/llslurl_test.cpp4
-rwxr-xr-xindra/newview/tests/llviewerhelputil_test.cpp4
-rwxr-xr-xindra/newview/tests/llviewernetwork_test.cpp14
-rwxr-xr-xindra/newview/tests/llxmlrpclistener_test.cpp4
-rwxr-xr-xindra/newview/viewer_manifest.py99
-rwxr-xr-xindra/viewer_components/updater/llupdatechecker.cpp58
-rwxr-xr-xindra/viewer_components/updater/llupdatechecker.h12
-rwxr-xr-xindra/viewer_components/updater/llupdaterservice.cpp53
-rwxr-xr-xindra/viewer_components/updater/llupdaterservice.h4
-rwxr-xr-xindra/viewer_components/updater/scripts/linux/update_install7
-rwxr-xr-xindra/viewer_components/updater/tests/llupdaterservice_test.cpp24
162 files changed, 3508 insertions, 1458 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 4ccb019106..50ac511d18 100755
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -648,7 +648,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;
}
@@ -975,8 +975,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 6a1b48a08a..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,19 +158,21 @@ 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)
diff --git a/indra/llui/llchatentry.h b/indra/llui/llchatentry.h
index 49c8d21450..e67f39b21b 100755
--- a/indra/llui/llchatentry.h
+++ b/indra/llui/llchatentry.h
@@ -56,14 +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();
+ /*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 913de49d63..d44b1ad51a 100755
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -507,22 +507,11 @@ LLFloater::~LLFloater()
{
LLFloaterReg::removeInstance(mInstanceName, mKey);
-// delete mNotificationContext;
-// mNotificationContext = NULL;
-
- //// am I not hosted by another floater?
- //if (mHostHandle.isDead())
- //{
- // LLFloaterView* parent = (LLFloaterView*) getParent();
-
- // if( parent )
- // {
- // parent->removeChild( this );
- // }
- //}
-
- // Just in case we might still have focus here, release it.
- releaseFocus();
+ if( gFocusMgr.childHasKeyboardFocus(this))
+ {
+ // Just in case we might still have focus here, release it.
+ releaseFocus();
+ }
// This is important so that floaters with persistent rects (i.e., those
// created with rect control rather than an LLRect) are restored in their
@@ -1490,6 +1479,7 @@ void LLFloater::moveResizeHandlesToFront()
}
}
+/*virtual*/
BOOL LLFloater::isFrontmost()
{
LLFloaterView* floater_view = getParentByType<LLFloaterView>();
@@ -1508,7 +1498,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
@@ -2754,7 +2744,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)
{
@@ -2807,7 +2797,7 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out
}
// move window fully onscreen
- if (floater->translateIntoRect( getSnapRect(), 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();
}
@@ -3277,6 +3267,11 @@ bool LLFloater::isShown() const
return ! isMinimized() && isInVisibleChain();
}
+bool LLFloater::isDetachedAndNotMinimized()
+{
+ return !getHost() && !isMinimized();
+}
+
/* static */
bool LLFloater::isShown(const LLFloater* floater)
{
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 09fe2219c0..b6ff04e000 100755
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -238,6 +238,7 @@ public:
void center();
LLMultiFloater* getHost();
+ bool isDetachedAndNotMinimized();
void applyTitle();
std::string getCurrentTitle() const;
@@ -261,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 +530,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 8aa1eb7cd5..cf449217f5 100755
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -323,9 +323,11 @@ static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View");
void LLFolderView::filter( LLFolderViewFilter& filter )
{
+ // Entry point of inventory filtering (CHUI-849)
LLFastTimer t2(FTM_FILTER);
- filter.setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000));
+ filter.resetTime(llclamp(LLUI::sSettingGroups["config"]->getS32(mParentPanel->getVisible() ? "FilterItemsMaxTimePerFrameVisible" : "FilterItemsMaxTimePerFrameUnvisible"), 1, 100));
+ // Note: we filter the model, not the view
getViewModelItem()->filter(filter);
}
@@ -661,7 +663,7 @@ void LLFolderView::draw()
// get preferable text height...
S32 pixel_height = mStatusTextBox->getTextPixelHeight();
- bool height_changed = local_rect.getHeight() != pixel_height;
+ bool height_changed = (local_rect.getHeight() < pixel_height);
if (height_changed)
{
// ... if it does not match current height, lets rearrange current view.
@@ -1601,15 +1603,17 @@ void LLFolderView::update()
{
mNeedsAutoSelect = TRUE;
}
- // filter to determine visibility before arranging
+
+ // Filter to determine visibility before arranging
filter(getFolderViewModel()->getFilter());
- // Clear the modified setting on the filter only if the filter count is non-zero after running the filter process
- // Note: if the filter count is zero, then the filter most likely halted before completing the entire set of items
- if (getFolderViewModel()->getFilter().isModified() && (getFolderViewModel()->getFilter().getFilterCount() > 0))
+
+ // Clear the modified setting on the filter only if the filter finished after running the filter process
+ // Note: if the filter count has timed out, that means the filter halted before completing the entire set of items
+ if (getFolderViewModel()->getFilter().isModified() && (!getFolderViewModel()->getFilter().isTimedOut()))
{
getFolderViewModel()->getFilter().clearModified();
}
-
+
// automatically show matching items, and select first one if we had a selection
if (mNeedsAutoSelect)
{
@@ -1649,11 +1653,13 @@ void LLFolderView::update()
BOOL is_visible = isInVisibleChain();
- //Puts folders/items in proper positions
- if ( is_visible )
+ // 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)
{
sanitizeSelection();
- if( needsArrange() )
+ if (needsArrange())
{
S32 height = 0;
S32 width = 0;
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index fdb4108afb..6c147ccc12 100755
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -274,6 +274,7 @@ void LLFolderViewItem::refresh()
}
mLabelWidthDirty = true;
+ // Dirty the filter flag of the model from the view (CHUI-849)
vmi.dirtyFilter();
}
@@ -943,11 +944,17 @@ void LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder)
static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange");
-// Finds width and height of this object and its children. Also
-// makes sure that this view and its children are the right size.
+// Make everything right and in the right place ready for drawing (CHUI-849)
+// * Sort everything correctly if necessary
+// * Turn widgets visible/invisible according to their model filtering state
+// * Takes animation state into account for opening/closing of folders (this makes widgets visible/invisible)
+// * Reposition visible widgets so that they line up correctly with no gap
+// * Compute the width and height of the current folder and its children
+// * Makes sure that this view and its children are the right size
S32 LLFolderViewFolder::arrange( S32* width, S32* height )
{
- // sort before laying out contents
+ // Sort before laying out contents
+ // Note that we sort from the root (CHUI-849)
getRoot()->getFolderViewModel()->sort(this);
LLFastTimer t2(FTM_ARRANGE);
@@ -1613,16 +1620,13 @@ void LLFolderViewFolder::addFolder(LLFolderViewFolder* folder)
}
void LLFolderViewFolder::requestArrange()
-{
- if ( mLastArrangeGeneration != -1)
- {
- mLastArrangeGeneration = -1;
- // flag all items up to root
- if (mParentFolder)
- {
- mParentFolder->requestArrange();
- }
- }
+{
+ mLastArrangeGeneration = -1;
+ // flag all items up to root
+ if (mParentFolder)
+ {
+ mParentFolder->requestArrange();
+ }
}
void LLFolderViewFolder::toggleOpen()
diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h
index ca31931e19..a9b0201236 100755
--- a/indra/llui/llfolderviewitem.h
+++ b/indra/llui/llfolderviewitem.h
@@ -316,7 +316,6 @@ protected:
F32 mAutoOpenCountdown;
S32 mLastArrangeGeneration;
S32 mLastCalculatedWidth;
- S32 mMostFilteredDescendantGeneration;
bool mNeedsSort;
public:
diff --git a/indra/llui/llfolderviewmodel.cpp b/indra/llui/llfolderviewmodel.cpp
index 3593804554..3363dc5316 100755
--- a/indra/llui/llfolderviewmodel.cpp
+++ b/indra/llui/llfolderviewmodel.cpp
@@ -48,7 +48,7 @@ std::string LLFolderViewModelCommon::getStatusText()
void LLFolderViewModelCommon::filter()
{
- getFilter().setFilterCount(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsPerFrame"), 1, 5000));
+ getFilter().resetTime(llclamp(LLUI::sSettingGroups["config"]->getS32("FilterItemsMaxTimePerFrameVisible"), 1, 100));
mFolderView->getViewModelItem()->filter(getFilter());
}
diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h
index 1b61212c0e..b1bcc8bbb4 100755
--- a/indra/llui/llfolderviewmodel.h
+++ b/indra/llui/llfolderviewmodel.h
@@ -87,12 +87,11 @@ public:
virtual void setModified(EFilterModified behavior = FILTER_RESTART) = 0;
// +-------------------------------------------------------------------+
- // + Count
+ // + Time
// +-------------------------------------------------------------------+
- virtual void setFilterCount(S32 count) = 0;
- virtual S32 getFilterCount() const = 0;
- virtual void decrementFilterCount() = 0;
-
+ virtual void resetTime(S32 timeout) = 0;
+ virtual bool isTimedOut() = 0;
+
// +-------------------------------------------------------------------+
// + Default
// +-------------------------------------------------------------------+
@@ -308,26 +307,28 @@ public:
virtual bool potentiallyVisible()
{
return passedFilter() // we've passed the filter
- || getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration() // or we don't know yet
+ || (getLastFilterGeneration() < mRootViewModel.getFilter().getFirstSuccessGeneration()) // or we don't know yet
|| descendantsPassedFilter();
}
virtual bool passedFilter(S32 filter_generation = -1)
{
- if (filter_generation < 0)
+ if (filter_generation < 0)
+ {
filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration();
-
- bool passed_folder_filter = mPassedFolderFilter && mLastFolderFilterGeneration >= filter_generation;
- bool passed_filter = mPassedFilter && mLastFilterGeneration >= filter_generation;
- return passed_folder_filter
- && (descendantsPassedFilter(filter_generation)
- || passed_filter);
+ }
+ bool passed_folder_filter = mPassedFolderFilter && (mLastFolderFilterGeneration >= filter_generation);
+ bool passed_filter = mPassedFilter && (mLastFilterGeneration >= filter_generation);
+ return passed_folder_filter && (passed_filter || descendantsPassedFilter(filter_generation));
}
virtual bool descendantsPassedFilter(S32 filter_generation = -1)
{
- if (filter_generation < 0) filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration();
- return mMostFilteredDescendantGeneration >= filter_generation;
+ if (filter_generation < 0)
+ {
+ filter_generation = mRootViewModel.getFilter().getFirstSuccessGeneration();
+ }
+ return mMostFilteredDescendantGeneration >= filter_generation;
}
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index e33ac1d5c2..c89c0203b4 100755
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -214,8 +214,15 @@ LLLayoutStack::Params::Params()
open_time_constant("open_time_constant", 0.02f),
close_time_constant("close_time_constant", 0.03f),
resize_bar_overlap("resize_bar_overlap", 1),
- border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0))
-{}
+ border_size("border_size", LLCachedControl<S32>(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0)),
+ show_drag_handle("show_drag_handle", false),
+ drag_handle_first_indent("drag_handle_first_indent", 0),
+ drag_handle_second_indent("drag_handle_second_indent", 0),
+ drag_handle_thickness("drag_handle_thickness", 5),
+ drag_handle_shift("drag_handle_shift", 2)
+{
+ addSynonym(border_size, "drag_handle_gap");
+}
LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)
: LLView(p),
@@ -227,8 +234,14 @@ LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p)
mClip(p.clip),
mOpenTimeConstant(p.open_time_constant),
mCloseTimeConstant(p.close_time_constant),
- mResizeBarOverlap(p.resize_bar_overlap)
-{}
+ mResizeBarOverlap(p.resize_bar_overlap),
+ mShowDragHandle(p.show_drag_handle),
+ mDragHandleFirstIndent(p.drag_handle_first_indent),
+ mDragHandleSecondIndent(p.drag_handle_second_indent),
+ mDragHandleThickness(p.drag_handle_thickness),
+ mDragHandleShift(p.drag_handle_shift)
+{
+}
LLLayoutStack::~LLLayoutStack()
{
@@ -262,6 +275,26 @@ void LLLayoutStack::draw()
drawChild(panelp, 0, 0, !clip_rect.isEmpty());
}
}
+
+ const LLView::child_list_t * child_listp = getChildList();
+ BOOST_FOREACH(LLView * childp, * child_listp)
+ {
+ LLResizeBar * resize_barp = dynamic_cast<LLResizeBar*>(childp);
+ if (resize_barp && resize_barp->isShowDragHandle() && resize_barp->getVisible() && resize_barp->getRect().isValid())
+ {
+ LLRect screen_rect = resize_barp->calcScreenRect();
+ if (LLUI::getRootView()->getLocalRect().overlaps(screen_rect) && LLUI::sDirtyRect.overlaps(screen_rect))
+ {
+ LLUI::pushMatrix();
+ {
+ const LLRect& rb_rect(resize_barp->getRect());
+ LLUI::translate(rb_rect.mLeft, rb_rect.mBottom);
+ resize_barp->draw();
+ }
+ LLUI::popMatrix();
+ }
+ }
+ }
}
void LLLayoutStack::removeChild(LLView* view)
@@ -390,7 +423,6 @@ void LLLayoutStack::updateLayout()
BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)
{
F32 panel_dim = llmax(panelp->getExpandedMinDim(), panelp->mTargetDim);
- F32 panel_visible_dim = panelp->getVisibleDim();
LLRect panel_rect;
if (mOrientation == HORIZONTAL)
@@ -407,27 +439,61 @@ void LLLayoutStack::updateLayout()
getRect().getWidth(),
llround(panel_dim));
}
- panelp->setIgnoreReshape(true);
- panelp->setShape(panel_rect);
- panelp->setIgnoreReshape(false);
LLRect resize_bar_rect(panel_rect);
-
+ LLResizeBar * resize_barp = panelp->getResizeBar();
+ bool show_drag_handle = resize_barp->isShowDragHandle();
F32 panel_spacing = (F32)mPanelSpacing * panelp->getVisibleAmount();
+ F32 panel_visible_dim = panelp->getVisibleDim();
+ S32 panel_spacing_round = (S32)(llround(panel_spacing));
+
if (mOrientation == HORIZONTAL)
{
- resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap;
- resize_bar_rect.mRight = panel_rect.mRight + (S32)(llround(panel_spacing)) + mResizeBarOverlap;
-
cur_pos += panel_visible_dim + panel_spacing;
+
+ if (show_drag_handle && panel_spacing_round > mDragHandleThickness)
+ {
+ resize_bar_rect.mLeft = panel_rect.mRight + mDragHandleShift;
+ resize_bar_rect.mRight = resize_bar_rect.mLeft + mDragHandleThickness;
+ }
+ else
+ {
+ resize_bar_rect.mLeft = panel_rect.mRight - mResizeBarOverlap;
+ resize_bar_rect.mRight = panel_rect.mRight + panel_spacing_round + mResizeBarOverlap;
+ }
+
+ if (show_drag_handle)
+ {
+ resize_bar_rect.mBottom += mDragHandleSecondIndent;
+ resize_bar_rect.mTop -= mDragHandleFirstIndent;
+ }
+
}
else //VERTICAL
{
- resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap;
- resize_bar_rect.mBottom = panel_rect.mBottom - (S32)(llround(panel_spacing)) - mResizeBarOverlap;
-
cur_pos -= panel_visible_dim + panel_spacing;
+
+ if (show_drag_handle && panel_spacing_round > mDragHandleThickness)
+ {
+ resize_bar_rect.mTop = panel_rect.mBottom - mDragHandleShift;
+ resize_bar_rect.mBottom = resize_bar_rect.mTop - mDragHandleThickness;
+ }
+ else
+ {
+ resize_bar_rect.mTop = panel_rect.mBottom + mResizeBarOverlap;
+ resize_bar_rect.mBottom = panel_rect.mBottom - panel_spacing_round - mResizeBarOverlap;
+ }
+
+ if (show_drag_handle)
+ {
+ resize_bar_rect.mLeft += mDragHandleFirstIndent;
+ resize_bar_rect.mRight -= mDragHandleSecondIndent;
+ }
}
+
+ panelp->setIgnoreReshape(true);
+ panelp->setShape(panel_rect);
+ panelp->setIgnoreReshape(false);
panelp->mResizeBar->setShape(resize_bar_rect);
}
@@ -475,14 +541,13 @@ void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp)
{
if (lp->mResizeBar == NULL)
{
- LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
-
LLResizeBar::Params resize_params;
resize_params.name("resize");
resize_params.resizing_view(lp);
resize_params.min_size(lp->getRelevantMinDim());
- resize_params.side(side);
+ resize_params.side((mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM);
resize_params.snapping_enabled(false);
+ resize_params.show_drag_handle(mShowDragHandle);
LLResizeBar* resize_bar = LLUICtrlFactory::create<LLResizeBar>(resize_params);
lp->mResizeBar = resize_bar;
LLView::addChild(resize_bar, 0);
@@ -864,3 +929,4 @@ void LLLayoutStack::updateResizeBarLimits()
previous_visible_panelp = visible_panelp;
}
}
+
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 02c664f1a0..b570974bd6 100755
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -62,6 +62,11 @@ public:
Optional<F32> open_time_constant,
close_time_constant;
Optional<S32> resize_bar_overlap;
+ Optional<bool> show_drag_handle;
+ Optional<S32> drag_handle_first_indent;
+ Optional<S32> drag_handle_second_indent;
+ Optional<S32> drag_handle_thickness;
+ Optional<S32> drag_handle_shift;
Params();
};
@@ -126,6 +131,11 @@ private:
F32 mCloseTimeConstant;
bool mNeedsLayout;
S32 mResizeBarOverlap;
+ bool mShowDragHandle;
+ S32 mDragHandleFirstIndent;
+ S32 mDragHandleSecondIndent;
+ S32 mDragHandleThickness;
+ S32 mDragHandleShift;
}; // end class LLLayoutStack
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index f7bf39c897..f854e1785d 100755
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -3146,6 +3146,13 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
const S32 CURSOR_HEIGHT = 22; // Approximate "normal" cursor size
const S32 CURSOR_WIDTH = 12;
+ if (menu->getChildList()->empty())
+ {
+ return;
+ }
+
+ menu->setVisible( TRUE );
+
//Do not show menu if all menu items are disabled
BOOL item_enabled = false;
for (LLView::child_list_t::const_iterator itor = menu->getChildList()->begin();
@@ -3156,8 +3163,9 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
item_enabled = item_enabled || menu_item->getEnabled();
}
- if(menu->getChildList()->empty() || !item_enabled)
+ if(!item_enabled)
{
+ menu->setVisible( FALSE );
return;
}
@@ -3173,8 +3181,6 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)
menu->mFirstVisibleItem = NULL;
}
- menu->setVisible( TRUE );
-
// Fix menu rect if needed.
menu->needsArrange();
menu->arrangeAndClear();
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 743d34c57b..26ede21572 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/llresizebar.cpp b/indra/llui/llresizebar.cpp
index 15e56cbfe5..e67b22c977 100755
--- a/indra/llui/llresizebar.cpp
+++ b/indra/llui/llresizebar.cpp
@@ -28,14 +28,53 @@
#include "llresizebar.h"
+#include "lllocalcliprect.h"
#include "llmath.h"
#include "llui.h"
#include "llmenugl.h"
#include "llfocusmgr.h"
#include "llwindow.h"
+class LLImagePanel : public LLPanel
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
+ {
+ Optional<bool> horizontal;
+ Params() : horizontal("horizontal", false) {}
+ };
+ LLImagePanel(const Params& p) : LLPanel(p), mHorizontal(p.horizontal) {}
+ virtual ~LLImagePanel() {}
+
+ void draw()
+ {
+ const LLRect& parent_rect = getParent()->getRect();
+ const LLRect& rect = getRect();
+ LLRect clip_rect( -rect.mLeft, parent_rect.getHeight() - rect.mBottom - 2
+ , parent_rect.getWidth() - rect.mLeft - (mHorizontal ? 2 : 0), -rect.mBottom);
+ LLLocalClipRect clip(clip_rect);
+ LLPanel::draw();
+ }
+
+private:
+ bool mHorizontal;
+};
+
+static LLDefaultChildRegistry::Register<LLImagePanel> t1("resize_bar_image_panel");
+
+LLResizeBar::Params::Params()
+: max_size("max_size", S32_MAX),
+ snapping_enabled("snapping_enabled", true),
+ resizing_view("resizing_view"),
+ side("side"),
+ allow_double_click_snapping("allow_double_click_snapping", true),
+ show_drag_handle("show_drag_handle", false)
+{
+ name = "resize_bar";
+}
+
LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)
-: LLView(p),
+: LLPanel(p),
mDragLastScreenX( 0 ),
mDragLastScreenY( 0 ),
mLastMouseScreenX( 0 ),
@@ -46,7 +85,9 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)
mSnappingEnabled(p.snapping_enabled),
mAllowDoubleClickSnapping(p.allow_double_click_snapping),
mResizingView(p.resizing_view),
- mResizeListener(NULL)
+ mResizeListener(NULL),
+ mShowDragHandle(p.show_drag_handle),
+ mImagePanel(NULL)
{
setFollowsNone();
// set up some generically good follow code.
@@ -75,8 +116,37 @@ LLResizeBar::LLResizeBar(const LLResizeBar::Params& p)
default:
break;
}
+
+ if (mShowDragHandle)
+ {
+ LLViewBorder::Params border_params;
+ border_params.border_thickness = 1;
+ border_params.highlight_light_color = LLUIColorTable::instance().getColor("ResizebarBorderLight");
+ border_params.shadow_dark_color = LLUIColorTable::instance().getColor("ResizebarBorderDark");
+
+ addBorder(border_params);
+ setBorderVisible(TRUE);
+
+ LLImagePanel::Params image_panel;
+ mDragHandleImage = LLUI::getUIImage(LLResizeBar::RIGHT == mSide ? "Vertical Drag Handle" : "Horizontal Drag Handle");
+ image_panel.bg_alpha_image = mDragHandleImage;
+ image_panel.background_visible = true;
+ image_panel.horizontal = (LLResizeBar::BOTTOM == mSide);
+ mImagePanel = LLUICtrlFactory::create<LLImagePanel>(image_panel);
+ setImagePanel(mImagePanel);
+ }
}
+BOOL LLResizeBar::postBuild()
+{
+ if (mShowDragHandle)
+ {
+ setBackgroundVisible(TRUE);
+ setTransparentColor(LLUIColorTable::instance().getColor("ResizebarBody"));
+ }
+
+ return LLPanel::postBuild();
+}
BOOL LLResizeBar::handleMouseDown(S32 x, S32 y, MASK mask)
{
@@ -342,3 +412,39 @@ BOOL LLResizeBar::handleDoubleClick(S32 x, S32 y, MASK mask)
return TRUE;
}
+void LLResizeBar::setImagePanel(LLPanel * panelp)
+{
+ const LLView::child_list_t * children = getChildList();
+ if (getChildCount() == 2)
+ {
+ LLPanel * image_panelp = dynamic_cast<LLPanel*>(children->back());
+ if (image_panelp)
+ {
+ removeChild(image_panelp);
+ delete image_panelp;
+ }
+ }
+
+ addChild(panelp);
+ sendChildToBack(panelp);
+}
+
+LLPanel * LLResizeBar::getImagePanel() const
+{
+ return getChildCount() > 0 ? (LLPanel *)getChildList()->back() : NULL;
+}
+
+void LLResizeBar::draw()
+{
+ if (mShowDragHandle)
+ {
+ S32 image_width = mDragHandleImage->getTextureWidth();
+ S32 image_height = mDragHandleImage->getTextureHeight();
+ const LLRect& panel_rect = getRect();
+ S32 image_left = (panel_rect.getWidth() - image_width) / 2 - 1;
+ S32 image_bottom = (panel_rect.getHeight() - image_height) / 2;
+ mImagePanel->setRect(LLRect(image_left, image_bottom + image_height, image_left + image_width, image_bottom));
+ }
+
+ LLPanel::draw();
+}
diff --git a/indra/llui/llresizebar.h b/indra/llui/llresizebar.h
index 8190a95a71..bcf8ea0b40 100755
--- a/indra/llui/llresizebar.h
+++ b/indra/llui/llresizebar.h
@@ -27,15 +27,14 @@
#ifndef LL_RESIZEBAR_H
#define LL_RESIZEBAR_H
-#include "llview.h"
-#include "llcoord.h"
+#include "llpanel.h"
-class LLResizeBar : public LLView
+class LLResizeBar : public LLPanel
{
public:
enum Side { LEFT, TOP, RIGHT, BOTTOM };
- struct Params : public LLInitParam::Block<Params, LLView::Params>
+ struct Params : public LLInitParam::Block<Params, LLPanel::Params>
{
Mandatory<LLView*> resizing_view;
Mandatory<Side> side;
@@ -44,24 +43,19 @@ public:
Optional<S32> max_size;
Optional<bool> snapping_enabled;
Optional<bool> allow_double_click_snapping;
+ Optional<bool> show_drag_handle;
- Params()
- : max_size("max_size", S32_MAX),
- snapping_enabled("snapping_enabled", true),
- resizing_view("resizing_view"),
- side("side"),
- allow_double_click_snapping("allow_double_click_snapping", true)
- {
- name = "resize_bar";
- }
+ Params();
};
protected:
LLResizeBar(const LLResizeBar::Params& p);
friend class LLUICtrlFactory;
+
+ /*virtual*/ BOOL postBuild();
public:
-// virtual void draw(); No appearance
+ virtual void draw();
virtual BOOL handleHover(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask);
virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask);
@@ -72,20 +66,26 @@ public:
void setAllowDoubleClickSnapping(BOOL allow) { mAllowDoubleClickSnapping = allow; }
bool canResize() { return getEnabled() && mMaxSize > mMinSize; }
void setResizeListener(boost::function<void(void*)> listener) {mResizeListener = listener;}
+ BOOL isShowDragHandle() const { return mShowDragHandle; }
+ void setImagePanel(LLPanel * panelp);
+ LLPanel * getImagePanel() const;
private:
- S32 mDragLastScreenX;
- S32 mDragLastScreenY;
- S32 mLastMouseScreenX;
- S32 mLastMouseScreenY;
- LLCoordGL mLastMouseDir;
- S32 mMinSize;
- S32 mMaxSize;
- const Side mSide;
- BOOL mSnappingEnabled;
- BOOL mAllowDoubleClickSnapping;
- LLView* mResizingView;
- boost::function<void(void*)> mResizeListener;
+ S32 mDragLastScreenX;
+ S32 mDragLastScreenY;
+ S32 mLastMouseScreenX;
+ S32 mLastMouseScreenY;
+ LLCoordGL mLastMouseDir;
+ S32 mMinSize;
+ S32 mMaxSize;
+ const Side mSide;
+ BOOL mSnappingEnabled;
+ BOOL mAllowDoubleClickSnapping;
+ BOOL mShowDragHandle;
+ LLView* mResizingView;
+ boost::function<void(void*)> mResizeListener;
+ LLPointer<LLUIImage> mDragHandleImage;
+ LLPanel * mImagePanel;
};
#endif // LL_RESIZEBAR_H
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 a45c4ced2e..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),
@@ -653,6 +654,10 @@ void LLTextBase::drawText()
mSpellCheckEnd = end;
}
}
+ else
+ {
+ mMisspellRanges.clear();
+ }
LLTextSegmentPtr cur_segment = *seg_iter;
@@ -1850,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(); }
@@ -1866,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(); }
@@ -1916,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));
@@ -1927,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);
@@ -2096,7 +2137,7 @@ void LLTextBase::resetLabel()
}
}
-bool LLTextBase::useLabel()
+bool LLTextBase::useLabel() const
{
return !getLength() && !mLabel.empty() && !hasFocus();
}
@@ -2602,21 +2643,18 @@ void LLTextBase::setCursorAtLocalPos( S32 local_x, S32 local_y, bool round, bool
void LLTextBase::changeLine( S32 delta )
{
S32 line = getLineNumFromDocIndex(mCursorPos);
+ S32 max_line_nb = getLineCount() - 1;
+ max_line_nb = (max_line_nb < 0 ? 0 : max_line_nb);
+
+ S32 new_line = llclamp(line + delta, 0, max_line_nb);
- S32 new_line = line;
- if( (delta < 0) && (line > 0 ) )
- {
- new_line = line - 1;
- }
- else if( (delta > 0) && (line < (getLineCount() - 1)) )
- {
- new_line = line + 1;
- }
-
- LLRect visible_region = getVisibleDocumentRect();
-
- S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel, mLineInfoList[new_line].mRect.mBottom + mVisibleTextRect.mBottom - visible_region.mBottom, TRUE);
- setCursorPos(new_cursor_pos, true);
+ if (new_line != line)
+ {
+ LLRect visible_region = getVisibleDocumentRect();
+ S32 new_cursor_pos = getDocIndexFromLocalCoord(mDesiredXPixel,
+ mLineInfoList[new_line].mRect.mBottom + mVisibleTextRect.mBottom - visible_region.mBottom, TRUE);
+ setCursorPos(new_cursor_pos, true);
+ }
}
bool LLTextBase::scrolledToStart()
@@ -2910,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
//
@@ -3203,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)
{
@@ -3211,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 43c0090993..30f5526500 100755
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -159,9 +159,8 @@ LLWinImm LLWinImm::sTheInstance;
LLWinImm::LLWinImm() : mHImmDll(NULL)
{
// Check system metrics
- if ( !GetSystemMetrics( SM_DBCSENABLED ) )
+ if ( !GetSystemMetrics( SM_IMMENABLED ) )
return;
-
mHImmDll = LoadLibraryA("Imm32");
if (mHImmDll != NULL)
@@ -3500,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 89add3e21f..e2ae7a5a9a 100755
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -229,6 +229,7 @@ set(viewer_SOURCE_FILES
llfloaterfonttest.cpp
llfloatergesture.cpp
llfloatergodtools.cpp
+ llfloatergotoline.cpp
llfloatergroupinvite.cpp
llfloatergroups.cpp
llfloaterhandler.cpp
@@ -812,6 +813,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 a6e93edc79..789a07fbe2 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>
@@ -378,7 +391,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>
@@ -389,7 +403,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 284bc85798..0b5c4d962f 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>
@@ -3489,16 +3566,27 @@
<key>Value</key>
<real>10.0</real>
</map>
- <key>FilterItemsPerFrame</key>
+ <key>FilterItemsMaxTimePerFrameVisible</key>
<map>
- <key>Comment</key>
- <string>Maximum number of inventory items to match against search filter every frame (lower to increase framerate while searching, higher to improve search speed)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <integer>500</integer>
+ <key>Comment</key>
+ <string>Max time devoted to items filtering per frame for visible inventory listings (in milliseconds)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>10</integer>
+ </map>
+ <key>FilterItemsMaxTimePerFrameUnvisible</key>
+ <map>
+ <key>Comment</key>
+ <string>Max time devoted to items filtering per frame for non visible inventory listings (in milliseconds)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>S32</string>
+ <key>Value</key>
+ <integer>1</integer>
</map>
<key>FindLandArea</key>
<map>
@@ -5227,6 +5315,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>
@@ -6404,6 +6514,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>
@@ -6440,7 +6561,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>
@@ -6451,7 +6575,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>
@@ -6462,7 +6589,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>
@@ -6473,7 +6603,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>
@@ -6484,7 +6617,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>
@@ -6997,6 +7147,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>
@@ -7030,6 +7191,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>
@@ -9664,6 +9891,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>
@@ -12891,12 +13129,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 3e94c5edf7..f4ce3c9118 100755
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -46,6 +46,7 @@
#include "llenvmanager.h"
#include "llfirstuse.h"
#include "llfloatercamera.h"
+#include "llfloaterimcontainer.h"
#include "llfloaterreg.h"
#include "llfloatertools.h"
#include "llgroupactions.h"
@@ -91,6 +92,7 @@
#include "llworld.h"
#include "llworldmap.h"
#include "stringize.h"
+#include "boost/foreach.hpp"
using namespace LLAvatarAppearanceDefines;
@@ -433,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.
@@ -2037,7 +2039,16 @@ void LLAgent::endAnimationUpdateUI()
{
skip_list.insert(LLFloaterReg::findInstance("mini_map"));
}
-
+
+ LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
+ LLFloaterIMContainer::floater_list_t conversations;
+ im_box->getDetachedConversationFloaters(conversations);
+ BOOST_FOREACH(LLFloater* conversation, conversations)
+ {
+ llinfos << "skip_list.insert(session_floater): " << conversation->getTitle() << llendl;
+ skip_list.insert(conversation);
+ }
+
gFloaterView->popVisibleAll(skip_list);
#endif
mViewsPushed = FALSE;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index d22376c3b2..338558c937 100755
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -672,7 +672,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),
@@ -2312,17 +2311,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)
@@ -2379,9 +2385,7 @@ bool LLAppViewer::initConfiguration()
{
c->setValue(true, false);
}
-#endif
-#ifndef LL_RELEASE_FOR_DOWNLOAD
gSavedSettings.setBOOL("QAMode", TRUE );
gSavedSettings.setS32("WatchdogEnabled", 0);
#endif
@@ -2417,13 +2421,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;
}
@@ -2470,12 +2468,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();
@@ -2552,91 +2554,52 @@ bool LLAppViewer::initConfiguration()
LLViewerEventRecorder::instance().setEventLoggingOn();
}
- if(clp.hasOption("channel"))
- {
- LLVersionInfo::resetChannel(clp.getOption("channel")[0]);
+ std::string CmdLineChannel(gSavedSettings.getString("CmdLineChannel"));
+ if(! CmdLineChannel.empty())
+ {
+ 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"))
- {
- 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];
+
+ std::string test_name(gSavedSettings.getString("LogMetrics"));
+ if (! test_name.empty())
+ {
+ LLFastTimer::sMetricLog = TRUE ;
+ // '--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;
- }
+ LLFastTimer::sLogName = test_name;
}
if (clp.hasOption("graphicslevel"))
{
- const LLCommandLineParser::token_vector_t& value = clp.getOption("graphicslevel");
- if(value.size() != 1)
- {
- 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;
- }
- }
- }
-
- if (clp.hasOption("analyzeperformance"))
- {
- LLFastTimerView::sAnalyzePerformance = TRUE;
+ // 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))
+ {
+ // 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("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;
@@ -2661,20 +2624,16 @@ 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
- if(clp.hasOption("url"))
- {
- LLStartUp::setStartSLURL(LLSLURL(clp.getOption("url")[0]));
- if(LLStartUp::getStartSLURL().getType() == LLSLURL::LOCATION)
- {
- LLGridManager::getInstance()->setGridChoice(LLStartUp::getStartSLURL().getGrid());
-
- }
- }
- else if(clp.hasOption("slurl"))
- {
- LLSLURL start_slurl(clp.getOption("slurl")[0]);
+ std::string CmdLineLoginLocation(gSavedSettings.getString("CmdLineLoginLocation"));
+ if(! CmdLineLoginLocation.empty())
+ {
+ LLSLURL start_slurl(CmdLineLoginLocation);
LLStartUp::setStartSLURL(start_slurl);
- }
+ if(start_slurl.getType() == LLSLURL::LOCATION)
+ {
+ LLGridManager::getInstance()->setGridChoice(start_slurl.getGrid());
+ }
+ }
const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent");
if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString())
@@ -2817,9 +2776,8 @@ bool LLAppViewer::initConfiguration()
LL_DEBUGS("AppInit")<<"set start from NextLoginLocation: "<<nextLoginLocation<<LL_ENDL;
LLStartUp::setStartSLURL(LLSLURL(nextLoginLocation));
}
- else if ( ( clp.hasOption("login") || clp.hasOption("autologin"))
- && !clp.hasOption("url")
- && !clp.hasOption("slurl"))
+ else if ((clp.hasOption("login") || clp.hasOption("autologin"))
+ && gSavedSettings.getString("CmdLineLoginLocation").empty())
{
// If automatic login from command line with --login switch
// init StartSLURL location.
@@ -3055,13 +3013,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;
@@ -3086,9 +3050,7 @@ void LLAppViewer::initUpdater()
}
mUpdater->setAppExitCallback(boost::bind(&LLAppViewer::forceQuit, this));
- mUpdater->initialize(url,
- service_path,
- channel,
+ mUpdater->initialize(channel,
version,
gPlatform,
getOSInfo().getOSVersionString(),
@@ -3193,11 +3155,12 @@ 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
gSavedSettings.setBOOL("RenderInitError", TRUE);
gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE );
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 b0aaa21ec9..affa24f78c 100755
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -364,7 +364,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"));
@@ -387,6 +390,10 @@ void LLConversationItemSession::buildContextMenu(LLMenuGL& menu, U32 flags)
addVoiceOptions(items);
items.push_back(std::string("chat_history"));
}
+ else if(this->getType() == CONV_SESSION_NEARBY)
+ {
+ items.push_back(std::string("chat_history"));
+ }
hide_context_entries(menu, items, disabled_items);
}
diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h
index 8766585049..d8cdcdfc97 100755
--- a/indra/newview/llconversationmodel.h
+++ b/indra/newview/llconversationmodel.h
@@ -252,11 +252,10 @@ public:
const std::string& getName() const { return mEmpty; }
const std::string& getFilterText() { return mEmpty; }
void setModified(EFilterModified behavior = FILTER_RESTART) { }
-
- void setFilterCount(S32 count) { }
- S32 getFilterCount() const { return 0; }
- void decrementFilterCount() { }
-
+
+ void resetTime(S32 timeout) { }
+ bool isTimedOut() { return false; }
+
bool isDefault() const { return true; }
bool isNotDefault() const { return false; }
void markDefault() { }
diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp
index b6c53e5e30..9faa12b2ee 100755
--- a/indra/newview/llconversationview.cpp
+++ b/indra/newview/llconversationview.cpp
@@ -118,9 +118,19 @@ void LLConversationViewSession::setFlashState(bool flash_state)
mFlashTimer->stopFlashing();
}
+void LLConversationViewSession::setHighlightState(bool hihglight_state)
+{
+ mFlashStateOn = hihglight_state;
+ mFlashStarted = true;
+ mFlashTimer->stopFlashing();
+}
+
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();
@@ -263,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);
@@ -340,16 +373,20 @@ void LLConversationViewSession::setVisibleIfDetached(BOOL visible)
{
// Do this only if the conversation floater has been torn off (i.e. no multi floater host) and is not minimized
// Note: minimized dockable floaters are brought to front hence unminimized when made visible and we don't want that here
- LLFolderViewModelItem* item = mViewModelItem;
- LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID();
- LLFloater* session_floater = LLFloaterIMSessionTab::getConversation(session_uuid);
-
- if (session_floater && !session_floater->getHost() && !session_floater->isMinimized())
+ LLFloater* session_floater = getSessionFloater();
+ if (session_floater && session_floater->isDetachedAndNotMinimized())
{
session_floater->setVisible(visible);
}
}
+LLFloater* LLConversationViewSession::getSessionFloater()
+{
+ LLFolderViewModelItem* item = mViewModelItem;
+ LLUUID session_uuid = dynamic_cast<LLConversationItem*>(item)->getUUID();
+ return LLFloaterIMSessionTab::getConversation(session_uuid);
+}
+
LLConversationViewParticipant* LLConversationViewSession::findParticipant(const LLUUID& participant_id)
{
// This is *not* a general tree parsing algorithm. We search only in the mItems list
diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h
index 3eb2e63792..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);
@@ -86,6 +87,9 @@ public:
virtual void refresh();
/*virtual*/ void setFlashState(bool flash_state);
+ void setHighlightState(bool hihglight_state);
+
+ LLFloater* getSessionFloater();
private:
diff --git a/indra/newview/lldonotdisturbnotificationstorage.cpp b/indra/newview/lldonotdisturbnotificationstorage.cpp
index 82affcf068..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));
}
@@ -115,7 +116,8 @@ void LLDoNotDisturbNotificationStorage::saveNotifications()
{
LLNotificationPtr notificationPtr = historyIter->second;
- if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() && !notificationPtr->isExpired())
+ if (!notificationPtr->isRespondedTo() && !notificationPtr->isCancelled() &&
+ !notificationPtr->isExpired() && !notificationPtr->isPersistent())
{
data.append(notificationPtr->asLLSD(true));
}
@@ -210,12 +212,8 @@ void LLDoNotDisturbNotificationStorage::loadNotifications()
}
- if(imToastExists)
- {
- LLFloaterReg::showInstance("im_container");
- }
-
- if(group_ad_hoc_toast_exists)
+ bool isConversationLoggingAllowed = gSavedPerAccountSettings.getS32("KeepConversationLogTranscripts") > 0;
+ if(group_ad_hoc_toast_exists && isConversationLoggingAllowed)
{
LLFloaterReg::showInstance("conversation");
}
@@ -266,11 +264,6 @@ void LLDoNotDisturbNotificationStorage::updateNotifications()
}
}
- if(imToastExists)
- {
- LLFloaterReg::showInstance("im_container");
- }
-
if(imToastExists || offerExists)
{
make_ui_sound("UISndNewIncomingIMSession");
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 1fbe1be11a..d6b4909318 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"
@@ -54,6 +55,7 @@
#include "llworld.h"
#include "llsdserialize.h"
#include "llviewerobjectlist.h"
+#include "boost/foreach.hpp"
//
// LLFloaterIMContainer
@@ -63,7 +65,8 @@ LLFloaterIMContainer::LLFloaterIMContainer(const LLSD& seed, const Params& param
mExpandCollapseBtn(NULL),
mConversationsRoot(NULL),
mConversationsEventStream("ConversationsEvents"),
- mInitialized(false)
+ mInitialized(false),
+ mIsFirstLaunch(true)
{
mEnableCallbackRegistrar.add("IMFloaterContainer.Check", boost::bind(&LLFloaterIMContainer::isActionChecked, this, _2));
mCommitCallbackRegistrar.add("IMFloaterContainer.Action", boost::bind(&LLFloaterIMContainer::onCustomAction, this, _2));
@@ -113,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);
}
@@ -204,6 +211,7 @@ BOOL LLFloaterIMContainer::postBuild()
// a scroller for folder view
LLRect scroller_view_rect = mConversationsListPanel->getRect();
scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
+ scroller_view_rect.mBottom += getChild<LLLayoutStack>("conversations_pane_buttons_stack")->getRect().getHeight();
LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>());
scroller_params.rect(scroller_view_rect);
@@ -221,7 +229,8 @@ BOOL LLFloaterIMContainer::postBuild()
mExpandCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onExpandCollapseButtonClicked, this));
mStubCollapseBtn = getChild<LLButton>("stub_collapse_btn");
mStubCollapseBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onStubCollapseButtonClicked, this));
- getChild<LLButton>("speak_btn")->setClickedCallback(boost::bind(&LLFloaterIMContainer::onSpeakButtonClicked, this));
+ mSpeakBtn = getChild<LLButton>("speak_btn");
+ mSpeakBtn->setClickedCallback(boost::bind(&LLFloaterIMContainer::onSpeakButtonClicked, this));
childSetAction("add_btn", boost::bind(&LLFloaterIMContainer::onAddButtonClicked, this));
@@ -258,7 +267,6 @@ BOOL LLFloaterIMContainer::postBuild()
void LLFloaterIMContainer::onOpen(const LLSD& key)
{
LLMultiFloater::onOpen(key);
- openNearbyChat();
reSelectConversation();
assignResizeLimits();
}
@@ -593,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())
@@ -621,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);
@@ -651,7 +659,11 @@ void LLFloaterIMContainer::setVisible(BOOL visible)
LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(widget_it->second);
if (widget)
{
- widget->setVisibleIfDetached(visible);
+ LLFloater* session_floater = widget->getSessionFloater();
+ if (session_floater != nearby_chat)
+ {
+ widget->setVisibleIfDetached(visible);
+ }
}
}
@@ -659,10 +671,37 @@ void LLFloaterIMContainer::setVisible(BOOL visible)
LLMultiFloater::setVisible(visible);
}
+void LLFloaterIMContainer::getDetachedConversationFloaters(floater_list_t& floaters)
+{
+ typedef conversations_widgets_map::value_type conv_pair;
+ BOOST_FOREACH(conv_pair item, mConversationsWidgets)
+ {
+ LLConversationViewSession* widget = dynamic_cast<LLConversationViewSession*>(item.second);
+ if (widget)
+ {
+ LLFloater* session_floater = widget->getSessionFloater();
+ if (session_floater && session_floater->isDetachedAndNotMinimized())
+ {
+ floaters.push_back(session_floater);
+ }
+ }
+ }
+}
+
void LLFloaterIMContainer::setVisibleAndFrontmost(BOOL take_focus, const LLSD& key)
{
LLMultiFloater::setVisibleAndFrontmost(take_focus, key);
- selectConversationPair(getSelectedSession(), false, take_focus);
+ // 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()
@@ -779,13 +818,6 @@ void LLFloaterIMContainer::reshapeFloaterAndSetResizeLimits(bool collapse, S32 d
setCanMinimize(at_least_one_panel_is_expanded);
assignResizeLimits();
-
- // force set correct size for the title after show/hide minimize button
- LLRect cur_rect = getRect();
- LLRect force_rect = cur_rect;
- force_rect.mRight = cur_rect.mRight + 1;
- setRect(force_rect);
- setRect(cur_rect);
}
void LLFloaterIMContainer::assignResizeLimits()
@@ -793,15 +825,12 @@ void LLFloaterIMContainer::assignResizeLimits()
bool is_conv_pane_expanded = !mConversationsPane->isCollapsed();
bool is_msg_pane_expanded = !mMessagesPane->isCollapsed();
- // With two panels visible number of borders is three, because the borders
- // between the panels are merged into one
- S32 number_of_visible_borders = llmin((is_conv_pane_expanded? 2 : 0) + (is_msg_pane_expanded? 2 : 0), 3);
- S32 summary_width_of_visible_borders = number_of_visible_borders * LLPANEL_BORDER_WIDTH;
- S32 conv_pane_target_width = is_conv_pane_expanded?
- (is_msg_pane_expanded?
- mConversationsPane->getRect().getWidth()
- : mConversationsPane->getExpandedMinDim())
- : mConversationsPane->getMinDim();
+ S32 summary_width_of_visible_borders = (is_msg_pane_expanded ? mConversationsStack->getPanelSpacing() : 0) + 1;
+
+ S32 conv_pane_target_width = is_conv_pane_expanded
+ ? ( is_msg_pane_expanded?mConversationsPane->getRect().getWidth():mConversationsPane->getExpandedMinDim() )
+ : 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;
@@ -961,11 +990,11 @@ void LLFloaterIMContainer::setSortOrder(const LLConversationSort& order)
conversation_floater->setSortOrder(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();
@@ -978,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();
@@ -1137,6 +1166,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());
@@ -1147,7 +1181,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());
}
@@ -1160,6 +1194,17 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,
}
}
}
+ //if there is no LLFloaterIMSession* instance for selected conversation it might be Nearby chat
+ else
+ {
+ if(conversationItem->getType() == LLConversationItem::CONV_SESSION_NEARBY)
+ {
+ if("chat_history" == command)
+ {
+ LLFloaterReg::showInstance("preview_conversation", LLSD(LLUUID::null), true);
+ }
+ }
+ }
}
void LLFloaterIMContainer::doToSelected(const LLSD& userdata)
@@ -1189,7 +1234,7 @@ void LLFloaterIMContainer::doToSelectedGroup(const LLSD& userdata)
if (action == "group_profile")
{
- LLGroupActions::show(mSelectedSession);
+ LLGroupActions::show(mSelectedSession);
}
else if (action == "activate_group")
{
@@ -1215,7 +1260,19 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata)
//Enable Chat history item for ad-hoc and group conversations
if ("can_chat_history" == item && uuids.size() > 0)
{
- return LLLogChat::isTranscriptExist(uuids.front());
+ //Disable menu item if selected participant is user agent
+ if(uuids.front() != gAgentID)
+ {
+ if (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_NEARBY)
+ {
+ return LLLogChat::isNearbyTranscriptExist();
+ }
+ else
+ {
+ bool is_group = (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP);
+ return LLLogChat::isTranscriptExist(uuids.front(),is_group);
+ }
+ }
}
// If nothing is selected(and selected item is not group chat), everything needs to be disabled
@@ -1890,13 +1947,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);
@@ -1908,7 +1958,6 @@ void LLFloaterIMContainer::reSelectConversation()
void LLFloaterIMContainer::updateSpeakBtnState()
{
- LLButton* mSpeakBtn = getChild<LLButton>("speak_btn");
mSpeakBtn->setToggleState(LLVoiceClient::getInstance()->getUserPTTState());
mSpeakBtn->setEnabled(LLAgent::isActionAllowed("speak"));
}
@@ -1929,6 +1978,17 @@ void LLFloaterIMContainer::flashConversationItemWidget(const LLUUID& session_id,
}
}
+void LLFloaterIMContainer::highlightConversationItemWidget(const LLUUID& session_id, bool is_highlighted)
+{
+ //Finds the conversation line item to highlight using the session_id
+ LLConversationViewSession * widget = dynamic_cast<LLConversationViewSession *>(get_ptr_in_map(mConversationsWidgets,session_id));
+
+ if (widget)
+ {
+ widget->setHighlightState(is_highlighted);
+ }
+}
+
bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conversation_item_widget)
{
llassert(conversation_item_widget != NULL);
@@ -1944,23 +2004,28 @@ bool LLFloaterIMContainer::isScrolledOutOfSight(LLConversationViewSession* conve
BOOL LLFloaterIMContainer::handleKeyHere(KEY key, MASK mask )
{
+ BOOL handled = FALSE;
+
if(mask == MASK_ALT)
{
if (KEY_RETURN == key )
{
expandConversation();
+ handled = TRUE;
}
if ((KEY_DOWN == key ) || (KEY_RIGHT == key))
{
selectNextorPreviousConversation(true);
+ handled = TRUE;
}
if ((KEY_UP == key) || (KEY_LEFT == key))
{
selectNextorPreviousConversation(false);
+ handled = TRUE;
}
}
- return TRUE;
+ return handled;
}
bool LLFloaterIMContainer::selectAdjacentConversation(bool focus_selected)
@@ -2017,7 +2082,22 @@ void LLFloaterIMContainer::expandConversation()
}
}
-void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)
+// 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()
{
// Always unminimize before trying to close.
// Most of the time the user will never see this state.
@@ -2026,7 +2106,80 @@ void LLFloaterIMContainer::closeFloater(bool app_quitting/* = false*/)
LLMultiFloater::setMinimized(FALSE);
}
- LLFloater::closeFloater(app_quitting);
+ 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*/)
+{
+ if(app_quitting)
+ {
+ closeAllConversations();
+ onClickCloseBtn();
+ }
+ else
+ {
+ // 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();
+ }
+ }
+ }
+}
+
+void LLFloaterIMContainer::handleReshape(const LLRect& rect, bool by_user)
+{
+ LLMultiFloater::handleReshape(rect, by_user);
+ storeRectControl();
}
// EOF
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index e39d20ec35..36da457cac 100755
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -63,6 +63,8 @@ public:
/*virtual*/ void setVisible(BOOL visible);
/*virtual*/ void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD());
/*virtual*/ void updateResizeLimits();
+ /*virtual*/ void handleReshape(const LLRect& rect, bool by_user);
+
void onCloseFloater(LLUUID& id);
/*virtual*/ void addFloater(LLFloater* floaterp,
@@ -105,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);
@@ -116,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;
@@ -130,6 +134,8 @@ private:
void onStubCollapseButtonClicked();
void processParticipantsStyleUpdate();
void onSpeakButtonClicked();
+ /*virtual*/ void onClickCloseBtn();
+ /*virtual*/ void closeHostedFloater();
void collapseConversationsPane(bool collapse, bool save_is_allowed=true);
@@ -144,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);
@@ -169,6 +175,7 @@ private:
LLButton* mExpandCollapseBtn;
LLButton* mStubCollapseBtn;
+ LLButton* mSpeakBtn;
LLPanel* mStubPanel;
LLTextBox* mStubTextBox;
LLLayoutPanel* mMessagesPane;
@@ -176,6 +183,7 @@ private:
LLLayoutStack* mConversationsStack;
bool mInitialized;
+ bool mIsFirstLaunch;
LLUUID mSelectedSession;
std::string mGeneralTitle;
@@ -190,9 +198,12 @@ public:
void updateSpeakBtnState();
static bool isConversationLoggingAllowed();
void flashConversationItemWidget(const LLUUID& session_id, bool is_flashes);
+ void highlightConversationItemWidget(const LLUUID& session_id, bool is_highlighted);
bool isScrolledOutOfSight(LLConversationViewSession* conversation_item_widget);
boost::signals2::connection mMicroChangedSignal;
S32 getConversationListItemSize() { return mConversationsWidgets.size(); }
+ typedef std::list<LLFloater*> floater_list_t;
+ void getDetachedConversationFloaters(floater_list_t& floaters);
private:
LLConversationViewSession* createConversationItemWidget(LLConversationItem* item);
diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp
index 56b0c15cb9..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);
}
@@ -568,7 +576,10 @@ void LLFloaterIMNearbyChat::sendChat( EChatType type )
if (0 == channel)
{
// discard returned "found" boolean
- LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text);
+ if(!LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text))
+ {
+ utf8_revised_text = utf8text;
+ }
}
else
{
@@ -582,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"));
}
}
@@ -636,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 8ec85e1160..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
@@ -442,8 +430,11 @@ void LLFloaterIMSession::addSessionParticipants(const uuid_vec_t& uuids)
}
else
{
- // remember whom we have invited, to notify others later, when the invited ones actually join
- mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end());
+ if(findInstance(mSessionID))
+ {
+ // remember whom we have invited, to notify others later, when the invited ones actually join
+ mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end());
+ }
inviteToSession(uuids);
}
@@ -469,13 +460,18 @@ void LLFloaterIMSession::addP2PSessionParticipants(const LLSD& notification, con
temp_ids.insert(temp_ids.end(), uuids.begin(), uuids.end());
// then we can close the current session
- onClose(false);
+ if(findInstance(mSessionID))
+ {
+ onClose(false);
+
+ // remember whom we have invited, to notify others later, when the invited ones actually join
+ mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end());
+ }
// we start a new session so reset the initialization flag
mSessionInitialized = false;
- // remember whom we have invited, to notify others later, when the invited ones actually join
- mInvitedParticipants.insert(mInvitedParticipants.end(), uuids.begin(), uuids.end());
+
// Start a new ad hoc voice call if we invite new participants to a P2P call,
// or start a text chat otherwise.
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index ce6e639305..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)
@@ -212,7 +211,7 @@ void LLFloaterIMSessionTab::assignResizeLimits()
mRightPartPanel->setIgnoreReshape(is_participants_pane_collapsed);
S32 participants_pane_target_width = is_participants_pane_collapsed?
- 0 : (mParticipantListPanel->getRect().getWidth() + LLPANEL_BORDER_WIDTH);
+ 0 : (mParticipantListPanel->getRect().getWidth() + mParticipantListAndHistoryStack->getPanelSpacing());
S32 new_min_width = participants_pane_target_width + mRightPartPanel->getExpandedMinDim() + mFloaterExtraWidth;
@@ -241,7 +240,10 @@ BOOL LLFloaterIMSessionTab::postBuild()
mTearOffBtn->setCommitCallback(boost::bind(&LLFloaterIMSessionTab::onTearOffClicked, this));
mGearBtn = getChild<LLButton>("gear_btn");
-
+ mAddBtn = getChild<LLButton>("add_btn");
+ mVoiceButton = getChild<LLButton>("voice_call_btn");
+ mTranslationCheckBox = getChild<LLUICtrl>("translate_chat_checkbox_lp");
+
mParticipantListPanel = getChild<LLLayoutPanel>("speakers_list_panel");
mRightPartPanel = getChild<LLLayoutPanel>("right_part_holder");
@@ -256,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);
@@ -270,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());
@@ -372,7 +373,7 @@ void LLFloaterIMSessionTab::draw()
void LLFloaterIMSessionTab::enableDisableCallBtn()
{
- getChildView("voice_call_btn")->setEnabled(
+ mVoiceButton->setEnabled(
mSessionID.notNull()
&& mSession
&& mSession->mSessionInitialized
@@ -399,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;
@@ -758,7 +769,7 @@ void LLFloaterIMSessionTab::reshapeChatLayoutPanel()
void LLFloaterIMSessionTab::showTranslationCheckbox(BOOL show)
{
- getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(mIsNearbyChat? show : FALSE);
+ mTranslationCheckBox->setVisible(mIsNearbyChat && show);
}
// static
@@ -805,15 +816,10 @@ void LLFloaterIMSessionTab::reloadEmptyFloaters()
void LLFloaterIMSessionTab::updateCallBtnState(bool callIsActive)
{
- LLButton* voiceButton = getChild<LLButton>("voice_call_btn");
- voiceButton->setImageOverlay(
- callIsActive? getString("call_btn_stop") : getString("call_btn_start"));
-
- voiceButton->setToolTip(
- callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip"));
+ mVoiceButton->setImageOverlay(callIsActive? getString("call_btn_stop") : getString("call_btn_start"));
+ mVoiceButton->setToolTip(callIsActive? getString("end_call_button_tooltip") : getString("start_call_button_tooltip"));
enableDisableCallBtn();
-
}
void LLFloaterIMSessionTab::onSlide(LLFloaterIMSessionTab* self)
@@ -898,6 +904,7 @@ void LLFloaterIMSessionTab::restoreFloater()
mExpandCollapseLineBtn->setImageOverlay(getString("expandline_icon"));
setMessagePaneExpanded(true);
saveCollapsedState();
+ mInputEditor->enableSingleLineMode(false);
enableResizeCtrls(true, true, true);
}
}
@@ -953,8 +960,8 @@ void LLFloaterIMSessionTab::updateGearBtn()
if(prevVisibility != mGearBtn->getVisible())
{
LLRect gear_btn_rect = mGearBtn->getRect();
- LLRect add_btn_rect = getChild<LLButton>("add_btn")->getRect();
- LLRect call_btn_rect = getChild<LLButton>("voice_call_btn")->getRect();
+ LLRect add_btn_rect = mAddBtn->getRect();
+ LLRect call_btn_rect = mVoiceButton->getRect();
S32 gap_width = call_btn_rect.mLeft - add_btn_rect.mRight;
S32 right_shift = gear_btn_rect.getWidth() + gap_width;
if(mGearBtn->getVisible())
@@ -968,24 +975,24 @@ void LLFloaterIMSessionTab::updateGearBtn()
add_btn_rect.translate(-right_shift,0);
call_btn_rect.translate(-right_shift,0);
}
- getChild<LLButton>("add_btn")->setRect(add_btn_rect);
- getChild<LLButton>("voice_call_btn")->setRect(call_btn_rect);
+ mAddBtn->setRect(add_btn_rect);
+ mVoiceButton->setRect(call_btn_rect);
}
}
void LLFloaterIMSessionTab::initBtns()
{
LLRect gear_btn_rect = mGearBtn->getRect();
- LLRect add_btn_rect = getChild<LLButton>("add_btn")->getRect();
- LLRect call_btn_rect = getChild<LLButton>("voice_call_btn")->getRect();
+ LLRect add_btn_rect = mAddBtn->getRect();
+ LLRect call_btn_rect = mVoiceButton->getRect();
S32 gap_width = call_btn_rect.mLeft - add_btn_rect.mRight;
S32 right_shift = gear_btn_rect.getWidth() + gap_width;
add_btn_rect.translate(-right_shift,0);
call_btn_rect.translate(-right_shift,0);
- getChild<LLButton>("add_btn")->setRect(add_btn_rect);
- getChild<LLButton>("voice_call_btn")->setRect(call_btn_rect);
+ mAddBtn->setRect(add_btn_rect);
+ mVoiceButton->setRect(call_btn_rect);
}
// static
@@ -1083,21 +1090,26 @@ void LLFloaterIMSessionTab::saveCollapsedState()
}
BOOL LLFloaterIMSessionTab::handleKeyHere(KEY key, MASK mask )
{
+ BOOL handled = FALSE;
+
if(mask == MASK_ALT)
{
LLFloaterIMContainer* floater_container = LLFloaterIMContainer::getInstance();
if (KEY_RETURN == key && !isTornOff())
{
floater_container->expandConversation();
+ handled = TRUE;
}
if ((KEY_UP == key) || (KEY_LEFT == key))
{
floater_container->selectNextorPreviousConversation(false);
+ handled = TRUE;
}
if ((KEY_DOWN == key ) || (KEY_RIGHT == key))
{
floater_container->selectNextorPreviousConversation(true);
+ handled = TRUE;
}
}
- return TRUE;
+ return handled;
}
diff --git a/indra/newview/llfloaterimsessiontab.h b/indra/newview/llfloaterimsessiontab.h
index 302d5a8066..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;
@@ -182,6 +181,9 @@ protected:
LLButton* mTearOffBtn;
LLButton* mCloseBtn;
LLButton* mGearBtn;
+ LLButton* mAddBtn;
+ LLButton* mVoiceButton;
+ LLUICtrl* mTranslationCheckBox;
private:
// Handling selection and contextual menu
@@ -201,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/llfolderviewmodelinventory.cpp b/indra/newview/llfolderviewmodelinventory.cpp
index 586965e5a0..c28657dbcd 100755
--- a/indra/newview/llfolderviewmodelinventory.cpp
+++ b/indra/newview/llfolderviewmodelinventory.cpp
@@ -74,6 +74,7 @@ void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder )
it != end_it;
++it)
{
+ // Recursive call to sort() on child (CHUI-849)
LLFolderViewFolder* child_folderp = *it;
sort(child_folderp);
@@ -129,12 +130,12 @@ void LLFolderViewModelItemInventory::requestSort()
void LLFolderViewModelItemInventory::setPassedFilter(bool passed, S32 filter_generation, std::string::size_type string_offset, std::string::size_type string_size)
{
LLFolderViewModelItemCommon::setPassedFilter(passed, filter_generation, string_offset, string_size);
-
- bool passed_filter_before = mPrevPassedAllFilters;
+ bool before = mPrevPassedAllFilters;
mPrevPassedAllFilters = passedFilter(filter_generation);
- if (passed_filter_before != mPrevPassedAllFilters)
+ if (before != mPrevPassedAllFilters)
{
+ // Need to rearrange the folder if the filtered state of the item changed
LLFolderViewFolder* parent_folder = mFolderViewItem->getParentFolder();
if (parent_folder)
{
@@ -150,11 +151,11 @@ bool LLFolderViewModelItemInventory::filterChildItem( LLFolderViewModelItem* ite
bool continue_filtering = true;
if (item->getLastFilterGeneration() < filter_generation)
{
- // recursive application of the filter for child items
+ // Recursive application of the filter for child items (CHUI-849)
continue_filtering = item->filter( filter );
}
- // track latest generation to pass any child items, for each folder up to root
+ // Update latest generation to pass filter in parent and propagate up to root
if (item->passedFilter())
{
LLFolderViewModelItemInventory* view_model = this;
@@ -174,53 +175,61 @@ bool LLFolderViewModelItemInventory::filter( LLFolderViewFilter& filter)
const S32 filter_generation = filter.getCurrentGeneration();
const S32 must_pass_generation = filter.getFirstRequiredGeneration();
- if (getLastFilterGeneration() >= must_pass_generation
+ if (getLastFilterGeneration() >= must_pass_generation
&& getLastFolderFilterGeneration() >= must_pass_generation
&& !passedFilter(must_pass_generation))
{
// failed to pass an earlier filter that was a subset of the current one
- // go ahead and flag this item as done
+ // go ahead and flag this item as not pass
setPassedFilter(false, filter_generation);
setPassedFolderFilter(false, filter_generation);
return true;
}
- const bool passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY)
- ? filter.checkFolder(this)
- : true;
+ // *TODO : Revise the logic for fast pass on less restrictive filter case
+ /*
+ const S32 sufficient_pass_generation = filter.getFirstSuccessGeneration();
+ if (getLastFilterGeneration() >= sufficient_pass_generation
+ && getLastFolderFilterGeneration() >= sufficient_pass_generation
+ && passedFilter(sufficient_pass_generation))
+ {
+ // passed an earlier filter that was a superset of the current one
+ // go ahead and flag this item as pass
+ setPassedFilter(true, filter_generation);
+ setPassedFolderFilter(true, filter_generation);
+ return true;
+ }
+ */
+
+ const bool passed_filter_folder = (getInventoryType() == LLInventoryType::IT_CATEGORY) ? filter.checkFolder(this) : true;
setPassedFolderFilter(passed_filter_folder, filter_generation);
- if(!mChildren.empty()
+ bool continue_filtering = true;
+
+ if (!mChildren.empty()
&& (getLastFilterGeneration() < must_pass_generation // haven't checked descendants against minimum required generation to pass
- || descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement
+ || descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement
{
// now query children
- for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end();
- iter != end_iter && filter.getFilterCount() > 0;
- ++iter)
+ for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end(); iter != end_iter; ++iter)
{
- if (!filterChildItem((*iter), filter))
+ continue_filtering = filterChildItem((*iter), filter);
+ if (!continue_filtering)
{
break;
}
}
}
- // if we didn't use all filter iterations
- // that means we filtered all of our descendants
- // so filter ourselves now
- if (filter.getFilterCount() > 0)
+ // If we didn't use all the filter time that means we filtered all of our descendants so we can filter ourselves now
+ if (continue_filtering)
{
- filter.decrementFilterCount();
-
+ // This is where filter check on the item done (CHUI-849)
const bool passed_filter = filter.check(this);
setPassedFilter(passed_filter, filter_generation, filter.getStringMatchOffset(this), filter.getFilterStringSize());
- return true;
- }
- else
- {
- return false;
+ continue_filtering = !filter.isTimedOut();
}
+ return continue_filtering;
}
LLFolderViewModelInventory* LLInventoryPanel::getFolderViewModel()
@@ -307,8 +316,8 @@ bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a,
}
}
-LLFolderViewModelItemInventory::LLFolderViewModelItemInventory( class LLFolderViewModelInventory& root_view_model )
- : LLFolderViewModelItemCommon(root_view_model),
- mPrevPassedAllFilters(false)
+LLFolderViewModelItemInventory::LLFolderViewModelItemInventory( class LLFolderViewModelInventory& root_view_model ) :
+ LLFolderViewModelItemCommon(root_view_model),
+ mPrevPassedAllFilters(false)
{
}
diff --git a/indra/newview/llfolderviewmodelinventory.h b/indra/newview/llfolderviewmodelinventory.h
index 890d03d1c9..9dcfdfa185 100755
--- a/indra/newview/llfolderviewmodelinventory.h
+++ b/indra/newview/llfolderviewmodelinventory.h
@@ -59,9 +59,8 @@ public:
virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0;
virtual LLToolDragAndDrop::ESource getDragSource() const = 0;
-
protected:
- bool mPrevPassedAllFilters;
+ bool mPrevPassedAllFilters;
};
class LLInventorySort
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index a0f2918bd7..302d21c2e4 100755
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -116,6 +116,80 @@ public:
};
LLGroupHandler gGroupHandler;
+// This object represents a pending request for specified group member information
+// which is needed to check whether avatar can leave group
+class LLFetchGroupMemberData : public LLGroupMgrObserver
+{
+public:
+ LLFetchGroupMemberData(const LLUUID& group_id) :
+ mGroupId(group_id),
+ mRequestProcessed(false),
+ LLGroupMgrObserver(group_id)
+ {
+ llinfos << "Sending new group member request for group_id: "<< group_id << llendl;
+ LLGroupMgr* mgr = LLGroupMgr::getInstance();
+ // register ourselves as an observer
+ mgr->addObserver(this);
+ // send a request
+ mgr->sendGroupPropertiesRequest(group_id);
+ mgr->sendCapGroupMembersRequest(group_id);
+ }
+
+ ~LLFetchGroupMemberData()
+ {
+ if (!mRequestProcessed)
+ {
+ // Request is pending
+ llwarns << "Destroying pending group member request for group_id: "
+ << mGroupId << llendl;
+ }
+ // Remove ourselves as an observer
+ LLGroupMgr::getInstance()->removeObserver(this);
+ }
+
+ void changed(LLGroupChange gc)
+ {
+ if (gc == GC_MEMBER_DATA && !mRequestProcessed)
+ {
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupId);
+ if (!gdatap)
+ {
+ llwarns << "LLGroupMgr::getInstance()->getGroupData() was NULL" << llendl;
+ }
+ else if (!gdatap->isMemberDataComplete())
+ {
+ llwarns << "LLGroupMgr::getInstance()->getGroupData()->isMemberDataComplete() was FALSE" << llendl;
+ }
+ else
+ {
+ processGroupData();
+ mRequestProcessed = true;
+ }
+ }
+ }
+
+ LLUUID getGroupId() { return mGroupId; }
+ virtual void processGroupData() = 0;
+protected:
+ LLUUID mGroupId;
+private:
+ bool mRequestProcessed;
+};
+
+class LLFetchLeaveGroupData: public LLFetchGroupMemberData
+{
+public:
+ LLFetchLeaveGroupData(const LLUUID& group_id)
+ : LLFetchGroupMemberData(group_id)
+ {}
+ void processGroupData()
+ {
+ LLGroupActions::processLeaveGroupDataResponse(mGroupId);
+ }
+};
+
+LLFetchLeaveGroupData* gFetchLeaveGroupData = NULL;
+
// static
void LLGroupActions::search()
{
@@ -208,23 +282,52 @@ bool LLGroupActions::onJoinGroup(const LLSD& notification, const LLSD& response)
void LLGroupActions::leave(const LLUUID& group_id)
{
if (group_id.isNull())
+ {
return;
+ }
- S32 count = gAgent.mGroups.count();
- S32 i;
- for (i = 0; i < count; ++i)
+ LLGroupData group_data;
+ if (gAgent.getGroupData(group_id, group_data))
{
- if(gAgent.mGroups.get(i).mID == group_id)
- break;
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id);
+ if (!gdatap || !gdatap->isMemberDataComplete())
+ {
+ if (gFetchLeaveGroupData != NULL)
+ {
+ delete gFetchLeaveGroupData;
+ gFetchLeaveGroupData = NULL;
+ }
+ gFetchLeaveGroupData = new LLFetchLeaveGroupData(group_id);
+ }
+ else
+ {
+ processLeaveGroupDataResponse(group_id);
+ }
}
- if (i < count)
+}
+
+//static
+void LLGroupActions::processLeaveGroupDataResponse(const LLUUID group_id)
+{
+ LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(group_id);
+ LLUUID agent_id = gAgent.getID();
+ LLGroupMgrGroupData::member_list_t::iterator mit = gdatap->mMembers.find(agent_id);
+ //get the member data for the group
+ if ( mit != gdatap->mMembers.end() )
{
- LLSD args;
- args["GROUP"] = gAgent.mGroups.get(i).mName;
- LLSD payload;
- payload["group_id"] = group_id;
- LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup);
+ LLGroupMemberData* member_data = (*mit).second;
+
+ if ( member_data && member_data->isOwner() && gdatap->mMemberCount == 1)
+ {
+ LLNotificationsUtil::add("OwnerCannotLeaveGroup");
+ return;
+ }
}
+ LLSD args;
+ args["GROUP"] = gdatap->mName;
+ LLSD payload;
+ payload["group_id"] = group_id;
+ LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, onLeaveGroup);
}
// static
diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h
index 3f9852f194..afc4686dd7 100755
--- a/indra/newview/llgroupactions.h
+++ b/indra/newview/llgroupactions.h
@@ -114,6 +114,14 @@ public:
private:
static bool onJoinGroup(const LLSD& notification, const LLSD& response);
static bool onLeaveGroup(const LLSD& notification, const LLSD& response);
+
+ /**
+ * This function is called by LLFetchLeaveGroupData upon receiving a response to a group
+ * members data request.
+ */
+ static void processLeaveGroupDataResponse(const LLUUID group_id);
+
+ friend class LLFetchLeaveGroupData;
};
#endif // LL_LLGROUPACTIONS_H
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 3b72ad3cd9..9e23755d73 100755
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -103,6 +103,7 @@ BOOL LLSessionTimeoutTimer::tick()
}
+void notify_of_message(const LLSD& msg, bool is_dnd_msg);
void process_dnd_im(const LLSD& notification)
{
@@ -129,15 +130,9 @@ 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)
+ }
- LLFloaterIMContainer* im_box = LLFloaterReg::getTypedInstance<LLFloaterIMContainer>("im_container");
-
- if (im_box)
- {
- im_box->flashConversationItemWidget(sessionID, true);
- }
-
- }
+ notify_of_message(data, true);
}
@@ -158,75 +153,106 @@ static void on_avatar_name_cache_toast(const LLUUID& agent_id,
LLNotificationsUtil::add("IMToast", args, args, boost::bind(&LLFloaterIMContainer::showConversation, LLFloaterIMContainer::getInstance(), msg["session_id"].asUUID()));
}
-void on_new_message(const LLSD& msg)
+void notify_of_message(const LLSD& msg, bool is_dnd_msg)
{
- std::string user_preferences;
- LLUUID participant_id = msg["from_id"].asUUID();
- LLUUID session_id = msg["session_id"].asUUID();
- LLIMModel::LLIMSession* session = LLIMModel::instance().findIMSession(session_id);
-
- // do not show notification which goes from agent
- if (gAgent.getID() == participant_id)
- {
- return;
- }
+ 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);
- // determine state of conversations floater
- enum {CLOSED, NOT_ON_TOP, ON_TOP, ON_TOP_AND_ITEM_IS_SELECTED} conversations_floater_status;
+ // 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;
- 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))
- {
- user_preferences = gSavedSettings.getString("NotificationFriendIMOptions");
- }
- else
- {
- user_preferences = gSavedSettings.getString("NotificationNonFriendIMOptions");
- }
- }
- else if(session->isAdHocSessionType())
- {
- user_preferences = gSavedSettings.getString("NotificationConferenceIMOptions");
- }
- else if(session->isGroupSessionType())
- {
- user_preferences = gSavedSettings.getString("NotificationGroupChatOptions");
- }
+ // determine user prefs for this session
+ if (session_id.isNull())
+ {
+ if (msg["source_type"].asInteger() == CHAT_SOURCE_OBJECT)
+ {
+ user_preferences = gSavedSettings.getString("NotificationObjectIMOptions");
+ if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundObjectIM") == TRUE))
+ {
+ make_ui_sound("UISndNewIncomingIMSession");
+ }
+ }
+ else
+ {
+ user_preferences = gSavedSettings.getString("NotificationNearbyChatOptions");
+ if (!gAgent.isDoNotDisturb() && (gSavedSettings.getBOOL("PlaySoundNearbyChatIM") == TRUE))
+ {
+ make_ui_sound("UISndNewIncomingIMSession");
+ }
+ }
+ }
+ 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->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())
{
@@ -261,57 +287,103 @@ void on_new_message(const LLSD& msg)
}
}
}
- else
- {
- //If in DND mode, allow notification to be stored so upon DND exit
- //useMostItrusiveIMNotification will be called to notify user a message exists
- if(session_id.notNull()
- && participant_id.notNull()
- && !session_floater->isShown())
- {
- LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
- }
- }
- }
+ 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))
- {
- if(!LLMuteList::getInstance()->isMuted(participant_id))
- {
- im_box->flashConversationItemWidget(session_id, true);
- }
- }
+ }
- // 3. Flash FUI button
- if (("toast" == user_preferences || "flash" == user_preferences) &&
- (CLOSED == conversations_floater_status
- || NOT_ON_TOP == conversations_floater_status))
- {
- if(!LLMuteList::getInstance()->isMuted(participant_id)
- && !gAgent.isDoNotDisturb())
- {
- gToolBarView->flashCommand(LLCommandId("chat"), 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
+ || NOT_ON_TOP == conversations_floater_status))
+ || is_dnd_msg)
+ {
+ if(!LLMuteList::getInstance()->isMuted(participant_id))
+ {
+ if(gAgent.isDoNotDisturb())
+ {
+ store_dnd_message = true;
+ }
+ else
+ {
+ if (is_dnd_msg && (ON_TOP == conversations_floater_status ||
+ NOT_ON_TOP == conversations_floater_status ||
+ CLOSED == conversations_floater_status))
+ {
+ im_box->highlightConversationItemWidget(session_id, true);
+ }
+ else
+ {
+ im_box->flashConversationItemWidget(session_id, true);
+ }
+ }
+ }
+ }
- // 4. Toast
- if ((("toast" == user_preferences) &&
- (CLOSED == conversations_floater_status
- || NOT_ON_TOP == conversations_floater_status))
- || !session_floater->isMessagePaneExpanded())
+ // 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, im_box->isMinimized());
+ }
+ else
+ {
+ store_dnd_message = true;
+ }
+ }
+ }
- {
- //Show IM toasts (upper right toasts)
- // Skip toasting for system messages and for nearby chat
- if(session_id.notNull() && participant_id.notNull())
- {
- LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
- }
- }
+ // 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())
+ {
+ if(!is_dnd_msg)
+ {
+ if(gAgent.isDoNotDisturb())
+ {
+ store_dnd_message = true;
+ }
+ else
+ {
+ LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
+ }
+ }
+ }
+ }
+ if (store_dnd_message)
+ {
+ // If in DND mode, allow notification to be stored so upon DND exit
+ // the user will be notified with some limitations (see 'is_dnd_msg' flag checks)
+ if(session_id.notNull()
+ && participant_id.notNull()
+ && !session_floater->isShown())
+ {
+ LLAvatarNameCache::get(participant_id, boost::bind(&on_avatar_name_cache_toast, _1, _2, msg));
+ }
+ }
+}
+
+void on_new_message(const LLSD& msg)
+{
+ notify_of_message(msg, false);
}
LLIMModel::LLIMModel()
@@ -2597,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)
@@ -2608,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.
@@ -2648,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")->
@@ -2971,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/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 92f2d33073..3c6974cf6d 100755
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -70,11 +70,8 @@ LLInventoryFilter::LLInventoryFilter(const Params& p)
mFilterSubString(p.substring),
mCurrentGeneration(0),
mFirstRequiredGeneration(0),
- mFirstSuccessGeneration(0),
- mFilterCount(0)
+ mFirstSuccessGeneration(0)
{
- mNextFilterGeneration = mCurrentGeneration + 1;
-
// copy mFilterOps into mDefaultFilterOps
markDefault();
}
@@ -92,9 +89,7 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
return passed_clipboard;
}
- std::string::size_type string_offset = mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) : std::string::npos;
-
- BOOL passed = (mFilterSubString.size() == 0 || string_offset != std::string::npos);
+ bool passed = (mFilterSubString.size() ? listener->getSearchableName().find(mFilterSubString) != std::string::npos : true);
passed = passed && checkAgainstFilterType(listener);
passed = passed && checkAgainstPermissions(listener);
passed = passed && checkAgainstFilterLinks(listener);
@@ -105,17 +100,12 @@ bool LLInventoryFilter::check(const LLFolderViewModelItem* item)
bool LLInventoryFilter::check(const LLInventoryItem* item)
{
- std::string::size_type string_offset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos;
-
+ const bool passed_string = (mFilterSubString.size() ? item->getName().find(mFilterSubString) != std::string::npos : true);
const bool passed_filtertype = checkAgainstFilterType(item);
const bool passed_permissions = checkAgainstPermissions(item);
- const BOOL passed_clipboard = checkAgainstClipboard(item->getUUID());
- const bool passed = (passed_filtertype
- && passed_permissions
- && passed_clipboard
- && (mFilterSubString.size() == 0 || string_offset != std::string::npos));
+ const bool passed_clipboard = checkAgainstClipboard(item->getUUID());
- return passed;
+ return passed_filtertype && passed_permissions && passed_clipboard && passed_string;
}
bool LLInventoryFilter::checkFolder(const LLFolderViewModelItem* item) const
@@ -439,7 +429,7 @@ void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types)
current_types = types;
if (more_bits_set && fewer_bits_set)
{
- // neither less or more restrive, both simultaneously
+ // neither less or more restrictive, both simultaneously
// so we need to filter from scratch
setModified(FILTER_RESTART);
}
@@ -714,7 +704,7 @@ void LLInventoryFilter::resetDefault()
void LLInventoryFilter::setModified(EFilterModified behavior)
{
mFilterText.clear();
- mCurrentGeneration = mNextFilterGeneration++;
+ mCurrentGeneration++;
if (mFilterModified == FILTER_NONE)
{
@@ -1021,21 +1011,19 @@ LLInventoryFilter::EFolderShow LLInventoryFilter::getShowFolderState() const
return mFilterOps.mShowFolderState;
}
-void LLInventoryFilter::setFilterCount(S32 count)
-{
- mFilterCount = count;
-}
-S32 LLInventoryFilter::getFilterCount() const
+bool LLInventoryFilter::isTimedOut()
{
- return mFilterCount;
+ return mFilterTime.hasExpired();
}
-void LLInventoryFilter::decrementFilterCount()
-{
- mFilterCount--;
+void LLInventoryFilter::resetTime(S32 timeout)
+{
+ mFilterTime.reset();
+ F32 time_in_sec = (F32)(timeout)/1000.0;
+ mFilterTime.setTimerExpirySec(time_in_sec);
}
-S32 LLInventoryFilter::getCurrentGeneration() const
+S32 LLInventoryFilter::getCurrentGeneration() const
{
return mCurrentGeneration;
}
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index 4912b5ca91..ce516af0b9 100755
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -215,12 +215,11 @@ public:
void setModified(EFilterModified behavior = FILTER_RESTART);
// +-------------------------------------------------------------------+
- // + Count
+ // + Time
// +-------------------------------------------------------------------+
- void setFilterCount(S32 count);
- S32 getFilterCount() const;
- void decrementFilterCount();
-
+ void resetTime(S32 timeout);
+ bool isTimedOut();
+
// +-------------------------------------------------------------------+
// + Default
// +-------------------------------------------------------------------+
@@ -262,13 +261,15 @@ private:
const std::string mName;
S32 mCurrentGeneration;
+ // The following makes checking for pass/no pass possible even if the item is not checked against the current generation
+ // Any item that *did not pass* the "required generation" will *not pass* the current one
+ // Any item that *passes* the "success generation" will *pass* the current one
S32 mFirstRequiredGeneration;
S32 mFirstSuccessGeneration;
- S32 mNextFilterGeneration;
- S32 mFilterCount;
EFilterModified mFilterModified;
-
+ LLTimer mFilterTime;
+
std::string mFilterText;
std::string mEmptyLookupMessage;
};
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index cf1fd4c0d0..e5b9e11d48 100755
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -192,7 +192,7 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )
p.show_item_link_overlays = mShowItemLinkOverlays;
p.root = NULL;
p.options_menu = "menu_inventory.xml";
-
+
return LLUICtrlFactory::create<LLFolderView>(p);
}
@@ -396,6 +396,7 @@ LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()
return getFilter().getShowFolderState();
}
+// Called when something changed in the global model (new item, item coming through the wire, rename, move, etc...) (CHUI-849)
void LLInventoryPanel::modelChanged(U32 mask)
{
static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh");
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 2d7454b636..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 ;
- }
-
- bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false;
+ {
+ LL_WARNS("LLLogChat::loadChatHistory") << "Session name is Empty!" << LL_ENDL;
+ return ;
+ }
- 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;
+ bool load_all_history = load_params.has("load_all_history") ? load_params["load_all_history"].asBoolean() : false;
- 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
@@ -631,7 +647,7 @@ void LLLogChat::deleteTranscripts()
}
// static
-bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id)
+bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id, bool is_group)
{
std::vector<std::string> list_of_transcriptions;
LLLogChat::getListOfTranscriptFiles(list_of_transcriptions);
@@ -641,20 +657,53 @@ bool LLLogChat::isTranscriptExist(const LLUUID& avatar_id)
LLAvatarName avatar_name;
LLAvatarNameCache::get(avatar_id, &avatar_name);
std::string avatar_user_name = avatar_name.getAccountName();
- std::replace(avatar_user_name.begin(), avatar_user_name.end(), '.', '_');
-
- BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)
+ if(!is_group)
{
- if (std::string::npos != transcript_file_name.find(avatar_user_name))
+ std::replace(avatar_user_name.begin(), avatar_user_name.end(), '.', '_');
+ BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)
{
- return true;
+ if (std::string::npos != transcript_file_name.find(avatar_user_name))
+ {
+ return true;
+ }
}
}
+ else
+ {
+ std::string file_name;
+ gCacheName->getGroupName(avatar_id, file_name);
+ file_name = makeLogFileName(file_name);
+ BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)
+ {
+ if (transcript_file_name == file_name)
+ {
+ return true;
+ }
+ }
+ }
+
}
return false;
}
+bool LLLogChat::isNearbyTranscriptExist()
+{
+ std::vector<std::string> list_of_transcriptions;
+ LLLogChat::getListOfTranscriptFiles(list_of_transcriptions);
+
+ std::string file_name;
+ file_name = makeLogFileName("chat");
+ BOOST_FOREACH(std::string& transcript_file_name, list_of_transcriptions)
+ {
+ if (transcript_file_name == file_name)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
//*TODO mark object's names in a special way so that they will be distinguishable form avatar name
//which are more strict by its nature (only firstname and secondname)
//Example, an object's name can be written like "Object <actual_object's_name>"
@@ -795,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 e819f00dd9..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);
@@ -67,7 +87,8 @@ public:
std::vector<std::string>& listOfFilesToMove);
static void deleteTranscripts();
- static bool isTranscriptExist(const LLUUID& avatar_id);
+ static bool isTranscriptExist(const LLUUID& avatar_id, bool is_group=false);
+ static bool isNearbyTranscriptExist();
private:
static std::string cleanFileName(std::string filename);
@@ -126,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/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/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index d6535c88e9..53deded2f2 100755
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -130,6 +130,8 @@ BOOL LLPanelMainInventory::postBuild()
mFilterTabs = getChild<LLTabContainer>("inventory filter tabs");
mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this));
+ mCounterCtrl = getChild<LLUICtrl>("ItemcountText");
+
//panel->getFilter().markDefault();
// Set up the default inv. panel/filter settings.
@@ -566,7 +568,7 @@ void LLPanelMainInventory::draw()
void LLPanelMainInventory::updateItemcountText()
{
// *TODO: Calling setlocale() on each frame may be inefficient.
- LLLocale locale(LLStringUtil::getLocale());
+ //LLLocale locale(LLStringUtil::getLocale());
std::string item_count_string;
LLResMgr::getInstance()->getIntegerString(item_count_string, gInventory.getItemCount());
@@ -589,8 +591,7 @@ void LLPanelMainInventory::updateItemcountText()
text = getString("ItemcountUnknown");
}
- // *TODO: Cache the LLUICtrl* for the ItemcountText control
- getChild<LLUICtrl>("ItemcountText")->setValue(text);
+ mCounterCtrl->setValue(text);
}
void LLPanelMainInventory::onFocusReceived()
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index 899931aa89..394b004e20 100755
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -121,6 +121,7 @@ private:
LLFilterEditor* mFilterEditor;
LLTabContainer* mFilterTabs;
+ LLUICtrl* mCounterCtrl;
LLHandle<LLFloater> mFinderHandle;
LLInventoryPanel* mActivePanel;
bool mResortActivePanel;
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 4138558bad..d7c634d619 100755
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -76,6 +76,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
{
@@ -808,6 +810,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 4846c54189..626d69aca4 100755
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -428,9 +428,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 75e6e3d13a..09ab31df36 100755
--- a/indra/newview/lltoastimpanel.cpp
+++ b/indra/newview/lltoastimpanel.cpp
@@ -28,6 +28,7 @@
#include "lltoastimpanel.h"
#include "llagent.h"
+#include "llavatarnamecache.h"
#include "llfloaterreg.h"
#include "llgroupactions.h"
#include "llgroupiconctrl.h"
@@ -61,6 +62,15 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif
style_params.font.name(font_name);
style_params.font.size(font_size);
+ LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(p.session_id);
+ mIsGroupMsg = (im_session && im_session->mSessionType == LLIMModel::LLIMSession::GROUP_SESSION);
+ if(mIsGroupMsg)
+ {
+ mAvatarName->setValue(im_session->mName);
+ LLAvatarName avatar_name;
+ LLAvatarNameCache::get(p.avatar_id, &avatar_name);
+ p.message = "[From " + avatar_name.getDisplayName() + "]\n" + p.message;
+ }
//Handle IRC styled /me messages.
std::string prefix = p.message.substr(0, 4);
@@ -81,12 +91,17 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif
mMessage->setText(p.message, style_params);
}
- mAvatarName->setValue(p.from);
+ if(!mIsGroupMsg)
+ {
+ mAvatarName->setValue(p.from);
+ }
mTime->setValue(p.time);
mSessionID = p.session_id;
mAvatarID = p.avatar_id;
mNotification = p.notification;
+
+
initIcon();
S32 maxLinesCount;
@@ -147,7 +162,14 @@ void LLToastIMPanel::spawnNameToolTip()
LLToolTip::Params params;
params.background_visible(false);
- params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE));
+ if(!mIsGroupMsg)
+ {
+ params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_avatar", LLSD().with("avatar_id", mAvatarID), FALSE));
+ }
+ else
+ {
+ params.click_callback(boost::bind(&LLFloaterReg::showInstance, "inspect_group", LLSD().with("group_id", mSessionID), FALSE));
+ }
params.delay_time(0.0f); // spawn instantly on hover
params.image(LLUI::getUIImage("Info_Small"));
params.message("");
diff --git a/indra/newview/lltoastimpanel.h b/indra/newview/lltoastimpanel.h
index 3eb11fb3bc..767617dabc 100755
--- a/indra/newview/lltoastimpanel.h
+++ b/indra/newview/lltoastimpanel.h
@@ -73,6 +73,8 @@ private:
LLTextBox* mAvatarName;
LLTextBox* mTime;
LLTextBox* mMessage;
+
+ bool mIsGroupMsg;
};
#endif // LLTOASTIMPANEL_H_
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 f744f5ace2..1f0ffac737 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;
@@ -2649,7 +2653,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
{
send_do_not_disturb_message(msg, from_id);
}
- else
+
+ if (!is_muted)
{
LL_INFOS("Messaging") << "Received IM_GROUP_INVITATION message." << LL_ENDL;
// Read the binary bucket for more information.
@@ -3685,6 +3690,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);
}
}
@@ -5942,6 +5948,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;
@@ -6017,14 +6032,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/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index e98a2cb32c..963eb3eb88 100755
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1824,7 +1824,6 @@ void LLViewerWindow::initBase()
gFloaterView = main_view->getChild<LLFloaterView>("Floater View");
gFloaterView->setFloaterSnapView(main_view->getChild<LLView>("floater_snap_region")->getHandle());
gSnapshotFloaterView = main_view->getChild<LLSnapshotFloaterView>("Snapshot Floater View");
-
// Console
llassert( !gConsole );
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index a9176595c7..f53995732f 100755
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -884,4 +884,19 @@
<color
name="blue"
value="0 0 1 1"/>
+
+ <!--Resize bar colors -->
+
+ <color
+ name="ResizebarBorderLight"
+ value="0.231 0.231 0.231 1"/>
+
+ <color
+ name="ResizebarBorderDark"
+ value="0.133 0.133 0.133 1"/>
+
+ <color
+ name="ResizebarBody"
+ value="0.208 0.208 0.208 1"/>
+
</colors>
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index b0e4b71d21..54f60f4441 100755
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -774,4 +774,7 @@ with the same filename but different name
<texture name="Popup_Caution" file_name="icons/pop_up_caution.png"/>
<texture name="Camera_Drag_Dot" file_name="world/CameraDragDot.png"/>
<texture name="NavBar Separator" file_name="navbar/separator.png"/>
+
+ <texture name="Horizontal Drag Handle" file_name="widgets/horizontal_drag_handle.png"/>
+ <texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png"/>
</textures>
diff --git a/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.png b/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.png
new file mode 100644
index 0000000000..642eac4065
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/horizontal_drag_handle.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/widgets/vertical_drag_handle.png b/indra/newview/skins/default/textures/widgets/vertical_drag_handle.png
new file mode 100644
index 0000000000..b06b70cf36
--- /dev/null
+++ b/indra/newview/skins/default/textures/widgets/vertical_drag_handle.png
Binary files differ
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 &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Du er ved [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] i regionen [REGION] lokaliseret ved &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([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 &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Sie befinden sich in [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] auf &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([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 &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+You are at [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] located at &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+SLURL: &lt;nolink&gt;[SLURL]&lt;/nolink&gt;
+(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 65f623a47e..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"
@@ -24,24 +25,28 @@
value="Conv_toolbar_expand"/>
<layout_stack
animate="true"
- bottom="-1"
+ bottom="-5"
+ drag_handle_gap="6"
+ drag_handle_first_indent="27"
+ drag_handle_second_indent="10"
follows="all"
layout="topleft"
left="0"
name="conversations_stack"
orientation="horizontal"
right="-1"
+ show_drag_handle="true"
top="0">
<layout_panel
auto_resize="false"
user_resize="true"
name="conversations_layout_panel"
min_dim="38"
- expanded_min_dim="156">
+ expanded_min_dim="136">
<layout_stack
animate="false"
follows="left|top|right"
- height="35"
+ height="27"
layout="topleft"
left="0"
name="conversations_pane_buttons_stack"
@@ -50,7 +55,6 @@
top="0">
<layout_panel
auto_resize="true"
- height="35"
name="conversations_pane_buttons_expanded">
<menu_button
follows="top|left"
@@ -64,7 +68,7 @@
left="5"
name="sort_btn"
tool_tip="View/sort options"
- top="5"
+ top="1"
width="31" />
<button
follows="top|left"
@@ -74,7 +78,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="add_btn"
tool_tip="Start a new conversation"
@@ -87,7 +91,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="speak_btn"
tool_tip="Speak with people using your microphone"
@@ -95,9 +99,8 @@
</layout_panel>
<layout_panel
auto_resize="false"
- height="35"
name="conversations_pane_buttons_collapsed"
- width="41">
+ width="31">
<button
follows="right|top"
height="25"
@@ -106,8 +109,8 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
- left="1"
+ top="1"
+ left="0"
name="expand_collapse_btn"
tool_tip="Collapse/Expand this list"
width="31" />
@@ -119,7 +122,7 @@
layout="topleft"
name="conversations_list_panel"
opaque="true"
- top="35"
+ top_pad="0"
left="5"
right="-1"/>
</layout_panel>
@@ -127,7 +130,7 @@
auto_resize="true"
user_resize="true"
name="messages_layout_panel"
- expanded_min_dim="222">
+ expanded_min_dim="212">
<panel_container
bottom="-1"
follows="all"
@@ -136,44 +139,44 @@
name="im_box_tab_container"
right="-1"
top="0">
- <panel
- bottom="-1"
- follows="all"
- layout="topleft"
- name="stub_panel"
- opaque="true"
- top_pad="0"
- left="0"
- right="-1">
- <button
- follows="right|top"
- height="25"
- image_hover_unselected="Toolbar_Middle_Over"
- image_overlay="Conv_toolbar_collapse"
- image_selected="Toolbar_Middle_Selected"
- image_unselected="Toolbar_Middle_Off"
+ <panel
+ bottom="-1"
+ follows="all"
layout="topleft"
- top="5"
- right="-10"
- name="stub_collapse_btn"
- tool_tip="Collapse this pane"
- width="31" />
- <text
- type="string"
- clip_partial="false"
- follows="left|top|right"
- layout="topleft"
- left="15"
- right="-15"
- name="stub_textbox"
- top="25"
- height="40"
- valign="center"
- parse_urls="true"
- wrap="true">
- This conversation is in a separate window. [secondlife:/// Bring it back.]
- </text>
- </panel>
+ name="stub_panel"
+ opaque="true"
+ top_pad="0"
+ left="0"
+ right="-1">
+ <button
+ follows="right|top"
+ height="25"
+ image_hover_unselected="Toolbar_Middle_Over"
+ image_overlay="Conv_toolbar_collapse"
+ image_selected="Toolbar_Middle_Selected"
+ image_unselected="Toolbar_Middle_Off"
+ layout="topleft"
+ top="1"
+ right="-10"
+ name="stub_collapse_btn"
+ tool_tip="Collapse this pane"
+ width="31" />
+ <text
+ type="string"
+ clip_partial="false"
+ follows="left|top|right"
+ layout="topleft"
+ left="15"
+ right="-15"
+ name="stub_textbox"
+ top="25"
+ height="40"
+ valign="center"
+ parse_urls="true"
+ wrap="true">
+ This conversation is in a separate window. [secondlife:/// Bring it back.]
+ </text>
+ </panel>
</panel_container>
</layout_panel>
</layout_stack>
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 2152a9f6e9..43d0f2fb18 100755
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -70,26 +70,23 @@
top="0"
left="0"
right="-1"
- bottom="-3">
+ bottom="-1">
<layout_stack
animate="false"
+ bottom="-1"
default_tab_group="2"
follows="all"
- right="-5"
- bottom="-1"
- top="0"
- left="5"
- border_size="0"
+ left="3"
layout="topleft"
- orientation="vertical"
name="main_stack"
- tab_group="1">
+ right="-3"
+ orientation="vertical"
+ tab_group="1"
+ top="0">
<layout_panel
auto_resize="false"
name="toolbar_panel"
- height="35"
- right="-1"
- left="1">
+ height="25">
<menu_button
menu_filename="menu_im_session_showmodes.xml"
follows="top|left"
@@ -102,7 +99,7 @@
left="5"
name="view_options_btn"
tool_tip="View/sort options"
- top="5"
+ top="1"
width="31" />
<menu_button
menu_filename="menu_im_conversation.xml"
@@ -113,7 +110,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="gear_btn"
visible="false"
@@ -128,7 +125,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="add_btn"
tool_tip="Add someone to this conversation"
@@ -141,23 +138,11 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
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"
@@ -166,8 +151,8 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
- right="-67"
+ top="1"
+ right="-70"
name="close_btn"
tool_tip="End this conversation"
width="31" />
@@ -179,7 +164,7 @@
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
layout="topleft"
- top="5"
+ top="1"
left_pad="2"
name="expand_collapse_btn"
tool_tip="Collapse/Expand this pane"
@@ -194,18 +179,21 @@
layout="topleft"
left_pad="2"
name="tear_off_btn"
- top="5"
+ top="1"
width="31" />
</layout_panel>
<layout_panel
name="body_panel"
- top="1"
- bottom="-1">
+ height="235">
<layout_stack
default_tab_group="2"
+ drag_handle_gap="6"
+ drag_handle_first_indent="0"
+ drag_handle_second_indent="1"
follows="all"
orientation="horizontal"
name="im_panels"
+ show_drag_handle="true"
tab_group="1"
top="0"
right="-1"
@@ -217,14 +205,12 @@
min_dim="0"
width="150"
user_resize="true"
- auto_resize="false"
- bottom="-1" />
+ auto_resize="false" />
<layout_panel
default_tab_group="3"
tab_group="2"
name="right_part_holder"
- min_width="221"
- bottom="-1">
+ min_width="172">
<layout_stack
animate="true"
default_tab_group="2"
@@ -233,7 +219,7 @@
name="translate_and_chat_stack"
tab_group="1"
top="0"
- left="0"
+ left="1"
right="-1"
bottom="-1">
<layout_panel
@@ -259,7 +245,7 @@
parse_highlights="true"
parse_urls="true"
right="-1"
- left="5"
+ left="0"
top="0"
bottom="-1" />
</layout_panel>
@@ -268,10 +254,7 @@
</layout_stack>
</layout_panel>
<layout_panel
- top_delta="0"
- top="0"
- height="26"
- bottom="-1"
+ height="35"
auto_resize="false"
name="chat_layout_panel">
<layout_stack
@@ -281,15 +264,11 @@
orientation="horizontal"
name="input_panels"
top="0"
- bottom="-2"
+ bottom="-1"
left="0"
right="-1">
<layout_panel
- name="input_editor_layout_panel"
- auto_resize="true"
- user_resize="false"
- top="0"
- bottom="-1">
+ name="input_editor_layout_panel">
<chat_editor
layout="topleft"
expand_lines_count="5"
@@ -302,32 +281,27 @@
max_length="1023"
spellcheck="true"
tab_group="3"
- top="1"
- bottom="-2"
- left="4"
- right="-4"
+ bottom="-8"
+ left="5"
+ right="-5"
wrap="true" />
</layout_panel>
<layout_panel
auto_resize="false"
- user_resize="false"
name="input_button_layout_panel"
- width="30"
- top="0"
- bottom="-1">
+ width="32">
<button
- layout="topleft"
left="1"
- right="-1"
- top="1"
- height="22"
+ top="4"
+ height="25"
follows="left|right|top"
image_hover_unselected="Toolbar_Middle_Over"
image_overlay="Conv_expand_one_line"
image_selected="Toolbar_Middle_Selected"
image_unselected="Toolbar_Middle_Off"
name="minz_btn"
- tool_tip="Shows/hides message panel" />
+ tool_tip="Shows/hides message panel"
+ width="28" />
</layout_panel>
</layout_stack>
</layout_panel>
diff --git a/indra/newview/skins/default/xui/en/menu_conversation.xml b/indra/newview/skins/default/xui/en/menu_conversation.xml
index d8eb2f0ffd..31b1d091ee 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 b71faa2d3e..dabfc4eebd 100755
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -874,6 +874,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
@@ -896,7 +905,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 1867141758..9ed9a6f409 100755
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -3736,6 +3736,17 @@ Leave Group?
</notification>
<notification
+ icon="alertmodal.tga"
+ name="OwnerCannotLeaveGroup"
+ type="alertmodal">
+ Unable to leave group. You cannot leave the group because you are the last owner of the group. Please assign another member to the owner role first.
+ <tag>group</tag>
+ <usetemplate
+ name="okbutton"
+ yestext="OK"/>
+ </notification>
+
+ <notification
icon="alert.tga"
name="ConfirmKick"
type="alert">
@@ -5991,9 +6002,7 @@ Your calling card was declined.
icon="notifytip.tga"
name="TeleportToPerson"
type="notifytip">
- To contact Residents like &apos;[NAME]&apos;, click on the &quot;People&quot; button , select a Resident from the window that opens, then click &apos;IM&apos; at the
- bottom of the window.
- (You can also double-click on their name in the list, or right-click and choose &apos;IM&apos;).
+ To open a private conversation with someone, right-click on their avatar and choose &apos;IM&apos; from the menu.
</notification>
<notification
@@ -6621,7 +6630,7 @@ Your object named &lt;nolink&gt;[OBJECTFROMNAME]&lt;/nolink&gt; has given you th
icon="notify.tga"
name="JoinGroup"
persist="true"
- type="notify">
+ type="offer">
<tag>group</tag>
[MESSAGE]
<form name="form">
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 7ce2627be9..ed274d0233 100755
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -480,10 +480,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 a56213cdfe..a6b1961849 100755
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -209,7 +209,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 (&#8984;W)</string>
@@ -3933,5 +3934,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 &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([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 &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([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 à &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Vous êtes à [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] dans [REGION], se trouvant à &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([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 &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Tu sei [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] in [REGION] che si trova a &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([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] です。位置は &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; です。([HOSTIP])
+ あなたの現在地は、[POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] の [REGION] です。位置は &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; です。([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 &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Położenie [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] w [REGION] zlokalizowanym w &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([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]&lt;/nolink&gt;([HOSTIP])
+ Você está em [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] em [REGION] localizado em [HOSTNAME]&lt;/nolink&gt;([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]», расположенном на &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ Вы в точке [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1] в регионе «[REGION]», расположенном на &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([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">
- &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP]) üzerinde bulunan [REGION] içerisinde [POSITION_0,number,1], [POSITION_1,number,1], [POSITION_2,number,1] konumundasınız
+ &lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([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],主機:&lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([HOSTIP])
+ 你的方位是 [POSITION_LOCAL_0,number,1], [POSITION_LOCAL_1,number,1], [POSITION_LOCAL_2,number,1],地區名:[REGION],主機:&lt;nolink&gt;[HOSTNAME]&lt;/nolink&gt; ([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 0b105cc1b6..3e170e44f4 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);
}
@@ -98,8 +97,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,
@@ -111,8 +109,7 @@ void LLUpdateChecker::Implementation::checkVersion(std::string const & hostUrl,
{
mInProgress = true;
- mHostUrl = hostUrl;
- mServicePath = servicePath;
+ mUrlBase = urlBase;
mChannel = channel;
mVersion = version;
mPlatform = platform;
@@ -122,7 +119,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);
@@ -152,11 +149,40 @@ void LLUpdateChecker::Implementation::completed(U32 status,
server_error += content["error_text"].asString();
}
- LL_WARNS("UpdaterService") << "response error " << status
- << " " << reason
- << " (" << server_error << ")"
- << LL_ENDL;
- mClient.error(reason);
+ if (status == 404)
+ {
+ if (mProtocol == sProtocolVersion)
+ {
+ mProtocol = sLegacyProtocolVersion;
+ std::string retryUrl = buildUrl(mUrlBase, mChannel, mVersion, mPlatform, mPlatformVersion, mUniqueId, mWillingToTest);
+
+ LL_WARNS("UpdaterService")
+ << "update response using " << sProtocolVersion
+ << " was HTTP 404 (" << server_error
+ << "); retry with legacy protocol " << mProtocol
+ << "\n at " << retryUrl
+ << LL_ENDL;
+
+ mHttpClient.get(retryUrl, this);
+ }
+ else
+ {
+ LL_WARNS("UpdaterService")
+ << "update response using " << sLegacyProtocolVersion
+ << " was 404 (" << server_error
+ << "); request failed"
+ << LL_ENDL;
+ mClient.error(reason);
+ }
+ }
+ else
+ {
+ LL_WARNS("UpdaterService") << "response error " << status
+ << " " << reason
+ << " (" << server_error << ")"
+ << LL_ENDL;
+ mClient.error(reason);
+ }
}
else
{
@@ -173,8 +199,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,
@@ -183,7 +208,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);
@@ -191,5 +215,5 @@ std::string LLUpdateChecker::Implementation::buildUrl(std::string const & hostUr
path.append(platform_version);
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();