Merge from v2 trunk.

master
Tofu Linden 2010-01-22 15:18:08 -08:00
commit 9e0920df2c
137 changed files with 3332 additions and 2568 deletions

View File

@ -76,11 +76,16 @@ public:
return dictionary_iter->first;
}
}
llassert(false);
return Index(-1);
return notFound();
}
protected:
virtual Index notFound() const
{
// default is to assert
llassert(false);
return Index(-1);
}
void addEntry(Index index, Entry *entry)
{
if (lookup(index))

View File

@ -75,6 +75,10 @@ const int LL_ERR_PRICE_MISMATCH = -23018;
#define SHOW_ASSERT
#else // _DEBUG
#ifdef LL_RELEASE_WITH_DEBUG_INFO
#define SHOW_ASSERT
#endif // LL_RELEASE_WITH_DEBUG_INFO
#ifdef RELEASE_SHOW_DEBUG
#define SHOW_DEBUG
#endif

View File

@ -59,6 +59,11 @@ class LLFolderDictionary : public LLSingleton<LLFolderDictionary>,
{
public:
LLFolderDictionary();
protected:
virtual LLFolderType::EType notFound() const
{
return LLFolderType::FT_NONE;
}
};
LLFolderDictionary::LLFolderDictionary()

View File

@ -668,6 +668,12 @@ void LLImageRaw::fill( const LLColor4U& color )
// Src and dst can be any size. Src and dst can each have 3 or 4 components.
void LLImageRaw::copy(LLImageRaw* src)
{
if (!src)
{
llwarns << "LLImageRaw::copy called with a null src pointer" << llendl;
return;
}
LLImageRaw* dst = this; // Just for clarity.
llassert( (3 == src->getComponents()) || (4 == src->getComponents()) );

View File

@ -89,6 +89,10 @@ S32 gCurlMultiCount = 0;
std::vector<LLMutex*> LLCurl::sSSLMutex;
std::string LLCurl::sCAPath;
std::string LLCurl::sCAFile;
// Verify SSL certificates by default (matches libcurl default). The ability
// to alter this flag is only to allow us to suppress verification if it's
// broken for some reason.
bool LLCurl::sSSLVerify = true;
//static
void LLCurl::setCAPath(const std::string& path)
@ -102,6 +106,18 @@ void LLCurl::setCAFile(const std::string& file)
sCAFile = file;
}
//static
void LLCurl::setSSLVerify(bool verify)
{
sSSLVerify = verify;
}
//static
bool LLCurl::getSSLVerify()
{
return sSSLVerify;
}
//static
std::string LLCurl::getVersionString()
{
@ -465,7 +481,8 @@ void LLCurl::Easy::prepRequest(const std::string& url,
setErrorBuffer();
setCA();
setopt(CURLOPT_SSL_VERIFYPEER, true);
setopt(CURLOPT_SSL_VERIFYPEER, LLCurl::getSSLVerify());
setopt(CURLOPT_SSL_VERIFYHOST, LLCurl::getSSLVerify()? 2 : 0);
setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT);
setoptString(CURLOPT_URL, url);
@ -1044,4 +1061,3 @@ void LLCurl::cleanupClass()
#endif
curl_global_cleanup();
}

View File

@ -157,6 +157,16 @@ public:
*/
static const std::string& getCAPath() { return sCAPath; }
/**
* @ brief Set flag controlling whether to verify HTTPS certs.
*/
static void setSSLVerify(bool verify);
/**
* @ brief Get flag controlling whether to verify HTTPS certs.
*/
static bool getSSLVerify();
/**
* @ brief Initialize LLCurl class
*/
@ -182,6 +192,7 @@ public:
private:
static std::string sCAPath;
static std::string sCAFile;
static bool sSSLVerify;
};
namespace boost

View File

@ -222,7 +222,7 @@ static void request(
LLPumpIO::chain_t chain;
LLURLRequest* req = new LLURLRequest(method, url);
req->checkRootCertificate(true);
req->checkRootCertificate(LLCurl::getSSLVerify());
lldebugs << LLURLRequest::actionAsVerb(method) << " " << url << " "

View File

@ -163,6 +163,7 @@ void LLURLRequest::setBodyLimit(U32 size)
void LLURLRequest::checkRootCertificate(bool check)
{
mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, (check? TRUE : FALSE));
mDetail->mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, (check? 2 : 0));
mDetail->mCurlRequest->setoptString(CURLOPT_ENCODING, "");
}

View File

@ -1022,6 +1022,20 @@ void LLButton::setImageOverlay(const std::string& image_name, LLFontGL::HAlign a
}
}
void LLButton::setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment, const LLColor4& color)
{
if (image_id.isNull())
{
mImageOverlay = NULL;
}
else
{
mImageOverlay = LLUI::getUIImageByID(image_id);
mImageOverlayAlignment = alignment;
mImageOverlayColor = color;
}
}
void LLButton::onMouseCaptureLost()
{
resetMouseDownTimer();

View File

@ -200,6 +200,7 @@ public:
void setDisabledSelectedLabelColor( const LLColor4& c ) { mDisabledSelectedLabelColor = c; }
void setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);
void setImageOverlay(const LLUUID& image_id, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white);
LLPointer<LLUIImage> getImageOverlay() { return mImageOverlay; }
void autoResize(); // resize with label of current btn state

View File

@ -1360,6 +1360,7 @@ void LLFloater::bringToFront( S32 x, S32 y )
// virtual
void LLFloater::setVisibleAndFrontmost(BOOL take_focus)
{
gFocusMgr.setTopCtrl(NULL);
setVisible(TRUE);
setFrontmost(take_focus);
}

View File

@ -1507,6 +1507,37 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
}
}
void LLTabContainer::setTabImage(LLPanel* child, const LLUUID& image_id, const LLColor4& color)
{
static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
LLTabTuple* tuple = getTabByPanel(child);
if( tuple )
{
tuple->mButton->setImageOverlay(image_id, LLFontGL::RIGHT, color);
if (!mIsVertical)
{
// remove current width from total tab strip width
mTotalTabWidth -= tuple->mButton->getRect().getWidth();
S32 image_overlay_width = tuple->mButton->getImageOverlay().notNull() ?
tuple->mButton->getImageOverlay()->getImage()->getWidth(0) :
0;
tuple->mPadding = image_overlay_width;
tuple->mButton->setRightHPad(6);
tuple->mButton->reshape(llclamp(mFont->getWidth(tuple->mButton->getLabelSelected()) + tab_padding + tuple->mPadding, mMinTabWidth, mMaxTabWidth),
tuple->mButton->getRect().getHeight());
// add back in button width to total tab strip width
mTotalTabWidth += tuple->mButton->getRect().getWidth();
// tabs have changed size, might need to scroll to see current tab
updateMaxScrollPos();
}
}
}
void LLTabContainer::setTitle(const std::string& title)
{
if (mTitleBox)

View File

@ -172,6 +172,7 @@ public:
BOOL getTabPanelFlashing(LLPanel* child);
void setTabPanelFlashing(LLPanel* child, BOOL state);
void setTabImage(LLPanel* child, std::string img_name, const LLColor4& color = LLColor4::white);
void setTabImage(LLPanel* child, const LLUUID& img_id, const LLColor4& color = LLColor4::white);
void setTitle( const std::string& title );
const std::string getPanelTitle(S32 index);

View File

@ -268,8 +268,8 @@ ATTACH_LHIP Passed to llAttachToAvatar to attach task to left hip
ATTACH_LULEG Passed to llAttachToAvatar to attach task to left upper leg
ATTACH_LLLEG Passed to llAttachToAvatar to attach task to left lower leg
ATTACH_BELLY Passed to llAttachToAvatar to attach task to belly
ATTACH_RPEC Passed to llAttachToAvatar to attach task to right pectoral
ATTACH_LPEC Passed to llAttachToAvatar to attach task to left pectoral
ATTACH_LEFT_PEC Passed to llAttachToAvatar to attach task to left pectoral
ATTACH_RIGHT_PEC Passed to llAttachToAvatar to attach task to right pectoral
LAND_LEVEL Passed to llModifyLand to level terrain
LAND_RAISE Passed to llModifyLand to raise terrain

View File

@ -1145,17 +1145,6 @@
<key>Value</key>
<integer>5</integer>
</map>
<key>CallFloaterMaxItems</key>
<map>
<key>Comment</key>
<string>Max number of visible participants in voice controls window</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>CameraAngle</key>
<map>
<key>Comment</key>
@ -3629,7 +3618,7 @@
<key>Type</key>
<string>String</string>
<key>Value</key>
<string>http://int.searchwww-phx0.damballah.lindenlab.com/viewer/[CATEGORY]?q=[QUERY]&amp;p=[AUTH_TOKEN]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]&amp;sid=[SESSION_ID]&amp;rid=[REGION_ID]&amp;pid=[PARCEL_ID]</string>
<string>http://search.secondlife.com/viewer/[CATEGORY]?q=[QUERY]&amp;p=[AUTH_TOKEN]&amp;r=[MATURITY]&amp;lang=[LANGUAGE]&amp;g=[GODLIKE]&amp;sid=[SESSION_ID]&amp;rid=[REGION_ID]&amp;pid=[PARCEL_ID]</string>
</map>
<key>HighResSnapshot</key>
<map>
@ -10104,6 +10093,18 @@
<key>Value</key>
<integer>0</integer>
</map>
<key>SpeakerParticipantRemoveDelay</key>
<map>
<key>Comment</key>
<string>Timeout to remove participants who is not in channel before removed from list of active speakers (text/voice chat)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>10.0</real>
</map>
<key>UseStartScreen</key>
<map>
<key>Comment</key>

View File

@ -274,6 +274,7 @@ private:
struct LLFoundData
{
LLFoundData() {}
LLFoundData(const LLUUID& item_id,
const LLUUID& asset_id,
const std::string& name,
@ -292,20 +293,94 @@ struct LLFoundData
};
struct LLWearableHoldingPattern
class LLWearableHoldingPattern
{
LLWearableHoldingPattern() : mResolved(0) {}
~LLWearableHoldingPattern()
{
for_each(mFoundList.begin(), mFoundList.end(), DeletePointer());
mFoundList.clear();
}
typedef std::list<LLFoundData*> found_list_t;
public:
LLWearableHoldingPattern();
~LLWearableHoldingPattern();
bool pollCompletion();
bool isDone();
bool isTimedOut();
typedef std::list<LLFoundData> found_list_t;
found_list_t mFoundList;
LLInventoryModel::item_array_t mObjItems;
LLInventoryModel::item_array_t mGestItems;
S32 mResolved;
bool append;
LLTimer mWaitTime;
};
LLWearableHoldingPattern::LLWearableHoldingPattern():
mResolved(0)
{
}
LLWearableHoldingPattern::~LLWearableHoldingPattern()
{
}
bool LLWearableHoldingPattern::isDone()
{
if (mResolved >= (S32)mFoundList.size())
return true; // have everything we were waiting for
else if (isTimedOut())
{
llwarns << "Exceeded max wait time, updating appearance based on what has arrived" << llendl;
return true;
}
return false;
}
bool LLWearableHoldingPattern::isTimedOut()
{
static F32 max_wait_time = 15.0; // give up if wearable fetches haven't completed in max_wait_time seconds.
return mWaitTime.getElapsedTimeF32() > max_wait_time;
}
bool LLWearableHoldingPattern::pollCompletion()
{
bool done = isDone();
llinfos << "polling, done status: " << done << " elapsed " << mWaitTime.getElapsedTimeF32() << llendl;
if (done)
{
// Activate all gestures in this folder
if (mGestItems.count() > 0)
{
llinfos << "Activating " << mGestItems.count() << " gestures" << llendl;
LLGestureManager::instance().activateGestures(mGestItems);
// Update the inventory item labels to reflect the fact
// they are active.
LLViewerInventoryCategory* catp =
gInventory.getCategory(LLAppearanceManager::instance().getCOF());
if (catp)
{
gInventory.updateCategory(catp);
gInventory.notifyObservers();
}
}
// Update wearables.
llinfos << "Updating agent wearables with " << mResolved << " wearable items " << llendl;
LLAppearanceManager::instance().updateAgentWearables(this, false);
// Update attachments to match those requested.
LLVOAvatar* avatar = gAgent.getAvatarObject();
if( avatar )
{
llinfos << "Updating " << mObjItems.count() << " attachments" << llendl;
LLAgentWearables::userUpdateAttachments(mObjItems);
}
delete this;
}
return done;
}
static void removeDuplicateItems(LLInventoryModel::item_array_t& items)
{
LLInventoryModel::item_array_t new_items;
@ -336,29 +411,24 @@ static void removeDuplicateItems(LLInventoryModel::item_array_t& items)
static void onWearableAssetFetch(LLWearable* wearable, void* data)
{
LLWearableHoldingPattern* holder = (LLWearableHoldingPattern*)data;
bool append = holder->append;
if(wearable)
{
for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
iter != holder->mFoundList.end(); ++iter)
{
LLFoundData* data = *iter;
if(wearable->getAssetID() == data->mAssetID)
LLFoundData& data = *iter;
if(wearable->getAssetID() == data.mAssetID)
{
data->mWearable = wearable;
data.mWearable = wearable;
break;
}
}
}
holder->mResolved += 1;
if(holder->mResolved >= (S32)holder->mFoundList.size())
{
LLAppearanceManager::instance().updateAgentWearables(holder, append);
}
}
LLUUID LLAppearanceManager::getCOF()
const LLUUID LLAppearanceManager::getCOF() const
{
return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
}
@ -662,12 +732,12 @@ void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder,
for (LLWearableHoldingPattern::found_list_t::iterator iter = holder->mFoundList.begin();
iter != holder->mFoundList.end(); ++iter)
{
LLFoundData* data = *iter;
LLWearable* wearable = data->mWearable;
LLFoundData& data = *iter;
LLWearable* wearable = data.mWearable;
if( wearable && ((S32)wearable->getType() == i) )
{
LLViewerInventoryItem* item;
item = (LLViewerInventoryItem*)gInventory.getItem(data->mItemID);
item = (LLViewerInventoryItem*)gInventory.getItem(data.mItemID);
if( item && (item->getAssetUUID() == wearable->getAssetID()) )
{
items.put(item);
@ -683,8 +753,6 @@ void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder,
gAgentWearables.setWearableOutfit(items, wearables, !append);
}
delete holder;
// dec_busy_count();
}
@ -706,86 +774,66 @@ void LLAppearanceManager::updateAppearanceFromCOF()
LLInventoryModel::item_array_t gest_items;
getUserDescendents(current_outfit_id, wear_items, obj_items, gest_items, follow_folder_links);
if( !wear_items.count() && !obj_items.count() && !gest_items.count())
if(!wear_items.count())
{
LLNotificationsUtil::add("CouldNotPutOnOutfit");
return;
}
LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
holder->mObjItems = obj_items;
holder->mGestItems = gest_items;
// Processes that take time should show the busy cursor
//inc_busy_count(); // BAP this is currently a no-op in llinventorybridge.cpp - do we need it?
// Activate all gestures in this folder
if (gest_items.count() > 0)
// Note: can't do normal iteration, because if all the
// wearables can be resolved immediately, then the
// callback will be called (and this object deleted)
// before the final getNextData().
LLDynamicArray<LLFoundData> found_container;
for(S32 i = 0; i < wear_items.count(); ++i)
{
llinfos << "Activating " << gest_items.count() << " gestures" << llendl;
LLGestureManager::instance().activateGestures(gest_items);
// Update the inventory item labels to reflect the fact
// they are active.
LLViewerInventoryCategory* catp = gInventory.getCategory(current_outfit_id);
if (catp)
LLViewerInventoryItem *item = wear_items.get(i);
LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL;
if (item && linked_item)
{
gInventory.updateCategory(catp);
gInventory.notifyObservers();
LLFoundData found(linked_item->getUUID(),
linked_item->getAssetUUID(),
linked_item->getName(),
linked_item->getType());
holder->mFoundList.push_front(found);
found_container.put(found);
}
else
{
if (!item)
{
llwarns << "attempt to wear a null item " << llendl;
}
else if (!linked_item)
{
llwarns << "attempt to wear a broken link " << item->getName() << llendl;
}
}
}
if(wear_items.count() > 0)
for(S32 i = 0; i < found_container.count(); ++i)
{
// Note: can't do normal iteration, because if all the
// wearables can be resolved immediately, then the
// callback will be called (and this object deleted)
// before the final getNextData().
LLWearableHoldingPattern* holder = new LLWearableHoldingPattern;
LLFoundData* found;
LLDynamicArray<LLFoundData*> found_container;
for(S32 i = 0; i < wear_items.count(); ++i)
{
LLViewerInventoryItem *item = wear_items.get(i);
LLViewerInventoryItem *linked_item = item ? item->getLinkedItem() : NULL;
if (item && linked_item)
{
found = new LLFoundData(linked_item->getUUID(),
linked_item->getAssetUUID(),
linked_item->getName(),
linked_item->getType());
holder->mFoundList.push_front(found);
found_container.put(found);
}
else
{
if (!item)
{
llwarns << "attempt to wear a null item " << llendl;
}
else if (!linked_item)
{
llwarns << "attempt to wear a broken link " << item->getName() << llendl;
}
}
}
for(S32 i = 0; i < found_container.count(); ++i)
{
holder->append = false;
found = found_container.get(i);
LLFoundData& found = found_container.get(i);
// Fetch the wearables about to be worn.
LLWearableList::instance().getAsset(found->mAssetID,
found->mName,
found->mAssetType,
onWearableAssetFetch,
(void*)holder);
}
// Fetch the wearables about to be worn.
LLWearableList::instance().getAsset(found.mAssetID,
found.mName,
found.mAssetType,
onWearableAssetFetch,
(void*)holder);
}
// Update attachments to match those requested.
LLVOAvatar* avatar = gAgent.getAvatarObject();
if( avatar )
if (!holder->pollCompletion())
{
LLAgentWearables::userUpdateAttachments(obj_items);
doOnIdleRepeating(boost::bind(&LLWearableHoldingPattern::pollCompletion,holder));
}
}
void LLAppearanceManager::getDescendentsOfAssetType(const LLUUID& category,
@ -1263,3 +1311,23 @@ void LLAppearanceManager::linkRegisteredAttachments()
}
mRegisteredAttachments.clear();
}
BOOL LLAppearanceManager::getIsInCOF(const LLUUID& obj_id) const
{
return gInventory.isObjectDescendentOf(obj_id, getCOF());
}
BOOL LLAppearanceManager::getIsProtectedCOFItem(const LLUUID& obj_id) const
{
if (!getIsInCOF(obj_id)) return FALSE;
const LLInventoryObject *obj = gInventory.getObject(obj_id);
if (!obj) return FALSE;
// Can't delete bodyparts, since this would be equivalent to removing the item.
if (obj->getType() == LLAssetType::AT_BODYPART) return TRUE;
// Can't delete the folder link, since this is saved for bookkeeping.
if (obj->getActualType() == LLAssetType::AT_LINK_FOLDER) return TRUE;
return FALSE;
}

View File

@ -39,7 +39,7 @@
#include "llcallbacklist.h"
class LLWearable;
struct LLWearableHoldingPattern;
class LLWearableHoldingPattern;
class LLAppearanceManager: public LLSingleton<LLAppearanceManager>
{
@ -59,7 +59,7 @@ public:
LLPointer<LLInventoryCallback> cb);
// Find the Current Outfit folder.
LLUUID getCOF();
const LLUUID getCOF() const;
// Finds the folder link to the currently worn outfit
const LLViewerInventoryItem *getBaseOutfitLink();
@ -132,6 +132,14 @@ private:
std::set<LLUUID> mRegisteredAttachments;
bool mAttachmentInvLinkEnabled;
bool mOutfitIsDirty;
//////////////////////////////////////////////////////////////////////////////////
// Item-specific convenience functions
public:
// Is this in the COF?
BOOL getIsInCOF(const LLUUID& obj_id) const;
// Is this in the COF and can the user delete it from the COF?
BOOL getIsProtectedCOFItem(const LLUUID& obj_id) const;
};
#define SUPPORT_ENSEMBLES 0
@ -168,4 +176,40 @@ void doOnIdle(T callable)
gIdleCallbacks.addFunction(&OnIdleCallback<T>::onIdle,cb_functor);
}
// Shim class and template function to allow arbitrary boost::bind
// expressions to be run as recurring idle callbacks.
template <typename T>
class OnIdleCallbackRepeating
{
public:
OnIdleCallbackRepeating(T callable):
mCallable(callable)
{
}
// Will keep getting called until the callable returns false.
static void onIdle(void *data)
{
OnIdleCallbackRepeating<T>* self = reinterpret_cast<OnIdleCallbackRepeating<T>*>(data);
bool done = self->call();
if (done)
{
gIdleCallbacks.deleteFunction(onIdle, data);
delete self;
}
}
bool call()
{
return mCallable();
}
private:
T mCallable;
};
template <typename T>
void doOnIdleRepeating(T callable)
{
OnIdleCallbackRepeating<T>* cb_functor = new OnIdleCallbackRepeating<T>(callable);
gIdleCallbacks.addFunction(&OnIdleCallbackRepeating<T>::onIdle,cb_functor);
}
#endif

