Merge Viewer-Bear

master
Ansariel 2015-08-22 03:13:17 +02:00
commit 5fe09cb64d
166 changed files with 2209 additions and 1025 deletions

View File

@ -443,6 +443,10 @@ BOOL LLImageBMP::decodeColorMask32( U8* dst, U8* src )
mBitfieldMask[2] = 0x000000FF;
}
if (getWidth() * getHeight() * 4 > getDataSize() - mBitmapOffset)
{ //here we have situation when data size in src less than actually needed
return FALSE;
}
S32 src_row_span = getWidth() * 4;
S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4
@ -476,6 +480,11 @@ BOOL LLImageBMP::decodeColorTable8( U8* dst, U8* src )
S32 src_row_span = getWidth() * 1;
S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4
if ((getWidth() * getHeight()) + getHeight() * alignment_bytes > getDataSize() - mBitmapOffset)
{ //here we have situation when data size in src less than actually needed
return FALSE;
}
for( S32 row = 0; row < getHeight(); row++ )
{
for( S32 col = 0; col < getWidth(); col++ )
@ -501,6 +510,11 @@ BOOL LLImageBMP::decodeTruecolor24( U8* dst, U8* src )
S32 src_row_span = getWidth() * 3;
S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4
if ((getWidth() * getHeight() * 3) + getHeight() * alignment_bytes > getDataSize() - mBitmapOffset)
{ //here we have situation when data size in src less than actually needed
return FALSE;
}
for( S32 row = 0; row < getHeight(); row++ )
{
for( S32 col = 0; col < getWidth(); col++ )

View File

@ -447,7 +447,13 @@ BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaqu
// Origin is the bottom left
U8* dst = raw_image->getData();
U8* src = getData() + mDataOffset;
S32 pixels = getWidth() * getHeight();
if (pixels * (mIs15Bit ? 2 : getComponents()) > getDataSize() - mDataOffset)
{ //here we have situation when data size in src less than actually needed
return FALSE;
}
if (getComponents() == 4)
{

View File

@ -193,8 +193,12 @@ const U8 LL_SCULPT_TYPE_MESH = 5;
const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE |
LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH;
// for value checks, assign new value after adding new types
const U8 LL_SCULPT_TYPE_MAX = LL_SCULPT_TYPE_MESH;
const U8 LL_SCULPT_FLAG_INVERT = 64;
const U8 LL_SCULPT_FLAG_MIRROR = 128;
const U8 LL_SCULPT_FLAG_MASK = LL_SCULPT_FLAG_INVERT | LL_SCULPT_FLAG_MIRROR;
const S32 LL_SCULPT_MESH_MAX_FACES = 8;

View File

@ -146,6 +146,8 @@ void LLPluginClassMedia::reset()
mClickTarget.clear();
mClickUUID.clear();
mStatusCode = 0;
mClickEnforceTarget = false;
// media_time class
mCurrentTime = 0.0f;
@ -1368,6 +1370,12 @@ void LLPluginClassMedia::addCertificateFilePath(const std::string& path)
sendMessage(message);
}
void LLPluginClassMedia::setOverrideClickTarget(const std::string &target)
{
mClickEnforceTarget = true;
mOverrideClickTarget = target;
}
void LLPluginClassMedia::crashPlugin()
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash");

View File

@ -249,6 +249,13 @@ public:
// This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE
std::string getClickUUID() const { return mClickUUID; };
// mClickTarget is received from message and governs how link will be opened
// use this to enforce your own way of opening links inside plugins
void setOverrideClickTarget(const std::string &target);
void resetOverrideClickTarget() { mClickEnforceTarget = false; };
bool isOverrideClickTarget() const { return mClickEnforceTarget; }
std::string getOverrideClickTarget() const { return mOverrideClickTarget; };
// These are valid during MEDIA_EVENT_DEBUG_MESSAGE
std::string getDebugMessageText() const { return mDebugMessageText; };
std::string getDebugMessageLevel() const { return mDebugMessageLevel; };
@ -404,6 +411,8 @@ protected:
std::string mClickNavType;
std::string mClickTarget;
std::string mClickUUID;
bool mClickEnforceTarget;
std::string mOverrideClickTarget;
std::string mDebugMessageText;
std::string mDebugMessageLevel;
S32 mGeometryX;

View File

@ -328,9 +328,9 @@ S32 LLPrimitive::setTEMaterialID(const U8 index, const LLMaterialID& pMaterialID
return mTextureList.setMaterialID(index, pMaterialID);
}
S32 LLPrimitive::setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams)
S32 LLPrimitive::setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer)
{
return mTextureList.setMaterialParams(index, pMaterialParams);
return mTextureList.setMaterialParams(index, pMaterialParams, isInitFromServer);
}
LLMaterialPtr LLPrimitive::getTEMaterialParams(const U8 index)
@ -1880,9 +1880,12 @@ BOOL LLSculptParams::pack(LLDataPacker &dp) const
BOOL LLSculptParams::unpack(LLDataPacker &dp)
{
dp.unpackUUID(mSculptTexture, "texture");
dp.unpackU8(mSculptType, "type");
U8 type;
LLUUID id;
dp.unpackUUID(id, "texture");
dp.unpackU8(type, "type");
setSculptTexture(id, type);
return TRUE;
}
@ -1907,8 +1910,7 @@ bool LLSculptParams::operator==(const LLNetworkData& data) const
void LLSculptParams::copy(const LLNetworkData& data)
{
const LLSculptParams *param = (LLSculptParams*)&data;
mSculptTexture = param->mSculptTexture;
mSculptType = param->mSculptType;
setSculptTexture(param->mSculptTexture, param->mSculptType);
}
@ -1926,20 +1928,38 @@ LLSD LLSculptParams::asLLSD() const
bool LLSculptParams::fromLLSD(LLSD& sd)
{
const char *w;
w = "texture";
if (sd.has(w))
{
setSculptTexture( sd[w] );
} else goto fail;
U8 type;
w = "type";
if (sd.has(w))
{
setSculptType( (U8)sd[w].asInteger() );
} else goto fail;
type = sd[w].asInteger();
}
else return false;
w = "texture";
if (sd.has(w))
{
setSculptTexture(sd[w], type);
}
else return false;
return true;
fail:
return false;
}
void LLSculptParams::setSculptTexture(const LLUUID& texture_id, U8 sculpt_type)
{
U8 type = sculpt_type & LL_SCULPT_TYPE_MASK;
U8 flags = sculpt_type & LL_SCULPT_FLAG_MASK;
if (sculpt_type != (type | flags) || type > LL_SCULPT_TYPE_MAX)
{
mSculptTexture.set(SCULPT_DEFAULT_TEXTURE);
mSculptType = LL_SCULPT_TYPE_SPHERE;
}
else
{
mSculptTexture = texture_id;
mSculptType = sculpt_type;
}
}
//============================================================================

View File

@ -267,9 +267,8 @@ public:
operator LLSD() const { return asLLSD(); }
bool fromLLSD(LLSD& sd);
void setSculptTexture(const LLUUID& id) { mSculptTexture = id; }
void setSculptTexture(const LLUUID& texture_id, U8 sculpt_type);
LLUUID getSculptTexture() const { return mSculptTexture; }
void setSculptType(U8 type) { mSculptType = type; }
U8 getSculptType() const { return mSculptType; }
};
@ -393,7 +392,7 @@ public:
virtual S32 setTEMediaFlags(const U8 te, const U8 flags);
virtual S32 setTEGlow(const U8 te, const F32 glow);
virtual S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID);
virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams);
virtual S32 setTEMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer);
virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed
virtual void setTESelected(const U8 te, bool sel);

View File

@ -368,11 +368,18 @@ S32 LLPrimTextureList::setMaterialID(const U8 index, const LLMaterialID& pMateri
return TEM_CHANGE_NONE;
}
S32 LLPrimTextureList::setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams)
S32 LLPrimTextureList::setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer)
{
if (index < mEntryList.size())
{
return mEntryList[index]->setMaterialParams(pMaterialParams);
if (!isInitFromServer && mEntryList[index]->isMatParamsInitFromServer())
{
return TEM_CHANGE_NONE;
}
else
{
return mEntryList[index]->setMaterialParams(pMaterialParams);
}
}
return TEM_CHANGE_NONE;
}

View File

@ -105,7 +105,7 @@ public:
S32 setMediaFlags(const U8 index, const U8 media_flags);
S32 setGlow(const U8 index, const F32 glow);
S32 setMaterialID(const U8 index, const LLMaterialID& pMaterialID);
S32 setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams);
S32 setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams, bool isInitFromServer);
LLMaterialPtr getMaterialParams(const U8 index);

View File

@ -63,6 +63,7 @@ LLTextureEntry::LLTextureEntry()
: mMediaEntry(NULL)
, mSelected(false)
, mMaterialUpdatePending(false)
, mInitMatParamsFromServer(false)
{
init(LLUUID::null,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);
}
@ -71,6 +72,7 @@ LLTextureEntry::LLTextureEntry(const LLUUID& tex_id)
: mMediaEntry(NULL)
, mSelected(false)
, mMaterialUpdatePending(false)
, mInitMatParamsFromServer(false)
{
init(tex_id,1.f,1.f,0.f,0.f,0.f,DEFAULT_BUMP_CODE);
}
@ -79,6 +81,7 @@ LLTextureEntry::LLTextureEntry(const LLTextureEntry &rhs)
: mMediaEntry(NULL)
, mSelected(false)
, mMaterialUpdatePending(false)
, mInitMatParamsFromServer(false)
{
mID = rhs.mID;
mScaleS = rhs.mScaleS;
@ -562,6 +565,7 @@ S32 LLTextureEntry::setMaterialParams(const LLMaterialPtr pMaterialParams)
mMaterialUpdatePending = true;
}
mMaterial = pMaterialParams;
this->mInitMatParamsFromServer = TRUE;
return TEM_CHANGE_TEXTURE;
}

View File

@ -156,6 +156,8 @@ public:
const LLMaterialID& getMaterialID() const { return mMaterialID; };
const LLMaterialPtr getMaterialParams() const { return mMaterial; };
bool isMatParamsInitFromServer() const { return mInitMatParamsFromServer; };
// *NOTE: it is possible for hasMedia() to return true, but getMediaData() to return NULL.
// CONVERSELY, it is also possible for hasMedia() to return false, but getMediaData()
// to NOT return NULL.
@ -213,6 +215,8 @@ protected:
bool mMaterialUpdatePending;
LLMaterialID mMaterialID;
LLMaterialPtr mMaterial;
bool mInitMatParamsFromServer; // Flag to identification when material paramas initialized from
// Note the media data is not sent via the same message structure as the rest of the TE
LLMediaEntry* mMediaEntry; // The media data for the face

View File

@ -153,7 +153,7 @@ void LLDockableFloater::setVisible(BOOL visible)
mDockControl.get()->repositionDockable();
}
if (visible)
if (visible && !isMinimized())
{
LLFloater::setFrontmost(getAutoFocus());
}

View File

@ -1581,31 +1581,37 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection)
LLFolderView* root = getRoot();
for (std::vector<LLFolderViewItem*>::iterator it = items_to_select_forward.begin(), end_it = items_to_select_forward.end();
BOOL selection_reverse = new_selection->isSelected(); //indication that some elements are being deselected
// array always go from 'will be selected' to ' will be unselected', iterate
// in opposite direction to simplify identification of 'point of origin' in
// case it is in the list we are working with
for (std::vector<LLFolderViewItem*>::reverse_iterator it = items_to_select_forward.rbegin(), end_it = items_to_select_forward.rend();
it != end_it;
++it)
{
LLFolderViewItem* item = *it;
if (item->isSelected())
BOOL selected = item->isSelected();
if (!selection_reverse && selected)
{
root->removeFromSelectionList(item);
// it is our 'point of origin' where we shift/expand from
// don't deselect it
selection_reverse = TRUE;
}
else
{
item->selectItem();
root->changeSelection(item, !selected);
}
root->addToSelectionList(item);
}
if (new_selection->isSelected())
if (selection_reverse)
{
root->removeFromSelectionList(new_selection);
// at some point we reversed selection, first element should be deselected
root->changeSelection(last_selected_item_from_cur, FALSE);
}
else
{
new_selection->selectItem();
}
root->addToSelectionList(new_selection);
// element we expand to should always be selected
root->changeSelection(new_selection, TRUE);
}

View File

@ -226,7 +226,6 @@ BOOL LLMenuItemGL::handleAcceleratorKey(KEY key, MASK mask)
BOOL LLMenuItemGL::handleHover(S32 x, S32 y, MASK mask)
{
setHover(TRUE);
getWindow()->setCursor(UI_CURSOR_ARROW);
return TRUE;
}
@ -247,6 +246,18 @@ BOOL LLMenuItemGL::handleRightMouseDown(S32 x, S32 y, MASK mask)
return LLUICtrl::handleRightMouseDown(x,y,mask);
}
void LLMenuItemGL::onMouseEnter(S32 x, S32 y, MASK mask)
{
setHover(TRUE);
LLUICtrl::onMouseEnter(x,y,mask);
}
void LLMenuItemGL::onMouseLeave(S32 x, S32 y, MASK mask)
{
setHover(FALSE);
LLUICtrl::onMouseLeave(x,y,mask);
}
//virtual
BOOL LLMenuItemGL::handleRightMouseUp(S32 x, S32 y, MASK mask)
{
@ -549,9 +560,6 @@ void LLMenuItemGL::draw( void )
gl_line_2d(x_begin, (MENU_ITEM_PADDING / 2) + 1, x_end, (MENU_ITEM_PADDING / 2) + 1);
}
}
// clear got hover every frame
setHover(FALSE);
}
BOOL LLMenuItemGL::setLabelArg( const std::string& key, const LLStringExplicit& text )
@ -1059,7 +1067,7 @@ void LLMenuItemBranchGL::onCommit( void )
// keyboard navigation automatically propagates highlight to sub-menu
// to facilitate fast menu control via jump keys
if (LLMenuGL::getKeyboardMode() && getBranch()&& !getBranch()->getHighlightedItem())
if (LLMenuGL::getKeyboardMode() && getBranch() && !getBranch()->getHighlightedItem())
{
getBranch()->highlightNextItem(NULL);
}
@ -1472,7 +1480,16 @@ BOOL LLMenuItemBranchDownGL::handleMouseDown( S32 x, S32 y, MASK mask )
{
// switch to mouse control mode
LLMenuGL::setKeyboardMode(FALSE);
onCommit();
if (getVisible() && isOpen())
{
LLMenuGL::sMenuContainer->hideMenus();
}
else
{
onCommit();
}
make_ui_sound("UISndClick");
return TRUE;
}
@ -1604,10 +1621,6 @@ void LLMenuItemBranchDownGL::draw( void )
gl_line_2d(x_begin, LABEL_BOTTOM_PAD_PIXELS, x_end, LABEL_BOTTOM_PAD_PIXELS);
}
}
// reset every frame so that we only show highlight
// when we get hover events on that frame
setHover(FALSE);
}
@ -3647,8 +3660,24 @@ BOOL LLMenuHolderGL::handleMouseDown( S32 x, S32 y, MASK mask )
BOOL handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL;
if (!handled)
{
// clicked off of menu, hide them all
hideMenus();
LLMenuGL* visible_menu = (LLMenuGL*)getVisibleMenu();
LLMenuItemGL* parent_menu = visible_menu ? visible_menu->getParentMenuItem() : NULL;
if (parent_menu && parent_menu->getVisible())
{
// don't hide menu if parent was hit
LLRect parent_rect;
parent_menu->localRectToOtherView(parent_menu->getLocalRect(), &parent_rect, this);
if (!parent_rect.pointInRect(x, y))
{
// clicked off of menu and parent, hide them all
hideMenus();
}
}
else
{
// no visible parent, clicked off of menu, hide them all
hideMenus();
}
}
return handled;
}

View File

@ -159,6 +159,10 @@ public:
virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask );
virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask );
virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks );
virtual void onMouseEnter(S32 x, S32 y, MASK mask);
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
virtual void draw( void );
BOOL getHover() const { return mGotHover; }

View File

@ -29,6 +29,7 @@
#include "linden_common.h"
#include "llsearcheditor.h"
#include "llkeyboard.h"
LLSearchEditor::LLSearchEditor(const LLSearchEditor::Params& p)
: LLUICtrl(p),
@ -166,4 +167,16 @@ void LLSearchEditor::handleKeystroke()
{
mKeystrokeCallback(this, getValue());
}
KEY key = gKeyboard->currentKey();
if (key == KEY_LEFT ||
key == KEY_RIGHT)
{
return;
}
if (mTextChangedCallback)
{
mTextChangedCallback(this, getValue());
}
}

View File

@ -82,12 +82,14 @@ public:
virtual void setFocus( BOOL b );
void setKeystrokeCallback( commit_callback_t cb ) { mKeystrokeCallback = cb; }
void setTextChangedCallback( commit_callback_t cb ) { mTextChangedCallback = cb; }
protected:
void onClearButtonClick(const LLSD& data);
virtual void handleKeystroke();
commit_callback_t mKeystrokeCallback;
commit_callback_t mTextChangedCallback;
LLLineEditor* mSearchEditor;
LLButton* mSearchButton;
LLButton* mClearButton;

View File

