diff options
-rw-r--r-- | indra/llui/llnotificationslistener.cpp | 269 | ||||
-rw-r--r-- | indra/llui/llnotificationslistener.h | 20 | ||||
-rw-r--r-- | indra/llui/llurlentry.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llavatarlist.cpp | 6 | ||||
-rw-r--r-- | indra/newview/llcallfloater.cpp | 7 | ||||
-rw-r--r-- | indra/newview/llcallfloater.h | 2 | ||||
-rw-r--r-- | indra/newview/llchiclet.cpp | 61 | ||||
-rw-r--r-- | indra/newview/llchiclet.h | 5 | ||||
-rw-r--r-- | indra/newview/llmoveview.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llpanelclassified.cpp | 39 | ||||
-rw-r--r-- | indra/newview/llpanelclassified.h | 6 | ||||
-rw-r--r-- | indra/newview/llpanelimcontrolpanel.cpp | 3 | ||||
-rw-r--r-- | indra/newview/llpanelpicks.cpp | 5 | ||||
-rw-r--r-- | indra/newview/llparticipantlist.cpp | 8 | ||||
-rw-r--r-- | indra/newview/llparticipantlist.h | 2 | ||||
-rw-r--r-- | indra/newview/llspeakers.cpp | 2 | ||||
-rw-r--r-- | indra/newview/lltoastalertpanel.h | 2 | ||||
-rw-r--r-- | indra/newview/lltransientfloatermgr.cpp | 8 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_customize.xml | 15 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/strings.xml | 2 |
20 files changed, 432 insertions, 34 deletions
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..95dc2ce027 100644 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -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/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 71b23e1383..5865df3e26 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -33,7 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llavatarlist.h" -#include "llagent.h" // for comparator +#include "llagentdata.h" // for comparator // newview #include "llcallingcard.h" // for LLAvatarTracker @@ -425,11 +425,11 @@ bool LLAvatarItemAgentOnTopComparator::doCompare(const LLAvatarListItem* avatar_ { //keep agent on top, if first is agent, //then we need to return true to elevate this id, otherwise false. - if(avatar_item1->getAvatarId() == gAgent.getID()) + if(avatar_item1->getAvatarId() == gAgentID) { return true; } - else if (avatar_item2->getAvatarId() == gAgent.getID()) + else if (avatar_item2->getAvatarId() == gAgentID) { return false; } diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index 20739d2401..1acdb96da6 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -162,6 +162,7 @@ void LLCallFloater::onChange() if (NULL == mPaticipants) return; mPaticipants->refreshVoiceState(); + } @@ -243,7 +244,7 @@ void LLCallFloater::updateSession() childSetVisible("leave_call_btn", !is_local_chat); refreshPartisipantList(); - updateModeratorState(); + updateAgentModeratorState(); //show floater for voice calls if (!is_local_chat) @@ -280,7 +281,7 @@ void LLCallFloater::refreshPartisipantList() if (!non_avatar_caller) { - mPaticipants = new LLParticipantList(mSpeakerManager, mAvatarList); + mPaticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT); if (LLLocalSpeakerMgr::getInstance() == mSpeakerManager) { @@ -366,7 +367,7 @@ void LLCallFloater::setModeratorMutedVoice(bool moderator_muted) mSpeakingIndicator->setIsMuted(moderator_muted); } -void LLCallFloater::updateModeratorState() +void LLCallFloater::updateAgentModeratorState() { std::string name; gCacheName->getFullName(gAgentID, name); diff --git a/indra/newview/llcallfloater.h b/indra/newview/llcallfloater.h index f9c9149085..ac45e283eb 100644 --- a/indra/newview/llcallfloater.h +++ b/indra/newview/llcallfloater.h @@ -101,7 +101,7 @@ private: void updateTitle(); void initAgentData(); void setModeratorMutedVoice(bool moderator_muted); - void updateModeratorState(); + void updateAgentModeratorState(); private: LLSpeakerMgr* mSpeakerManager; diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index bb09f34362..17ef1f41a4 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -68,7 +68,8 @@ 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(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 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; @@ -186,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(); @@ -1311,7 +1312,6 @@ bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index) chiclet->setChicletSizeChangedCallback(boost::bind(&LLChicletPanel::onChicletSizeChanged, this, _1, index)); arrange(); - showScrollButtonsIfNeeded(); return true; } @@ -1322,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¶m) @@ -1340,8 +1338,6 @@ void LLChicletPanel::removeChiclet(chiclet_list_t::iterator it) mChicletList.erase(it); arrange(); - trimChiclets(); - showScrollButtonsIfNeeded(); } void LLChicletPanel::removeChiclet(S32 index) @@ -1434,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; @@ -1446,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(); @@ -1461,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) { @@ -1476,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() @@ -1493,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(); diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 259476c2ad..2ab6abfb5b 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -1050,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/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/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..ae1c28c7ab 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -282,8 +282,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/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp index 4d22d96072..a52aa6d30f 100644 --- a/indra/newview/llpanelpicks.cpp +++ b/indra/newview/llpanelpicks.cpp @@ -769,6 +769,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/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index afb9892d12..e8aa1e9831 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -51,12 +51,13 @@ static const LLAvatarItemAgentOnTopComparator AGENT_ON_TOP_NAME_COMPARATOR; -LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list, bool use_context_menu/* = true*/): +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(true) +, mExcludeAgent(exclude_agent) { mSpeakerAddListener = new SpeakerAddListener(*this); mSpeakerRemoveListener = new SpeakerRemoveListener(*this); @@ -101,7 +102,6 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av } } // we need to exclude agent id for non group chat - mExcludeAgent = !gAgent.isInGroup(mSpeakerMgr->getSessionID()); mAvatarList->setDirty(true); sort(); } @@ -555,7 +555,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; } diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 72c413d188..b85d4c9bc4 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -43,7 +43,7 @@ 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); 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/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/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml index ffdb59d44c..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 diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 7438a36ed0..a1f2548f81 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2085,7 +2085,7 @@ this texture in your inventory <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_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> |