View File

@ -930,7 +930,6 @@ bool LLAppViewer::mainLoop()
{
LLMemType mt1(LLMemType::MTYPE_MAIN);
mMainloopTimeout = new LLWatchdogTimeout();
// *FIX:Mani - Make this a setting, once new settings exist in this branch.
//-------------------------------------------
// Run main loop until time to quit
@ -940,12 +939,13 @@ bool LLAppViewer::mainLoop()
gServicePump = new LLPumpIO(gAPRPoolp);
LLHTTPClient::setPump(*gServicePump);
LLCurl::setCAFile(gDirUtilp->getCAFile());
LLCurl::setSSLVerify(! gSavedSettings.getBOOL("NoVerifySSLCert"));
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be instantiated.
LLVoiceChannel::initClass();
LLVoiceClient::init(gServicePump);
LLTimer frameTimer,idleTimer;
LLTimer debugTime;
LLViewerJoystick* joystick(LLViewerJoystick::getInstance());

View File

@ -322,7 +322,7 @@ void LLBottomTray::setVisible(BOOL visible)
// Chat bar and gesture button are shown even in mouselook mode.
// But the move, camera and snapshot buttons shouldn't be displayed. See EXT-3988.
if ("chat_bar" == name || "gesture_panel" == name)
if ("chat_bar" == name || "gesture_panel" == name || (visibility && ("movement_panel" == name || "cam_panel" == name || "snapshot_panel" == name)))
continue;
else
{

View File

@ -51,9 +51,9 @@
#include "lltransientfloatermgr.h"
#include "llviewerwindow.h"
#include "llvoicechannel.h"
#include "lllayoutstack.h"
static void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids);
void reshape_floater(LLCallFloater* floater, S32 delta_height);
class LLNonAvatarCaller : public LLAvatarListItem
{
@ -93,22 +93,6 @@ static void* create_non_avatar_caller(void*)
return new LLNonAvatarCaller;
}
LLCallFloater::LLAvatarListItemRemoveTimer::LLAvatarListItemRemoveTimer(callback_t remove_cb, F32 period, const LLUUID& speaker_id)
: LLEventTimer(period)
, mRemoveCallback(remove_cb)
, mSpeakerId(speaker_id)
{
}
BOOL LLCallFloater::LLAvatarListItemRemoveTimer::tick()
{
if (mRemoveCallback)
{
mRemoveCallback(mSpeakerId);
}
return TRUE;
}
LLVoiceChannel* LLCallFloater::sCurrentVoiceCanel = NULL;
LLCallFloater::LLCallFloater(const LLSD& key)
@ -122,10 +106,9 @@ LLCallFloater::LLCallFloater(const LLSD& key)
, mSpeakingIndicator(NULL)
, mIsModeratorMutedVoice(false)
, mInitParticipantsVoiceState(false)
, mVoiceLeftRemoveDelay(10)
{
static LLUICachedControl<S32> voice_left_remove_delay ("VoiceParticipantLeftRemoveDelay", 10);
mVoiceLeftRemoveDelay = voice_left_remove_delay;
mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), voice_left_remove_delay);
mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);
LLVoiceClient::getInstance()->addObserver(this);
@ -135,6 +118,7 @@ LLCallFloater::LLCallFloater(const LLSD& key)
LLCallFloater::~LLCallFloater()
{
resetVoiceRemoveTimers();
delete mSpeakerDelayRemover;
delete mParticipants;
mParticipants = NULL;
@ -225,16 +209,6 @@ void LLCallFloater::onChange()
}
}
S32 LLCallFloater::notifyParent(const LLSD& info)
{
if("size_changes" == info["action"])
{
reshapeToFitContent();
return 1;
}
return LLDockableFloater::notifyParent(info);
}
//////////////////////////////////////////////////////////////////////////
/// PRIVATE SECTION
//////////////////////////////////////////////////////////////////////////
@ -316,7 +290,7 @@ void LLCallFloater::updateSession()
//hide "Leave Call" button for nearby chat
bool is_local_chat = mVoiceType == VC_LOCAL_CHAT;
childSetVisible("leave_call_btn_panel", !is_local_chat);
refreshParticipantList();
updateAgentModeratorState();
@ -658,33 +632,11 @@ void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state)
void LLCallFloater::setVoiceRemoveTimer(const LLUUID& voice_speaker_id)
{
// If there is already a started timer for the current panel don't do anything.
bool no_timer_for_current_panel = true;
if (mVoiceLeftTimersMap.size() > 0)
{
timers_map::iterator found_it = mVoiceLeftTimersMap.find(voice_speaker_id);
if (found_it != mVoiceLeftTimersMap.end())
{
no_timer_for_current_panel = false;
}
}
if (no_timer_for_current_panel)
{
// Starting a timer to remove an avatar row panel after timeout
mVoiceLeftTimersMap.insert(timer_pair(voice_speaker_id,
new LLAvatarListItemRemoveTimer(boost::bind(&LLCallFloater::removeVoiceLeftParticipant, this, _1), mVoiceLeftRemoveDelay, voice_speaker_id)));
}
mSpeakerDelayRemover->setActionTimer(voice_speaker_id);
}
void LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id)
bool LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id)
{
if (mVoiceLeftTimersMap.size() > 0)
{
mVoiceLeftTimersMap.erase(mVoiceLeftTimersMap.find(voice_speaker_id));
}
LLAvatarList::uuid_vector_t& speaker_uuids = mAvatarList->getIDs();
LLAvatarList::uuid_vector_t::iterator pos = std::find(speaker_uuids.begin(), speaker_uuids.end(), voice_speaker_id);
if(pos != speaker_uuids.end())
@ -692,34 +644,19 @@ void LLCallFloater::removeVoiceLeftParticipant(const LLUUID& voice_speaker_id)
speaker_uuids.erase(pos);
mAvatarList->setDirty();
}
return false;
}
void LLCallFloater::resetVoiceRemoveTimers()
{
if (mVoiceLeftTimersMap.size() > 0)
{
for (timers_map::iterator iter = mVoiceLeftTimersMap.begin();
iter != mVoiceLeftTimersMap.end(); ++iter)
{
delete iter->second;
}
}
mVoiceLeftTimersMap.clear();
mSpeakerDelayRemover->removeAllTimers();
}
void LLCallFloater::removeVoiceRemoveTimer(const LLUUID& voice_speaker_id)
{
// Remove the timer if it has been already started
if (mVoiceLeftTimersMap.size() > 0)
{
timers_map::iterator found_it = mVoiceLeftTimersMap.find(voice_speaker_id);
if (found_it != mVoiceLeftTimersMap.end())
{
delete found_it->second;
mVoiceLeftTimersMap.erase(found_it);
}
}
mSpeakerDelayRemover->unsetActionTimer(voice_speaker_id);
}
bool LLCallFloater::validateSpeaker(const LLUUID& speaker_id)
@ -798,90 +735,4 @@ void LLCallFloater::reset()
mSpeakerManager = NULL;
}
void reshape_floater(LLCallFloater* floater, S32 delta_height)
{
// Try to update floater top side if it is docked(to bottom bar).
// Try to update floater bottom side or top side if it is un-docked.
// If world rect is too small, floater will not be reshaped at all.
LLRect floater_rect = floater->getRect();
LLRect world_rect = gViewerWindow->getWorldViewRectScaled();
// floater is docked to bottom bar
if(floater->isDocked())
{
// can update floater top side
if(floater_rect.mTop + delta_height < world_rect.mTop)
{
floater_rect.set(floater_rect.mLeft, floater_rect.mTop + delta_height,
floater_rect.mRight, floater_rect.mBottom);
}
}
// floater is un-docked
else
{
// can update floater bottom side
if( floater_rect.mBottom - delta_height >= world_rect.mBottom )
{
floater_rect.set(floater_rect.mLeft, floater_rect.mTop,
floater_rect.mRight, floater_rect.mBottom - delta_height);
}
// could not update floater bottom side, check if we can update floater top side
else if( floater_rect.mTop + delta_height < world_rect.mTop )
{
floater_rect.set(floater_rect.mLeft, floater_rect.mTop + delta_height,
floater_rect.mRight, floater_rect.mBottom);
}
}
floater->setShape(floater_rect);
floater->getChild<LLLayoutStack>("my_call_stack")->updateLayout(FALSE);
}
void LLCallFloater::reshapeToFitContent()
{
const S32 ITEM_HEIGHT = getParticipantItemHeight();
static const S32 MAX_VISIBLE_ITEMS = getMaxVisibleItems();
static S32 items_pad = mAvatarList->getItemsPad();
S32 list_height = mAvatarList->getRect().getHeight();
S32 items_height = mAvatarList->getItemsRect().getHeight();
if(items_height <= 0)
{
// make "no one near" text visible
items_height = ITEM_HEIGHT + items_pad;
}
S32 max_list_height = MAX_VISIBLE_ITEMS * ITEM_HEIGHT + items_pad * (MAX_VISIBLE_ITEMS - 1);
max_list_height += 2* mAvatarList->getBorderWidth();
S32 delta = items_height - list_height;
// too many items, don't reshape floater anymore, let scroll bar appear.
if(items_height > max_list_height)
{
delta = max_list_height - list_height;
}
reshape_floater(this, delta);
}
S32 LLCallFloater::getParticipantItemHeight()
{
std::vector<LLPanel*> items;
mAvatarList->getItems(items);
if(items.size() > 0)
{
return items[0]->getRect().getHeight();
}
else
{
return getChild<LLPanel>("non_avatar_caller")->getRect().getHeight();
}
}
S32 LLCallFloater::getMaxVisibleItems()
{
static LLCachedControl<S32> max_visible_items(*LLUI::sSettingGroups["config"],"CallFloaterMaxItems");
return max_visible_items;
}
//EOF

View File

@ -44,6 +44,8 @@ class LLNonAvatarCaller;
class LLOutputMonitorCtrl;
class LLParticipantList;
class LLSpeakerMgr;
class LLSpeakersDelayActionsStorage;
/**
* The Voice Control Panel is an ambient window summoned by clicking the flyout chevron on the Speak button.
* It can be torn-off and freely positioned onscreen.
@ -75,11 +77,6 @@ public:
*/
/*virtual*/ void onChange();
/**
* Will reshape floater when participant list size changes
*/
/*virtual*/ S32 notifyParent(const LLSD& info);
static void sOnCurrentChannelChanged(const LLUUID& session_id);
private:
@ -174,7 +171,7 @@ private:
*
* @param voice_speaker_id LLUUID of Avatar List item to be removed from the list.
*/
void removeVoiceLeftParticipant(const LLUUID& voice_speaker_id);
bool removeVoiceLeftParticipant(const LLUUID& voice_speaker_id);
/**
* Deletes all timers from the list to prevent started timers from ticking after destruction
@ -221,21 +218,6 @@ private:
*/
void reset();
/**
* Reshapes floater to fit participant list height
*/
void reshapeToFitContent();
/**
* Returns height of participant list item
*/
S32 getParticipantItemHeight();
/**
* Returns predefined max visible participants.
*/
S32 getMaxVisibleItems();
private:
speaker_state_map_t mSpeakerStateMap;
LLSpeakerMgr* mSpeakerManager;
@ -260,32 +242,11 @@ private:
boost::signals2::connection mAvatarListRefreshConnection;
/**
* class LLAvatarListItemRemoveTimer
*
* Implements a timer that removes avatar list item of a participant
* who has left the call.
* time out speakers when they are not part of current session
*/
class LLAvatarListItemRemoveTimer : public LLEventTimer
{
public:
typedef boost::function<void(const LLUUID&)> callback_t;
LLAvatarListItemRemoveTimer(callback_t remove_cb, F32 period, const LLUUID& speaker_id);
virtual ~LLAvatarListItemRemoveTimer() {};
virtual BOOL tick();
private:
callback_t mRemoveCallback;
LLUUID mSpeakerId;
};
typedef std::pair<LLUUID, LLAvatarListItemRemoveTimer*> timer_pair;
typedef std::map<LLUUID, LLAvatarListItemRemoveTimer*> timers_map;
timers_map mVoiceLeftTimersMap;
S32 mVoiceLeftRemoveDelay;
LLSpeakersDelayActionsStorage* mSpeakerDelayRemover;
/**
* Stores reference to current voice channel.

View File

@ -47,6 +47,7 @@
#include "llnotificationsutil.h"
#include "lloutputmonitorctrl.h"
#include "llscriptfloater.h"
#include "llspeakers.h"
#include "lltextbox.h"
#include "llvoiceclient.h"
#include "llgroupmgr.h"
@ -1271,6 +1272,7 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)
chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index));
arrange();
LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, chiclet);
return true;
}
@ -1298,6 +1300,7 @@ void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it)
mChicletList.erase(it);
arrange();
LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, chiclet);
chiclet->die();
}

View File

@ -51,6 +51,7 @@
#include "llinventorymodel.h"
#include "llfloaterworldmap.h"
#include "lllandmarkactions.h"
#include "llnotificationsutil.h"
#include "llsidetray.h"
#include "lltoggleablemenu.h"
#include "llviewerinventory.h"
@ -975,6 +976,10 @@ BOOL LLFavoritesBarCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
void copy_slurl_to_clipboard_cb(std::string& slurl)
{
gClipboard.copyFromString(utf8str_to_wstring(slurl));
LLSD args;
args["SLURL"] = slurl;
LLNotificationsUtil::add("CopySLURL", args);
}

View File

@ -277,13 +277,8 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
{
object_owner.append("Unknown");
}
childSetText("object_name", object_owner);
std::string owner_link =
LLSLURL::buildCommand("agent", mObjectID, "inspect");
childSetText("owner_name", owner_link);
childSetText("abuser_name_edit", object_owner);
mAbuserID = object_id;
mOwnerName = object_owner;
setFromAvatar(object_id, object_owner);
}
else
{
@ -305,7 +300,6 @@ void LLFloaterReporter::getObjectInfo(const LLUUID& object_id)
}
}
void LLFloaterReporter::onClickSelectAbuser()
{
gFloaterView->getParentFloater(this)->addDependentFloater(LLFloaterAvatarPicker::show(boost::bind(&LLFloaterReporter::callbackAvatarID, this, _1, _2), FALSE, TRUE ));
@ -323,6 +317,17 @@ void LLFloaterReporter::callbackAvatarID(const std::vector<std::string>& names,
}
void LLFloaterReporter::setFromAvatar(const LLUUID& avatar_id, const std::string& avatar_name)
{
mAbuserID = mObjectID = avatar_id;
mOwnerName = avatar_name;
std::string avatar_link = LLSLURL::buildCommand("agent", mObjectID, "inspect");
childSetText("owner_name", avatar_link);
childSetText("object_name", avatar_name); // name
childSetText("abuser_name_edit", avatar_name);
}
// static
void LLFloaterReporter::onClickSend(void *userdata)
{
@ -458,9 +463,8 @@ void LLFloaterReporter::showFromMenu(EReportType report_type)
}
}
// static
void LLFloaterReporter::showFromObject(const LLUUID& object_id)
void LLFloaterReporter::show(const LLUUID& object_id, const std::string& avatar_name)
{
LLFloaterReporter* f = LLFloaterReg::showTypedInstance<LLFloaterReporter>("reporter");
@ -469,8 +473,11 @@ void LLFloaterReporter::showFromObject(const LLUUID& object_id)
LLAgentUI::buildFullname(fullname);
f->childSetText("reporter_field", fullname);
// Request info for this object
f->getObjectInfo(object_id);
if (avatar_name.empty())
// Request info for this object
f->getObjectInfo(object_id);
else
f->setFromAvatar(object_id, avatar_name);
// Need to deselect on close
f->mDeselectOnClose = TRUE;
@ -479,6 +486,18 @@ void LLFloaterReporter::showFromObject(const LLUUID& object_id)
}
// static
void LLFloaterReporter::showFromObject(const LLUUID& object_id)
{
show(object_id);
}
// static
void LLFloaterReporter::showFromAvatar(const LLUUID& avatar_id, const std::string avatar_name)
{
show(avatar_id, avatar_name);
}
void LLFloaterReporter::setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id)
{
childSetText("object_name", object_name);

View File

@ -93,6 +93,7 @@ public:
static void showFromMenu(EReportType report_type);
static void showFromObject(const LLUUID& object_id);
static void showFromAvatar(const LLUUID& avatar_id, const std::string avatar_name);
static void onClickSend (void *userdata);
static void onClickCancel (void *userdata);
@ -109,6 +110,8 @@ public:
void setPickedObjectProperties(const std::string& object_name, const std::string& owner_name, const LLUUID owner_id);
private:
static void show(const LLUUID& object_id, const std::string& avatar_name = LLStringUtil::null);
void takeScreenshot();
void sendReportViaCaps(std::string url);
void uploadImage();
@ -121,6 +124,7 @@ private:
void enableControls(BOOL own_avatar);
void getObjectInfo(const LLUUID& object_id);
void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids);
void setFromAvatar(const LLUUID& avatar_id, const std::string& avatar_name = LLStringUtil::null);
private:
EReportType mReportType;

View File

@ -1391,6 +1391,7 @@ void LLFolderView::startRenamingSelectedItem( void )
// set focus will fail unless item is visible
mRenamer->setFocus( TRUE );
mRenamer->setTopLostCallback(boost::bind(onRenamerLost, _1));
mRenamer->setFocusLostCallback(boost::bind(onRenamerLost, _1));
gFocusMgr.setTopCtrl( mRenamer );
}
}

View File

@ -98,6 +98,41 @@ void LLGestureManager::init()
// TODO
}
void LLGestureManager::changed(U32 mask)
{
LLInventoryFetchObserver::changed(mask);
if (mask & LLInventoryObserver::GESTURE)
{
// If there was a gesture label changed, update all the names in the
// active gestures and then notify observers
if (mask & LLInventoryObserver::LABEL)
{
for(item_map_t::iterator it = mActive.begin(); it != mActive.end(); ++it)
{
if(it->second)
{
LLViewerInventoryItem* item = gInventory.getItem(it->first);
if(item)
{
it->second->mName = item->getName();
}
}
}
notifyObservers();
}
// If there was a gesture added or removed notify observers
// STRUCTURE denotes that the inventory item has been moved
// In the case of deleting gesture, it is moved to the trash
else if(mask & LLInventoryObserver::ADD ||
mask & LLInventoryObserver::REMOVE ||
mask & LLInventoryObserver::STRUCTURE)
{
notifyObservers();
}
}
}
// Use this version when you have the item_id but not the asset_id,
// and you KNOW the inventory is loaded.

View File

@ -140,6 +140,9 @@ public:
void removeObserver(LLGestureManagerObserver* observer);
void notifyObservers();
// Overriding so we can update active gesture names and notify observers
void changed(U32 mask);
BOOL matchPrefix(const std::string& in_str, std::string* out_str);
// Copy item ids into the vector

View File

@ -58,6 +58,7 @@
#include "llinventorymodel.h"
#include "llrootview.h"
#include "llspeakers.h"
LLIMFloater::LLIMFloater(const LLUUID& session_id)
@ -109,6 +110,8 @@ LLIMFloater::LLIMFloater(const LLUUID& session_id)
}
}
setOverlapsScreenChannel(true);
LLTransientFloaterMgr::getInstance()->addControlView(LLTransientFloaterMgr::IM, this);
}
void LLIMFloater::onFocusLost()
@ -227,6 +230,7 @@ void LLIMFloater::sendMsg()
LLIMFloater::~LLIMFloater()
{
LLTransientFloaterMgr::getInstance()->removeControlView(LLTransientFloaterMgr::IM, this);
}
//virtual
@ -350,13 +354,15 @@ void* LLIMFloater::createPanelAdHocControl(void* userdata)
void LLIMFloater::onSlide()
{
LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel");
im_control_panel->setVisible(!im_control_panel->getVisible());
mControlPanel->setVisible(!mControlPanel->getVisible());
gSavedSettings.setBOOL("IMShowControlPanel", im_control_panel->getVisible());
gSavedSettings.setBOOL("IMShowControlPanel", mControlPanel->getVisible());
getChild<LLButton>("slide_left_btn")->setVisible(im_control_panel->getVisible());
getChild<LLButton>("slide_right_btn")->setVisible(!im_control_panel->getVisible());
getChild<LLButton>("slide_left_btn")->setVisible(mControlPanel->getVisible());
getChild<LLButton>("slide_right_btn")->setVisible(!mControlPanel->getVisible());
LLLayoutStack* stack = getChild<LLLayoutStack>("im_panels");
if (stack) stack->setAnimate(true);
}
//static
@ -510,14 +516,14 @@ bool LLIMFloater::toggle(const LLUUID& session_id)
if(!isChatMultiTab())
{
LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
if (floater && floater->getVisible())
if (floater && floater->getVisible() && floater->hasFocus())
{
// clicking on chiclet to close floater just hides it to maintain existing
// scroll/text entry state
floater->setVisible(false);
return false;
}
else if(floater && !floater->isDocked())
else if(floater && (!floater->isDocked() || floater->getVisible() && !floater->hasFocus()))
{
floater->setVisible(TRUE);
floater->setFocus(TRUE);

View File

@ -116,6 +116,8 @@ public:
static void onIMChicletCreated(const LLUUID& session_id);
virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::IM; }
private:
// process focus events to set a currently active session
/* virtual */ void onFocusLost();