@ -37,6 +37,7 @@
#include "lltextparser.h"
#include "lltextutil.h"
#include "lltooltip.h"
#include "lltrans.h"
#include "lluictrl.h"
#include "llurlaction.h"
#include "llurlregistry.h"
@ -2265,9 +2266,17 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
// add icon before url if need
// <FS:Ansariel> Optional icon position
//LLTextUtil::processUrlMatch(&match, this, isContentTrusted() || match.isTrusted());
//if ((isContentTrusted() || match.isTrusted()) && !match.getIcon().empty() )
//{
// setLastSegmentToolTip(LLTrans::getString("TooltipSLIcon"));
//}
if (mIconPositioning == LLTextBaseEnums::LEFT || match.isTrusted())
{
LLTextUtil::processUrlMatch(&match, this, isContentTrusted() || match.isTrusted());
if ((isContentTrusted() || match.isTrusted()) && !match.getIcon().empty() )
{
setLastSegmentToolTip(LLTrans::getString("TooltipSLIcon"));
}
}
// </FS:Ansariel> Optional icon position
@ -2277,48 +2286,34 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
appendAndHighlightTextImpl(match.getLabel(), part, link_params,
input_params.is_name_slurl ? false : match.underlineOnHoverOnly());
// </FS:CR>
bool tooltip_required = !match.getTooltip().empty();
// <FS:Ansariel> Unfail URI display
// set the tooltip for the Url label (host part)
if (! match.getTooltip().empty())
// set the tooltip for the Url label
if (tooltip_required)
{
segment_set_t::iterator it = getSegIterContaining(getLength()-1);
if (it != mSegments.end())
{
LLTextSegmentPtr segment = *it;
segment->setToolTip(match.getTooltip());
}
setLastSegmentToolTip(match.getTooltip());
}
// </FS:Ansariel>
// show query part of url with gray color only for LLUrlEntryHTTP and LLUrlEntryHTTPNoProtocol url entries
// show query part of url with gray color only for LLUrlEntryHTTP url entries
std::string label = match.getQuery();
if (label.size())
{
// <FS:Ansariel> Custom URI query part color
//link_params.color = LLColor4::grey;
//link_params.readonly_color = LLColor4::grey;
//appendAndHighlightTextImpl(label, part, link_params, match.underlineOnHoverOnly());
static LLUIColor query_part_color = LLUIColorTable::getInstance()->getColor("UriQueryPartColor", LLColor4::grey);
link_params.color = query_part_color;
link_params.readonly_color = query_part_color;
// </FS:Ansariel>
// <FS:Ansariel> Unfail URI display; add tooltip for query part
//appendAndHighlightTextImpl(label, part, link_params, match.underlineOnHoverOnly());
appendAndHighlightTextImpl(label, part, link_params, input_params.is_name_slurl ? false : match.underlineOnHoverOnly());
//}
// set the tooltip for the Url label
if (! match.getTooltip().empty())
{
segment_set_t::iterator it = getSegIterContaining(getLength()-1);
if (it != mSegments.end())
// </FS:Ansariel>
// set the tooltip for the query part of url
if (tooltip_required)
{
LLTextSegmentPtr segment = *it;
segment->setToolTip(match.getTooltip());
setLastSegmentToolTip(match.getTooltip());
}
}
// <FS:Ansariel> Unfail URI display
}
// <FS:Ansariel> Optional icon position
if (mIconPositioning == LLTextBaseEnums::RIGHT && !match.isTrusted())
@ -2350,6 +2345,16 @@ void LLTextBase::appendTextImpl(const std::string &new_text, const LLStyle::Para
}
}
void LLTextBase::setLastSegmentToolTip(const std::string &tooltip)
{
segment_set_t::iterator it = getSegIterContaining(getLength()-1);
if (it != mSegments.end())
{
LLTextSegmentPtr segment = *it;
segment->setToolTip(tooltip);
}
}
static LLTrace::BlockTimerStatHandle FTM_APPEND_TEXT("Append Text");
void LLTextBase::appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params)
@ -3868,6 +3873,22 @@ S32 LLImageTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
return 0;
}
BOOL LLImageTextSegment::handleToolTip(S32 x, S32 y, MASK mask)
{
if (!mTooltip.empty())
{
LLToolTipMgr::instance().show(mTooltip);
return TRUE;
}
return FALSE;
}
void LLImageTextSegment::setToolTip(const std::string& tooltip)
{
mTooltip = tooltip;
}
F32 LLImageTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
{
if ( (start >= 0) && (end <= mEnd - mStart))

View File

@ -241,9 +241,15 @@ public:
S32 getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const;
F32 draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect);
/*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
/*virtual*/ void setToolTip(const std::string& tooltip);
private:
class LLTextBase& mEditor;
LLStyleConstSP mStyle;
protected:
std::string mTooltip;
};
typedef LLPointer<LLTextSegment> LLTextSegmentPtr;
@ -428,6 +434,8 @@ public:
const std::string& getLabel() { return mLabel.getString(); }
const LLWString& getWlabel() { return mLabel.getWString();}
void setLastSegmentToolTip(const std::string &tooltip);
/**
* If label is set, draws text label (which is LLLabelTextSegment)
* that is visible when no user text provided

View File

@ -219,10 +219,10 @@ std::string LLUrlEntryBase::urlToGreyQuery(const std::string &url) const
LLUriParser up(url);
// </FS:Ansariel>
std::string query;
std::string label;
up.extractParts();
up.glueSecond(query);
up.glueFirst(label);
std::string query = url.substr(label.size());
// <FS:Ansariel> Unfail URI display
//return query;
return unescapeUrl(query);
@ -249,8 +249,8 @@ LLUrlEntryHTTP::LLUrlEntryHTTP()
: LLUrlEntryBase()
{
// <FS:Ansariel> FIRE-1715: Links using FTP protocol are not recognized
//mPattern = boost::regex("https?://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?/?\\S*",
mPattern = boost::regex("(https?|ftp)://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?/?\\S*",
//mPattern = boost::regex("https?://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?\\.[a-z](:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?/?\\S*",
mPattern = boost::regex("(https?|ftp)://([-\\w\\.]+)+(:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?\\.[a-z](:\\d+)?(:\\w+)?(@\\d+)?(@\\w+)?/?\\S*",
// </FS:Ansariel>
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_http.xml";
@ -315,51 +315,6 @@ std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string) const
return getUrlFromWikiLink(string);
}
//
// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com
//
LLUrlEntryHTTPNoProtocol::LLUrlEntryHTTPNoProtocol()
: LLUrlEntryBase()
{
mPattern = boost::regex("("
// <FS:Ansariel> FIRE-1715: Links using FTP protocol are not recognized
//"\\bwww\\.\\S+\\.\\S+" // i.e. www.FOO.BAR
"\\b(www|ftp)\\.\\S+\\.\\S+" // i.e. www.FOO.BAR
// </FS:Ansariel>
"|" // or
"(?<!@)\\b[^[:space:]:@/>]+\\.(?:com|net|edu|org)([/:][^[:space:]<]*)?\\b" // i.e. FOO.net
")",
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_http.xml";
mTooltip = LLTrans::getString("TooltipHttpUrl");
}
std::string LLUrlEntryHTTPNoProtocol::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
return urlToLabelWithGreyQuery(url);
}
std::string LLUrlEntryHTTPNoProtocol::getQuery(const std::string &url) const
{
return urlToGreyQuery(url);
}
std::string LLUrlEntryHTTPNoProtocol::getUrl(const std::string &string) const
{
if (string.find("://") == std::string::npos)
{
return "http://" + escapeUrl(string);
}
return escapeUrl(string);
}
std::string LLUrlEntryHTTPNoProtocol::getTooltip(const std::string &url) const
{
// <FS:Ansariel> Unfail URI display
//return unescapeUrl(url);
return mTooltip;
// </FS:Ansariel>
}
LLUrlEntryInvalidSLURL::LLUrlEntryInvalidSLURL()
: LLUrlEntryBase()
@ -531,7 +486,7 @@ std::string LLUrlEntrySLURL::getLocation(const std::string &url) const
//
LLUrlEntrySecondlifeURL::LLUrlEntrySecondlifeURL()
{
mPattern = boost::regex("(https?://)?([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(:\\d{1,5})?\\/\\S*",
mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(:\\d{1,5})?\\/\\S*",
boost::regex::perl|boost::regex::icase);
mIcon = "Hand";
@ -572,7 +527,7 @@ std::string LLUrlEntrySecondlifeURL::getTooltip(const std::string &url) const
//
LLUrlEntrySimpleSecondlifeURL::LLUrlEntrySimpleSecondlifeURL()
{
mPattern = boost::regex("(https?://)?([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(?!\\S)",
mPattern = boost::regex("https?://([-\\w\\.]*\\.)?(secondlife|lindenlab)\\.com(?!\\S)",
boost::regex::perl|boost::regex::icase);
mIcon = "Hand";
@ -1546,9 +1501,43 @@ std::string LLUrlEntryJira::getUrl(const std::string &string) const
}
}
//
// LLUrlEntryEmail Describes a generic mailto: Urls
//
LLUrlEntryEmail::LLUrlEntryEmail()
: LLUrlEntryBase()
{
mPattern = boost::regex("(mailto:)?[\\w\\.\\-]+@[\\w\\.\\-]+\\.[a-z]{2,6}",
boost::regex::perl | boost::regex::icase);
mMenuName = "menu_url_email.xml";
mTooltip = LLTrans::getString("TooltipEmail");
}
std::string LLUrlEntryEmail::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
int pos = url.find("mailto:");
if (pos == std::string::npos)
{
return escapeUrl(url);
}
std::string ret = escapeUrl(url.substr(pos + 7, url.length() - pos + 8));
return ret;
}
std::string LLUrlEntryEmail::getUrl(const std::string &string) const
{
if (string.find("mailto:") == std::string::npos)
{
return "mailto:" + escapeUrl(string);
}
return escapeUrl(string);
}
LLUrlEntryExperienceProfile::LLUrlEntryExperienceProfile()
{
mPattern = boost::regex(APP_HEADER_REGEX "/experience/[\\da-f-]+/\\w+\\S*",
mPattern = boost::regex(APP_HEADER_REGEX "/experience/[\\da-f-]+/profile",
boost::regex::perl|boost::regex::icase);
mIcon = "Generic_Experience";
mMenuName = "menu_url_experience.xml";

View File

@ -157,19 +157,6 @@ public:
/*virtual*/ std::string getUrl(const std::string &string) const;
};
///
/// LLUrlEntryHTTPNoProtocol Describes generic Urls like www.google.com
///
class LLUrlEntryHTTPNoProtocol : public LLUrlEntryBase
{
public:
LLUrlEntryHTTPNoProtocol();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getQuery(const std::string &url) const;
/*virtual*/ std::string getUrl(const std::string &string) const;
/*virtual*/ std::string getTooltip(const std::string &url) const;
};
class LLUrlEntryInvalidSLURL : public LLUrlEntryBase
{
public:
@ -549,6 +536,17 @@ public:
/*virtual*/ std::string getIcon(const std::string &url);
};
///
/// LLUrlEntryEmail Describes a generic mailto: Urls
///
class LLUrlEntryEmail : public LLUrlEntryBase
{
public:
LLUrlEntryEmail();
/*virtual*/ std::string getLabel(const std::string &url, const LLUrlLabelCallback &cb);
/*virtual*/ std::string getUrl(const std::string &string) const;
};
///
/// LLUrlEntryJira Describes Jira issue names -KC
///

View File

@ -90,9 +90,7 @@ LLUrlRegistry::LLUrlRegistry()
registerUrl(new LLUrlEntrySL());
mUrlEntrySLLabel = new LLUrlEntrySLLabel();
registerUrl(mUrlEntrySLLabel);
// most common pattern is a URL without any protocol,
// e.g., "secondlife.com"
registerUrl(new LLUrlEntryHTTPNoProtocol());
registerUrl(new LLUrlEntryEmail());
// parse jira issue names to links -KC
registerUrl(new LLUrlEntryJira());
}
@ -171,9 +169,6 @@ static bool stringHasUrl(const std::string &text)
return (text.find("://") != std::string::npos ||
// text.find("www.") != std::string::npos ||
// text.find(".com") != std::string::npos ||
// text.find(".net") != std::string::npos ||
// text.find(".edu") != std::string::npos ||
// text.find(".org") != std::string::npos ||
// allow ALLCAPS urls -KC
boost::ifind_first(text, "www.") ||
boost::ifind_first(text, ".com") ||
@ -181,7 +176,8 @@ static bool stringHasUrl(const std::string &text)
boost::ifind_first(text, ".edu") ||
boost::ifind_first(text, ".org") ||
text.find("<nolink>") != std::string::npos ||
text.find("<icon") != std::string::npos);
text.find("<icon") != std::string::npos ||
text.find("@") != std::string::npos);
}
static bool stringHasJira(const std::string &text)
@ -278,9 +274,40 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
// did we find a match? if so, return its details in the match object
if (match_entry)
{
// Skip if link is an email with an empty username (starting with @). See MAINT-5371.
if (match_start > 0 && text.substr(match_start - 1, 1) == "@")
return false;
// fill in the LLUrlMatch object and return it
std::string url = text.substr(match_start, match_end - match_start + 1);
LLUrlEntryBase *stripped_entry = NULL;
if(LLStringUtil::containsNonprintable(url))
{
LLStringUtil::stripNonprintable(url);
std::vector<LLUrlEntryBase *>::iterator iter;
for (iter = mUrlEntry.begin(); iter != mUrlEntry.end(); ++iter)
{
LLUrlEntryBase *url_entry = *iter;
U32 start = 0, end = 0;
if (matchRegex(url.c_str(), url_entry->getPattern(), start, end))
{
if (mLLUrlEntryInvalidSLURL == *iter)
{
if(url_entry && url_entry->isSLURLvalid(url))
{
continue;
}
}
stripped_entry = url_entry;
break;
}
}
}
// <FS:Ansariel> Fix the "nolink>" fail; Fix from Alchemy viewer, courtesy of Drake Arconis
//if (match_entry == mUrlEntryTrusted)
//{
@ -298,10 +325,12 @@ bool LLUrlRegistry::findUrl(const std::string &text, LLUrlMatch &match, const LL
}
// </FS:Ansariel>
std::string url_label = stripped_entry? stripped_entry->getLabel(url, cb) : match_entry->getLabel(url, cb);
std::string url_query = stripped_entry? stripped_entry->getQuery(url) : match_entry->getQuery(url);
match.setValues(match_start, match_end,
match_entry->getUrl(url),
match_entry->getLabel(url, cb),
match_entry->getQuery(url),
url_label,
url_query,
match_entry->getTooltip(url),
match_entry->getIcon(url),
match_entry->getStyle(),

View File

@ -651,79 +651,6 @@ namespace tut
template<> template<>
void object::test<11>()
{
//
// test LLUrlEntryHTTPNoProtocol - general URLs without a protocol
//
LLUrlEntryHTTPNoProtocol url;
testRegex("naked .com URL", url,
"see google.com",
"http://google.com");
testRegex("naked .org URL", url,
"see en.wikipedia.org for details",
"http://en.wikipedia.org");
testRegex("naked .net URL", url,
"example.net",
"http://example.net");
testRegex("naked .edu URL (2 instances)", url,
"MIT web site is at web.mit.edu and also www.mit.edu",
"http://web.mit.edu");
testRegex("don't match e-mail addresses", url,
"test@lindenlab.com",
"");
testRegex(".com URL with path", url,
"see secondlife.com/status for grid status",
"http://secondlife.com/status");
testRegex(".com URL with port", url,
"secondlife.com:80",
"http://secondlife.com:80");
testRegex(".com URL with port and path", url,
"see secondlife.com:80/status",
"http://secondlife.com:80/status");
testRegex("www.*.com URL with port and path", url,
"see www.secondlife.com:80/status",
"http://www.secondlife.com:80/status");
testRegex("invalid .com URL [1]", url,
"..com",
"");
testRegex("invalid .com URL [2]", url,
"you.come",
"");
testRegex("invalid .com URL [3]", url,
"recommended",
"");
testRegex("invalid .edu URL", url,
"hi there scheduled maitenance has begun",
"");
testRegex("invalid .net URL", url,
"foo.netty",
"");
testRegex("XML tags around URL [1]", url,
"<foo>secondlife.com</foo>",
"http://secondlife.com");
testRegex("XML tags around URL [2]", url,
"<foo>secondlife.com/status?bar=1</foo>",
"http://secondlife.com/status?bar=1");
}
template<> template<>
void object::test<12>()
{
//
// test LLUrlEntryNoLink - turn off hyperlinking
@ -752,7 +679,7 @@ namespace tut
}
template<> template<>
void object::test<13>()
void object::test<12>()
{
//
// test LLUrlEntryRegion - secondlife:///app/region/<location> URLs
@ -860,4 +787,101 @@ namespace tut
"secondlife:///app/region/Product%20Engine",
"Product Engine");
}
template<> template<>
void object::test<13>()
{
//
// test LLUrlEntryemail - general emails
//
LLUrlEntryEmail url;
// Regex tests.
testRegex("match e-mail addresses", url,
"test@lindenlab.com",
"mailto:test@lindenlab.com");
testRegex("match e-mail addresses with mailto: prefix", url,
"mailto:test@lindenlab.com",
"mailto:test@lindenlab.com");
testRegex("match e-mail addresses with different domains", url,
"test@foo.org.us",
"mailto:test@foo.org.us");
testRegex("match e-mail addresses with different domains", url,
"test@foo.bar",
"mailto:test@foo.bar");
testRegex("don't match incorrect e-mail addresses", url,
"test @foo.com",
"");
testRegex("don't match incorrect e-mail addresses", url,
"test@ foo.com",
"");
}
template<> template<>
void object::test<14>()
{
//
// test LLUrlEntrySimpleSecondlifeURL - http://*.secondlife.com/* and http://*lindenlab.com/* urls
//
LLUrlEntrySecondlifeURL url;
testRegex("match urls with protocol", url,
"this url should match http://lindenlab.com/products/second-life",
"http://lindenlab.com/products/second-life");
testRegex("match urls with protocol", url,
"search something https://marketplace.secondlife.com/products/search on marketplace and test the https",
"https://marketplace.secondlife.com/products/search");
testRegex("match urls with port", url,
"let's specify some port http://secondlife.com:888/status",
"http://secondlife.com:888/status");
testRegex("don't match urls w/o protocol", url,
"looks like an url something www.marketplace.secondlife.com/products but no https prefix",
"");
testRegex("but with a protocol www is fine", url,
"so let's add a protocol http://www.marketplace.secondlife.com:8888/products",
"http://www.marketplace.secondlife.com:8888/products");
testRegex("don't match urls w/o protocol", url,
"and even no www something secondlife.com/status",
"");
}
template<> template<>
void object::test<15>()
{
//
// test LLUrlEntrySimpleSecondlifeURL - http://*.secondlife.com and http://*lindenlab.com urls
//
LLUrlEntrySimpleSecondlifeURL url;
testRegex("match urls with a protocol", url,
"this url should match http://lindenlab.com",
"http://lindenlab.com");
testRegex("match urls with a protocol", url,
"search something https://marketplace.secondlife.com on marketplace and test the https",
"https://marketplace.secondlife.com");
testRegex("don't match urls w/o protocol", url,
"looks like an url something www.marketplace.secondlife.com but no https prefix",
"");
testRegex("but with a protocol www is fine", url,
"so let's add a protocol http://www.marketplace.secondlife.com",
"http://www.marketplace.secondlife.com");
testRegex("don't match urls w/o protocol", url,
"and even no www something lindenlab.com",
"");
}
}

