summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/llflatlistview.cpp30
-rw-r--r--indra/llui/llflatlistview.h2
-rw-r--r--indra/llui/llmenugl.cpp2
-rw-r--r--indra/llui/llnotificationslistener.cpp269
-rw-r--r--indra/llui/llnotificationslistener.h20
-rw-r--r--indra/llui/llurlentry.cpp4
-rw-r--r--indra/llui/llurlregistry.cpp20
-rw-r--r--indra/llui/llurlregistry.h4
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h6
-rw-r--r--indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp11
-rw-r--r--indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp63
-rw-r--r--indra/newview/CMakeLists.txt12
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl52
-rw-r--r--indra/newview/featuretable.txt3
-rw-r--r--indra/newview/featuretable_linux.txt3
-rw-r--r--indra/newview/featuretable_mac.txt3
-rw-r--r--indra/newview/llagentwearables.cpp21
-rw-r--r--indra/newview/llavatarlist.cpp16
-rw-r--r--indra/newview/llavatarlist.h12
-rw-r--r--indra/newview/llavatarlistitem.cpp58
-rw-r--r--indra/newview/llavatarlistitem.h14
-rw-r--r--indra/newview/llbottomtray.cpp32
-rw-r--r--indra/newview/llbottomtray.h2
-rw-r--r--indra/newview/llcallfloater.cpp271
-rw-r--r--indra/newview/llcallfloater.h41
-rw-r--r--indra/newview/llchathistory.cpp37
-rw-r--r--indra/newview/llchiclet.cpp287
-rw-r--r--indra/newview/llchiclet.h103
-rw-r--r--indra/newview/llcommanddispatcherlistener.cpp13
-rw-r--r--indra/newview/llcommanddispatcherlistener.h1
-rw-r--r--indra/newview/llcommandhandler.cpp55
-rw-r--r--indra/newview/llcommandhandler.h5
-rw-r--r--indra/newview/llfavoritesbar.cpp9
-rw-r--r--indra/newview/llfloaterland.cpp22
-rw-r--r--indra/newview/llfloaterland.h7
-rw-r--r--indra/newview/llfloaterscriptlimits.cpp1061
-rw-r--r--indra/newview/llfloaterscriptlimits.h259
-rw-r--r--indra/newview/llfloatertopobjects.cpp5
-rw-r--r--indra/newview/llfolderview.cpp6
-rw-r--r--indra/newview/llfolderviewitem.cpp31
-rw-r--r--indra/newview/llfolderviewitem.h9
-rw-r--r--indra/newview/llgroupactions.cpp30
-rw-r--r--indra/newview/llgroupactions.h5
-rw-r--r--indra/newview/llgrouplist.cpp71
-rw-r--r--indra/newview/llgrouplist.h6
-rw-r--r--indra/newview/llimview.cpp87
-rw-r--r--indra/newview/llinventorymodel.cpp73
-rw-r--r--indra/newview/llinventorymodel.h19
-rw-r--r--indra/newview/llinventorypanel.cpp7
-rw-r--r--indra/newview/lllogininstance.cpp41
-rw-r--r--indra/newview/lllogininstance.h2
-rwxr-xr-xindra/newview/llmediadataclient.cpp16
-rw-r--r--indra/newview/llmoveview.cpp2
-rw-r--r--indra/newview/llnavigationbar.cpp18
-rw-r--r--indra/newview/llnearbychat.cpp2
-rw-r--r--indra/newview/llpanelclassified.cpp39
-rw-r--r--indra/newview/llpanelclassified.h6
-rw-r--r--indra/newview/llpanelimcontrolpanel.cpp6
-rw-r--r--indra/newview/llpanelpeople.cpp8
-rw-r--r--indra/newview/llpanelpeople.h1
-rw-r--r--indra/newview/llpanelpeoplemenus.cpp2
-rw-r--r--indra/newview/llpanelpicks.cpp17
-rw-r--r--indra/newview/llpanelpicks.h2
-rw-r--r--indra/newview/llparticipantlist.cpp119
-rw-r--r--indra/newview/llparticipantlist.h34
-rw-r--r--indra/newview/llpreviewtexture.cpp4
-rw-r--r--indra/newview/llprogressview.cpp27
-rw-r--r--indra/newview/llprogressview.h6
-rw-r--r--indra/newview/llspeakbutton.cpp7
-rw-r--r--indra/newview/llspeakers.cpp2
-rw-r--r--indra/newview/llstartup.cpp22
-rw-r--r--indra/newview/llstartup.h1
-rw-r--r--indra/newview/llsyswellwindow.cpp112
-rw-r--r--indra/newview/llsyswellwindow.h12
-rw-r--r--indra/newview/lltexturefetch.cpp22
-rw-r--r--indra/newview/lltextureview.cpp28
-rw-r--r--indra/newview/lltoastalertpanel.h2
-rw-r--r--indra/newview/lltransientfloatermgr.cpp8
-rw-r--r--indra/newview/llviewerdisplay.cpp2
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/llviewermenu.cpp6
-rw-r--r--indra/newview/llviewermessage.cpp26
-rw-r--r--indra/newview/llviewerregion.cpp3
-rw-r--r--indra/newview/llviewerstats.cpp4
-rw-r--r--indra/newview/llviewertexture.cpp3
-rw-r--r--indra/newview/llvoicechannel.cpp5
-rw-r--r--indra/newview/llvovolume.cpp16
-rw-r--r--indra/newview/pipeline.cpp3
-rw-r--r--indra/newview/skins/default/textures/textures.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_about_land.xml13
-rw-r--r--indra/newview/skins/default/xui/en/floater_customize.xml25
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_texture.xml8
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_limits.xml20
-rw-r--r--indra/newview/skins/default/xui/en/floater_search.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_water.xml1
-rw-r--r--indra/newview/skins/default/xui/en/menu_im_well_button.xml16
-rw-r--r--indra/newview/skins/default/xui/en/menu_notification_well_button.xml16
-rw-r--r--indra/newview/skins/default/xui/en/menu_participant_list.xml30
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_groups.xml57
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml8
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml11
-rw-r--r--indra/newview/skins/default/xui/en/panel_activeim_row.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_bottomtray.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_im_control_panel.xml15
-rw-r--r--indra/newview/skins/default/xui/en/panel_landmark_info.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_outfits_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_people.xml10
-rw-r--r--indra/newview/skins/default/xui/en/panel_place_profile.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_places.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_setup.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml62
-rw-r--r--indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml122
-rw-r--r--indra/newview/skins/default/xui/en/panel_teleport_history_item.xml1
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_appearance.xml17
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml67
-rw-r--r--[-rwxr-xr-x]indra/newview/skins/default/xui/en/widgets/tab_container.xml0
-rwxr-xr-xindra/newview/viewer_manifest.py20
-rw-r--r--indra/test_apps/llplugintest/CMakeLists.txt42
-rw-r--r--indra/viewer_components/login/lllogin.cpp11
-rw-r--r--install.xml8
121 files changed, 3986 insertions, 438 deletions
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 64a4824a17..7b7a3139a4 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -530,7 +530,8 @@ BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask)
if ( !selectNextItemPair(true, reset_selection) && reset_selection)
{
// If case we are in accordion tab notify parent to go to the previous accordion
- notifyParent(LLSD().with("action","select_prev"));
+ if(notifyParent(LLSD().with("action","select_prev")) > 0 )//message was processed
+ resetSelection();
}
break;
}
@@ -539,7 +540,8 @@ BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask)
if ( !selectNextItemPair(false, reset_selection) && reset_selection)
{
// If case we are in accordion tab notify parent to go to the next accordion
- notifyParent(LLSD().with("action","select_next"));
+ if( notifyParent(LLSD().with("action","select_next")) > 0 ) //message was processed
+ resetSelection();
}
break;
}
@@ -558,6 +560,8 @@ BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask)
if ( ( key == KEY_UP || key == KEY_DOWN ) && mSelectedItemPairs.size() )
{
+ ensureSelectedVisible();
+ /*
LLRect visible_rc = getVisibleContentRect();
LLRect selected_rc = getLastSelectedItemRect();
@@ -570,7 +574,8 @@ BOOL LLFlatListView::handleKeyHere(KEY key, MASK mask)
// In case we are in accordion tab notify parent to show selected rectangle
LLRect screen_rc;
localRectToScreen(selected_rc, &screen_rc);
- notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));
+ notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));*/
+
handled = TRUE;
}
@@ -692,11 +697,30 @@ LLRect LLFlatListView::getSelectedItemsRect()
void LLFlatListView::selectFirstItem ()
{
selectItemPair(mItemPairs.front(), true);
+ ensureSelectedVisible();
}
void LLFlatListView::selectLastItem ()
{
selectItemPair(mItemPairs.back(), true);
+ ensureSelectedVisible();
+}
+
+void LLFlatListView::ensureSelectedVisible()
+{
+ LLRect visible_rc = getVisibleContentRect();
+ LLRect selected_rc = getLastSelectedItemRect();
+
+ if ( !visible_rc.contains (selected_rc) )
+ {
+ // But scroll in Items panel coordinates
+ scrollToShowRect(selected_rc);
+ }
+
+ // In case we are in accordion tab notify parent to show selected rectangle
+ LLRect screen_rc;
+ localRectToScreen(selected_rc, &screen_rc);
+ notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue()));
}
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
index ba824ff2df..26e84a6fe1 100644
--- a/indra/llui/llflatlistview.h
+++ b/indra/llui/llflatlistview.h
@@ -359,6 +359,8 @@ protected:
LLRect getSelectedItemsRect();
+ void ensureSelectedVisible();
+
private:
void setItemsNoScrollWidth(S32 new_width) {mItemsNoScrollWidth = new_width - 2 * mBorderThickness;}
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index c42ae040d6..202ed04fbc 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -3905,7 +3905,7 @@ BOOL LLContextMenu::appendContextSubMenu(LLContextMenu *menu)
item = LLUICtrlFactory::create<LLContextMenuBranch>(p);
LLMenuGL::sMenuContainer->addChild(item->getBranch());
- item->setFont( LLFontGL::getFontSansSerifSmall() );
+ item->setFont( LLFontGL::getFontSansSerif() );
return append( item );
}
diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp
index fe4fbe7510..629964c322 100644
--- a/indra/llui/llnotificationslistener.cpp
+++ b/indra/llui/llnotificationslistener.cpp
@@ -10,10 +10,10 @@
*/
#include "linden_common.h"
-
#include "llnotificationslistener.h"
-
#include "llnotifications.h"
+#include "llsd.h"
+#include "llui.h"
LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) :
LLEventAPI("LLNotifications",
@@ -24,6 +24,47 @@ LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications
"Add a notification with specified [\"name\"], [\"substitutions\"] and [\"payload\"].\n"
"If optional [\"reply\"] specified, arrange to send user response on that LLEventPump.",
&LLNotificationsListener::requestAdd);
+ add("listChannels",
+ "Post to [\"reply\"] a map of info on existing channels",
+ &LLNotificationsListener::listChannels,
+ LLSD().with("reply", LLSD()));
+ add("listChannelNotifications",
+ "Post to [\"reply\"] an array of info on notifications in channel [\"channel\"]",
+ &LLNotificationsListener::listChannelNotifications,
+ LLSD().with("reply", LLSD()).with("channel", LLSD()));
+ add("respond",
+ "Respond to notification [\"uuid\"] with data in [\"response\"]",
+ &LLNotificationsListener::respond,
+ LLSD().with("uuid", LLSD()));
+ add("cancel",
+ "Cancel notification [\"uuid\"]",
+ &LLNotificationsListener::cancel,
+ LLSD().with("uuid", LLSD()));
+ add("ignore",
+ "Ignore future notification [\"name\"]\n"
+ "(from <notification name= > in notifications.xml)\n"
+ "according to boolean [\"ignore\"].\n"
+ "If [\"name\"] is omitted or undefined, [un]ignore all future notifications.\n"
+ "Note that ignored notifications are not forwarded unless intercepted before\n"
+ "the \"Ignore\" channel.",
+ &LLNotificationsListener::ignore);
+ add("forward",
+ "Forward to [\"pump\"] future notifications on channel [\"channel\"]\n"
+ "according to boolean [\"forward\"]. When enabled, only types matching\n"
+ "[\"types\"] are forwarded, as follows:\n"
+ "omitted or undefined: forward all notifications\n"
+ "string: forward only the specific named [sig]type\n"
+ "array of string: forward any notification matching any named [sig]type.\n"
+ "When boolean [\"respond\"] is true, we auto-respond to each forwarded\n"
+ "notification.",
+ &LLNotificationsListener::forward,
+ LLSD().with("channel", LLSD()));
+}
+
+// This is here in the .cpp file so we don't need the definition of class
+// Forwarder in the header file.
+LLNotificationsListener::~LLNotificationsListener()
+{
}
void LLNotificationsListener::requestAdd(const LLSD& event_data) const
@@ -57,3 +98,227 @@ void LLNotificationsListener::NotificationResponder(const std::string& reply_pum
reponse_event["response"] = response;
LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event);
}
+
+void LLNotificationsListener::listChannels(const LLSD& params) const
+{
+ LLReqID reqID(params);
+ LLSD response(reqID.makeResponse());
+ for (LLNotifications::ChannelMap::const_iterator cmi(mNotifications.mChannels.begin()),
+ cmend(mNotifications.mChannels.end());
+ cmi != cmend; ++cmi)
+ {
+ LLSD channelInfo;
+ channelInfo["parent"] = cmi->second->getParentChannelName();
+ response[cmi->first] = channelInfo;
+ }
+ LLEventPumps::instance().obtain(params["reply"]).post(response);
+}
+
+void LLNotificationsListener::listChannelNotifications(const LLSD& params) const
+{
+ LLReqID reqID(params);
+ LLSD response(reqID.makeResponse());
+ LLNotificationChannelPtr channel(mNotifications.getChannel(params["channel"]));
+ if (channel)
+ {
+ LLSD notifications(LLSD::emptyArray());
+ for (LLNotificationChannel::Iterator ni(channel->begin()), nend(channel->end());
+ ni != nend; ++ni)
+ {
+ notifications.append(asLLSD(*ni));
+ }
+ response["notifications"] = notifications;
+ }
+ LLEventPumps::instance().obtain(params["reply"]).post(response);
+}
+
+void LLNotificationsListener::respond(const LLSD& params) const
+{
+ LLNotificationPtr notification(mNotifications.find(params["uuid"]));
+ if (notification)
+ {
+ notification->respond(params["response"]);
+ }
+}
+
+void LLNotificationsListener::cancel(const LLSD& params) const
+{
+ LLNotificationPtr notification(mNotifications.find(params["uuid"]));
+ if (notification)
+ {
+ mNotifications.cancel(notification);
+ }
+}
+
+void LLNotificationsListener::ignore(const LLSD& params) const
+{
+ // Calling a method named "ignore", but omitting its "ignore" Boolean
+ // argument, should by default cause something to be ignored. Explicitly
+ // pass ["ignore"] = false to cancel ignore.
+ bool ignore = true;
+ if (params.has("ignore"))
+ {
+ ignore = params["ignore"].asBoolean();
+ }
+ // This method can be used to affect either a single notification name or
+ // all future notifications. The two use substantially different mechanisms.
+ if (params["name"].isDefined())
+ {
+ // ["name"] was passed: ignore just that notification
+ LLUI::sSettingGroups["ignores"]->setBOOL(params["name"], ignore);
+ }
+ else
+ {
+ // no ["name"]: ignore all future notifications
+ mNotifications.setIgnoreAllNotifications(ignore);
+ }
+}
+
+class LLNotificationsListener::Forwarder: public LLEventTrackable
+{
+ LOG_CLASS(LLNotificationsListener::Forwarder);
+public:
+ Forwarder(LLNotifications& llnotifications, const std::string& channel):
+ mNotifications(llnotifications),
+ mRespond(false)
+ {
+ // Connect to the specified channel on construction. Because
+ // LLEventTrackable is a base, we should automatically disconnect when
+ // destroyed.
+ LLNotificationChannelPtr channelptr(llnotifications.getChannel(channel));
+ if (channelptr)
+ {
+ // Try connecting at the front of the 'changed' signal. That way
+ // we shouldn't get starved by preceding listeners.
+ channelptr->connectAtFrontChanged(boost::bind(&Forwarder::handle, this, _1));
+ }
+ }
+
+ void setPumpName(const std::string& name) { mPumpName = name; }
+ void setTypes(const LLSD& types) { mTypes = types; }
+ void setRespond(bool respond) { mRespond = respond; }
+
+private:
+ bool handle(const LLSD& notification) const;
+ bool matchType(const LLSD& filter, const std::string& type) const;
+
+ LLNotifications& mNotifications;
+ std::string mPumpName;
+ LLSD mTypes;
+ bool mRespond;
+};
+
+void LLNotificationsListener::forward(const LLSD& params)
+{
+ std::string channel(params["channel"]);
+ // First decide whether we're supposed to start forwarding or stop it.
+ // Default to true.
+ bool forward = true;
+ if (params.has("forward"))
+ {
+ forward = params["forward"].asBoolean();
+ }
+ if (! forward)
+ {
+ // This is a request to stop forwarding notifications on the specified
+ // channel. The rest of the params don't matter.
+ // Because mForwarders contains scoped_ptrs, erasing the map entry
+ // DOES delete the heap Forwarder object. Because Forwarder derives
+ // from LLEventTrackable, destroying it disconnects it from the
+ // channel.
+ mForwarders.erase(channel);
+ return;
+ }
+ // From here on, we know we're being asked to start (or modify) forwarding
+ // on the specified channel. Find or create an appropriate Forwarder.
+ ForwarderMap::iterator
+ entry(mForwarders.insert(ForwarderMap::value_type(channel, ForwarderMap::mapped_type())).first);
+ if (! entry->second)
+ {
+ entry->second.reset(new Forwarder(mNotifications, channel));
+ }
+ // Now, whether this Forwarder is brand-new or not, update it with the new
+ // request info.
+ Forwarder& fwd(*entry->second);
+ fwd.setPumpName(params["pump"]);
+ fwd.setTypes(params["types"]);
+ fwd.setRespond(params["respond"]);
+}
+
+bool LLNotificationsListener::Forwarder::handle(const LLSD& notification) const
+{
+ LL_INFOS("LLNotificationsListener") << "handle(" << notification << ")" << LL_ENDL;
+ if (notification["sigtype"].asString() == "delete")
+ {
+ LL_INFOS("LLNotificationsListener") << "ignoring delete" << LL_ENDL;
+ return false;
+ }
+ LLNotificationPtr note(mNotifications.find(notification["id"]));
+ if (! note)
+ {
+ LL_INFOS("LLNotificationsListener") << notification["id"] << " not found" << LL_ENDL;
+ return false;
+ }
+ if (! matchType(mTypes, note->getType()))
+ {
+ LL_INFOS("LLNotificationsListener") << "didn't match types " << mTypes << LL_ENDL;
+ return false;
+ }
+ LL_INFOS("LLNotificationsListener") << "sending via '" << mPumpName << "'" << LL_ENDL;
+ // This is a notification we care about. Forward it through specified
+ // LLEventPump.
+ LLEventPumps::instance().obtain(mPumpName).post(asLLSD(note));
+ // Are we also being asked to auto-respond?
+ if (mRespond)
+ {
+ LL_INFOS("LLNotificationsListener") << "should respond" << LL_ENDL;
+ note->respond(LLSD::emptyMap());
+ // Did that succeed in removing the notification? Only cancel() if
+ // it's still around -- otherwise we get an LL_ERRS crash!
+ note = mNotifications.find(notification["id"]);
+ if (note)
+ {
+ LL_INFOS("LLNotificationsListener") << "respond() didn't clear, canceling" << LL_ENDL;
+ mNotifications.cancel(note);
+ }
+ }
+ return false; // let other listeners get same notification
+}
+
+bool LLNotificationsListener::Forwarder::matchType(const LLSD& filter, const std::string& type) const
+{
+ // Decide whether this notification matches filter:
+ // undefined: forward all notifications
+ if (filter.isUndefined())
+ {
+ return true;
+ }
+ // array of string: forward any notification matching any named type
+ if (filter.isArray())
+ {
+ for (LLSD::array_const_iterator ti(filter.beginArray()), tend(filter.endArray());
+ ti != tend; ++ti)
+ {
+ if (ti->asString() == type)
+ {
+ return true;
+ }
+ }
+ // Didn't match any entry in the array
+ return false;
+ }
+ // string: forward only the specific named type
+ return (filter.asString() == type);
+}
+
+LLSD LLNotificationsListener::asLLSD(LLNotificationPtr note)
+{
+ LLSD notificationInfo(note->asLLSD());
+ // For some reason the following aren't included in asLLSD().
+ notificationInfo["summary"] = note->summarize();
+ notificationInfo["id"] = note->id();
+ notificationInfo["type"] = note->getType();
+ notificationInfo["message"] = note->getMessage();
+ notificationInfo["label"] = note->getLabel();
+ return notificationInfo;
+}
diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h
index 9b405d7b4b..de208b57f0 100644
--- a/indra/llui/llnotificationslistener.h
+++ b/indra/llui/llnotificationslistener.h
@@ -13,6 +13,10 @@
#define LL_LLNOTIFICATIONSLISTENER_H
#include "lleventapi.h"
+#include "llnotificationptr.h"
+#include <boost/shared_ptr.hpp>
+#include <map>
+#include <string>
class LLNotifications;
class LLSD;
@@ -21,13 +25,27 @@ class LLNotificationsListener : public LLEventAPI
{
public:
LLNotificationsListener(LLNotifications & notifications);
+ ~LLNotificationsListener();
+private:
void requestAdd(LLSD const & event_data) const;
-private:
void NotificationResponder(const std::string& replypump,
const LLSD& notification,
const LLSD& response) const;
+
+ void listChannels(const LLSD& params) const;
+ void listChannelNotifications(const LLSD& params) const;
+ void respond(const LLSD& params) const;
+ void cancel(const LLSD& params) const;
+ void ignore(const LLSD& params) const;
+ void forward(const LLSD& params);
+
+ static LLSD asLLSD(LLNotificationPtr);
+
+ class Forwarder;
+ typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap;
+ ForwarderMap mForwarders;
LLNotifications & mNotifications;
};
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index 7350457274..983f0a2d49 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -80,7 +80,7 @@ std::string LLUrlEntryBase::escapeUrl(const std::string &url) const
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789"
- "-._~!$?&()*+,@:;=/%";
+ "-._~!$?&()*+,@:;=/%#";
std::sort(no_escape_chars.begin(), no_escape_chars.end());
initialized = true;
@@ -201,7 +201,7 @@ std::string LLUrlEntryHTTPLabel::getUrl(const std::string &string)
//
LLUrlEntryHTTPNoProtocol::LLUrlEntryHTTPNoProtocol()
{
- mPattern = boost::regex("(\\bwww\\.\\S+\\.\\S+|\\S+.com\\S*|\\S+.net\\S*|\\S+.edu\\S*|\\S+.org\\S*)",
+ mPattern = boost::regex("(\\bwww\\.\\S+\\.\\S+|\\b[^ \t\n\r\f\v:/]+.com\\S*|\\b[^ \t\n\r\f\v:/]+.net\\S*|\\b[^ \t\n\r\f\v:/]+.edu\\S*|\\b[^ \t\n\r\f\v:/]+.org\\S*)",
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_http.xml";
mTooltip = LLTrans::getString("TooltipHttpUrl");
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index afcff0d409..ad5c0911f8 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -223,3 +223,23 @@ bool LLUrlRegistry::hasUrl(const LLWString &text)
LLUrlMatch match;
return findUrl(text, match);
}
+
+bool LLUrlRegistry::isUrl(const std::string &text)
+{
+ LLUrlMatch match;
+ if (findUrl(text, match))
+ {
+ return (match.getStart() == 0 && match.getEnd() >= text.size()-1);
+ }
+ return false;
+}
+
+bool LLUrlRegistry::isUrl(const LLWString &text)
+{
+ LLUrlMatch match;
+ if (findUrl(text, match))
+ {
+ return (match.getStart() == 0 && match.getEnd() >= text.size()-1);
+ }
+ return false;
+}
diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h
index d7800d8cfc..399ee0a988 100644
--- a/indra/llui/llurlregistry.h
+++ b/indra/llui/llurlregistry.h
@@ -85,6 +85,10 @@ public:
bool hasUrl(const std::string &text);
bool hasUrl(const LLWString &text);
+ // return true if the given string is a URL that findUrl would match
+ bool isUrl(const std::string &text);
+ bool isUrl(const LLWString &text);
+
private:
LLUrlRegistry();
friend class LLSingleton<LLUrlRegistry>;
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h b/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h
index 2244ccc146..799808aa8b 100644
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamertriviallogging.h
@@ -37,10 +37,16 @@
#include <cstdio>
+extern "C" {
+#include <sys/types.h>
+#include <unistd.h>
+}
+
/////////////////////////////////////////////////////////////////////////
// Debug/Info/Warning macros.
#define MSGMODULEFOO "(media plugin)"
#define STDERRMSG(...) do{\
+ fprintf(stderr, " pid:%d: ", (int)getpid());\
fprintf(stderr, MSGMODULEFOO " %s:%d: ", __FUNCTION__, __LINE__);\
fprintf(stderr, __VA_ARGS__);\
fputc('\n',stderr);\
diff --git a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
index 5bb0ef5a99..109e20f179 100644
--- a/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
+++ b/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
@@ -108,11 +108,10 @@ gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf)
slvideo = GST_SLVIDEO(bsink);
-#if 0
- fprintf(stderr, "\n\ntransferring a frame of %dx%d <- %p (%d)\n\n",
- slvideo->width, slvideo->height, GST_BUFFER_DATA(buf),
- slvideo->format);
-#endif
+ DEBUGMSG("\n\ntransferring a frame of %dx%d <- %p (%d)\n\n",
+ slvideo->width, slvideo->height, GST_BUFFER_DATA(buf),
+ slvideo->format);
+
if (GST_BUFFER_DATA(buf))
{
// copy frame and frame info into neutral territory
@@ -528,7 +527,7 @@ void gst_slvideo_init_class (void)
"http://www.secondlife.com/");
#undef PACKAGE
ll_gst_plugin_register_static (&gst_plugin_desc);
- DEBUGMSG(stderr, "\n\n\nCLASS INIT\n\n\n");
+ DEBUGMSG("\n\n\nCLASS INIT\n\n\n");
}
#endif // LL_GSTREAMER010_ENABLED
diff --git a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
index d21ff26f83..8e850ed7ff 100644
--- a/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
+++ b/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
@@ -115,13 +115,16 @@ private:
int mDepth;
- // media natural size
+ // media NATURAL size
int mNaturalWidth;
int mNaturalHeight;
- int mNaturalRowbytes;
- // previous media natural size so we can detect changes
- int mPreviousNaturalWidth;
- int mPreviousNaturalHeight;
+ // media current size
+ int mCurrentWidth;
+ int mCurrentHeight;
+ int mCurrentRowbytes;
+ // previous media size so we can detect changes
+ int mPreviousWidth;
+ int mPreviousHeight;
// desired render size from host
int mWidth;
int mHeight;
@@ -149,7 +152,7 @@ MediaPluginGStreamer010::MediaPluginGStreamer010(
void *host_user_data ) :
MediaPluginBase(host_send_func, host_user_data),
mBusWatchID ( 0 ),
- mNaturalRowbytes ( 4 ),
+ mCurrentRowbytes ( 4 ),
mTextureFormatPrimary ( GL_RGBA ),
mTextureFormatType ( GL_UNSIGNED_INT_8_8_8_8_REV ),
mSeekWanted(false),
@@ -195,6 +198,7 @@ MediaPluginGStreamer010::processGSTEvents(GstBus *bus,
}
else
{
+ // TODO: grok 'duration' message type
DEBUGMSG("Got GST message type: %s",
LLGST_MESSAGE_TYPE_NAME (message));
}
@@ -429,8 +433,8 @@ MediaPluginGStreamer010::update(int milliseconds)
{
DEBUGMSG("NEW FRAME READY");
- if (mVideoSink->retained_frame_width != mNaturalWidth ||
- mVideoSink->retained_frame_height != mNaturalHeight)
+ if (mVideoSink->retained_frame_width != mCurrentWidth ||
+ mVideoSink->retained_frame_height != mCurrentHeight)
// *TODO: also check for change in format
{
// just resize container, don't consume frame
@@ -457,39 +461,39 @@ MediaPluginGStreamer010::update(int milliseconds)
GST_OBJECT_UNLOCK(mVideoSink);
- mNaturalRowbytes = neww * newd;
+ mCurrentRowbytes = neww * newd;
DEBUGMSG("video container resized to %dx%d",
neww, newh);
mDepth = newd;
- mNaturalWidth = neww;
- mNaturalHeight = newh;
+ mCurrentWidth = neww;
+ mCurrentHeight = newh;
sizeChanged();
return true;
}
if (mPixels &&
- mNaturalHeight <= mHeight &&
- mNaturalWidth <= mWidth &&
+ mCurrentHeight <= mHeight &&
+ mCurrentWidth <= mWidth &&
!mTextureSegmentName.empty())
{
// we're gonna totally consume this frame - reset 'ready' flag
mVideoSink->retained_frame_ready = FALSE;
int destination_rowbytes = mWidth * mDepth;
- for (int row=0; row<mNaturalHeight; ++row)
+ for (int row=0; row<mCurrentHeight; ++row)
{
memcpy(&mPixels
[destination_rowbytes * row],
&mVideoSink->retained_frame_data
- [mNaturalRowbytes * row],
- mNaturalRowbytes);
+ [mCurrentRowbytes * row],
+ mCurrentRowbytes);
}
GST_OBJECT_UNLOCK(mVideoSink);
DEBUGMSG("NEW FRAME REALLY TRULY CONSUMED, TELLING HOST");
- setDirty(0,0,mNaturalWidth,mNaturalHeight);
+ setDirty(0,0,mCurrentWidth,mCurrentHeight);
}
else
{
@@ -841,12 +845,21 @@ MediaPluginGStreamer010::sizeChanged()
{
// the shared writing space has possibly changed size/location/whatever
- // Check to see whether the movie's natural size has updated
- if (mNaturalWidth != mPreviousNaturalWidth ||
- mNaturalHeight != mPreviousNaturalHeight)
+ // Check to see whether the movie's NATURAL size has been set yet
+ if (1 == mNaturalWidth &&
+ 1 == mNaturalHeight)
{
- mPreviousNaturalWidth = mNaturalWidth;
- mPreviousNaturalHeight = mNaturalHeight;
+ mNaturalWidth = mCurrentWidth;
+ mNaturalHeight = mCurrentHeight;
+ DEBUGMSG("Media NATURAL size better detected as %dx%d",
+ mNaturalWidth, mNaturalHeight);
+ }
+
+ if (mCurrentWidth != mPreviousWidth ||
+ mCurrentHeight != mPreviousHeight) // if the size has changed then the shm has changed and the app needs telling
+ {
+ mPreviousWidth = mCurrentWidth;
+ mPreviousHeight = mCurrentHeight;
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_request");
message.setValue("name", mTextureSegmentName);
@@ -941,10 +954,12 @@ void MediaPluginGStreamer010::receiveMessage(const char *message_string)
// lame to have to decide this now, it depends on the movie. Oh well.
mDepth = 4;
+ mCurrentWidth = 1;
+ mCurrentHeight = 1;
+ mPreviousWidth = 1;
+ mPreviousHeight = 1;
mNaturalWidth = 1;
mNaturalHeight = 1;
- mPreviousNaturalWidth = 1;
- mPreviousNaturalHeight = 1;
mWidth = 1;
mHeight = 1;
mTextureWidth = 1;
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 8953682fae..f3d399c616 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -200,6 +200,7 @@ set(viewer_SOURCE_FILES
llfloaterregioninfo.cpp
llfloaterreporter.cpp
llfloaterscriptdebug.cpp
+ llfloaterscriptlimits.cpp
llfloatersearch.cpp
llfloatersellland.cpp
llfloatersettingsdebug.cpp
@@ -696,7 +697,7 @@ set(viewer_HEADER_FILES
llfloatermediasettings.h
llfloatermemleak.h
llfloaternamedesc.h
- llfloaternearbymedia.h
+ llfloaternearbymedia.h
llfloaternotificationsconsole.h
llfloateropenobject.h
llfloaterparcel.h
@@ -709,6 +710,7 @@ set(viewer_HEADER_FILES
llfloaterregioninfo.h
llfloaterreporter.h
llfloaterscriptdebug.h
+ llfloaterscriptlimits.h
llfloatersearch.h
llfloatersellland.h
llfloatersettingsdebug.h
@@ -1444,6 +1446,10 @@ if (WINDOWS)
${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qmng4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qsvg4.dll
${ARCH_PREBUILT_DIRS_RELEASE}/imageformats/qtiff4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qcncodecs4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qjpcodecs4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qkrcodecs4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qtwcodecs4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/libeay32.dll
${ARCH_PREBUILT_DIRS_DEBUG}/qtcored4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/qtguid4.dll
@@ -1458,6 +1464,10 @@ if (WINDOWS)
${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qmngd4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qsvgd4.dll
${ARCH_PREBUILT_DIRS_DEBUG}/imageformats/qtiffd4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qcncodecsd4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qjpcodecsd4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qkrcodecsd4.dll
+ ${ARCH_PREBUILT_DIRS_RELEASE}/codecs/qtwcodecsd4.dll
SLPlugin
media_plugin_quicktime
media_plugin_webkit
diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
index 28908a311d..0fad5b4b50 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
@@ -10,7 +10,6 @@
uniform sampler2DRect depthMap;
uniform sampler2DRect normalMap;
uniform sampler2DRect lightMap;
-uniform sampler2DRect edgeMap;
uniform float dist_factor;
uniform float blur_size;
@@ -46,53 +45,36 @@ void main()
dlt /= max(-pos.z*dist_factor, 1.0);
- vec2 defined_weight = kern[0].xy; // special case the kern[0] (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
+ vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
vec4 col = defined_weight.xyxx * ccol;
-
- float center_e = 1.0 - (texture2DRect(edgeMap, vary_fragcoord.xy).a+
- texture2DRect(edgeMap, vary_fragcoord.xy+dlt*0.333).a+
- texture2DRect(edgeMap, vary_fragcoord.xy-dlt*0.333).a);
- float e = center_e;
for (int i = 1; i < 4; i++)
{
vec2 tc = vary_fragcoord.xy + kern[i].z*dlt;
-
- e = max(e, 0.0);
-
- vec2 wght = kern[i].xy*e;
-
- col += texture2DRect(lightMap, tc)*wght.xyxx;
- defined_weight += wght;
-
- e *= e;
- e -= texture2DRect(edgeMap, tc.xy).a+
- texture2DRect(edgeMap, tc.xy+dlt*0.333).a+
- texture2DRect(edgeMap, tc.xy-dlt*0.333).a;
+ vec3 samppos = getPosition(tc).xyz;
+ float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
+ if (d*d <= 0.003)
+ {
+ col += texture2DRect(lightMap, tc)*kern[i].xyxx;
+ defined_weight += kern[i].xy;
+ }
}
-
- e = center_e;
for (int i = 1; i < 4; i++)
{
vec2 tc = vary_fragcoord.xy - kern[i].z*dlt;
-
- e = max(e, 0.0);
-
- vec2 wght = kern[i].xy*e;
-
- col += texture2DRect(lightMap, tc)*wght.xyxx;
- defined_weight += wght;
-
- e *= e;
- e -= texture2DRect(edgeMap, tc.xy).a+
- texture2DRect(edgeMap, tc.xy+dlt*0.333).a+
- texture2DRect(edgeMap, tc.xy-dlt*0.333).a;
+ vec3 samppos = getPosition(tc).xyz;
+ float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
+ if (d*d <= 0.003)
+ {
+ col += texture2DRect(lightMap, tc)*kern[i].xyxx;
+ defined_weight += kern[i].xy;
+ }
}
+
col /= defined_weight.xyxx;
gl_FragColor = col;
-
- //gl_FragColor = ccol;
}
+
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index d20c23df80..4029bf95a0 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -1,4 +1,4 @@
-version 20
+version 21
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -28,6 +28,7 @@ RenderAvatarCloth 1 1
RenderAvatarLODFactor 1 1.0
RenderAvatarVP 1 1
RenderCubeMap 1 1
+RenderDelayVBUpdate 1 0
RenderFarClip 1 256
RenderFlexTimeFactor 1 1.0
RenderFogRatio 1 4.0
diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt
index 57d712ede7..61a8e51c50 100644
--- a/indra/newview/featuretable_linux.txt
+++ b/indra/newview/featuretable_linux.txt
@@ -1,4 +1,4 @@
-version 20
+version 21
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -28,6 +28,7 @@ RenderAvatarCloth 1 1
RenderAvatarLODFactor 1 1.0
RenderAvatarVP 1 1
RenderCubeMap 1 1
+RenderDelayVBUpdate 1 0
RenderFarClip 1 256
RenderFlexTimeFactor 1 1.0
RenderFogRatio 1 4.0
diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt
index 15974c0691..12d47a904c 100644
--- a/indra/newview/featuretable_mac.txt
+++ b/indra/newview/featuretable_mac.txt
@@ -1,4 +1,4 @@
-version 20
+version 21
// NOTE: This is mostly identical to featuretable_mac.txt with a few differences
// Should be combined into one table
@@ -28,6 +28,7 @@ RenderAvatarCloth 0 0
RenderAvatarLODFactor 1 1.0
RenderAvatarVP 1 0
RenderCubeMap 1 1
+RenderDelayVBUpdate 1 0
RenderFarClip 1 256
RenderFlexTimeFactor 1 1.0
RenderFogRatio 1 4.0
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 454e547155..79ba3fb51d 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -871,24 +871,31 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
if (mInitialWearablesUpdateReceived)
return;
mInitialWearablesUpdateReceived = true;
+
+ // If this is the very first time the user has logged into viewer2+ (from a legacy viewer, or new account)
+ // then auto-populate outfits from the library into the My Outfits folder.
+ if (LLInventoryModel::getIsFirstTimeInViewer2())
+ {
+ gAgentWearables.populateMyOutfitsFolder();
+ }
LLUUID agent_id;
gMessageSystem->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
- const BOOL is_first_time_in_viewer2_0 = (gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, FALSE) == LLUUID::null);
-
-
LLVOAvatar* avatar = gAgent.getAvatarObject();
if (avatar && (agent_id == avatar->getID()))
{
gMessageSystem->getU32Fast(_PREHASH_AgentData, _PREHASH_SerialNum, gAgentQueryManager.mUpdateSerialNum);
+ const S32 NUM_BODY_PARTS = 4;
S32 num_wearables = gMessageSystem->getNumberOfBlocksFast(_PREHASH_WearableData);
- if (num_wearables < 4)
+ if (num_wearables < NUM_BODY_PARTS)
{
// Transitional state. Avatars should always have at least their body parts (hair, eyes, shape and skin).
- // The fact that they don't have any here (only a dummy is sent) implies that this account existed
- // before we had wearables, or that the database has gotten messed up.
+ // The fact that they don't have any here (only a dummy is sent) implies that either:
+ // 1. This account existed before we had wearables
+ // 2. The database has gotten messed up
+ // 3. This is the account's first login (i.e. the wearables haven't been generated yet).
return;
}
@@ -957,8 +964,6 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
gInventory.addObserver(outfit);
}
- if (is_first_time_in_viewer2_0)
- gAgentWearables.populateMyOutfitsFolder();
}
}
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 3bd4f898c8..5317cf2cd0 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -33,6 +33,7 @@
#include "llviewerprecompiledheaders.h"
#include "llavatarlist.h"
+#include "llagentdata.h" // for comparator
// newview
#include "llcallingcard.h" // for LLAvatarTracker
@@ -321,7 +322,6 @@ void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is
item->setAvatarId(id, mIgnoreOnlineStatus);
item->setOnline(mIgnoreOnlineStatus ? true : is_online);
item->showLastInteractionTime(mShowLastInteractionTime);
- item->setContextMenu(mContextMenu);
item->childSetVisible("info_btn", false);
item->setAvatarIconVisible(mShowIcons);
@@ -420,3 +420,17 @@ bool LLAvatarItemNameComparator::doCompare(const LLAvatarListItem* avatar_item1,
return name1 < name2;
}
+bool LLAvatarItemAgentOnTopComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const
+{
+ //keep agent on top, if first is agent,
+ //then we need to return true to elevate this id, otherwise false.
+ if(avatar_item1->getAvatarId() == gAgentID)
+ {
+ return true;
+ }
+ else if (avatar_item2->getAvatarId() == gAgentID)
+ {
+ return false;
+ }
+ return LLAvatarItemNameComparator::doCompare(avatar_item1,avatar_item2);
+}
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index 9058fec540..e913be0f62 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -155,4 +155,16 @@ protected:
virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const;
};
+class LLAvatarItemAgentOnTopComparator : public LLAvatarItemNameComparator
+{
+ LOG_CLASS(LLAvatarItemAgentOnTopComparator);
+
+public:
+ LLAvatarItemAgentOnTopComparator() {};
+ virtual ~LLAvatarItemAgentOnTopComparator() {};
+
+protected:
+ virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const;
+};
+
#endif // LL_LLAVATARLIST_H
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index 072eebdf2d..c8544bc3fb 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -43,6 +43,12 @@
#include "lltextutil.h"
#include "llbutton.h"
+bool LLAvatarListItem::sStaticInitialized = false;
+S32 LLAvatarListItem::sIconWidth = 0;
+S32 LLAvatarListItem::sInfoBtnWidth = 0;
+S32 LLAvatarListItem::sProfileBtnWidth = 0;
+S32 LLAvatarListItem::sSpeakingIndicatorWidth = 0;
+
LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/)
: LLPanel(),
mAvatarIcon(NULL),
@@ -51,7 +57,6 @@ LLAvatarListItem::LLAvatarListItem(bool not_from_ui_factory/* = true*/)
mSpeakingIndicator(NULL),
mInfoBtn(NULL),
mProfileBtn(NULL),
- mContextMenu(NULL),
mOnlineStatus(E_UNKNOWN),
mShowInfoBtn(true),
mShowProfileBtn(true)
@@ -88,10 +93,15 @@ BOOL LLAvatarListItem::postBuild()
// Remember avatar icon width including its padding from the name text box,
// so that we can hide and show the icon again later.
- mIconWidth = mAvatarName->getRect().mLeft - mAvatarIcon->getRect().mLeft;
- mInfoBtnWidth = mInfoBtn->getRect().mRight - mSpeakingIndicator->getRect().mRight;
- mProfileBtnWidth = mProfileBtn->getRect().mRight - mInfoBtn->getRect().mRight;
- mSpeakingIndicatorWidth = mSpeakingIndicator->getRect().mRight - mAvatarName->getRect().mRight;
+ if (!sStaticInitialized)
+ {
+ sIconWidth = mAvatarName->getRect().mLeft - mAvatarIcon->getRect().mLeft;
+ sInfoBtnWidth = mInfoBtn->getRect().mRight - mSpeakingIndicator->getRect().mRight;
+ sProfileBtnWidth = mProfileBtn->getRect().mRight - mInfoBtn->getRect().mRight;
+ sSpeakingIndicatorWidth = mSpeakingIndicator->getRect().mRight - mAvatarName->getRect().mRight;
+
+ sStaticInitialized = true;
+ }
/*
if(!p.buttons.profile)
@@ -173,6 +183,28 @@ void LLAvatarListItem::setHighlight(const std::string& highlight)
setNameInternal(mAvatarName->getText(), mHighlihtSubstring = highlight);
}
+void LLAvatarListItem::setStyle(const LLStyle::Params& new_style)
+{
+// LLTextUtil::textboxSetHighlightedVal(mAvatarName, mAvatarNameStyle = new_style);
+
+ // Active group should be bold.
+ LLFontDescriptor new_desc(mAvatarName->getDefaultFont()->getFontDesc());
+
+ new_desc.setStyle(new_style.font()->getFontDesc().getStyle());
+ // *NOTE dzaporozhan
+ // On Windows LLFontGL::NORMAL will not remove LLFontGL::BOLD if font
+ // is predefined as bold (SansSerifSmallBold, for example)
+// new_desc.setStyle(active ? LLFontGL::BOLD : LLFontGL::NORMAL);
+ LLFontGL* new_font = LLFontGL::getFont(new_desc);
+
+//
+ mAvatarNameStyle.font = new_font;
+
+ // *NOTE: You cannot set the style on a text box anymore, you must
+ // rebuild the text. This will cause problems if the text contains
+ // hyperlinks, as their styles will be wrong.
+ mAvatarName->setText(mAvatarName->getText(), mAvatarNameStyle/* = new_style*/);
+}
void LLAvatarListItem::setAvatarId(const LLUUID& id, bool ignore_status_changes)
{
if (mAvatarId.notNull())
@@ -214,7 +246,7 @@ void LLAvatarListItem::setShowInfoBtn(bool show)
if(mShowInfoBtn == show)
return;
mShowInfoBtn = show;
- S32 width_delta = show ? - mInfoBtnWidth : mInfoBtnWidth;
+ S32 width_delta = show ? - sInfoBtnWidth : sInfoBtnWidth;
//Translating speaking indicator
mSpeakingIndicator->translate(width_delta, 0);
@@ -228,7 +260,7 @@ void LLAvatarListItem::setShowProfileBtn(bool show)
if(mShowProfileBtn == show)
return;
mShowProfileBtn = show;
- S32 width_delta = show ? - mProfileBtnWidth : mProfileBtnWidth;
+ S32 width_delta = show ? - sProfileBtnWidth : sProfileBtnWidth;
//Translating speaking indicator
mSpeakingIndicator->translate(width_delta, 0);
@@ -242,7 +274,7 @@ void LLAvatarListItem::setSpeakingIndicatorVisible(bool visible)
if (mSpeakingIndicator->getVisible() == (BOOL)visible)
return;
mSpeakingIndicator->setVisible(visible);
- S32 width_delta = visible ? - mSpeakingIndicatorWidth : mSpeakingIndicatorWidth;
+ S32 width_delta = visible ? - sSpeakingIndicatorWidth : sSpeakingIndicatorWidth;
//Reshaping avatar name
mAvatarName->reshape(mAvatarName->getRect().getWidth() + width_delta, mAvatarName->getRect().getHeight());
@@ -259,7 +291,7 @@ void LLAvatarListItem::setAvatarIconVisible(bool visible)
// Move the avatar name horizontally by icon size + its distance from the avatar name.
LLRect name_rect = mAvatarName->getRect();
- name_rect.mLeft += visible ? mIconWidth : -mIconWidth;
+ name_rect.mLeft += visible ? sIconWidth : -sIconWidth;
mAvatarName->setRect(name_rect);
}
@@ -327,10 +359,10 @@ void LLAvatarListItem::onNameCache(const std::string& first_name, const std::str
void LLAvatarListItem::reshapeAvatarName()
{
S32 width_delta = 0;
- width_delta += mShowProfileBtn ? mProfileBtnWidth : 0;
- width_delta += mSpeakingIndicator->getVisible() ? mSpeakingIndicatorWidth : 0;
- width_delta += mAvatarIcon->getVisible() ? mIconWidth : 0;
- width_delta += mShowInfoBtn ? mInfoBtnWidth : 0;
+ width_delta += mShowProfileBtn ? sProfileBtnWidth : 0;
+ width_delta += mSpeakingIndicator->getVisible() ? sSpeakingIndicatorWidth : 0;
+ width_delta += mAvatarIcon->getVisible() ? sIconWidth : 0;
+ width_delta += mShowInfoBtn ? sInfoBtnWidth : 0;
width_delta += mLastInteractionTime->getVisible() ? mLastInteractionTime->getRect().getWidth() : 0;
S32 height = mAvatarName->getRect().getHeight();
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index aa1b7593f5..0e058f75db 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -73,6 +73,7 @@ public:
void setOnline(bool online);
void setName(const std::string& name);
void setHighlight(const std::string& highlight);
+ void setStyle(const LLStyle::Params& new_style);
void setAvatarId(const LLUUID& id, bool ignore_status_changes = false);
void setLastInteractionTime(U32 secs_since);
//Show/hide profile/info btn, translating speaker indicator and avatar name coordinates accordingly
@@ -91,8 +92,6 @@ public:
void showInfoBtn(bool show_info_btn) {mInfoBtn->setVisible(show_info_btn); }
void showLastInteractionTime(bool show);
- void setContextMenu(ContextMenu* menu) { mContextMenu = menu; }
-
/**
* This method was added to fix EXT-2364 (Items in group/ad-hoc IM participant list (avatar names) should be reshaped when adding/removing the "(Moderator)" label)
* But this is a *HACK. The real reason of it was in incorrect logic while hiding profile/info/speaker buttons
@@ -126,7 +125,6 @@ private:
LLButton* mInfoBtn;
LLButton* mProfileBtn;
- ContextMenu* mContextMenu;
LLUUID mAvatarId;
std::string mHighlihtSubstring; // substring to highlight
@@ -135,10 +133,12 @@ private:
//Speaker indicator and avatar name coords are translated accordingly
bool mShowInfoBtn;
bool mShowProfileBtn;
- S32 mIconWidth; // icon width + padding
- S32 mInfoBtnWidth; //info btn width + padding
- S32 mProfileBtnWidth; //profile btn width + padding
- S32 mSpeakingIndicatorWidth; //speaking indicator width + padding
+
+ static bool sStaticInitialized; // this variable is introduced to improve code readability
+ static S32 sIconWidth; // icon width + padding
+ static S32 sInfoBtnWidth; //info btn width + padding
+ static S32 sProfileBtnWidth; //profile btn width + padding
+ static S32 sSpeakingIndicatorWidth; //speaking indicator width + padding
};
#endif //LL_LLAVATARLISTITEM_H
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 6f2e666cc7..4d5d416907 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -67,6 +67,10 @@ LLBottomTray::LLBottomTray(const LLSD&)
, mGesturePanel(NULL)
, mCamButton(NULL)
{
+ // Firstly add ourself to IMSession observers, so we catch session events
+ // before chiclets do that.
+ LLIMMgr::getInstance()->addSessionObserver(this);
+
mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL);
LLUICtrlFactory::getInstance()->buildPanel(this,"panel_bottomtray.xml");
@@ -76,10 +80,6 @@ LLBottomTray::LLBottomTray(const LLSD&)
mChicletPanel->setChicletClickedCallback(boost::bind(&LLBottomTray::onChicletClick,this,_1));
LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraPresets, _2));
- LLIMMgr::getInstance()->addSessionObserver(this);
-
- //managing chiclets for voice calls
- LLIMModel::getInstance()->addNewMsgCallback(boost::bind(&LLBottomTray::onNewIM, this, _1));
//this is to fix a crash that occurs because LLBottomTray is a singleton
//and thus is deleted at the end of the viewers lifetime, but to be cleanly
@@ -150,9 +150,6 @@ void LLBottomTray::sessionAdded(const LLUUID& session_id, const std::string& nam
if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return;
- // For im sessions started as voice call chiclet gets created on the first incoming message
- if (gIMMgr->isVoiceCall(session_id)) return;
-
LLIMChiclet* chiclet = createIMChiclet(session_id);
if(chiclet)
{
@@ -194,27 +191,6 @@ void LLBottomTray::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID&
}
}
-void LLBottomTray::onNewIM(const LLSD& data)
-{
- LLUUID from_id = data["from_id"];
- if (from_id.isNull() || gAgentID == from_id) return;
-
- LLUUID session_id = data["session_id"];
- if (session_id.isNull()) return;
-
- if (!gIMMgr->isVoiceCall(session_id)) return;
-
- if (getChicletPanel()->findChiclet<LLChiclet>(session_id)) return;
-
- //first real message, time to create chiclet
- LLIMChiclet* chiclet = createIMChiclet(session_id);
- if(chiclet)
- {
- chiclet->setIMSessionName(LLIMModel::getInstance()->getName(session_id));
- chiclet->setOtherParticipantId(LLIMModel::getInstance()->getOtherParticipantID(session_id));
- }
-}
-
S32 LLBottomTray::getTotalUnreadIMCount()
{
return getChicletPanel()->getTotalUnreadIMCount();
diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h
index 5cd3f15746..9be0e5810f 100644
--- a/indra/newview/llbottomtray.h
+++ b/indra/newview/llbottomtray.h
@@ -75,8 +75,6 @@ public:
virtual void sessionRemoved(const LLUUID& session_id);
void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);
- void onNewIM(const LLSD& data);
-
S32 getTotalUnreadIMCount();
virtual void reshape(S32 width, S32 height, BOOL called_from_parent);
diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp
index 1f23840109..fe4f0c5525 100644
--- a/indra/newview/llcallfloater.cpp
+++ b/indra/newview/llcallfloater.cpp
@@ -42,6 +42,8 @@
#include "llagentdata.h" // for gAgentID
#include "llavatarlist.h"
#include "llbottomtray.h"
+#include "llimfloater.h"
+#include "llfloaterreg.h"
#include "llparticipantlist.h"
#include "llspeakers.h"
#include "lltransientfloatermgr.h"
@@ -87,6 +89,7 @@ LLCallFloater::LLCallFloater(const LLSD& key)
, mAgentPanel(NULL)
, mSpeakingIndicator(NULL)
, mIsModeratorMutedVoice(false)
+, mInitParticipantsVoiceState(false)
{
mFactoryMap["non_avatar_caller"] = LLCallbackMap(create_non_avatar_caller, NULL);
LLVoiceClient::getInstance()->addObserver(this);
@@ -95,10 +98,11 @@ LLCallFloater::LLCallFloater(const LLSD& key)
LLCallFloater::~LLCallFloater()
{
- mChannelChangedConnection.disconnect();
delete mPaticipants;
mPaticipants = NULL;
+ mAvatarListRefreshConnection.disconnect();
+
// Don't use LLVoiceClient::getInstance() here
// singleton MAY have already been destroyed.
if(gVoiceClient)
@@ -113,6 +117,8 @@ BOOL LLCallFloater::postBuild()
{
LLDockableFloater::postBuild();
mAvatarList = getChild<LLAvatarList>("speakers_list");
+ mAvatarListRefreshConnection = mAvatarList->setRefreshCompleteCallback(boost::bind(&LLCallFloater::onAvatarListRefreshed, this));
+
childSetAction("leave_call_btn", boost::bind(&LLCallFloater::leaveCall, this));
mNonAvatarCaller = getChild<LLNonAvatarCaller>("non_avatar_caller");
@@ -128,8 +134,6 @@ BOOL LLCallFloater::postBuild()
// update list for current session
updateSession();
- // subscribe to to be notified Voice Channel is changed
- mChannelChangedConnection = LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::onCurrentChannelChanged, this, _1));
return TRUE;
}
@@ -154,6 +158,10 @@ void LLCallFloater::draw()
setModeratorMutedVoice(is_moderator_muted);
}
+ // Need to resort the participant list if it's in sort by recent speaker order.
+ if (mPaticipants)
+ mPaticipants->updateRecentSpeakersOrder();
+
LLDockableFloater::draw();
}
@@ -162,7 +170,7 @@ void LLCallFloater::onChange()
{
if (NULL == mPaticipants) return;
- mPaticipants->refreshVoiceState();
+ updateParticipantsVoiceState();
}
@@ -244,7 +252,18 @@ void LLCallFloater::updateSession()
childSetVisible("leave_call_btn", !is_local_chat);
refreshPartisipantList();
- updateModeratorState();
+ updateAgentModeratorState();
+
+ //show floater for voice calls
+ if (!is_local_chat)
+ {
+ LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
+ bool show_me = !(im_floater && im_floater->getVisible());
+ if (show_me)
+ {
+ setVisible(true);
+ }
+ }
}
void LLCallFloater::refreshPartisipantList()
@@ -270,18 +289,33 @@ void LLCallFloater::refreshPartisipantList()
if (!non_avatar_caller)
{
- bool do_not_use_context_menu_in_local_chat = LLLocalSpeakerMgr::getInstance() != mSpeakerManager;
- mPaticipants = new LLParticipantList(mSpeakerManager, mAvatarList, do_not_use_context_menu_in_local_chat);
+ mPaticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT);
- if (!do_not_use_context_menu_in_local_chat)
+ if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager)
{
mAvatarList->setNoItemsCommentText(getString("no_one_near"));
}
- mPaticipants->refreshVoiceState();
+
+ // we have to made delayed initialization of voice state of participant list.
+ // it will be performed after first LLAvatarList refreshing in the onAvatarListRefreshed().
+ mInitParticipantsVoiceState = true;
+ }
+}
+
+void LLCallFloater::onAvatarListRefreshed()
+{
+ if (mInitParticipantsVoiceState)
+ {
+ initParticipantsVoiceState();
+ mInitParticipantsVoiceState = false;
+ }
+ else
+ {
+ updateParticipantsVoiceState();
}
}
-void LLCallFloater::onCurrentChannelChanged(const LLUUID& /*session_id*/)
+void LLCallFloater::sOnCurrentChannelChanged(const LLUUID& /*session_id*/)
{
// Don't update participant list if no channel info is available.
// Fix for ticket EXT-3427
@@ -291,9 +325,11 @@ void LLCallFloater::onCurrentChannelChanged(const LLUUID& /*session_id*/)
{
return;
}
+ LLCallFloater* call_floater = LLFloaterReg::getTypedInstance<LLCallFloater>("voice_controls");
+
// Forget speaker manager from the previous session to avoid using it after session was destroyed.
- mSpeakerManager = NULL;
- updateSession();
+ call_floater->mSpeakerManager = NULL;
+ call_floater->updateSession();
}
void LLCallFloater::updateTitle()
@@ -355,7 +391,7 @@ void LLCallFloater::setModeratorMutedVoice(bool moderator_muted)
mSpeakingIndicator->setIsMuted(moderator_muted);
}
-void LLCallFloater::updateModeratorState()
+void LLCallFloater::updateAgentModeratorState()
{
std::string name;
gCacheName->getFullName(gAgentID, name);
@@ -377,4 +413,213 @@ void LLCallFloater::updateModeratorState()
}
mAgentPanel->childSetValue("user_text", name);
}
+
+void get_voice_participants_uuids(std::vector<LLUUID>& speakers_uuids)
+{
+ // Get a list of participants from VoiceClient
+ LLVoiceClient::participantMap *voice_map = gVoiceClient->getParticipantList();
+ if (voice_map)
+ {
+ for (LLVoiceClient::participantMap::const_iterator iter = voice_map->begin();
+ iter != voice_map->end(); ++iter)
+ {
+ LLUUID id = (*iter).second->mAvatarID;
+ speakers_uuids.push_back(id);
+ }
+ }
+}
+
+void LLCallFloater::initParticipantsVoiceState()
+{
+ // Set initial status for each participant in the list.
+ std::vector<LLPanel*> items;
+ mAvatarList->getItems(items);
+ std::vector<LLPanel*>::const_iterator
+ it = items.begin(),
+ it_end = items.end();
+
+
+ std::vector<LLUUID> speakers_uuids;
+ get_voice_participants_uuids(speakers_uuids);
+
+ for(; it != it_end; ++it)
+ {
+ LLAvatarListItem *item = dynamic_cast<LLAvatarListItem*>(*it);
+
+ if (!item) continue;
+
+ LLUUID speaker_id = item->getAvatarId();
+
+ std::vector<LLUUID>::const_iterator speaker_iter = std::find(speakers_uuids.begin(), speakers_uuids.end(), speaker_id);
+
+ // If an avatarID assigned to a panel is found in a speakers list
+ // obtained from VoiceClient we assign the JOINED status to the owner
+ // of this avatarID.
+ if (speaker_iter != speakers_uuids.end())
+ {
+ setState(item, STATE_JOINED);
+ }
+ else
+ {
+ LLPointer<LLSpeaker> speakerp = mSpeakerManager->findSpeaker(speaker_id);
+ // If someone has already left the call before, we create his
+ // avatar row panel with HAS_LEFT status and remove it after
+ // the timeout, otherwise we create a panel with INVITED status
+ if (speakerp.notNull() && speakerp.get()->mHasLeftCurrentCall)
+ {
+ setState(item, STATE_LEFT);
+ }
+ else
+ {
+ setState(item, STATE_INVITED);
+ }
+ }
+ }
+}
+
+void LLCallFloater::updateParticipantsVoiceState()
+{
+ std::vector<LLUUID> speakers_list;
+
+ // Get a list of participants from VoiceClient
+ LLVoiceClient::participantMap *map = gVoiceClient->getParticipantList();
+ if (!map) return;
+
+ for (LLVoiceClient::participantMap::const_iterator iter = map->begin();
+ iter != map->end(); ++iter)
+ {
+ LLUUID id = (*iter).second->mAvatarID;
+// if ( id != gAgent.getID() )
+ {
+ speakers_list.push_back(id);
+/*
+ LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (mAvatarList->getItemByValue(id));
+ if (item)
+ {
+ setState(item, STATE_JOINED);
+ }
+*/
+
+ }
+ }
+
+ // Updating the status for each participant.
+ std::vector<LLPanel*> items;
+ mAvatarList->getItems(items);
+ std::vector<LLPanel*>::const_iterator
+ it = items.begin(),
+ it_end = items.end();
+
+ for(; it != it_end; ++it)
+ {
+ LLAvatarListItem *item = dynamic_cast<LLAvatarListItem*>(*it);
+ if (!item) continue;
+
+ const LLUUID participant_id = item->getAvatarId();
+ bool found = false;
+
+ std::vector<LLUUID>::iterator speakers_iter = std::find(speakers_list.begin(), speakers_list.end(), participant_id);
+
+ lldebugs << "processing speaker: " << item->getAvatarName() << ", " << item->getAvatarId() << llendl;
+
+ // If an avatarID assigned to a panel is found in a speakers list
+ // obtained from VoiceClient we assign the JOINED status to the owner
+ // of this avatarID.
+ if (speakers_iter != speakers_list.end())
+ {
+ setState(item, STATE_JOINED);
+
+ LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(participant_id);
+ if (speaker.isNull())
+ continue;
+ speaker->mHasLeftCurrentCall = FALSE;
+
+ speakers_list.erase(speakers_iter);
+ found = true;
+ }
+
+ // If an avatarID is not found in a speakers list from VoiceClient and
+ // a panel with this ID has a JOINED status this means that this person
+ // HAS LEFT the call.
+ if (!found)
+ {
+ if ((getState(participant_id) == STATE_JOINED))
+ {
+ setState(item, STATE_LEFT);
+
+ LLPointer<LLSpeaker> speaker = mSpeakerManager->findSpeaker(item->getAvatarId());
+ if (speaker.isNull())
+ continue;
+
+ speaker->mHasLeftCurrentCall = TRUE;
+ }
+ else if ((getState(participant_id) != STATE_LEFT))
+ {
+ setState(item, STATE_INVITED);
+ }
+
+/*
+ // If there is already a started timer for the current panel don't do anything.
+ bool no_timer_for_current_panel = true;
+ if (mTimersMap.size() > 0)
+ {
+ timers_map::iterator found_it = mTimersMap.find(participant_id);
+ if (found_it != mTimersMap.end())
+ {
+ no_timer_for_current_panel = false;
+ }
+ }
+
+ if (no_timer_for_current_panel)
+ {
+ // Starting a timer to remove an avatar row panel after timeout
+ // *TODO Make the timeout period adjustable
+ mTimersMap.insert(timer_pair(participant_id, new LLAvatarRowRemoveTimer(this->getHandle(), 10, participant_id)));
+ }
+*/
+ }
+ }
+
+}
+
+void LLCallFloater::setState(LLAvatarListItem* item, ESpeakerState state)
+{
+ setState(item->getAvatarId(), state);
+
+ LLStyle::Params speaker_style;
+ LLFontDescriptor new_desc(speaker_style.font()->getFontDesc());
+
+ switch (state)
+ {
+ case STATE_INVITED:
+// status_str = "INVITED"; // *TODO: localize
+ new_desc.setStyle(LLFontGL::NORMAL);
+ break;
+ case STATE_JOINED:
+// status_str = "JOINED"; // *TODO: localize
+ new_desc.setStyle(LLFontGL::NORMAL);
+ break;
+ case STATE_LEFT:
+ {
+ // status_str = "HAS LEFT CALL"; // *TODO: localize
+ new_desc.setStyle(LLFontGL::ITALIC);
+
+ }
+ break;
+ default:
+ llwarns << "Unrecognized avatar panel state (" << state << ")" << llendl;
+ break;
+ }
+
+ LLFontGL* new_font = LLFontGL::getFont(new_desc);
+ speaker_style.font = new_font;
+ item->setStyle(speaker_style);
+
+// if ()
+ {
+ // found speaker is in voice, mark him as online
+ item->setOnline(STATE_JOINED == state);
+ }
+}
+
//EOF
diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h
index b2288a42ff..21fba433c6 100644
--- a/indra/newview/llcallfloater.h
+++ b/indra/newview/llcallfloater.h
@@ -38,6 +38,7 @@
#include "llvoiceclient.h"
class LLAvatarList;
+class LLAvatarListItem;
class LLNonAvatarCaller;
class LLOutputMonitorCtrl;
class LLParticipantList;
@@ -70,6 +71,8 @@ public:
*/
/*virtual*/ void onChange();
+ static void sOnCurrentChannelChanged(const LLUUID& session_id);
+
private:
typedef enum e_voice_controls_type
{
@@ -79,6 +82,16 @@ private:
VC_PEER_TO_PEER
}EVoiceControls;
+ typedef enum e_speaker_state
+ {
+ STATE_UNKNOWN,
+ STATE_INVITED,
+ STATE_JOINED,
+ STATE_LEFT,
+ } ESpeakerState;
+
+ typedef std::map<LLUUID, ESpeakerState> speaker_state_map_t;
+
void leaveCall();
/**
@@ -93,13 +106,32 @@ private:
* Refreshes participant list according to current Voice Channel
*/
void refreshPartisipantList();
- void onCurrentChannelChanged(const LLUUID& session_id);
+ void onAvatarListRefreshed();
+
+
void updateTitle();
void initAgentData();
void setModeratorMutedVoice(bool moderator_muted);
- void updateModeratorState();
+ void updateAgentModeratorState();
+
+ void initParticipantsVoiceState();
+ void updateParticipantsVoiceState();
+ void setState(LLAvatarListItem* item, ESpeakerState state);
+ void setState(const LLUUID& speaker_id, ESpeakerState state)
+ {
+ lldebugs << "Storing state: " << speaker_id << ", " << state << llendl;
+ mSpeakerStateMap[speaker_id] = state;
+ }
+
+ ESpeakerState getState(const LLUUID& speaker_id)
+ {
+ lldebugs << "Getting state: " << speaker_id << ", " << mSpeakerStateMap[speaker_id] << llendl;
+
+ return mSpeakerStateMap[speaker_id];
+ }
private:
+ speaker_state_map_t mSpeakerStateMap;
LLSpeakerMgr* mSpeakerManager;
LLParticipantList* mPaticipants;
LLAvatarList* mAvatarList;
@@ -109,7 +141,10 @@ private:
LLOutputMonitorCtrl* mSpeakingIndicator;
bool mIsModeratorMutedVoice;
- boost::signals2::connection mChannelChangedConnection;
+ bool mInitParticipantsVoiceState;
+
+ boost::signals2::connection mAvatarListRefreshConnection;
+
};
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 37e27cf165..b1ddddc4b1 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -204,6 +204,8 @@ public:
userName->setValue(SL);
}
+ mMinUserNameWidth = style_params.font()->getWidth(userName->getWText().c_str()) + PADDING;
+
setTimeField(chat);
LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
@@ -220,7 +222,37 @@ public:
icon->setValue(LLSD("SL_Logo"));
}
- }
+ }
+
+ /*virtual*/ void draw()
+ {
+ LLTextEditor* user_name = getChild<LLTextEditor>("user_name");
+ LLTextBox* time_box = getChild<LLTextBox>("time_box");
+
+ LLRect user_name_rect = user_name->getRect();
+ S32 user_name_width = user_name_rect.getWidth();
+ S32 time_box_width = time_box->getRect().getWidth();
+
+ if (time_box->getVisible() && user_name_width <= mMinUserNameWidth)
+ {
+ time_box->setVisible(FALSE);
+
+ user_name_rect.mRight += time_box_width;
+ user_name->reshape(user_name_rect.getWidth(), user_name_rect.getHeight());
+ user_name->setRect(user_name_rect);
+ }
+
+ if (!time_box->getVisible() && user_name_width > mMinUserNameWidth + time_box_width)
+ {
+ user_name_rect.mRight -= time_box_width;
+ user_name->reshape(user_name_rect.getWidth(), user_name_rect.getHeight());
+ user_name->setRect(user_name_rect);
+
+ time_box->setVisible(TRUE);
+ }
+
+ LLPanel::draw();
+ }
void nameUpdatedCallback(const LLUUID& id,const std::string& first,const std::string& last,BOOL is_group)
{
@@ -230,6 +262,8 @@ public:
mLastName = last;
}
protected:
+ static const S32 PADDING = 20;
+
void showContextMenu(S32 x,S32 y)
{
if(mSourceType == CHAT_SOURCE_SYSTEM)
@@ -309,6 +343,7 @@ protected:
std::string mLastName;
std::string mFrom;
+ S32 mMinUserNameWidth;
};
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index c6fe076911..17ef1f41a4 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -66,11 +66,14 @@ static LLDefaultChildRegistry::Register<LLInvOfferChiclet> t7("chiclet_offer");
static const LLRect CHICLET_RECT(0, 25, 25, 0);
static const LLRect CHICLET_ICON_RECT(0, 22, 22, 0);
-static const LLRect VOICE_INDICATOR_RECT(25, 25, 45, 0);
-static const S32 OVERLAY_ICON_SHIFT = 2; // used for shifting of an overlay icon for new massages in a chiclet
+static const LLRect VOICE_INDICATOR_RECT(50, 25, 70, 0);
+static const LLRect COUNTER_RECT(25, 25, 50, 0);
+static const S32 OVERLAY_ICON_SHIFT = 2; // used for shifting of an overlay icon for new massages in a chiclet
+static const S32 SCROLL_BUTTON_PAD = 5;
// static
const S32 LLChicletPanel::s_scroll_ratio = 10;
+const S32 LLChicletNotificationCounterCtrl::MAX_DISPLAYED_COUNT = 99;
boost::signals2::signal<LLChiclet* (const LLUUID&),
@@ -138,7 +141,7 @@ private:
LLSysWellChiclet::Params::Params()
: button("button")
, unread_notifications("unread_notifications")
-, max_displayed_count("max_displayed_count", 9)
+, max_displayed_count("max_displayed_count", 99)
, flash_to_lit_count("flash_to_lit_count", 3)
, flash_period("flash_period", 0.5F)
{
@@ -154,6 +157,7 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p)
, mMaxDisplayedCount(p.max_displayed_count)
, mIsNewMessagesState(false)
, mFlashToLitTimer(NULL)
+, mContextMenu(NULL)
{
LLButton::Params button_params = p.button;
mButton = LLUICtrlFactory::create<LLButton>(button_params);
@@ -169,6 +173,7 @@ LLSysWellChiclet::~LLSysWellChiclet()
void LLSysWellChiclet::setCounter(S32 counter)
{
+ // note same code in LLChicletNotificationCounterCtrl::setCounter(S32 counter)
std::string s_count;
if(counter != 0)
{
@@ -182,9 +187,9 @@ void LLSysWellChiclet::setCounter(S32 counter)
mButton->setLabel(s_count);
- setNewMessagesState(counter > 0);
+ setNewMessagesState(counter > mCounter);
- // we have to flash to 'Lit' state each time new unread message is comming.
+ // we have to flash to 'Lit' state each time new unread message is coming.
if (counter > mCounter)
{
mFlashToLitTimer->flash();
@@ -229,6 +234,21 @@ void LLSysWellChiclet::setNewMessagesState(bool new_messages)
mIsNewMessagesState = new_messages;
}
+// virtual
+BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ if(!mContextMenu)
+ {
+ createMenu();
+ }
+ if (mContextMenu)
+ {
+ mContextMenu->show(x, y);
+ LLMenuGL::showPopup(this, mContextMenu, x, y);
+ }
+ return TRUE;
+}
+
/************************************************************************/
/* LLIMWellChiclet implementation */
/************************************************************************/
@@ -248,6 +268,47 @@ LLIMWellChiclet::~LLIMWellChiclet()
LLIMMgr::getInstance()->removeSessionObserver(this);
}
+void LLIMWellChiclet::onMenuItemClicked(const LLSD& user_data)
+{
+ std::string action = user_data.asString();
+ if("close all" == action)
+ {
+ LLIMWellWindow::getInstance()->closeAll();
+ }
+}
+
+bool LLIMWellChiclet::enableMenuItem(const LLSD& user_data)
+{
+ std::string item = user_data.asString();
+ if (item == "can close all")
+ {
+ return !LLIMWellWindow::getInstance()->isWindowEmpty();
+ }
+ return true;
+}
+
+void LLIMWellChiclet::createMenu()
+{
+ if(mContextMenu)
+ {
+ llwarns << "Menu already exists" << llendl;
+ return;
+ }
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("IMWellChicletMenu.Action",
+ boost::bind(&LLIMWellChiclet::onMenuItemClicked, this, _2));
+
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+ enable_registrar.add("IMWellChicletMenu.EnableItem",
+ boost::bind(&LLIMWellChiclet::enableMenuItem, this, _2));
+
+ mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>
+ ("menu_im_well_button.xml",
+ LLMenuGL::sMenuContainer,
+ LLViewerMenuHolderGL::child_registry_t::instance());
+}
+
void LLIMWellChiclet::messageCountChanged(const LLSD& session_data)
{
setCounter(LLBottomTray::getInstance()->getTotalUnreadIMCount());
@@ -281,6 +342,47 @@ void LLNotificationChiclet::connectCounterUpdatersToSignal(const std::string& no
}
}
+void LLNotificationChiclet::onMenuItemClicked(const LLSD& user_data)
+{
+ std::string action = user_data.asString();
+ if("close all" == action)
+ {
+ LLNotificationWellWindow::getInstance()->closeAll();
+ }
+}
+
+bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data)
+{
+ std::string item = user_data.asString();
+ if (item == "can close all")
+ {
+ return mUreadSystemNotifications != 0;
+ }
+ return true;
+}
+
+void LLNotificationChiclet::createMenu()
+{
+ if(mContextMenu)
+ {
+ llwarns << "Menu already exists" << llendl;
+ return;
+ }
+
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ registrar.add("NotificationWellChicletMenu.Action",
+ boost::bind(&LLNotificationChiclet::onMenuItemClicked, this, _2));
+
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+ enable_registrar.add("NotificationWellChicletMenu.EnableItem",
+ boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2));
+
+ mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>
+ ("menu_notification_well_button.xml",
+ LLMenuGL::sMenuContainer,
+ LLViewerMenuHolderGL::child_registry_t::instance());
+}
+
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
@@ -365,7 +467,7 @@ LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p)
// shift an icon a little bit to the right and up corner of a chiclet
overlay_icon_rect.translate(OVERLAY_ICON_SHIFT, OVERLAY_ICON_SHIFT);
- setShowCounter(false);
+ enableCounterControl(false);
}
void LLIMChiclet::setShowSpeaker(bool show)
@@ -378,30 +480,87 @@ void LLIMChiclet::setShowSpeaker(bool show)
onChicletSizeChanged();
}
}
+
+void LLIMChiclet::enableCounterControl(bool enable)
+{
+ mCounterEnabled = enable;
+ if(!enable)
+ {
+ LLChiclet::setShowCounter(false);
+ }
+}
+
+void LLIMChiclet::setShowCounter(bool show)
+{
+ if(!mCounterEnabled)
+ {
+ return;
+ }
+
+ bool needs_resize = getShowCounter() != show;
+ if(needs_resize)
+ {
+ LLChiclet::setShowCounter(show);
+ toggleCounterControl();
+ onChicletSizeChanged();
+ }
+}
+
void LLIMChiclet::initSpeakerControl()
{
// virtual
}
-void LLIMChiclet::toggleSpeakerControl()
+void LLIMChiclet::setRequiredWidth()
{
- LLRect speaker_rect = mSpeakerCtrl->getRect();
- S32 required_width = getRect().getWidth();
+ bool show_speaker = getShowSpeaker();
+ bool show_counter = getShowCounter();
+ S32 required_width = CHICLET_RECT.getWidth();
- if(getShowSpeaker())
+ if (show_counter)
{
- required_width = required_width + speaker_rect.getWidth();
- initSpeakerControl();
+ required_width += COUNTER_RECT.getWidth();
}
- else
+ if (show_speaker)
{
- required_width = required_width - speaker_rect.getWidth();
- }
-
+ required_width += VOICE_INDICATOR_RECT.getWidth();
+ }
+
reshape(required_width, getRect().getHeight());
+}
+
+void LLIMChiclet::toggleSpeakerControl()
+{
+ if(getShowSpeaker())
+ {
+ if(getShowCounter())
+ {
+ mSpeakerCtrl->setRect(VOICE_INDICATOR_RECT);
+ }
+ else
+ {
+ mSpeakerCtrl->setRect(COUNTER_RECT);
+ }
+ initSpeakerControl();
+ }
+
+ setRequiredWidth();
mSpeakerCtrl->setVisible(getShowSpeaker());
}
+void LLIMChiclet::setCounter(S32 counter)
+{
+ mCounterCtrl->setCounter(counter);
+ setShowCounter(counter);
+ setShowNewMessagesIcon(counter);
+}
+
+void LLIMChiclet::toggleCounterControl()
+{
+ setRequiredWidth();
+ mCounterCtrl->setVisible(getShowCounter());
+}
+
void LLIMChiclet::setShowNewMessagesIcon(bool show)
{
if(mNewMessagesIcon)
@@ -502,6 +661,7 @@ LLIMP2PChiclet::Params::Params()
unread_notifications.v_pad(5);
unread_notifications.text_color(LLColor4::white);
unread_notifications.mouse_opaque(false);
+ unread_notifications.rect(COUNTER_RECT);
unread_notifications.visible(false);
speaker.name("speaker");
@@ -540,12 +700,6 @@ LLIMP2PChiclet::LLIMP2PChiclet(const Params& p)
mSpeakerCtrl->setVisible(getShowSpeaker());
}
-void LLIMP2PChiclet::setCounter(S32 counter)
-{
- mCounterCtrl->setCounter(counter);
- setShowNewMessagesIcon(counter);
-}
-
void LLIMP2PChiclet::initSpeakerControl()
{
mSpeakerCtrl->setSpeakerId(getOtherParticipantId());
@@ -658,6 +812,7 @@ LLAdHocChiclet::Params::Params()
unread_notifications.v_pad(5);
unread_notifications.text_color(LLColor4::white);
unread_notifications.mouse_opaque(false);
+ unread_notifications.rect(COUNTER_RECT);
unread_notifications.visible(false);
@@ -732,12 +887,6 @@ void LLAdHocChiclet::switchToCurrentSpeaker()
mSpeakerCtrl->setSpeakerId(speaker_id);
}
-void LLAdHocChiclet::setCounter(S32 counter)
-{
- mCounterCtrl->setCounter(counter);
- setShowNewMessagesIcon(counter);
-}
-
void LLAdHocChiclet::createPopupMenu()
{
if(mPopupMenu)
@@ -809,6 +958,7 @@ LLIMGroupChiclet::Params::Params()
unread_notifications.font_halign(LLFontGL::HCENTER);
unread_notifications.v_pad(5);
unread_notifications.text_color(LLColor4::white);
+ unread_notifications.rect(COUNTER_RECT);
unread_notifications.visible(false);
speaker.name("speaker");
@@ -849,12 +999,6 @@ LLIMGroupChiclet::~LLIMGroupChiclet()
LLGroupMgr::getInstance()->removeObserver(this);
}
-void LLIMGroupChiclet::setCounter(S32 counter)
-{
- mCounterCtrl->setCounter(counter);
- setShowNewMessagesIcon(counter);
-}
-
void LLIMGroupChiclet::draw()
{
switchToCurrentSpeaker();
@@ -1168,7 +1312,6 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)
chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index));
arrange();
- showScrollButtonsIfNeeded();
return true;
}
@@ -1179,8 +1322,6 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)
void LLChicletPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param)
{
arrange();
- trimChiclets();
- showScrollButtonsIfNeeded();
}
void LLChicletPanel::onChicletClick(LLUICtrl*ctrl,const LLSD&param)
@@ -1197,8 +1338,6 @@ void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it)
mChicletList.erase(it);
arrange();
- trimChiclets();
- showScrollButtonsIfNeeded();
}
void LLChicletPanel::removeChiclet(S32 index)
@@ -1291,8 +1430,6 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )
{
LLPanel::reshape(width,height,called_from_parent);
- static const S32 SCROLL_BUTTON_PAD = 5;
-
//Needed once- to avoid error at first call of reshape() before postBuild()
if(!mLeftScrollButton||!mRightScrollButton)
return;
@@ -1303,9 +1440,21 @@ void LLChicletPanel::reshape(S32 width, S32 height, BOOL called_from_parent )
scroll_button_rect = mRightScrollButton->getRect();
mRightScrollButton->setRect(LLRect(width - scroll_button_rect.getWidth(),scroll_button_rect.mTop,
width, scroll_button_rect.mBottom));
- mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD,
- height, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0));
+
+
+ bool need_show_scroll = needShowScroll();
+ if(need_show_scroll)
+ {
+ mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD,
+ height, width - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0));
+ }
+ else
+ {
+ mScrollArea->setRect(LLRect(0,height, width, 0));
+ }
+
mShowControls = width >= mMinWidth;
+
mScrollArea->setVisible(mShowControls);
trimChiclets();
@@ -1318,8 +1467,8 @@ void LLChicletPanel::arrange()
if(mChicletList.empty())
return;
+ //initial arrange of chicklets positions
S32 chiclet_left = getChiclet(0)->getRect().mLeft;
-
S32 size = getChicletCount();
for( int n = 0; n < size; ++n)
{
@@ -1333,6 +1482,24 @@ void LLChicletPanel::arrange()
chiclet_left += chiclet_width + getChicletPadding();
}
+
+ //reset size and pos on mScrollArea
+ LLRect rect = getRect();
+ LLRect scroll_button_rect = mLeftScrollButton->getRect();
+
+ bool need_show_scroll = needShowScroll();
+ if(need_show_scroll)
+ {
+ mScrollArea->setRect(LLRect(scroll_button_rect.getWidth() + SCROLL_BUTTON_PAD,
+ rect.getHeight(), rect.getWidth() - scroll_button_rect.getWidth() - SCROLL_BUTTON_PAD, 0));
+ }
+ else
+ {
+ mScrollArea->setRect(LLRect(0,rect.getHeight(), rect.getWidth(), 0));
+ }
+
+ trimChiclets();
+ showScrollButtonsIfNeeded();
}
void LLChicletPanel::trimChiclets()
@@ -1350,6 +1517,17 @@ void LLChicletPanel::trimChiclets()
}
}
+bool LLChicletPanel::needShowScroll()
+{
+ if(mChicletList.empty())
+ return false;
+
+ S32 chicklet_width = (*mChicletList.rbegin())->getRect().mRight - (*mChicletList.begin())->getRect().mLeft;
+
+ return chicklet_width>getRect().getWidth();
+}
+
+
void LLChicletPanel::showScrollButtonsIfNeeded()
{
bool can_scroll_left = canScrollLeft();
@@ -1546,11 +1724,16 @@ S32 LLChicletPanel::getTotalUnreadIMCount()
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
+LLChicletNotificationCounterCtrl::Params::Params()
+: max_displayed_count("max_displayed_count", MAX_DISPLAYED_COUNT)
+{
+}
LLChicletNotificationCounterCtrl::LLChicletNotificationCounterCtrl(const Params& p)
: LLTextBox(p)
, mCounter(0)
, mInitialWidth(0)
+ , mMaxDisplayedCount(p.max_displayed_count)
{
mInitialWidth = getRect().getWidth();
}
@@ -1559,11 +1742,21 @@ void LLChicletNotificationCounterCtrl::setCounter(S32 counter)
{
mCounter = counter;
- std::stringstream stream;
- stream << getCounter();
+ // note same code in LLSysWellChiclet::setCounter(S32 counter)
+ std::string s_count;
+ if(counter != 0)
+ {
+ static std::string more_messages_exist("+");
+ std::string more_messages(counter > mMaxDisplayedCount ? more_messages_exist : "");
+ s_count = llformat("%d%s"
+ , llmin(counter, mMaxDisplayedCount)
+ , more_messages.c_str()
+ );
+ }
+
if(mCounter != 0)
{
- setText(stream.str());
+ setText(s_count);
}
else
{
diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h
index b3341f78a8..2ab6abfb5b 100644
--- a/indra/newview/llchiclet.h
+++ b/indra/newview/llchiclet.h
@@ -52,10 +52,19 @@ class LLChicletNotificationCounterCtrl : public LLTextBox
{
public:
+ static const S32 MAX_DISPLAYED_COUNT;
+
struct Params : public LLInitParam::Block<Params, LLTextBox::Params>
{
- Params()
- {};
+ /**
+ * Contains maximum displayed count of unread messages. Default value is 9.
+ *
+ * If count is less than "max_unread_count" will be displayed as is.
+ * Otherwise 9+ will be shown (for default value).
+ */
+ Optional<S32> max_displayed_count;
+
+ Params();
};
/**
@@ -93,6 +102,7 @@ private:
S32 mCounter;
S32 mInitialWidth;
+ S32 mMaxDisplayedCount;
};
/**
@@ -359,6 +369,32 @@ public:
virtual void toggleSpeakerControl();
/**
+ * Sets number of unread messages. Will update chiclet's width if number text
+ * exceeds size of counter and notify it's parent about size change.
+ */
+ virtual void setCounter(S32);
+
+ /**
+ * Enables/disables the counter control for a chiclet.
+ */
+ virtual void enableCounterControl(bool enable);
+
+ /**
+ * Sets show counter state.
+ */
+ virtual void setShowCounter(bool show);
+
+ /**
+ * Shows/Hides for counter control for a chiclet.
+ */
+ virtual void toggleCounterControl();
+
+ /**
+ * Sets required width for a chiclet according to visible controls.
+ */
+ virtual void setRequiredWidth();
+
+ /**
* Shows/hides overlay icon concerning new unread messages.
*/
virtual void setShowNewMessagesIcon(bool show);
@@ -400,6 +436,7 @@ protected:
protected:
bool mShowSpeaker;
+ bool mCounterEnabled;
LLIconCtrl* mNewMessagesIcon;
LLChicletNotificationCounterCtrl* mCounterCtrl;
@@ -453,12 +490,6 @@ public:
/* virtual */ void setOtherParticipantId(const LLUUID& other_participant_id);
/**
- * Sets number of unread messages. Will update chiclet's width if number text
- * exceeds size of counter and notify it's parent about size change.
- */
- /*virtual*/ void setCounter(S32);
-
- /**
* Init Speaker Control with speaker's ID
*/
/*virtual*/ void initSpeakerControl();
@@ -527,12 +558,6 @@ public:
/*virtual*/ void setSessionId(const LLUUID& session_id);
/**
- * Sets number of unread messages. Will update chiclet's width if number text
- * exceeds size of counter and notify it's parent about size change.
- */
- /*virtual*/ void setCounter(S32);
-
- /**
* Keep Speaker Control with actual speaker's ID
*/
/*virtual*/ void draw();
@@ -695,12 +720,6 @@ public:
/*virtual*/ void changed(LLGroupChange gc);
/**
- * Sets number of unread messages. Will update chiclet's width if number text
- * exceeds size of counter and notify it's parent about size change.
- */
- /*virtual*/ void setCounter(S32);
-
- /**
* Init Speaker Control with speaker's ID
*/
/*virtual*/ void initSpeakerControl();
@@ -806,6 +825,13 @@ protected:
*/
void changeLitState();
+ /**
+ * Displays menu.
+ */
+ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+ virtual void createMenu() = 0;
+
protected:
class FlashToLitTimer;
LLButton* mButton;
@@ -814,7 +840,7 @@ protected:
bool mIsNewMessagesState;
FlashToLitTimer* mFlashToLitTimer;
-
+ LLContextMenu* mContextMenu;
};
/**
@@ -835,6 +861,21 @@ protected:
LLIMWellChiclet(const Params& p);
/**
+ * Processes clicks on chiclet popup menu.
+ */
+ virtual void onMenuItemClicked(const LLSD& user_data);
+
+ /**
+ * Enables chiclet menu items.
+ */
+ bool enableMenuItem(const LLSD& user_data);
+
+ /**
+ * Creates menu.
+ */
+ /*virtual*/ void createMenu();
+
+ /**
* Handles changes in a session (message was added, messages were read, etc.)
*
* It get total count of unread messages from a LLIMMgr in all opened sessions and display it.
@@ -854,6 +895,21 @@ class LLNotificationChiclet : public LLSysWellChiclet
protected:
LLNotificationChiclet(const Params& p);
+ /**
+ * Processes clicks on chiclet menu.
+ */
+ void onMenuItemClicked(const LLSD& user_data);
+
+ /**
+ * Enables chiclet menu items.
+ */
+ bool enableMenuItem(const LLSD& user_data);
+
+ /**
+ * Creates menu.
+ */
+ /*virtual*/ void createMenu();
+
// connect counter updaters to the corresponding signals
void connectCounterUpdatersToSignal(const std::string& notification_type);
@@ -994,6 +1050,11 @@ protected:
bool canScrollRight();
/**
+ * Returns true if we need to show scroll buttons
+ */
+ bool needShowScroll();
+
+ /**
* Returns true if chiclets can be scrolled left.
*/
bool canScrollLeft();
diff --git a/indra/newview/llcommanddispatcherlistener.cpp b/indra/newview/llcommanddispatcherlistener.cpp
index 00a20de30e..91baeaf989 100644
--- a/indra/newview/llcommanddispatcherlistener.cpp
+++ b/indra/newview/llcommanddispatcherlistener.cpp
@@ -31,6 +31,11 @@ LLCommandDispatcherListener::LLCommandDispatcherListener(/* LLCommandDispatcher*
"[\"query\"] map of parameters, as if from ?key1=val&key2=val\n"
"[\"trusted\"] boolean indicating trusted browser [default true]",
&LLCommandDispatcherListener::dispatch);
+ add("enumerate",
+ "Post to [\"reply\"] a map of registered LLCommandHandler instances, containing\n"
+ "name key and (e.g.) untrusted flag",
+ &LLCommandDispatcherListener::enumerate,
+ LLSD().with("reply", LLSD()));
}
void LLCommandDispatcherListener::dispatch(const LLSD& params) const
@@ -45,3 +50,11 @@ void LLCommandDispatcherListener::dispatch(const LLSD& params) const
LLCommandDispatcher::dispatch(params["cmd"], params["params"], params["query"], NULL,
trusted_browser);
}
+
+void LLCommandDispatcherListener::enumerate(const LLSD& params) const
+{
+ LLReqID reqID(params);
+ LLSD response(LLCommandDispatcher::enumerate());
+ reqID.stamp(response);
+ LLEventPumps::instance().obtain(params["reply"]).post(response);
+}
diff --git a/indra/newview/llcommanddispatcherlistener.h b/indra/newview/llcommanddispatcherlistener.h
index d0070ddd71..9bcddebcc1 100644
--- a/indra/newview/llcommanddispatcherlistener.h
+++ b/indra/newview/llcommanddispatcherlistener.h
@@ -23,6 +23,7 @@ public:
private:
void dispatch(const LLSD& params) const;
+ void enumerate(const LLSD& params) const;
//LLCommandDispatcher* mDispatcher;
};
diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp
index 8c7e7bea83..dc506a1692 100644
--- a/indra/newview/llcommandhandler.cpp
+++ b/indra/newview/llcommandhandler.cpp
@@ -36,6 +36,7 @@
#include "llcommandhandler.h"
#include "llnotificationsutil.h"
#include "llcommanddispatcherlistener.h"
+#include "stringize.h"
// system includes
#include <boost/tokenizer.hpp>
@@ -67,6 +68,7 @@ public:
bool trusted_browser);
private:
+ friend LLSD LLCommandDispatcher::enumerate();
std::map<std::string, LLCommandHandlerInfo> mMap;
};
@@ -175,3 +177,56 @@ bool LLCommandDispatcher::dispatch(const std::string& cmd,
return LLCommandHandlerRegistry::instance().dispatch(
cmd, params, query_map, web, trusted_browser);
}
+
+static std::string lookup(LLCommandHandler::EUntrustedAccess value);
+
+LLSD LLCommandDispatcher::enumerate()
+{
+ LLSD response;
+ LLCommandHandlerRegistry& registry(LLCommandHandlerRegistry::instance());
+ for (std::map<std::string, LLCommandHandlerInfo>::const_iterator chi(registry.mMap.begin()),
+ chend(registry.mMap.end());
+ chi != chend; ++chi)
+ {
+ LLSD info;
+ info["untrusted"] = chi->second.mUntrustedBrowserAccess;
+ info["untrusted_str"] = lookup(chi->second.mUntrustedBrowserAccess);
+ response[chi->first] = info;
+ }
+ return response;
+}
+
+/*------------------------------ lookup stuff ------------------------------*/
+struct symbol_info
+{
+ const char* name;
+ LLCommandHandler::EUntrustedAccess value;
+};
+
+#define ent(SYMBOL) \
+ { \
+ #SYMBOL + 28, /* skip "LLCommandHandler::UNTRUSTED_" prefix */ \
+ SYMBOL \
+ }
+
+symbol_info symbols[] =
+{
+ ent(LLCommandHandler::UNTRUSTED_ALLOW), // allow commands from untrusted browsers
+ ent(LLCommandHandler::UNTRUSTED_BLOCK), // ignore commands from untrusted browsers
+ ent(LLCommandHandler::UNTRUSTED_THROTTLE) // allow untrusted, but only a few per min.
+};
+
+#undef ent
+
+static std::string lookup(LLCommandHandler::EUntrustedAccess value)
+{
+ for (symbol_info *sii(symbols), *siend(symbols + (sizeof(symbols)/sizeof(symbols[0])));
+ sii != siend; ++sii)
+ {
+ if (sii->value == value)
+ {
+ return sii->name;
+ }
+ }
+ return STRINGIZE("UNTRUSTED_" << value);
+}
diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h
index 1bae6d9414..a1d4c880f5 100644
--- a/indra/newview/llcommandhandler.h
+++ b/indra/newview/llcommandhandler.h
@@ -34,6 +34,8 @@
#ifndef LLCOMMANDHANDLER_H
#define LLCOMMANDHANDLER_H
+#include "llsd.h"
+
/* Example: secondlife:///app/foo/<uuid>
Command "foo" that takes one parameter, a UUID.
@@ -103,6 +105,9 @@ public:
// Execute a command registered via the above mechanism,
// passing string parameters.
// Returns true if command was found and executed correctly.
+ /// Return an LLSD::Map of registered LLCommandHandlers and associated
+ /// info (e.g. EUntrustedAccess).
+ static LLSD enumerate();
};
#endif
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 826cb0bb3b..832626e007 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -657,7 +657,7 @@ void LLFavoritesBarCtrl::updateButtons()
int first_changed_item_index = 0;
int rightest_point = getRect().mRight - mChevronButton->getRect().getWidth();
//lets find first changed button
- while (child_it != childs->end())
+ while (child_it != childs->end() && first_changed_item_index < mItems.count())
{
LLFavoriteLandmarkButton* button = dynamic_cast<LLFavoriteLandmarkButton*> (*child_it);
if (button)
@@ -679,9 +679,8 @@ void LLFavoritesBarCtrl::updateButtons()
}
// now first_changed_item_index should contains a number of button that need to change
- if (first_changed_item_index < mItems.count())
+ if (first_changed_item_index <= mItems.count())
{
- mUpdateDropDownItems = true;
// Rebuild the buttons only
// child_list_t is a linked list, so safe to erase from the middle if we pre-incrament the iterator
@@ -726,6 +725,10 @@ void LLFavoritesBarCtrl::updateButtons()
// Chevron button
if (mFirstDropDownItem < mItems.count())
{
+ // if updateButton had been called it means:
+ //or there are some new favorites, or width had been changed
+ // so if we need to display chevron button, we must update dropdown items too.
+ mUpdateDropDownItems = true;
S32 buttonHGap = 2; // default value
buttonXMLNode->getAttributeS32("left", buttonHGap);
LLRect rect;
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 81322abbf7..02884575b0 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -52,6 +52,7 @@
#include "llfloateravatarpicker.h"
#include "llfloaterauction.h"
#include "llfloatergroups.h"
+#include "llfloaterscriptlimits.h"
#include "llavataractions.h"
#include "lllineeditor.h"
#include "llnamelistctrl.h"
@@ -148,6 +149,10 @@ void send_parcel_select_objects(S32 parcel_local_id, U32 return_type,
msg->sendReliable(region->getHost());
}
+LLParcel* LLFloaterLand::getCurrentSelectedParcel()
+{
+ return mParcel->getParcel();
+};
//static
LLPanelLandObjects* LLFloaterLand::getCurrentPanelLandObjects()
@@ -421,6 +426,9 @@ BOOL LLPanelLandGeneral::postBuild()
mBtnBuyLand = getChild<LLButton>("Buy Land...");
mBtnBuyLand->setClickedCallback(onClickBuyLand, (void*)&BUY_PERSONAL_LAND);
+ mBtnScriptLimits = getChild<LLButton>("Scripts...");
+ mBtnScriptLimits->setClickedCallback(onClickScriptLimits, this);
+
mBtnBuyGroupLand = getChild<LLButton>("Buy For Group...");
mBtnBuyGroupLand->setClickedCallback(onClickBuyLand, (void*)&BUY_GROUP_LAND);
@@ -508,6 +516,7 @@ void LLPanelLandGeneral::refresh()
mTextDwell->setText(LLStringUtil::null);
mBtnBuyLand->setEnabled(FALSE);
+ mBtnScriptLimits->setEnabled(FALSE);
mBtnBuyGroupLand->setEnabled(FALSE);
mBtnReleaseLand->setEnabled(FALSE);
mBtnReclaimLand->setEnabled(FALSE);
@@ -715,6 +724,8 @@ void LLPanelLandGeneral::refresh()
mBtnBuyLand->setEnabled(
LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false));
+ mBtnScriptLimits->setEnabled(true);
+// LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false));
mBtnBuyGroupLand->setEnabled(
LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, true));
@@ -854,6 +865,17 @@ void LLPanelLandGeneral::onClickBuyLand(void* data)
LLViewerParcelMgr::getInstance()->startBuyLand(*for_group);
}
+// static
+void LLPanelLandGeneral::onClickScriptLimits(void* data)
+{
+ LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data;
+ LLParcel* parcel = panelp->mParcel->getParcel();
+ if(parcel != NULL)
+ {
+ LLFloaterReg::showInstance("script_limits");
+ }
+}
+
BOOL LLPanelLandGeneral::enableDeedToGroup(void* data)
{
LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data;
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index f7fb978c2a..eb47fbe15b 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -70,6 +70,7 @@ class LLPanelLandAccess;
class LLPanelLandBan;
class LLPanelLandRenters;
class LLPanelLandCovenant;
+class LLParcel;
class LLFloaterLand
: public LLFloater
@@ -80,7 +81,9 @@ public:
static LLPanelLandObjects* getCurrentPanelLandObjects();
static LLPanelLandCovenant* getCurrentPanelLandCovenant();
-
+
+ LLParcel* getCurrentSelectedParcel();
+
virtual void onOpen(const LLSD& key);
virtual BOOL postBuild();
@@ -146,6 +149,7 @@ public:
static BOOL enableDeedToGroup(void*);
static void onClickDeed(void*);
static void onClickBuyLand(void* data);
+ static void onClickScriptLimits(void* data);
static void onClickRelease(void*);
static void onClickReclaim(void*);
static void onClickBuyPass(void* deselect_when_done);
@@ -215,6 +219,7 @@ protected:
LLTextBox* mTextDwell;
LLButton* mBtnBuyLand;
+ LLButton* mBtnScriptLimits;
LLButton* mBtnBuyGroupLand;
// these buttons share the same location, but
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
new file mode 100644
index 0000000000..3042fbc6ec
--- /dev/null
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -0,0 +1,1061 @@
+/**
+ * @file llfloaterscriptlimits.cpp
+ * @author Gabriel Lee
+ * @brief Implementation of the region info and controls floater and panels.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llfloaterscriptlimits.h"
+
+#include "llsdutil.h"
+#include "llsdutil_math.h"
+#include "message.h"
+
+#include "llagent.h"
+#include "llfloateravatarpicker.h"
+#include "llfloaterland.h"
+#include "llfloaterreg.h"
+#include "llregionhandle.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llparcel.h"
+#include "lltabcontainer.h"
+#include "lltracker.h"
+#include "lltrans.h"
+#include "llviewercontrol.h"
+#include "lluictrlfactory.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llviewerwindow.h"
+
+///----------------------------------------------------------------------------
+/// LLFloaterScriptLimits
+///----------------------------------------------------------------------------
+
+// due to server side bugs the full summary display is not possible
+// until they are fixed this define creates a simple version of the
+// summary which only shows available & correct information
+#define USE_SIMPLE_SUMMARY
+
+LLFloaterScriptLimits::LLFloaterScriptLimits(const LLSD& seed)
+ : LLFloater(seed)
+{
+}
+
+BOOL LLFloaterScriptLimits::postBuild()
+{
+ // a little cheap and cheerful - if there's an about land panel open default to showing parcel info,
+ // otherwise default to showing attachments (avatar appearance)
+ bool selectParcelPanel = false;
+
+ LLFloaterLand* instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land");
+ if(instance)
+ {
+ if(instance->isShown())
+ {
+ selectParcelPanel = true;
+ }
+ }
+
+ mTab = getChild<LLTabContainer>("scriptlimits_panels");
+
+ // contruct the panels
+ LLPanelScriptLimitsRegionMemory* panel_memory;
+ panel_memory = new LLPanelScriptLimitsRegionMemory;
+ mInfoPanels.push_back(panel_memory);
+
+ LLUICtrlFactory::getInstance()->buildPanel(panel_memory, "panel_script_limits_region_memory.xml");
+ mTab->addTabPanel(panel_memory);
+
+ LLPanelScriptLimitsRegionURLs* panel_urls = new LLPanelScriptLimitsRegionURLs;
+ mInfoPanels.push_back(panel_urls);
+ LLUICtrlFactory::getInstance()->buildPanel(panel_urls, "panel_script_limits_region_urls.xml");
+ mTab->addTabPanel(panel_urls);
+
+ LLPanelScriptLimitsAttachment* panel_attachments = new LLPanelScriptLimitsAttachment;
+ mInfoPanels.push_back(panel_attachments);
+ LLUICtrlFactory::getInstance()->buildPanel(panel_attachments, "panel_script_limits_my_avatar.xml");
+ mTab->addTabPanel(panel_attachments);
+
+ if(selectParcelPanel)
+ {
+ mTab->selectTab(0);
+ }
+ else
+ {
+ mTab->selectTab(2);
+ }
+
+ return TRUE;
+}
+
+LLFloaterScriptLimits::~LLFloaterScriptLimits()
+{
+}
+
+// public
+void LLFloaterScriptLimits::refresh()
+{
+ for(info_panels_t::iterator iter = mInfoPanels.begin();
+ iter != mInfoPanels.end(); ++iter)
+ {
+ (*iter)->refresh();
+ }
+}
+
+
+///----------------------------------------------------------------------------
+// Base class for panels
+///----------------------------------------------------------------------------
+
+LLPanelScriptLimitsInfo::LLPanelScriptLimitsInfo()
+ : LLPanel()
+{
+}
+
+
+// virtual
+BOOL LLPanelScriptLimitsInfo::postBuild()
+{
+ refresh();
+ return TRUE;
+}
+
+// virtual
+void LLPanelScriptLimitsInfo::updateChild(LLUICtrl* child_ctr)
+{
+}
+
+///----------------------------------------------------------------------------
+// Responders
+///----------------------------------------------------------------------------
+
+void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content)
+{
+ // at this point we have an llsd which should contain ether one or two urls to the services we want.
+ // first we look for the details service:
+ if(content.has("ScriptResourceDetails"))
+ {
+ LLHTTPClient::get(content["ScriptResourceDetails"], new fetchScriptLimitsRegionDetailsResponder(mInfo));
+ }
+ else
+ {
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(!instance)
+ {
+ llinfos << "Failed to get llfloaterscriptlimits instance" << llendl;
+ }
+ else
+ {
+
+// temp - only show info if we get details - there's nothing to show if not until the sim gets fixed
+#ifdef USE_SIMPLE_SUMMARY
+
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ std::string msg = LLTrans::getString("ScriptLimitsRequestDontOwnParcel");
+ panel_memory->childSetValue("loading_text", LLSD(msg));
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ panel_urls->childSetValue("loading_text", LLSD(msg));
+
+ // intentional early out as we dont want the resource summary if we are using the "simple summary"
+ // and the details are missing
+ return;
+#endif
+ }
+ }
+
+ // then the summary service:
+ if(content.has("ScriptResourceSummary"))
+ {
+ LLHTTPClient::get(content["ScriptResourceSummary"], new fetchScriptLimitsRegionSummaryResponder(mInfo));
+ }
+}
+
+void fetchScriptLimitsRegionInfoResponder::error(U32 status, const std::string& reason)
+{
+ llinfos << "Error from responder " << reason << llendl;
+}
+
+void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content)
+{
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(!instance)
+ {
+ llinfos << "Failed to get llfloaterscriptlimits instance" << llendl;
+ }
+ else
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel_memory->setRegionSummary(content);
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ panel_urls->setRegionSummary(content);
+ }
+}
+
+void fetchScriptLimitsRegionSummaryResponder::error(U32 status, const std::string& reason)
+{
+ llinfos << "Error from responder " << reason << llendl;
+}
+
+void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content)
+{
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+
+ if(!instance)
+ {
+ llinfos << "Failed to get llfloaterscriptlimits instance" << llendl;
+ }
+ else
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel_memory->setRegionDetails(content);
+
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ panel_urls->setRegionDetails(content);
+ }
+}
+
+void fetchScriptLimitsRegionDetailsResponder::error(U32 status, const std::string& reason)
+{
+ llinfos << "Error from responder " << reason << llendl;
+}
+
+void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content)
+{
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+
+ if(!instance)
+ {
+ llinfos << "Failed to get llfloaterscriptlimits instance" << llendl;
+ }
+ else
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsAttachment* panel = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel");
+ panel->setAttachmentDetails(content);
+ }
+}
+
+void fetchScriptLimitsAttachmentInfoResponder::error(U32 status, const std::string& reason)
+{
+ llinfos << "Error from responder " << reason << llendl;
+}
+
+///----------------------------------------------------------------------------
+// Memory Panel
+///----------------------------------------------------------------------------
+
+BOOL LLPanelScriptLimitsRegionMemory::getLandScriptResources()
+{
+ LLSD body;
+ std::string url = gAgent.getRegion()->getCapability("LandResources");
+ if (!url.empty())
+ {
+ body["parcel_id"] = mParcelId;
+
+ LLSD info;
+ info["parcel_id"] = mParcelId;
+ LLHTTPClient::post(url, body, new fetchScriptLimitsRegionInfoResponder(info));
+
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+void LLPanelScriptLimitsRegionMemory::processParcelInfo(const LLParcelData& parcel_data)
+{
+ mParcelId = parcel_data.parcel_id;
+
+ if(!getLandScriptResources())
+ {
+ std::string msg_error = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(msg_error));
+ }
+ else
+ {
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ }
+}
+
+void LLPanelScriptLimitsRegionMemory::setParcelID(const LLUUID& parcel_id)
+{
+ if (!parcel_id.isNull())
+ {
+ LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
+ LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
+ }
+ else
+ {
+ std::string msg_error = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(msg_error));
+ }
+}
+
+// virtual
+void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::string& reason)
+{
+ llerrs << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
+}
+
+void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
+{
+ LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
+
+ S32 number_parcels = content["parcels"].size();
+
+ LLStringUtil::format_map_t args_parcels;
+ args_parcels["[PARCELS]"] = llformat ("%d", number_parcels);
+ std::string msg_parcels = LLTrans::getString("ScriptLimitsParcelsOwned", args_parcels);
+ childSetValue("parcels_listed", LLSD(msg_parcels));
+
+ S32 total_objects = 0;
+ S32 total_size = 0;
+
+ for(S32 i = 0; i < number_parcels; i++)
+ {
+ std::string parcel_name = content["parcels"][i]["name"].asString();
+
+ S32 number_objects = content["parcels"][i]["objects"].size();
+ for(S32 j = 0; j < number_objects; j++)
+ {
+ S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / 1024;
+ total_size += size;
+
+ std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString();
+ LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID();
+
+ LLSD element;
+
+ element["id"] = task_id;
+ element["columns"][0]["column"] = "size";
+ element["columns"][0]["value"] = llformat("%d", size);
+ element["columns"][0]["font"] = "SANSSERIF";
+ element["columns"][1]["column"] = "name";
+ element["columns"][1]["value"] = name_buf;
+ element["columns"][1]["font"] = "SANSSERIF";
+ element["columns"][2]["column"] = "owner";
+ element["columns"][2]["value"] = "";
+ element["columns"][2]["font"] = "SANSSERIF";
+ element["columns"][3]["column"] = "location";
+ element["columns"][3]["value"] = parcel_name;
+ element["columns"][3]["font"] = "SANSSERIF";
+
+ list->addElement(element);
+ mObjectListIDs.push_back(task_id);
+ total_objects++;
+ }
+ }
+
+ mParcelMemoryUsed =total_size;
+ mGotParcelMemoryUsed = TRUE;
+ populateParcelMemoryText();
+}
+
+void LLPanelScriptLimitsRegionMemory::populateParcelMemoryText()
+{
+ if(mGotParcelMemoryUsed && mGotParcelMemoryMax)
+ {
+#ifdef USE_SIMPLE_SUMMARY
+ LLStringUtil::format_map_t args_parcel_memory;
+ args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed);
+ std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsedSimple", args_parcel_memory);
+ childSetValue("memory_used", LLSD(msg_parcel_memory));
+#else
+ S32 parcel_memory_available = mParcelMemoryMax - mParcelMemoryUsed;
+
+ LLStringUtil::format_map_t args_parcel_memory;
+ args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed);
+ args_parcel_memory["[MAX]"] = llformat ("%d", mParcelMemoryMax);
+ args_parcel_memory["[AVAILABLE]"] = llformat ("%d", parcel_memory_available);
+ std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsed", args_parcel_memory);
+ childSetValue("memory_used", LLSD(msg_parcel_memory));
+#endif
+
+ childSetValue("loading_text", LLSD(std::string("")));
+ }
+}
+
+void LLPanelScriptLimitsRegionMemory::setRegionSummary(LLSD content)
+{
+ if(content["summary"]["available"][0]["type"].asString() == std::string("memory"))
+ {
+ mParcelMemoryMax = content["summary"]["available"][0]["amount"].asInteger();
+ mGotParcelMemoryMax = TRUE;
+ }
+ else if(content["summary"]["available"][1]["type"].asString() == std::string("memory"))
+ {
+ mParcelMemoryMax = content["summary"]["available"][1]["amount"].asInteger();
+ mGotParcelMemoryMax = TRUE;
+ }
+ else
+ {
+ llinfos << "summary doesn't contain memory info" << llendl;
+ return;
+ }
+/*
+ currently this is broken on the server, so we get this value from the details section
+ and update via populateParcelMemoryText() when both sets of information have been returned
+
+ when the sim is fixed this should be used instead:
+ if(content["summary"]["used"][0]["type"].asString() == std::string("memory"))
+ {
+ mParcelMemoryUsed = content["summary"]["used"][0]["amount"].asInteger();
+ mGotParcelMemoryUsed = TRUE;
+ }
+ else if(content["summary"]["used"][1]["type"].asString() == std::string("memory"))
+ {
+ mParcelMemoryUsed = content["summary"]["used"][1]["amount"].asInteger();
+ mGotParcelMemoryUsed = TRUE;
+ }
+ else
+ {
+ //ERROR!!!
+ return;
+ }*/
+
+ populateParcelMemoryText();
+}
+
+BOOL LLPanelScriptLimitsRegionMemory::postBuild()
+{
+ childSetAction("refresh_list_btn", onClickRefresh, this);
+ childSetAction("highlight_btn", onClickHighlight, this);
+ childSetAction("return_btn", onClickReturn, this);
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+
+ return StartRequestChain();
+}
+
+BOOL LLPanelScriptLimitsRegionMemory::StartRequestChain()
+{
+ LLUUID region_id;
+
+ LLFloaterLand* instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land");
+ if(!instance)
+ {
+ //this isnt really an error...
+// llinfos << "Failed to get about land instance" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(std::string("")));
+ //might have to do parent post build here
+ //if not logic below could use early outs
+ return FALSE;
+ }
+
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+
+ LLParcel* parcel = instance->getCurrentSelectedParcel();
+ LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
+
+ LLUUID current_region_id = gAgent.getRegion()->getRegionID();
+
+ if ((region) && (parcel))
+ {
+ LLVector3 parcel_center = parcel->getCenterpoint();
+
+ region_id = region->getRegionID();
+
+ if(region_id != current_region_id)
+ {
+ std::string msg_wrong_region = LLTrans::getString("ScriptLimitsRequestWrongRegion");
+ childSetValue("loading_text", LLSD(msg_wrong_region));
+ panel_urls->childSetValue("loading_text", LLSD(msg_wrong_region));
+ return FALSE;
+ }
+
+ LLVector3d pos_global = region->getCenterGlobal();
+
+ LLSD body;
+ std::string url = region->getCapability("RemoteParcelRequest");
+ if (!url.empty())
+ {
+ body["location"] = ll_sd_from_vector3(parcel_center);
+ if (!region_id.isNull())
+ {
+ body["region_id"] = region_id;
+ }
+ if (!pos_global.isExactlyZero())
+ {
+ U64 region_handle = to_region_handle(pos_global);
+ body["region_handle"] = ll_sd_from_U64(region_handle);
+ }
+ LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle()));
+ }
+ else
+ {
+ llwarns << "Can't get parcel info for script information request" << region_id
+ << ". Region: " << region->getName()
+ << " does not support RemoteParcelRequest" << llendl;
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ panel_urls->childSetValue("loading_text", LLSD(msg_waiting));
+ }
+ }
+ else
+ {
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ panel_urls->childSetValue("loading_text", LLSD(msg_waiting));
+ }
+
+ return LLPanelScriptLimitsInfo::postBuild();
+}
+
+void LLPanelScriptLimitsRegionMemory::clearList()
+{
+ LLCtrlListInterface *list = childGetListInterface("scripts_list");
+
+ if (list)
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ }
+
+ mGotParcelMemoryUsed = FALSE;
+ mGotParcelMemoryMax = FALSE;
+
+ LLStringUtil::format_map_t args_parcel_memory;
+ std::string msg_empty_string("");
+ childSetValue("memory_used", LLSD(msg_empty_string));
+ childSetValue("parcels_listed", LLSD(msg_empty_string));
+
+ mObjectListIDs.clear();
+}
+
+// static
+void LLPanelScriptLimitsRegionMemory::onClickRefresh(void* userdata)
+{
+ llinfos << "LLPanelRegionGeneralInfo::onClickRefresh" << llendl;
+
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel_memory->clearList();
+
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ panel_urls->clearList();
+
+ panel_memory->StartRequestChain();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl;
+ return;
+ }
+}
+
+void LLPanelScriptLimitsRegionMemory::showBeacon()
+{
+/* LLScrollListCtrl* list = getChild<LLScrollListCtrl>("scripts_list");
+ if (!list) return;
+
+ LLScrollListItem* first_selected = list->getFirstSelected();
+ if (!first_selected) return;
+
+ std::string name = first_selected->getColumn(1)->getValue().asString();
+ std::string pos_string = first_selected->getColumn(3)->getValue().asString();
+
+ llinfos << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" <<llendl;
+ llinfos << "name = " << name << " pos = " << pos_string << llendl;
+
+ F32 x, y, z;
+ S32 matched = sscanf(pos_string.c_str(), "<%g,%g,%g>", &x, &y, &z);
+ if (matched != 3) return;
+
+ LLVector3 pos_agent(x, y, z);
+ LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
+ llinfos << "name = " << name << " pos = " << pos_string << llendl;
+ std::string tooltip("");
+ LLTracker::trackLocation(pos_global, name, tooltip, LLTracker::LOCATION_ITEM);*/
+}
+
+// static
+void LLPanelScriptLimitsRegionMemory::onClickHighlight(void* userdata)
+{
+/* llinfos << "LLPanelRegionGeneralInfo::onClickHighlight" << llendl;
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel->showBeacon();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+// panel->childSetValue("loading_text", LLSD(msg_waiting));
+ return;
+ }*/
+}
+
+void LLPanelScriptLimitsRegionMemory::returnObjects()
+{
+/* llinfos << "started" << llendl;
+ LLMessageSystem *msg = gMessageSystem;
+
+ LLViewerRegion* region = gAgent.getRegion();
+ if (!region) return;
+
+ llinfos << "got region" << llendl;
+ LLCtrlListInterface *list = childGetListInterface("scripts_list");
+ if (!list || list->getItemCount() == 0) return;
+
+ llinfos << "got list" << llendl;
+ std::vector<LLUUID>::iterator id_itor;
+
+ bool start_message = true;
+
+ for (id_itor = mObjectListIDs.begin(); id_itor != mObjectListIDs.end(); ++id_itor)
+ {
+ LLUUID task_id = *id_itor;
+ llinfos << task_id << llendl;
+ if (!list->isSelected(task_id))
+ {
+ llinfos << "not selected" << llendl;
+ // Selected only
+ continue;
+ }
+ llinfos << "selected" << llendl;
+ if (start_message)
+ {
+ msg->newMessageFast(_PREHASH_ParcelReturnObjects);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ParcelData);
+ msg->addS32Fast(_PREHASH_LocalID, -1); // Whole region
+ msg->addS32Fast(_PREHASH_ReturnType, RT_LIST);
+ start_message = false;
+ llinfos << "start message" << llendl;
+ }
+
+ msg->nextBlockFast(_PREHASH_TaskIDs);
+ msg->addUUIDFast(_PREHASH_TaskID, task_id);
+ llinfos << "added id" << llendl;
+
+ if (msg->isSendFullFast(_PREHASH_TaskIDs))
+ {
+ msg->sendReliable(region->getHost());
+ start_message = true;
+ llinfos << "sent 1" << llendl;
+ }
+ }
+
+ if (!start_message)
+ {
+ msg->sendReliable(region->getHost());
+ llinfos << "sent 2" << llendl;
+ }*/
+}
+
+// static
+void LLPanelScriptLimitsRegionMemory::onClickReturn(void* userdata)
+{
+/* llinfos << "LLPanelRegionGeneralInfo::onClickReturn" << llendl;
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel->returnObjects();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+// panel->childSetValue("loading_text", LLSD(msg_waiting));
+ return;
+ }*/
+}
+
+///----------------------------------------------------------------------------
+// URLs Panel
+///----------------------------------------------------------------------------
+
+void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content)
+{
+ LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
+
+ S32 number_parcels = content["parcels"].size();
+
+ LLStringUtil::format_map_t args_parcels;
+ args_parcels["[PARCELS]"] = llformat ("%d", number_parcels);
+ std::string msg_parcels = LLTrans::getString("ScriptLimitsParcelsOwned", args_parcels);
+ childSetValue("parcels_listed", LLSD(msg_parcels));
+
+ S32 total_objects = 0;
+ S32 total_size = 0;
+
+ for(S32 i = 0; i < number_parcels; i++)
+ {
+ std::string parcel_name = content["parcels"][i]["name"].asString();
+ llinfos << parcel_name << llendl;
+
+ S32 number_objects = content["parcels"][i]["objects"].size();
+ for(S32 j = 0; j < number_objects; j++)
+ {
+ if(content["parcels"][i]["objects"][j]["resources"].has("urls"))
+ {
+ S32 size = content["parcels"][i]["objects"][j]["resources"]["urls"].asInteger();
+ total_size += size;
+
+ std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString();
+ LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID();
+
+ LLSD element;
+
+ element["id"] = task_id;
+ element["columns"][0]["column"] = "urls";
+ element["columns"][0]["value"] = llformat("%d", size);
+ element["columns"][0]["font"] = "SANSSERIF";
+ element["columns"][1]["column"] = "name";
+ element["columns"][1]["value"] = name_buf;
+ element["columns"][1]["font"] = "SANSSERIF";
+ element["columns"][2]["column"] = "owner";
+ element["columns"][2]["value"] = "";
+ element["columns"][2]["font"] = "SANSSERIF";
+ element["columns"][3]["column"] = "location";
+ element["columns"][3]["value"] = parcel_name;
+ element["columns"][3]["font"] = "SANSSERIF";
+
+ list->addElement(element);
+ mObjectListIDs.push_back(task_id);
+ total_objects++;
+ }
+ }
+ }
+
+ mParcelURLsUsed =total_size;
+ mGotParcelURLsUsed = TRUE;
+ populateParcelURLsText();
+}
+
+void LLPanelScriptLimitsRegionURLs::populateParcelURLsText()
+{
+ if(mGotParcelURLsUsed && mGotParcelURLsMax)
+ {
+
+#ifdef USE_SIMPLE_SUMMARY
+ LLStringUtil::format_map_t args_parcel_urls;
+ args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed);
+ std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsedSimple", args_parcel_urls);
+ childSetValue("urls_used", LLSD(msg_parcel_urls));
+#else
+ S32 parcel_urls_available = mParcelURLsMax - mParcelURLsUsed;
+
+ LLStringUtil::format_map_t args_parcel_urls;
+ args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed);
+ args_parcel_urls["[MAX]"] = llformat ("%d", mParcelURLsMax);
+ args_parcel_urls["[AVAILABLE]"] = llformat ("%d", parcel_urls_available);
+ std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsed", args_parcel_urls);
+ childSetValue("urls_used", LLSD(msg_parcel_urls));
+#endif
+
+ childSetValue("loading_text", LLSD(std::string("")));
+
+ }
+}
+
+void LLPanelScriptLimitsRegionURLs::setRegionSummary(LLSD content)
+{
+ if(content["summary"]["available"][0]["type"].asString() == std::string("urls"))
+ {
+ mParcelURLsMax = content["summary"]["available"][0]["amount"].asInteger();
+ mGotParcelURLsMax = TRUE;
+ }
+ else if(content["summary"]["available"][1]["type"].asString() == std::string("urls"))
+ {
+ mParcelURLsMax = content["summary"]["available"][1]["amount"].asInteger();
+ mGotParcelURLsMax = TRUE;
+ }
+ else
+ {
+ llinfos << "summary contains no url info" << llendl;
+ return;
+ }
+/*
+ currently this is broken on the server, so we get this value from the details section
+ and update via populateParcelMemoryText() when both sets of information have been returned
+
+ when the sim is fixed this should be used instead:
+ if(content["summary"]["used"][0]["type"].asString() == std::string("urls"))
+ {
+ mParcelURLsUsed = content["summary"]["used"][0]["amount"].asInteger();
+ mGotParcelURLsUsed = TRUE;
+ }
+ else if(content["summary"]["used"][1]["type"].asString() == std::string("urls"))
+ {
+ mParcelURLsUsed = content["summary"]["used"][1]["amount"].asInteger();
+ mGotParcelURLsUsed = TRUE;
+ }
+ else
+ {
+ //ERROR!!!
+ return;
+ }*/
+
+ populateParcelURLsText();
+}
+
+BOOL LLPanelScriptLimitsRegionURLs::postBuild()
+{
+ childSetAction("refresh_list_btn", onClickRefresh, this);
+ childSetAction("highlight_btn", onClickHighlight, this);
+ childSetAction("return_btn", onClickReturn, this);
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ return FALSE;
+}
+
+void LLPanelScriptLimitsRegionURLs::clearList()
+{
+ LLCtrlListInterface *list = childGetListInterface("scripts_list");
+
+ if (list)
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ }
+
+ mGotParcelURLsUsed = FALSE;
+ mGotParcelURLsMax = FALSE;
+
+ LLStringUtil::format_map_t args_parcel_urls;
+ std::string msg_empty_string("");
+ childSetValue("urls_used", LLSD(msg_empty_string));
+ childSetValue("parcels_listed", LLSD(msg_empty_string));
+
+ mObjectListIDs.clear();
+}
+
+// static
+void LLPanelScriptLimitsRegionURLs::onClickRefresh(void* userdata)
+{
+ llinfos << "Refresh clicked" << llendl;
+
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ // use the memory panel to re-request all the info
+ panel_memory->clearList();
+
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ // but the urls panel to clear itself
+ panel_urls->clearList();
+
+ panel_memory->StartRequestChain();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl;
+ return;
+ }
+}
+
+// static
+void LLPanelScriptLimitsRegionURLs::onClickHighlight(void* userdata)
+{
+/* llinfos << "Highlight clicked" << llendl;
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ // use the beacon function from the memory panel
+ panel->showBeacon();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+// panel->childSetValue("loading_text", LLSD(msg_waiting));
+ return;
+ }*/
+}
+
+// static
+void LLPanelScriptLimitsRegionURLs::onClickReturn(void* userdata)
+{
+/* llinfos << "Return clicked" << llendl;
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ // use the return function from the memory panel
+ panel->returnObjects();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+// panel->childSetValue("loading_text", LLSD(msg_waiting));
+ return;
+ }*/
+}
+
+///----------------------------------------------------------------------------
+// Attachment Panel
+///----------------------------------------------------------------------------
+
+BOOL LLPanelScriptLimitsAttachment::requestAttachmentDetails()
+{
+ LLSD body;
+ std::string url = gAgent.getRegion()->getCapability("AttachmentResources");
+ if (!url.empty())
+ {
+ LLHTTPClient::get(url, body, new fetchScriptLimitsAttachmentInfoResponder());
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content)
+{
+ LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
+ S32 number_attachments = content["attachments"].size();
+
+ for(int i = 0; i < number_attachments; i++)
+ {
+ std::string humanReadableLocation = "";
+ if(content["attachments"][i].has("location"))
+ {
+ std::string actualLocation = content["attachments"][i]["location"];
+ humanReadableLocation = LLTrans::getString(actualLocation.c_str());
+ }
+
+ S32 number_objects = content["attachments"][i]["objects"].size();
+ for(int j = 0; j < number_objects; j++)
+ {
+ LLUUID task_id = content["attachments"][i]["objects"][j]["id"].asUUID();
+ S32 size = 0;
+ if(content["attachments"][i]["objects"][j]["resources"].has("memory"))
+ {
+ size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger();
+ }
+ S32 urls = 0;
+ if(content["attachments"][i]["objects"][j]["resources"].has("urls"))
+ {
+ urls = content["attachments"][i]["objects"][j]["resources"]["urls"].asInteger();
+ }
+ std::string name = content["attachments"][i]["objects"][j]["name"].asString();
+
+ LLSD element;
+
+ element["id"] = task_id;
+ element["columns"][0]["column"] = "size";
+ element["columns"][0]["value"] = llformat("%d", size);
+ element["columns"][0]["font"] = "SANSSERIF";
+
+ element["columns"][1]["column"] = "urls";
+ element["columns"][1]["value"] = llformat("%d", urls);
+ element["columns"][1]["font"] = "SANSSERIF";
+
+ element["columns"][2]["column"] = "name";
+ element["columns"][2]["value"] = name;
+ element["columns"][2]["font"] = "SANSSERIF";
+
+ element["columns"][3]["column"] = "location";
+ element["columns"][3]["value"] = humanReadableLocation;
+ element["columns"][3]["font"] = "SANSSERIF";
+
+ list->addElement(element);
+ }
+ }
+
+ childSetValue("loading_text", LLSD(std::string("")));
+}
+
+BOOL LLPanelScriptLimitsAttachment::postBuild()
+{
+ childSetAction("refresh_list_btn", onClickRefresh, this);
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ return requestAttachmentDetails();
+}
+
+void LLPanelScriptLimitsAttachment::clearList()
+{
+ LLCtrlListInterface *list = childGetListInterface("scripts_list");
+
+ if (list)
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ }
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+}
+
+// static
+void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata)
+{
+ llinfos << "Refresh clicked" << llendl;
+
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsAttachment* panel_attachments = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel");
+ panel_attachments->clearList();
+ panel_attachments->requestAttachmentDetails();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl;
+ return;
+ }
+}
diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h
new file mode 100644
index 0000000000..88239136e3
--- /dev/null
+++ b/indra/newview/llfloaterscriptlimits.h
@@ -0,0 +1,259 @@
+/**
+ * @file llfloaterscriptlimits.h
+ * @author Gabriel Lee
+ * @brief Declaration of the region info and controls floater and panels.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERSCRIPTLIMITS_H
+#define LL_LLFLOATERSCRIPTLIMITS_H
+
+#include <vector>
+#include "llfloater.h"
+#include "llhost.h"
+#include "llpanel.h"
+#include "llremoteparcelrequest.h"
+
+class LLPanelScriptLimitsInfo;
+class LLTabContainer;
+
+class LLPanelScriptLimitsRegionMemory;
+
+class LLFloaterScriptLimits : public LLFloater
+{
+ friend class LLFloaterReg;
+public:
+
+ /*virtual*/ BOOL postBuild();
+
+ // from LLPanel
+ virtual void refresh();
+
+private:
+
+ LLFloaterScriptLimits(const LLSD& seed);
+ ~LLFloaterScriptLimits();
+
+protected:
+
+ LLTabContainer* mTab;
+ typedef std::vector<LLPanelScriptLimitsInfo*> info_panels_t;
+ info_panels_t mInfoPanels;
+};
+
+
+// Base class for all script limits information panels.
+class LLPanelScriptLimitsInfo : public LLPanel
+{
+public:
+ LLPanelScriptLimitsInfo();
+
+ virtual BOOL postBuild();
+ virtual void updateChild(LLUICtrl* child_ctrl);
+
+protected:
+ void initCtrl(const std::string& name);
+
+ typedef std::vector<std::string> strings_t;
+
+ LLHost mHost;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Responders
+/////////////////////////////////////////////////////////////////////////////
+
+class fetchScriptLimitsRegionInfoResponder: public LLHTTPClient::Responder
+{
+ public:
+ fetchScriptLimitsRegionInfoResponder(const LLSD& info) : mInfo(info) {};
+
+ void result(const LLSD& content);
+ void error(U32 status, const std::string& reason);
+ public:
+ protected:
+ LLSD mInfo;
+};
+
+class fetchScriptLimitsRegionSummaryResponder: public LLHTTPClient::Responder
+{
+ public:
+ fetchScriptLimitsRegionSummaryResponder(const LLSD& info) : mInfo(info) {};
+
+ void result(const LLSD& content);
+ void error(U32 status, const std::string& reason);
+ public:
+ protected:
+ LLSD mInfo;
+};
+
+class fetchScriptLimitsRegionDetailsResponder: public LLHTTPClient::Responder
+{
+ public:
+ fetchScriptLimitsRegionDetailsResponder(const LLSD& info) : mInfo(info) {};
+
+ void result(const LLSD& content);
+ void error(U32 status, const std::string& reason);
+ public:
+ protected:
+ LLSD mInfo;
+};
+
+class fetchScriptLimitsAttachmentInfoResponder: public LLHTTPClient::Responder
+{
+ public:
+ fetchScriptLimitsAttachmentInfoResponder() {};
+
+ void result(const LLSD& content);
+ void error(U32 status, const std::string& reason);
+ public:
+ protected:
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Memory panel
+/////////////////////////////////////////////////////////////////////////////
+
+class LLPanelScriptLimitsRegionMemory : public LLPanelScriptLimitsInfo, LLRemoteParcelInfoObserver
+{
+
+public:
+ LLPanelScriptLimitsRegionMemory()
+ : LLPanelScriptLimitsInfo(), LLRemoteParcelInfoObserver(), mParcelId(LLUUID()), mGotParcelMemoryUsed(FALSE), mGotParcelMemoryMax(FALSE) {};
+ ~LLPanelScriptLimitsRegionMemory()
+ {
+ LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this);
+ };
+
+ // LLPanel
+ virtual BOOL postBuild();
+
+ void setRegionDetails(LLSD content);
+ void setRegionSummary(LLSD content);
+
+ BOOL StartRequestChain();
+
+ void populateParcelMemoryText();
+ BOOL getLandScriptResources();
+ void clearList();
+ void showBeacon();
+ void returnObjects();
+
+private:
+
+ LLUUID mParcelId;
+ BOOL mGotParcelMemoryUsed;
+ BOOL mGotParcelMemoryMax;
+ S32 mParcelMemoryMax;
+ S32 mParcelMemoryUsed;
+
+ std::vector<LLUUID> mObjectListIDs;
+
+protected:
+
+// LLRemoteParcelInfoObserver interface:
+/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
+/*virtual*/ void setParcelID(const LLUUID& parcel_id);
+/*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+
+ static void onClickRefresh(void* userdata);
+ static void onClickHighlight(void* userdata);
+ static void onClickReturn(void* userdata);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// URLs panel
+/////////////////////////////////////////////////////////////////////////////
+
+class LLPanelScriptLimitsRegionURLs : public LLPanelScriptLimitsInfo
+{
+
+public:
+ LLPanelScriptLimitsRegionURLs()
+ : LLPanelScriptLimitsInfo(), mParcelId(LLUUID()), mGotParcelURLsUsed(FALSE), mGotParcelURLsMax(FALSE) {};
+ ~LLPanelScriptLimitsRegionURLs()
+ {
+ };
+
+ // LLPanel
+ virtual BOOL postBuild();
+
+ void setRegionDetails(LLSD content);
+ void setRegionSummary(LLSD content);
+
+ void populateParcelURLsText();
+ void clearList();
+
+private:
+
+ LLUUID mParcelId;
+ BOOL mGotParcelURLsUsed;
+ BOOL mGotParcelURLsMax;
+ S32 mParcelURLsMax;
+ S32 mParcelURLsUsed;
+
+ std::vector<LLUUID> mObjectListIDs;
+
+protected:
+
+ static void onClickRefresh(void* userdata);
+ static void onClickHighlight(void* userdata);
+ static void onClickReturn(void* userdata);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Attachment panel
+/////////////////////////////////////////////////////////////////////////////
+
+class LLPanelScriptLimitsAttachment : public LLPanelScriptLimitsInfo
+{
+
+public:
+ LLPanelScriptLimitsAttachment()
+ : LLPanelScriptLimitsInfo() {};
+ ~LLPanelScriptLimitsAttachment()
+ {
+ };
+
+ // LLPanel
+ virtual BOOL postBuild();
+
+ void setAttachmentDetails(LLSD content);
+
+ BOOL requestAttachmentDetails();
+ void clearList();
+
+private:
+
+protected:
+
+ static void onClickRefresh(void* userdata);
+};
+
+#endif
diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp
index 86992d6a31..c930e99bad 100644
--- a/indra/newview/llfloatertopobjects.cpp
+++ b/indra/newview/llfloatertopobjects.cpp
@@ -162,7 +162,7 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)
msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ReportType, mCurrentMode);
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("objects_list");
-
+
S32 block_count = msg->getNumberOfBlocks("ReportData");
for (S32 block = 0; block < block_count; ++block)
{
@@ -432,7 +432,6 @@ void LLFloaterTopObjects::onRefresh()
filter = mFilter;
clearList();
-
LLMessageSystem *msg = gMessageSystem;
msg->newMessageFast(_PREHASH_LandStatRequest);
msg->nextBlockFast(_PREHASH_AgentData);
@@ -465,7 +464,7 @@ void LLFloaterTopObjects::onGetByOwnerName()
}
void LLFloaterTopObjects::showBeacon()
-{
+{
LLScrollListCtrl* list = getChild<LLScrollListCtrl>("objects_list");
if (!list) return;
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 8b05f8614d..9cca1b07db 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -751,7 +751,7 @@ void LLFolderView::sanitizeSelection()
}
// Don't allow invisible items (such as root folders) to be selected.
- if (item->getDontShowInHierarchy())
+ if (item->getHidden())
{
items_to_remove.push_back(item);
}
@@ -774,7 +774,7 @@ void LLFolderView::sanitizeSelection()
parent_folder;
parent_folder = parent_folder->getParentFolder())
{
- if (parent_folder->potentiallyVisible() && !parent_folder->getDontShowInHierarchy())
+ if (parent_folder->potentiallyVisible() && !parent_folder->getHidden())
{
// give initial selection to first ancestor folder that potentially passes the filter
if (!new_selection)
@@ -796,7 +796,7 @@ void LLFolderView::sanitizeSelection()
// nothing selected to start with, so pick "My Inventory" as best guess
new_selection = getItemByID(gInventory.getRootFolderID());
// ... except if it's hidden from the UI.
- if (new_selection && new_selection->getDontShowInHierarchy())
+ if (new_selection && new_selection->getHidden())
{
new_selection = NULL;
}
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index bfd9d6dca7..720c2c7b1a 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -136,7 +136,7 @@ LLFolderViewItem::LLFolderViewItem(LLFolderViewItem::Params p)
mListener(p.listener),
mArrowImage(p.folder_arrow_image),
mBoxImage(p.selection_image),
- mDontShowInHierarchy(false),
+ mHidden(false),
mShowLoadStatus(false)
{
refresh();
@@ -201,7 +201,7 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children)
LLFolderViewItem* itemp = mParentFolder->getPreviousFromChild( this, include_children );
// Skip over items that are invisible or are hidden from the UI.
- while(itemp && (!itemp->getVisible() || itemp->getDontShowInHierarchy()))
+ while(itemp && (!itemp->getVisible() || itemp->getHidden()))
{
LLFolderViewItem* next_itemp = itemp->mParentFolder->getPreviousFromChild( itemp, include_children );
if (itemp == next_itemp)
@@ -418,7 +418,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)
S32 LLFolderViewItem::getItemHeight()
{
- if (mDontShowInHierarchy) return 0;
+ if (mHidden) return 0;
S32 icon_height = mIcon->getHeight();
S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight());
@@ -823,7 +823,7 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
void LLFolderViewItem::draw()
{
- if (mDontShowInHierarchy) return;
+ if (mHidden) return;
static LLUIColor sFgColor = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
static LLUIColor sHighlightBgColor = LLUIColorTable::instance().getColor("MenuItemHighlightBgColor", DEFAULT_WHITE);
@@ -970,11 +970,26 @@ void LLFolderViewItem::draw()
font->renderUTF8( mLabel, 0, text_left, y, color,
- LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
- S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE);
+ LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
+ S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE);
+// LLViewerInventoryCategory *item = 0;
+// if (getListener())
+// item = gInventory.getCategory(getListener()->getUUID());
+ bool root_is_loading = false;
+ if (getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(),gInventory.getRootFolderID()))
+ {
+ // Descendent of my inventory.
+ root_is_loading = gInventory.myInventoryFetchInProgress();
+ }
+ if (getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(),gInventory.getLibraryRootFolderID()))
+ {
+ // Descendent of library
+ root_is_loading = gInventory.libraryFetchInProgress();
+ }
+
if ( (mIsLoading && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime"))
- || (LLInventoryModel::backgroundFetchActive() && mShowLoadStatus) )
+ || (LLInventoryModel::backgroundFetchActive() && root_is_loading && mShowLoadStatus) )
{
std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) ";
font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor,
@@ -1257,7 +1272,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter)
// filter self only on first pass through
LLFolderViewItem::filter( filter );
}
- if (mDontShowInHierarchy)
+ if (mHidden)
{
setOpen();
}
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index a43096dcb2..21e24c2a4d 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -162,7 +162,7 @@ protected:
LLUIImagePtr mBoxImage;
BOOL mIsLoading;
LLTimer mTimeSinceRequestStart;
- bool mDontShowInHierarchy;
+ bool mHidden;
bool mShowLoadStatus;
// helper function to change the selection from the root.
@@ -206,8 +206,11 @@ public:
// makes sure that this view and it's children are the right size.
virtual S32 arrange( S32* width, S32* height, S32 filter_generation );
virtual S32 getItemHeight();
- void setDontShowInHierarchy(bool dont_show) { mDontShowInHierarchy = dont_show; }
- bool getDontShowInHierarchy() const { return mDontShowInHierarchy; }
+
+ // Hide the folder from the UI, such as if you want to hide the root
+ // folder in an inventory panel.
+ void setHidden(bool hidden) { mHidden = hidden; }
+ bool getHidden() const { return mHidden; }
// applies filters to control visibility of inventory items
virtual void filter( LLInventoryFilter& filter);
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index ff75d461df..22658b4d65 100644
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -119,6 +119,36 @@ void LLGroupActions::search()
}
// static
+void LLGroupActions::startCall(const LLUUID& group_id)
+{
+ // create a new group voice session
+ LLGroupData gdata;
+
+ if (!gAgent.getGroupData(group_id, gdata))
+ {
+ llwarns << "Error getting group data" << llendl;
+ return;
+ }
+
+ LLUUID session_id = gIMMgr->addSession(gdata.mName, IM_SESSION_GROUP_START, group_id, true);
+ if (session_id == LLUUID::null)
+ {
+ llwarns << "Error adding session" << llendl;
+ return;
+ }
+
+ // start the call
+ // *TODO: move this to LLIMMgr?
+ LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(session_id);
+ if (session && session->mSessionInitialized)
+ gIMMgr->startCall(session_id);
+ else
+ gIMMgr->autoStartCallOnStartup(session_id);
+
+ make_ui_sound("UISndStartIM");
+}
+
+// static
void LLGroupActions::join(const LLUUID& group_id)
{
LLGroupMgrGroupData* gdatap =
diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h
index 9750b3e3cb..e99df86cd9 100644
--- a/indra/newview/llgroupactions.h
+++ b/indra/newview/llgroupactions.h
@@ -99,6 +99,11 @@ public:
static bool isInGroup(const LLUUID& group_id);
/**
+ * Start a group voice call.
+ */
+ static void startCall(const LLUUID& group_id);
+
+ /**
* Returns true if avatar is in group.
*
* Note that data about group members is loaded from server.
diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp
index ab9db10f38..3ca459a403 100644
--- a/indra/newview/llgrouplist.cpp
+++ b/indra/newview/llgrouplist.cpp
@@ -37,6 +37,7 @@
// libs
#include "llbutton.h"
#include "lliconctrl.h"
+#include "llmenugl.h"
#include "lltextbox.h"
#include "lltrans.h"
@@ -46,6 +47,7 @@
#include "llfloaterreg.h"
#include "lltextutil.h"
#include "llviewercontrol.h" // for gSavedSettings
+#include "llviewermenu.h" // for gMenuHolder
static LLDefaultChildRegistry::Register<LLGroupList> r("group_list");
S32 LLGroupListItem::sIconWidth = 0;
@@ -88,11 +90,24 @@ LLGroupList::LLGroupList(const Params& p)
// Set default sort order.
setComparator(&GROUP_COMPARATOR);
+
+ // Set up context menu.
+ LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
+ LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+
+ registrar.add("People.Groups.Action", boost::bind(&LLGroupList::onContextMenuItemClick, this, _2));
+ enable_registrar.add("People.Groups.Enable", boost::bind(&LLGroupList::onContextMenuItemEnable, this, _2));
+
+ LLMenuGL* context_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_people_groups.xml",
+ gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ if(context_menu)
+ mContextMenuHandle = context_menu->getHandle();
}
LLGroupList::~LLGroupList()
{
gAgent.removeListener(this);
+ LLView::deleteViewByHandle(mContextMenuHandle);
}
// virtual
@@ -104,6 +119,22 @@ void LLGroupList::draw()
LLFlatListView::draw();
}
+// virtual
+BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = LLUICtrl::handleRightMouseDown(x, y, mask);
+
+ LLMenuGL* context_menu = (LLMenuGL*)mContextMenuHandle.get();
+ if (context_menu)
+ {
+ context_menu->buildDrawLabels();
+ context_menu->updateParent(LLMenuGL::sMenuContainer);
+ LLMenuGL::showPopup(this, context_menu, x, y);
+ }
+
+ return handled;
+}
+
void LLGroupList::setNameFilter(const std::string& filter)
{
if (mNameFilter != filter)
@@ -203,6 +234,46 @@ bool LLGroupList::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD&
return false;
}
+bool LLGroupList::onContextMenuItemClick(const LLSD& userdata)
+{
+ std::string action = userdata.asString();
+ LLUUID selected_group = getSelectedUUID();
+
+ if (action == "view_info")
+ {
+ LLGroupActions::show(selected_group);
+ }
+ else if (action == "chat")
+ {
+ LLGroupActions::startIM(selected_group);
+ }
+ else if (action == "call")
+ {
+ LLGroupActions::startCall(selected_group);
+ }
+ else if (action == "activate")
+ {
+ LLGroupActions::activate(selected_group);
+ }
+ else if (action == "leave")
+ {
+ LLGroupActions::leave(selected_group);
+ }
+
+ return true;
+}
+
+bool LLGroupList::onContextMenuItemEnable(const LLSD& userdata)
+{
+ LLUUID selected_group_id = getSelectedUUID();
+ bool real_group_selected = selected_group_id.notNull(); // a "real" (not "none") group is selected
+
+ if (userdata.asString() == "activate")
+ return real_group_selected && gAgent.getGroupID() != selected_group_id;
+
+ return real_group_selected;
+}
+
/************************************************************************/
/* LLGroupListItem implementation */
/************************************************************************/
diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h
index 33cfe005b9..f7afe0c0b2 100644
--- a/indra/newview/llgrouplist.h
+++ b/indra/newview/llgrouplist.h
@@ -60,6 +60,7 @@ public:
virtual ~LLGroupList();
virtual void draw(); // from LLView
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); // from LLView
void setNameFilter(const std::string& filter);
void toggleIcons();
@@ -71,6 +72,11 @@ private:
void addNewItem(const LLUUID& id, const std::string& name, const LLUUID& icon_id, EAddPosition pos = ADD_BOTTOM);
bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); // called on agent group list changes
+ bool onContextMenuItemClick(const LLSD& userdata);
+ bool onContextMenuItemEnable(const LLSD& userdata);
+
+ LLHandle<LLView> mContextMenuHandle;
+
bool mShowIcons;
bool mDirty;
std::string mNameFilter;
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 9e878f8c75..8917cc11e1 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -238,15 +238,17 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string&
void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction)
{
- bool is_p2p_session = dynamic_cast<LLVoiceChannelP2P*>(mVoiceChannel);
- std::string other_avatar_name;
+ std::string you = LLTrans::getString("You");
+ std::string started_call = LLTrans::getString("started_call");
+ std::string joined_call = LLTrans::getString("joined_call");
+ std::string other_avatar_name = "";
- if(is_p2p_session)
+ switch(mSessionType)
{
+ case AVALINE_SESSION:
+ // *TODO: test avaline calls (EXT-2211)
+ case P2P_SESSION:
gCacheName->getFullName(mOtherParticipantID, other_avatar_name);
- std::string you = LLTrans::getString("You");
- std::string started_call = LLTrans::getString("started_call");
- std::string joined_call = LLTrans::getString("joined_call");
if(direction == LLVoiceChannel::INCOMING_CALL)
{
@@ -280,10 +282,45 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES
{
mSpeakers->update(true);
}
- }
- else // group || ad-hoc calls
- {
+ break;
+
+ case GROUP_SESSION:
+ case ADHOC_SESSION:
+ // *TODO: determine call starter's name "other_avatar_name" (EXT-2211)
+ // decide how to show notifications for a group/adhoc chat already opened
+ // for now there is no notification from voice channel for this case
+ if(direction == LLVoiceChannel::INCOMING_CALL)
+ {
+ switch(new_state)
+ {
+ case LLVoiceChannel::STATE_CALL_STARTED :
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, other_avatar_name, mOtherParticipantID, started_call);
+ break;
+ case LLVoiceChannel::STATE_CONNECTED :
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), joined_call);
+ default:
+ break;
+ }
+ }
+ else // outgoing call
+ {
+ switch(new_state)
+ {
+ case LLVoiceChannel::STATE_CALL_STARTED :
+ LLIMModel::getInstance()->addMessageSilently(mSessionID, you, gAgent.getID(), started_call);
+ break;
+ default:
+ break;
+ }
+ }
+
+ // Update speakers list when connected
+ if (LLVoiceChannel::STATE_CONNECTED == new_state)
+ {
+ mSpeakers->update(true);
+ }
+ break;
}
}
@@ -1190,15 +1227,15 @@ LLIMMgr::showSessionEventError(
const std::string& error_string,
const LLUUID session_id)
{
- const LLFloater* floater = getFloaterBySessionID (session_id);
- if (!floater) return;
-
LLSD args;
+ LLStringUtil::format_map_t event_args;
+
+ event_args["RECIPIENT"] = LLIMModel::getInstance()->getName(session_id);
+
args["REASON"] =
LLTrans::getString(error_string);
args["EVENT"] =
- LLTrans::getString(event_string);
- args["RECIPIENT"] = floater->getTitle();
+ LLTrans::getString(event_string, event_args);
LLNotificationsUtil::add(
"ChatterBoxSessionEventError",
@@ -1279,6 +1316,28 @@ void LLCallDialogManager::onVoiceChannelChanged(const LLUUID &session_id)
sPreviousSessionlName = sCurrentSessionlName;
sCurrentSessionlName = session->mName;
}
+
+ if (LLVoiceChannel::getCurrentVoiceChannel()->getState() == LLVoiceChannel::STATE_CALL_STARTED &&
+ LLVoiceChannel::getCurrentVoiceChannel()->getCallDirection() == LLVoiceChannel::OUTGOING_CALL)
+ {
+
+ //*TODO get rid of duplicated code
+ LLSD mCallDialogPayload;
+ mCallDialogPayload["session_id"] = sSession->mSessionID;
+ mCallDialogPayload["session_name"] = sSession->mName;
+ mCallDialogPayload["other_user_id"] = sSession->mOtherParticipantID;
+ mCallDialogPayload["old_channel_name"] = sPreviousSessionlName;
+ mCallDialogPayload["state"] = LLVoiceChannel::STATE_CALL_STARTED;
+ mCallDialogPayload["disconnected_channel_name"] = sSession->mName;
+ mCallDialogPayload["session_type"] = sSession->mSessionType;
+
+ LLOutgoingCallDialog* ocd = LLFloaterReg::getTypedInstance<LLOutgoingCallDialog>("outgoing_call", LLOutgoingCallDialog::OCD_KEY);
+ if(ocd)
+ {
+ ocd->show(mCallDialogPayload);
+ }
+ }
+
}
void LLCallDialogManager::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction)
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 0a8108899a..1eb8d1bc2c 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -67,6 +67,7 @@ F32 LLInventoryModel::sMaxTimeBetweenFetches = 10.f;
BOOL LLInventoryModel::sTimelyFetchPending = FALSE;
LLFrameTimer LLInventoryModel::sFetchTimer;
S16 LLInventoryModel::sBulkFetchCount = 0;
+BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE;
// Increment this if the inventory contents change in a non-backwards-compatible way.
// For viewer 2, the addition of link items makes a pre-viewer-2 cache incorrect.
@@ -1339,8 +1340,7 @@ bool LLInventoryModel::fetchDescendentsOf(const LLUUID& folder_id)
//Initialize statics.
bool LLInventoryModel::isBulkFetchProcessingComplete()
{
- return ( (sFetchQueue.empty()
- && sBulkFetchCount<=0) ? TRUE : FALSE ) ;
+ return sFetchQueue.empty() && sBulkFetchCount<=0;
}
class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder
@@ -1615,10 +1615,58 @@ void LLInventoryModel::bulkFetch(std::string url)
}
}
+bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id)
+{
+ for (std::deque<LLUUID>::iterator it = sFetchQueue.begin();
+ it != sFetchQueue.end(); ++it)
+ {
+ const LLUUID& fetch_id = *it;
+ if (gInventory.isObjectDescendentOf(fetch_id, cat_id))
+ return false;
+ }
+ return true;
+}
+
+/* static */
+bool LLInventoryModel::libraryFetchStarted()
+{
+ return sLibraryFetchStarted;
+}
+
+/* static */
+bool LLInventoryModel::libraryFetchCompleted()
+{
+ return libraryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getLibraryRootFolderID());
+}
+
+/* static */
+bool LLInventoryModel::libraryFetchInProgress()
+{
+ return libraryFetchStarted() && !libraryFetchCompleted();
+}
+
+/* static */
+bool LLInventoryModel::myInventoryFetchStarted()
+{
+ return sMyInventoryFetchStarted;
+}
+
+/* static */
+bool LLInventoryModel::myInventoryFetchCompleted()
+{
+ return myInventoryFetchStarted() && fetchQueueContainsNoDescendentsOf(gInventory.getRootFolderID());
+}
+
+/* static */
+bool LLInventoryModel::myInventoryFetchInProgress()
+{
+ return myInventoryFetchStarted() && !myInventoryFetchCompleted();
+}
+
// static
bool LLInventoryModel::isEverythingFetched()
{
- return (sAllFoldersFetched ? true : false);
+ return sAllFoldersFetched;
}
//static
@@ -1637,7 +1685,6 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)
if (!sMyInventoryFetchStarted)
{
sMyInventoryFetchStarted = TRUE;
- sFetchQueue.push_back(gInventory.getLibraryRootFolderID());
sFetchQueue.push_back(gInventory.getRootFolderID());
gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
}
@@ -1645,7 +1692,6 @@ void LLInventoryModel::startBackgroundFetch(const LLUUID& cat_id)
{
sLibraryFetchStarted = TRUE;
sFetchQueue.push_back(gInventory.getLibraryRootFolderID());
- sFetchQueue.push_back(gInventory.getRootFolderID());
gIdleCallbacks.addFunction(&LLInventoryModel::backgroundFetch, NULL);
}
}
@@ -2517,6 +2563,10 @@ void LLInventoryModel::buildParentChildMap()
llwarns << "Found " << lost << " lost categories." << llendl;
}
+ const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, FALSE) != LLUUID::null);
+ sFirstTimeInViewer2 = !COF_exists || gAgent.isFirstLogin();
+
+
// Now the items. We allocated in the last step, so now all we
// have to do is iterate over the items and put them in the right
// place.
@@ -3530,6 +3580,19 @@ void LLInventoryModel::setLibraryOwnerID(const LLUUID& val)
mLibraryOwnerID = val;
}
+// static
+BOOL LLInventoryModel::getIsFirstTimeInViewer2()
+{
+ // Do not call this before parentchild map is built.
+ if (!gInventory.mIsAgentInvUsable)
+ {
+ llwarns << "Parent Child Map not yet built; guessing as first time in viewer2." << llendl;
+ return TRUE;
+ }
+
+ return sFirstTimeInViewer2;
+}
+
//----------------------------------------------------------------------------
// *NOTE: DEBUG functionality
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 27bbca493d..39377b4ae2 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -499,9 +499,9 @@ public:
// *NOTE: DEBUG functionality
void dumpInventory() const;
- ////////////////////////////////////////////////////////////////////////////////
- // Bulk / Background Fetch
+ ////////////////////////////////////////////////////////////////////////////////
+ // Bulk fetch
public:
// Start and stop background breadth-first fetching of inventory contents.
// This gets triggered when performing a filter-search
@@ -516,6 +516,14 @@ public:
// Add categories to a list to be fetched in bulk.
static void bulkFetch(std::string url);
+ static bool libraryFetchStarted();
+ static bool libraryFetchCompleted();
+ static bool libraryFetchInProgress();
+
+ static bool myInventoryFetchStarted();
+ static bool myInventoryFetchCompleted();
+ static bool myInventoryFetchInProgress();
+
private:
static BOOL sMyInventoryFetchStarted;
static BOOL sLibraryFetchStarted;
@@ -525,6 +533,13 @@ private:
// completing the fetch once per session should be sufficient
static BOOL sBackgroundFetchActive;
static S16 sBulkFetchCount;
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Login status
+public:
+ static BOOL getIsFirstTimeInViewer2();
+private:
+ static BOOL sFirstTimeInViewer2;
};
// a special inventory model for the agent
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 3c34ba32e2..082b7a9468 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -402,9 +402,12 @@ void LLInventoryPanel::modelChanged(U32 mask)
// static
void LLInventoryPanel::onIdle(void *userdata)
{
+ if (!gInventory.isInventoryUsable())
+ return;
+
LLInventoryPanel *self = (LLInventoryPanel*)userdata;
// Inventory just initialized, do complete build
- if (!self->mViewsInitialized && gInventory.isInventoryUsable())
+ if (!self->mViewsInitialized)
{
self->initializeViews();
}
@@ -502,7 +505,7 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
// but still have the parent folder present for listener-related operations.
if (id == mStartFolderID)
{
- folderp->setDontShowInHierarchy(TRUE);
+ folderp->setHidden(TRUE);
}
}
}
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 2dc9f255d7..24c72c65ce 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -76,6 +76,7 @@ LLLoginInstance::LLLoginInstance() :
mDispatcher.add("fail.login", boost::bind(&LLLoginInstance::handleLoginFailure, this, _1));
mDispatcher.add("connect", boost::bind(&LLLoginInstance::handleLoginSuccess, this, _1));
mDispatcher.add("disconnect", boost::bind(&LLLoginInstance::handleDisconnect, this, _1));
+ mDispatcher.add("indeterminate", boost::bind(&LLLoginInstance::handleIndeterminate, this, _1));
}
LLLoginInstance::~LLLoginInstance()
@@ -204,6 +205,8 @@ bool LLLoginInstance::handleLoginEvent(const LLSD& event)
mTransferRate = event["transfer_rate"].asReal();
}
+
+
// Call the method registered in constructor, if any, for more specific
// handling
LLEventDispatcher::Callable method(mDispatcher.get(event["change"]));
@@ -295,6 +298,22 @@ void LLLoginInstance::handleDisconnect(const LLSD& event)
// placeholder
}
+void LLLoginInstance::handleIndeterminate(const LLSD& event)
+{
+ // The indeterminate response means that the server
+ // gave the viewer a new url and params to try.
+ // The login module handles the retry, but it gives us the
+ // server response so that we may show
+ // the user some status.
+ LLSD message = event.get("data").get("message");
+ if(message.isDefined())
+ {
+ LLSD progress_update;
+ progress_update["desc"] = message;
+ LLEventPumps::getInstance()->obtain("LLProgressView").post(progress_update);
+ }
+}
+
bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key)
{
if(accepted)
@@ -374,28 +393,6 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg)
mNotifications->add(notification_name, args, payload,
boost::bind(&LLLoginInstance::updateDialogCallback, this, _1, _2));
}
-
- /* *NOTE:Mani Experiment with Event API interface.
- if(!mUpdateAppResponse)
- {
- bool make_unique = true;
- mUpdateAppResponse.reset(new LLEventStream("logininstance_updateapp", make_unique));
- mUpdateAppResponse->listen("diaupdateDialogCallback",
- boost::bind(&LLLoginInstance::updateDialogCallback,
- this, _1
- )
- );
- }
-
- LLSD event;
- event["op"] = "requestAdd";
- event["name"] = notification_name;
- event["substitutions"] = args;
- event["payload"] = payload;
- event["reply"] = mUpdateAppResponse->getName();
-
- LLEventPumps::getInstance()->obtain("LLNotifications").post(event);
- */
}
bool LLLoginInstance::updateDialogCallback(const LLSD& notification, const LLSD& response)
diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h
index 19d7449bc1..c8704eddb4 100644
--- a/indra/newview/lllogininstance.h
+++ b/indra/newview/lllogininstance.h
@@ -89,6 +89,7 @@ private:
void handleLoginFailure(const LLSD& event);
void handleLoginSuccess(const LLSD& event);
void handleDisconnect(const LLSD& event);
+ void handleIndeterminate(const LLSD& event);
bool handleTOSResponse(bool v, const std::string& key);
@@ -107,7 +108,6 @@ private:
std::string mSerialNumber;
int mLastExecEvent;
UpdaterLauncherCallback mUpdaterLauncher;
- boost::scoped_ptr<LLEventStream> mUpdateAppResponse;
LLEventDispatcher mDispatcher;
};
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp
index 2bb2a3da6f..b8da368bd7 100755
--- a/indra/newview/llmediadataclient.cpp
+++ b/indra/newview/llmediadataclient.cpp
@@ -164,7 +164,7 @@ void LLMediaDataClient::enqueue(const Request *request)
// Sadly, we have to const-cast because items put into the queue are not const
mSortedQueue.push_back(const_cast<LLMediaDataClient::Request*>(request));
- LL_DEBUGS("LLMediaDataClient") << "SORTED queue:" << mSortedQueue << LL_ENDL;
+ LL_DEBUGS("LLMediaDataClientQueue") << "SORTED queue:" << mSortedQueue << LL_ENDL;
}
else {
if (mRoundRobinQueue.size() > mMaxRoundRobinQueueSize)
@@ -187,7 +187,7 @@ void LLMediaDataClient::enqueue(const Request *request)
// Sadly, we have to const-cast because items put into the queue are not const
mRoundRobinQueue.push_front(const_cast<LLMediaDataClient::Request*>(request));
- LL_DEBUGS("LLMediaDataClient") << "RR queue:" << mRoundRobinQueue << LL_ENDL;
+ LL_DEBUGS("LLMediaDataClientQueue") << "RR queue:" << mRoundRobinQueue << LL_ENDL;
}
else
{
@@ -226,16 +226,16 @@ bool LLMediaDataClient::processQueueTimer()
{
LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, SORTED queue size is: " << mSortedQueue.size()
<< ", RR queue size is: " << mRoundRobinQueue.size() << LL_ENDL;
- LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, SORTED queue is: " << mSortedQueue << LL_ENDL;
- LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, RR queue is: " << mRoundRobinQueue << LL_ENDL;
+ LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() started, SORTED queue is: " << mSortedQueue << LL_ENDL;
+ LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() started, RR queue is: " << mRoundRobinQueue << LL_ENDL;
}
serviceQueue();
LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, SORTED queue size is: " << mSortedQueue.size()
<< ", RR queue size is: " << mRoundRobinQueue.size() << LL_ENDL;
- LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, SORTED queue is: " << mSortedQueue << LL_ENDL;
- LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() finished, RR queue is: " << mRoundRobinQueue << LL_ENDL;
+ LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() finished, SORTED queue is: " << mSortedQueue << LL_ENDL;
+ LL_DEBUGS("LLMediaDataClientQueue") << "QueueTimer::tick() finished, RR queue is: " << mRoundRobinQueue << LL_ENDL;
return isEmpty();
}
@@ -649,7 +649,7 @@ void LLMediaDataClient::Responder::error(U32 status, const std::string& reason)
/*virtual*/
void LLMediaDataClient::Responder::result(const LLSD& content)
{
- LL_DEBUGS("LLMediaDataClient") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL;
+ LL_DEBUGS("LLMediaDataClientResponse") << *mRequest << " result : " << ll_print_sd(content) << LL_ENDL;
}
//////////////////////////////////////////////////////////////////////////////////////
@@ -703,7 +703,7 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content)
llassert(type == LLMediaDataClient::Request::GET || type == LLMediaDataClient::Request::UPDATE)
if (type == LLMediaDataClient::Request::GET)
{
- LL_DEBUGS("LLMediaDataClient") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL;
+ LL_DEBUGS("LLMediaDataClientResponse") << *(getRequest()) << " GET returned: " << ll_print_sd(content) << LL_ENDL;
// Look for an error
if (content.has("error"))
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index 22201aecb2..818e7e0db1 100644
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -571,7 +571,7 @@ BOOL LLPanelStandStopFlying::postBuild()
mStandButton->setVisible(FALSE);
mStopFlyingButton = getChild<LLButton>("stop_fly_btn");
- mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE));
+ //mStopFlyingButton->setCommitCallback(boost::bind(&LLFloaterMove::setFlyingMode, FALSE));
mStopFlyingButton->setCommitCallback(boost::bind(&LLPanelStandStopFlying::onStopFlyingButtonClick, this));
mStopFlyingButton->setVisible(FALSE);
diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp
index 6210151d1b..71dc0f9011 100644
--- a/indra/newview/llnavigationbar.cpp
+++ b/indra/newview/llnavigationbar.cpp
@@ -51,6 +51,8 @@
#include "llsidetray.h"
#include "llslurl.h"
#include "llurlsimstring.h"
+#include "llurlregistry.h"
+#include "llurldispatcher.h"
#include "llviewerinventory.h"
#include "llviewermenu.h"
#include "llviewerparcelmgr.h"
@@ -58,6 +60,7 @@
#include "llappviewer.h"
#include "llviewercontrol.h"
#include "llfloatermediabrowser.h"
+#include "llweb.h"
#include "llinventorymodel.h"
#include "lllandmarkactions.h"
@@ -543,7 +546,20 @@ void LLNavigationBar::onRegionNameResponse(
// Invalid location?
if (!region_handle)
{
- invokeSearch(typed_location);
+ // handle any secondlife:// SLapps, or
+ // display http:// URLs in the media browser, or
+ // anything else is sent to the search floater
+ if (LLUrlRegistry::instance().isUrl(typed_location))
+ {
+ if (! LLURLDispatcher::dispatchFromTextEditor(typed_location))
+ {
+ LLWeb::loadURL(typed_location);
+ }
+ }
+ else
+ {
+ invokeSearch(typed_location);
+ }
return;
}
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 3a1ae5bf46..1a0183a8ba 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -178,6 +178,8 @@ void LLNearbyChat::addMessage(const LLChat& chat,bool archive)
if (!chat.mMuted)
{
+ tmp_chat.mFromName = chat.mFromID != gAgentID ? chat.mFromName : LLTrans::getString("You");
+
if (chat.mChatStyle == CHAT_STYLE_IRC)
{
LLColor4 txt_color = LLUIColorTable::instance().getColor("White");
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index 0dae667e7f..e29320ffc2 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -1557,6 +1557,11 @@ void LLPanelClassifiedEdit::resetControls()
childSetValue("price_for_listing", MINIMUM_PRICE_FOR_LISTING);
}
+bool LLPanelClassifiedEdit::canClose()
+{
+ return isValidName();
+}
+
void LLPanelClassifiedEdit::sendUpdate()
{
LLAvatarClassifiedInfo c_data;
@@ -1671,6 +1676,12 @@ void LLPanelClassifiedEdit::onChange()
void LLPanelClassifiedEdit::onSaveClick()
{
+ if(!isValidName())
+ {
+ notifyInvalidName();
+ return;
+ }
+
sendUpdate();
resetDirty();
}
@@ -1681,6 +1692,34 @@ std::string LLPanelClassifiedEdit::getLocationNotice()
return location_notice;
}
+bool LLPanelClassifiedEdit::isValidName()
+{
+ std::string name = getClassifiedName();
+ if (name.empty())
+ {
+ return false;
+ }
+ if (!isalnum(name[0]))
+ {
+ return false;
+ }
+
+ return true;
+}
+
+void LLPanelClassifiedEdit::notifyInvalidName()
+{
+ std::string name = getClassifiedName();
+ if (name.empty())
+ {
+ LLNotificationsUtil::add("BlankClassifiedName");
+ }
+ else if (!isalnum(name[0]))
+ {
+ LLNotificationsUtil::add("ClassifiedMustBeAlphanumeric");
+ }
+}
+
void LLPanelClassifiedEdit::onTexturePickerMouseEnter(LLUICtrl* ctrl)
{
ctrl->setVisible(TRUE);
diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h
index 8b32495854..10fdf60bbe 100644
--- a/indra/newview/llpanelclassified.h
+++ b/indra/newview/llpanelclassified.h
@@ -305,6 +305,8 @@ public:
bool isNew() { return mIsNew; }
+ bool canClose();
+
protected:
LLPanelClassifiedEdit();
@@ -325,6 +327,10 @@ protected:
std::string getLocationNotice();
+ bool isValidName();
+
+ void notifyInvalidName();
+
void onSetLocationClick();
void onChange();
void onSaveClick();
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index 70e4798079..3f309b3bf5 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -247,6 +247,9 @@ 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();
LLPanelChatControlPanel::draw();
}
@@ -282,8 +285,9 @@ void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id)
mGroupID = LLIMModel::getInstance()->getOtherParticipantID(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"));
+ mParticipantList = new LLParticipantList(mSpeakerManager, getChild<LLAvatarList>("speakers_list"), true,false);
}
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index e134840153..e5846c7318 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -564,6 +564,7 @@ BOOL LLPanelPeople::postBuild()
buttonSetAction("chat_btn", boost::bind(&LLPanelPeople::onChatButtonClicked, this));
buttonSetAction("im_btn", boost::bind(&LLPanelPeople::onImButtonClicked, this));
buttonSetAction("call_btn", boost::bind(&LLPanelPeople::onCallButtonClicked, this));
+ buttonSetAction("group_call_btn", boost::bind(&LLPanelPeople::onGroupCallButtonClicked, this));
buttonSetAction("teleport_btn", boost::bind(&LLPanelPeople::onTeleportButtonClicked, this));
buttonSetAction("share_btn", boost::bind(&LLPanelPeople::onShareButtonClicked, this));
@@ -733,6 +734,7 @@ void LLPanelPeople::updateButtons()
buttonSetVisible("view_profile_btn", !group_tab_active);
buttonSetVisible("im_btn", !group_tab_active);
buttonSetVisible("call_btn", !group_tab_active);
+ buttonSetVisible("group_call_btn", group_tab_active);
buttonSetVisible("teleport_btn", friends_tab_active);
buttonSetVisible("share_btn", nearby_tab_active || friends_tab_active);
@@ -781,6 +783,7 @@ void LLPanelPeople::updateButtons()
bool none_group_selected = item_selected && selected_id.isNull();
buttonSetEnabled("group_info_btn", !none_group_selected);
+ buttonSetEnabled("group_call_btn", !none_group_selected);
buttonSetEnabled("chat_btn", !none_group_selected);
}
@@ -1272,6 +1275,11 @@ void LLPanelPeople::onCallButtonClicked()
}
}
+void LLPanelPeople::onGroupCallButtonClicked()
+{
+ LLGroupActions::startCall(getCurrentItemID());
+}
+
void LLPanelPeople::onTeleportButtonClicked()
{
LLAvatarActions::offerTeleport(getCurrentItemID());
diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h
index f5cdc0935c..0d2bae1baf 100644
--- a/indra/newview/llpanelpeople.h
+++ b/indra/newview/llpanelpeople.h
@@ -100,6 +100,7 @@ private:
void onChatButtonClicked();
void onImButtonClicked();
void onCallButtonClicked();
+ void onGroupCallButtonClicked();
void onTeleportButtonClicked();
void onShareButtonClicked();
void onMoreButtonClicked();
diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp
index 0314642d9e..c1c10e6022 100644
--- a/indra/newview/llpanelpeoplemenus.cpp
+++ b/indra/newview/llpanelpeoplemenus.cpp
@@ -184,8 +184,6 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)
else if (item == std::string("can_call"))
{
bool result = false;
- int size = mUUIDs.size();
- std::cout << size << std::endl;
std::vector<LLUUID>::const_iterator
id = mUUIDs.begin(),
uuids_end = mUUIDs.end();
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
index 4d22d96072..751705dd57 100644
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
@@ -485,6 +485,18 @@ void LLPanelPicks::onOpen(const LLSD& key)
LLPanelProfileTab::onOpen(key);
}
+void LLPanelPicks::onClosePanel()
+{
+ if (mPanelClassifiedInfo)
+ {
+ onPanelClassifiedClose(mPanelClassifiedInfo);
+ }
+ if (mPanelPickInfo)
+ {
+ onPanelPickClose(mPanelPickInfo);
+ }
+}
+
void LLPanelPicks::onListCommit(const LLFlatListView* f_list)
{
// Make sure only one of the lists has selection.
@@ -769,6 +781,11 @@ void LLPanelPicks::onPanelPickSave(LLPanel* panel)
void LLPanelPicks::onPanelClassifiedSave(LLPanelClassifiedEdit* panel)
{
+ if(!panel->canClose())
+ {
+ return;
+ }
+
if(panel->isNew())
{
LLClassifiedItem* c_item = new LLClassifiedItem(getAvatarId(), panel->getClassifiedId());
diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h
index fd8a9e6938..1b2e35ca46 100644
--- a/indra/newview/llpanelpicks.h
+++ b/indra/newview/llpanelpicks.h
@@ -74,6 +74,8 @@ public:
/*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void onClosePanel();
+
void processProperties(void* data, EAvatarProcessorType type);
void updateData();
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
index 93e5b8fa15..5941487c7d 100644
--- a/indra/newview/llparticipantlist.cpp
+++ b/indra/newview/llparticipantlist.cpp
@@ -39,7 +39,6 @@
#include "llimview.h"
#include "llparticipantlist.h"
-#include "llavatarlist.h"
#include "llspeakers.h"
#include "llviewermenu.h"
#include "llvoiceclient.h"
@@ -49,11 +48,15 @@
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
#endif
-LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu/* = true*/):
+static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR;
+
+LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu/* = true*/,
+ bool exclude_agent /*= true*/):
mSpeakerMgr(data_source),
mAvatarList(avatar_list),
mSortOrder(E_SORT_BY_NAME)
, mParticipantListMenu(NULL)
+, mExcludeAgent(exclude_agent)
{
mSpeakerAddListener = new SpeakerAddListener(*this);
mSpeakerRemoveListener = new SpeakerRemoveListener(*this);
@@ -97,6 +100,7 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av
mModeratorList.insert(speakerp->mID);
}
}
+ // we need to exclude agent id for non group chat
mAvatarList->setDirty(true);
sort();
}
@@ -110,13 +114,16 @@ LLParticipantList::~LLParticipantList()
// It is possible Participant List will be re-created from LLCallFloater::onCurrentChannelChanged()
// See ticket EXT-3427
// hide menu before deleting it to stop enable and check handlers from triggering.
- if(mParticipantListMenu)
+ if(mParticipantListMenu && !LLApp::isExiting())
{
mParticipantListMenu->hide();
}
- delete mParticipantListMenu;
- mParticipantListMenu = NULL;
+ if (mParticipantListMenu)
+ {
+ delete mParticipantListMenu;
+ mParticipantListMenu = NULL;
+ }
}
void LLParticipantList::setSpeakingIndicatorsVisible(BOOL visible)
@@ -196,24 +203,18 @@ void LLParticipantList::setSortOrder(EParticipantSortOrder order)
}
}
-void LLParticipantList::refreshVoiceState()
+LLParticipantList::EParticipantSortOrder LLParticipantList::getSortOrder()
{
- LLSpeakerMgr::speaker_list_t speakers;
- mSpeakerMgr->getSpeakerList(&speakers, TRUE);
+ return mSortOrder;
+}
- for (LLSpeakerMgr::speaker_list_t::iterator iter = speakers.begin();
- iter != speakers.end(); ++iter)
+void LLParticipantList::updateRecentSpeakersOrder()
+{
+ if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder())
{
- LLSpeaker* speakerp = (*iter).get();
- const LLUUID& speaker_id = speakerp->mID;
- LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (mAvatarList->getItemByValue(speaker_id));
- if ( item )
- {
- // if voice is disabled for this speaker show non voice speakers as disabled
- bool is_in_voice = speakerp->mStatus > LLSpeaker::STATUS_VOICE_ACTIVE
- && speakerp->mStatus != LLSpeaker::STATUS_MUTED;
- item->setOnline(!is_in_voice);
- }
+ // Resort avatar list
+ mAvatarList->setDirty(true);
+ sort();
}
}
@@ -304,10 +305,24 @@ void LLParticipantList::sort()
if ( !mAvatarList )
return;
- // TODO: Implement more sorting orders after specs updating (EM)
switch ( mSortOrder ) {
case E_SORT_BY_NAME :
- mAvatarList->sortByName();
+ // if mExcludeAgent == true , then no need to keep agent on top of the list
+ if(mExcludeAgent)
+ {
+ mAvatarList->sortByName();
+ }
+ else
+ {
+ mAvatarList->setComparator(&AGENT_ON_TOP_NAME_COMPARATOR);
+ mAvatarList->sort();
+ }
+ break;
+ case E_SORT_BY_RECENT_SPEAKERS:
+ if (mSortByRecentSpeakers.isNull())
+ mSortByRecentSpeakers = new LLAvatarItemRecentSpeakerComparator(*this);
+ mAvatarList->setComparator(mSortByRecentSpeakers.get());
+ mAvatarList->sort();
break;
default :
llwarns << "Unrecognized sort order for " << mAvatarList->getName() << llendl;
@@ -317,7 +332,7 @@ void LLParticipantList::sort()
void LLParticipantList::addAvatarIDExceptAgent(std::vector<LLUUID>& existing_list, const LLUUID& avatar_id)
{
- if (gAgent.getID() == avatar_id) return;
+ if (mExcludeAgent && gAgent.getID() == avatar_id) return;
existing_list.push_back(avatar_id);
adjustParticipant(avatar_id);
@@ -385,6 +400,7 @@ LLContextMenu* LLParticipantList::LLParticipantListMenu::createMenu()
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
+ registrar.add("ParticipantList.Sort", boost::bind(&LLParticipantList::LLParticipantListMenu::sortParticipantList, this, _2));
registrar.add("ParticipantList.ToggleAllowTextChat", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleAllowTextChat, this, _2));
registrar.add("ParticipantList.ToggleMuteText", boost::bind(&LLParticipantList::LLParticipantListMenu::toggleMuteText, this, _2));
@@ -430,6 +446,24 @@ 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)
+{
+ std::string param = userdata.asString();
+ if ("sort_by_name" == param)
+ {
+ mParent.setSortOrder(E_SORT_BY_NAME);
+ }
+ else if ("sort_by_recent_speakers" == param)
+ {
+ mParent.setSortOrder(E_SORT_BY_RECENT_SPEAKERS);
+ }
}
void LLParticipantList::LLParticipantListMenu::toggleAllowTextChat(const LLSD& userdata)
@@ -538,7 +572,7 @@ void LLParticipantList::LLParticipantListMenu::moderateVoiceOtherParticipants(co
bool LLParticipantList::LLParticipantListMenu::enableContextMenuItem(const LLSD& userdata)
{
std::string item = userdata.asString();
- if (item == "can_mute_text")
+ if (item == "can_mute_text" || "can_block" == item)
{
return mUUIDs.front() != gAgentID;
}
@@ -599,8 +633,45 @@ bool LLParticipantList::LLParticipantListMenu::checkContextMenuItem(const LLSD&
{
return LLMuteList::getInstance()->isMuted(id, LLMute::flagVoiceChat);
}
+ else if(item == "is_sorted_by_name")
+ {
+ return E_SORT_BY_NAME == mParent.mSortOrder;
+ }
+ else if(item == "is_sorted_by_recent_speakers")
+ {
+ return E_SORT_BY_RECENT_SPEAKERS == mParent.mSortOrder;
+ }
return false;
}
+bool LLParticipantList::LLAvatarItemRecentSpeakerComparator::doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const
+{
+ if (mParent.mSpeakerMgr)
+ {
+ LLPointer<LLSpeaker> lhs = mParent.mSpeakerMgr->findSpeaker(avatar_item1->getAvatarId());
+ LLPointer<LLSpeaker> rhs = mParent.mSpeakerMgr->findSpeaker(avatar_item2->getAvatarId());
+ if ( lhs.notNull() && rhs.notNull() )
+ {
+ // Compare by last speaking time
+ if( lhs->mLastSpokeTime != rhs->mLastSpokeTime )
+ return ( lhs->mLastSpokeTime > rhs->mLastSpokeTime );
+ else if ( lhs->mSortIndex != rhs->mSortIndex )
+ return ( lhs->mSortIndex < rhs->mSortIndex );
+ }
+ else if ( lhs.notNull() )
+ {
+ // True if only avatar_item1 speaker info available
+ return true;
+ }
+ else if ( rhs.notNull() )
+ {
+ // False if only avatar_item2 speaker info available
+ return false;
+ }
+ }
+ // By default compare by name.
+ return LLAvatarItemNameComparator::doCompare(avatar_item1, avatar_item2);
+}
+
//EOF
diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h
index bc6c6c2b50..c4eb180917 100644
--- a/indra/newview/llparticipantlist.h
+++ b/indra/newview/llparticipantlist.h
@@ -34,6 +34,7 @@
#include "llevent.h"
#include "llpanelpeoplemenus.h"
#include "llimview.h"
+#include "llavatarlist.h" // for LLAvatarItemRecentSpeakerComparator
class LLSpeakerMgr;
class LLAvatarList;
@@ -43,24 +44,25 @@ class LLParticipantList
{
LOG_CLASS(LLParticipantList);
public:
- LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu = true);
+ LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu = true, bool exclude_agent = true);
~LLParticipantList();
void setSpeakingIndicatorsVisible(BOOL visible);
typedef enum e_participant_sort_oder {
E_SORT_BY_NAME = 0,
+ E_SORT_BY_RECENT_SPEAKERS = 1,
} EParticipantSortOrder;
/**
* Set and sort Avatarlist by given order
*/
void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME);
+ EParticipantSortOrder getSortOrder();
/**
- * Refreshes participants to display ones not in voice as disabled.
- * TODO: mantipov: probably should be moved into derived class for LLFloaterCall
+ * Refreshes the participant list if it's in sort by recent speaker order.
*/
- void refreshVoiceState();
+ void updateRecentSpeakersOrder();
protected:
/**
@@ -139,6 +141,7 @@ class LLParticipantList
bool enableContextMenuItem(const LLSD& userdata);
bool checkContextMenuItem(const LLSD& userdata);
+ void sortParticipantList(const LLSD& userdata);
void toggleAllowTextChat(const LLSD& userdata);
void toggleMute(const LLSD& userdata, U32 flags);
void toggleMuteText(const LLSD& userdata);
@@ -195,6 +198,21 @@ class LLParticipantList
void moderateVoiceOtherParticipants(const LLUUID& excluded_avatar_id, bool unmute);
};
+ /**
+ * Comparator for comparing avatar items by last spoken time
+ */
+ class LLAvatarItemRecentSpeakerComparator : public LLAvatarItemNameComparator, public LLRefCount
+ {
+ LOG_CLASS(LLAvatarItemRecentSpeakerComparator);
+ public:
+ LLAvatarItemRecentSpeakerComparator(LLParticipantList& parent):mParent(parent){};
+ virtual ~LLAvatarItemRecentSpeakerComparator() {};
+ protected:
+ virtual bool doCompare(const LLAvatarListItem* avatar_item1, const LLAvatarListItem* avatar_item2) const;
+ private:
+ LLParticipantList& mParent;
+ };
+
private:
void onAvatarListDoubleClicked(LLAvatarList* list);
void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param);
@@ -229,9 +247,17 @@ class LLParticipantList
LLParticipantListMenu* mParticipantListMenu;
EParticipantSortOrder mSortOrder;
+ /*
+ * This field manages an adding a new avatar_id in the mAvatarList
+ * If true, then agent_id wont be added into mAvatarList
+ * Also by default this field is controlling a sort procedure, @c sort()
+ */
+ bool mExcludeAgent;
// boost::connections
boost::signals2::connection mAvatarListDoubleClickConnection;
boost::signals2::connection mAvatarListRefreshConnection;
boost::signals2::connection mAvatarListReturnConnection;
+
+ LLPointer<LLAvatarItemRecentSpeakerComparator> mSortByRecentSpeakers;
};
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index 26694ac433..26368fb0a8 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -422,8 +422,8 @@ void LLPreviewTexture::updateDimensions()
if (mShowKeepDiscard || mCopyToInv) { //mCopyToInvBtn
// add space for buttons
- view_height += BTN_HEIGHT + CLIENT_RECT_VPAD;
- button_height = BTN_HEIGHT + PREVIEW_PAD;
+ view_height += (BTN_HEIGHT + CLIENT_RECT_VPAD) * 3;
+ button_height = (BTN_HEIGHT + PREVIEW_PAD) * 3;
}
view_width = llmax(view_width, getMinWidth());
diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp
index 5f6b210767..7a48f890e0 100644
--- a/indra/newview/llprogressview.cpp
+++ b/indra/newview/llprogressview.cpp
@@ -72,10 +72,12 @@ const S32 ANIMATION_FRAMES = 1; //13;
LLProgressView::LLProgressView(const LLRect &rect)
: LLPanel(),
mPercentDone( 0.f ),
- mMouseDownInActiveArea( false )
+ mMouseDownInActiveArea( false ),
+ mUpdateEvents("LLProgressView")
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_progress.xml");
reshape(rect.getWidth(), rect.getHeight());
+ mUpdateEvents.listen("self", boost::bind(&LLProgressView::handleUpdate, this, _1));
}
BOOL LLProgressView::postBuild()
@@ -260,3 +262,26 @@ void LLProgressView::onClickMessage(void* data)
}
}
}
+
+bool LLProgressView::handleUpdate(const LLSD& event_data)
+{
+ LLSD message = event_data.get("message");
+ LLSD desc = event_data.get("desc");
+ LLSD percent = event_data.get("percent");
+
+ if(message.isDefined())
+ {
+ setMessage(message.asString());
+ }
+
+ if(desc.isDefined())
+ {
+ setText(desc.asString());
+ }
+
+ if(percent.isDefined())
+ {
+ setPercent(percent.asReal());
+ }
+ return false;
+}
diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h
index 865646c85d..6853674d88 100644
--- a/indra/newview/llprogressview.h
+++ b/indra/newview/llprogressview.h
@@ -35,6 +35,7 @@
#include "llpanel.h"
#include "llframetimer.h"
+#include "llevents.h"
class LLImageRaw;
class LLButton;
@@ -75,7 +76,12 @@ protected:
LLRect mOutlineRect;
bool mMouseDownInActiveArea;
+ // The LLEventStream mUpdateEvents depends upon this class being a singleton
+ // to avoid pump name conflicts.
static LLProgressView* sInstance;
+ LLEventStream mUpdateEvents;
+
+ bool handleUpdate(const LLSD& event_data);
};
#endif // LL_LLPROGRESSVIEW_H
diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp
index 5edc4804ca..90214a1bd7 100644
--- a/indra/newview/llspeakbutton.cpp
+++ b/indra/newview/llspeakbutton.cpp
@@ -61,7 +61,9 @@ void LLSpeakButton::draw()
{
// gVoiceClient is the authoritative global source of info regarding our open-mic state, we merely reflect that state.
bool openmic = gVoiceClient->getUserPTTState();
- mSpeakBtn->setToggleState(openmic);
+ bool voiceenabled = gVoiceClient->voiceEnabled();
+ mSpeakBtn->setToggleState(openmic && voiceenabled);
+ mOutputMonitor->setIsMuted(!voiceenabled);
LLUICtrl::draw();
}
@@ -119,6 +121,9 @@ LLSpeakButton::LLSpeakButton(const Params& p)
// never show "muted" because you can't mute yourself
mOutputMonitor->setIsMuted(false);
mOutputMonitor->setIsAgentControl(true);
+
+ //*TODO find a better place to do that
+ LLVoiceChannel::setCurrentVoiceChannelChangedCallback(boost::bind(&LLCallFloater::sOnCurrentChannelChanged, _1));
}
LLSpeakButton::~LLSpeakButton()
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 3861a96355..91b417c61f 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -630,8 +630,6 @@ void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id)
void LLIMSpeakerMgr::moderateVoiceParticipant(const LLUUID& avatar_id, bool unmute)
{
- if (gAgentID == avatar_id) return; // do not process myself
-
LLPointer<LLSpeaker> speakerp = findSpeaker(avatar_id);
if (!speakerp) return;
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 73e7d99815..eb2275bff0 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1082,6 +1082,17 @@ bool idle_startup()
credentials["passwd"] = gPassword;
login->connect(credentials);
+ LLStartUp::setStartupState( STATE_LOGIN_CURL_UNSTUCK );
+ return FALSE;
+ }
+
+ if(STATE_LOGIN_CURL_UNSTUCK == LLStartUp::getStartupState())
+ {
+ // If we get here we have gotten past the potential stall
+ // in curl, so take "may appear frozen" out of progress bar. JC
+ auth_desc = LLTrans::getString("LoginInProgressNoFrozen");
+ set_startup_status(progress, auth_desc, auth_message);
+
LLStartUp::setStartupState( STATE_LOGIN_PROCESS_RESPONSE );
return FALSE;
}
@@ -1168,16 +1179,6 @@ bool idle_startup()
show_connect_box = true;
}
}
- else
- {
- // Still waiting for response.
- // *TODO:Mani - Actually check for login progress.
- // If we get here we have gotten past the potential stall
- // in curl, so take "may appear frozen" out of progress bar. JC
- auth_desc = LLTrans::getString("LoginInProgressNoFrozen");
- set_startup_status(progress, auth_desc, auth_message);
- }
-
return FALSE;
}
@@ -2703,6 +2704,7 @@ std::string LLStartUp::startupStateToString(EStartupState state)
RTNENUM( STATE_LOGIN_WAIT );
RTNENUM( STATE_LOGIN_CLEANUP );
RTNENUM( STATE_LOGIN_AUTH_INIT );
+ RTNENUM( STATE_LOGIN_CURL_UNSTUCK );
RTNENUM( STATE_LOGIN_PROCESS_RESPONSE );
RTNENUM( STATE_WORLD_INIT );
RTNENUM( STATE_MULTIMEDIA_INIT );
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index ab11b42e74..92fe9521d3 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -55,6 +55,7 @@ typedef enum {
STATE_LOGIN_WAIT, // Wait for user input at login screen
STATE_LOGIN_CLEANUP, // Get rid of login screen and start login
STATE_LOGIN_AUTH_INIT, // Start login to SL servers
+ STATE_LOGIN_CURL_UNSTUCK, // Update progress to remove "SL appears frozen" msg.
STATE_LOGIN_PROCESS_RESPONSE, // Check authentication reply
STATE_WORLD_INIT, // Start building the world
STATE_MULTIMEDIA_INIT, // Init the rest of multimedia library
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 3769ddb1cc..8c6ea59407 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -48,6 +48,8 @@
#include "llchiclet.h"
#include "lltoastpanel.h"
#include "llnotificationmanager.h"
+#include "llnotificationsutil.h"
+#include "llspeakers.h"
//---------------------------------------------------------------------------------
LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key),
@@ -350,6 +352,9 @@ LLIMWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID&
}
// Initialize chiclet.
+ mChiclet->setRect(LLRect(5, 28, 30, 3)); // *HACK: workaround for (EXT-3599)
+ mChiclet->setChicletSizeChangedCallback(boost::bind(&LLIMWellWindow::RowPanel::onChicletSizeChanged, this, mChiclet, _2));
+ mChiclet->enableCounterControl(true);
mChiclet->setCounter(chicletCounter);
mChiclet->setSessionId(sessionId);
mChiclet->setIMSessionName(name);
@@ -364,6 +369,16 @@ LLIMWellWindow::RowPanel::RowPanel(const LLSysWellWindow* parent, const LLUUID&
}
//---------------------------------------------------------------------------------
+void LLIMWellWindow::RowPanel::onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param)
+{
+ LLTextBox* text = getChild<LLTextBox>("contact_name");
+ S32 new_text_left = mChiclet->getRect().mRight + CHICLET_HPAD;
+ LLRect text_rect = text->getRect();
+ text_rect.mLeft = new_text_left;
+ text->setRect(text_rect);
+}
+
+//---------------------------------------------------------------------------------
LLIMWellWindow::RowPanel::~RowPanel()
{
}
@@ -610,6 +625,23 @@ void LLNotificationWellWindow::addItem(LLSysWellItem::Params p)
}
}
+void LLNotificationWellWindow::closeAll()
+{
+ // Need to clear notification channel, to add storable toasts into the list.
+ clearScreenChannels();
+ std::vector<LLPanel*> items;
+ mMessageList->getItems(items);
+ for (std::vector<LLPanel*>::iterator
+ iter = items.begin(),
+ iter_end = items.end();
+ iter != iter_end; ++iter)
+ {
+ LLSysWellItem* sys_well_item = dynamic_cast<LLSysWellItem*>(*iter);
+ if (sys_well_item)
+ onItemClose(sys_well_item);
+ }
+}
+
//////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
void LLNotificationWellWindow::initChannel()
@@ -713,9 +745,6 @@ void LLIMWellWindow::sessionAdded(const LLUUID& session_id,
{
if (mMessageList->getItemByValue(session_id)) return;
- // For im sessions started as voice call chiclet gets created on the first incoming message
- if (gIMMgr->isVoiceCall(session_id)) return;
-
if (!gIMMgr->hasSession(session_id)) return;
addIMRow(session_id, 0, name, other_participant_id);
@@ -874,21 +903,80 @@ bool LLIMWellWindow::hasIMRow(const LLUUID& session_id)
return mMessageList->getItemByValue(session_id);
}
-void LLIMWellWindow::onNewIM(const LLSD& data)
+void LLIMWellWindow::closeAll()
{
- LLUUID from_id = data["from_id"];
- if (from_id.isNull() || gAgentID == from_id) return;
+ // Generate an ignorable alert dialog if there is an active voice IM sesion
+ bool need_confirmation = false;
+ const LLIMModel& im_model = LLIMModel::instance();
+ std::vector<LLSD> values;
+ mMessageList->getValues(values);
+ for (std::vector<LLSD>::iterator
+ iter = values.begin(),
+ iter_end = values.end();
+ iter != iter_end; ++iter)
+ {
+ LLIMSpeakerMgr* speaker_mgr = im_model.getSpeakerManager(*iter);
+ if (speaker_mgr && speaker_mgr->isVoiceActive())
+ {
+ need_confirmation = true;
+ break;
+ }
+ }
+ if ( need_confirmation )
+ {
+ //Bring up a confirmation dialog
+ LLNotificationsUtil::add
+ ("ConfirmCloseAll", LLSD(), LLSD(),
+ boost::bind(&LLIMWellWindow::confirmCloseAll, this, _1, _2));
+ }
+ else
+ {
+ closeAllImpl();
+ }
+}
- LLUUID session_id = data["session_id"];
- if (session_id.isNull()) return;
+void LLIMWellWindow::closeAllImpl()
+{
+ std::vector<LLSD> values;
+ mMessageList->getValues(values);
- if (!gIMMgr->isVoiceCall(session_id)) return;
+ for (std::vector<LLSD>::iterator
+ iter = values.begin(),
+ iter_end = values.end();
+ iter != iter_end; ++iter)
+ {
+ LLPanel* panel = mMessageList->getItemByValue(*iter);
- if (hasIMRow(session_id)) return;
+ RowPanel* im_panel = dynamic_cast <RowPanel*> (panel);
+ if (im_panel)
+ {
+ gIMMgr->leaveSession(*iter);
+ continue;
+ }
- //first real message, time to create chiclet
- addIMRow(session_id);
+ ObjectRowPanel* obj_panel = dynamic_cast <ObjectRowPanel*> (panel);
+ if (obj_panel)
+ {
+ LLScriptFloaterManager::instance()
+ .removeNotificationByObjectId(*iter);
+ }
+ }
}
+bool LLIMWellWindow::confirmCloseAll(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ switch(option)
+ {
+ case 0:
+ {
+ closeAllImpl();
+ return true;
+ }
+ default:
+ break;
+ }
+ return false;
+}
// EOF
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index 736b1b9fb4..7030f4b427 100644
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -147,6 +147,9 @@ public:
// Operating with items
void addItem(LLSysWellItem::Params p);
+ // Closes all notifications and removes them from the Notification Well
+ void closeAll();
+
protected:
/*virtual*/ const std::string& getAnchorViewName() { return NOTIFICATION_WELL_ANCHOR_NAME; }
@@ -188,14 +191,14 @@ public:
/*virtual*/ void sessionRemoved(const LLUUID& session_id);
/*virtual*/ void sessionIDUpdated(const LLUUID& old_session_id, const LLUUID& new_session_id);
- void onNewIM(const LLSD& data);
-
void addObjectRow(const LLUUID& object_id, bool new_message = false);
void removeObjectRow(const LLUUID& object_id);
void addIMRow(const LLUUID& session_id);
bool hasIMRow(const LLUUID& session_id);
+ void closeAll();
+
protected:
/*virtual*/ const std::string& getAnchorViewName() { return IM_WELL_ANCHOR_NAME; }
@@ -205,7 +208,8 @@ private:
void addIMRow(const LLUUID& sessionId, S32 chicletCounter, const std::string& name, const LLUUID& otherParticipantId);
void delIMRow(const LLUUID& sessionId);
-
+ bool confirmCloseAll(const LLSD& notification, const LLSD& response);
+ void closeAllImpl();
/**
* Scrolling row panel.
@@ -220,6 +224,8 @@ private:
void onMouseLeave(S32 x, S32 y, MASK mask);
BOOL handleMouseDown(S32 x, S32 y, MASK mask);
private:
+ static const S32 CHICLET_HPAD = 10;
+ void onChicletSizeChanged(LLChiclet* ctrl, const LLSD& param);
void onClosePanel();
public:
LLIMChiclet* mChiclet;
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 83e0b53960..e80dafe245 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -158,7 +158,7 @@ public:
void callbackHttpGet(const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer,
- bool last_block, bool success);
+ bool partial, bool success);
void callbackCacheRead(bool success, LLImageFormatted* image,
S32 imagesize, BOOL islocal);
void callbackCacheWrite(bool success);
@@ -316,7 +316,7 @@ public:
if (HTTP_OK <= status && status < HTTP_MULTIPLE_CHOICES)
{
success = true;
- if (HTTP_PARTIAL_CONTENT == status) // partial information (i.e. last block)
+ if (HTTP_PARTIAL_CONTENT == status) // partial information
{
partial = true;
}
@@ -882,8 +882,18 @@ bool LLTextureFetchWorker::doWork(S32 param)
++mHTTPFailCount;
if (mHTTPFailCount >= max_attempts)
{
- resetFormattedData();
- return true; // failed
+ if (cur_size > 0)
+ {
+ // Use available data
+ mLoadedDiscard = mFormattedImage->getDiscardLevel();
+ mState = DECODE_IMAGE;
+ return false;
+ }
+ else
+ {
+ resetFormattedData();
+ return true; // failed
+ }
}
else
{
@@ -1207,7 +1217,7 @@ bool LLTextureFetchWorker::processSimulatorPackets()
void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
const LLIOPipe::buffer_ptr_t& buffer,
- bool last_block, bool success)
+ bool partial, bool success)
{
LLMutexLock lock(&mWorkMutex);
@@ -1236,7 +1246,7 @@ void LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
mBuffer = new U8[data_size];
buffer->readAfter(channels.in(), NULL, mBuffer, data_size);
mBufferSize += data_size;
- if (data_size < mRequestedSize || last_block == true)
+ if (data_size < mRequestedSize && mRequestedDiscard == 0)
{
mHaveAllData = TRUE;
}
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index 9573b884eb..98731f90f4 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -412,7 +412,7 @@ void LLGLTexMemBar::draw()
F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ;
F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ;
S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
- S32 h_offset = (S32)((texture_bar_height + 2.5f) * mTextureView->mNumTextureBars + 2.5f);
+ S32 v_offset = (S32)((texture_bar_height + 2.5f) * mTextureView->mNumTextureBars + 2.5f);
//----------------------------------------------------------------------------
LLGLSUIDefault gls_ui;
LLColor4 text_color(1.f, 1.f, 1.f, 0.75f);
@@ -428,14 +428,14 @@ void LLGLTexMemBar::draw()
cache_usage, cache_max_usage);
//, cache_entries, cache_max_entries
- LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, h_offset + line_height*3,
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*3,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
//----------------------------------------------------------------------------
#if 0
S32 bar_left = 400;
S32 bar_width = 200;
- S32 top = line_height*3 - 2 + h_offset;
+ S32 top = line_height*3 - 2 + v_offset;
S32 bottom = top - 6;
S32 left = bar_left;
S32 right = left + bar_width;
@@ -494,18 +494,18 @@ void LLGLTexMemBar::draw()
#endif
//----------------------------------------------------------------------------
- text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d RAW:%d HTP:%d CRE:%d",
+ text = llformat("Textures: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d RAW:%d HTP:%d DEC:%d CRE:%d",
gTextureList.getNumImages(),
LLAppViewer::getTextureFetch()->getNumRequests(), LLAppViewer::getTextureFetch()->getNumDeletes(),
LLAppViewer::getTextureFetch()->mPacketCount, LLAppViewer::getTextureFetch()->mBadPacketCount,
LLAppViewer::getTextureCache()->getNumReads(), LLAppViewer::getTextureCache()->getNumWrites(),
LLLFSThread::sLocal->getPending(),
- LLAppViewer::getImageDecodeThread()->getPending(),
LLImageRaw::sRawImageCount,
LLAppViewer::getTextureFetch()->getNumHTTPRequests(),
+ LLAppViewer::getImageDecodeThread()->getPending(),
gTextureList.mCreateTextureList.size());
- LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, h_offset + line_height*2,
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*2,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
@@ -515,40 +515,40 @@ void LLGLTexMemBar::draw()
color = bandwidth > max_bandwidth ? LLColor4::red : bandwidth > max_bandwidth*.75f ? LLColor4::yellow : text_color;
color[VALPHA] = text_color[VALPHA];
text = llformat("BW:%.0f/%.0f",bandwidth, max_bandwidth);
- LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, line_height*2,
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, left, v_offset + line_height*2,
color, LLFontGL::LEFT, LLFontGL::TOP);
S32 dx1 = 0;
if (LLAppViewer::getTextureFetch()->mDebugPause)
{
- LLFontGL::getFontMonospace()->renderUTF8(std::string("!"), 0, title_x1, h_offset + line_height,
+ LLFontGL::getFontMonospace()->renderUTF8(std::string("!"), 0, title_x1, v_offset + line_height,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
dx1 += 8;
}
if (mTextureView->mFreezeView)
{
- LLFontGL::getFontMonospace()->renderUTF8(std::string("*"), 0, title_x1, h_offset + line_height,
+ LLFontGL::getFontMonospace()->renderUTF8(std::string("*"), 0, title_x1, v_offset + line_height,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
dx1 += 8;
}
if (mTextureView->mOrderFetch)
{
- LLFontGL::getFontMonospace()->renderUTF8(title_string1b, 0, title_x1+dx1, h_offset + line_height,
+ LLFontGL::getFontMonospace()->renderUTF8(title_string1b, 0, title_x1+dx1, v_offset + line_height,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
}
else
{
- LLFontGL::getFontMonospace()->renderUTF8(title_string1a, 0, title_x1+dx1, h_offset + line_height,
+ LLFontGL::getFontMonospace()->renderUTF8(title_string1a, 0, title_x1+dx1, v_offset + line_height,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
}
- LLFontGL::getFontMonospace()->renderUTF8(title_string2, 0, title_x2, h_offset + line_height,
+ LLFontGL::getFontMonospace()->renderUTF8(title_string2, 0, title_x2, v_offset + line_height,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
- LLFontGL::getFontMonospace()->renderUTF8(title_string3, 0, title_x3, h_offset + line_height,
+ LLFontGL::getFontMonospace()->renderUTF8(title_string3, 0, title_x3, v_offset + line_height,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
- LLFontGL::getFontMonospace()->renderUTF8(title_string4, 0, title_x4, h_offset + line_height,
+ LLFontGL::getFontMonospace()->renderUTF8(title_string4, 0, title_x4, v_offset + line_height,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
}
diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h
index 875ab82c54..43e105a4f1 100644
--- a/indra/newview/lltoastalertpanel.h
+++ b/indra/newview/lltoastalertpanel.h
@@ -37,6 +37,7 @@
#include "llfloater.h"
#include "llui.h"
#include "llnotificationptr.h"
+#include "llerror.h"
class LLButton;
class LLCheckBoxCtrl;
@@ -53,6 +54,7 @@ class LLLineEditor;
class LLToastAlertPanel
: public LLToastPanel
{
+ LOG_CLASS(LLToastAlertPanel);
public:
typedef bool (*display_callback_t)(S32 modal);
diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp
index 7befb87248..347399f239 100644
--- a/indra/newview/lltransientfloatermgr.cpp
+++ b/indra/newview/lltransientfloatermgr.cpp
@@ -37,6 +37,7 @@
#include "llrootview.h"
#include "llviewerwindow.h"
#include "lldockablefloater.h"
+#include "llmenugl.h"
LLTransientFloaterMgr::LLTransientFloaterMgr()
@@ -87,6 +88,13 @@ void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
for (controls_set_t::iterator it = mControlsSet.begin(); it
!= mControlsSet.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())
{
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 68a5147bc7..3dac0ee452 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -713,7 +713,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
gBumpImageList.updateImages(); // must be called before gTextureList version so that it's textures are thrown out first.
F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time
- max_image_decode_time = llclamp(max_image_decode_time, 0.001f, 0.005f ); // min 1ms/frame, max 5ms/frame)
+ max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame)
gTextureList.updateImages(max_image_decode_time);
//remove dead textures from GL
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 35c9a1d367..00db11a767 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -94,6 +94,7 @@
#include "llfloaterregioninfo.h"
#include "llfloaterreporter.h"
#include "llfloaterscriptdebug.h"
+#include "llfloaterscriptlimits.h"
#include "llfloatersellland.h"
#include "llfloatersettingsdebug.h"
#include "llfloatersnapshot.h"
@@ -241,6 +242,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("script_debug", "floater_script_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebug>);
LLFloaterReg::add("script_debug_output", "floater_script_debug_panel.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebugOutput>);
LLFloaterReg::add("script_floater", "floater_script.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLScriptFloater>);
+ LLFloaterReg::add("script_limits", "floater_script_limits.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptLimits>);
LLFloaterReg::add("sell_land", "floater_sell_land.xml", &LLFloaterSellLand::buildFloater);
LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>);
LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 5cfd587bd1..23bcca9603 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -439,6 +439,12 @@ void init_menus()
// menu holder appears on top of menu bar so you can see the menu title
// flash when an item is triggered (the flash occurs in the holder)
gViewerWindow->getRootView()->addChild(gMenuHolder);
+
+ // This removes tool tip view from main view and adds it
+ // to root view in front of menu holder.
+ // Otherwise tool tips for menu items would be overlapped by menu, since
+ // main view is behind of menu holder now.
+ gViewerWindow->getRootView()->addChild(gToolTipView);
gViewerWindow->setMenuBackgroundColor(false,
LLViewerLogin::getInstance()->isInProductionGrid());
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index ea40f2aae1..6a31bbfa1e 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1078,6 +1078,28 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,_4,this));
}
+ // *NOTE dzaporozhan
+ // Restored from viewer-1-23 to fix EXT-3520
+ // Saves Group Notice Attachments to inventory.
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_ImprovedInstantMessage);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_MessageBlock);
+ msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
+ msg->addUUIDFast(_PREHASH_ToAgentID, mFromID);
+ msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
+ msg->addUUIDFast(_PREHASH_ID, mTransactionID);
+ msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
+ std::string name;
+ LLAgentUI::buildFullname(name);
+ msg->addStringFast(_PREHASH_FromAgentName, name);
+ msg->addStringFast(_PREHASH_Message, "");
+ msg->addU32Fast(_PREHASH_ParentEstateID, 0);
+ msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null);
+ msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
+
std::string from_string; // Used in the pop-up.
std::string chatHistory_string; // Used in chat history.
@@ -1129,6 +1151,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD&
// Show falls through to accept.
case IOR_ACCEPT:
+ msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1));
+ msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData), sizeof(mFolderID.mData));
+ msg->sendReliable(mHost);
+
//don't spam them if they are getting flooded
if (check_offer_throttle(mFromName, true))
{
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index d1c9840a97..77d2d493bd 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1421,6 +1421,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
setCapability("Seed", url);
LLSD capabilityNames = LLSD::emptyArray();
+
+ capabilityNames.append("AttachmentResources");
capabilityNames.append("ChatSessionRequest");
capabilityNames.append("CopyInventoryFromNotecard");
capabilityNames.append("DispatchRegionInfo");
@@ -1434,6 +1436,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("GetTexture");
capabilityNames.append("GroupProposalBallot");
capabilityNames.append("HomeLocation");
+ capabilityNames.append("LandResources");
capabilityNames.append("MapLayer");
capabilityNames.append("MapLayerGod");
capabilityNames.append("NewFileAgentInventory");
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index a1a3bc6d6a..8059f866ba 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -656,9 +656,9 @@ void update_statistics(U32 frame_count)
gObjectBits = 0;
// gDecodedBits = 0;
- // Only update texture stats ones per second so that they are less noisy
+ // Only update texture stats periodically so that they are less noisy
{
- static const F32 texture_stats_freq = 1.f;
+ static const F32 texture_stats_freq = 10.f;
static LLFrameTimer texture_stats_timer;
if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq)
{
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index b45148a186..ae9db94000 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -1497,7 +1497,8 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
{
priority += 10000000.f;
}
- else if(mAdditionalDecodePriority > 0.0f)
+
+ if(mAdditionalDecodePriority > 0.0f)
{
// 1-9
S32 additional_priority = (S32)(1.0f + mAdditionalDecodePriority*8.0f + .5f); // round
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index 60a2c3b638..69d2458217 100644
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -316,8 +316,6 @@ void LLVoiceChannel::activate()
}
}
- sCurrentVoiceChannelChangedSignal(this->mSessionID);
-
if (mState == STATE_NO_CHANNEL_INFO)
{
// responsible for setting status to active
@@ -327,6 +325,9 @@ void LLVoiceChannel::activate()
{
setState(STATE_CALL_STARTED);
}
+
+ //do not send earlier, channel should be initialized, should not be in STATE_NO_CHANNEL_INFO state
+ sCurrentVoiceChannelChangedSignal(this->mSessionID);
}
void LLVoiceChannel::getChannelInfo()
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index f98aa361e0..70bfc67523 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -134,9 +134,21 @@ public:
virtual F64 getMediaInterest() const
{
- F64 tmp = mObject->getTotalMediaInterest();
- return (tmp < 0.0) ? mObject->getPixelArea() : tmp;
+ F64 interest = mObject->getTotalMediaInterest();
+ if (interest < (F64)0.0)
+ {
+ // media interest not valid yet, try pixel area
+ interest = mObject->getPixelArea();
+ // HACK: force recalculation of pixel area if interest is the "magic default" of 1024.
+ if (interest == 1024.f)
+ {
+ const_cast<LLVOVolume*>(static_cast<LLVOVolume*>(mObject))->setPixelAreaAndAngle(gAgent);
+ interest = mObject->getPixelArea();
+ }
+ }
+ return interest;
}
+
virtual bool isInterestingEnough() const
{
return LLViewerMedia::isInterestingEnough(mObject, getMediaInterest());
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index 73b5222ee3..4f4fc83819 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -6352,7 +6352,8 @@ void LLPipeline::renderDeferredLighting()
mDeferredLight[0].flush();
- if (gSavedSettings.getBOOL("RenderDeferredBlurLight"))
+ if (gSavedSettings.getBOOL("RenderDeferredBlurLight") &&
+ gSavedSettings.getBOOL("RenderDeferredGI"))
{
LLFastTimer ftm(FTM_EDGE_DETECTION);
//get edge map
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 9212d3d87b..8a9126208a 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -50,8 +50,10 @@ with the same filename but different name
<texture name="Arrow_Right_Off" file_name="navbar/Arrow_Right_Off.png" preload="true" />
<texture name="Arrow_Right_Press" file_name="navbar/Arrow_Right_Press.png" preload="true" />
+<!--
<texture name="Arrow_Left" file_name="widgets/Arrow_Left.png" preload="true" />
<texture name="Arrow_Right" file_name="widgets/Arrow_Right.png" preload="true" />
+-->
<texture name="Arrow_Small_Up" file_name="widgets/Arrow_Small_Up.png" preload="true" />
<texture name="Arrow_Small_Left" file_name="widgets/Arrow_Small_Left.png" preload="true" />
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 81e6503407..cc955369e2 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -4,6 +4,7 @@
height="420"
layout="topleft"
name="floaterland"
+ help_topic="floaterland"
save_rect="true"
title="ABOUT LAND"
width="490">
@@ -274,7 +275,7 @@
<button
enabled="false"
follows="left|top"
- height="23S"
+ height="23"
label="Deed"
layout="topleft"
left_pad="2"
@@ -472,6 +473,16 @@
top="328"
width="100" />
<button
+ enabled="true"
+ follows="left|top"
+ height="23"
+ label="Script Info"
+ layout="topleft"
+ left="10"
+ name="Scripts..."
+ top="352"
+ width="100" />
+ <button
enabled="false"
follows="left|top"
height="23"
diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml
index 153a9c2c45..94686f0bb0 100644
--- a/indra/newview/skins/default/xui/en/floater_customize.xml
+++ b/indra/newview/skins/default/xui/en/floater_customize.xml
@@ -55,6 +55,7 @@
label="Shape"
layout="topleft"
name="Shape"
+ help_topic="customize_shape_tab"
width="400">
<icon
follows="top|right"
@@ -340,6 +341,7 @@ scratch and wear it.
label="Skin"
layout="topleft"
name="Skin"
+ help_topic="customize_skin_tab"
width="400">
<icon
follows="top|right"
@@ -591,6 +593,7 @@ scratch and wear it.
label="Hair"
layout="topleft"
name="Hair"
+ help_topic="customize_hair_tab"
width="400">
<icon
follows="top|right"
@@ -812,6 +815,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Eyes"
+ help_topic="customize_eyes_tab"
top_delta="0"
width="389">
<icon
@@ -1010,6 +1014,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Shirt"
+ help_topic="customize_shirt_tab"
top_delta="0"
width="389">
<icon
@@ -1215,6 +1220,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Pants"
+ help_topic="customize_pants_tab"
top_delta="0"
width="389">
<icon
@@ -1420,6 +1426,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Shoes"
+ help_topic="customize_shoes_tab"
top_delta="0"
width="389">
<icon
@@ -1625,6 +1632,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Socks"
+ help_topic="customize_socks_tab"
top_delta="0"
width="389">
<icon
@@ -1830,6 +1838,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Jacket"
+ help_topic="customize_jacket_tab"
top_delta="0"
width="389">
<icon
@@ -2047,6 +2056,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Gloves"
+ help_topic="customize_gloves_tab"
top_delta="0"
width="389">
<icon
@@ -2252,6 +2262,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Undershirt"
+ help_topic="customize_undershirt_tab"
top_delta="0"
width="389">
<icon
@@ -2457,6 +2468,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Underpants"
+ help_topic="customize_underpants_tab"
top_delta="0"
width="389">
<icon
@@ -2662,6 +2674,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Skirt"
+ help_topic="customize_skirt_tab"
top_delta="0"
width="389">
<icon
@@ -2867,6 +2880,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Alpha"
+ help_topic="customize_alpha_tab"
top_delta="0"
width="389">
<icon
@@ -3154,6 +3168,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Tattoo"
+ help_topic="customize_tattoo_tab"
top_delta="0"
width="389">
<icon
@@ -3381,6 +3396,16 @@ scratch and wear it.
</scroll_container>
<button
bottom="598"
+ follows="right|left"
+ height="20"
+ label="Script Info"
+ label_selected="Script Info"
+ layout="topleft"
+ name="script_info"
+ left="2"
+ width="98" />
+ <button
+ bottom="598"
follows="right|bottom"
height="23"
label="Make Outfit"
diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml
index 2f26e5d0c1..15655a920e 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences.xml
@@ -7,6 +7,7 @@
height="460"
layout="topleft"
name="Preferences"
+ help_topic="preferences"
single_instance="true"
title="PREFERENCES"
width="620">
diff --git a/indra/newview/skins/default/xui/en/floater_preview_texture.xml b/indra/newview/skins/default/xui/en/floater_preview_texture.xml
index abc30c335c..552902d1d9 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_texture.xml
@@ -4,13 +4,13 @@
auto_tile="true"
can_resize="true"
follows="left|top"
- height="313"
+ height="350"
layout="topleft"
- min_height="120"
- min_width="320"
+ min_height="200"
+ min_width="370"
name="preview_texture"
help_topic="preview_texture"
- width="320">
+ width="370">
<floater.string
name="Title">
Texture: [NAME]
diff --git a/indra/newview/skins/default/xui/en/floater_script_limits.xml b/indra/newview/skins/default/xui/en/floater_script_limits.xml
new file mode 100644
index 0000000000..98c44ad1b3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_script_limits.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="570"
+ help_topic="scriptlimits"
+ layout="topleft"
+ name="scriptlimits"
+ save_rect="true"
+ title="SCRIPT INFORMATION"
+ width="480">
+ <tab_container
+ bottom="555"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="1"
+ name="scriptlimits_panels"
+ right="-1"
+ tab_position="top"
+ top="20" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_search.xml b/indra/newview/skins/default/xui/en/floater_search.xml
index 9c1a5499db..5a9e2ebe6e 100644
--- a/indra/newview/skins/default/xui/en/floater_search.xml
+++ b/indra/newview/skins/default/xui/en/floater_search.xml
@@ -4,8 +4,8 @@
can_resize="true"
height="646"
layout="topleft"
- min_height="140"
- min_width="467"
+ min_height="646"
+ min_width="670"
name="floater_search"
help_topic="floater_search"
save_rect="true"
diff --git a/indra/newview/skins/default/xui/en/floater_water.xml b/indra/newview/skins/default/xui/en/floater_water.xml
index 7f31692ad9..32739ac953 100644
--- a/indra/newview/skins/default/xui/en/floater_water.xml
+++ b/indra/newview/skins/default/xui/en/floater_water.xml
@@ -4,6 +4,7 @@
height="240"
layout="topleft"
name="Water Floater"
+ help_topic="water_floater"
save_rect="true"
title="ADVANCED WATER EDITOR"
width="700">
diff --git a/indra/newview/skins/default/xui/en/menu_im_well_button.xml b/indra/newview/skins/default/xui/en/menu_im_well_button.xml
new file mode 100644
index 0000000000..f8dfba91ff
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_im_well_button.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="IM Well Button Context Menu">
+ <menu_item_call
+ label="Close All"
+ layout="topleft"
+ name="Close All">
+ <menu_item_call.on_click
+ function="IMWellChicletMenu.Action"
+ parameter="close all" />
+ <menu_item_call.on_enable
+ function="IMWellChicletMenu.EnableItem"
+ parameter="can close all" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_notification_well_button.xml b/indra/newview/skins/default/xui/en/menu_notification_well_button.xml
new file mode 100644
index 0000000000..263ac40f4e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_notification_well_button.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<context_menu
+ layout="topleft"
+ name="Notification Well Button Context Menu">
+ <menu_item_call
+ label="Close All"
+ layout="topleft"
+ name="Close All">
+ <menu_item_call.on_click
+ function="NotificationWellChicletMenu.Action"
+ parameter="close all" />
+ <menu_item_call.on_enable
+ function="NotificationWellChicletMenu.EnableItem"
+ parameter="can close all" />
+ </menu_item_call>
+</context_menu>
diff --git a/indra/newview/skins/default/xui/en/menu_participant_list.xml b/indra/newview/skins/default/xui/en/menu_participant_list.xml
index 449202aaaa..31263fbea8 100644
--- a/indra/newview/skins/default/xui/en/menu_participant_list.xml
+++ b/indra/newview/skins/default/xui/en/menu_participant_list.xml
@@ -2,7 +2,29 @@
<context_menu
layout="topleft"
name="Participant List Context Menu">
- <menu_item_call
+ <menu_item_check
+ label="Sort by Name"
+ layout="topleft"
+ name="SortByName">
+ <menu_item_check.on_click
+ function="ParticipantList.Sort"
+ parameter="sort_by_name" />
+ <menu_item_check.on_check
+ function="ParticipantList.CheckItem"
+ parameter="is_sorted_by_name" />
+ </menu_item_check>
+ <menu_item_check
+ label="Sort by Recent Speakers"
+ layout="topleft"
+ name="SortByRecentSpeakers">
+ <menu_item_check.on_click
+ function="ParticipantList.Sort"
+ parameter="sort_by_recent_speakers" />
+ <menu_item_check.on_check
+ function="ParticipantList.CheckItem"
+ parameter="is_sorted_by_recent_speakers" />
+ </menu_item_check>
+ <menu_item_call
label="View Profile"
layout="topleft"
name="View Profile">
@@ -51,6 +73,8 @@
<menu_item_call.on_click
function="Avatar.Pay" />
</menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
<menu_item_check
label="Block Voice"
layout="topleft"
@@ -64,8 +88,6 @@
function="ParticipantList.EnableItem"
parameter="can_block" />
</menu_item_check>
- <menu_item_separator
- layout="topleft" />
<menu_item_check
label="Block Text"
layout="topleft"
@@ -79,6 +101,8 @@
function="ParticipantList.EnableItem"
parameter="can_mute_text" />
</menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
<context_menu
label="Moderator Options &gt;"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/menu_people_groups.xml b/indra/newview/skins/default/xui/en/menu_people_groups.xml
new file mode 100644
index 0000000000..afa680139d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_people_groups.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu name="menu_group_plus"
+ left="0" bottom="0" visible="false"
+ mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false">
+ <menu_item_call
+ label="View Info"
+ name="View Info">
+ <menu_item_call.on_click
+ function="People.Groups.Action"
+ parameter="view_info" />
+ <menu_item_call.on_enable
+ function="People.Groups.Enable"
+ parameter="view_info" />
+ </menu_item_call>
+ <menu_item_call
+ label="Chat"
+ name="Chat">
+ <menu_item_call.on_click
+ function="People.Groups.Action"
+ parameter="chat" />
+ <menu_item_call.on_enable
+ function="People.Groups.Enable"
+ parameter="chat" />
+ </menu_item_call>
+ <menu_item_call
+ label="Call"
+ name="Call">
+ <menu_item_call.on_click
+ function="People.Groups.Action"
+ parameter="call" />
+ <menu_item_call.on_enable
+ function="People.Groups.Enable"
+ parameter="call" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ label="Activate"
+ name="Activate">
+ <menu_item_call.on_click
+ function="People.Groups.Action"
+ parameter="activate" />
+ <menu_item_call.on_enable
+ function="People.Groups.Enable"
+ parameter="activate" />
+ </menu_item_call>
+ <menu_item_separator />
+ <menu_item_call
+ label="Leave"
+ name="Leave">
+ <menu_item_call.on_click
+ function="People.Groups.Action"
+ parameter="leave" />
+ <menu_item_call.on_enable
+ function="People.Groups.Enable"
+ parameter="leave" />
+ </menu_item_call>
+</menu>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index b4ce32ea1d..8f1799688b 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -2975,14 +2975,6 @@
<menu_item_call.on_click
function="Advanced.SendTestIMs" />
</menu_item_call>
- <menu_item_call
- label="Test Inspectors"
- name="Test Inspectors"
- shortcut="control|shift|I">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="test_inspectors" />
- </menu_item_call>
</menu>
<menu
create_jump_keys="true"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 87d1fc071d..d4b712e048 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -5773,6 +5773,17 @@ They will be blocked for a few seconds for your security.
</form>
</notification>
+ <notification
+ icon="alert.tga"
+ name="ConfirmCloseAll"
+ type="alertmodal">
+Are you sure you want to close all IMs?
+ <usetemplate
+ name="okcancelignore"
+ notext="Cancel"
+ yestext="Ok"/>
+ </notification>
+
<notification icon="notifytip.tga"
name="AttachmentSaved" type="notifytip">
Attachment has been saved.
diff --git a/indra/newview/skins/default/xui/en/panel_activeim_row.xml b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
index 3ed91cb48f..3416b2369d 100644
--- a/indra/newview/skins/default/xui/en/panel_activeim_row.xml
+++ b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
@@ -69,9 +69,9 @@
name="contact_name"
layout="topleft"
top="10"
- left_pad="20"
+ left_pad="10"
height="14"
- width="245"
+ width="255"
length="1"
follows="right|left"
use_ellipses="true"
diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
index 3e2910458f..5ae808581d 100644
--- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml
+++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
@@ -327,6 +327,7 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.
min_width="35"
user_resize="false">
<chiclet_im_well
+ max_displayed_count="99"
flash_period="0.3"
follows="right"
height="23"
@@ -356,7 +357,6 @@ image_pressed_selected "Lit" + "Selected" - there are new messages and the Well
image_selected="PushButton_Selected_Press"
label_color="Black"
left="0"
- max_displayed_count="99"
name="Unread IM messages"
pad_left="0"
pad_right="0"
diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
index 0a3fd1699f..30e652befd 100644
--- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
@@ -21,32 +21,32 @@
value="Unknown"
width="100" />
<button
- follows="left|top"
+ follows="left|top|right"
height="20"
label="Profile"
name="view_profile_btn"
width="100" />
<button
- follows="left|top"
+ follows="left|top|right"
height="20"
label="Add Friend"
name="add_friend_btn"
width="100" />
<button
- follows="left|top"
+ follows="left|top|right"
height="20"
label="Teleport"
name="teleport_btn"
width="100" />
<button
- follows="left|top"
+ follows="left|top|right"
height="20"
label="Share"
name="share_btn"
width="100" />
<!--Removing pay button to save space - will update spec - verified by Erica/Steve -->
<!-- <button
- follows="left|top"
+ follows="left|top|right"
height="20"
label="Pay"
name="pay_btn"
@@ -56,13 +56,14 @@
bg_alpha_color="DkGray2"
border="false"
top_pad="10"
- follows="left|bottom"
+ follows="left|bottom|right"
height="70"
left="1"
name="panel_call_buttons"
width="109">
<button
bottom="10"
+ follows="left|top|right"
height="20"
label="Call"
left_delta="5"
@@ -70,6 +71,7 @@
width="100" />
<button
bottom="35"
+ follows="left|top|right"
height="20"
label="Leave Call"
name="end_call_btn"
@@ -77,6 +79,7 @@
width="100" />
<button
bottom="10"
+ follows="left|top|right"
height="20"
label="Voice Controls"
name="voice_ctrls_btn"
diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
index 68e58b27ec..9f06e64560 100644
--- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
@@ -60,6 +60,7 @@
layout="topleft"
left="10"
name="back_btn"
+ tool_tip="Back"
tab_stop="false"
top="0"
width="23" />
diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
index 5c99022f35..d6d8e9562b 100644
--- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml
@@ -3,7 +3,7 @@
<panel name="Outfits"
background_visible="true"
follows="all"
- height="550"
+ height="570"
label="Things"
layout="topleft"
min_height="350"
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 8883c27c47..08a10553a8 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -411,5 +411,15 @@ background_visible="true"
name="chat_btn"
tool_tip="Open chat session"
width="110" />
+ <button
+ follows="bottom|left"
+ top="4"
+ left_pad="2"
+ height="23"
+ label="Group Call"
+ layout="topleft"
+ name="group_call_btn"
+ tool_tip="Call this group"
+ width="110" />
</panel>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_place_profile.xml b/indra/newview/skins/default/xui/en/panel_place_profile.xml
index c3138bb443..8fc2ae39f0 100644
--- a/indra/newview/skins/default/xui/en/panel_place_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml
@@ -145,6 +145,7 @@
layout="topleft"
left="10"
name="back_btn"
+ tool_tip="Back"
tab_stop="false"
top="0"
width="23" />
diff --git a/indra/newview/skins/default/xui/en/panel_places.xml b/indra/newview/skins/default/xui/en/panel_places.xml
index db03f334e5..8a5c023133 100644
--- a/indra/newview/skins/default/xui/en/panel_places.xml
+++ b/indra/newview/skins/default/xui/en/panel_places.xml
@@ -96,6 +96,7 @@ background_visible="true"
layout="topleft"
left_pad="5"
name="edit_btn"
+ tool_tip="Edit landmark information"
top="0"
width="70" />
<button
@@ -106,6 +107,7 @@ background_visible="true"
image_unselected="ForwardArrow_Off"
layout="topleft"
name="overflow_btn"
+ tool_tip="Show additional options"
right="-10"
top="0"
width="18" />
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
index 83dc7cd854..34bd6fb091 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
@@ -98,12 +98,12 @@
decimal_digits="0"
follows="left|top"
height="15"
- increment="10"
- initial_value="50"
+ increment="100"
+ initial_value="500"
layout="topleft"
left_delta="150"
- max_val="1500"
- min_val="50"
+ max_val="10000"
+ min_val="100"
name="max_bandwidth"
top_delta="0"
width="180" />
diff --git a/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml b/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml
new file mode 100644
index 0000000000..d98f690339
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="top|left"
+ height="570"
+ label="MY AVATAR"
+ layout="topleft"
+ left="0"
+ name="script_limits_my_avatar_panel"
+ top="0"
+ width="480">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="loading_text"
+ top="10"
+ text_color="EmphasisColor"
+ width="480">
+ Loading...
+ </text>
+ <scroll_list
+ draw_heading="true"
+ follows="all"
+ height="500"
+ layout="topleft"
+ left_delta="0"
+ multi_select="true"
+ name="scripts_list"
+ top_delta="17"
+ width="460">
+ <scroll_list.columns
+ label="Size (kb)"
+ name="size"
+ width="70" />
+ <scroll_list.columns
+ label="URLs"
+ name="urls"
+ width="50" />
+ <scroll_list.columns
+ label="Object Name"
+ name="name"
+ width="140" />
+ <scroll_list.columns
+ label="Location"
+ name="location"
+ width="130" />
+ </scroll_list>
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Refresh List"
+ layout="bottomleft"
+ left_pad="5"
+ name="refresh_list_btn"
+ top="34"
+ left="10"
+ width="100" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml
new file mode 100644
index 0000000000..0fa3c1cf2e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="top|left"
+ height="570"
+ label="REGION MEMORY"
+ layout="topleft"
+ name="script_limits_region_memory_panel"
+ top="0"
+ left="0"
+ width="480">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="script_memory"
+ top_pad="24"
+ text_color="White"
+ width="480">
+ Parcel Script Memory
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="30"
+ name="parcels_listed"
+ top_delta="18"
+ visible="true"
+ width="480">
+ Parcels Owned:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="30"
+ name="memory_used"
+ top_delta="18"
+ width="480">
+ Memory used:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="loading_text"
+ top_delta="32"
+ text_color="EmphasisColor"
+ width="480">
+ Loading...
+ </text>
+ <scroll_list
+ draw_heading="true"
+ follows="all"
+ height="409"
+ layout="topleft"
+ left_delta="0"
+ multi_select="true"
+ name="scripts_list"
+ top_delta="16"
+ width="460">
+ <scroll_list.columns
+ label="Size (kb)"
+ name="size"
+ width="70" />
+ <scroll_list.columns
+ label="Object Name"
+ name="name"
+ width="100" />
+ <scroll_list.columns
+ label="Object Owner"
+ name="owner"
+ width="100" />
+ <scroll_list.columns
+ label="Parcel / Location"
+ name="location"
+ width="130" />
+<!-- <scroll_list.commit_callback
+ function="TopObjects.CommitObjectsList" />-->
+ </scroll_list>
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Refresh List"
+ layout="bottomleft"
+ left_pad="5"
+ name="refresh_list_btn"
+ top="34"
+ left="10"
+ width="100" />
+ <button
+ follows="bottom|right"
+ height="19"
+ visible="false"
+ label="Highlight"
+ layout="bottomright"
+ left="370"
+ name="highlight_btn"
+ top="34"
+ width="100" />
+ <button
+ follows="bottom|right"
+ height="19"
+ visible="false"
+ label="Return"
+ layout="bottomright"
+ name="return_btn"
+ top="34"
+ left_delta="-105"
+ width="100" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
index 3384852f27..4f40e00815 100644
--- a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
@@ -55,6 +55,7 @@
left_pad="5"
right="-3"
name="profile_btn"
+ tool_tip="Show item info"
top="1"
visible="false"
width="20" />
diff --git a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
index 7f4b4aef82..44248eedd5 100644
--- a/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
+++ b/indra/newview/skins/default/xui/en/sidepanel_appearance.xml
@@ -2,23 +2,24 @@
<panel
background_visible="true"
follows="all"
-height="635"
+height="570"
label="Outfits"
layout="topleft"
-min_height="460"
+min_height="350"
+min_width="240"
name="appearance panel"
top="0"
left="0"
- width="333">
+width="333">
<string
name="No Outfit"
value="No Outfit" />
<panel
left="0"
top="0"
- follows="left|top|right"
+ follows="all"
layout="topleft"
- width="333"
+ width="330"
height="33"
name="panel_currentlook"
>
@@ -85,9 +86,9 @@ left="0"
class="panel_outfits_inventory"
filename="panel_outfits_inventory.xml"
name="panel_outfits_inventory"
- height="550"
- min_height="510"
- width="333"
+ height="515"
+ min_height="410"
+ width="320"
top_pad="0"
follows="all"
/>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 1ab2507232..acdf3d1bf7 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2041,6 +2041,59 @@ this texture in your inventory
<string name="RegionInfoAllowedResidents">Allowed residents: ([ALLOWEDAGENTS], max [MAXACCESS])</string>
<string name="RegionInfoAllowedGroups">Allowed groups: ([ALLOWEDGROUPS], max [MAXACCESS])</string>
+ <!-- script limits floater -->
+ <string name="ScriptLimitsParcelScriptMemory">Parcel Script Memory</string>
+ <string name="ScriptLimitsParcelsOwned">Parcels Listed: [PARCELS]</string>
+ <string name="ScriptLimitsMemoryUsed">Memory used: [COUNT] kb out of [MAX] kb; [AVAILABLE] kb available</string>
+ <string name="ScriptLimitsMemoryUsedSimple">Memory used: [COUNT] kb</string>
+ <string name="ScriptLimitsParcelScriptURLs">Parcel Script URLs</string>
+ <string name="ScriptLimitsURLsUsed">URLs used: [COUNT] out of [MAX]; [AVAILABLE] available</string>
+ <string name="ScriptLimitsURLsUsedSimple">URLs used: [COUNT]</string>
+ <string name="ScriptLimitsRequestError">Error requesting information</string>
+ <string name="ScriptLimitsRequestWrongRegion">Error: script information is only available in your current region</string>
+ <string name="ScriptLimitsRequestWaiting">Retrieving information...</string>
+ <string name="ScriptLimitsRequestDontOwnParcel">You do not have permission to examine this parcel</string>
+
+ <string name="SITTING_ON">Sitting On</string>
+ <string name="ATTACH_CHEST">Chest</string>
+ <string name="ATTACH_HEAD">Head</string>
+ <string name="ATTACH_LSHOULDER">Left Shoulder</string>
+ <string name="ATTACH_RSHOULDER">Right Shoulder</string>
+ <string name="ATTACH_LHAND">Left Hand</string>
+ <string name="ATTACH_RHAND">Right Hand</string>
+ <string name="ATTACH_LFOOT">Left Foot</string>
+ <string name="ATTACH_RFOOT">Right Foot</string>
+ <string name="ATTACH_BACK">Back</string>
+ <string name="ATTACH_PELVIS">Pelvis</string>
+ <string name="ATTACH_MOUTH">Mouth</string>
+ <string name="ATTACH_CHIN">Chin</string>
+ <string name="ATTACH_LEAR">Left Ear</string>
+ <string name="ATTACH_REAR">Right Ear</string>
+ <string name="ATTACH_LEYE">Left Eye</string>
+ <string name="ATTACH_REYE">Right Eye</string>
+ <string name="ATTACH_NOSE">Nose</string>
+ <string name="ATTACH_RUARM">Right Upper Arm</string>
+ <string name="ATTACH_RLARM">Right Lower Arm</string>
+ <string name="ATTACH_LUARM">Left Upper Arm</string>
+ <string name="ATTACH_LLARM">Left Lower Arm</string>
+ <string name="ATTACH_RHIP">Right Hip</string>
+ <string name="ATTACH_RULEG">Right Upper Leg</string>
+ <string name="ATTACH_RLLEG">Right Lower Leg</string>
+ <string name="ATTACH_LHIP">Left Hip</string>
+ <string name="ATTACH_LULEG">Left Upper Leg</string>
+ <string name="ATTACH_LLLEG">Left Lower Leg</string>
+ <string name="ATTACH_BELLY">Belly</string>
+ <string name="ATTACH_RPEC">Right Pec</string>
+ <string name="ATTACH_LPEC">Left Pec</string>
+ <string name="ATTACH_HUD_CENTER_2">HUD Center 2</string>
+ <string name="ATTACH_HUD_TOP_RIGHT">HUD Top Right</string>
+ <string name="ATTACH_HUD_TOP_CENTER">HUD Top Center</string>
+ <string name="ATTACH_HUD_TOP_LEFT">HUD Top Left</string>
+ <string name="ATTACH_HUD_CENTER_1">HUD Center 1</string>
+ <string name="ATTACH_HUD_BOTTOM_LEFT">HUD Bottom Left</string>
+ <string name="ATTACH_HUD_BOTTOM">HUD Bottom</string>
+ <string name="ATTACH_HUD_BOTTOM_RIGHT">HUD Bottom Right</string>
+
<!-- script editor -->
<string name="CursorPos">Line [LINE], Column [COLUMN]</string>
@@ -2911,12 +2964,26 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="not_a_mod_error">
You are not a session moderator.
</string>
+ <!--Some times string name is getting from the body of server response.
+ For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
+ In case of the EXT-3562 issue 'muted' is passed into the gIMMgr::showSessionStartError as a string name.
+ So, let add string with name="muted" with the same value as "muted_error" -->
+ <string name="muted">
+ A group moderator disabled your text chat.
+ </string>
<string name="muted_error">
A group moderator disabled your text chat.
</string>
<string name="add_session_event">
Unable to add users to chat session with [RECIPIENT].
</string>
+ <!--Some times string name is getting from the body of server response.
+ For ex.: from gIMMgr::showSessionStartError in the LLViewerChatterBoxSessionStartReply::post.
+ In case of the EXT-3562 issue 'message' is passed into the gIMMgr::showSessionStartError as a string name.
+ So, let add string with name="message" with the same value as "message_session_event" -->
+ <string name="message">
+ Unable to send your message to the chat session with [RECIPIENT].
+ </string>
<string name="message_session_event">
Unable to send your message to the chat session with [RECIPIENT].
</string>
diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
index 3f5a4b8379..3f5a4b8379 100755..100644
--- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml
+++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index d69a771bbb..0db18525d7 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -345,7 +345,7 @@ class WindowsManifest(ViewerManifest):
self.path("ssleay32.dll")
# For WebKit/Qt plugin runtimes (image format plugins)
- if self.prefix(src="imageformats", dst="llplugin/imageformats"):
+ if self.prefix(src="imageformats", dst="imageformats"):
self.path("qgifd4.dll")
self.path("qicod4.dll")
self.path("qjpegd4.dll")
@@ -354,6 +354,14 @@ class WindowsManifest(ViewerManifest):
self.path("qtiffd4.dll")
self.end_prefix()
+ # For WebKit/Qt plugin runtimes (codec/character encoding plugins)
+ if self.prefix(src="codecs", dst="codecs"):
+ self.path("qcncodecsd4.dll")
+ self.path("qjpcodecsd4.dll")
+ self.path("qkrcodecsd4.dll")
+ self.path("qtwcodecsd4.dll")
+ self.end_prefix()
+
self.end_prefix()
else:
if self.prefix(src=os.path.join(os.pardir, os.pardir, 'libraries', 'i686-win32', 'lib', 'release'),
@@ -368,7 +376,7 @@ class WindowsManifest(ViewerManifest):
self.path("ssleay32.dll")
# For WebKit/Qt plugin runtimes (image format plugins)
- if self.prefix(src="imageformats", dst="llplugin/imageformats"):
+ if self.prefix(src="imageformats", dst="imageformats"):
self.path("qgif4.dll")
self.path("qico4.dll")
self.path("qjpeg4.dll")
@@ -377,6 +385,14 @@ class WindowsManifest(ViewerManifest):
self.path("qtiff4.dll")
self.end_prefix()
+ # For WebKit/Qt plugin runtimes (codec/character encoding plugins)
+ if self.prefix(src="codecs", dst="codecs"):
+ self.path("qcncodecs4.dll")
+ self.path("qjpcodecs4.dll")
+ self.path("qkrcodecs4.dll")
+ self.path("qtwcodecs4.dll")
+ self.end_prefix()
+
self.end_prefix()
self.disable_manifest_check()
diff --git a/indra/test_apps/llplugintest/CMakeLists.txt b/indra/test_apps/llplugintest/CMakeLists.txt
index 89e2d8582d..b4043b0fd9 100644
--- a/indra/test_apps/llplugintest/CMakeLists.txt
+++ b/indra/test_apps/llplugintest/CMakeLists.txt
@@ -428,7 +428,23 @@ if(WINDOWS)
${plugintest_debug_files}
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
-
+
+ # Debug config runtime files required for the plugin test mule (Qt codec plugins)
+ set(plugintest_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug/codecs")
+ set(plugintest_debug_files
+ qcncodecsd4.dll
+ qjpcodecsd4.dll
+ qkrcodecsd4.dll
+ qtwcodecsd4.dll
+ )
+ copy_if_different(
+ ${plugintest_debug_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/Debug/codecs"
+ out_targets
+ ${plugintest_debug_files}
+ )
+ set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
# Release & ReleaseDebInfo config runtime files required for the plugin test mule
set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release")
set(plugintest_release_files
@@ -486,6 +502,30 @@ if(WINDOWS)
${plugintest_release_files}
)
set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+ # Release & ReleaseDebInfo config runtime files required for the plugin test mule (Qt codec plugins)
+ set(plugintest_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release/codecs")
+ set(plugintest_release_files
+ qcncodecs4.dll
+ qjpcodecs4.dll
+ qkrcodecs4.dll
+ qtwcodecs4.dll
+ )
+ copy_if_different(
+ ${plugintest_release_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/Release/codecs"
+ out_targets
+ ${plugintest_release_files}
+ )
+ set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+ copy_if_different(
+ ${plugintest_release_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/codecs"
+ out_targets
+ ${plugintest_release_files}
+ )
+ set(plugin_test_targets ${plugin_test_targets} ${out_targets})
add_custom_target(copy_plugintest_libs ALL
DEPENDS
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
index 018f691672..364088ab31 100644
--- a/indra/viewer_components/login/lllogin.cpp
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -235,6 +235,8 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential
break;
}
+ sendProgressEvent("offline", "indeterminate", mAuthResponse["responses"]);
+
// Here the login service at the current URI is redirecting us
// to some other URI ("indeterminate" -- why not "redirect"?).
// The response should contain another uri to try, with its
@@ -276,7 +278,14 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential
// Here we got through all the rewrittenURIs without succeeding. Tell
// caller this didn't work out so well. Of course, the only failure data
// we can reasonably show are from the last of the rewrittenURIs.
- sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]);
+
+ // *NOTE: The response from LLXMLRPCListener's Poller::poll method returns an
+ // llsd with no "responses" node. To make the output from an incomplete login symmetrical
+ // to success, add a data/message and data/reason fields.
+ LLSD error_response;
+ error_response["reason"] = mAuthResponse["status"];
+ error_response["message"] = mAuthResponse["error"];
+ sendProgressEvent("offline", "fail.login", error_response);
}
void LLLogin::Impl::disconnect()
diff --git a/install.xml b/install.xml
index 0501ef9cfd..fdd7458384 100644
--- a/install.xml
+++ b/install.xml
@@ -948,9 +948,9 @@ anguage Infrstructure (CLI) international standard</string>
<key>darwin</key>
<map>
<key>md5sum</key>
- <string>1631831b63310d85ad272b4dca3c1fbf</string>
+ <string>5362a53488693f9bd7d9083758af25eb</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20091217.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20091218.tar.bz2</uri>
</map>
<key>linux</key>
<map>
@@ -962,9 +962,9 @@ anguage Infrstructure (CLI) international standard</string>
<key>windows</key>
<map>
<key>md5sum</key>
- <string>3846354e2e20a98c0401317eb114ff5e</string>
+ <string>4dd305f2ce38b2e55a2014ad3a2de34d</string>
<key>url</key>
- <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-windows-qt4.6-20091215.tar.bz2</uri>
+ <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-windows-qt4.6-20091218.tar.bz2</uri>
</map>
</map>
</map>