View File

@ -35,19 +35,22 @@
#include "llimfloatercontainer.h"
#include "llfloaterreg.h"
#include "llimview.h"
#include "llavatariconctrl.h"
#include "llagent.h"
//
// LLIMFloaterContainer
//
LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed)
: LLMultiFloater(seed),
mActiveVoiceFloater(NULL)
: LLMultiFloater(seed)
{
mAutoResize = FALSE;
}
LLIMFloaterContainer::~LLIMFloaterContainer()
{
LLGroupMgr::getInstance()->removeObserver(this);
}
BOOL LLIMFloaterContainer::postBuild()
@ -87,11 +90,82 @@ void LLIMFloaterContainer::addFloater(LLFloater* floaterp,
LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point);
// make sure active voice icon shows up for new tab
if (floaterp == mActiveVoiceFloater)
LLUUID session_id = floaterp->getKey();
if(gAgent.isInGroup(session_id))
{
mTabContainer->setTabImage(floaterp, "active_voice_tab.tga");
mSessions[session_id] = floaterp;
mID = session_id;
mGroupID.push_back(session_id);
LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(session_id);
LLGroupMgr* gm = LLGroupMgr::getInstance();
gm->addObserver(this);
if (group_data && group_data->mInsigniaID.notNull())
{
mTabContainer->setTabImage(get_ptr_in_map(mSessions, session_id), group_data->mInsigniaID);
}
else
{
gm->sendGroupPropertiesRequest(session_id);
}
}
else
{
LLUUID avatar_id = LLIMModel::getInstance()->getOtherParticipantID(session_id);
LLAvatarPropertiesProcessor& app = LLAvatarPropertiesProcessor::instance();
app.addObserver(avatar_id, this);
floaterp->mCloseSignal.connect(boost::bind(&LLIMFloaterContainer::onCloseFloater, this, avatar_id));
mSessions[avatar_id] = floaterp;
LLUUID* icon_id_ptr = LLAvatarIconIDCache::getInstance()->get(avatar_id);
if(!icon_id_ptr)
{
app.sendAvatarPropertiesRequest(avatar_id);
}
else
{
mTabContainer->setTabImage(floaterp, *icon_id_ptr);
}
}
}
void LLIMFloaterContainer::processProperties(void* data, enum EAvatarProcessorType type)
{
if (APT_PROPERTIES == type)
{
LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data);
if (avatar_data)
{
LLUUID avatar_id = avatar_data->avatar_id;
if(avatar_data->image_id != *LLAvatarIconIDCache::getInstance()->get(avatar_id))
{
LLAvatarIconIDCache::getInstance()->add(avatar_id,avatar_data->image_id);
}
mTabContainer->setTabImage(get_ptr_in_map(mSessions, avatar_id), avatar_data->image_id);
}
}
}
void LLIMFloaterContainer::changed(LLGroupChange gc)
{
if (GC_PROPERTIES == gc)
{
for(groupIDs_t::iterator it = mGroupID.begin(); it!=mGroupID.end(); it++)
{
LLUUID group_id = *it;
LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(group_id);
if (group_data && group_data->mInsigniaID.notNull())
{
mTabContainer->setTabImage(get_ptr_in_map(mSessions, group_id), group_data->mInsigniaID);
}
}
}
}
void LLIMFloaterContainer::onCloseFloater(LLUUID id)
{
LLAvatarPropertiesProcessor::instance().removeObserver(id, this);
}
LLIMFloaterContainer* LLIMFloaterContainer::findInstance()

View File

@ -33,12 +33,17 @@
#ifndef LL_LLIMFLOATERCONTAINER_H
#define LL_LLIMFLOATERCONTAINER_H
#include <map>
#include <vector>
#include "llfloater.h"
#include "llmultifloater.h"
#include "llavatarpropertiesprocessor.h"
#include "llgroupmgr.h"
class LLTabContainer;
class LLIMFloaterContainer : public LLMultiFloater
class LLIMFloaterContainer : public LLMultiFloater, public LLAvatarPropertiesObserver, public LLGroupMgrObserver
{
public:
LLIMFloaterContainer(const LLSD& seed);
@ -51,15 +56,23 @@ public:
BOOL select_added_floater,
LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END);
void processProperties(void* data, EAvatarProcessorType type);
void changed(LLGroupChange gc);
static LLFloater* getCurrentVoiceFloater();
static LLIMFloaterContainer* findInstance();
static LLIMFloaterContainer* getInstance();
protected:
LLFloater* mActiveVoiceFloater;
private:
typedef std::map<LLUUID,LLPanel*> avatarID_panel_map_t;
avatarID_panel_map_t mSessions;
typedef std::vector<LLUUID> groupIDs_t;
groupIDs_t mGroupID;
void onCloseFloater(LLUUID avatar_id);
};
#endif // LL_LLIMFLOATERCONTAINER_H

View File

@ -40,6 +40,7 @@
#include "llfontgl.h"
#include "llrect.h"
#include "llerror.h"
#include "llmultifloater.h"
#include "llstring.h"
#include "message.h"
#include "lltextbox.h"

View File

@ -42,47 +42,31 @@
#include "llhttpclient.h"
#include "llsdutil_math.h"
#include "llstring.h"
#include "lltrans.h"
#include "lluictrlfactory.h"
#include "llagent.h"
#include "llagentui.h"
#include "llappviewer.h"
#include "llavatariconctrl.h"
#include "llbottomtray.h"
#include "llcallingcard.h"
#include "llchat.h"
#include "llchiclet.h"
#include "llresmgr.h"
#include "llfloaterchatterbox.h"
#include "llavataractions.h"
#include "llhttpnode.h"
#include "llimfloater.h"
#include "llimpanel.h"
#include "llgroupiconctrl.h"
#include "llresizebar.h"
#include "lltabcontainer.h"
#include "llviewercontrol.h"
#include "llfloater.h"
#include "llmd5.h"
#include "llmutelist.h"
#include "llresizehandle.h"
#include "llkeyboard.h"
#include "llui.h"
#include "llviewermenu.h"
#include "llcallingcard.h"
#include "lltoolbar.h"
#include "llrecentpeople.h"
#include "llviewermessage.h"
#include "llviewerwindow.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "llnearbychat.h"
#include "llviewerregion.h"
#include "llvoicechannel.h"
#include "lltrans.h"
#include "llrecentpeople.h"
#include "llsyswellwindow.h"
//#include "llfirstuse.h"
#include "llagentui.h"
#include "llspeakers.h" //for LLIMSpeakerMgr
#include "lltextutil.h"
#include "llviewercontrol.h"
const static std::string IM_TIME("time");
const static std::string IM_TEXT("message");
@ -232,12 +216,14 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
mTextIMPossible = LLVoiceClient::getInstance()->isSessionTextIMPossible(mSessionID);
}
buildHistoryFileName();
if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
{
std::list<LLSD> chat_history;
//involves parsing of a chat history
LLLogChat::loadAllHistory(mName, chat_history);
LLLogChat::loadAllHistory(mHistoryFileName, chat_history);
addMessagesFromHistory(chat_history);
}
}
@ -484,6 +470,44 @@ bool LLIMModel::LLIMSession::isOtherParticipantAvaline()
return !mOtherParticipantIsAvatar;
}
void LLIMModel::LLIMSession::buildHistoryFileName()
{
mHistoryFileName = mName;
//ad-hoc requires sophisticated chat history saving schemes
if (isAdHoc())
{
//in case of outgoing ad-hoc sessions
if (mInitialTargetIDs.size())
{
std::set<LLUUID> sorted_uuids(mInitialTargetIDs.begin(), mInitialTargetIDs.end());
mHistoryFileName = mName + " hash" + generateHash(sorted_uuids);
return;
}
//in case of incoming ad-hoc sessions
mHistoryFileName = mName + " " + LLLogChat::timestamp(true) + " " + mSessionID.asString().substr(0, 4);
}
}
//static
std::string LLIMModel::LLIMSession::generateHash(const std::set<LLUUID>& sorted_uuids)
{
LLMD5 md5_uuid;
std::set<LLUUID>::const_iterator it = sorted_uuids.begin();
while (it != sorted_uuids.end())
{
md5_uuid.update((unsigned char*)(*it).mData, 16);
it++;
}
md5_uuid.finalize();
LLUUID participants_md5_hash;
md5_uuid.raw_digest((unsigned char*) participants_md5_hash.mData);
return participants_md5_hash.asString();
}
void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id)
{
@ -631,11 +655,11 @@ bool LLIMModel::addToHistory(const LLUUID& session_id, const std::string& from,
return true;
}
bool LLIMModel::logToFile(const std::string& session_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
bool LLIMModel::logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
{
if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
{
LLLogChat::saveHistory(session_name, from, from_id, utf8_text);
LLLogChat::saveHistory(file_name, from, from_id, utf8_text);
return true;
}
else
@ -646,15 +670,7 @@ bool LLIMModel::logToFile(const std::string& session_name, const std::string& fr
bool LLIMModel::logToFile(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
{
if (gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
{
LLLogChat::saveHistory(LLIMModel::getInstance()->getName(session_id), from, from_id, utf8_text);
return true;
}
else
{
return false;
}
return logToFile(LLIMModel::getInstance()->getHistoryFileName(session_id), from, from_id, utf8_text);
}
bool LLIMModel::proccessOnlineOfflineNotification(
@ -799,6 +815,18 @@ LLIMSpeakerMgr* LLIMModel::getSpeakerManager( const LLUUID& session_id ) const
return session->mSpeakers;
}
const std::string& LLIMModel::getHistoryFileName(const LLUUID& session_id) const
{
LLIMSession* session = findIMSession(session_id);
if (!session)
{
llwarns << "session " << session_id << " does not exist " << llendl;
return LLStringUtil::null;
}
return session->mHistoryFileName;
}
// TODO get rid of other participant ID
void LLIMModel::sendTypingState(LLUUID session_id, LLUUID other_participant_id, BOOL typing)

View File

@ -33,22 +33,19 @@
#ifndef LL_LLIMVIEW_H
#define LL_LLIMVIEW_H
#include "lldarray.h"
#include "lldockablefloater.h"
#include "llspeakers.h" //for LLIMSpeakerMgr
#include "llimpanel.h" //for voice channels
#include "llmodaldialog.h"
#include "lldockablefloater.h"
#include "llinstantmessage.h"
#include "lluuid.h"
#include "llmultifloater.h"
#include "lllogchat.h"
#include "llvoicechannel.h"
class LLFloaterChatterBox;
class LLUUID;
class LLFloaterIMPanel;
class LLFriendObserver;
class LLCallDialogManager;
class LLIMSpeakerMgr;
class LLIMModel : public LLSingleton<LLIMModel>
{
@ -72,6 +69,8 @@ public:
void addMessagesFromHistory(const std::list<LLSD>& history);
void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time);
void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction);
/** @deprecated */
static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata);
bool isAdHoc();
@ -83,12 +82,20 @@ public:
bool isGroupSessionType() const { return mSessionType == GROUP_SESSION;}
bool isAvalineSessionType() const { return mSessionType == AVALINE_SESSION;}
//*TODO make private
/** ad-hoc sessions involve sophisticated chat history file naming schemes */
void buildHistoryFileName();
//*TODO make private
static std::string generateHash(const std::set<LLUUID>& sorted_uuids);
LLUUID mSessionID;
std::string mName;
EInstantMessage mType;
SType mSessionType;
LLUUID mOtherParticipantID;
std::vector<LLUUID> mInitialTargetIDs;
std::string mHistoryFileName;
// connection to voice channel state change signal
boost::signals2::connection mVoiceChannelStateChangeConnection;
@ -234,6 +241,8 @@ public:
*/
LLIMSpeakerMgr* getSpeakerManager(const LLUUID& session_id) const;
const std::string& getHistoryFileName(const LLUUID& session_id) const;
static void sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id);
static bool sendStartSession(const LLUUID& temp_session_id, const LLUUID& other_participant_id,
const std::vector<LLUUID>& ids, EInstantMessage dialog);
@ -246,7 +255,7 @@ public:
/**
* Saves an IM message into a file
*/
bool logToFile(const std::string& session_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
bool logToFile(const std::string& file_name, const std::string& from, const LLUUID& from_id, const std::string& utf8_text);
private:

View File

@ -689,7 +689,7 @@ void LLInspectAvatar::onToggleMute()
void LLInspectAvatar::onClickReport()
{
LLFloaterReporter::showFromObject(mAvatarID);
LLFloaterReporter::showFromAvatar(mAvatarID, mAvatarName);
closeFloater();
}

View File

@ -187,6 +187,11 @@ BOOL LLInvFVBridge::isItemRemovable()
{
return FALSE;
}
if (LLAppearanceManager::instance().getIsProtectedCOFItem(mUUID))
{
return FALSE;
}
const LLInventoryObject *obj = model->getItem(mUUID);
if (obj && obj->getIsLinkType())
{
@ -576,8 +581,8 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
disabled_items.push_back(std::string("Paste As Link"));
}
}
items.push_back(std::string("Paste Separator"));
items.push_back(std::string("Paste Separator"));
if (obj && obj->getIsLinkType() && !get_is_item_worn(mUUID))
{
@ -714,14 +719,7 @@ BOOL LLInvFVBridge::isAgentInventory() const
BOOL LLInvFVBridge::isCOFFolder() const
{
const LLInventoryModel* model = getInventoryModel();
if(!model) return TRUE;
const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id))
{
return TRUE;
}
return FALSE;
return LLAppearanceManager::instance().getIsInCOF(mUUID);
}
BOOL LLInvFVBridge::isItemPermissive() const
@ -3702,18 +3700,6 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
return rv;
}
BOOL LLCallingCardBridge::removeItem()
{
if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem()))
{
LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID());
return FALSE;
}
else
{
return LLItemBridge::removeItem();
}
}
// +=================================================+
// | LLNotecardBridge |
// +=================================================+
@ -3825,8 +3811,25 @@ void LLGestureBridge::openItem()
BOOL LLGestureBridge::removeItem()
{
// Force close the preview window, if it exists
LLGestureManager::instance().deactivateGesture(mUUID);
// Grab class information locally since *this may be deleted
// within this function. Not a great pattern...
const LLInventoryModel* model = getInventoryModel();
if(!model)
{
return FALSE;
}
const LLUUID item_id = mUUID;
// This will also force close the preview window, if it exists.
// This may actually delete *this, if mUUID is in the COF.
LLGestureManager::instance().deactivateGesture(item_id);
// If deactivateGesture deleted *this, then return out immediately.
if (!model->getObject(item_id))
{
return TRUE;
}
return LLItemBridge::removeItem();
}
@ -4620,7 +4623,10 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
getClipboardEntries(true, items, disabled_items, flags);
items.push_back(std::string("Wearable Separator"));
if (!is_sidepanel)
{
items.push_back(std::string("Wearable Separator"));
}
items.push_back(std::string("Wearable Edit"));
@ -5150,8 +5156,12 @@ void LLLandmarkBridgeAction::doIt()
// Opening (double-clicking) a landmark immediately teleports,
// but warns you the first time.
LLSD payload;
payload["asset_id"] = item->getAssetUUID();
LLNotificationsUtil::add("TeleportFromLandmark", LLSD(), payload);
payload["asset_id"] = item->getAssetUUID();
LLSD args;
args["LOCATION"] = item->getDisplayName();
LLNotificationsUtil::add("TeleportFromLandmark", args, payload);
}
LLInvFVBridgeAction::doIt();

View File

@ -450,7 +450,6 @@ public:
EDragAndDropType cargo_type,
void* cargo_data);
void refreshFolderViewItem();
BOOL removeItem();
protected:
LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid );

View File

@ -755,6 +755,10 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
gCacheName->get(id, FALSE, boost::bind(&LLViewerInventoryItem::onCallingCardNameLookup, new_item.get(), _1, _2, _3));
}
}
else if (new_item->getType() == LLAssetType::AT_GESTURE)
{
mask |= LLInventoryObserver::GESTURE;
}
addChangedMask(mask, new_item->getUUID());
return mask;
}

View File

@ -61,8 +61,9 @@ public:
REMOVE = 8, // something deleted
STRUCTURE = 16, // structural change (eg item or folder moved)
CALLING_CARD = 32, // (eg online, grant status, cancel)
REBUILD = 64, // item UI changed (eg item type different)
SORT = 128, // folder needs to be resorted.
GESTURE = 64,
REBUILD = 128, // item UI changed (eg item type different)
SORT = 256, // folder needs to be resorted.
ALL = 0xffffffff
};
LLInventoryObserver();

View File