View File

@ -50,14 +50,14 @@ BOOL gDebugClicks = FALSE;
BOOL gDebugWindowProc = FALSE;
// <FS:Zi> Allow file: links to open folders, chat history etc. on Linux systems
//const S32 gURLProtocolWhitelistCount = 5;
//const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "data:", "mailto:" };
#if LL_LINUX
const S32 gURLProtocolWhitelistCount = 6;
const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "ftp:", "data:", "file:" };
const S32 gURLProtocolWhitelistCount = 7;
const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "ftp:", "data:", "mailto:", "file:" };
#else
// </FS:Zi>
const S32 gURLProtocolWhitelistCount = 5;
const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "ftp:", "data:" };
// <FS:Zi> Allow file: links to open folders, chat history etc. on Linux systems
const S32 gURLProtocolWhitelistCount = 6;
const std::string gURLProtocolWhitelist[] = { "secondlife:", "http:", "https:", "ftp:", "data:", "mailto:" };
#endif
// </FS:Zi>

View File

@ -53,6 +53,7 @@ bool runMainLoop();
void initMainLoop();
void cleanupViewer();
void handleUrl(const char* url);
void dispatchUrl(std::string url);
/* Defined in llwindowmacosx-objc.mm: */
int createNSApp(int argc, const char **argv);

View File

@ -29,6 +29,7 @@ out vec4 frag_data[3];
#define frag_data gl_FragData
#endif
uniform float minimum_alpha;
uniform sampler2D diffuseMap;
uniform sampler2D bumpMap;
@ -47,16 +48,23 @@ vec2 encode_normal(vec3 n)
void main()
{
vec3 col = vertex_color.rgb * texture2D(diffuseMap, vary_texcoord0.xy).rgb;
vec3 norm = texture2D(bumpMap, vary_texcoord0.xy).rgb * 2.0 - 1.0;
vec4 col = texture2D(diffuseMap, vary_texcoord0.xy);
if(col.a < minimum_alpha)
{
discard;
}
col *= vertex_color;
vec3 norm = texture2D(bumpMap, vary_texcoord0.xy).rgb * 2.0 - 1.0;
vec3 tnorm = vec3(dot(norm,vary_mat0),
vec3 tnorm = vec3(dot(norm,vary_mat0),
dot(norm,vary_mat1),
dot(norm,vary_mat2));
frag_data[0] = vec4(col, 0.0);
frag_data[1] = vertex_color.aaaa; // spec
//frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested
vec3 nvn = normalize(tnorm);
frag_data[2] = vec4(encode_normal(nvn.xyz), vertex_color.a, 0.0);
frag_data[0] = vec4(col.rgb, 0.0);
frag_data[1] = vertex_color.aaaa; // spec
//frag_data[1] = vec4(vec3(vertex_color.a), vertex_color.a+(1.0-vertex_color.a)*vertex_color.a); // spec - from former class3 - maybe better, but not so well tested
vec3 nvn = normalize(tnorm);
frag_data[2] = vec4(encode_normal(nvn), vertex_color.a, 0.0);
}

View File

@ -420,6 +420,10 @@ public:
//mFrom = LLTrans::getString("SECOND_LIFE");
//[FIX FIRE-2852] Changed function to find the right Gridname
mFrom = LLGridManager::getInstance()->getGridLabel();
if(!chat.mFromName.empty() && (mFrom != chat.mFromName))
{
mFrom += " (" + chat.mFromName + ")";
}
user_name->setValue(mFrom);
updateMinUserNameWidth();
}

View File

@ -365,7 +365,7 @@ LLSD FSCommon::populateGroupCount()
LLStringUtil::format_map_t args;
S32 groupcount = gAgent.mGroups.size();
args["[COUNT]"] = llformat("%d", groupcount);
args["[REMAINING]"] = llformat("%d", gMaxAgentGroups - groupcount);
args["[REMAINING]"] = llformat("%d", gMaxAgentGroups > groupcount ? gMaxAgentGroups - groupcount : 0);
LLUIString groupcountstring = LLTrans::getString((gMaxAgentGroups ? "groupcountstring" : "groupcountunlimitedstring"), args);
return LLSD(groupcountstring);
}

View File

@ -782,7 +782,7 @@ bool FSFloaterImport::processPrimCreated(LLViewerObject* object)
LL_DEBUGS("import") << "Setting materials" << LL_ENDL;
LLMaterial* mat = new LLMaterial();
mat->fromLLSD(*m_itr);
object->setTEMaterialParams(te, mat);
object->setTEMaterialParams(te, mat, false);
++te;
}
}
@ -796,7 +796,7 @@ bool FSFloaterImport::processPrimCreated(LLViewerObject* object)
if (mAssetMap[sculpt_params.getSculptTexture()].notNull())
{
sculpt_params.setSculptTexture(mAssetMap[sculpt_params.getSculptTexture()]);
sculpt_params.setSculptTexture(mAssetMap[sculpt_params.getSculptTexture()], sculpt_params.getSculptType());
LL_DEBUGS("import") << "Replaced " << prim["sculpt"]["texture"].asUUID().asString() << " with " << sculpt_params.getSculptTexture().asString() << LL_ENDL;
}

View File

@ -197,7 +197,12 @@ lbl_configure_default_lang:
StrCpy $LANGUAGE $0
# For silent installs, no language prompt, use default
# <FS:Ansariel> Disable autorun
#IfSilent 0 +3
#StrCpy $SKIP_AUTORUN "true"
#Goto lbl_return
IfSilent lbl_return
# </FS:Ansariel>
StrCmp $SKIP_DIALOGS "true" lbl_return
# <FS:Ansariel> Commented out; Warning in build log about not being used

View File

@ -3324,7 +3324,7 @@ BOOL LLAgent::isInGroup(const LLUUID& group_id, BOOL ignore_god_mode /* FALSE */
// This implementation should mirror LLAgentInfo::hasPowerInGroup
BOOL LLAgent::hasPowerInGroup(const LLUUID& group_id, U64 power) const
{
if (isGodlike())
if (isGodlikeWithoutAdminMenuFakery())
return true;
// GP_NO_POWERS can also mean no power is enough to grant an ability.

View File

@ -31,3 +31,4 @@
LLUUID gAgentID;
LLUUID gAgentSessionID;
std::string gAgentUsername;

View File

@ -30,5 +30,6 @@
extern LLUUID gAgentID;
extern LLUUID gAgentSessionID;
extern std::string gAgentUsername;
#endif

View File

@ -1980,6 +1980,10 @@ bool LLAppearanceMgr::canAddWearables(const uuid_vec_t& item_ids)
{
++n_clothes;
}
else if (item->getType() == LLAssetType::AT_BODYPART)
{
return isAgentAvatarValid();
}
else
{
LL_WARNS() << "Unexpected wearable type" << LL_ENDL;

View File

@ -3308,10 +3308,12 @@ bool LLAppViewer::initConfiguration()
//
gWindowTitle = LLVersionInfo::getChannelAndVersion(); // <FS:CR>
#if LL_DEBUG
gWindowTitle += std::string(" [DEBUG] ") + gArgs;
#else
gWindowTitle += std::string(" ") + gArgs;
gWindowTitle += std::string(" [DEBUG]")
#endif
if (!gArgs.empty())
{
gWindowTitle += std::string(" ") + gArgs;
}
LLStringUtil::truncate(gWindowTitle, 255);
//RN: if we received a URL, hand it off to the existing instance.
@ -5779,6 +5781,7 @@ void LLAppViewer::idle()
gIdleCallbacks.callFunctions();
gInventory.idleNotifyObservers();
LLAvatarTracker::instance().idleNotifyObservers();
}
// Metrics logging (LLViewerAssetStats, etc.)

View File

@ -62,9 +62,10 @@ namespace
// They are not used immediately by the app.
int gArgC;
char** gArgV;
LLAppViewerMacOSX* gViewerAppPtr;
LLAppViewerMacOSX* gViewerAppPtr = NULL;
void (*gOldTerminateHandler)() = NULL;
std::string gHandleSLURL;
}
static void exceptionTerminateHandler()
@ -107,7 +108,11 @@ bool initViewer()
{
LL_WARNS() << "Application init failed." << LL_ENDL;
}
else if (!gHandleSLURL.empty())
{
dispatchUrl(gHandleSLURL);
gHandleSLURL = "";
}
return ok;
}
@ -393,22 +398,31 @@ bool LLAppViewerMacOSX::getMasterSystemAudioMute()
void handleUrl(const char* url_utf8)
{
if (url_utf8)
if (url_utf8 && gViewerAppPtr)
{
std::string url = url_utf8;
// Safari 3.2 silently mangles secondlife:///app/ URLs into
// secondlife:/app/ (only one leading slash).
// Fix them up to meet the URL specification. JC
const std::string prefix = "secondlife:/app/";
std::string test_prefix = url.substr(0, prefix.length());
LLStringUtil::toLower(test_prefix);
if (test_prefix == prefix)
{
url.replace(0, prefix.length(), "secondlife:///app/");
}
LLMediaCtrl* web = NULL;
const bool trusted_browser = false;
LLURLDispatcher::dispatch(url, "", web, trusted_browser);
gHandleSLURL = "";
dispatchUrl(url_utf8);
}
else if (url_utf8)
{
gHandleSLURL = url_utf8;
}
}
void dispatchUrl(std::string url)
{
// Safari 3.2 silently mangles secondlife:///app/ URLs into
// secondlife:/app/ (only one leading slash).
// Fix them up to meet the URL specification. JC
const std::string prefix = "secondlife:/app/";
std::string test_prefix = url.substr(0, prefix.length());
LLStringUtil::toLower(test_prefix);
if (test_prefix == prefix)
{
url.replace(0, prefix.length(), "secondlife:///app/");
}
LLMediaCtrl* web = NULL;
const bool trusted_browser = false;
LLURLDispatcher::dispatch(url, "", web, trusted_browser);
}

View File

