Merge - final pull of viewer-development.

master
Monty Brandenberg 2010-12-20 09:57:39 -08:00
commit 9c97a200be
11 changed files with 267 additions and 23 deletions

View File

@ -373,6 +373,8 @@ Khyota Wulluf
Kitty Barnett
VWR-19699
STORM-288
STORM-799
STORM-800
Kunnis Basiat
VWR-82
VWR-102

View File

@ -805,6 +805,69 @@ std::string LLUrlEntryPlace::getLocation(const std::string &url) const
return ::getStringAfterToken(url, "://");
}
//
// LLUrlEntryRegion Describes secondlife:///app/region/REGION_NAME/X/Y/Z URLs, e.g.
// secondlife:///app/region/Ahern/128/128/0
//
LLUrlEntryRegion::LLUrlEntryRegion()
{
mPattern = boost::regex("secondlife:///app/region/[^/\\s]+(/\\d+)?(/\\d+)?(/\\d+)?/?",
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_slurl.xml";
mTooltip = LLTrans::getString("TooltipSLURL");
}
std::string LLUrlEntryRegion::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
//
// we handle SLURLs in the following formats:
// - secondlife:///app/region/Place/X/Y/Z
// - secondlife:///app/region/Place/X/Y
// - secondlife:///app/region/Place/X
// - secondlife:///app/region/Place
//
LLSD path_array = LLURI(url).pathArray();
S32 path_parts = path_array.size();
if (path_parts < 3) // no region name
{
llwarns << "Failed to parse url [" << url << "]" << llendl;
return url;
}
std::string label = unescapeUrl(path_array[2]); // region name
if (path_parts > 3) // secondlife:///app/region/Place/X
{
std::string x = path_array[3];
label += " (" + x;
if (path_parts > 4) // secondlife:///app/region/Place/X/Y
{
std::string y = path_array[4];
label += "," + y;
if (path_parts > 5) // secondlife:///app/region/Place/X/Y/Z
{
std::string z = path_array[5];
label = label + "," + z;
}
}
label += ")";
}
return label;
}
std::string LLUrlEntryRegion::getLocation(const std::string &url) const
{
LLSD path_array = LLURI(url).pathArray();
std::string region_name = unescapeUrl(path_array[2]);
return region_name;
}
//
// LLUrlEntryTeleport Describes a Second Life teleport Url, e.g.,
// secondlife:///app/teleport/Ahern/50/50/50/

View File

@ -301,6 +301,18 @@ public:
/*virtual*/ std::string getLocation(const std::string &url) const;
};
///
/// LLUrlEntryRegion Describes a Second Life location Url, e.g.,
/// secondlife:///app/region/Ahern/128/128/0
///
class LLUrlEntryRegion : public LLUrlEntryBase
{
public:
LLUrlEntryRegion();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getLocation(const std::string &url) const;
};
///
/// LLUrlEntryTeleport Describes a Second Life teleport Url, e.g.,
/// secondlife:///app/teleport/Ahern/50/50/50/

View File

@ -54,6 +54,7 @@ LLUrlRegistry::LLUrlRegistry()
registerUrl(new LLUrlEntryGroup());
registerUrl(new LLUrlEntryParcel());
registerUrl(new LLUrlEntryTeleport());
registerUrl(new LLUrlEntryRegion());
registerUrl(new LLUrlEntryWorldMap());
registerUrl(new LLUrlEntryObjectIM());
registerUrl(new LLUrlEntryPlace());

View File