@ -682,6 +682,14 @@ void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_foc
mFolders->setSelectionByID(obj_id, take_keyboard_focus);
}
void LLInventoryPanel::setSelectCallback(const LLFolderView::signal_t::slot_type& cb)
{
if (mFolders)
{
mFolders->setSelectCallback(cb);
}
}
void LLInventoryPanel::clearSelection()
{
mFolders->clearSelection();

View File

@ -123,7 +123,7 @@ public:
// Call this method to set the selection.
void openAllFolders();
void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus);
void setSelectCallback(const LLFolderView::signal_t::slot_type& cb) { if (mFolders) mFolders->setSelectCallback(cb); }
void setSelectCallback(const LLFolderView::signal_t::slot_type& cb);
void clearSelection();
LLInventoryFilter* getFilter();
void setFilterTypes(U64 filter, LLInventoryFilter::EFilterType = LLInventoryFilter::FILTERTYPE_OBJECT);

View File

@ -43,8 +43,11 @@
#include "lltrans.h"
#include "lluictrlfactory.h"
#include "lltooltip.h"
#include "llnotificationsutil.h"
#include "llregionflags.h"
// newview includes
#include "llagent.h"
#include "llinventoryobserver.h"
#include "lllandmarkactions.h"
#include "lllandmarklist.h"
@ -56,6 +59,7 @@
#include "lltrans.h"
#include "llviewerinventory.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
#include "llviewercontrol.h"
#include "llviewermenu.h"
#include "llurllineeditorctrl.h"
@ -256,36 +260,42 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p)
voice_icon.tool_tip = LLTrans::getString("LocationCtrlVoiceTooltip");
voice_icon.mouse_opaque = true;
mParcelIcon[VOICE_ICON] = LLUICtrlFactory::create<LLIconCtrl>(voice_icon);
mParcelIcon[VOICE_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, VOICE_ICON));
addChild(mParcelIcon[VOICE_ICON]);
LLIconCtrl::Params fly_icon = p.fly_icon;
fly_icon.tool_tip = LLTrans::getString("LocationCtrlFlyTooltip");
fly_icon.mouse_opaque = true;
mParcelIcon[FLY_ICON] = LLUICtrlFactory::create<LLIconCtrl>(fly_icon);
mParcelIcon[FLY_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, FLY_ICON));
addChild(mParcelIcon[FLY_ICON]);
LLIconCtrl::Params push_icon = p.push_icon;
push_icon.tool_tip = LLTrans::getString("LocationCtrlPushTooltip");
push_icon.mouse_opaque = true;
mParcelIcon[PUSH_ICON] = LLUICtrlFactory::create<LLIconCtrl>(push_icon);
mParcelIcon[PUSH_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, PUSH_ICON));
addChild(mParcelIcon[PUSH_ICON]);
LLIconCtrl::Params build_icon = p.build_icon;
build_icon.tool_tip = LLTrans::getString("LocationCtrlBuildTooltip");
build_icon.mouse_opaque = true;
mParcelIcon[BUILD_ICON] = LLUICtrlFactory::create<LLIconCtrl>(build_icon);
mParcelIcon[BUILD_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, BUILD_ICON));
addChild(mParcelIcon[BUILD_ICON]);
LLIconCtrl::Params scripts_icon = p.scripts_icon;
scripts_icon.tool_tip = LLTrans::getString("LocationCtrlScriptsTooltip");
scripts_icon.mouse_opaque = true;
mParcelIcon[SCRIPTS_ICON] = LLUICtrlFactory::create<LLIconCtrl>(scripts_icon);
mParcelIcon[SCRIPTS_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, SCRIPTS_ICON));
addChild(mParcelIcon[SCRIPTS_ICON]);
LLIconCtrl::Params damage_icon = p.damage_icon;
damage_icon.tool_tip = LLTrans::getString("LocationCtrlDamageTooltip");
damage_icon.mouse_opaque = true;
mParcelIcon[DAMAGE_ICON] = LLUICtrlFactory::create<LLIconCtrl>(damage_icon);
mParcelIcon[DAMAGE_ICON]->setMouseDownCallback(boost::bind(&LLLocationInputCtrl::onParcelIconClick, this, DAMAGE_ICON));
addChild(mParcelIcon[DAMAGE_ICON]);
LLTextBox::Params damage_text = p.damage_text;
@ -918,3 +928,45 @@ bool LLLocationInputCtrl::onLocationContextMenuItemEnabled(const LLSD& userdata)
return false;
}
void LLLocationInputCtrl::onParcelIconClick(EParcelIcon icon)
{
switch (icon)
{
case VOICE_ICON:
LLNotificationsUtil::add("NoVoice");
break;
case FLY_ICON:
LLNotificationsUtil::add("NoFly");
break;
case PUSH_ICON:
LLNotificationsUtil::add("PushRestricted");
break;
case BUILD_ICON:
LLNotificationsUtil::add("NoBuild");
break;
case SCRIPTS_ICON:
{
LLViewerRegion* region = gAgent.getRegion();
if(region && region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS)
{
LLNotificationsUtil::add("ScriptsStopped");
}
else if(region && region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS)
{
LLNotificationsUtil::add("ScriptsNotRunning");
}
else
{
LLNotificationsUtil::add("NoOutsideScripts");
}
break;
}
case DAMAGE_ICON:
LLNotificationsUtil::add("NotSafe");
break;
case ICON_COUNT:
break;
// no default to get compiler warning when a new icon gets added
}
}

View File

@ -102,6 +102,18 @@ public:
void handleLoginComplete();
private:
enum EParcelIcon
{
VOICE_ICON = 0,
FLY_ICON,
PUSH_ICON,
BUILD_ICON,
SCRIPTS_ICON,
DAMAGE_ICON,
ICON_COUNT
};
friend class LLUICtrlFactory;
LLLocationInputCtrl(const Params&);
virtual ~LLLocationInputCtrl();
@ -138,6 +150,7 @@ private:
// callbacks
bool onLocationContextMenuItemEnabled(const LLSD& userdata);
void onLocationContextMenuItemClicked(const LLSD& userdata);
void onParcelIconClick(EParcelIcon icon);
LLMenuGL* mLocationContextMenu;
LLButton* mAddLandmarkBtn;
@ -146,16 +159,6 @@ private:
S32 mIconHPad; // pad between all icons
S32 mAddLandmarkHPad; // pad to left of landmark star
enum EParcelIcon
{
VOICE_ICON = 0,
FLY_ICON,
PUSH_ICON,
BUILD_ICON,
SCRIPTS_ICON,
DAMAGE_ICON,
ICON_COUNT
};
LLIconCtrl* mParcelIcon[ICON_COUNT];
LLTextBox* mDamageText;

View File

@ -237,15 +237,15 @@ void append_to_last_message(std::list<LLSD>& messages, const std::string& line)
messages.back()[IM_TEXT] = im_text;
}
void LLLogChat::loadAllHistory(const std::string& session_name, std::list<LLSD>& messages)
void LLLogChat::loadAllHistory(const std::string& file_name, std::list<LLSD>& messages)
{
if (session_name.empty())
if (file_name.empty())
{
llwarns << "Session name is Empty!" << llendl;
return ;
}
LLFILE* fptr = LLFile::fopen(makeLogFileName(session_name), "r"); /*Flawfinder: ignore*/
LLFILE* fptr = LLFile::fopen(makeLogFileName(file_name), "r"); /*Flawfinder: ignore*/
if (!fptr) return; //No previous conversation with this name.
char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/

View File

@ -56,7 +56,7 @@ public:
void (*callback)(ELogLineType, const LLSD&, void*),
void* userdata);
static void loadAllHistory(const std::string& session_name, std::list<LLSD>& messages);
static void loadAllHistory(const std::string& file_name, std::list<LLSD>& messages);
private:
static std::string cleanFileName(std::string filename);
};

View File

@ -869,38 +869,6 @@ void LLMediaCtrl::convertInputCoords(S32& x, S32& y)
};
}
////////////////////////////////////////////////////////////////////////////////
// static
bool LLMediaCtrl::onClickLinkExternalTarget(const LLSD& notification, const LLSD& response )
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if ( 0 == option )
{
LLSD payload = notification["payload"];
std::string url = payload["url"].asString();
S32 target_type = payload["target_type"].asInteger();
switch (target_type)
{
case LLPluginClassMedia::TARGET_EXTERNAL:
// load target in an external browser
LLWeb::loadURLExternal(url);
break;
case LLPluginClassMedia::TARGET_BLANK:
// load target in the user's preferred browser
LLWeb::loadURL(url);
break;
default:
// unsupported link target - shouldn't happen
LL_WARNS("LinkTarget") << "Unsupported link target type" << LL_ENDL;
break;
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
// inherited from LLViewerMediaObserver
//virtual
@ -1014,40 +982,79 @@ void LLMediaCtrl::onClickLinkHref( LLPluginClassMedia* self )
U32 target_type = self->getClickTargetType();
// is there is a target specified for the link?
if (target_type == LLPluginClassMedia::TARGET_EXTERNAL ||
target_type == LLPluginClassMedia::TARGET_BLANK)
if (gSavedSettings.getBOOL("UseExternalBrowser") || target_type == LLPluginClassMedia::TARGET_EXTERNAL)
{
LLSD payload;
payload["url"] = url;
payload["target_type"] = LLSD::Integer(target_type);
LLNotificationsUtil::add( "WebLaunchExternalTarget", LLSD(), payload, onClickLinkExternalTarget);
return;
}
else if (target_type == LLPluginClassMedia::TARGET_BLANK)
{
clickLinkWithTarget(url, target_type);
}
else {
const std::string protocol1( "http://" );
const std::string protocol2( "https://" );
if( mOpenLinksInExternalBrowser )
{
if ( !url.empty() )
{
if ( LLStringUtil::compareInsensitive( url.substr( 0, protocol1.length() ), protocol1 ) == 0 ||
LLStringUtil::compareInsensitive( url.substr( 0, protocol2.length() ), protocol2 ) == 0 )
{
LLWeb::loadURLExternal( url );
}
}
}
else
if( mOpenLinksInInternalBrowser )
{
if ( !url.empty() )
{
if ( LLStringUtil::compareInsensitive( url.substr( 0, protocol1.length() ), protocol1 ) == 0 ||
LLStringUtil::compareInsensitive( url.substr( 0, protocol2.length() ), protocol2 ) == 0 )
{
llwarns << "Dead, unimplemented path that we used to send to the built-in browser long ago." << llendl;
}
}
}
}
}
const std::string protocol1( "http://" );
const std::string protocol2( "https://" );
if( mOpenLinksInExternalBrowser )
////////////////////////////////////////////////////////////////////////////////
// static
bool LLMediaCtrl::onClickLinkExternalTarget(const LLSD& notification, const LLSD& response )
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
if ( 0 == option )
{
if ( !url.empty() )
{
if ( LLStringUtil::compareInsensitive( url.substr( 0, protocol1.length() ), protocol1 ) == 0 ||
LLStringUtil::compareInsensitive( url.substr( 0, protocol2.length() ), protocol2 ) == 0 )
{
LLWeb::loadURLExternal( url );
}
}
LLSD payload = notification["payload"];
std::string url = payload["url"].asString();
S32 target_type = payload["target_type"].asInteger();
clickLinkWithTarget(url, target_type);
}
else
if( mOpenLinksInInternalBrowser )
return false;
}
////////////////////////////////////////////////////////////////////////////////
// static
void LLMediaCtrl::clickLinkWithTarget(const std::string& url, const S32& target_type )
{
if (gSavedSettings.getBOOL("UseExternalBrowser") || target_type == LLPluginClassMedia::TARGET_EXTERNAL)
{
if ( !url.empty() )
{
if ( LLStringUtil::compareInsensitive( url.substr( 0, protocol1.length() ), protocol1 ) == 0 ||
LLStringUtil::compareInsensitive( url.substr( 0, protocol2.length() ), protocol2 ) == 0 )
{
llwarns << "Dead, unimplemented path that we used to send to the built-in browser long ago." << llendl;
}
}
// load target in an external browser
LLWeb::loadURLExternal(url);
}
else if (target_type == LLPluginClassMedia::TARGET_BLANK)
{
// load target in the user's preferred browser
LLWeb::loadURL(url);
}
else {
// unsupported link target - shouldn't happen
LL_WARNS("LinkTarget") << "Unsupported link target type" << LL_ENDL;
}
}

View File

@ -172,6 +172,7 @@ public:
private:
void onVisibilityChange ( const LLSD& new_visibility );
static bool onClickLinkExternalTarget( const LLSD&, const LLSD& );
static void clickLinkWithTarget(const std::string& url, const S32& target_type );
const S32 mTextureDepthBytes;
LLUUID mMediaTextureID;

View File

@ -64,6 +64,7 @@
#include "llviewerwindow.h"
#include "llworld.h" //for particle system banning
#include "llchat.h"
#include "llimpanel.h"
#include "llimview.h"
#include "llnotifications.h"
#include "lluistring.h"

View File

@ -65,6 +65,7 @@
#include "llvovolume.h"
#include "lluictrlfactory.h"
#include "llpluginclassmedia.h"
#include "llviewertexturelist.h"
//
// Methods
@ -406,14 +407,40 @@ void LLPanelFace::getState()
LLUUID id;
struct f1 : public LLSelectedTEGetFunctor<LLUUID>
{
LLUUID get(LLViewerObject* object, S32 te)
LLUUID get(LLViewerObject* object, S32 te_index)
{
LLViewerTexture* image = object->getTEImage(te);
return image ? image->getID() : LLUUID::null;
LLUUID id;
LLViewerTexture* image = object->getTEImage(te_index);
if (image) id = image->getID();
if (!id.isNull() && LLViewerMedia::textureHasMedia(id))
{
LLTextureEntry *te = object->getTE(te_index);
if (te)
{
LLViewerTexture* tex = te->getID().notNull() ? gTextureList.findImage(te->getID()) : NULL ;
if(!tex)
{
tex = LLViewerFetchedTexture::sDefaultImagep;
}
if (tex)
{
id = tex->getID();
}
}
}
return id;
}
} func;
identical = LLSelectMgr::getInstance()->getSelection()->getSelectedTEValue( &func, id );
if(LLViewerMedia::textureHasMedia(id))
{
childSetEnabled("textbox autofix",editable);
childSetEnabled("button align",editable);
}
if (identical)
{
// All selected have the same texture
@ -444,13 +471,6 @@ void LLPanelFace::getState()
}
}
}
if(LLViewerMedia::textureHasMedia(id))
{
childSetEnabled("textbox autofix",editable);
childSetEnabled("button align",editable);
}
}

View File

@ -356,13 +356,6 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
for(std::vector<LLPanelGroupTab* >::iterator it = mTabs.begin();it!=mTabs.end();++it)
(*it)->setGroupID(group_id);
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID);
if(gdatap)
{
childSetValue("group_name", gdatap->mName);
childSetToolTip("group_name",gdatap->mName);
}
LLButton* button_apply = findChild<LLButton>("btn_apply");
LLButton* button_refresh = findChild<LLButton>("btn_refresh");
LLButton* button_create = findChild<LLButton>("btn_create");
@ -425,6 +418,11 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
getChild<LLUICtrl>("group_name")->setVisible(false);
getChild<LLUICtrl>("group_name_editor")->setVisible(true);
if(button_call)
button_call->setVisible(false);
if(button_chat)
button_chat->setVisible(false);
}
else
{
@ -452,9 +450,24 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
if(button_apply)
button_apply->setVisible(is_member);
if(button_call)
button_call->setVisible(is_member);
if(button_chat)
button_chat->setVisible(is_member);
}
reposButtons();
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID);
if(gdatap)
{
childSetValue("group_name", gdatap->mName);
childSetToolTip("group_name",gdatap->mName);
//group data is already present, call update manually
update(GC_ALL);
}
}
bool LLPanelGroup::apply(LLPanelGroupTab* tab)

View File

@ -452,6 +452,7 @@ LLPanelGroupSubTab::LLPanelGroupSubTab()
: LLPanelGroupTab(),
mHeader(NULL),
mFooter(NULL),
mActivated(false),
mSearchEditor(NULL)
{
}
@ -504,13 +505,14 @@ void LLPanelGroupSubTab::setGroupID(const LLUUID& id)
mSearchEditor->clear();
setSearchFilter("");
}
mActivated = false;
}
void LLPanelGroupSubTab::setSearchFilter(const std::string& filter)
{
if(mSearchFilter == filter)
return;
lldebugs << "LLPanelGroupSubTab::setSearchFilter() ==> '" << filter << "'" << llendl;
mSearchFilter = filter;
LLStringUtil::toLower(mSearchFilter);
update(GC_ALL);
@ -518,13 +520,11 @@ void LLPanelGroupSubTab::setSearchFilter(const std::string& filter)
void LLPanelGroupSubTab::activate()
{
lldebugs << "LLPanelGroupSubTab::activate()" << llendl;
setOthersVisible(TRUE);
}
void LLPanelGroupSubTab::deactivate()
{
lldebugs << "LLPanelGroupSubTab::deactivate()" << llendl;
setOthersVisible(FALSE);
}
@ -534,19 +534,11 @@ void LLPanelGroupSubTab::setOthersVisible(BOOL b)
{
mHeader->setVisible( b );
}
else
{
llwarns << "LLPanelGroupSubTab missing header!" << llendl;
}
if (mFooter)
{
mFooter->setVisible( b );
}
else
{
llwarns << "LLPanelGroupSubTab missing footer!" << llendl;
}
}
bool LLPanelGroupSubTab::matchesActionSearchFilter(std::string action)
@ -875,10 +867,12 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
for (itor = selection.begin();
itor != selection.end(); ++itor)
{
selected_members.push_back( (*itor)->getUUID() );
LLUUID member_id = (*itor)->getValue()["uuid"];
selected_members.push_back( member_id );
// Get this member's power mask including any unsaved changes
U64 powers = getAgentPowersBasedOnRoleChanges((*itor)->getUUID());
U64 powers = getAgentPowersBasedOnRoleChanges( member_id );
allowed_by_all &= powers;
allowed_by_some |= powers;
@ -1022,6 +1016,7 @@ void LLPanelGroupMembersSubTab::handleMemberSelect()
//last owner. We should check for this special case
// -jwolk
check->setEnabled(cb_enable);
item->setEnabled(cb_enable);
}
}
else
@ -1098,7 +1093,8 @@ void LLPanelGroupMembersSubTab::handleEjectMembers()
for (itor = selection.begin() ;
itor != selection.end(); ++itor)
{
selected_members.push_back((*itor)->getUUID());
LLUUID member_id = (*itor)->getValue()["uuid"];
selected_members.push_back( member_id );
}
mMembersList->deleteSelectedItems();
@ -1154,7 +1150,8 @@ void LLPanelGroupMembersSubTab::handleRoleCheck(const LLUUID& role_id,
for (std::vector<LLScrollListItem*>::iterator itor = selection.begin() ;
itor != selection.end(); ++itor)
{
member_id = (*itor)->getUUID();
member_id = (*itor)->getValue()["uuid"];
//see if we requested a change for this member before
if ( mMemberRoleChangeData.find(member_id) == mMemberRoleChangeData.end() )
@ -1245,15 +1242,19 @@ void LLPanelGroupMembersSubTab::handleMemberDoubleClick()
LLScrollListItem* selected = mMembersList->getFirstSelected();
if (selected)
{
LLAvatarActions::showProfile(selected->getUUID());
LLUUID member_id = selected->getValue()["uuid"];
LLAvatarActions::showProfile( member_id );
}
}
void LLPanelGroupMembersSubTab::activate()
{
LLPanelGroupSubTab::activate();
update(GC_ALL);
if(!mActivated)
{
update(GC_ALL);
mActivated = true;
}
}
void LLPanelGroupMembersSubTab::deactivate()
@ -1629,7 +1630,9 @@ void LLPanelGroupMembersSubTab::updateMembers()
row["columns"][2]["value"] = mMemberProgress->second->getOnlineStatus();
row["columns"][2]["font"] = "SANSSERIF_SMALL";
mMembersList->addElement(row);//, ADD_SORTED);
LLScrollListItem* member = mMembersList->addElement(row);//, ADD_SORTED);
LLUUID id = member->getValue()["uuid"];
mHasMatch = TRUE;
}
}