@ -105,7 +105,8 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id,
LLAvatarTracker::LLAvatarTracker() :
mTrackingData(NULL),
mTrackedAgentValid(false),
mModifyMask(0x0)
mModifyMask(0x0),
mIsNotifyObservers(FALSE)
{
}
@ -280,8 +281,8 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds)
<< "]" << LL_ENDL;
}
}
notifyObservers();
// do not notify observers here - list can be large so let it be done on idle.
return new_buddy_count;
}
@ -484,8 +485,25 @@ void LLAvatarTracker::removeObserver(LLFriendObserver* observer)
mObservers.end());
}
void LLAvatarTracker::idleNotifyObservers()
{
if (mModifyMask == LLFriendObserver::NONE && mChangedBuddyIDs.size() == 0)
{
return;
}
notifyObservers();
}
void LLAvatarTracker::notifyObservers()
{
if (mIsNotifyObservers)
{
// Don't allow multiple calls.
// new masks and ids will be processed later from idle.
return;
}
mIsNotifyObservers = TRUE;
observer_list_t observers(mObservers);
observer_list_t::iterator it = observers.begin();
observer_list_t::iterator end = observers.end();
@ -501,6 +519,7 @@ void LLAvatarTracker::notifyObservers()
mModifyMask = LLFriendObserver::NONE;
mChangedBuddyIDs.clear();
mIsNotifyObservers = FALSE;
}
void LLAvatarTracker::addParticularFriendObserver(const LLUUID& buddy_id, LLFriendObserver* observer)
@ -604,7 +623,7 @@ void LLAvatarTracker::notifyFriendPermissionObservers(const LLUUID& buddy_id)
// store flag for change
// and id of object change applies to
void LLAvatarTracker::addChangedMask(U32 mask, const LLUUID& referent)
{
{
mModifyMask |= mask;
if (referent.notNull())
{

View File

@ -144,6 +144,7 @@ public:
// observers left behind.
void addObserver(LLFriendObserver* observer);
void removeObserver(LLFriendObserver* observer);
void idleNotifyObservers();
void notifyObservers();
// Observers interested in updates of a particular avatar.
@ -216,6 +217,8 @@ private:
LLAvatarTracker(const LLAvatarTracker&);
bool operator==(const LLAvatarTracker&);
BOOL mIsNotifyObservers;
public:
// don't you dare create or delete this object
LLAvatarTracker();

View File

@ -393,6 +393,10 @@ public:
|| mSourceType == CHAT_SOURCE_SYSTEM)
{
mFrom = LLTrans::getString("SECOND_LIFE");
if(!chat.mFromName.empty() && (mFrom != chat.mFromName))
{
mFrom += " (" + chat.mFromName + ")";
}
user_name->setValue(mFrom);
updateMinUserNameWidth();
}

View File

@ -153,6 +153,7 @@ public:
* file name is conversation.log
*/
std::string getFileName();
LLConversation* findConversation(const LLIMModel::LLIMSession* session);
private:
@ -184,7 +185,7 @@ private:
void updateConversationName(const LLIMModel::LLIMSession* session, const std::string& name);
void updateOfflineIMs(const LLIMModel::LLIMSession* session, BOOL new_messages);
LLConversation* findConversation(const LLIMModel::LLIMSession* session);
typedef std::vector<LLConversation> conversations_vec_t;
std::vector<LLConversation> mConversations;

View File

@ -138,7 +138,24 @@ void LLConversationItem::buildParticipantMenuOptions(menuentry_vec_t& items, U32
items.push_back(std::string("im"));
items.push_back(std::string("offer_teleport"));
items.push_back(std::string("request_teleport"));
items.push_back(std::string("voice_call"));
if (getType() != CONV_SESSION_1_ON_1)
{
items.push_back(std::string("voice_call"));
}
else
{
LLVoiceChannel* voice_channel = LLIMModel::getInstance() ? LLIMModel::getInstance()->getVoiceChannel(this->getUUID()) : NULL;
if(voice_channel != LLVoiceChannel::getCurrentVoiceChannel())
{
items.push_back(std::string("voice_call"));
}
else
{
items.push_back(std::string("disconnect_from_voice"));
}
}
items.push_back(std::string("chat_history"));
items.push_back(std::string("separator_chat_history"));
items.push_back(std::string("add_friend"));

View File

@ -875,6 +875,7 @@ void LLDrawPoolBump::renderDeferred(S32 pass)
{
LLDrawInfo& params = **i;
gDeferredBumpProgram.setMinimumAlpha(params.mAlphaMaskCutoff);
LLDrawPoolBump::bindBumpMap(params, bump_channel);
pushBatch(params, mask, TRUE);
}

View File

@ -29,6 +29,7 @@
#include "llviewerprecompiledheaders.h"
#include "llexperienceassociationresponder.h"
#include "llexperiencecache.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llagent.h"
@ -47,7 +48,13 @@ void ExperienceAssociationResponder::fetchAssociatedExperience( const LLUUID& ob
void ExperienceAssociationResponder::fetchAssociatedExperience(LLSD& request, callback_t callback)
{
LLViewerRegion* region = gAgent.getRegion();
LLViewerObject* object = gObjectList.findObject(request["object-id"]);
if (!object)
{
LL_WARNS() << "Failed to find object with ID " << request["object-id"] << " in fetchAssociatedExperience" << LL_ENDL;
return;
}
LLViewerRegion* region = object->getRegion();
if (region)
{
std::string lookup_url=region->getCapability("GetMetadata");

View File

@ -385,9 +385,11 @@ LLFavoritesBarCtrl::LLFavoritesBarCtrl(const LLFavoritesBarCtrl::Params& p)
mShowDragMarker(FALSE),
mLandingTab(NULL),
mLastTab(NULL),
mTabsHighlightEnabled(TRUE)
, mUpdateDropDownItems(true)
, mRestoreOverflowMenu(false)
mTabsHighlightEnabled(TRUE),
mUpdateDropDownItems(true),
mRestoreOverflowMenu(false),
mGetPrevItems(true),
mItemsChangedTimer()
{
// Register callback for menus with current registrar (will be parent panel's registrar)
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Favorites.DoToSelected",
@ -680,6 +682,15 @@ void LLFavoritesBarCtrl::changed(U32 mask)
LLFavoritesOrderStorage::instance().getSLURL((*i)->getAssetUUID());
}
updateButtons();
if (!mItemsChangedTimer.getStarted())
{
mItemsChangedTimer.start();
}
else
{
mItemsChangedTimer.reset();
}
}
}
@ -714,6 +725,21 @@ void LLFavoritesBarCtrl::draw()
// Once drawn, mark this false so we won't draw it again (unless we hit the favorite bar again)
mShowDragMarker = FALSE;
}
if (mItemsChangedTimer.getStarted())
{
if (mItemsChangedTimer.getElapsedTimeF32() > 1.f)
{
LLFavoritesOrderStorage::instance().saveFavoritesRecord();
mItemsChangedTimer.stop();
}
}
if(!mItemsChangedTimer.getStarted() && LLFavoritesOrderStorage::instance().mUpdateRequired)
{
LLFavoritesOrderStorage::instance().mUpdateRequired = false;
mItemsChangedTimer.start();
}
}
const LLButton::Params& LLFavoritesBarCtrl::getButtonParams()
@ -744,6 +770,12 @@ void LLFavoritesBarCtrl::updateButtons()
return;
}
if(mGetPrevItems)
{
LLFavoritesOrderStorage::instance().mPrevFavorites = mItems;
mGetPrevItems = false;
}
const LLButton::Params& button_params = getButtonParams();
if(mItems.empty())
@ -883,6 +915,7 @@ void LLFavoritesBarCtrl::updateButtons()
{
mUpdateDropDownItems = false;
}
}
LLButton* LLFavoritesBarCtrl::createButton(const LLPointer<LLViewerInventoryItem> item, const LLButton::Params& button_params, S32 x_offset)
@ -954,9 +987,11 @@ BOOL LLFavoritesBarCtrl::postBuild()
BOOL LLFavoritesBarCtrl::collectFavoriteItems(LLInventoryModel::item_array_t &items)
{
if (mFavoriteFolderId.isNull())
return FALSE;
LLInventoryModel::cat_array_t cats;
LLIsType is_type(LLAssetType::AT_LANDMARK);
@ -1466,6 +1501,7 @@ void LLFavoritesBarCtrl::insertItem(LLInventoryModel::item_array_t& items, const
const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml";
const S32 LLFavoritesOrderStorage::NO_INDEX = -1;
bool LLFavoritesOrderStorage::mSaveOnExit = false;
void LLFavoritesOrderStorage::setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index)
{
@ -1502,19 +1538,23 @@ void LLFavoritesOrderStorage::getSLURL(const LLUUID& asset_id)
LL_DEBUGS("FavoritesBar") << "landmark for " << asset_id << " already loaded" << LL_ENDL;
onLandmarkLoaded(asset_id, lm);
}
return;
}
// static
std::string LLFavoritesOrderStorage::getStoredFavoritesFilename()
{
std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
// <FS:Ansariel> Favorites are stored in username.grid folder
//std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "");
return (user_dir.empty() ? ""
: gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
"stored_favorites_"
+ LLGridManager::getInstance()->getGrid()
+ ".xml")
);
// return (user_dir.empty() ? ""
// : gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,
// "stored_favorites_"
// + LLGridManager::getInstance()->getGrid()
// + ".xml")
// );
return gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
// <FS:Ansariel>
}
// static
@ -1536,15 +1576,19 @@ void LLFavoritesOrderStorage::destroyClass()
// LLFile::copy(old_filename,new_filename);
// LLFile::remove(old_filename);
//}
llifstream file;
// </FS:Ansariel>
if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin"))
std::string filename = getSavedOrderFileName();
file.open(filename.c_str());
if (file.is_open())
{
LLFavoritesOrderStorage::instance().saveFavoritesSLURLs();
}
else
{
LLFavoritesOrderStorage::instance().removeFavoritesRecordOfUser();
file.close();
LLFile::remove(filename);
if(mSaveOnExit)
{
LLFavoritesOrderStorage::instance().saveFavoritesRecord(true);
}
}
}
@ -1559,124 +1603,66 @@ std::string LLFavoritesOrderStorage::getSavedOrderFileName()
void LLFavoritesOrderStorage::load()
{
// load per-resident sorting information
std::string filename = getSavedOrderFileName();
LLSD settings_llsd;
llifstream file;
file.open(filename.c_str());
if (file.is_open())
{
LLSDSerialize::fromXML(settings_llsd, file);
LL_INFOS("FavoritesBar") << "loaded favorites order from '" << filename << "' "
<< (settings_llsd.isMap() ? "" : "un") << "successfully"
<< LL_ENDL;
file.close();
}
else
{
LL_WARNS("FavoritesBar") << "unable to open favorites order file at '" << filename << "'" << LL_ENDL;
}
LL_INFOS("FavoritesBar") << "loaded favorites order from '" << filename << "' "
<< (settings_llsd.isMap() ? "" : "un") << "successfully"
<< LL_ENDL;
file.close();
mSaveOnExit = true;
for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
iter != settings_llsd.endMap(); ++iter)
for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
iter != settings_llsd.endMap(); ++iter)
{
mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger()));
}
}
else
{
mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger()));
filename = getStoredFavoritesFilename();
if (!filename.empty())
{
llifstream in_file;
in_file.open(filename.c_str());
LLSD fav_llsd;
LLSD user_llsd;
if (in_file.is_open())
{
LLSDSerialize::fromXML(fav_llsd, in_file);
LL_INFOS("FavoritesBar") << "loaded favorites from '" << filename << "' "
<< (fav_llsd.isMap() ? "" : "un") << "successfully"
<< LL_ENDL;
in_file.close();
// <FS:Ansariel> FIRE-10122 - User@grid stored_favorites.xml
//user_llsd = fav_llsd[gAgentUsername];
user_llsd = fav_llsd[gAgentUsername + " @ " + LLGridManager::getInstance()->getGridLabel()];
// </FS:Ansariel>
S32 index = 0;
for (LLSD::array_iterator iter = user_llsd.beginArray();
iter != user_llsd.endArray(); ++iter)
{
mSortIndexes.insert(std::make_pair(iter->get("id").asUUID(), index));
index++;
}
}
else
{
LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL;
}
}
}
}
void LLFavoritesOrderStorage::saveFavoritesSLURLs()
{
// Do not change the file if we are not logged in yet.
if (!LLLoginInstance::getInstance()->authSuccess())
{
LL_WARNS("FavoritesBar") << "Cannot save favorites: not logged in" << LL_ENDL;
return;
}
// <FS:Ansariel> Favorites are stored in username.grid folder
// std::string filename = getStoredFavoritesFilename();
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
// </FS:Ansariel>
if (!filename.empty())
{
llifstream in_file;
in_file.open(filename.c_str());
LLSD fav_llsd;
if (in_file.is_open())
{
LLSDSerialize::fromXML(fav_llsd, in_file);
LL_INFOS("FavoritesBar") << "loaded favorites from '" << filename << "' "
<< (fav_llsd.isMap() ? "" : "un") << "successfully"
<< LL_ENDL;
in_file.close();
}
else
{
LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL;
}
const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
LLSD user_llsd;
for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++)
{
LLSD value;
value["name"] = (*it)->getName();
value["asset_id"] = (*it)->getAssetUUID();
slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]);
if (slurl_iter != mSLURLs.end())
{
LL_DEBUGS("FavoritesBar") << "Saving favorite: idx=" << LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID()) << ", SLURL=" << slurl_iter->second << ", value=" << value << LL_ENDL;
value["slurl"] = slurl_iter->second;
user_llsd[LLFavoritesOrderStorage::instance().getSortIndex((*it)->getUUID())] = value;
}
else
{
LL_WARNS("FavoritesBar") << "Not saving favorite " << value["name"] << ": no matching SLURL" << LL_ENDL;
}
}
LLAvatarName av_name;
LLAvatarNameCache::get( gAgentID, &av_name );
// Note : use the "John Doe" and not the "john.doe" version of the name
// as we'll compare it with the stored credentials in the login panel.
// <FS:CR> FIRE-10122 - User@grid stored_favorites.xml
//fav_llsd[av_name.getUserName()] = user_llsd;
std::string name = av_name.getUserName() + " @ " + LLGridManager::getInstance()->getGridLabel();
LL_DEBUGS("Favorites") << "Saved favorites for " << name << LL_ENDL;
fav_llsd[name] = user_llsd;
// </FS:CR>
llofstream file;
file.open(filename.c_str());
if ( file.is_open() )
{
LLSDSerialize::toPrettyXML(fav_llsd, file);
LL_INFOS("FavoritesBar") << "saved favorites for '" << av_name.getUserName()
<< "' to '" << filename << "' "
<< LL_ENDL;
file.close();
}
else
{
LL_WARNS("FavoritesBar") << "unable to open favorites storage for '" << av_name.getUserName()
<< "' at '" << filename << "' "
<< LL_ENDL;
}
}
}
void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()
{
// <FS:Ansariel> Favorites are stored in username.grid folder
// std::string filename = getStoredFavoritesFilename();
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
// </FS:Ansariel>
std::string filename = getStoredFavoritesFilename();
if (!filename.empty())
{
LLSD fav_llsd;
@ -1691,19 +1677,46 @@ void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()
LLAvatarNameCache::get( gAgentID, &av_name );
// Note : use the "John Doe" and not the "john.doe" version of the name.
// See saveFavoritesSLURLs() here above for the reason why.
// <FS:CR> FIRE-10122 - User@grid stored_favorites.xml
// if (fav_llsd.has(av_name.getUserName()))
// <FS:CR> FIRE-10122 - User@grid stored_favorites.xml
//if (fav_llsd.has(av_name.getUserName()))
//{
// LL_INFOS("FavoritesBar") << "Removed favorites for " << av_name.getUserName() << LL_ENDL;
// fav_llsd.erase(av_name.getUserName());
//}
std::string name = av_name.getUserName() + " @ " + LLGridManager::getInstance()->getGridLabel();
LL_DEBUGS("Favorites") << "Removed favorites for " << name << LL_ENDL;
if (fav_llsd.has(name))
{
fav_llsd.erase(name);
}
// </FS:CR>
// LLSD user_llsd = fav_llsd[av_name.getUserName()];
std::string name = av_name.getUserName() + " @ " + LLGridManager::getInstance()->getGridLabel();
if (fav_llsd.has(name))
{
LLSD user_llsd = fav_llsd[name];
// </FS:CR>
if (user_llsd.beginArray()->has("id"))
{
for (LLSD::array_iterator iter = user_llsd.beginArray();iter != user_llsd.endArray(); ++iter)
{
LLSD value;
value["id"]= iter->get("id").asUUID();
iter->assign(value);
}
// <FS:CR> FIRE-10122 - User@grid stored_favorites.xml
//fav_llsd[av_name.getUserName()] = user_llsd;
fav_llsd[name] = user_llsd;
// </FS:CR> FIRE-10122
llofstream file;
file.open(filename.c_str());
if ( file.is_open() )
{
LLSDSerialize::toPrettyXML(fav_llsd, file);
file.close();
}
}
else
{
// <FS:CR> FIRE-10122 - User@grid stored_favorites.xml
//LL_INFOS("FavoritesBar") << "Removed favorites for " << av_name.getUserName() << LL_ENDL;
//fav_llsd.erase(av_name.getUserName());
LL_INFOS("FavoritesBar") << "Removed favorites for " << name << LL_ENDL;
fav_llsd.erase(name);
// </FS:CR> FIRE-10122
}
}
llofstream out_file;
out_file.open(filename.c_str());
@ -1723,20 +1736,20 @@ void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmar
if (landmark)
{
LL_DEBUGS("FavoritesBar") << "landmark for " << asset_id << " loaded" << LL_ENDL;
LLVector3d pos_global;
if (!landmark->getGlobalPos(pos_global))
{
// If global position was unknown on first getGlobalPos() call
// it should be set for the subsequent calls.
landmark->getGlobalPos(pos_global);
}
LLVector3d pos_global;
if (!landmark->getGlobalPos(pos_global))
{
// If global position was unknown on first getGlobalPos() call
// it should be set for the subsequent calls.
landmark->getGlobalPos(pos_global);
}
if (!pos_global.isExactlyZero())
{
LL_DEBUGS("FavoritesBar") << "requesting slurl for landmark " << asset_id << LL_ENDL;
LLLandmarkActions::getSLURLfromPosGlobal(pos_global,
if (!pos_global.isExactlyZero())
{
LL_DEBUGS("FavoritesBar") << "requesting slurl for landmark " << asset_id << LL_ENDL;
LLLandmarkActions::getSLURLfromPosGlobal(pos_global,
boost::bind(&LLFavoritesOrderStorage::storeFavoriteSLURL, this, asset_id, _1));
}
}
}
}
@ -1746,41 +1759,6 @@ void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::st
mSLURLs[asset_id] = slurl;
}
void LLFavoritesOrderStorage::save()
{
if (mIsDirty)
{
// something changed, so save it
std::string filename = LLFavoritesOrderStorage::getInstance()->getSavedOrderFileName();
if (!filename.empty())
{
LLSD settings_llsd;
for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter)
{
settings_llsd[iter->first.asString()] = iter->second;
}
llofstream file;
file.open(filename.c_str());
if ( file.is_open() )
{
LLSDSerialize::toPrettyXML(settings_llsd, file);
LL_INFOS("FavoritesBar") << "saved favorites order to '" << filename << "' " << LL_ENDL;
}
else
{
LL_WARNS("FavoritesBar") << "failed to open favorites order file '" << filename << "' " << LL_ENDL;
}
}
else
{
LL_DEBUGS("FavoritesBar") << "no user directory available to store favorites order file" << LL_ENDL;
}
}
}
void LLFavoritesOrderStorage::cleanup()
{
// nothing to clean
@ -1795,7 +1773,7 @@ void LLFavoritesOrderStorage::cleanup()
sort_index_map_t aTempMap;
//copy unremoved values from mSortIndexes to aTempMap
std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(),
std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(),
inserter(aTempMap, aTempMap.begin()),
is_not_in_fav);
@ -1827,8 +1805,8 @@ void LLFavoritesOrderStorage::saveOrder()
void LLFavoritesOrderStorage::saveItemsOrder( const LLInventoryModel::item_array_t& items )
{
int sortField = 0;
int sortField = 0;
// current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
for (LLInventoryModel::item_array_t::const_iterator i = items.begin(); i != items.end(); ++i)
{
@ -1868,6 +1846,115 @@ void LLFavoritesOrderStorage::rearrangeFavoriteLandmarks(const LLUUID& source_it
saveItemsOrder(items);
}
BOOL LLFavoritesOrderStorage::saveFavoritesRecord(bool pref_changed)
{
LLUUID favorite_folder= gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
if (favorite_folder.isNull())
return FALSE;
LLInventoryModel::item_array_t items;
LLInventoryModel::cat_array_t cats;
LLIsType is_type(LLAssetType::AT_LANDMARK);
gInventory.collectDescendentsIf(favorite_folder, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
std::sort(items.begin(), items.end(), LLFavoritesSort());
if((items != mPrevFavorites) || pref_changed)
{
std::string filename = getStoredFavoritesFilename();
if (!filename.empty())
{
llifstream in_file;
in_file.open(filename.c_str());
LLSD fav_llsd;
if (in_file.is_open())
{
LLSDSerialize::fromXML(fav_llsd, in_file);
in_file.close();
}
else
{
LL_WARNS("FavoritesBar") << "unable to open favorites from '" << filename << "'" << LL_ENDL;
}
LLSD user_llsd;
S32 fav_iter = 0;
for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); it++)
{
LLSD value;
if (gSavedPerAccountSettings.getBOOL("ShowFavoritesOnLogin"))
{
value["name"] = (*it)->getName();
value["asset_id"] = (*it)->getAssetUUID();
value["id"] = (*it)->getUUID();
slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]);
if (slurl_iter != mSLURLs.end())
{
value["slurl"] = slurl_iter->second;
user_llsd[fav_iter] = value;
}
else
{
getSLURL((*it)->getAssetUUID());
mUpdateRequired = true;
return FALSE;
}
}
else
{
value["id"] = (*it)->getUUID();
user_llsd[fav_iter] = value;
}
fav_iter ++;
}
LLAvatarName av_name;
LLAvatarNameCache::get( gAgentID, &av_name );
// Note : use the "John Doe" and not the "john.doe" version of the name
// as we'll compare it with the stored credentials in the login panel.
// <FS:CR> FIRE-10122 - User@grid stored_favorites.xml
//fav_llsd[av_name.getUserName()] = user_llsd;
std::string name = av_name.getUserName() + " @ " + LLGridManager::getInstance()->getGridLabel();
LL_DEBUGS("Favorites") << "Saved favorites for " << name << LL_ENDL;
fav_llsd[name] = user_llsd;
// </FS:CR>
llofstream file;
file.open(filename.c_str());
if ( file.is_open() )
{
LLSDSerialize::toPrettyXML(fav_llsd, file);
file.close();
mSaveOnExit = false;
}
else
{
LL_WARNS("FavoritesBar") << "unable to open favorites storage for '" << av_name.getUserName()
<< "' at '" << filename << "' " << LL_ENDL;
}
}
mPrevFavorites = items;
}
return TRUE;
}
void LLFavoritesOrderStorage::showFavoritesOnLoginChanged(BOOL show)
{
if (show)
{
saveFavoritesRecord(true);
}
else
{
removeFavoritesRecordOfUser();
}
}
void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id)
{
if (mTargetLandmarkId.isNull()) return;

View File

@ -108,8 +108,10 @@ protected:
bool mUpdateDropDownItems;
bool mRestoreOverflowMenu;
LLUUID mSelectedItemID;
bool mGetPrevItems;
LLUUID mSelectedItemID;
LLFrameTimer mItemsChangedTimer;
LLUIImage* mImageDragIndication;
private:
@ -211,12 +213,23 @@ public:
* @see cleanup()
*/
static void destroyClass();
static std::string getStoredFavoritesFilename();
static std::string getSavedOrderFileName();
BOOL saveFavoritesRecord(bool pref_changed = false);
void showFavoritesOnLoginChanged(BOOL show);
LLInventoryModel::item_array_t mPrevFavorites;
const static S32 NO_INDEX;
static bool mSaveOnExit;
bool mUpdateRequired;
private:
friend class LLSingleton<LLFavoritesOrderStorage>;
LLFavoritesOrderStorage() : mIsDirty(false) { load(); }
~LLFavoritesOrderStorage() { save(); }
LLFavoritesOrderStorage() : mIsDirty(false), mUpdateRequired(false){ load(); }
~LLFavoritesOrderStorage() {}
/**
* Removes sort indexes for items which are not in Favorites bar for now.
@ -224,13 +237,8 @@ private:
void cleanup();
const static std::string SORTING_DATA_FILE_NAME;
std::string getSavedOrderFileName();
static std::string getStoredFavoritesFilename();
void load();
void save();
void saveFavoritesSLURLs();
void load();
// Remove record of current user's favorites from file on disk.
void removeFavoritesRecordOfUser();

View File

@ -34,10 +34,12 @@
// Viewer includes
#include "llagent.h"
#include "llagentui.h"
#include "llappviewer.h"
#include "llappviewer.h"
#include "llnotificationsutil.h"
#include "llslurl.h"
#include "llvoiceclient.h"
#include "lluictrlfactory.h"
#include "llupdaterservice.h"
#include "llviewertexteditor.h"
#include "llviewercontrol.h"
#include "llviewerstats.h"
@ -99,10 +101,24 @@ public:
/// separated so that we can programmatically access the same info.
static LLSD getInfo();
void onClickCopyToClipboard();
void onClickUpdateCheck();
// checks state of updater service and starts a check outside of schedule.
// subscribes callback for closest state update
static void setUpdateListener();
// <FS:Ansariel> Release notes link not updating
//private:
void setSupportText(const std::string& server_release_notes_url);
// notifications for user requested checks
static void showCheckUpdateNotification(S32 state);
// callback method for manual checks
static bool callbackCheckUpdate(LLSD const & event);
// listener name for update checks
static const std::string sCheckUpdateListenerName;
};
@ -133,6 +149,11 @@ BOOL LLFloaterAbout::postBuild()
getChild<LLUICtrl>("copy_btn")->setCommitCallback(
boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this));
// <FS:Ansariel> Disabled update button
//getChild<LLUICtrl>("update_btn")->setCommitCallback(
// boost::bind(&LLFloaterAbout::onClickUpdateCheck, this));
// </FS:Ansariel>
static const LLUIColor about_color = LLUIColorTable::instance().getColor("TextFgReadOnlyColor");
if (gAgent.getRegion())
@ -236,6 +257,11 @@ void LLFloaterAbout::onClickCopyToClipboard()
support_widget->deselect();
}
void LLFloaterAbout::onClickUpdateCheck()
{
setUpdateListener();
}
void LLFloaterAbout::setSupportText(const std::string& server_release_notes_url)
{
#if LL_WINDOWS
@ -256,6 +282,68 @@ void LLFloaterAbout::setSupportText(const std::string& server_release_notes_url)
FALSE, LLStyle::Params() .color(about_color));
}
///----------------------------------------------------------------------------
/// Floater About Update-check related functions
///----------------------------------------------------------------------------
const std::string LLFloaterAbout::sCheckUpdateListenerName = "LLUpdateNotificationListener";
void LLFloaterAbout::showCheckUpdateNotification(S32 state)
{
switch (state)
{
case LLUpdaterService::UP_TO_DATE:
LLNotificationsUtil::add("UpdateViewerUpToDate");
break;
case LLUpdaterService::DOWNLOADING:
case LLUpdaterService::INSTALLING:
LLNotificationsUtil::add("UpdateDownloadInProgress");
break;
case LLUpdaterService::TERMINAL:
// download complete, user triggered check after download pop-up appeared
LLNotificationsUtil::add("UpdateDownloadComplete");
break;
default:
LLNotificationsUtil::add("UpdateCheckError");
break;
}
}
bool LLFloaterAbout::callbackCheckUpdate(LLSD const & event)
{
if (!event.has("payload"))
{
return false;
}
LLSD payload = event["payload"];
if (payload.has("type") && payload["type"].asInteger() == LLUpdaterService::STATE_CHANGE)
{
LLEventPumps::instance().obtain("mainlooprepeater").stopListening(sCheckUpdateListenerName);
showCheckUpdateNotification(payload["state"].asInteger());
}
return false;
}
void LLFloaterAbout::setUpdateListener()
{
LLUpdaterService update_service;
S32 service_state = update_service.getState();
// Note: Do not set state listener before forceCheck() since it set's new state
if (update_service.forceCheck() || service_state == LLUpdaterService::CHECKING_FOR_UPDATE)
{
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainlooprepeater"));
if (mainloop.getListener(sCheckUpdateListenerName) == LLBoundListener()) // dummy listener
{
mainloop.listen(sCheckUpdateListenerName, boost::bind(&callbackCheckUpdate, _1));
}
}
else
{
showCheckUpdateNotification(service_state);
}
}
///----------------------------------------------------------------------------
/// LLFloaterAboutUtil
///----------------------------------------------------------------------------
@ -266,6 +354,11 @@ void LLFloaterAboutUtil::registerFloater()
}
void LLFloaterAboutUtil::checkUpdatesAndNotify()
{
LLFloaterAbout::setUpdateListener();
}
///----------------------------------------------------------------------------
/// Class LLServerReleaseNotesURLFetcher implementation
///----------------------------------------------------------------------------

View File

@ -30,6 +30,9 @@
namespace LLFloaterAboutUtil
{
void registerFloater();
// Support for user initialized update/state checks
void checkUpdatesAndNotify();
}
#endif // LL_LLFLOATERABOUT_H

View File

@ -32,6 +32,7 @@
#include "llavataractions.h"
#include "llfloaterbump.h"
#include "llfloaterreg.h"
#include "llfloaterreporter.h"
#include "llmutelist.h"
#include "llpanelblockedlist.h"
@ -106,8 +107,10 @@ BOOL LLFloaterBump::postBuild()
void LLFloaterBump::onOpen(const LLSD& key)
{
// <FS:Ansariel> Instant bump list floater update
//mNames.clear();
//mList->deleteAllItems();
//if (gMeanCollisionList.empty())
//{
// mNames.clear();
// mList->deleteAllItems();
updateList();
}
@ -129,10 +132,10 @@ void LLFloaterBump::updateList()
return;
}
mList->deleteAllItems();
// </FS:Ansariel>
if (gMeanCollisionList.empty())
{
// </FS:Ansariel>
std::string none_detected = getString("none_detected");
LLSD row;
row["columns"][0]["value"] = none_detected;
@ -141,13 +144,26 @@ void LLFloaterBump::updateList()
}
else
{
for (mean_collision_list_t::iterator iter = gMeanCollisionList.begin();
iter != gMeanCollisionList.end(); ++iter)
{
LLMeanCollisionData *mcd = *iter;
add(mList, mcd);
}
// <FS:Ansariel> Instant bump list floater update
// populateCollisionList();
// }
//}
//void LLFloaterBump::populateCollisionList()
//{
// mNames.clear();
// mList->deleteAllItems();
// </FS:Ansariel>
for (mean_collision_list_t::iterator iter = gMeanCollisionList.begin();
iter != gMeanCollisionList.end(); ++iter)
{
LLMeanCollisionData *mcd = *iter;
add(mList, mcd);
}
// <FS:Ansariel> Instant bump list floater update
}
// </FS:Ansariel>
}
void LLFloaterBump::add(LLScrollListCtrl* list, LLMeanCollisionData* mcd)
@ -290,6 +306,11 @@ void LLFloaterBump::inviteToGroup()
{
LLAvatarActions::inviteToGroup(mItemUUID);
}
LLFloaterBump* LLFloaterBump::getInstance()
{
return LLFloaterReg::getTypedInstance<LLFloaterBump>("bumps");
}
#endif
// </FS:Ansariel>

View File

@ -52,6 +52,11 @@ public:
/*virtual*/ void draw();
void setDirty() { mDirty = true; }
static LLFloaterBump* getInstance();
// <FS:Ansariel> Instant bump list floater update
//void populateCollisionList();
void startIM();
void startCall();
void reportAbuse();

View File

@ -66,8 +66,8 @@ const std::string DEFAULT_CHECKIN_ICON_URL = "http://map.secondlife.com.s3.amazo
const std::string DEFAULT_CHECKIN_QUERY_PARAMETERS = "?sourceid=slshare_checkin&utm_source=facebook&utm_medium=checkin&utm_campaign=slshare";
const std::string DEFAULT_PHOTO_QUERY_PARAMETERS = "?sourceid=slshare_photo&utm_source=facebook&utm_medium=photo&utm_campaign=slshare";
const S32 MAX_QUALITY = 100; // Max quality value for jpeg images
const S32 MIN_QUALITY = 0; // Min quality value for jpeg images
const S32 MAX_QUALITY = 100; // Max quality value for jpeg images
const S32 MIN_QUALITY = 0; // Min quality value for jpeg images
const S32 TARGET_DATA_SIZE = 950000; // Size of the image (compressed) we're trying to send to Facebook
std::string get_map_url()

View File

@ -262,6 +262,8 @@ BOOL LLFloaterIMContainer::postBuild()
mInitialized = true;
mIsFirstOpen = true;
// Add callbacks:
// We'll take care of view updates on idle
gIdleCallbacks.addFunction(idle, this);
@ -637,14 +639,16 @@ void LLFloaterIMContainer::setVisible(BOOL visible)
{
// Make sure we have the Nearby Chat present when showing the conversation container
nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat");
if (nearby_chat == NULL)
if ((nearby_chat == NULL) || mIsFirstOpen)
{
mIsFirstOpen = false;
// If not found, force the creation of the nearby chat conversation panel
// *TODO: find a way to move this to XML as a default panel or something like that
LLSD name("nearby_chat");
LLFloaterReg::toggleInstanceOrBringToFront(name);
selectConversationPair(LLUUID(NULL), false, false);
}
flashConversationItemWidget(mSelectedSession,false);
LLFloaterIMSessionTab* session_floater = LLFloaterIMSessionTab::findConversation(mSelectedSession);
@ -1217,7 +1221,22 @@ void LLFloaterIMContainer::doToSelectedConversation(const std::string& command,
{
if (selectedIDS.size() > 0)
{
LLAvatarActions::viewChatHistory(selectedIDS.front());
if(conversationItem->getType() == LLConversationItem::CONV_SESSION_GROUP)
{
LLFloaterReg::showInstance("preview_conversation", conversationItem->getUUID(), true);
}
else if(conversationItem->getType() == LLConversationItem::CONV_SESSION_AD_HOC)
{
LLConversation* conv = LLConversationLog::instance().findConversation(LLIMModel::getInstance()->findIMSession(conversationItem->getUUID()));
if(conv)
{
LLFloaterReg::showInstance("preview_conversation", conv->getSessionID(), true);
}
}
else
{
LLAvatarActions::viewChatHistory(selectedIDS.front());
}
}
}
else
@ -1317,6 +1336,15 @@ bool LLFloaterIMContainer::enableContextMenuItem(const LLSD& userdata)
{
return LLLogChat::isNearbyTranscriptExist();
}
else if (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_AD_HOC)
{
const LLConversation* conv = LLConversationLog::instance().findConversation(LLIMModel::getInstance()->findIMSession(uuids.front()));
if(conv)
{
return LLLogChat::isAdHocTranscriptExist(conv->getHistoryFileName());
}
return false;
}
else
{
bool is_group = (getCurSelectedViewModelItem()->getType() == LLConversationItem::CONV_SESSION_GROUP);
@ -1882,22 +1910,28 @@ bool LLFloaterIMContainer::canBanSelectedMember(const LLUUID& participant_uuid)
return false;
}
if (!gdatap->mMembers.size())
if (gdatap->mPendingBanRequest)
{
return false;
}
LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find((participant_uuid));
if (mi == gdatap->mMembers.end())
if (gdatap->isRoleMemberDataComplete())
{
return false;
}
if (!gdatap->mMembers.size())
{
return false;
}
LLGroupMemberData* member_data = (*mi).second;
// Is the member an owner?
if ( member_data && member_data->isInRole(gdatap->mOwnerRole) )
{
return false;
LLGroupMgrGroupData::member_list_t::iterator mi = gdatap->mMembers.find((participant_uuid));
if (mi != gdatap->mMembers.end())
{
LLGroupMemberData* member_data = (*mi).second;
// Is the member an owner?
if (member_data && member_data->isInRole(gdatap->mOwnerRole))
{
return false;
}
}
}
if( gAgent.hasPowerInGroup(group_uuid, GP_ROLE_REMOVE_MEMBER) &&
@ -1925,20 +1959,8 @@ void LLFloaterIMContainer::banSelectedMember(const LLUUID& participant_uuid)
LL_WARNS("Groups") << "Unable to get group data for group " << group_uuid << LL_ENDL;
return;
}
std::vector<LLUUID> ids;
ids.push_back(participant_uuid);
LLGroupBanData ban_data;
gdatap->createBanEntry(participant_uuid, ban_data);
LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, group_uuid, LLGroupMgr::BAN_CREATE, ids);
LLGroupMgr::getInstance()->sendGroupMemberEjects(group_uuid, ids);
LLGroupMgr::getInstance()->sendGroupMembersRequest(group_uuid);
LLSD args;
std::string name;
gCacheName->getFullName(participant_uuid, name);
args["AVATAR_NAME"] = name;
args["GROUP_NAME"] = gdatap->mName;
LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args));
gdatap->banMemberById(participant_uuid);
}