@ -103,6 +103,45 @@ namespace tut
ensure_equals(testname, url, expected);
}
void dummyCallback(const std::string &url, const std::string &label, const std::string& icon)
{
}
void testLabel(const std::string &testname, LLUrlEntryBase &entry,
const char *text, const std::string &expected)
{
boost::regex regex = entry.getPattern();
std::string label = "";
boost::cmatch result;
bool found = boost::regex_search(text, result, regex);
if (found)
{
S32 start = static_cast<U32>(result[0].first - text);
S32 end = static_cast<U32>(result[0].second - text);
std::string url = std::string(text+start, end-start);
label = entry.getLabel(url, boost::bind(dummyCallback, _1, _2, _3));
}
ensure_equals(testname, label, expected);
}
void testLocation(const std::string &testname, LLUrlEntryBase &entry,
const char *text, const std::string &expected)
{
boost::regex regex = entry.getPattern();
std::string location = "";
boost::cmatch result;
bool found = boost::regex_search(text, result, regex);
if (found)
{
S32 start = static_cast<U32>(result[0].first - text);
S32 end = static_cast<U32>(result[0].second - text);
std::string url = std::string(text+start, end-start);
location = entry.getLocation(url);
}
ensure_equals(testname, location, expected);
}
template<> template<>
void object::test<1>()
{
@ -697,4 +736,114 @@ namespace tut
"<nolink>My Object</nolink>",
"My Object");
}
template<> template<>
void object::test<13>()
{
//
// test LLUrlEntryRegion - secondlife:///app/region/<location> URLs
//
LLUrlEntryRegion url;
// Regex tests.
testRegex("no valid region", url,
"secondlife:///app/region/",
"");
testRegex("invalid coords", url,
"secondlife:///app/region/Korea2/a/b/c",
"secondlife:///app/region/Korea2/"); // don't count invalid coords
testRegex("Ahern (50,50,50) [1]", url,
"secondlife:///app/region/Ahern/50/50/50/",
"secondlife:///app/region/Ahern/50/50/50/");
testRegex("Ahern (50,50,50) [2]", url,
"XXX secondlife:///app/region/Ahern/50/50/50/ XXX",
"secondlife:///app/region/Ahern/50/50/50/");
testRegex("Ahern (50,50,50) [3]", url,
"XXX secondlife:///app/region/Ahern/50/50/50 XXX",
"secondlife:///app/region/Ahern/50/50/50");
testRegex("Ahern (50,50,50) multicase", url,
"XXX secondlife:///app/region/Ahern/50/50/50/ XXX",
"secondlife:///app/region/Ahern/50/50/50/");
testRegex("Ahern (50,50) [1]", url,
"XXX secondlife:///app/region/Ahern/50/50/ XXX",
"secondlife:///app/region/Ahern/50/50/");
testRegex("Ahern (50,50) [2]", url,
"XXX secondlife:///app/region/Ahern/50/50 XXX",
"secondlife:///app/region/Ahern/50/50");
// DEV-21577: In-world SLURLs containing "(" or ")" are not treated as a hyperlink in chat
testRegex("Region with brackets", url,
"XXX secondlife:///app/region/Burning%20Life%20(Hyper)/27/210/30 XXX",
"secondlife:///app/region/Burning%20Life%20(Hyper)/27/210/30");
// DEV-35459: SLURLs and teleport Links not parsed properly
testRegex("Region with quote", url,
"XXX secondlife:///app/region/A'ksha%20Oasis/41/166/701 XXX",
"secondlife:///app/region/A%27ksha%20Oasis/41/166/701");
// Rendering tests.
testLabel("Render /app/region/Ahern/50/50/50/", url,
"secondlife:///app/region/Ahern/50/50/50/",
"Ahern (50,50,50)");
testLabel("Render /app/region/Ahern/50/50/50", url,
"secondlife:///app/region/Ahern/50/50/50",
"Ahern (50,50,50)");
testLabel("Render /app/region/Ahern/50/50/", url,
"secondlife:///app/region/Ahern/50/50/",
"Ahern (50,50)");
testLabel("Render /app/region/Ahern/50/50", url,
"secondlife:///app/region/Ahern/50/50",
"Ahern (50,50)");
testLabel("Render /app/region/Ahern/50/", url,
"secondlife:///app/region/Ahern/50/",
"Ahern (50)");
testLabel("Render /app/region/Ahern/50", url,
"secondlife:///app/region/Ahern/50",
"Ahern (50)");
testLabel("Render /app/region/Ahern/", url,
"secondlife:///app/region/Ahern/",
"Ahern");
testLabel("Render /app/region/Ahern/ within context", url,
"XXX secondlife:///app/region/Ahern/ XXX",
"Ahern");
testLabel("Render /app/region/Ahern", url,
"secondlife:///app/region/Ahern",
"Ahern");
testLabel("Render /app/region/Ahern within context", url,
"XXX secondlife:///app/region/Ahern XXX",
"Ahern");
testLabel("Render /app/region/Product%20Engine/", url,
"secondlife:///app/region/Product%20Engine/",
"Product Engine");
testLabel("Render /app/region/Product%20Engine", url,
"secondlife:///app/region/Product%20Engine",
"Product Engine");
// Location parsing texts.
testLocation("Location /app/region/Ahern/50/50/50/", url,
"secondlife:///app/region/Ahern/50/50/50/",
"Ahern");
testLocation("Location /app/region/Product%20Engine", url,
"secondlife:///app/region/Product%20Engine",
"Product Engine");
}
}

View File