View File

@ -149,6 +149,8 @@ protected:
icon_map_t mActionIcons;
bool mActivated;
void setOthersVisible(BOOL b);
};

View File

@ -46,6 +46,7 @@
#include "llimview.h"
#include "llvoicechannel.h"
#include "llsidetray.h"
#include "llspeakers.h"
#include "lltrans.h"
void LLPanelChatControlPanel::onCallButtonClicked()
@ -244,7 +245,6 @@ void LLPanelIMControlPanel::nameUpdatedCallback(const LLUUID& id, const std::str
LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id):
mParticipantList(NULL)
{
mSpeakerManager = LLIMModel::getInstance()->getSpeakerManager(session_id);
}
BOOL LLPanelGroupControlPanel::postBuild()
@ -263,9 +263,6 @@ LLPanelGroupControlPanel::~LLPanelGroupControlPanel()
// virtual
void LLPanelGroupControlPanel::draw()
{
//Remove event does not raised until speakerp->mActivityTimer.hasExpired() is false, see LLSpeakerManager::update()
//so we need update it to raise needed event
mSpeakerManager->update(true);
// Need to resort the participant list if it's in sort by recent speaker order.
if (mParticipantList)
mParticipantList->updateRecentSpeakersOrder();
@ -306,7 +303,10 @@ void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id)
// for group and Ad-hoc chat we need to include agent into list
if(!mParticipantList)
mParticipantList = new LLParticipantList(mSpeakerManager, getChild<LLAvatarList>("speakers_list"), true,false);
{
LLSpeakerMgr* speaker_manager = LLIMModel::getInstance()->getSpeakerManager(session_id);
mParticipantList = new LLParticipantList(speaker_manager, getChild<LLAvatarList>("speakers_list"), true,false);
}
}

View File

@ -37,8 +37,6 @@
#include "llvoicechannel.h"
#include "llcallingcard.h"
class LLSpeakerMgr;
class LLAvatarList;
class LLParticipantList;
class LLPanelChatControlPanel : public LLPanel
@ -110,7 +108,6 @@ public:
protected:
LLUUID mGroupID;
LLSpeakerMgr* mSpeakerManager;
LLParticipantList* mParticipantList;

View File

@ -37,6 +37,7 @@
// viewer includes
#include "llmimetypes.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
#include "lluictrlfactory.h"
// library includes
@ -83,8 +84,14 @@ BOOL LLPanelLandAudio::postBuild()
mCheckSoundLocal = getChild<LLCheckBoxCtrl>("check sound local");
childSetCommitCallback("check sound local", onCommitAny, this);
mRadioVoiceChat = getChild<LLRadioGroup>("parcel_voice_channel");
childSetCommitCallback("parcel_voice_channel", onCommitAny, this);
mCheckParcelEnableVoice = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel");
childSetCommitCallback("parcel_enable_voice_channel", onCommitAny, this);
// This one is always disabled so no need for a commit callback
mCheckEstateDisabledVoice = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel_is_estate_disabled");
mCheckParcelVoiceLocal = getChild<LLCheckBoxCtrl>("parcel_enable_voice_channel_local");
childSetCommitCallback("parcel_enable_voice_channel_local", onCommitAny, this);
mMusicURLEdit = getChild<LLLineEditor>("music_url");
childSetCommitCallback("music_url", onCommitAny, this);
@ -118,19 +125,33 @@ void LLPanelLandAudio::refresh()
mMusicUrlCheck->set( parcel->getObscureMusic() );
mMusicUrlCheck->setEnabled( can_change_media );
if(parcel->getParcelFlagAllowVoice())
bool allow_voice = parcel->getParcelFlagAllowVoice();
LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
if (region && region->isVoiceEnabled())
{
if(parcel->getParcelFlagUseEstateVoiceChannel())
mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatEstate);
else
mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatPrivate);
mCheckEstateDisabledVoice->setVisible(false);
mCheckParcelEnableVoice->setVisible(true);
mCheckParcelEnableVoice->setEnabled( can_change_media );
mCheckParcelEnableVoice->set(allow_voice);
mCheckParcelVoiceLocal->setEnabled( can_change_media && allow_voice );
}
else
{
mRadioVoiceChat->setSelectedIndex(kRadioVoiceChatDisable);
// Voice disabled at estate level, overrides parcel settings
// Replace the parcel voice checkbox with a disabled one
// labelled with an explanatory message
mCheckEstateDisabledVoice->setVisible(true);
mCheckParcelEnableVoice->setVisible(false);
mCheckParcelEnableVoice->setEnabled(false);
mCheckParcelVoiceLocal->setEnabled(false);
}
mRadioVoiceChat->setEnabled( can_change_media );
mCheckParcelEnableVoice->set(allow_voice);
mCheckParcelVoiceLocal->set(!parcel->getParcelFlagUseEstateVoiceChannel());
mMusicURLEdit->setText(parcel->getMusicURL());
mMusicURLEdit->setEnabled( can_change_media );
@ -149,30 +170,11 @@ void LLPanelLandAudio::onCommitAny(LLUICtrl*, void *userdata)
// Extract data from UI
BOOL sound_local = self->mCheckSoundLocal->get();
int voice_setting = self->mRadioVoiceChat->getSelectedIndex();
std::string music_url = self->mMusicURLEdit->getText();
U8 obscure_music = self->mMusicUrlCheck->get();
BOOL voice_enabled;
BOOL voice_estate_chan;
switch(voice_setting)
{
default:
case kRadioVoiceChatEstate:
voice_enabled = TRUE;
voice_estate_chan = TRUE;
break;
case kRadioVoiceChatPrivate:
voice_enabled = TRUE;
voice_estate_chan = FALSE;
break;
case kRadioVoiceChatDisable:
voice_enabled = FALSE;
voice_estate_chan = FALSE;
break;
}
BOOL voice_enabled = self->mCheckParcelEnableVoice->get();
BOOL voice_estate_chan = !self->mCheckParcelVoiceLocal->get();
// Remove leading/trailing whitespace (common when copying/pasting)
LLStringUtil::trim(music_url);

View File

@ -52,7 +52,9 @@ private:
private:
LLCheckBoxCtrl* mCheckSoundLocal;
LLRadioGroup* mRadioVoiceChat;
LLCheckBoxCtrl* mCheckParcelEnableVoice;
LLCheckBoxCtrl* mCheckEstateDisabledVoice;
LLCheckBoxCtrl* mCheckParcelVoiceLocal;
LLLineEditor* mMusicURLEdit;
LLCheckBoxCtrl* mMusicUrlCheck;

View File

@ -305,6 +305,29 @@ void LLLandmarksPanel::updateShowFolderState()
);
}
void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus)
{
if (selectItemInAccordionTab(mFavoritesInventoryPanel, "tab_favorites", obj_id, take_keyboard_focus))
{
return;
}
if (selectItemInAccordionTab(mLandmarksInventoryPanel, "tab_landmarks", obj_id, take_keyboard_focus))
{
return;
}
if (selectItemInAccordionTab(mMyInventoryPanel, "tab_inventory", obj_id, take_keyboard_focus))
{
return;
}
if (selectItemInAccordionTab(mLibraryInventoryPanel, "tab_library", obj_id, take_keyboard_focus))
{
return;
}
}
//////////////////////////////////////////////////////////////////////////
// PROTECTED METHODS
//////////////////////////////////////////////////////////////////////////
@ -350,6 +373,36 @@ LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem() const
return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL;
}
LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list,
const std::string& tab_name,
const LLUUID& obj_id,
BOOL take_keyboard_focus) const
{
if (!inventory_list)
return NULL;
LLFolderView* folder_view = inventory_list->getRootFolder();
LLFolderViewItem* item = folder_view->getItemByID(obj_id);
if (!item)
return NULL;
LLAccordionCtrlTab* tab = getChild<LLAccordionCtrlTab>(tab_name);
if (!tab->isExpanded())
{
tab->changeOpenClose(false);
}
folder_view->setSelection(item, FALSE, take_keyboard_focus);
LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion");
LLRect screen_rc;
localRectToScreen(item->getRect(), &screen_rc);
accordion->notifyParent(LLSD().with("scrollToShowRect", screen_rc.getValue()));
return item;
}
void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate)
{
if(!panel) return;

View File

@ -73,6 +73,11 @@ public:
*/
void updateShowFolderState();
/**
* Selects item with "obj_id" in one of accordion tabs.
*/
void setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_focus);
protected:
/**
* @return true - if current selected panel is not null and selected item is a landmark
@ -81,6 +86,17 @@ protected:
bool isReceivedFolderSelected() const;
void doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb);
LLFolderViewItem* getCurSelectedItem() const;
/**
* Selects item with "obj_id" in "inventory_list" and scrolls accordion
* scrollbar to show the item.
* Returns pointer to the item if it is found in "inventory_list", otherwise NULL.
*/
LLFolderViewItem* selectItemInAccordionTab(LLPlacesInventoryPanel* inventory_list,
const std::string& tab_name,
const LLUUID& obj_id,
BOOL take_keyboard_focus) const;
void updateSortOrder(LLInventoryPanel* panel, bool byDate);
//LLRemoteParcelInfoObserver interface

View File

@ -61,6 +61,9 @@
#include "llviewercontrol.h"
static const std::string OUTFITS_TAB_NAME = "outfitslist_tab";
static const std::string COF_TAB_NAME = "cof_tab";
static LLRegisterPanelClassWrapper<LLPanelOutfitsInventory> t_inventory("panel_outfits_inventory");
bool LLPanelOutfitsInventory::sShowDebugEditor = false;
@ -267,7 +270,7 @@ void LLPanelOutfitsInventory::onSaveCommit(const std::string& outfit_name)
if (mAppearanceTabs)
{
mAppearanceTabs->selectTabByName("outfitslist_tab");
mAppearanceTabs->selectTabByName(OUTFITS_TAB_NAME);
}
}
@ -503,8 +506,7 @@ BOOL LLPanelOutfitsInventory::isActionEnabled(const LLSD& userdata)
if (command_name == "wear")
{
const BOOL is_my_outfits = (mActivePanel->getName() == "outfitslist_tab");
if (!is_my_outfits)
if (isCOFPanelActive())
{
return FALSE;
}
@ -558,17 +560,15 @@ bool LLPanelOutfitsInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropTy
void LLPanelOutfitsInventory::initTabPanels()
{
mTabPanels.resize(2);
LLInventoryPanel *cof_panel = getChild<LLInventoryPanel>("cof_tab");
LLInventoryPanel *cof_panel = getChild<LLInventoryPanel>(COF_TAB_NAME);
cof_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
mTabPanels[0] = cof_panel;
LLInventoryPanel *myoutfits_panel = getChild<LLInventoryPanel>("outfitslist_tab");
mTabPanels.push_back(cof_panel);
LLInventoryPanel *myoutfits_panel = getChild<LLInventoryPanel>(OUTFITS_TAB_NAME);
myoutfits_panel->setFilterTypes(1LL << LLFolderType::FT_OUTFIT, LLInventoryFilter::FILTERTYPE_CATEGORY);
myoutfits_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
mTabPanels[1] = myoutfits_panel;
mTabPanels.push_back(myoutfits_panel);
for (tabpanels_vec_t::iterator iter = mTabPanels.begin();
iter != mTabPanels.end();
++iter)
@ -615,19 +615,19 @@ void LLPanelOutfitsInventory::onTabChange()
updateVerbs();
}
LLInventoryPanel* LLPanelOutfitsInventory::getActivePanel()
BOOL LLPanelOutfitsInventory::isTabPanel(LLInventoryPanel *panel) const
{
return mActivePanel;
}
bool LLPanelOutfitsInventory::isTabPanel(LLInventoryPanel *panel)
{
for(tabpanels_vec_t::iterator it = mTabPanels.begin();
for(tabpanels_vec_t::const_iterator it = mTabPanels.begin();
it != mTabPanels.end();
++it)
{
if (*it == panel)
return true;
return TRUE;
}
return false;
return FALSE;
}
BOOL LLPanelOutfitsInventory::isCOFPanelActive() const
{
return (getActivePanel()->getName() == COF_TAB_NAME);
}

View File

@ -78,24 +78,26 @@ protected:
bool getIsCorrectType(const LLFolderViewEventListener *listenerp) const;
private:
LLSidepanelAppearance* mParent;
LLSaveFolderState* mSavedFolderState;
LLTabContainer* mAppearanceTabs;
std::string mFilterSubString;
LLSidepanelAppearance* mParent;
LLSaveFolderState* mSavedFolderState;
LLTabContainer* mAppearanceTabs;
std::string mFilterSubString;
public:
//////////////////////////////////////////////////////////////////////////////////
// tab panels
LLInventoryPanel* getActivePanel();
bool isTabPanel(LLInventoryPanel *panel);
LLInventoryPanel* getActivePanel() { return mActivePanel; }
const LLInventoryPanel* getActivePanel() const { return mActivePanel; }
BOOL isTabPanel(LLInventoryPanel *panel) const;
protected:
void initTabPanels();
void onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action);
void onTabChange();
void initTabPanels();
void onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action);
void onTabChange();
BOOL isCOFPanelActive() const;
private:
LLInventoryPanel* mActivePanel;
LLInventoryPanel* mActivePanel;
typedef std::vector<LLInventoryPanel *> tabpanels_vec_t;
tabpanels_vec_t mTabPanels;

View File

@ -34,26 +34,20 @@
#include "llpanelplaceinfo.h"
#include "roles_constants.h"
#include "llsdutil.h"
#include "llsecondlifeurls.h"
#include "llsdutil_math.h"
#include "llregionhandle.h"
#include "message.h"
#include "lliconctrl.h"
#include "lltextbox.h"
#include "llagent.h"
#include "llavatarpropertiesprocessor.h"
#include "llexpandabletextbox.h"
#include "llpanelpick.h"
#include "lltexturectrl.h"
#include "llviewerinventory.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
#include "llviewertexteditor.h"
LLPanelPlaceInfo::LLPanelPlaceInfo()
: LLPanel(),
@ -265,25 +259,6 @@ void LLPanelPlaceInfo::reshape(S32 width, S32 height, BOOL called_from_parent)
}
}
// virtual
void LLPanelPlaceInfo::handleVisibilityChange(BOOL new_visibility)
{
LLPanel::handleVisibilityChange(new_visibility);
LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
if (!parcel_mgr)
return;
// Remove land selection when panel hides.
if (!new_visibility)
{
if (!parcel_mgr->selectionEmpty())
{
parcel_mgr->deselectLand();
}
}
}
void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel)
{
std::string region_name = mRegionName->getText();

View File

@ -94,7 +94,6 @@ public:
/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
/*virtual*/ void handleVisibilityChange (BOOL new_visibility);
// Create a pick for the location specified
// by global_pos.

View File

@ -257,6 +257,25 @@ void LLPanelPlaceProfile::processParcelInfo(const LLParcelData& parcel_data)
}
}
// virtual
void LLPanelPlaceProfile::handleVisibilityChange(BOOL new_visibility)
{
LLPanel::handleVisibilityChange(new_visibility);
LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
if (!parcel_mgr)
return;
// Remove land selection when panel hides.
if (!new_visibility)
{
if (!parcel_mgr->selectionEmpty())
{
parcel_mgr->deselectUnused();
}
}
}
void LLPanelPlaceProfile::displaySelectedParcelInfo(LLParcel* parcel,
LLViewerRegion* region,
const LLVector3d& pos_global,

View File

@ -52,6 +52,8 @@ public:
/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
/*virtual*/ void handleVisibilityChange(BOOL new_visibility);
// Displays information about the currently selected parcel
// without sending a request to the server.
// If is_current_parcel true shows "You Are Here" banner.

View File

@ -289,88 +289,91 @@ BOOL LLPanelPlaces::postBuild()
void LLPanelPlaces::onOpen(const LLSD& key)
{
if(!mPlaceProfile || !mLandmarkInfo || key.size() == 0)
if (!mPlaceProfile || !mLandmarkInfo)
return;
mFilterEditor->clear();
onFilterEdit("", false);
mPlaceInfoType = key["type"].asString();
mPosGlobal.setZero();
mItem = NULL;
isLandmarkEditModeOn = false;
togglePlaceInfoPanel(TRUE);
if (mPlaceInfoType == AGENT_INFO_TYPE)
if (key.size() != 0)
{
mPlaceProfile->setInfoType(LLPanelPlaceInfo::AGENT);
}
else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
{
mLandmarkInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK);
mFilterEditor->clear();
onFilterEdit("", false);
if (key.has("x") && key.has("y") && key.has("z"))
mPlaceInfoType = key["type"].asString();
mPosGlobal.setZero();
mItem = NULL;
isLandmarkEditModeOn = false;
togglePlaceInfoPanel(TRUE);
if (mPlaceInfoType == AGENT_INFO_TYPE)
{
mPosGlobal = LLVector3d(key["x"].asReal(),
key["y"].asReal(),
key["z"].asReal());
mPlaceProfile->setInfoType(LLPanelPlaceInfo::AGENT);
}
else
else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
{
mPosGlobal = gAgent.getPositionGlobal();
mLandmarkInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK);
if (key.has("x") && key.has("y") && key.has("z"))
{
mPosGlobal = LLVector3d(key["x"].asReal(),
key["y"].asReal(),
key["z"].asReal());
}
else
{
mPosGlobal = gAgent.getPositionGlobal();
}
mLandmarkInfo->displayParcelInfo(LLUUID(), mPosGlobal);
// Disable Save button because there is no item to save yet.
// The button will be enabled in onLandmarkLoaded callback.
mSaveBtn->setEnabled(FALSE);
}
mLandmarkInfo->displayParcelInfo(LLUUID(), mPosGlobal);
// Disable Save button because there is no item to save yet.
// The button will be enabled in onLandmarkLoaded callback.
mSaveBtn->setEnabled(FALSE);
}
else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
{
mLandmarkInfo->setInfoType(LLPanelPlaceInfo::LANDMARK);
LLInventoryItem* item = gInventory.getItem(key["id"].asUUID());
if (!item)
return;
setItem(item);
}
else if (mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
{
if (key.has("id"))
else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
{
LLUUID parcel_id = key["id"].asUUID();
mPlaceProfile->setParcelID(parcel_id);
mLandmarkInfo->setInfoType(LLPanelPlaceInfo::LANDMARK);
// query the server to get the global 3D position of this
// parcel - we need this for teleport/mapping functions.
mRemoteParcelObserver->setParcelID(parcel_id);
LLInventoryItem* item = gInventory.getItem(key["id"].asUUID());
if (!item)
return;
setItem(item);
}
else
else if (mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
{
mPosGlobal = LLVector3d(key["x"].asReal(),
key["y"].asReal(),
key["z"].asReal());
if (key.has("id"))
{
LLUUID parcel_id = key["id"].asUUID();
mPlaceProfile->setParcelID(parcel_id);
// query the server to get the global 3D position of this
// parcel - we need this for teleport/mapping functions.
mRemoteParcelObserver->setParcelID(parcel_id);
}
else
{
mPosGlobal = LLVector3d(key["x"].asReal(),
key["y"].asReal(),
key["z"].asReal());
mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
}
mPlaceProfile->setInfoType(LLPanelPlaceInfo::PLACE);
}
else if (mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
{
S32 index = key["id"].asInteger();
const LLTeleportHistoryStorage::slurl_list_t& hist_items =
LLTeleportHistoryStorage::getInstance()->getItems();
mPosGlobal = hist_items[index].mGlobalPos;
mPlaceProfile->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY);
mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
}
mPlaceProfile->setInfoType(LLPanelPlaceInfo::PLACE);
updateVerbs();
}
else if (mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
{
S32 index = key["id"].asInteger();
const LLTeleportHistoryStorage::slurl_list_t& hist_items =
LLTeleportHistoryStorage::getInstance()->getItems();
mPosGlobal = hist_items[index].mGlobalPos;
mPlaceProfile->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY);
mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
}
updateVerbs();
LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
if (!parcel_mgr)
@ -388,9 +391,12 @@ void LLPanelPlaces::onOpen(const LLSD& key)
{
parcel_mgr->removeObserver(mParcelObserver);
// Clear the reference to selection to allow its removal in deselectUnused().
mParcel.clear();
if (!parcel_mgr->selectionEmpty())
{
parcel_mgr->deselectLand();
parcel_mgr->deselectUnused();
}
}
}
@ -765,23 +771,23 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param)
mPickPanel->reshape(rect.getWidth(), rect.getHeight());
mPickPanel->setRect(rect);
}
else if (item == "add_to_favbar")
{
if ( mItem.notNull() )
{
const LLUUID& favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
if ( favorites_id.notNull() )
{
copy_inventory_item(gAgent.getID(),
mItem->getPermissions().getOwner(),
mItem->getUUID(),
favorites_id,
std::string(),
LLPointer<LLInventoryCallback>(NULL));
llinfos << "Copied inventory item #" << mItem->getUUID() << " to favorites." << llendl;
}
}
}
else if (item == "add_to_favbar")
{
if ( mItem.notNull() )
{
const LLUUID& favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
if ( favorites_id.notNull() )
{
copy_inventory_item(gAgent.getID(),
mItem->getPermissions().getOwner(),
mItem->getUUID(),
favorites_id,
std::string(),
LLPointer<LLInventoryCallback>(NULL));
llinfos << "Copied inventory item #" << mItem->getUUID() << " to favorites." << llendl;
}
}
}
}
void LLPanelPlaces::onBackButtonClicked()
@ -826,6 +832,14 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
mLandmarkInfo->setVisible(FALSE);
}
else if (mPlaceInfoType == AGENT_INFO_TYPE)
{
LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
// Clear reference to parcel selection when closing place profile panel.
// LLViewerParcelMgr removes the selection if it has 1 reference to it.
mParcel.clear();
}
}
else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE ||
mPlaceInfoType == LANDMARK_INFO_TYPE)
@ -842,6 +856,33 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
mPlaceProfile->setVisible(FALSE);
}
else
{
LLLandmarksPanel* landmarks_panel =
dynamic_cast<LLLandmarksPanel*>(mTabContainer->getPanelByName("Landmarks"));
if (landmarks_panel && mItem.notNull())
{
// If a landmark info is being closed we open the landmarks tab
// and set this landmark selected.
mTabContainer->selectTabPanel(landmarks_panel);
landmarks_panel->setItemSelected(mItem->getUUID(), TRUE);
}
}
}
}
// virtual
void LLPanelPlaces::handleVisibilityChange(BOOL new_visibility)
{
LLPanel::handleVisibilityChange(new_visibility);
if (!new_visibility && mPlaceInfoType == AGENT_INFO_TYPE)
{
LLViewerParcelMgr::getInstance()->removeObserver(mParcelObserver);
// Clear reference to parcel selection when closing places panel.
mParcel.clear();
}
}