View File

@ -195,6 +195,8 @@ private:
bool mInitialized;
bool mIsFirstLaunch;
bool mIsFirstOpen;
LLUUID mSelectedSession;
std::string mGeneralTitle;

View File

@ -328,7 +328,21 @@ void LLFloaterJoystick::onClickOK(void *joy_panel)
}
}
void LLFloaterJoystick::onClickCloseBtn(bool app_quitting)
{
cancel();
closeFloater(app_quitting);
}
void LLFloaterJoystick::setSNDefaults()
{
LLViewerJoystick::getInstance()->setSNDefaults();
}
void LLFloaterJoystick::onClose(bool app_quitting)
{
if (app_quitting)
{
cancel();
}
}

View File

@ -45,6 +45,11 @@ public:
virtual void draw();
static void setSNDefaults();
protected:
void onClose(bool app_quitting);
void onClickCloseBtn(bool app_quitting);
private:
LLFloaterJoystick(const LLSD& data);

View File

@ -2660,13 +2660,15 @@ void LLPanelLandAccess::refresh()
mListAccess->clearSortOrder();
mListAccess->deleteAllItems();
S32 count = parcel->mAccessList.size();
getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count));
getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST));
// <FS:Ansariel> FIRE-9211: Add counter to parcel ban and access lists
//getChild<LLUICtrl>("AllowedText")->setTextArg("[COUNT]", llformat("%d",count));
getChild<LLUICtrl>("AllowedText")->setTextArg(LLStringExplicit("[LISTED]"), llformat("%d",count));
getChild<LLUICtrl>("AllowedText")->setTextArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST));
// </FS:Ansariel>
getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count));
getChild<LLUICtrl>("AccessList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST));
for (LLAccessEntry::map::const_iterator cit = parcel->mAccessList.begin();
cit != parcel->mAccessList.end(); ++cit)
{
@ -2709,14 +2711,15 @@ void LLPanelLandAccess::refresh()
mListBanned->clearSortOrder();
mListBanned->deleteAllItems();
S32 count = parcel->mBanList.size();
getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count));
getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST));
// <FS:Ansariel> FIRE-9211: Add counter to parcel ban and access lists
//getChild<LLUICtrl>("BanCheck")->setTextArg("[COUNT]", llformat("%d",count));
getChild<LLUICtrl>("BanCheck")->setTextArg(LLStringExplicit("[LISTED]"), llformat("%d",count));
getChild<LLUICtrl>("BanCheck")->setTextArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST));
// </FS:Ansariel>
getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[LISTED]"), llformat("%d",count));
getChild<LLUICtrl>("BannedList")->setToolTipArg(LLStringExplicit("[MAX]"), llformat("%d",PARCEL_MAX_ACCESS_LIST));
for (LLAccessEntry::map::const_iterator cit = parcel->mBanList.begin();
cit != parcel->mBanList.end(); ++cit)
{

View File

@ -2314,10 +2314,15 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)
for (U32 lod = 0; lod < LLModel::NUM_LODS; ++lod)
{
if (!model[lod].empty())
if (model[lod].size() > idx)
{
instance_list[i].mLOD[lod] = model[lod][idx];
}
else if (!model[lod].empty())
{
// slm load failed - indexes are corrupted
return false;
}
}
instance_list[i].mModel = model[LLModel::LOD_HIGH][idx];

View File