@ -46,6 +46,7 @@ public:
virtual ~LLInspectToast();
/*virtual*/ void onOpen(const LLSD& notification_id);
/*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
private:
void onToastDestroy(LLToast * toast);
@ -73,6 +74,7 @@ LLInspectToast::~LLInspectToast()
LLTransientFloaterMgr::getInstance()->removeControlView(this);
}
// virtual
void LLInspectToast::onOpen(const LLSD& notification_id)
{
LLInspect::onOpen(notification_id);
@ -103,6 +105,15 @@ void LLInspectToast::onOpen(const LLSD& notification_id)
LLUI::positionViewNearMouse(this);
}
// virtual
BOOL LLInspectToast::handleToolTip(S32 x, S32 y, MASK mask)
{
// We don't like the way LLInspect handles tooltips
// (black tooltips look weird),
// so force using the default implementation (STORM-511).
return LLFloater::handleToolTip(x, y, mask);
}
void LLInspectToast::onToastDestroy(LLToast * toast)
{
closeFloater(false);

View File

@ -341,10 +341,11 @@ LLPanelAvatarNotes::~LLPanelAvatarNotes()
if(getAvatarId().notNull())
{
LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this);
if(LLVoiceClient::instanceExists())
{
LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
}
}
if(LLVoiceClient::instanceExists())
{
LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
}
}
@ -758,10 +759,11 @@ LLPanelAvatarProfile::~LLPanelAvatarProfile()
if(getAvatarId().notNull())
{
LLAvatarTracker::instance().removeParticularFriendObserver(getAvatarId(), this);
if(LLVoiceClient::instanceExists())
{
LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
}
}
if(LLVoiceClient::instanceExists())
{
LLVoiceClient::getInstance()->removeObserver((LLVoiceClientStatusObserver*)this);
}
}

View File

@ -140,22 +140,25 @@ void LLRemoteParcelInfoProcessor::processParcelInfoReply(LLMessageSystem* msg, v
typedef std::vector<observer_multimap_t::iterator> deadlist_t;
deadlist_t dead_iters;
observer_multimap_t::iterator oi;
observer_multimap_t::iterator start = observers.lower_bound(parcel_data.parcel_id);
observer_multimap_t::iterator oi = observers.lower_bound(parcel_data.parcel_id);
observer_multimap_t::iterator end = observers.upper_bound(parcel_data.parcel_id);
for (oi = start; oi != end; ++oi)
while (oi != end)
{
LLRemoteParcelInfoObserver * observer = oi->second.get();
// increment the loop iterator now since it may become invalid below
observer_multimap_t::iterator cur_oi = oi++;
LLRemoteParcelInfoObserver * observer = cur_oi->second.get();
if(observer)
{
// may invalidate cur_oi if the observer removes itself
observer->processParcelInfo(parcel_data);
}
else
{
// the handle points to an expired observer, so don't keep it
// around anymore
dead_iters.push_back(oi);
dead_iters.push_back(cur_oi);
}
}

View File

@ -77,6 +77,7 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
from << from_name << "/" << groupData.mName;
LLTextBox* pTitleText = getChild<LLTextBox>("title");
pTitleText->setValue(from.str());
pTitleText->setToolTip(from.str());
//message subject
const std::string& subject = payload["subject"].asString();

View File

@ -185,7 +185,7 @@
</expandable_text>
</panel>
<text
follows="left|top"
follows="left|top|right"
height="15"
font.style="BOLD"
font="SansSerifMedium"
@ -200,7 +200,7 @@
use_ellipses="true"
/>
<text
follows="left|top"
follows="left|top|right"
font.style="BOLD"
height="10"
layout="topleft"
@ -213,7 +213,7 @@
<text_editor
allow_scroll="false"
bg_visible="false"
follows="left|top"
follows="left|top|right"
h_pad="0"
height="15"
layout="topleft"
@ -226,7 +226,7 @@
width="300"
word_wrap="true" />
<text
follows="left|top"
follows="left|top|right"
font.style="BOLD"
height="15"
layout="topleft"
@ -250,7 +250,7 @@
<text_editor
allow_scroll="false"
bg_visible="false"
follows="left|top"
follows="left|top|right"
h_pad="0"
height="28"
layout="topleft"
@ -266,7 +266,7 @@
Linden.
</text_editor>
<text
follows="left|top"
follows="left|top|right"
font.style="BOLD"
height="15"
layout="topleft"
@ -277,7 +277,7 @@
value="Partner:"
width="300" />
<panel
follows="left|top"
follows="left|top|right"
height="15"
layout="topleft"
left="10"
@ -285,7 +285,7 @@
top_pad="0"
width="300">
<text
follows="left|top"
follows="left|top|right"
height="10"
initial_value="(retrieving)"
layout="topleft"
@ -297,7 +297,7 @@
width="300" />
</panel>
<text
follows="left|top"
follows="left|top|right"
font.style="BOLD"
height="13"
layout="topleft"

View File

@ -82,7 +82,7 @@
control_name="AllowMultipleViewers"
follows="top|left"
height="15"
label="Allow Multiple Viewer"
label="Allow Multiple Viewers"
layout="topleft"
left="30"
name="allow_multiple_viewer_check"