View File

@ -97,6 +97,8 @@ private:
void togglePickPanel(BOOL visible);
void togglePlaceInfoPanel(BOOL visible);
/*virtual*/ void handleVisibilityChange(BOOL new_visibility);
void updateVerbs();
LLPanelPlaceInfo* getCurrentInfoPanel();

View File

@ -1036,7 +1036,7 @@ void LLTeleportHistoryPanel::setAccordionCollapsedByUser(LLUICtrl* acc_tab, bool
bool LLTeleportHistoryPanel::isAccordionCollapsedByUser(LLUICtrl* acc_tab)
{
LLSD param = acc_tab->getValue();
if(!param.has("acc_collapsed"))
if(!param.has(COLLAPSED_BY_USER))
{
return false;
}

View File

@ -125,6 +125,8 @@ LLParticipantList::~LLParticipantList()
delete mParticipantListMenu;
mParticipantListMenu = NULL;
}
mAvatarList->setContextMenu(NULL);
}
void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible)
@ -431,6 +433,10 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()
LLContextMenu* main_menu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
"menu_participant_list.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance());
// Don't show sort options for P2P chat
bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1);
main_menu->setItemVisible("SortByName", is_sort_visible);
main_menu->setItemVisible("SortByRecentSpeakers", is_sort_visible);
main_menu->setItemVisible("Moderator Options", isGroupModerator());
main_menu->arrangeAndClear();
@ -456,11 +462,6 @@ void LLParticipantList::LLParticipantListMenu::show(LLView* spawning_view, const
LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteSelected", false);
LLMenuGL::sMenuContainer->childSetVisible("ModerateVoiceUnMuteOthers", false);
}
// Don't show sort options for P2P chat
bool is_sort_visible = (mParent.mAvatarList && mParent.mAvatarList->size() > 1);
LLMenuGL::sMenuContainer->childSetVisible("SortByName", is_sort_visible);
LLMenuGL::sMenuContainer->childSetVisible("SortByRecentSpeakers", is_sort_visible);
}
void LLParticipantList::LLParticipantListMenu::sortParticipantList(const LLSD& userdata)

View File

@ -380,138 +380,53 @@ void LLPreviewTexture::updateDimensions()
mUpdateDimensions = FALSE;
S32 image_height = llmax(1, mImage->getFullHeight());
S32 image_width = llmax(1, mImage->getFullWidth());
// Attempt to make the image 1:1 on screen.
// If that fails, cut width by half.
S32 client_width = image_width;
S32 client_height = image_height;
S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE;
S32 vert_pad = PREVIEW_HEADER_SIZE + 2 * CLIENT_RECT_VPAD + LLPANEL_BORDER_WIDTH;
S32 max_client_width = gViewerWindow->getWindowWidthScaled() - horiz_pad;
S32 max_client_height = gViewerWindow->getWindowHeightScaled() - vert_pad;
if (mAspectRatio > 0.f)
{
client_height = llceil((F32)client_width / mAspectRatio);
}
while ((client_width > max_client_width) ||
(client_height > max_client_height ))
{
client_width /= 2;
client_height /= 2;
}
S32 view_width = client_width + horiz_pad;
S32 view_height = client_height + vert_pad;
// set text on dimensions display (should be moved out of here and into a callback of some sort)
childSetTextArg("dimensions", "[WIDTH]", llformat("%d", mImage->getFullWidth()));
childSetTextArg("dimensions", "[HEIGHT]", llformat("%d", mImage->getFullHeight()));
LLRect dim_rect;
childGetRect("dimensions", dim_rect);
S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE;
// add space for dimensions and aspect ratio
S32 info_height = 0;
LLRect aspect_rect;
childGetRect("combo_aspect_ratio", aspect_rect);
S32 aspect_height = aspect_rect.getHeight();
info_height += aspect_height + CLIENT_RECT_VPAD;
view_height += info_height;
S32 button_height = 0;
// add space for buttons
view_height += (BTN_HEIGHT + CLIENT_RECT_VPAD) * 3;
button_height = (BTN_HEIGHT + PREVIEW_PAD) * 3;
S32 info_height = dim_rect.mTop + CLIENT_RECT_VPAD;
view_width = llmax(view_width, getMinWidth());
view_height = llmax(view_height, getMinHeight());
if (view_height != mLastHeight || view_width != mLastWidth)
{
if (getHost())
{
getHost()->growToFit(view_width, view_height);
reshape( view_width, view_height );
setOrigin( 0, getHost()->getRect().getHeight() - (view_height + PREVIEW_HEADER_SIZE) );
}
else
{
S32 old_top = getRect().mTop;
S32 old_left = getRect().mLeft;
reshape( view_width, view_height );
S32 new_bottom = old_top - getRect().getHeight();
setOrigin( old_left, new_bottom );
}
// Try to keep whole view onscreen, don't allow partial offscreen.
if (getHost())
gFloaterView->adjustToFitScreen(getHost(), FALSE);
else
gFloaterView->adjustToFitScreen(this, FALSE);
if (image_height > 1 && image_width > 1)
{
// Resize until we know the image's height
mLastWidth = view_width;
mLastHeight = view_height;
}
}
if (!mUserResized)
{
// clamp texture size to fit within actual size of floater after attempting resize
client_width = llmin(client_width, getRect().getWidth() - horiz_pad);
client_height = llmin(client_height, getRect().getHeight() - PREVIEW_HEADER_SIZE
- (2 * CLIENT_RECT_VPAD) - LLPANEL_BORDER_WIDTH - info_height);
LLRect client_rect(horiz_pad, getRect().getHeight(), getRect().getWidth() - horiz_pad, 0);
client_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD);
client_rect.mBottom += PREVIEW_BORDER + CLIENT_RECT_VPAD + info_height ;
}
else
{
client_width = getRect().getWidth() - horiz_pad;
if (mAspectRatio > 0)
{
client_height = llround(client_width / mAspectRatio);
}
else
{
client_height = getRect().getHeight() - vert_pad;
}
}
S32 max_height = getRect().getHeight() - PREVIEW_BORDER - button_height
- CLIENT_RECT_VPAD - info_height - CLIENT_RECT_VPAD - PREVIEW_HEADER_SIZE;
S32 client_width = client_rect.getWidth();
S32 client_height = client_rect.getHeight();
if (mAspectRatio > 0.f)
{
max_height = llmax(max_height, 1);
if (client_height > max_height)
if(mAspectRatio > 1.f)
{
client_height = max_height;
client_width = llround(client_height * mAspectRatio);
client_height = llceil((F32)client_width / mAspectRatio);
if(client_height > client_rect.getHeight())
{
client_height = client_rect.getHeight();
client_width = llceil((F32)client_height * mAspectRatio);
}
}
else
{
client_width = llceil((F32)client_height * mAspectRatio);
if(client_width > client_rect.getWidth())
{
client_width = client_rect.getWidth();
client_height = llceil((F32)client_width / mAspectRatio);
}
}
}
else
{
S32 max_width = getRect().getWidth() - horiz_pad;
client_height = llclamp(client_height, 1, max_height);
client_width = llclamp(client_width, 1, max_width);
}
LLRect window_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
window_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD);
window_rect.mBottom += PREVIEW_BORDER + button_height + CLIENT_RECT_VPAD + info_height + CLIENT_RECT_VPAD;
mClientRect.setLeftTopAndSize(client_rect.getCenterX() - (client_width / 2), client_rect.getCenterY() + (client_height / 2), client_width, client_height);
mClientRect.setLeftTopAndSize(window_rect.getCenterX() - (client_width / 2), window_rect.mTop, client_width, client_height);
// Hide the aspect ratio label if the window is too narrow
// Assumes the label should be to the right of the dimensions
LLRect dim_rect, aspect_label_rect;
LLRect aspect_label_rect;
childGetRect("aspect_ratio", aspect_label_rect);
childGetRect("dimensions", dim_rect);
childSetVisible("aspect_ratio", dim_rect.mRight < aspect_label_rect.mLeft);
}

View File

@ -44,7 +44,6 @@
#include "llvoavatar.h"
#include "llworld.h"
const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers
const LLColor4 INACTIVE_COLOR(0.3f, 0.3f, 0.3f, 0.5f);
const LLColor4 ACTIVE_COLOR(0.5f, 0.5f, 0.5f, 1.f);
@ -73,8 +72,6 @@ LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerTy
}
gVoiceClient->setUserVolume(id, LLMuteList::getInstance()->getSavedResidentVolume(id));
mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
}
@ -164,6 +161,89 @@ bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPo
return( lhs->mDisplayName.compare(rhs->mDisplayName) < 0 );
}
LLSpeakerActionTimer::LLSpeakerActionTimer(action_callback_t action_cb, F32 action_period, const LLUUID& speaker_id)
: LLEventTimer(action_period)
, mActionCallback(action_cb)
, mSpeakerId(speaker_id)
{
}
BOOL LLSpeakerActionTimer::tick()
{
if (mActionCallback)
{
return (BOOL)mActionCallback(mSpeakerId);
}
return TRUE;
}
LLSpeakersDelayActionsStorage::LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay)
: mActionCallback(action_cb)
, mActionDelay(action_delay)
{
}
LLSpeakersDelayActionsStorage::~LLSpeakersDelayActionsStorage()
{
removeAllTimers();
}
void LLSpeakersDelayActionsStorage::setActionTimer(const LLUUID& speaker_id)
{
bool not_found = true;
if (mActionTimersMap.size() > 0)
{
not_found = mActionTimersMap.find(speaker_id) == mActionTimersMap.end();
}
// If there is already a started timer for the passed UUID don't do anything.
if (not_found)
{
// Starting a timer to remove an participant after delay is completed
mActionTimersMap.insert(LLSpeakerActionTimer::action_value_t(speaker_id,
new LLSpeakerActionTimer(
boost::bind(&LLSpeakersDelayActionsStorage::onTimerActionCallback, this, _1),
mActionDelay, speaker_id)));
}
}
void LLSpeakersDelayActionsStorage::unsetActionTimer(const LLUUID& speaker_id)
{
if (mActionTimersMap.size() == 0) return;
LLSpeakerActionTimer::action_timer_iter_t it_speaker = mActionTimersMap.find(speaker_id);
if (it_speaker != mActionTimersMap.end())
{
delete it_speaker->second;
mActionTimersMap.erase(it_speaker);
}
}
void LLSpeakersDelayActionsStorage::removeAllTimers()
{
LLSpeakerActionTimer::action_timer_iter_t iter = mActionTimersMap.begin();
for (; iter != mActionTimersMap.end(); ++iter)
{
delete iter->second;
}
mActionTimersMap.clear();
}
bool LLSpeakersDelayActionsStorage::onTimerActionCallback(const LLUUID& speaker_id)
{
unsetActionTimer(speaker_id);
if (mActionCallback)
{
mActionCallback(speaker_id);
}
// do not return true to avoid deleting of an timer twice:
// in LLSpeakersDelayActionsStorage::unsetActionTimer() & LLEventTimer::updateClass()
return false;
}
//
// LLSpeakerMgr
@ -172,10 +252,14 @@ bool LLSortRecentSpeakers::operator()(const LLPointer<LLSpeaker> lhs, const LLPo
LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) :
mVoiceChannel(channelp)
{
static LLUICachedControl<F32> remove_delay ("SpeakerParticipantRemoveDelay", 10.0);
mSpeakerDelayRemover = new LLSpeakersDelayActionsStorage(boost::bind(&LLSpeakerMgr::removeSpeaker, this, _1), remove_delay);
}
LLSpeakerMgr::~LLSpeakerMgr()
{
delete mSpeakerDelayRemover;
}
LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::string& name, LLSpeaker::ESpeakerStatus status, LLSpeaker::ESpeakerType type)
@ -198,7 +282,6 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
{
// keep highest priority status (lowest value) instead of overriding current value
speakerp->mStatus = llmin(speakerp->mStatus, status);
speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
// RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id
// we need to override speakers that we think are objects when we find out they are really
// residents
@ -210,6 +293,8 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin
}
}
mSpeakerDelayRemover->unsetActionTimer(speakerp->mID);
return speakerp;
}
@ -314,7 +399,7 @@ void LLSpeakerMgr::update(BOOL resort_ok)
S32 sort_index = 0;
speaker_list_t::iterator sorted_speaker_it;
for(sorted_speaker_it = mSpeakersSorted.begin();
sorted_speaker_it != mSpeakersSorted.end(); )
sorted_speaker_it != mSpeakersSorted.end(); ++sorted_speaker_it)
{
LLPointer<LLSpeaker> speakerp = *sorted_speaker_it;
@ -327,19 +412,6 @@ void LLSpeakerMgr::update(BOOL resort_ok)
// stuff sort ordinal into speaker so the ui can sort by this value
speakerp->mSortIndex = sort_index++;
// remove speakers that have been gone too long
if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL && speakerp->mActivityTimer.hasExpired())
{
fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "remove");
mSpeakers.erase(speakerp->mID);
sorted_speaker_it = mSpeakersSorted.erase(sorted_speaker_it);
}
else
{
++sorted_speaker_it;
}
}
}
@ -363,6 +435,35 @@ void LLSpeakerMgr::updateSpeakerList()
}
}
void LLSpeakerMgr::setSpeakerNotInChannel(LLSpeaker* speakerp)
{
speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
speakerp->mDotColor = INACTIVE_COLOR;
mSpeakerDelayRemover->setActionTimer(speakerp->mID);
}
bool LLSpeakerMgr::removeSpeaker(const LLUUID& speaker_id)
{
mSpeakers.erase(speaker_id);
speaker_list_t::iterator sorted_speaker_it = mSpeakersSorted.begin();
for(; sorted_speaker_it != mSpeakersSorted.end(); ++sorted_speaker_it)
{
if (speaker_id == (*sorted_speaker_it)->mID)
{
mSpeakersSorted.erase(sorted_speaker_it);
break;
}
}
fireEvent(new LLSpeakerListChangeEvent(this, speaker_id), "remove");
update(TRUE);
return false;
}
LLPointer<LLSpeaker> LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id)
{
//In some conditions map causes crash if it is empty(Windows only), adding check (EK)
@ -511,9 +612,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
{
if (agent_data["transition"].asString() == "LEAVE" && speakerp.notNull())
{
speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
speakerp->mDotColor = INACTIVE_COLOR;
speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
setSpeakerNotInChannel(speakerp);
}
else if (agent_data["transition"].asString() == "ENTER")
{
@ -563,9 +662,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)
std::string agent_transition = update_it->second.asString();
if (agent_transition == "LEAVE" && speakerp.notNull())
{
speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
speakerp->mDotColor = INACTIVE_COLOR;
speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
setSpeakerNotInChannel(speakerp);
}
else if ( agent_transition == "ENTER")
{
@ -734,12 +831,13 @@ void LLActiveSpeakerMgr::updateSpeakerList()
mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
// always populate from active voice channel
if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel)
if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel) //MA: seems this is always false
{
fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear");
mSpeakers.clear();
mSpeakersSorted.clear();
mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
mSpeakerDelayRemover->removeAllTimers();
}
LLSpeakerMgr::updateSpeakerList();
@ -800,9 +898,7 @@ void LLLocalSpeakerMgr::updateSpeakerList()
LLVOAvatar* avatarp = (LLVOAvatar*)gObjectList.findObject(speaker_id);
if (!avatarp || dist_vec(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS)
{
speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
speakerp->mDotColor = INACTIVE_COLOR;
speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
setSpeakerNotInChannel(speakerp);
}
}
}

View File