@ -169,61 +169,83 @@ void LLFloaterPermsDefault::onCommitCopy(const LLSD& user_data)
xfer->setEnabled(copyable);
}
class LLFloaterPermsResponder : public LLHTTPClient::Responder
const int MAX_HTTP_RETRIES = 5;
LLFloaterPermsRequester* LLFloaterPermsRequester::sPermsRequester = NULL;
LLFloaterPermsRequester::LLFloaterPermsRequester(const std::string url, const LLSD report,
int maxRetries)
: mRetriesCount(0), mMaxRetries(maxRetries), mUrl(url), mReport(report)
{}
//static
void LLFloaterPermsRequester::init(const std::string url, const LLSD report, int maxRetries)
{
public:
LLFloaterPermsResponder(): LLHTTPClient::Responder() {}
// <FS:Ansariel> Add some retry function
static U32 sRetryCount;
private:
static std::string sPreviousReason;
void httpFailure()
if (sPermsRequester == NULL) {
sPermsRequester = new LLFloaterPermsRequester(url, report, maxRetries);
}
}
//static
void LLFloaterPermsRequester::finalize()
{
if (sPermsRequester != NULL)
{
delete sPermsRequester;
sPermsRequester = NULL;
}
}
//static
LLFloaterPermsRequester* LLFloaterPermsRequester::instance()
{
return sPermsRequester;
}
void LLFloaterPermsRequester::start()
{
++mRetriesCount;
LLHTTPClient::post(mUrl, mReport, new LLFloaterPermsResponder());
}
bool LLFloaterPermsRequester::retry()
{
if (++mRetriesCount < mMaxRetries)
{
LLHTTPClient::post(mUrl, mReport, new LLFloaterPermsResponder());
return true;
}
return false;
}
void LLFloaterPermsResponder::httpFailure()
{
if (!LLFloaterPermsRequester::instance() || !LLFloaterPermsRequester::instance()->retry())
{
LLFloaterPermsRequester::finalize();
const std::string& reason = getReason();
// Do not display the same error more than once in a row
if (reason != sPreviousReason)
{
// <FS:Ansariel> Add some retry function
if (sRetryCount >= 5)
{
// </FS:Ansariel>
sPreviousReason = reason;
LLSD args;
args["REASON"] = reason;
LLNotificationsUtil::add("DefaultObjectPermissions", args);
// <FS:Ansariel> Add some retry function
}
else
{
LL_WARNS("FloaterPermsResponder") << "Sending default permissions to simulator failed. Retrying (attempt " << sRetryCount << ")" << LL_ENDL;
sRetryCount++;
LLFloaterPermsDefault::sendInitialPerms();
}
// </FS:Ansariel>
}
}
}
void httpSuccess()
{
//const LLSD& content = getContent();
//dump_sequential_xml("perms_responder_result.xml", content);
void LLFloaterPermsResponder::httpSuccess()
{
//const LLSD& content = getContent();
//dump_sequential_xml("perms_responder_result.xml", content);
// Since we have had a successful POST call be sure to display the next error message
// even if it is the same as a previous one.
sPreviousReason = "";
// <FS:Ansariel> Add some retry function
sRetryCount = 0;
LLFloaterPermsDefault::setCapSent(true);
LL_INFOS("ObjectPermissionsFloater") << "Default permissions successfully sent to simulator" << LL_ENDL;
}
};
// Since we have had a successful POST call be sure to display the next error message
// even if it is the same as a previous one.
sPreviousReason = "";
LL_INFOS("ObjectPermissionsFloater") << "Default permissions successfully sent to simulator" << LL_ENDL;
}
// <FS:Ansariel> Add some retry function
U32 LLFloaterPermsResponder::sRetryCount = 0;
std::string LLFloaterPermsResponder::sPreviousReason;
std::string LLFloaterPermsResponder::sPreviousReason;
void LLFloaterPermsDefault::sendInitialPerms()
{
@ -233,6 +255,7 @@ void LLFloaterPermsDefault::sendInitialPerms()
// </FS:Ansariel>
{
updateCap();
setCapSent(true);
}
}
@ -257,9 +280,8 @@ void LLFloaterPermsDefault::updateCap()
LLSDSerialize::toPrettyXML(report, sent_perms_log);
LL_CONT << sent_perms_log.str() << LL_ENDL;
}
LLFloaterPermsResponder::sRetryCount++;
LLHTTPClient::post(object_url, report, new LLFloaterPermsResponder());
LLFloaterPermsRequester::init(object_url, report, MAX_HTTP_RETRIES);
LLFloaterPermsRequester::instance()->start();
}
else
{
@ -277,9 +299,6 @@ void LLFloaterPermsDefault::setCapSent(bool cap_sent)
void LLFloaterPermsDefault::ok()
{
// <FS:Ansariel> Add some retry function
LLFloaterPermsResponder::sRetryCount = 0;
// Changes were already applied automatically to saved settings.
// Refreshing internal values makes it official.
refresh();

View File

@ -29,6 +29,7 @@
#define LL_LLFLOATERPERMPREFS_H
#include "llfloater.h"
#include "llhttpclient.h"
class LLFloaterPerms : public LLFloater
{
@ -94,4 +95,36 @@ private:
static bool sCapSent;
};
class LLFloaterPermsRequester
{
public:
LLFloaterPermsRequester(const std::string url, const LLSD report, int maxRetries);
static void init(const std::string url, const LLSD report, int maxRetries);
static void finalize();
static LLFloaterPermsRequester* instance();
void start();
bool retry();
private:
int mRetriesCount;
int mMaxRetries;
const std::string mUrl;
const LLSD mReport;
public:
static LLFloaterPermsRequester* sPermsRequester;
};
class LLFloaterPermsResponder : public LLHTTPClient::Responder
{
public:
LLFloaterPermsResponder() : LLHTTPClient::Responder() {}
private:
static std::string sPreviousReason;
void httpFailure();
void httpSuccess();
};
#endif

View File

@ -50,6 +50,7 @@
//#include "llfirstuse.h"
#include "llfloaterreg.h"
#include "llfloaterabout.h"
#include "llfavoritesbar.h"
#include "llfloaterhardwaresettings.h"
#include "llfloatersidepanelcontainer.h"
// <FS:Ansariel> [FS communication UI]
@ -2854,7 +2855,7 @@ BOOL LLPanelPreference::postBuild()
}
if (hasChild("favorites_on_login_check", TRUE))
{
getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setCommitCallback(boost::bind(&showFavoritesOnLoginWarning, _1, _2));
getChild<LLCheckBoxCtrl>("favorites_on_login_check")->setCommitCallback(boost::bind(&handleFavoritesOnLoginChanged, _1, _2));
// <FS:Ansariel> [FS Login Panel]
//bool show_favorites_at_login = LLPanelLogin::getShowFavorites();
bool show_favorites_at_login = FSPanelLogin::getShowFavorites();
@ -2987,11 +2988,15 @@ void LLPanelPreference::showCustomPortWarning(LLUICtrl* checkbox, const LLSD& va
}
// [/WoLf]
void LLPanelPreference::showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value)
void LLPanelPreference::handleFavoritesOnLoginChanged(LLUICtrl* checkbox, const LLSD& value)
{
if (checkbox && checkbox->getValue())
if (checkbox)
{
LLNotificationsUtil::add("FavoritesOnLogin");
LLFavoritesOrderStorage::instance().showFavoritesOnLoginChanged(checkbox->getValue().asBoolean());
if(checkbox->getValue())
{
LLNotificationsUtil::add("FavoritesOnLogin");
}
}
}
@ -3371,6 +3376,11 @@ void LLFloaterPreferenceProxy::onOpen(const LLSD& key)
void LLFloaterPreferenceProxy::onClose(bool app_quitting)
{
if(app_quitting)
{
cancel();
}
if (mSocksSettingsDirty)
{
@ -3470,6 +3480,11 @@ void LLFloaterPreferenceProxy::onBtnCancel()
cancel();
}
void LLFloaterPreferenceProxy::onClickCloseBtn(bool app_quitting)
{
cancel();
}
void LLFloaterPreferenceProxy::cancel()
{
@ -3480,7 +3495,7 @@ void LLFloaterPreferenceProxy::cancel()
LLSD ctrl_value = iter->second;
control->set(ctrl_value);
}
mSocksSettingsDirty = false;
closeFloater();
}

View File

@ -304,7 +304,7 @@ private:
static void showCustomPortWarning(LLUICtrl*, const LLSD&); // -WoLf
//for "Show my Favorite Landmarks at Login"
static void showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value);
static void handleFavoritesOnLoginChanged(LLUICtrl* checkbox, const LLSD& value);
// <FS:Ansariel> Only enable Growl checkboxes if Growl is usable
void onEnableGrowlChanged();
@ -468,6 +468,7 @@ protected:
void saveSettings();
void onBtnOk();
void onBtnCancel();
void onClickCloseBtn(bool app_quitting = false);
void onChangeSocksSettings();

View File

@ -35,6 +35,7 @@
#include "llassetstorage.h"
#include "llavatarnamecache.h"
#include "llcachename.h"
#include "llcheckboxctrl.h"
#include "llfontgl.h"
#include "llimagej2c.h"
#include "llinventory.h"
@ -137,6 +138,7 @@ BOOL LLFloaterReporter::postBuild()
mOwnerName = LLStringUtil::null;
getChild<LLUICtrl>("summary_edit")->setFocus(TRUE);
getChild<LLCheckBoxCtrl>("screen_check")->set(TRUE);
mDefaultSummary = getChild<LLUICtrl>("details_edit")->getValue().asString();

View File

@ -751,14 +751,20 @@ void LLFloaterSnapshot::Impl::onCommitFreezeFrame(LLUICtrl* ctrl, void* data)
{
LLCheckBoxCtrl* check_box = (LLCheckBoxCtrl*)ctrl;
LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
LLSnapshotLivePreview* previewp = getPreviewView(view);
if (!view || !check_box)
if (!view || !check_box || !previewp)
{
return;
}
gSavedSettings.setBOOL("UseFreezeFrame", check_box->get());
if (check_box->get())
{
previewp->prepareFreezeFrame();
}
updateLayout(view);
}

View File

@ -178,6 +178,12 @@ BOOL LLFloaterTOS::postBuild()
// Don't use the start_url parameter for this browser instance -- it may finish loading before we get to add our observer.
// Store the URL separately and navigate here instead.
web_browser->navigateTo( getString( "loading_url" ) );
LLPluginClassMedia* media_plugin = web_browser->getMediaPlugin();
if (media_plugin)
{
// All links from tos_html should be opened in external browser
media_plugin->setOverrideClickTarget("_external");
}
}
}
#ifdef OPENSIM

View File

@ -337,12 +337,12 @@ BOOL LLFloaterWorldMap::postBuild()
LLComboBox *avatar_combo = getChild<LLComboBox>("friend combo");
avatar_combo->selectFirstItem();
avatar_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onAvatarComboPrearrange, this) );
avatar_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
avatar_combo->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
mListFriendCombo = dynamic_cast<LLCtrlListInterface *>(avatar_combo);
LLSearchEditor *location_editor = getChild<LLSearchEditor>("location");
location_editor->setFocusChangedCallback(boost::bind(&LLFloaterWorldMap::onLocationFocusChanged, this, _1));
location_editor->setKeystrokeCallback( boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this));
location_editor->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onSearchTextEntry, this));
getChild<LLScrollListCtrl>("search_results")->setDoubleClickCallback( boost::bind(&LLFloaterWorldMap::onClickTeleportBtn, this));
mListSearchResults = childGetListInterface("search_results");
@ -350,7 +350,7 @@ BOOL LLFloaterWorldMap::postBuild()
LLComboBox *landmark_combo = getChild<LLComboBox>( "landmark combo");
landmark_combo->selectFirstItem();
landmark_combo->setPrearrangeCallback( boost::bind(&LLFloaterWorldMap::onLandmarkComboPrearrange, this) );
landmark_combo->setTextEntryCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
landmark_combo->setTextChangedCallback( boost::bind(&LLFloaterWorldMap::onComboTextEntry, this) );
mListLandmarkCombo = dynamic_cast<LLCtrlListInterface *>(landmark_combo);
mCurZoomVal = log(LLWorldMapView::sMapScale)/log(2.f);

View File

@ -254,7 +254,8 @@ LLGroupMgrGroupData::LLGroupMgrGroupData(const LLUUID& id) :
mRoleMemberDataComplete(false),
mGroupPropertiesDataComplete(false),
mPendingRoleMemberRequest(false),
mAccessTime(0.0f)
mAccessTime(0.0f),
mPendingBanRequest(false)
{
mMemberVersion.generate();
}
@ -776,8 +777,69 @@ void LLGroupMgrGroupData::removeBanEntry(const LLUUID& ban_id)
mBanList.erase(ban_id);
}
void LLGroupMgrGroupData::banMemberById(const LLUUID& participant_uuid)
{
if (!mMemberDataComplete ||
!mRoleDataComplete ||
!(mRoleMemberDataComplete && mMembers.size()))
{
LL_WARNS() << "No Role-Member data yet, setting ban request to pending." << LL_ENDL;
mPendingBanRequest = true;
mPendingBanMemberID = participant_uuid;
if (!mMemberDataComplete)
{
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mID);
}
if (!mRoleDataComplete)
{
LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mID);
}
return;
}
LLGroupMgrGroupData::member_list_t::iterator mi = mMembers.find((participant_uuid));
if (mi == mMembers.end())
{
if (!mPendingBanRequest)
{
mPendingBanRequest = true;
mPendingBanMemberID = participant_uuid;
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mID); // member isn't in members list, request reloading
}
else
{
mPendingBanRequest = false;
}
return;
}
mPendingBanRequest = false;
LLGroupMemberData* member_data = (*mi).second;
if (member_data && member_data->isInRole(mOwnerRole))
{
return; // can't ban group owner
}
std::vector<LLUUID> ids;
ids.push_back(participant_uuid);
LLGroupBanData ban_data;
createBanEntry(participant_uuid, ban_data);
LLGroupMgr::getInstance()->sendGroupBanRequest(LLGroupMgr::REQUEST_POST, mID, LLGroupMgr::BAN_CREATE, ids);
LLGroupMgr::getInstance()->sendGroupMemberEjects(mID, ids);
LLGroupMgr::getInstance()->sendGroupMembersRequest(mID);
LLSD args;
std::string name;
gCacheName->getFullName(participant_uuid, name);
args["AVATAR_NAME"] = name;
args["GROUP_NAME"] = mName;
LLNotifications::instance().add(LLNotification::Params("EjectAvatarFromGroup").substitutions(args));
}
//
// LLGroupMgr
@ -1260,6 +1322,11 @@ void LLGroupMgr::processGroupRoleMembersReply(LLMessageSystem* msg, void** data)
group_datap->mChanged = TRUE;
LLGroupMgr::getInstance()->notifyObservers(GC_ROLE_MEMBER_DATA);
if (group_datap->mPendingBanRequest)
{
group_datap->banMemberById(group_datap->mPendingBanMemberID);
}
}
// static
@ -2029,8 +2096,6 @@ void LLGroupMgr::processGroupBanRequest(const LLSD& content)
LLGroupMgr::getInstance()->notifyObservers(GC_BANLIST);
}
// Responder class for capability group management
class GroupMemberDataResponder : public LLHTTPClient::Responder
{
@ -2119,11 +2184,6 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
return;
}
// If we have no members, there's no reason to do anything else
S32 num_members = content["member_count"];
if(num_members < 1)
return;
LLUUID group_id = content["group_id"].asUUID();
LLGroupMgrGroupData* group_datap = LLGroupMgr::getInstance()->getGroupData(group_id);
@ -2133,6 +2193,18 @@ void LLGroupMgr::processCapGroupMembersRequest(const LLSD& content)
return;
}
// If we have no members, there's no reason to do anything else
S32 num_members = content["member_count"];
if (num_members < 1)
{
LL_INFOS("GrpMgr") << "Received empty group members list for group id: " << group_id.asString() << LL_ENDL;
// Set mMemberDataComplete for correct handling of empty responses. See MAINT-5237
group_datap->mMemberDataComplete = true;
group_datap->mChanged = TRUE;
LLGroupMgr::getInstance()->notifyObservers(GC_MEMBER_DATA);
return;
}
group_datap->mMemberCount = num_members;
LLSD member_list = content["members"];

View File

@ -153,7 +153,7 @@ public:
const uuid_vec_t& getRoleMembers() const { return mMemberIDs; }
S32 getMembersInRole(uuid_vec_t members, BOOL needs_sort = TRUE);
S32 getTotalMembersInRole() { return mMemberIDs.size(); }
S32 getTotalMembersInRole() { return mMemberCount ? mMemberCount : mMemberIDs.size(); } //FIXME: Returns 0 for Everyone role when Member list isn't yet loaded, see MAINT-5225
LLRoleData getRoleData() const { return mRoleData; }
void setRoleData(LLRoleData data) { mRoleData = data; }
@ -279,8 +279,8 @@ public:
void createBanEntry(const LLUUID& ban_id, const LLGroupBanData& ban_data = LLGroupBanData());
void removeBanEntry(const LLUUID& ban_id);
void banMemberById(const LLUUID& participant_uuid);
public:
typedef std::map<LLUUID,LLGroupMemberData*> member_list_t;
typedef std::map<LLUUID,LLGroupRoleData*> role_list_t;
@ -312,6 +312,9 @@ public:
S32 mMemberCount;
S32 mRoleCount;
bool mPendingBanRequest;
LLUUID mPendingBanMemberID;
protected:
void sendRoleChanges();
void cancelRoleChanges();

View File

@ -146,7 +146,7 @@ bool isAddAction(const std::string& action)
bool isRemoveAction(const std::string& action)
{
return ("take_off" == action || "detach" == action || "deactivate" == action);
return ("take_off" == action || "detach" == action);
}
bool isMarketplaceCopyAction(const std::string& action)
@ -1038,15 +1038,7 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items,
return;
}
// "Remove link" and "Delete" are the same operation.
if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID))
{
items.push_back(std::string("Remove Link"));
}
else
{
items.push_back(std::string("Delete"));
}
items.push_back(std::string("Delete"));
if (!isItemRemovable())
{
@ -1994,7 +1986,9 @@ void LLItemBridge::restoreItem()
if(item)
{
LLInventoryModel* model = getInventoryModel();
const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType()));
bool is_snapshot = (item->getInventoryType() == LLInventoryType::IT_SNAPSHOT);
const LLUUID new_parent = model->findCategoryUUIDForType(is_snapshot? LLFolderType::FT_SNAPSHOT_CATEGORY : LLFolderType::assetTypeToFolderType(item->getType()));
// do not restamp on restore.
LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE);
}
@ -2709,7 +2703,8 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
BOOL drop,
std::string& tooltip_msg,
BOOL user_confirm)
BOOL is_link,
BOOL user_confirm)
{
LLInventoryModel* model = getInventoryModel();
@ -2759,6 +2754,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);
const BOOL move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
const BOOL move_is_into_current_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_CURRENT_OUTFIT);
// <FS:Ansariel> FIRE-1392: Allow dragging all asset types into Landmarks folder
//const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id);
@ -2806,6 +2802,10 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
is_movable = false;
}
}
if(is_movable && move_is_into_current_outfit && is_link)
{
is_movable = FALSE;
}
if (is_movable && (mUUID == model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE)))
{
is_movable = FALSE;
@ -2999,9 +2999,11 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
}
// if target is current outfit folder we use link
if (move_is_into_current_outfit &&
inv_cat->getPreferredType() == LLFolderType::FT_NONE)
(inv_cat->getPreferredType() == LLFolderType::FT_NONE ||
inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT))
{
// traverse category and add all contents to currently worn.
BOOL append = true;
@ -4515,7 +4517,7 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
LLInventoryCategory* linked_category = gInventory.getCategory(inv_item->getLinkedUUID());
if (linked_category)
{
accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop, tooltip_msg);
accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop, tooltip_msg, TRUE);
}
}
else
@ -4963,7 +4965,7 @@ void LLFolderBridge::callback_dropCategoryIntoFolder(const LLSD& notification, c
if (option == 0) // YES
{
std::string tooltip_msg;
dragCategoryIntoFolder(inv_category, TRUE, tooltip_msg, FALSE);
dragCategoryIntoFolder(inv_category, TRUE, tooltip_msg, FALSE, FALSE);
}
}
@ -6275,7 +6277,7 @@ void LLGestureBridge::performAction(LLInventoryModel* model, std::string action)
gInventory.updateItem(item);
gInventory.notifyObservers();
}
else if (isRemoveAction(action))
else if ("deactivate" == action || isRemoveAction(action))
{
LLGestureMgr::instance().deactivateGesture(mUUID);
@ -7052,12 +7054,8 @@ void LLWearableBridge::performAction(LLInventoryModel* model, std::string action
void LLWearableBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
}
performAction(getInventoryModel(),
get_is_item_worn(mUUID) ? "take_off" : "wear");
}
void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)

View File

@ -300,7 +300,7 @@ public:
{}
BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg, BOOL user_confirm = TRUE);
BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg, BOOL user_confirm = TRUE);
BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg, BOOL is_link = FALSE, BOOL user_confirm = TRUE);
void callback_dropItemIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryItem* inv_item);
void callback_dropCategoryIntoFolder(const LLSD& notification, const LLSD& response, LLInventoryCategory* inv_category);

View File

@ -2573,7 +2573,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
{
LLSD args;
args["QUESTION"] = LLTrans::getString(root->getSelectedCount() > 1 ? "DeleteItems" : "DeleteItem");
LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&onItemsRemovalConfirmation, _1, _2, root->getHandle()));
LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryAction::onItemsRemovalConfirmation, _1, _2, root->getHandle()));
// Note: marketplace listings will be updated in the callback if delete confirmed
return;
}

View File

@ -485,9 +485,9 @@ struct LLInventoryAction
static void removeItemFromDND(LLFolderView* root);
private:
static void buildMarketplaceFolders(LLFolderView* root);
static void updateMarketplaceFolders();
static std::list<LLUUID> sMarketplaceFolders; // Marketplace folders that will need update once the action is completed
static void buildMarketplaceFolders(LLFolderView* root);
static void updateMarketplaceFolders();
static std::list<LLUUID> sMarketplaceFolders; // Marketplace folders that will need update once the action is completed
};

View File

@ -524,7 +524,7 @@ void LLLocalBitmap::updateUserSculpts(LLUUID old_id, LLUUID new_id)
{
LLSculptParams* old_params = (LLSculptParams*)object->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
LLSculptParams new_params(*old_params);
new_params.setSculptTexture(new_id);
new_params.setSculptTexture(new_id, (*old_params).getSculptType());
object->setParameterEntry(LLNetworkData::PARAMS_SCULPT, new_params, TRUE);
}
}

View File

@ -934,19 +934,11 @@ void LLLocationInputCtrl::refreshParcelIcons()
#endif // OPENSIM
// </FS:CR>
// <FS:Ansariel> Undo MAIN-23 for now...
//bool is_parcel_owner = (gAgent.getID() == current_parcel->getOwnerID());
//bool allow_group_modify = (gAgent.isInGroup(current_parcel->getGroupID()) && current_parcel->getAllowGroupModify());
// </FS:Ansariel>
// Most icons are "block this ability"
mParcelIcon[VOICE_ICON]->setVisible( !allow_voice );
mParcelIcon[FLY_ICON]->setVisible( !allow_fly );
mParcelIcon[PUSH_ICON]->setVisible( !allow_push );
// <FS:Ansariel> Undo MAIN-23 for now...
//mParcelIcon[BUILD_ICON]->setVisible( !allow_build && !is_parcel_owner && !allow_group_modify );
mParcelIcon[BUILD_ICON]->setVisible( !allow_build );
// </FS:Ansariel>
mParcelIcon[SCRIPTS_ICON]->setVisible( !allow_scripts );
mParcelIcon[DAMAGE_ICON]->setVisible( allow_damage );
mParcelIcon[PATHFINDING_DIRTY_ICON]->setVisible(mIsNavMeshDirty);

View File

@ -886,6 +886,22 @@ bool LLLogChat::isNearbyTranscriptExist()
return false;
}
bool LLLogChat::isAdHocTranscriptExist(std::string file_name)
{
std::vector<std::string> list_of_transcriptions;
LLLogChat::getListOfTranscriptFiles(list_of_transcriptions);
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;
}
//*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>"

View File

@ -120,6 +120,7 @@ public:
static void deleteTranscripts();
static bool isTranscriptExist(const LLUUID& avatar_id, bool is_group=false);
static bool isNearbyTranscriptExist();
static bool isAdHocTranscriptExist(std::string file_name);
static bool historyThreadsFinished(LLUUID session_id);
static LLLoadHistoryThread* getLoadHistoryThread(LLUUID session_id);

View File

@ -95,6 +95,7 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) :
mStretchToFill( true ),
mMaintainAspectRatio ( true ),
mDecoupleTextureSize ( false ),
mUpdateScrolls( false ),
mTextureWidth ( 1024 ),
mTextureHeight ( 1024 ),
mClearCache(false),
@ -701,7 +702,13 @@ bool LLMediaCtrl::ensureMediaSourceExists()
mMediaSource->addObserver( this );
mMediaSource->setBackgroundColor( getBackgroundColor() );
mMediaSource->setTrustedBrowser(mTrusted);
mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] );
F32 scale_factor = LLUI::getScaleFactor().mV[ VX ];
if (scale_factor != mMediaSource->getPageZoomFactor())
{
mMediaSource->setPageZoomFactor( scale_factor );
mUpdateScrolls = true;
}
if(mClearCache)
{
@ -739,10 +746,11 @@ void LLMediaCtrl::draw()
{
F32 alpha = getDrawContext().mAlpha;
if ( gRestoreGL == 1 )
if ( gRestoreGL == 1 || mUpdateScrolls)
{
LLRect r = getRect();
reshape( r.getWidth(), r.getHeight(), FALSE );
mUpdateScrolls = false;
return;
}
@ -784,7 +792,12 @@ void LLMediaCtrl::draw()
{
gGL.pushUIMatrix();
{
mMediaSource->setPageZoomFactor( LLUI::getScaleFactor().mV[ VX ] );
F32 scale_factor = LLUI::getScaleFactor().mV[ VX ];
if (scale_factor != mMediaSource->getPageZoomFactor())
{
mMediaSource->setPageZoomFactor( scale_factor );
mUpdateScrolls = true;
}
// scale texture to fit the space using texture coords
gGL.getTexUnit(0)->bind(media_texture);
@ -989,11 +1002,11 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
case MEDIA_EVENT_CLICK_LINK_HREF:
{
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << self->getClickTarget() << "\", uri is " << self->getClickURL() << LL_ENDL;
// retrieve the event parameters
std::string url = self->getClickURL();
std::string target = self->getClickTarget();
std::string target = self->isOverrideClickTarget() ? self->getOverrideClickTarget() : self->getClickTarget();
std::string uuid = self->getClickUUID();
LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_CLICK_LINK_HREF, target is \"" << target << "\", uri is " << url << LL_ENDL;
LLNotification::Params notify_params;
notify_params.name = "PopupAttempt";

View File

@ -193,7 +193,8 @@ public:
mHidingInitialLoad,
mClearCache,
mHoverTextChanged,
mDecoupleTextureSize;
mDecoupleTextureSize,
mUpdateScrolls;
std::string mHomePageUrl,
mHomePageMimeType,

View File

@ -309,7 +309,15 @@ void LLFloaterMove::onFlyButtonClick()
void LLFloaterMove::setMovementMode(const EMovementMode mode)
{
mCurrentMode = mode;
gAgent.setFlying(MM_FLY == mode);
if(MM_FLY == mode)
{
LLAgent::toggleFlying();
}
else
{
gAgent.setFlying(FALSE);
}
// attempts to set avatar flying can not set it real flying in some cases.
// For ex. when avatar fell down & is standing up.

View File

@ -134,8 +134,14 @@ BOOL LLNameListCtrl::handleDragAndDrop(
return handled;
}
void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group)
void LLNameListCtrl::showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience)
{
if(is_experience)
{
LLFloaterReg::showInstance("experience_profile", avatar_id, true);
return;
}
if (is_group)
LLFloaterReg::showInstance("inspect_group", LLSD().with("group_id", avatar_id));
else
@ -234,10 +240,11 @@ BOOL LLNameListCtrl::handleToolTip(S32 x, S32 y, MASK mask)
// Should we show a group or an avatar inspector?
bool is_group = hit_item->isGroup();
bool is_experience = hit_item->isExperience();
LLToolTip::Params params;
params.background_visible( false );
params.click_callback( boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group) );
params.click_callback( boost::bind(&LLNameListCtrl::showInspector, this, avatar_id, is_group, is_experience) );
params.delay_time(0.0f); // spawn instantly on hover
params.image( icon );
params.message("");
@ -305,7 +312,7 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(
const std::string& prefix)
{
LLUUID id = name_item.value().asUUID();
LLNameListItem* item = new LLNameListItem(name_item,name_item.target() == GROUP);
LLNameListItem* item = new LLNameListItem(name_item,name_item.target() == GROUP, name_item.target() == EXPERIENCE);
if (!item) return NULL;
@ -365,6 +372,8 @@ LLScrollListItem* LLNameListCtrl::addNameItemRow(
}
break;
}
case EXPERIENCE:
// just use supplied name
default:
break;
}

View File

@ -50,22 +50,30 @@ class LLNameListItem : public LLScrollListItem, public LLHandleProvider<LLNameLi
public:
bool isGroup() const { return mIsGroup; }
void setIsGroup(bool is_group) { mIsGroup = is_group; }
bool isExperience() const { return mIsExperience; }
void setIsExperience(bool is_experience) { mIsExperience = is_experience; }
protected:
friend class LLNameListCtrl;
LLNameListItem( const LLScrollListItem::Params& p )
: LLScrollListItem(p), mIsGroup(false)
: LLScrollListItem(p), mIsGroup(false), mIsExperience(false)
{
}
LLNameListItem( const LLScrollListItem::Params& p, bool is_group )
: LLScrollListItem(p), mIsGroup(is_group)
: LLScrollListItem(p), mIsGroup(is_group), mIsExperience(false)
{
}
LLNameListItem( const LLScrollListItem::Params& p, bool is_group, bool is_experience )
: LLScrollListItem(p), mIsGroup(is_group), mIsExperience(is_experience)
{
}
private:
bool mIsGroup;
bool mIsExperience;
};
@ -82,7 +90,8 @@ public:
{
INDIVIDUAL,
GROUP,
SPECIAL
SPECIAL,
EXPERIENCE
} ENameType;
// provide names for enums
@ -172,7 +181,7 @@ public:
/*virtual*/ void mouseOverHighlightNthItem( S32 index );
private:
void showInspector(const LLUUID& avatar_id, bool is_group);
void showInspector(const LLUUID& avatar_id, bool is_group, bool is_experience = false);
void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name, std::string suffix, LLHandle<LLNameListItem> item);
private:

View File

@ -1192,6 +1192,8 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO
targetPanel->setVisible(show);
toggleTypeSpecificControls(type);
// Update type controls here
updateTypeSpecificControls(type);
if (show)
{
@ -1203,7 +1205,6 @@ void LLPanelEditWearable::showWearable(LLViewerWearable* wearable, BOOL show, BO
mNameEditor->setText(mWearableItem->getName());
updatePanelPickerControls(type);
updateTypeSpecificControls(type);
// clear and rebuild visual param list
U8 num_subparts = wearable_entry->mSubparts.size();

View File

@ -33,6 +33,7 @@
#include "llfloaterexperiencepicker.h"
#include "llfloaterreg.h"
#include "llhandle.h"
#include "llnamelistctrl.h"
#include "llscrolllistctrl.h"
#include "llviewerregion.h"
#include "llagent.h"
@ -54,7 +55,7 @@ LLPanelExperienceListEditor::LLPanelExperienceListEditor()
BOOL LLPanelExperienceListEditor::postBuild()
{
mItems = getChild<LLScrollListCtrl>("experience_list");
mItems = getChild<LLNameListCtrl>("experience_list");
mAdd = getChild<LLButton>("btn_add");
mRemove = getChild<LLButton>("btn_remove");
mProfile = getChild<LLButton>("btn_profile");
@ -186,12 +187,13 @@ void LLPanelExperienceListEditor::onItems()
{
const LLUUID& experience = *it;
item["id"]=experience;
item["target"] = LLNameListCtrl::EXPERIENCE;
LLSD& columns = item["columns"];
columns[0]["column"] = "experience_name";
columns[0]["value"] = getString("loading");
mItems->addElement(item);
LLExperienceCache::get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback,
LLExperienceCache::get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback,
getDerivedHandle<LLPanelExperienceListEditor>(), _1));
}

View File

@ -31,6 +31,7 @@
#include "lluuid.h"
#include <set>
class LLNameListCtrl;
class LLScrollListCtrl;
class LLButton;
class LLFloaterExperiencePicker;
@ -82,7 +83,7 @@ private:
uuid_list_t mExperienceIds;
LLScrollListCtrl* mItems;
LLNameListCtrl* mItems;
filter_list mFilters;
LLButton* mAdd;
LLButton* mRemove;

View File

@ -42,6 +42,7 @@
#include "llviewercontrol.h"
#include "llfloater.h"
#include "lltrans.h"
#include <boost/regex.hpp>
#define BTN_FIND "find"
#define BTN_OK "ok_btn"
@ -148,6 +149,46 @@ void LLPanelExperiencePicker::editKeystroke( class LLLineEditor* caller, void* u
void LLPanelExperiencePicker::onBtnFind()
{
mCurrentPage=1;
boost::cmatch what;
std::string text = getChild<LLUICtrl>(TEXT_EDIT)->getValue().asString();
const boost::regex expression("secondlife:///app/experience/[\\da-f-]+/profile");
if (boost::regex_match(text.c_str(), what, expression))
{
LLURI uri(text);
LLSD path_array = uri.pathArray();
if (path_array.size() == 4)
{
std::string exp_id = path_array.get(2).asString();
LLUUID experience_id(exp_id);
if (!experience_id.isNull())
{
const LLSD& experience_details = LLExperienceCache::get(experience_id);
if(!experience_details.isUndefined())
{
std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString();
if(!experience_name_string.empty())
{
getChild<LLUICtrl>(TEXT_EDIT)->setValue(experience_name_string);
}
}
else
{
getChild<LLScrollListCtrl>(LIST_RESULTS)->deleteAllItems();
getChild<LLScrollListCtrl>(LIST_RESULTS)->setCommentText(getString("searching"));
getChildView(BTN_OK)->setEnabled(FALSE);
getChildView(BTN_PROFILE)->setEnabled(FALSE);
getChildView(BTN_RIGHT)->setEnabled(FALSE);
getChildView(BTN_LEFT)->setEnabled(FALSE);
LLExperienceCache::get(experience_id, boost::bind(&LLPanelExperiencePicker::onBtnFind, this));
return;
}
}
}
}
find();
}
@ -184,7 +225,6 @@ void LLPanelExperiencePicker::find()
getChildView(BTN_LEFT)->setEnabled(FALSE);
}
bool LLPanelExperiencePicker::isSelectButtonEnabled()
{
LLScrollListCtrl* list=getChild<LLScrollListCtrl>(LIST_RESULTS);

View File

@ -361,7 +361,7 @@ private:
LLMaterialMgr::getInstance()->put(object->getID(),face,*new_material);
}
object->setTEMaterialParams(face, new_material);
object->setTEMaterialParams(face, new_material, TRUE);
return new_material;
}
return NULL;

View File

@ -367,7 +367,7 @@ void LLPanelGroup::update(LLGroupChange gc)
// </FS:Ansariel>
LLGroupData agent_gdatap;
bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlike();
bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlikeWithoutAdminMenuFakery();
bool join_btn_visible = !is_member && gdatap->mOpenEnrollment;
mButtonJoin->setVisible(join_btn_visible);
@ -499,7 +499,7 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
}
LLGroupData agent_gdatap;
bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlike();
bool is_member = gAgent.getGroupData(mID,agent_gdatap) || gAgent.isGodlikeWithoutAdminMenuFakery();
tab_roles->setVisible(is_member);
tab_notices->setVisible(is_member);

View File