@ -73,7 +73,6 @@ public:
F32 mLastSpokeTime; // timestamp when this speaker last spoke
F32 mSpeechVolume; // current speech amplitude (timea average rms amplitude?)
std::string mDisplayName; // cache user name for this speaker
LLFrameTimer mActivityTimer; // time out speakers when they are not part of current voice channel
BOOL mHasSpoken; // has this speaker said anything this session?
BOOL mHasLeftCurrentCall; // has this speaker left the current voice call?
LLColor4 mDotColor;
@ -120,6 +119,92 @@ private:
const LLUUID& mSpeakerID;
};
/**
* class LLSpeakerActionTimer
*
* Implements a timer that calls stored callback action for stored speaker after passed period.
*
* Action is called until callback returns "true".
* In this case the timer will be removed via LLEventTimer::updateClass().
* Otherwise it should be deleted manually in place where it is used.
* If action callback is not set timer will tick only once and deleted.
*/
class LLSpeakerActionTimer : public LLEventTimer
{
public:
typedef boost::function<bool(const LLUUID&)> action_callback_t;
typedef std::map<LLUUID, LLSpeakerActionTimer*> action_timers_map_t;
typedef action_timers_map_t::value_type action_value_t;
typedef action_timers_map_t::const_iterator action_timer_const_iter_t;
typedef action_timers_map_t::iterator action_timer_iter_t;
/**
* Constructor.
*
* @param action_cb - callback which will be called each time after passed action period.
* @param action_period - time in seconds timer should tick.
* @param speaker_id - LLUUID of speaker which will be passed into action callback.
*/
LLSpeakerActionTimer(action_callback_t action_cb, F32 action_period, const LLUUID& speaker_id);
virtual ~LLSpeakerActionTimer() {};
/**
* Implements timer "tick".
*
* If action callback is not specified returns true. Instance will be deleted by LLEventTimer::updateClass().
*/
virtual BOOL tick();
private:
action_callback_t mActionCallback;
LLUUID mSpeakerId;
};
/**
* Represents a functionality to store actions for speakers with delay.
* Is based on LLSpeakerActionTimer.
*/
class LLSpeakersDelayActionsStorage
{
public:
LLSpeakersDelayActionsStorage(LLSpeakerActionTimer::action_callback_t action_cb, F32 action_delay);
~LLSpeakersDelayActionsStorage();
/**
* Sets new LLSpeakerActionTimer with passed speaker UUID.
*/
void setActionTimer(const LLUUID& speaker_id);
/**
* Removes stored LLSpeakerActionTimer for passed speaker UUID from internal map and deletes it.
*
* @see onTimerActionCallback()
*/
void unsetActionTimer(const LLUUID& speaker_id);
void removeAllTimers();
private:
/**
* Callback of the each instance of LLSpeakerActionTimer.
*
* Unsets an appropriate timer instance and calls action callback for specified speacker_id.
* It always returns false to not use LLEventTimer::updateClass functionality of timer deleting.
*
* @see unsetActionTimer()
*/
bool onTimerActionCallback(const LLUUID& speaker_id);
LLSpeakerActionTimer::action_timers_map_t mActionTimersMap;
LLSpeakerActionTimer::action_callback_t mActionCallback;
/**
* Delay to call action callback for speakers after timer was set.
*/
F32 mActionDelay;
};
class LLSpeakerMgr : public LLOldEvents::LLObservable
{
public:
@ -144,6 +229,8 @@ public:
protected:
virtual void updateSpeakerList();
void setSpeakerNotInChannel(LLSpeaker* speackerp);
bool removeSpeaker(const LLUUID& speaker_id);
typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t;
speaker_map_t mSpeakers;
@ -151,6 +238,11 @@ protected:
speaker_list_t mSpeakersSorted;
LLFrameTimer mSpeechTimer;
LLVoiceChannel* mVoiceChannel;
/**
* time out speakers when they are not part of current session
*/
LLSpeakersDelayActionsStorage* mSpeakerDelayRemover;
};
class LLIMSpeakerMgr : public LLSpeakerMgr

View File

@ -1140,6 +1140,10 @@ LLTexLayerInterface::LLTexLayerInterface(const LLTexLayerInterface &layer, LLWea
BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearable ) // This sets mInfo and calls initialization functions
{
//llassert(mInfo == NULL); // nyx says this is probably bogus but needs investigating
if (mInfo != NULL) // above llassert(), but softened into a warning
{
llwarns << "BAD STUFF! mInfo != NULL" << llendl;
}
mInfo = info;
//mID = info->mID; // No ID

View File

@ -1103,7 +1103,10 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op)
{
if (op == TEXTURE_CANCEL)
mViewModel->resetDirty();
else
// If the "no_commit_on_selection" parameter is set
// we get dirty only when user presses OK in the picker
// (i.e. op == TEXTURE_SELECT) or texture changes via DnD.
else if (mCommitOnSelection || op == TEXTURE_SELECT)
mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here?
if( floaterp->isDirty() )
@ -1125,7 +1128,7 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op)
{
// If the "no_commit_on_selection" parameter is set
// we commit only when user presses OK in the picker
// (i.e. op == TEXTURE_SELECT) or changes texture via DnD.
// (i.e. op == TEXTURE_SELECT) or texture changes via DnD.
if (mCommitOnSelection || op == TEXTURE_SELECT)
onCommit();
}
@ -1167,6 +1170,9 @@ BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask,
{
if(doDrop(item))
{
if (!mCommitOnSelection)
mViewModel->setDirty();
// This removes the 'Multiple' overlay, since
// there is now only one texture selected.
setTentative( FALSE );

View File

@ -74,7 +74,8 @@ public:
Optional<std::string> default_image_name;
Optional<bool> allow_no_texture;
Optional<bool> can_apply_immediately;
Optional<bool> no_commit_on_selection; // don't commit unless it's DnD or OK button press
Optional<bool> no_commit_on_selection; // alternative mode: commit occurs and the widget gets dirty
// only on DnD or when OK is pressed in the picker
Optional<S32> label_width;
Optional<LLUIColor> border_color;

View File

@ -661,78 +661,317 @@ static bool needs_tooltip(LLSelectNode* nodep)
return false;
}
BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)
BOOL LLToolPie::handleTooltipLand(std::string line, std::string tooltip_msg)
{
if (!LLUI::sSettingGroups["config"]->getBOOL("ShowHoverTips")) return TRUE;
if (!mHoverPick.isValid()) return TRUE;
LLViewerObject* hover_object = mHoverPick.getObject();
// update hover object and hover parcel
LLSelectMgr::getInstance()->setHoverObject(hover_object, mHoverPick.mObjectFace);
if (mHoverPick.mPickType == LLPickInfo::PICK_LAND)
LLViewerParcelMgr::getInstance()->setHoverParcel( mHoverPick.mPosGlobal );
//
// Do not show hover for land unless prefs are set to allow it.
//
if (!gSavedSettings.getBOOL("ShowLandHoverTip")) return TRUE;
// Didn't hit an object, but since we have a land point we
// must be hovering over land.
LLParcel* hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel();
LLUUID owner;
S32 width = 0;
S32 height = 0;
if ( hover_parcel )
{
LLViewerParcelMgr::getInstance()->setHoverParcel( mHoverPick.mPosGlobal );
owner = hover_parcel->getOwnerID();
width = S32(LLViewerParcelMgr::getInstance()->getHoverParcelWidth());
height = S32(LLViewerParcelMgr::getInstance()->getHoverParcelHeight());
}
std::string tooltip_msg;
std::string line;
if ( hover_object )
// Line: "Land"
line.clear();
line.append(LLTrans::getString("TooltipLand"));
if (hover_parcel)
{
if ( hover_object->isHUDAttachment() )
line.append(hover_parcel->getName());
}
tooltip_msg.append(line);
tooltip_msg.push_back('\n');
// Line: "Owner: James Linden"
line.clear();
line.append(LLTrans::getString("TooltipOwner") + " ");
if ( hover_parcel )
{
std::string name;
if (LLUUID::null == owner)
{
// no hover tips for HUD elements, since they can obscure
// what the HUD is displaying
line.append(LLTrans::getString("TooltipPublic"));
}
else if (hover_parcel->getIsGroupOwned())
{
if (gCacheName->getGroupName(owner, name))
{
line.append(name);
line.append(LLTrans::getString("TooltipIsGroup"));
}
else
{
line.append(LLTrans::getString("RetrievingData"));
}
}
else if(gCacheName->getFullName(owner, name))
{
line.append(name);
}
else
{
line.append(LLTrans::getString("RetrievingData"));
}
}
else
{
line.append(LLTrans::getString("RetrievingData"));
}
tooltip_msg.append(line);
tooltip_msg.push_back('\n');
// Line: "no fly, not safe, no build"
// Don't display properties for your land. This is just
// confusing, because you can do anything on your own land.
if ( hover_parcel && owner != gAgent.getID() )
{
S32 words = 0;
line.clear();
// JC - Keep this in the same order as the checkboxes
// on the land info panel
if ( !hover_parcel->getAllowModify() )
{
if ( hover_parcel->getAllowGroupModify() )
{
line.append(LLTrans::getString("TooltipFlagGroupBuild"));
}
else
{
line.append(LLTrans::getString("TooltipFlagNoBuild"));
}
words++;
}
if ( !hover_parcel->getAllowTerraform() )
{
if (words) line.append(", ");
line.append(LLTrans::getString("TooltipFlagNoEdit"));
words++;
}
if ( hover_parcel->getAllowDamage() )
{
if (words) line.append(", ");
line.append(LLTrans::getString("TooltipFlagNotSafe"));
words++;
}
// Maybe we should reflect the estate's block fly bit here as well? DK 12/1/04
if ( !hover_parcel->getAllowFly() )
{
if (words) line.append(", ");
line.append(LLTrans::getString("TooltipFlagNoFly"));
words++;
}
if ( !hover_parcel->getAllowOtherScripts() )
{
if (words) line.append(", ");
if ( hover_parcel->getAllowGroupScripts() )
{
line.append(LLTrans::getString("TooltipFlagGroupScripts"));
}
else
{
line.append(LLTrans::getString("TooltipFlagNoScripts"));
}
words++;
}
if (words)
{
tooltip_msg.append(line);
tooltip_msg.push_back('\n');
}
}
if (hover_parcel && hover_parcel->getParcelFlag(PF_FOR_SALE))
{
LLStringUtil::format_map_t args;
args["[AMOUNT]"] = llformat("%d", hover_parcel->getSalePrice());
line = LLTrans::getString("TooltipForSaleL$", args);
tooltip_msg.append(line);
tooltip_msg.push_back('\n');
}
// trim last newlines
if (!tooltip_msg.empty())
{
tooltip_msg.erase(tooltip_msg.size() - 1);
LLToolTipMgr::instance().show(tooltip_msg);
}
return TRUE;
}
BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string line, std::string tooltip_msg)
{
if ( hover_object->isHUDAttachment() )
{
// no hover tips for HUD elements, since they can obscure
// what the HUD is displaying
return TRUE;
}
if ( hover_object->isAttachment() )
{
// get root of attachment then parent, which is avatar
LLViewerObject* root_edit = hover_object->getRootEdit();
if (!root_edit)
{
// Strange parenting issue, don't show any text
return TRUE;
}
if ( hover_object->isAttachment() )
hover_object = (LLViewerObject*)root_edit->getParent();
if (!hover_object)
{
// get root of attachment then parent, which is avatar
LLViewerObject* root_edit = hover_object->getRootEdit();
if (!root_edit)
{
// Strange parenting issue, don't show any text
return TRUE;
}
hover_object = (LLViewerObject*)root_edit->getParent();
if (!hover_object)
{
// another strange parenting issue, bail out
return TRUE;
}
// another strange parenting issue, bail out
return TRUE;
}
line.clear();
if (hover_object->isAvatar())
}
line.clear();
if (hover_object->isAvatar())
{
// only show tooltip if same inspector not already open
LLFloater* existing_inspector = LLFloaterReg::findInstance("inspect_avatar");
if (!existing_inspector
|| !existing_inspector->getVisible()
|| existing_inspector->getKey()["avatar_id"].asUUID() != hover_object->getID())
{
// only show tooltip if same inspector not already open
LLFloater* existing_inspector = LLFloaterReg::findInstance("inspect_avatar");
if (!existing_inspector
|| !existing_inspector->getVisible()
|| existing_inspector->getKey()["avatar_id"].asUUID() != hover_object->getID())
std::string avatar_name;
LLNameValue* firstname = hover_object->getNVPair("FirstName");
LLNameValue* lastname = hover_object->getNVPair("LastName");
if (firstname && lastname)
{
std::string avatar_name;
LLNameValue* firstname = hover_object->getNVPair("FirstName");
LLNameValue* lastname = hover_object->getNVPair("LastName");
if (firstname && lastname)
avatar_name = llformat("%s %s", firstname->getString(), lastname->getString());
}
else
{
avatar_name = LLTrans::getString("TooltipPerson");
}
// *HACK: We may select this object, so pretend it was clicked
mPick = mHoverPick;
LLInspector::Params p;
p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());
p.message(avatar_name);
p.image.name("Inspector_I");
p.click_callback(boost::bind(showAvatarInspector, hover_object->getID()));
p.visible_time_near(6.f);
p.visible_time_far(3.f);
p.delay_time(0.35f);
p.wrap(false);
LLToolTipMgr::instance().show(p);
}
}
else
{
//
// We have hit a regular object (not an avatar or attachment)
//
//
// Default prefs will suppress display unless the object is interactive
//
bool show_all_object_tips =
(bool)gSavedSettings.getBOOL("ShowAllObjectHoverTip");
LLSelectNode *nodep = LLSelectMgr::getInstance()->getHoverNode();
// only show tooltip if same inspector not already open
LLFloater* existing_inspector = LLFloaterReg::findInstance("inspect_object");
if (nodep &&
(!existing_inspector
|| !existing_inspector->getVisible()
|| existing_inspector->getKey()["object_id"].asUUID() != hover_object->getID()))
{
if (nodep->mName.empty())
{
tooltip_msg.append(LLTrans::getString("TooltipNoName"));
}
else
{
tooltip_msg.append( nodep->mName );
}
bool is_time_based_media = false;
bool is_web_based_media = false;
bool is_media_playing = false;
// Does this face have media?
const LLTextureEntry* tep = hover_object->getTE(mHoverPick.mObjectFace);
if(tep)
{
const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
if (mep)
{
avatar_name = llformat("%s %s", firstname->getString(), lastname->getString());
viewer_media_t media_impl = mep ? LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()) : NULL;
LLPluginClassMedia* media_plugin = NULL;
if (media_impl.notNull() && (media_impl->hasMedia()))
{
LLStringUtil::format_map_t args;
media_plugin = media_impl->getMediaPlugin();
if(media_plugin)
{ if(media_plugin->pluginSupportsMediaTime())
{
is_time_based_media = true;
is_web_based_media = false;
//args["[CurrentURL]"] = media_impl->getMediaURL();
is_media_playing = media_impl->isMediaPlaying();
}
else
{
is_time_based_media = false;
is_web_based_media = true;
//args["[CurrentURL]"] = media_plugin->getLocation();
}
//tooltip_msg.append(LLTrans::getString("CurrentURL", args));
}
}
}
else
{
avatar_name = LLTrans::getString("TooltipPerson");
}
// *HACK: We may select this object, so pretend it was clicked
}
// also check the primary node since sometimes it can have an action even though
// the root node doesn't
bool needs_tip = needs_tooltip(nodep) ||
needs_tooltip(LLSelectMgr::getInstance()->getPrimaryHoverNode());
if (show_all_object_tips || needs_tip)
{
// We may select this object, so pretend it was clicked
mPick = mHoverPick;
LLInspector::Params p;
p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());
p.message(avatar_name);
p.message(tooltip_msg);
p.image.name("Inspector_I");
p.click_callback(boost::bind(showAvatarInspector, hover_object->getID()));
p.click_callback(boost::bind(showObjectInspector, hover_object->getID(), mHoverPick.mObjectFace));
p.time_based_media(is_time_based_media);
p.web_based_media(is_web_based_media);
p.media_playing(is_media_playing);
p.click_playmedia_callback(boost::bind(playCurrentMedia, mHoverPick));
p.click_homepage_callback(boost::bind(VisitHomePage, mHoverPick));
p.visible_time_near(6.f);
p.visible_time_far(3.f);
p.delay_time(0.35f);
@ -741,261 +980,33 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)
LLToolTipMgr::instance().show(p);
}
}
else
{
//
// We have hit a regular object (not an avatar or attachment)
//
//
// Default prefs will suppress display unless the object is interactive
//
bool show_all_object_tips =
(bool)gSavedSettings.getBOOL("ShowAllObjectHoverTip");
LLSelectNode *nodep = LLSelectMgr::getInstance()->getHoverNode();
// only show tooltip if same inspector not already open
LLFloater* existing_inspector = LLFloaterReg::findInstance("inspect_object");
if (nodep &&
(!existing_inspector
|| !existing_inspector->getVisible()
|| existing_inspector->getKey()["object_id"].asUUID() != hover_object->getID()))
{
if (nodep->mName.empty())
{
tooltip_msg.append(LLTrans::getString("TooltipNoName"));
}
else
{
tooltip_msg.append( nodep->mName );
}
bool is_time_based_media = false;
bool is_web_based_media = false;
bool is_media_playing = false;
// Does this face have media?
const LLTextureEntry* tep = hover_object->getTE(mHoverPick.mObjectFace);
if(tep)
{
const LLMediaEntry* mep = tep->hasMedia() ? tep->getMediaData() : NULL;
if (mep)
{
viewer_media_t media_impl = mep ? LLViewerMedia::getMediaImplFromTextureID(mep->getMediaID()) : NULL;
LLPluginClassMedia* media_plugin = NULL;
if (media_impl.notNull() && (media_impl->hasMedia()))
{
LLStringUtil::format_map_t args;
media_plugin = media_impl->getMediaPlugin();
if(media_plugin)
{ if(media_plugin->pluginSupportsMediaTime())
{
is_time_based_media = true;
is_web_based_media = false;
//args["[CurrentURL]"] = media_impl->getMediaURL();
is_media_playing = media_impl->isMediaPlaying();
}
else
{
is_time_based_media = false;
is_web_based_media = true;
//args["[CurrentURL]"] = media_plugin->getLocation();
}
//tooltip_msg.append(LLTrans::getString("CurrentURL", args));
}
}
}
}
// also check the primary node since sometimes it can have an action even though
// the root node doesn't
bool needs_tip = needs_tooltip(nodep) ||
needs_tooltip(LLSelectMgr::getInstance()->getPrimaryHoverNode());
if (show_all_object_tips || needs_tip)
{
// We may select this object, so pretend it was clicked
mPick = mHoverPick;
LLInspector::Params p;
p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());
p.message(tooltip_msg);
p.image.name("Inspector_I");
p.click_callback(boost::bind(showObjectInspector, hover_object->getID(), mHoverPick.mObjectFace));
p.time_based_media(is_time_based_media);
p.web_based_media(is_web_based_media);
p.media_playing(is_media_playing);
p.click_playmedia_callback(boost::bind(playCurrentMedia, mHoverPick));
p.click_homepage_callback(boost::bind(VisitHomePage, mHoverPick));
p.visible_time_near(6.f);
p.visible_time_far(3.f);
p.delay_time(0.35f);
p.wrap(false);
LLToolTipMgr::instance().show(p);
}
}
}
}
else if ( mHoverPick.mPickType == LLPickInfo::PICK_LAND )
return TRUE;
}
BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)
{
if (!LLUI::sSettingGroups["config"]->getBOOL("ShowHoverTips")) return TRUE;
if (!mHoverPick.isValid()) return TRUE;
LLViewerObject* hover_object = mHoverPick.getObject();
// update hover object and hover parcel
LLSelectMgr::getInstance()->setHoverObject(hover_object, mHoverPick.mObjectFace);
std::string tooltip_msg;
std::string line;
if ( hover_object )
{
//
// Do not show hover for land unless prefs are set to allow it.
//
if (!gSavedSettings.getBOOL("ShowLandHoverTip")) return TRUE;
// Didn't hit an object, but since we have a land point we
// must be hovering over land.
LLParcel* hover_parcel = LLViewerParcelMgr::getInstance()->getHoverParcel();
LLUUID owner;
S32 width = 0;
S32 height = 0;
if ( hover_parcel )
{
owner = hover_parcel->getOwnerID();
width = S32(LLViewerParcelMgr::getInstance()->getHoverParcelWidth());
height = S32(LLViewerParcelMgr::getInstance()->getHoverParcelHeight());
}
// Line: "Land"
line.clear();
line.append(LLTrans::getString("TooltipLand"));
if (hover_parcel)
{
line.append(hover_parcel->getName());
}
tooltip_msg.append(line);
tooltip_msg.push_back('\n');
// Line: "Owner: James Linden"
line.clear();
line.append(LLTrans::getString("TooltipOwner") + " ");
if ( hover_parcel )
{
std::string name;
if (LLUUID::null == owner)
{
line.append(LLTrans::getString("TooltipPublic"));
}
else if (hover_parcel->getIsGroupOwned())
{
if (gCacheName->getGroupName(owner, name))
{
line.append(name);
line.append(LLTrans::getString("TooltipIsGroup"));
}
else
{
line.append(LLTrans::getString("RetrievingData"));
}
}
else if(gCacheName->getFullName(owner, name))
{
line.append(name);
}
else
{
line.append(LLTrans::getString("RetrievingData"));
}
}
else
{
line.append(LLTrans::getString("RetrievingData"));
}
tooltip_msg.append(line);
tooltip_msg.push_back('\n');
// Line: "no fly, not safe, no build"
// Don't display properties for your land. This is just
// confusing, because you can do anything on your own land.
if ( hover_parcel && owner != gAgent.getID() )
{
S32 words = 0;
line.clear();
// JC - Keep this in the same order as the checkboxes
// on the land info panel
if ( !hover_parcel->getAllowModify() )
{
if ( hover_parcel->getAllowGroupModify() )
{
line.append(LLTrans::getString("TooltipFlagGroupBuild"));
}
else
{
line.append(LLTrans::getString("TooltipFlagNoBuild"));
}
words++;
}
if ( !hover_parcel->getAllowTerraform() )
{
if (words) line.append(", ");
line.append(LLTrans::getString("TooltipFlagNoEdit"));
words++;
}
if ( hover_parcel->getAllowDamage() )
{
if (words) line.append(", ");
line.append(LLTrans::getString("TooltipFlagNotSafe"));
words++;
}
// Maybe we should reflect the estate's block fly bit here as well? DK 12/1/04
if ( !hover_parcel->getAllowFly() )
{
if (words) line.append(", ");
line.append(LLTrans::getString("TooltipFlagNoFly"));
words++;
}
if ( !hover_parcel->getAllowOtherScripts() )
{
if (words) line.append(", ");
if ( hover_parcel->getAllowGroupScripts() )
{
line.append(LLTrans::getString("TooltipFlagGroupScripts"));
}
else
{
line.append(LLTrans::getString("TooltipFlagNoScripts"));
}
words++;
}
if (words)
{
tooltip_msg.append(line);
tooltip_msg.push_back('\n');
}
}
if (hover_parcel && hover_parcel->getParcelFlag(PF_FOR_SALE))
{
LLStringUtil::format_map_t args;
args["[AMOUNT]"] = llformat("%d", hover_parcel->getSalePrice());
line = LLTrans::getString("TooltipForSaleL$", args);
tooltip_msg.append(line);
tooltip_msg.push_back('\n');
}
// trim last newlines
if (!tooltip_msg.empty())
{
tooltip_msg.erase(tooltip_msg.size() - 1);
LLToolTipMgr::instance().show(tooltip_msg);
}
handleTooltipObject(hover_object, line, tooltip_msg );
}
else if (mHoverPick.mPickType == LLPickInfo::PICK_LAND)
{
handleTooltipLand(line, tooltip_msg);
}
return TRUE;
}