@ -243,56 +243,59 @@ void LLPanelGroupInvite::impl::addRoleNames(LLGroupMgrGroupData* gdatap)
LLGroupMgrGroupData::member_list_t::iterator agent_iter =
gdatap->mMembers.find(gAgent.getID());
//get the member data for the agent if it exists
if ( agent_iter != gdatap->mMembers.end() )
{
LLGroupMemberData* member_data = (*agent_iter).second;
//loop over the agent's roles in the group
//then add those roles to the list of roles that the agent
//can invite people to be
if ( member_data && mRoleNames)
{
//if the user is the owner then we add
//all of the roles in the group
//else if they have the add to roles power
//we add every role but owner,
//else if they have the limited add to roles power
//we add every role the user is in
//else we just add to everyone
bool is_owner = member_data->isOwner();
bool can_assign_any = gAgent.hasPowerInGroup(mGroupID,
//loop over the agent's roles in the group
//then add those roles to the list of roles that the agent
//can invite people to be.
//if the user is the owner then we add
//all of the roles in the group,
//else if they have the add to roles power
//we add every role but owner,
//else if they have the limited add to roles power
//we add every role the user is in,
//else we just add to everyone
bool is_owner = FALSE;
bool can_assign_any = gAgent.hasPowerInGroup(mGroupID,
GP_ROLE_ASSIGN_MEMBER);
bool can_assign_limited = gAgent.hasPowerInGroup(mGroupID,
GP_ROLE_ASSIGN_MEMBER_LIMITED);
LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.begin();
LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end();
//populate the role list
for ( ; rit != end; ++rit)
{
LLUUID role_id = (*rit).first;
LLRoleData rd;
if ( gdatap->getRoleData(role_id,rd) )
{
// Owners can add any role.
if ( is_owner
// Even 'can_assign_any' can't add owner role.
|| (can_assign_any && role_id != gdatap->mOwnerRole)
// Add all roles user is in
|| (can_assign_limited && member_data->isInRole(role_id))
// Everyone role.
|| role_id == LLUUID::null )
{
mRoleNames->add(rd.mRoleName,
role_id,
ADD_BOTTOM);
}
}
}
bool can_assign_limited = gAgent.hasPowerInGroup(mGroupID,
GP_ROLE_ASSIGN_MEMBER_LIMITED);
LLGroupMemberData* member_data = NULL;
//get the member data for the agent if it exists
if (agent_iter != gdatap->mMembers.end())
{
member_data = (*agent_iter).second;
if (member_data && mRoleNames)
{
is_owner = member_data->isOwner();
}//end if member data is not null
}//end if agent is in the group
LLGroupMgrGroupData::role_list_t::iterator rit = gdatap->mRoles.begin();
LLGroupMgrGroupData::role_list_t::iterator end = gdatap->mRoles.end();
//populate the role list:
for ( ; rit != end; ++rit)
{
LLUUID role_id = (*rit).first;
LLRoleData rd;
if ( gdatap->getRoleData(role_id,rd) )
{
// Owners can add any role.
if ( is_owner
// Even 'can_assign_any' can't add owner role.
|| (can_assign_any && role_id != gdatap->mOwnerRole)
// Add all roles user is in
|| (can_assign_limited && member_data && member_data->isInRole(role_id))
// Everyone role.
|| role_id == LLUUID::null )
{
mRoleNames->add(rd.mRoleName,
role_id,
ADD_BOTTOM);
}
}
}
}
//static
@ -581,7 +584,8 @@ void LLPanelGroupInvite::updateLists()
{
waiting = true;
}
if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete() && gdatap->isRoleMemberDataComplete())
if (gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete()
&& (gdatap->isRoleMemberDataComplete() || !gdatap->mMembers.size())) // MAINT-5270: large groups receives an empty members list without some powers, so RoleMemberData wouldn't be complete for them
{
if ( mImplementation->mRoleNames )
{

View File

@ -354,12 +354,10 @@ void LLPanelGroupRoles::update(LLGroupChange gc)
void LLPanelGroupRoles::activate()
{
if (!gAgent.isInGroup(mGroupID)) return;
// Start requesting member and role data if needed.
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
if (!gdatap || !gdatap->isMemberDataComplete() )
{
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
}
if (!gdatap || !gdatap->isRoleDataComplete() )
{
@ -368,13 +366,7 @@ void LLPanelGroupRoles::activate()
LLGroupMgr::getInstance()->sendGroupRoleDataRequest(mGroupID);
}
// Check role-member mapping data.
if (!gdatap || !gdatap->isRoleMemberDataComplete() )
{
LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
}
// Need this to get base group member powers
if (!gdatap || !gdatap->isGroupPropertiesDataComplete() )
{
@ -1182,7 +1174,37 @@ void LLPanelGroupMembersSubTab::onEjectMembers(void *userdata)
if ( selfp )
{
selfp->handleEjectMembers();
selfp->confirmEjectMembers();
}
}
void LLPanelGroupMembersSubTab::confirmEjectMembers()
{
std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
if (selection.empty()) return;
S32 selection_count = selection.size();
if (selection_count == 1)
{
LLSD args;
std::string fullname;
gCacheName->getFullName(mMembersList->getValue(), fullname);
args["AVATAR_NAME"] = fullname;
LLSD payload;
LLNotificationsUtil::add("EjectGroupMemberWarning",
args,
payload,
boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2));
}
else
{
LLSD args;
args["COUNT"] = llformat("%d", selection_count);
LLSD payload;
LLNotificationsUtil::add("EjectGroupMembersWarning",
args,
payload,
boost::bind(&LLPanelGroupMembersSubTab::handleEjectCallback, this, _1, _2));
}
}
@ -1209,6 +1231,16 @@ void LLPanelGroupMembersSubTab::handleEjectMembers()
LLGroupMgr::getInstance()->sendGroupMemberEjects(mGroupID, selected_members);
}
bool LLPanelGroupMembersSubTab::handleEjectCallback(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option) // Eject button
{
handleEjectMembers();
}
return false;
}
void LLPanelGroupMembersSubTab::sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members)
{
LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(group_id);
@ -1348,15 +1380,26 @@ void LLPanelGroupMembersSubTab::handleMemberDoubleClick()
void LLPanelGroupMembersSubTab::activate()
{
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
LLPanelGroupSubTab::activate();
if(!mActivated)
{
if (!gdatap || !gdatap->isMemberDataComplete())
{
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
}
if (!gdatap || !gdatap->isRoleMemberDataComplete())
{
LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
}
update(GC_ALL);
mActivated = true;
}
else
{
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mGroupID);
// Members can be removed outside of this tab, checking changes
if (!gdatap || (gdatap->isMemberDataComplete() && gdatap->mMembers.size() != mMembersList->getItemCount()))
{
@ -1657,7 +1700,13 @@ void LLPanelGroupMembersSubTab::update(LLGroupChange gc)
{
// Build a string with info on retrieval progress.
std::ostringstream retrieved;
if ( !gdatap->isMemberDataComplete() )
if ( gdatap->isRoleDataComplete() && gdatap->isMemberDataComplete() && !gdatap->mMembers.size() )
{
// MAINT-5237
retrieved << "Member list not available.";
}
else if ( !gdatap->isMemberDataComplete() )
{
// Still busy retreiving member list.
retrieved << "Retrieving member list (" << gdatap->mMembers.size()
@ -1821,7 +1870,7 @@ void LLPanelGroupMembersSubTab::updateMembers()
{
mMembersList->setEnabled(TRUE);
}
else
else if (gdatap->mMembers.size())
{
mMembersList->setEnabled(FALSE);
mMembersList->setCommentText(std::string("No match."));
@ -1839,7 +1888,47 @@ void LLPanelGroupMembersSubTab::updateMembers()
void LLPanelGroupMembersSubTab::onBanMember(void* user_data)
{
LLPanelGroupMembersSubTab* self = static_cast<LLPanelGroupMembersSubTab*>(user_data);
self->handleBanMember();
self->confirmBanMembers();
}
void LLPanelGroupMembersSubTab::confirmBanMembers()
{
std::vector<LLScrollListItem*> selection = mMembersList->getAllSelected();
if (selection.empty()) return;
S32 selection_count = selection.size();
if (selection_count == 1)
{
LLSD args;
std::string fullname;
gCacheName->getFullName(mMembersList->getValue(), fullname);
args["AVATAR_NAME"] = fullname;
LLSD payload;
LLNotificationsUtil::add("BanGroupMemberWarning",
args,
payload,
boost::bind(&LLPanelGroupMembersSubTab::handleBanCallback, this, _1, _2));
}
else
{
LLSD args;
args["COUNT"] = llformat("%d", selection_count);
LLSD payload;
LLNotificationsUtil::add("BanGroupMembersWarning",
args,
payload,
boost::bind(&LLPanelGroupMembersSubTab::handleBanCallback, this, _1, _2));
}
}
bool LLPanelGroupMembersSubTab::handleBanCallback(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if (0 == option) // Eject button
{
handleBanMember();
}
return false;
}
// [FS:CR] FIRE-12276
@ -2189,20 +2278,7 @@ void LLPanelGroupRolesSubTab::update(LLGroupChange gc)
mDeleteRoleButton->setEnabled(FALSE);
}
}
if(!mFirstOpen)
{
if (!gdatap || !gdatap->isMemberDataComplete())
{
LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID);
}
if (!gdatap || !gdatap->isRoleMemberDataComplete())
{
LLGroupMgr::getInstance()->sendGroupRoleMembersRequest(mGroupID);
}
}
if ((GC_ROLE_MEMBER_DATA == gc || GC_MEMBER_DATA == gc)
&& gdatap
&& gdatap->isMemberDataComplete()

View File

@ -171,6 +171,7 @@ public:
void handleEjectMembers();
void sendEjectNotifications(const LLUUID& group_id, const uuid_vec_t& selected_members);
bool handleEjectCallback(const LLSD& notification, const LLSD& response);
void confirmEjectMembers();
static void onRoleCheck(LLUICtrl* check, void* user_data);
void handleRoleCheck(const LLUUID& role_id,
@ -178,6 +179,8 @@ public:
static void onBanMember(void* user_data);
void handleBanMember();
bool handleBanCallback(const LLSD& notification, const LLSD& response);
void confirmBanMembers();
void applyMemberChanges();

View File

@ -147,6 +147,7 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type)
}
else
{
LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_NORMAL, agent_pos);
region_name = desc;
}

View File

@ -920,7 +920,7 @@ void LLPanelMainInventory::updateItemcountText()
}
else
{
text = getString("ItemcountUnknown");
text = getString("ItemcountUnknown", string_args);
}
mCounterCtrl->setValue(text);

View File

@ -319,6 +319,10 @@ void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& _media
// Helper to set media control to media URL as required
void LLPanelMediaSettingsGeneral::updateMediaPreview()
{
if(LLTrans::getString("Multiple Media") == mHomeURL->getValue().asString())
{
return;
}
if ( mHomeURL->getValue().asString().length() > 0 )
{
if(mPreviewMedia->getCurrentNavUrl() != mHomeURL->getValue().asString())

View File

@ -2153,9 +2153,10 @@ void LLPanelObject::sendSculpt()
return;
LLSculptParams sculpt_params;
LLUUID sculpt_id = LLUUID::null;
if (mCtrlSculptTexture)
sculpt_params.setSculptTexture(mCtrlSculptTexture->getImageAssetID());
sculpt_id = mCtrlSculptTexture->getImageAssetID();
U8 sculpt_type = 0;
@ -2179,7 +2180,7 @@ void LLPanelObject::sendSculpt()
if ((mCtrlSculptInvert) && (mCtrlSculptInvert->get()))
sculpt_type |= LL_SCULPT_FLAG_INVERT;
sculpt_params.setSculptType(sculpt_type);
sculpt_params.setSculptTexture(sculpt_id, sculpt_type);
mObject->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE);
}
@ -2416,7 +2417,11 @@ void LLPanelObject::onCancelSculpt(const LLSD& data)
LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control");
if(!mTextureCtrl)
return;
if(mSculptTextureRevert == LLUUID::null)
{
mSculptTextureRevert = LLUUID(SCULPT_DEFAULT_TEXTURE);
}
mTextureCtrl->setImageAssetID(mSculptTextureRevert);
sendSculpt();
@ -2744,10 +2749,7 @@ void LLPanelObject::onPasteParams(const LLSD& data)
LLSculptParams sculpt_params;
if (mPramsClipboard.has("sculptid"))
sculpt_params.setSculptTexture(mPramsClipboard["sculptid"].asUUID());
if (mPramsClipboard.has("sculptid"))
sculpt_params.setSculptType((U8)mPramsClipboard["sculpt_type"].asInteger());
sculpt_params.setSculptTexture(mPramsClipboard["sculptid"].asUUID(), (U8)mPramsClipboard["sculpt_type"].asInteger());
objectp->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE);
}

View File

@ -98,6 +98,9 @@ static const std::string BLOCKED_TAB_NAME = "blocked_panel"; // blocked avatars
static const std::string CONTACT_SETS_TAB_NAME = "contact_sets_panel"; // [FS:CR] Contact sets
static const std::string COLLAPSED_BY_USER = "collapsed_by_user";
const S32 BASE_MAX_AGENT_GROUPS = 42;
const S32 PREMIUM_MAX_AGENT_GROUPS = 60;
// [FS] FIRE-12229
//extern S32 gMaxAgentGroups;
@ -631,6 +634,7 @@ BOOL LLPanelPeople::postBuild()
getChild<LLFilterEditor>("groups_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
getChild<LLFilterEditor>("recent_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2));
//getChild<LLFilterEditor>("fbc_filter_input")->setCommitCallback(boost::bind(&LLPanelPeople::onFilterEdit, this, _2)); // <FS:Ansariel> Doesn't exist anymore
getChild<LLTextBox>("groupcount")->setURLClickedCallback(boost::bind(&LLPanelPeople::onGroupLimitInfo, this));
mTabContainer = getChild<LLTabContainer>("tabs");
mTabContainer->setCommitCallback(boost::bind(&LLPanelPeople::onTabSelected, this, _2));
@ -1018,9 +1022,12 @@ void LLPanelPeople::updateButtons()
LLPanel* groups_panel = mTabContainer->getCurrentPanel();
groups_panel->getChildView("minus_btn")->setEnabled(item_selected && selected_id.notNull()); // a real group selected
// [CR] FIRE-12229
//groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d",gAgent.mGroups.size()));
//groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[REMAINING]", llformat("%d",(gMaxAgentGroups-gAgent.mGroups.size())));
//U32 groups_count = gAgent.mGroups.size();
//U32 groups_ramaining = gMaxAgentGroups > groups_count ? gMaxAgentGroups - groups_count : 0;
//groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[COUNT]", llformat("%d", groups_count));
//groups_panel->getChild<LLUICtrl>("groupcount")->setTextArg("[REMAINING]", llformat("%d", groups_ramaining));
getChild<LLUICtrl>("groupcount")->setValue(FSCommon::populateGroupCount());
// [/CR]
}
@ -1261,6 +1268,14 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)
}
}
void LLPanelPeople::onGroupLimitInfo()
{
LLSD args;
args["MAX_BASIC"] = BASE_MAX_AGENT_GROUPS;
args["MAX_PREMIUM"] = PREMIUM_MAX_AGENT_GROUPS;
LLNotificationsUtil::add("GroupLimitInfo", args);
}
void LLPanelPeople::onTabSelected(const LLSD& param)
{
std::string tab_name = getChild<LLPanel>(param.asString())->getName();

View File

@ -105,6 +105,7 @@ private:
// UI callbacks
void onFilterEdit(const std::string& search_string);
void onGroupLimitInfo();
void onTabSelected(const LLSD& param);
void onAddFriendButtonClicked();
void onAddFriendWizButtonClicked();

View File

@ -450,7 +450,7 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
mNoPicks = !mPicksList->size();
}
else if(APT_CLASSIFIEDS == type)
else if((APT_CLASSIFIEDS == type) || (APT_CLASSIFIED_INFO == type))
{
LLAvatarClassifieds* c_info = static_cast<LLAvatarClassifieds*>(data);
if(c_info && getAvatarId() == c_info->target_id)

View File

@ -963,7 +963,12 @@ void LLPanelPlaces::onBackButtonClicked()
void LLPanelPlaces::togglePickPanel(BOOL visible)
{
if (mPickPanel)
{
mPickPanel->setVisible(visible);
mPlaceProfile->setVisible(!visible);
updateVerbs();
}
}
void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
@ -1183,16 +1188,21 @@ void LLPanelPlaces::updateVerbs()
bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE;
bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE;
bool is_pick_panel_visible = false;
if(mPickPanel)
{
is_pick_panel_visible = mPickPanel->isInVisibleChain();
}
bool have_3d_pos = ! mPosGlobal.isExactlyZero();
mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible);
mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible);
mOverflowBtn->setVisible(is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn);
mEditBtn->setVisible(mPlaceInfoType == LANDMARK_INFO_TYPE && !isLandmarkEditModeOn);
mSaveBtn->setVisible(isLandmarkEditModeOn);
mCancelBtn->setVisible(isLandmarkEditModeOn);
mCloseBtn->setVisible(is_create_landmark_visible && !isLandmarkEditModeOn);
mPlaceInfoBtn->setVisible(!is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn);
mPlaceInfoBtn->setVisible(!is_place_info_visible && !is_create_landmark_visible && !isLandmarkEditModeOn && !is_pick_panel_visible);
mPlaceInfoBtn->setEnabled(!is_create_landmark_visible && !isLandmarkEditModeOn && have_3d_pos);

View File

@ -328,19 +328,11 @@ void LLPanelTopInfoBar::updateParcelIcons()
bool allow_damage = vpm->allowAgentDamage(agent_region, current_parcel);
bool see_avs = current_parcel->getSeeAVs();
// <FS:Ansariel> Undo MAIN-23 for now...
//bool is_parcel_owner = (gAgent.getID() == current_parcel->getOwnerID());
//bool allow_group_modify = (gAgent.isInGroup(current_parcel->getGroupID()) && current_parcel->getAllowGroupModify());
// </FS:Ansariel>
// Most icons are "block this ability"
mParcelIcon[VOICE_ICON]->setVisible( !allow_voice );
mParcelIcon[FLY_ICON]->setVisible( !allow_fly );
mParcelIcon[PUSH_ICON]->setVisible( !allow_push );
// <FS:Ansariel> Undo MAIN-23 for now...
//mParcelIcon[BUILD_ICON]->setVisible( !allow_build && !is_parcel_owner && !allow_group_modify );
mParcelIcon[BUILD_ICON]->setVisible( !allow_build );
// </FS:Ansariel>
mParcelIcon[SCRIPTS_ICON]->setVisible( !allow_scripts );
mParcelIcon[DAMAGE_ICON]->setVisible( allow_damage );
mDamageText->setVisible(allow_damage);

View File

@ -1751,6 +1751,8 @@ void LLLiveLSLEditor::buildExperienceList()
else
{
mExperiences->setEnabled(TRUE);
mExperiences->sortByName(TRUE);
mExperiences->setCurrentByIndex(mExperiences->getCurrentIndex());
getChild<LLButton>("view_profile")->setVisible(TRUE);
}
}
@ -3243,12 +3245,16 @@ void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save, bool sync)
// </FS:Ansariel>
{
LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
self->mCloseAfterSave = close_after_save;
// <FS:Ansariel> FIRE-7514: Script in external editor needs to be saved twice
//self->saveIfNeeded();
self->saveIfNeeded(sync);
// </FS:Ansariel>
if(self)
{
self->mCloseAfterSave = close_after_save;
// <FS:Ansariel> Commented out because we fixed errors differently
//self->mScriptEd->mErrorList->setCommentText("");
// <FS:Ansariel> FIRE-7514: Script in external editor needs to be saved twice
//self->saveIfNeeded();
self->saveIfNeeded(sync);
// </FS:Ansariel>
}
}

View File

@ -1076,4 +1076,5 @@ void LLPreviewTexture::setObjectID(const LLUUID& object_id)
mAssetStatus = PREVIEW_ASSET_UNLOADED;
loadAsset();
}
refreshFromItem();
}

View File

@ -2204,7 +2204,7 @@ void LLSelectMgr::selectionRemoveMaterial()
{
LL_DEBUGS("Materials") << "Removing material from object " << object->getID() << " face " << face << LL_ENDL;
LLMaterialMgr::getInstance()->remove(object->getID(),face);
object->setTEMaterialParams(face, NULL);
object->setTEMaterialParams(face, NULL, FALSE);
}
return true;
}
@ -5119,6 +5119,7 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
ESendType send_type)
{
LLSelectNode* node;
LLSelectNode* linkset_root = NULL;
LLViewerRegion* last_region;
LLViewerRegion* current_region;
@ -5126,6 +5127,8 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
S32 packets_sent = 0;
S32 objects_in_this_packet = 0;
bool link_operation = message_name == "ObjectLink";
//clear update override data (allow next update through)
struct f : public LLSelectedNodeFunctor
{
@ -5234,6 +5237,12 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
&& (! gMessageSystem->isSendFull(NULL))
&& (objects_in_this_packet < MAX_OBJECTS_PER_PACKET))
{
if (link_operation && linkset_root == NULL)
{
// linksets over 254 will be split into multiple messages,
// but we need to provide same root for all messages or we will get separate linksets
linkset_root = node;
}
// add another instance of the body of the data
(*pack_body)(node, user_data);
// do any related logging
@ -5262,6 +5271,22 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
gMessageSystem->newMessage(message_name.c_str());
(*pack_header)(user_data);
if (linkset_root != NULL)
{
if (current_region != last_region)
{
// root should be in one region with the child, reset it
linkset_root = NULL;
}
else
{
// add root instance into new message
(*pack_body)(linkset_root, user_data);
++objects_sent;
++objects_in_this_packet;
}
}
// don't move to the next object, we still need to add the
// body data.
}

Some files were not shown because too many files have changed in this diff Show More