View File

@ -89,7 +89,9 @@ private:
bool handleMediaClick(const LLPickInfo& info);
bool handleMediaHover(const LLPickInfo& info);
bool handleMediaMouseUp();
bool handleMediaMouseUp();
BOOL handleTooltipLand(std::string line, std::string tooltip_msg);
BOOL handleTooltipObject( LLViewerObject* hover_object, std::string line, std::string tooltip_msg);
private:
BOOL mGrabMouseButtonDown;

View File

@ -42,6 +42,7 @@ LLTransientDockableFloater::LLTransientDockableFloater(LLDockControl* dockContro
LLDockableFloater(dockControl, uniqueDocking, key, params)
{
LLTransientFloaterMgr::getInstance()->registerTransientFloater(this);
LLTransientFloater::init(this);
}
LLTransientDockableFloater::~LLTransientDockableFloater()

View File

@ -37,12 +37,13 @@
#include "llfloater.h"
#include "lldockcontrol.h"
#include "lldockablefloater.h"
#include "lltransientfloatermgr.h"
/**
* Represents floater that can dock and managed by transient floater manager.
* Transient floaters should be hidden if user click anywhere except defined view list.
*/
class LLTransientDockableFloater : public LLDockableFloater
class LLTransientDockableFloater : public LLDockableFloater, LLTransientFloater
{
public:
LOG_CLASS(LLTransientDockableFloater);
@ -52,6 +53,7 @@ public:
/*virtual*/ void setVisible(BOOL visible);
/* virtual */void setDocked(bool docked, bool pop_on_undock = true);
virtual LLTransientFloaterMgr::ETransientGroup getGroup() { return LLTransientFloaterMgr::GLOBAL; }
};
#endif /* LL_TRANSIENTDOCKABLEFLOATER_H */

View File

@ -44,57 +44,68 @@ LLTransientFloaterMgr::LLTransientFloaterMgr()
{
gViewerWindow->getRootView()->addMouseDownCallback(boost::bind(
&LLTransientFloaterMgr::leftMouseClickCallback, this, _1, _2, _3));
mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(GLOBAL, std::set<LLView*>()));
mGroupControls.insert(std::pair<ETransientGroup, std::set<LLView*> >(IM, std::set<LLView*>()));
}
void LLTransientFloaterMgr::registerTransientFloater(LLFloater* floater)
void LLTransientFloaterMgr::registerTransientFloater(LLTransientFloater* floater)
{
mTransSet.insert(floater);
}
void LLTransientFloaterMgr::unregisterTransientFloater(LLFloater* floater)
void LLTransientFloaterMgr::unregisterTransientFloater(LLTransientFloater* floater)
{
mTransSet.erase(floater);
}
void LLTransientFloaterMgr::addControlView(ETransientGroup group, LLView* view)
{
mGroupControls.find(group)->second.insert(view);
}
void LLTransientFloaterMgr::removeControlView(ETransientGroup group, LLView* view)
{
mGroupControls.find(group)->second.erase(view);
}
void LLTransientFloaterMgr::addControlView(LLView* view)
{
mControlsSet.insert(view);
addControlView(GLOBAL, view);
}
void LLTransientFloaterMgr::removeControlView(LLView* view)
{
// we will still get focus lost callbacks on this view, but that's ok
// since we run sanity checking logic every time
mControlsSet.erase(view);
removeControlView(GLOBAL, view);
}
void LLTransientFloaterMgr::hideTransientFloaters()
void LLTransientFloaterMgr::hideTransientFloaters(S32 x, S32 y)
{
for (std::set<LLFloater*>::iterator it = mTransSet.begin(); it
for (std::set<LLTransientFloater*>::iterator it = mTransSet.begin(); it
!= mTransSet.end(); it++)
{
LLFloater* floater = *it;
if (floater->isDocked())
LLTransientFloater* floater = *it;
if (floater->isTransientDocked())
{
floater->setVisible(FALSE);
ETransientGroup group = floater->getGroup();
bool hide = isControlClicked(mGroupControls.find(group)->second, x, y);
if (hide)
{
floater->setTransientVisible(FALSE);
}
}
}
}
void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
MASK mask)
bool LLTransientFloaterMgr::isControlClicked(std::set<LLView*>& set, S32 x, S32 y)
{
bool hide = true;
for (controls_set_t::iterator it = mControlsSet.begin(); it
!= mControlsSet.end(); it++)
bool res = true;
for (controls_set_t::iterator it = set.begin(); it
!= set.end(); it++)
{
// don't hide transient floater if any context menu opened
if (LLMenuGL::sMenuContainer->getVisibleMenu() != NULL)
{
hide = false;
break;
}
LLView* control_view = *it;
if (!control_view->getVisible())
{
@ -105,14 +116,32 @@ void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
// if click inside view rect
if (rect.pointInRect(x, y))
{
hide = false;
res = false;
break;
}
}
return res;
}
void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
MASK mask)
{
// don't hide transient floater if any context menu opened
if (LLMenuGL::sMenuContainer->getVisibleMenu() != NULL)
{
return;
}
bool hide = isControlClicked(mGroupControls.find(GLOBAL)->second, x, y);
if (hide)
{
hideTransientFloaters();
hideTransientFloaters(x, y);
}
}
void LLTransientFloater::init(LLFloater* thiz)
{
// used since LLTransientFloater(this) can't be used in descendant constructor parameter initialization.
mFloater = thiz;
}

View File

@ -37,27 +37,60 @@
#include "llsingleton.h"
#include "llfloater.h"
class LLTransientFloater;
/**
* Provides functionality to hide transient floaters.
*/
class LLTransientFloaterMgr: public LLSingleton<LLTransientFloaterMgr>
{
public:
protected:
LLTransientFloaterMgr();
void registerTransientFloater(LLFloater* floater);
void unregisterTransientFloater(LLFloater* floater);
friend class LLSingleton<LLTransientFloaterMgr>;
public:
enum ETransientGroup
{
GLOBAL, IM
};
void registerTransientFloater(LLTransientFloater* floater);
void unregisterTransientFloater(LLTransientFloater* floater);
void addControlView(ETransientGroup group, LLView* view);
void removeControlView(ETransientGroup group, LLView* view);
void addControlView(LLView* view);
void removeControlView(LLView* view);
private:
void hideTransientFloaters();
void hideTransientFloaters(S32 x, S32 y);
void leftMouseClickCallback(S32 x, S32 y, MASK mask);
bool isControlClicked(std::set<LLView*>& set, S32 x, S32 y);
private:
std::set<LLTransientFloater*> mTransSet;
typedef std::set<LLView*> controls_set_t;
typedef std::map<ETransientGroup, std::set<LLView*> > group_controls_t;
group_controls_t mGroupControls;
};
/**
* An abstract class declares transient floater interfaces.
*/
class LLTransientFloater
{
protected:
/**
* Class initialization method.
* Should be called from descendant constructor.
*/
void init(LLFloater* thiz);
public:
virtual LLTransientFloaterMgr::ETransientGroup getGroup() = 0;
bool isTransientDocked() { return mFloater->isDocked(); };
void setTransientVisible(BOOL visible) {mFloater->setVisible(visible); }
private:
std::set<LLFloater*> mTransSet;
typedef std::set<LLView*> controls_set_t;
controls_set_t mControlsSet;
LLFloater* mFloater;
};
#endif // LL_LLTRANSIENTFLOATERMGR_H

View File

@ -483,7 +483,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
{
LLAppViewer::instance()->pingMainloopTimeout("Display:Disconnected");
render_ui();
render_disconnected_background();
}
//////////////////////////
@ -1135,6 +1134,10 @@ void render_ui(F32 zoom_factor, int subfield)
render_ui_3d();
LLGLState::checkStates();
}
else
{
render_disconnected_background();
}
render_ui_2d();
LLGLState::checkStates();

View File

@ -752,6 +752,11 @@ void LLViewerMedia::updateMedia(void *dummy_arg)
new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
impl_count_interest_normal++;
}
else if(pimpl->isParcelMedia())
{
new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
impl_count_interest_normal++;
}
else
{
// Look at interest and CPU usage for instances that aren't in any of the above states.

View File

@ -6099,7 +6099,8 @@ class LLAttachmentEnableDrop : public view_listener_t
LLViewerJointAttachment* attachment = NULL;
LLInventoryItem* item = NULL;
if (object)
// Do not enable drop if all faces of object are not enabled
if (object && LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES ))
{
S32 attachmentID = ATTACHMENT_ID_FROM_STATE(object->getState());
attachment = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, attachmentID, (LLViewerJointAttachment*)NULL);
@ -6141,8 +6142,14 @@ class LLAttachmentEnableDrop : public view_listener_t
BOOL enable_detach(const LLSD&)
{
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
if (!object) return FALSE;
if (!object->isAttachment()) return FALSE;
// Only enable detach if all faces of object are selected
if (!object ||
!object->isAttachment() ||
!LLSelectMgr::getInstance()->getSelection()->contains(object,SELECT_ALL_TES ))
{
return FALSE;
}
// Find the avatar who owns this attachment
LLViewerObject* avatar = object;

View File

@ -78,6 +78,7 @@
#include "llstatenums.h"
#include "llstatusbar.h"
#include "llimview.h"
#include "llspeakers.h"
#include "lltrans.h"
#include "llviewerfoldertype.h"
#include "lluri.h"
@ -1471,7 +1472,12 @@ void inventory_offer_handler(LLOfferInfo* info)
{
LLStringUtil::truncate(msg, indx);
}
if(LLAssetType::AT_LANDMARK == info->mType)
{
msg = LLViewerInventoryItem::getDisplayName(msg);
}
LLSD args;
args["[OBJECTNAME]"] = msg;
@ -2008,7 +2014,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
// Someone has offered us some inventory.
{
LLOfferInfo* info = new LLOfferInfo;
bool mute_im = false;
if (IM_INVENTORY_OFFERED == dialog)
{
struct offer_agent_bucket_t
@ -2025,11 +2030,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
bucketp = (struct offer_agent_bucket_t*) &binary_bucket[0];
info->mType = (LLAssetType::EType) bucketp->asset_type;
info->mObjectID = bucketp->object_id;
if(accept_im_from_only_friend&&!is_friend)
{
mute_im = true;
}
}
else
{
@ -2060,7 +2060,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
info->mDesc = message;
info->mHost = msg->getSender();
//if (((is_busy && !is_owned_by_me) || is_muted))
if ( is_muted || mute_im)
if (is_muted)
{
// Prefetch the offered item so that it can be discarded by the appropriate observer. (EXT-4331)
LLInventoryFetchObserver::item_ref_t items;

View File

@ -212,22 +212,15 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
else
{
// Since the texture id is different, we need to generate a new impl
LL_DEBUGS("Media") << "new media impl with mime type " << mime_type << ", url " << media_url << LL_ENDL;
// Delete the old one first so they don't fight over the texture.
sMediaImpl = NULL;
sMediaImpl = LLViewerMedia::newMediaImpl(
placeholder_texture_id,
media_width,
media_height,
media_auto_scale,
media_loop);
sMediaImpl->setIsParcelMedia(true);
sMediaImpl->navigateTo(media_url, mime_type, true);
// A new impl will be created below.
}
}
else
if(!sMediaImpl)
{
LL_DEBUGS("Media") << "new media impl with mime type " << mime_type << ", url " << media_url << LL_ENDL;

View File

@ -1560,7 +1560,11 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
void LLViewerFetchedTexture::setDecodePriority(F32 priority)
{
llassert(!mInImageList);
//llassert(!mInImageList); // firing a lot, figure out why
if (mInImageList) // above llassert() softened to a warning
{
llwarns << "BAD STUFF! mInImageList" << llendl;
}
mDecodePriority = priority;
}

View File

@ -502,7 +502,10 @@ void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image)
{
llerrs << "LLViewerTextureList::addImageToList - Image already in list" << llendl;
}
llverify((mImageList.insert(image)).second == true);
if ((mImageList.insert(image)).second != true)
{
llwarns << "BAD STUFF! (mImageList.insert(image)).second != true" << llendl;
}
image->setInImageList(TRUE) ;
}
@ -519,7 +522,10 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
}
llerrs << "LLViewerTextureList::removeImageFromList - Image not in list" << llendl;
}
llverify(mImageList.erase(image) == 1);
if (mImageList.erase(image) != 1)
{
llwarns << "BAD STUFF! mImageList.erase(image) != 1" << llendl;
}
image->setInImageList(FALSE) ;
}

View File

@ -63,6 +63,7 @@
#include "llparcel.h"
#include "llviewerparcelmgr.h"
//#include "llfirstuse.h"
#include "llspeakers.h"
#include "lltrans.h"
#include "llviewerwindow.h"
#include "llviewercamera.h"

View File

@ -252,9 +252,8 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)
// mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // usefull for debugging
mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);
mCurlRequest->setWriteCallback(&curlDownloadCallback, (void*)this);
BOOL vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert");
mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, vefifySSLCert);
mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, vefifySSLCert ? 2 : 0);
mCurlRequest->setopt(CURLOPT_SSL_VERIFYPEER, LLCurl::getSSLVerify());
mCurlRequest->setopt(CURLOPT_SSL_VERIFYHOST, LLCurl::getSSLVerify() ? 2 : 0);
// Be a little impatient about establishing connections.
mCurlRequest->setopt(CURLOPT_CONNECTTIMEOUT, 40L);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 490 B

After

Width:  |  Height:  |  Size: 309 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 302 B

After

Width:  |  Height:  |  Size: 309 B

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="floater_about" title="OM [APP_NAME]">
<floater name="floater_about" title="OM [CAPITALIZED_APP_NAME]">
<floater.string name="AboutHeader">
[APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL])
[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<floater name="floater_about" title="INFO ÜBER [APP_NAME]">
<floater name="floater_about" title="INFO ÜBER [CAPITALIZED_APP_NAME]">
<floater.string name="AboutHeader">
[APP_NAME] [VIEWER_VERSION_0].[VIEWER_VERSION_1].[VIEWER_VERSION_2] ([VIEWER_VERSION_3]) [BUILD_DATE] [BUILD_TIME] ([CHANNEL])
[[VIEWER_RELEASE_NOTES_URL] [ReleaseNotes]]

View File

@ -39,7 +39,7 @@
<line_editor name="homepage_edit" value="http://"/>
<check_box label="In Suchergebnissen anzeigen" name="show_in_search_checkbox"/>
<text name="title_acc_status_text" value="Mein Konto:"/>
<text name="my_account_link" value="Meine Startseite aufrufen"/>
<text name="my_account_link" value="[[URL] Meine Startseite aufrufen]"/>
<text name="acc_status_text" value="Einwohner. Keine Zahlungsinfo archiviert."/>
<text name="title_partner_text" value="Mein Partner:"/>
<text name="partner_edit_link" value="[[URL] bearbeiten]"/>

View File

@ -3,7 +3,6 @@
<!-- All buttons in the Favorites bar will be created from this one -->
<button
follows="left|bottom"
font_halign="center"
halign="center"
height="15"
image_disabled="transparent.j2c"
@ -11,6 +10,8 @@
image_selected="transparent.j2c"
image_unselected="transparent.j2c"
image_pressed="Favorite_Link_Over"
image_hover_selected="Favorite_Link_Over"
image_hover_unselected="Favorite_Link_Over"
hover_glow_amount="0.15"
label_shadow="false"
layout="topleft"

View File

@ -1871,13 +1871,14 @@ Only large parcels can be listed in search.
layout="topleft"
left="110"
name="parcel_enable_voice_channel_is_estate_disabled"
top_delta="0"
width="300" />
<check_box
height="16"
label="Restrict Voice to this parcel"
layout="topleft"
left="110"
name="parcel_enable_voice_channel_parcel"
name="parcel_enable_voice_channel_local"
width="300" />
</panel>
<panel

View File

@ -304,7 +304,7 @@ Re-enter amount to see the latest exchange rate.
</text>
<text
type="string"
width="175"
width="176"
height="125"
top="60"
left="165"

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<multi_floater
can_minimize="false"
can_close="false"
can_minimize="true"
can_resize="true"
height="390"
layout="topleft"

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