summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llmessage/lltemplatemessagereader.cpp34
-rw-r--r--indra/llmessage/lltemplatemessagereader.h9
-rw-r--r--indra/newview/fsfloatersearch.cpp3212
-rw-r--r--indra/newview/fsfloatersearch.h404
-rw-r--r--indra/newview/llavatarpropertiesprocessor.cpp2
-rw-r--r--indra/newview/llavatarpropertiesprocessor.h60
-rw-r--r--indra/newview/lleventnotifier.cpp54
-rw-r--r--indra/newview/lleventnotifier.h29
-rw-r--r--indra/newview/llpanelprofileclassifieds.h3
-rw-r--r--indra/newview/llsearchcombobox.h10
-rw-r--r--indra/newview/llstartup.cpp11
-rw-r--r--indra/newview/llviewerfloaterreg.cpp5
-rw-r--r--indra/newview/llviewerinput.cpp9
-rw-r--r--indra/newview/llviewermenu.cpp1
-rw-r--r--indra/newview/llviewernetwork.cpp12
-rw-r--r--indra/newview/llviewernetwork.h19
-rw-r--r--indra/newview/skins/default/textures/icon_auction.tgabin0 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/icon_group.tgabin0 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/icon_legacy_event.tgabin0 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/icon_legacy_event_adult.tgabin0 -> 648 bytes
-rw-r--r--indra/newview/skins/default/textures/icon_legacy_event_mature.tgabin0 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/icon_place.tgabin0 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ProgressLarge_1.pngbin0 -> 6163 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ProgressLarge_10.pngbin0 -> 6310 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ProgressLarge_11.pngbin0 -> 6169 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ProgressLarge_12.pngbin0 -> 6197 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ProgressLarge_2.pngbin0 -> 6227 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ProgressLarge_3.pngbin0 -> 6090 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ProgressLarge_4.pngbin0 -> 6295 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ProgressLarge_5.pngbin0 -> 6158 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ProgressLarge_6.pngbin0 -> 6220 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ProgressLarge_7.pngbin0 -> 6100 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ProgressLarge_8.pngbin0 -> 6223 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ProgressLarge_9.pngbin0 -> 6034 bytes
-rw-r--r--indra/newview/skins/default/textures/megapahit/icon_group.pngbin0 -> 1479 bytes
-rw-r--r--indra/newview/skins/default/textures/megapahit/icon_land_auction.pngbin0 -> 1464 bytes
-rw-r--r--indra/newview/skins/default/textures/megapahit/icon_land_forsale.pngbin0 -> 1485 bytes
-rw-r--r--indra/newview/skins/default/textures/megapahit/icon_place.pngbin0 -> 1584 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml54
-rw-r--r--indra/newview/skins/default/xui/en/floater_fs_search.xml337
-rw-r--r--indra/newview/skins/default/xui/en/floater_world_map.xml10
-rw-r--r--indra/newview/skins/default/xui/en/panel_fs_search_legacy_classifieds.xml169
-rw-r--r--indra/newview/skins/default/xui/en/panel_fs_search_legacy_events.xml258
-rw-r--r--indra/newview/skins/default/xui/en/panel_fs_search_legacy_groups.xml159
-rw-r--r--indra/newview/skins/default/xui/en/panel_fs_search_legacy_land.xml281
-rw-r--r--indra/newview/skins/default/xui/en/panel_fs_search_legacy_people.xml89
-rw-r--r--indra/newview/skins/default/xui/en/panel_fs_search_legacy_places.xml169
-rw-r--r--indra/newview/skins/default/xui/en/panel_fs_search_legacy_web.xml21
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml58
49 files changed, 5410 insertions, 69 deletions
diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp
index 370d458eb8..c24c850a86 100644
--- a/indra/llmessage/lltemplatemessagereader.cpp
+++ b/indra/llmessage/lltemplatemessagereader.cpp
@@ -118,6 +118,9 @@ void LLTemplateMessageReader::getData(const char *blockname, const char *varname
{
switch( vardata_size )
{
+ case 0:
+ // This is here to prevent a memcpy from a null value which is undefined behavior.
+ break;
case 1:
*((U8*)datap) = *((U8*)vardata.getData());
break;
@@ -286,7 +289,7 @@ void LLTemplateMessageReader::getU8(const char *block, const char *var,
void LLTemplateMessageReader::getBOOL(const char *block, const char *var,
BOOL &b, S32 blocknum )
{
- U8 value;
+ U8 value(0);
getData(block, var, &value, sizeof(U8), blocknum);
b = (BOOL) value;
}
@@ -445,7 +448,7 @@ S32 LLTemplateMessageReader::getMessageSize() const
// Returns template for the message contained in buffer
BOOL LLTemplateMessageReader::decodeTemplate(
const U8* buffer, S32 buffer_size, // inputs
- LLMessageTemplate** msg_template ) // outputs
+ LLMessageTemplate** msg_template, bool custom ) // outputs
{
const U8* header = buffer + LL_PACKET_ID_SIZE;
@@ -487,6 +490,7 @@ BOOL LLTemplateMessageReader::decodeTemplate(
}
else // bogus packet received (too short)
{
+ if (!custom)
LL_WARNS() << "Packet with unusable length received (too short): "
<< buffer_size << LL_ENDL;
return(FALSE);
@@ -499,10 +503,11 @@ BOOL LLTemplateMessageReader::decodeTemplate(
}
else
{
- // MAINT-7482 - make viewer more tolerant of unknown messages.
+ if (!custom)
+ {
LL_WARNS_ONCE() << "Message #" << std::hex << num << std::dec
<< " received but not registered!" << LL_ENDL;
- //gMessageSystem->callExceptionFunc(MX_UNREGISTERED_MESSAGE);
+ }
return(FALSE);
}
@@ -531,7 +536,7 @@ void LLTemplateMessageReader::logRanOffEndOfPacket( const LLHost& host, const S3
static LLTrace::BlockTimerStatHandle FTM_PROCESS_MESSAGES("Process Messages");
// decode a given message
-BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender )
+BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender, bool custom )
{
LL_RECORD_BLOCK_TIME(FTM_PROCESS_MESSAGES);
@@ -591,6 +596,7 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
}
else
{
+ if (!custom)
LL_ERRS() << "Unknown block type" << LL_ENDL;
return FALSE;
}
@@ -637,6 +643,7 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
if ((decode_pos + data_size) > mReceiveSize)
{
+ if (!custom)
logRanOffEndOfPacket(sender, decode_pos, data_size);
// default to 0 length variable blocks
@@ -673,6 +680,7 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
// so, copy data pointer and set data size to fixed size
if ((decode_pos + mvci.getSize()) > mReceiveSize)
{
+ if (!custom)
logRanOffEndOfPacket(sender, decode_pos, mvci.getSize());
// default to 0s.
@@ -697,10 +705,11 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
if (mCurrentRMessageData->mMemberBlocks.empty()
&& !mCurrentRMessageTemplate->mMemberBlocks.empty())
{
- LL_DEBUGS() << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << LL_ENDL;
+ LL_WARNS() << "Empty message '" << mCurrentRMessageTemplate->mName << "' (no blocks)" << LL_ENDL;
return FALSE;
}
+ if (!custom)
{
static LLTimer decode_timer;
@@ -753,11 +762,12 @@ BOOL LLTemplateMessageReader::decodeData(const U8* buffer, const LLHost& sender
BOOL LLTemplateMessageReader::validateMessage(const U8* buffer,
S32 buffer_size,
const LLHost& sender,
- bool trusted)
+ bool trusted,
+ bool custom)
{
mReceiveSize = buffer_size;
- BOOL valid = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate );
- if(valid)
+ BOOL valid = decodeTemplate(buffer, buffer_size, &mCurrentRMessageTemplate, custom );
+ if(valid && !custom)
{
mCurrentRMessageTemplate->mReceiveCount++;
//LL_DEBUGS() << "MessageRecvd:"
@@ -828,3 +838,9 @@ void LLTemplateMessageReader::copyToBuilder(LLMessageBuilder& builder) const
}
builder.copyFromMessageData(*mCurrentRMessageData);
}
+
+LLMessageTemplate* LLTemplateMessageReader::getTemplate()
+{
+ return mCurrentRMessageTemplate;
+}
+
diff --git a/indra/llmessage/lltemplatemessagereader.h b/indra/llmessage/lltemplatemessagereader.h
index 1aa5d2e164..772b8fd607 100644
--- a/indra/llmessage/lltemplatemessagereader.h
+++ b/indra/llmessage/lltemplatemessagereader.h
@@ -99,24 +99,27 @@ public:
virtual void copyToBuilder(LLMessageBuilder&) const;
BOOL validateMessage(const U8* buffer, S32 buffer_size,
- const LLHost& sender, bool trusted = false);
+ const LLHost& sender, bool trusted = false, bool custom = false);
BOOL readMessage(const U8* buffer, const LLHost& sender);
bool isTrusted() const;
bool isBanned(bool trusted_source) const;
bool isUdpBanned() const;
+ BOOL decodeData(const U8* buffer, const LLHost& sender, bool custom = false);
+ LLMessageTemplate* getTemplate();
+
private:
void getData(const char *blockname, const char *varname, void *datap,
S32 size = 0, S32 blocknum = 0, S32 max_size = S32_MAX);
BOOL decodeTemplate(const U8* buffer, S32 buffer_size, // inputs
- LLMessageTemplate** msg_template ); // outputs
+ LLMessageTemplate** msg_template, bool custom = false ); // outputs
void logRanOffEndOfPacket( const LLHost& host, const S32 where, const S32 wanted );
- BOOL decodeData(const U8* buffer, const LLHost& sender );
+ //BOOL decodeData(const U8* buffer, const LLHost& sender );
S32 mReceiveSize;
LLMessageTemplate* mCurrentRMessageTemplate;
diff --git a/indra/newview/fsfloatersearch.cpp b/indra/newview/fsfloatersearch.cpp
new file mode 100644
index 0000000000..f05e996699
--- /dev/null
+++ b/indra/newview/fsfloatersearch.cpp
@@ -0,0 +1,3212 @@
+/**
+ * @file fsfloatersearch.cpp
+ * @brief Firestorm Search Floater
+ *
+ * $LicenseInfo:firstyear=2012&license=fsviewerlgpl$
+ * Phoenix Firestorm Viewer Source Code
+ * Copyright (C) 2012, Cinder Roxley <cinder.roxley@phoenixviewer.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
+ * http://www.firestormviewer.org
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "fsfloatersearch.h"
+
+#include "lldispatcher.h"
+#include "llagent.h"
+#include "llavataractions.h"
+#include "llavatarname.h"
+#include "llavatarnamecache.h"
+#include "llavatarpropertiesprocessor.h"
+#include "llclassifiedflags.h"
+#include "llclassifiedinfo.h"
+#include "llcombobox.h"
+#include "lldateutil.h"
+#include "lleventflags.h"
+#include "lleventnotifier.h"
+#include "llfloaterreg.h"
+#include "llfloaterworldmap.h"
+#include "llgroupactions.h"
+#include "llgroupmgr.h"
+#include "llloadingindicator.h"
+#include "lllogininstance.h"
+#include "llnotificationsutil.h"
+#include "llpanelprofile.h"
+#include "llpanelprofileclassifieds.h"
+#include "llparcel.h"
+#include "llproductinforequest.h"
+#include "llqueryflags.h"
+#include "llregionhandle.h"
+#include "llremoteparcelrequest.h"
+#include "lltimer.h"
+#include "lltrans.h"
+#include "llviewercontrol.h"
+#include "llviewergenericmessage.h"
+#include "llviewernetwork.h"
+#include "llviewerregion.h"
+#include "llworldmapmessage.h"
+#include "message.h"
+#include <boost/tokenizer.hpp>
+#include <boost/algorithm/string.hpp>
+#include <string>
+
+#include <chrono>
+
+static const S32 MIN_SEARCH_STRING_SIZE = 2;
+static const S32 RESULT_PAGE_SIZE = 100;
+
+// (observeur) Hack to avoid Find to be called several times (due to a bug in llsearchcombobox)
+static std::chrono::time_point<std::chrono::system_clock> lastRequestTime;
+static const S32 REQUEST_MIN_ELAPSED_TIME = 500;
+
+std::string filterShortWords(std::string query_string);
+void fillSearchComboBox(LLSearchComboBox* search_combo);
+
+////////////////////////////////////////
+// Observer Classes //
+////////////////////////////////////////
+
+class FSSearchRemoteParcelInfoObserver : public LLRemoteParcelInfoObserver
+{
+public:
+ FSSearchRemoteParcelInfoObserver(FSFloaterSearch* floater, bool for_events) : LLRemoteParcelInfoObserver(),
+ mParent(floater),
+ mForEvents(for_events)
+ {}
+
+ ~FSSearchRemoteParcelInfoObserver()
+ {
+ // remove any in-flight observers
+ std::set<LLUUID>::iterator it;
+ for (it = mParcelIDs.begin(); it != mParcelIDs.end(); ++it)
+ {
+ const LLUUID &id = *it;
+ LLRemoteParcelInfoProcessor::getInstance()->removeObserver(id, this);
+ }
+ mParcelIDs.clear();
+ }
+
+ /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data)
+ {
+ if (mParent)
+ {
+ if (mForEvents)
+ {
+ mParent->displayEventParcelImage(parcel_data);
+ }
+ else
+ {
+ mParent->displayParcelDetails(parcel_data);
+ }
+ }
+ mParcelIDs.erase(parcel_data.parcel_id);
+ LLRemoteParcelInfoProcessor::getInstance()->removeObserver(parcel_data.parcel_id, this);
+ }
+
+ /*virtual*/ void setParcelID(const LLUUID& parcel_id)
+ {
+ if (!parcel_id.isNull())
+ {
+ mParcelIDs.insert(parcel_id);
+ LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
+ LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
+ }
+ }
+
+ /*virtual*/ void setErrorStatus(S32 status, const std::string& reason)
+ {
+ LL_WARNS("Search") << "Can't complete remote parcel request. Http Status: " << status << ". Reason : " << reason << LL_ENDL;
+ }
+private:
+ std::set<LLUUID> mParcelIDs;
+ FSFloaterSearch* mParent;
+ bool mForEvents;
+};
+
+///// Avatar Properties Observer /////
+
+class FSSearchAvatarPropertiesObserver : public LLAvatarPropertiesObserver
+{
+public:
+ FSSearchAvatarPropertiesObserver(FSFloaterSearch* floater) : LLAvatarPropertiesObserver(),
+ mParent(floater)
+ {}
+
+ ~FSSearchAvatarPropertiesObserver()
+ {
+ // remove any in-flight observers
+ std::set<LLUUID>::iterator it;
+ for (it = mAvatarIDs.begin(); it != mAvatarIDs.end(); ++it)
+ {
+ const LLUUID &id = *it;
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(id, this);
+ }
+ mAvatarIDs.clear();
+ }
+
+ void processProperties(void* data, EAvatarProcessorType type)
+ {
+ if (!data)
+ return;
+
+ if (APT_PROPERTIES == type)
+ {
+ LLAvatarData* avatar_data = static_cast<LLAvatarData*>(data);
+ if (avatar_data)
+ {
+ mParent->displayAvatarDetails(avatar_data);
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(avatar_data->avatar_id, this);
+ }
+ }
+ else if (APT_PROPERTIES_LEGACY == type)
+ {
+ LLAvatarData avatar_data(*static_cast<LLAvatarLegacyData*>(data));
+ mParent->displayAvatarDetails(&avatar_data);
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(avatar_data.avatar_id, this);
+ }
+ if (APT_CLASSIFIED_INFO == type)
+ {
+ LLAvatarClassifiedInfo* c_info = static_cast<LLAvatarClassifiedInfo*>(data);
+ if (c_info)
+ {
+ mParent->displayClassifiedDetails(c_info);
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(c_info->classified_id, this);
+ std::string url = gAgent.getRegionCapability("SearchStatRequest");
+ if (!url.empty())
+ {
+ LL_INFOS("Search") << "Classified stat request via capability" << LL_ENDL;
+ LLSD body;
+ body["classified_id"] = c_info->classified_id;
+ LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, body, boost::bind(&LLPanelProfileClassified::handleSearchStatResponse, c_info->classified_id, _1));
+ }
+ }
+ }
+ }
+private:
+ std::set<LLUUID> mAvatarIDs;
+ FSFloaterSearch* mParent;
+};
+
+///// Group Info Observer /////
+
+class FSSearchGroupInfoObserver : public LLGroupMgrObserver
+{
+public:
+ FSSearchGroupInfoObserver(const LLUUID& group_id, FSFloaterSearch* parent) :
+ LLGroupMgrObserver(group_id),
+ mParent(parent)
+ {
+ LLGroupMgr* groupmgr = LLGroupMgr::getInstance();
+ if (!group_id.isNull() && groupmgr)
+ {
+ groupmgr->addObserver(this);
+ mID = group_id;
+ groupmgr->sendGroupPropertiesRequest(group_id);
+ }
+ }
+
+ ~FSSearchGroupInfoObserver()
+ {
+ LLGroupMgr::getInstance()->removeObserver(this);
+ }
+
+ void changed(LLGroupChange gc)
+ {
+ if (gc == GC_PROPERTIES)
+ {
+ LLGroupMgrGroupData* group_data = LLGroupMgr::getInstance()->getGroupData(mID);
+ mParent->displayGroupDetails(group_data);
+ LLGroupMgr::getInstance()->removeObserver(this);
+ }
+ }
+private:
+ FSFloaterSearch* mParent;
+ LLUUID mID;
+};
+
+///// Silly Classified Clickthrough Class /////
+class FSDispatchClassifiedClickThrough : public LLDispatchHandler
+{
+public:
+ virtual bool operator()(
+ const LLDispatcher* dispatcher,
+ const std::string& key,
+ const LLUUID& invoice,
+ const sparam_t& strings)
+ {
+ if (strings.size() != 4) return false;
+ LLUUID classified_id(strings[0]);
+ S32 teleport_clicks = atoi(strings[1].c_str());
+ S32 map_clicks = atoi(strings[2].c_str());
+ S32 profile_clicks = atoi(strings[3].c_str());
+
+ LLPanelProfileClassified::setClickThrough(
+ classified_id, teleport_clicks, map_clicks, profile_clicks, false);
+
+ return true;
+ }
+};
+static FSDispatchClassifiedClickThrough sClassifiedClickThrough;
+
+SearchQuery::SearchQuery()
+: category("category", "")
+, query("query")
+{}
+
+////////////////////////////////////////
+// The floater itself //
+////////////////////////////////////////
+
+FSFloaterSearch::FSFloaterSearch(const Params& key)
+: LLFloater(key)
+{
+ mRemoteParcelObserver = new FSSearchRemoteParcelInfoObserver(this, false);
+ mRemoteParcelEventLocationObserver = new FSSearchRemoteParcelInfoObserver(this, true);
+ mAvatarPropertiesObserver = new FSSearchAvatarPropertiesObserver(this);
+ mEventNotifierConnection = gEventNotifier.setNewEventCallback(boost::bind(&FSFloaterSearch::displayEventDetails, this, boost::placeholders::_1));
+}
+
+FSFloaterSearch::~FSFloaterSearch()
+{
+ mEventNotifierConnection.disconnect();
+ delete mRemoteParcelObserver;
+ delete mRemoteParcelEventLocationObserver;
+ delete mAvatarPropertiesObserver;
+ gGenericDispatcher.addHandler("classifiedclickthrough", nullptr);
+}
+
+// virtual
+void FSFloaterSearch::onOpen(const LLSD& key)
+{
+ Params p(key);
+ mPanelWeb->loadURL(p.search);
+ if (key.has("query"))
+ {
+ mTabContainer->selectTabPanel(mPanelWeb);
+ }
+ else if (key.has("tab") && key["tab"].asString() == "groups")
+ {
+ mTabContainer->selectTabPanel(mPanelGroups);
+ }
+
+ FSSearchPanelBase* current_panel = dynamic_cast<FSSearchPanelBase*>(mTabContainer->getCurrentPanel());
+ if (current_panel)
+ {
+ current_panel->focusDefaultElement();
+ }
+}
+
+//virtual
+void FSFloaterSearch::onClose(bool app_quitting)
+{
+ if (mTabContainer)
+ {
+ gSavedSettings.setS32("FSLastSearchTab", mTabContainer->getCurrentPanelIndex());
+ }
+}
+
+BOOL FSFloaterSearch::postBuild()
+{
+ childSetAction("people_profile_btn", boost::bind(&FSFloaterSearch::onBtnPeopleProfile, this));
+ childSetAction("people_message_btn", boost::bind(&FSFloaterSearch::onBtnPeopleIM, this));
+ childSetAction("people_friend_btn", boost::bind(&FSFloaterSearch::onBtnPeopleFriend, this));
+ childSetAction("group_profile_btn", boost::bind(&FSFloaterSearch::onBtnGroupProfile, this));
+ childSetAction("group_message_btn", boost::bind(&FSFloaterSearch::onBtnGroupChat, this));
+ childSetAction("group_join_btn", boost::bind(&FSFloaterSearch::onBtnGroupJoin, this));
+ childSetAction("event_reminder_btn", boost::bind(&FSFloaterSearch::onBtnEventReminder, this));
+ childSetAction("teleport_btn", boost::bind(&FSFloaterSearch::onBtnTeleport, this));
+ childSetAction("map_btn", boost::bind(&FSFloaterSearch::onBtnMap, this));
+ resetVerbs();
+
+ mPanelPeople = findChild<FSPanelSearchPeople>("panel_ls_people");
+ mPanelGroups = findChild<FSPanelSearchGroups>("panel_ls_groups");
+ mPanelPlaces = findChild<FSPanelSearchPlaces>("panel_ls_places");
+ mPanelEvents = findChild<FSPanelSearchEvents>("panel_ls_events");
+ mPanelLand = findChild<FSPanelSearchLand>("panel_ls_land");
+ mPanelClassifieds = findChild<FSPanelSearchClassifieds>("panel_ls_classifieds");
+ mPanelWeb = findChild<FSPanelSearchWeb>("panel_ls_web");
+
+ mDetailsPanel = getChild<LLPanel>("panel_ls_details");
+ mDetailTitle = getChild<LLTextEditor>("title");
+ mDetailDesc = getChild<LLTextEditor>("desc");
+ mDetailAux1 = getChild<LLTextEditor>("aux1");
+ mDetailAux2 = getChild<LLTextEditor>("aux2");
+ mDetailLocation = getChild<LLTextEditor>("location");
+ mDetailSnapshot = getChild<LLTextureCtrl>("snapshot");
+ mDetailSnapshotParcel = getChild<LLTextureCtrl>("snapshot_parcel");
+ mDetailMaturity = getChild<LLIconCtrl>("maturity_icon");
+ mTabContainer = getChild<LLTabContainer>("ls_tabs");
+
+ mTabContainer->setCommitCallback(boost::bind(&FSFloaterSearch::onTabChange, this));
+
+ flushDetails();
+
+ mDetailsPanel->setVisible(false);
+
+ mHasSelection = false;
+
+ if (!mTabContainer->selectTab(gSavedSettings.getS32("FSLastSearchTab")))
+ {
+ mTabContainer->selectFirstTab();
+ }
+
+ return TRUE;
+}
+
+void FSFloaterSearch::onTabChange()
+{
+ LL_INFOS() << "onTabChange()()" << LL_ENDL;
+
+ flushDetails();
+
+ LLPanel* active_panel = mTabContainer->getCurrentPanel();
+
+ if (active_panel == mPanelWeb)
+ {
+ mDetailsPanel->setVisible(false);
+ mPanelWeb->resetFocusOnLoad();
+ }
+ else if (active_panel == mPanelPeople)
+ {
+ mDetailsPanel->setVisible(mHasSelection);
+ }
+
+ if (active_panel == mPanelPeople || active_panel == mPanelGroups)
+ {
+ mDetailSnapshotParcel->setVisible(FALSE);
+ mDetailSnapshot->setVisible(TRUE);
+ }
+ else if (active_panel == mPanelPlaces || active_panel == mPanelLand ||
+ active_panel == mPanelEvents || active_panel == mPanelClassifieds)
+ {
+ mDetailSnapshot->setVisible(FALSE);
+ mDetailSnapshotParcel->setVisible(TRUE);
+ }
+}
+
+//static
+template <class T>
+T* FSFloaterSearch::getSearchPanel(const std::string& panel_name)
+{
+ FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search");
+ if (search_instance && search_instance->mTabContainer)
+ {
+ return dynamic_cast<T*>(search_instance->mTabContainer->getPanelByName(panel_name));
+ }
+ else
+ {
+ return nullptr;
+ }
+}
+
+void FSFloaterSearch::onSelectedItem(const LLUUID& selected_item, ESearchCategory type)
+{
+ LL_INFOS() << "onSelectedItem()" << LL_ENDL;
+
+ if (!selected_item.isNull())
+ {
+ mSelectedID = selected_item;
+ resetVerbs();
+ flushDetails();
+ switch (type)
+ {
+ case SC_AVATAR:
+ {
+ LLAvatarPropertiesProcessor::getInstance()->addObserver(selected_item, mAvatarPropertiesObserver);
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesRequest(selected_item);
+ }
+ break;
+ case SC_GROUP:
+ mGroupPropertiesRequest = new FSSearchGroupInfoObserver(selected_item, this);
+ break;
+ case SC_PLACE:
+ mRemoteParcelObserver->setParcelID(selected_item);
+ break;
+ case SC_CLASSIFIED:
+ LLAvatarPropertiesProcessor::getInstance()->addObserver(selected_item, mAvatarPropertiesObserver);
+ LLAvatarPropertiesProcessor::getInstance()->sendClassifiedInfoRequest(selected_item);
+ gGenericDispatcher.addHandler("classifiedclickthrough", &sClassifiedClickThrough);
+ break;
+ }
+ setLoadingProgress(true);
+ }
+}
+
+void FSFloaterSearch::onSelectedEvent(const S32 selected_event)
+{
+ LL_INFOS() << "onSelectedEvent()()" << LL_ENDL;
+
+ resetVerbs();
+ flushDetails();
+
+ gMessageSystem->newMessageFast(_PREHASH_EventInfoRequest);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
+ gMessageSystem->nextBlockFast(_PREHASH_EventData);
+ gMessageSystem->addU32Fast(_PREHASH_EventID, selected_event);
+ gAgent.sendReliableMessage();
+}
+
+void FSFloaterSearch::displayParcelDetails(const LLParcelData& parcel_data)
+{
+ S32 region_x;
+ S32 region_y;
+ S32 region_z;
+ region_x = ll_round(parcel_data.global_x) % REGION_WIDTH_UNITS;
+ region_y = ll_round(parcel_data.global_y) % REGION_WIDTH_UNITS;
+ region_z = ll_round(parcel_data.global_z);
+ // HACK: Flag 0x2 == adult region,
+ // Flag 0x1 == mature region, otherwise assume PG
+ if (parcel_data.flags & 0x2)
+ {
+ mDetailMaturity->setValue("Parcel_R_Dark");
+ }
+ else if (parcel_data.flags & 0x1)
+ {
+ mDetailMaturity->setValue("Parcel_M_Dark");
+ }
+ else
+ {
+ mDetailMaturity->setValue("Parcel_PG_Dark");
+ }
+
+ LLStringUtil::format_map_t map;
+ map["DWELL"] = llformat("%.0f", (F64)parcel_data.dwell);
+ map["AREA"] = llformat("%d m²", parcel_data.actual_area);
+ map["LOCATION"] = llformat("%s (%d, %d, %d)", parcel_data.sim_name.c_str(), region_x, region_y, region_z);
+
+ mParcelGlobal = LLVector3d(parcel_data.global_x, parcel_data.global_y, parcel_data.global_z);
+ mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_places" || mTabContainer->getCurrentPanel()->getName() == "panel_ls_land");
+ mHasSelection = true;
+ mDetailMaturity->setVisible(true);
+ mDetailTitle->setValue(parcel_data.name);
+ mDetailDesc->setValue(parcel_data.desc);
+ mDetailAux1->setValue(getString("string.traffic", map));
+ mDetailAux2->setValue(getString("string.area", map));
+ mDetailLocation->setValue(getString("string.location", map));
+ mDetailSnapshotParcel->setValue(parcel_data.snapshot_id);
+ childSetVisible("teleport_btn", true);
+ childSetVisible("map_btn", true);
+ setLoadingProgress(false);
+}
+
+void FSFloaterSearch::displayAvatarDetails(LLAvatarData* avatar_data)
+{
+ if (avatar_data)
+ {
+ LLStringUtil::format_map_t map;
+ map["AGE"] = LLDateUtil::ageFromDate(avatar_data->born_on, LLDate::now());
+ if (avatar_data->partner_id.notNull())
+ {
+ map["PARTNER"] = LLSLURL("agent", avatar_data->partner_id, "inspect").getSLURLString();
+ mDetailAux2->setValue(getString("string.partner", map));
+ }
+
+ mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_people");
+ mHasSelection = true;
+ mDetailTitle->setValue(LLTrans::getString("LoadingData"));
+ mDetailDesc->setValue(avatar_data->about_text);
+ mDetailSnapshot->setValue(avatar_data->image_id);
+ mDetailAux1->setValue(avatar_data->hide_age ? "" : getString("string.age", map));
+ LLAvatarNameCache::get(avatar_data->avatar_id, boost::bind(&FSFloaterSearch::avatarNameUpdatedCallback,this, _1, _2));
+ childSetVisible("people_profile_btn", true);
+ childSetVisible("people_message_btn", true);
+ childSetVisible("people_friend_btn", true);
+ getChildView("people_friend_btn")->setEnabled(!LLAvatarActions::isFriend(avatar_data->avatar_id));
+ }
+}
+
+void FSFloaterSearch::displayGroupDetails(LLGroupMgrGroupData*& group_data)
+{
+ if (group_data)
+ {
+ LLStringUtil::format_map_t map;
+ map["MEMBER_COUNT"] = llformat("%d",group_data->mMemberCount);
+ map["FOUNDER"] = LLSLURL("agent", group_data->mFounderID, "inspect").getSLURLString();
+
+ mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_groups");
+ mHasSelection = true;
+ mDetailTitle->setValue(LLTrans::getString("LoadingData"));
+ mDetailDesc->setValue(group_data->mCharter);
+ mDetailSnapshot->setValue(group_data->mInsigniaID);
+ mDetailAux1->setValue(getString("string.members", map));
+ mDetailAux2->setValue(getString("string.founder", map));
+ LLGroupData agent_gdatap;
+ bool is_member = gAgent.getGroupData(getSelectedID(),agent_gdatap) || gAgent.isGodlike();
+ bool join_btn_enabled = !is_member && group_data->mOpenEnrollment;
+ childSetVisible("group_profile_btn", true);
+ childSetVisible("group_message_btn", true);
+ childSetVisible("group_join_btn", true);
+ getChildView("group_join_btn")->setEnabled(join_btn_enabled);
+ getChildView("group_message_btn")->setEnabled(is_member);
+ gCacheName->getGroup(getSelectedID(), boost::bind(&FSFloaterSearch::groupNameUpdatedCallback, this, _1, _2, _3));
+ }
+}
+
+void FSFloaterSearch::displayClassifiedDetails(LLAvatarClassifiedInfo*& c_info)
+{
+ if (c_info)
+ {
+ if (c_info->flags & CLASSIFIED_FLAG_MATURE)
+ {
+ mDetailMaturity->setValue("Parcel_M_Dark");
+ }
+ else
+ {
+ mDetailMaturity->setValue("Parcel_PG_Dark");
+ }
+
+ LLStringUtil::format_map_t map;
+ map["LISTING_PRICE"] = llformat("L$%d", c_info->price_for_listing);
+ map["SLURL"] = LLSLURL("parcel", c_info->parcel_id, "about").getSLURLString();
+
+ mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_classifieds");
+ mHasSelection = true;
+ mDetailMaturity->setVisible(true);
+ mParcelGlobal = c_info->pos_global;
+ mDetailTitle->setValue(c_info->name);
+ mDetailDesc->setValue(c_info->description);
+ mDetailSnapshotParcel->setValue(c_info->snapshot_id);
+ mDetailAux1->setValue(getString("string.listing_price", map));
+ mDetailLocation->setValue(getString("string.slurl", map));
+ childSetVisible("teleport_btn", true);
+ childSetVisible("map_btn", true);
+ setLoadingProgress(false);
+ }
+}
+
+bool FSFloaterSearch::displayEventDetails(LLEventStruct event)
+{
+ if (event.flags == EVENT_FLAG_ADULT)
+ {
+ mDetailMaturity->setValue("Parcel_R_Dark");
+ }
+ else if (event.flags == EVENT_FLAG_MATURE)
+ {
+ mDetailMaturity->setValue("Parcel_M_Dark");
+ }
+ else
+ {
+ mDetailMaturity->setValue("Parcel_PG_Dark");
+ }
+
+ S32 region_x;
+ S32 region_y;
+ S32 region_z;
+ region_x = (S64)ll_round(event.globalPos.mdV[VX]) % REGION_WIDTH_UNITS;
+ region_y = (S64)ll_round(event.globalPos.mdV[VY]) % REGION_WIDTH_UNITS;
+ region_z = (S32)ll_round(event.globalPos.mdV[VZ]);
+ LLStringUtil::format_map_t map;
+ map["DURATION"] = llformat("%d:%.2d", event.duration / 60, event.duration % 60);
+ map["LOCATION"] = llformat("%s (%d, %d, %d)", event.simName.c_str(), region_x, region_y, region_z);
+ if (event.cover > 0)
+ {
+ map["COVERCHARGE"] = llformat("L$%d", event.cover);
+ mDetailAux2->setValue(getString("string.covercharge", map));
+ }
+
+ mParcelGlobal = event.globalPos;
+ mEventID = event.eventId;
+ mDetailsPanel->setVisible(mTabContainer->getCurrentPanel()->getName() == "panel_ls_events");
+ mHasSelection = true;
+ mDetailMaturity->setVisible(true);
+ mDetailTitle->setValue(event.eventName);
+ mDetailDesc->setValue(event.desc);
+ mDetailAux1->setValue(getString("string.duration", map));
+ mDetailLocation->setValue(getString("string.location", map));
+ mDetailSnapshotParcel->setValue(LLUUID::null);
+ childSetVisible("teleport_btn", true);
+ childSetVisible("map_btn", true);
+ childSetVisible("event_reminder_btn", true);
+
+ LLWorldMapMessage::getInstance()->sendNamedRegionRequest(event.simName, boost::bind(&FSFloaterSearch::regionHandleCallback, this, _1, event.globalPos), "", false);
+ return true;
+}
+
+void FSFloaterSearch::regionHandleCallback(U64 region_handle, LLVector3d pos_global)
+{
+ std::string url = gAgent.getRegionCapability("RemoteParcelRequest");
+ if (!url.empty())
+ {
+ auto region_origin = from_region_handle(region_handle);
+ LLVector3 pos_region(LLVector3(pos_global - region_origin));
+
+ LLRemoteParcelInfoProcessor::getInstance()->requestRegionParcelInfo(url,
+ LLUUID::null, pos_region, pos_global, mRemoteParcelEventLocationObserver->getObserverHandle());
+ }
+ else
+ {
+ setLoadingProgress(false);
+ }
+}
+
+void FSFloaterSearch::displayEventParcelImage(const LLParcelData& parcel_data)
+{
+ mDetailSnapshotParcel->setValue(parcel_data.snapshot_id);
+ setLoadingProgress(false);
+}
+
+void FSFloaterSearch::avatarNameUpdatedCallback(const LLUUID& id, const LLAvatarName& av_name)
+{
+ if (id == getSelectedID())
+ {
+ mDetailTitle->setValue(av_name.getCompleteName());
+ setLoadingProgress(false);
+ }
+ // Otherwise possibly a request for an older selection, ignore it.
+}
+
+void FSFloaterSearch::groupNameUpdatedCallback(const LLUUID& id, const std::string& name, bool is_group)
+{
+ if (id == getSelectedID())
+ {
+ mDetailTitle->setValue( LLSD(name) );
+ setLoadingProgress(false);
+ }
+ // Otherwise possibly a request for an older selection, ignore it.
+}
+
+void FSFloaterSearch::setLoadingProgress(bool started)
+{
+ LLLoadingIndicator* indicator = getChild<LLLoadingIndicator>("loading");
+
+ indicator->setVisible(started);
+
+ if (started)
+ {
+ indicator->start();
+ }
+ else
+ {
+ indicator->stop();
+ }
+}
+
+void FSFloaterSearch::resetVerbs()
+{
+ childSetVisible("people_profile_btn", false);
+ childSetVisible("people_message_btn", false);
+ childSetVisible("people_friend_btn", false);
+ childSetVisible("group_profile_btn", false);
+ childSetVisible("group_message_btn", false);
+ childSetVisible("group_join_btn", false);
+ childSetVisible("event_reminder_btn", false);
+ childSetVisible("teleport_btn", false);
+ childSetVisible("map_btn", false);
+}
+
+void FSFloaterSearch::flushDetails()
+{
+ LL_INFOS() << "flushDetails()" << LL_ENDL;
+ mDetailTitle->setValue("");
+ mDetailDesc->setValue("");
+ mDetailAux1->setValue("");
+ mDetailAux2->setValue("");
+ mDetailLocation->setValue("");
+ mDetailSnapshot->setValue(LLSD());
+ mDetailMaturity->setVisible(false);
+ mParcelGlobal.setZero();
+}
+
+void FSFloaterSearch::onBtnPeopleProfile()
+{
+ LLAvatarActions::showProfile(getSelectedID());
+}
+
+void FSFloaterSearch::onBtnPeopleIM()
+{
+ LLAvatarActions::startIM(getSelectedID());
+}
+
+void FSFloaterSearch::onBtnPeopleFriend()
+{
+ LLAvatarActions::requestFriendshipDialog(getSelectedID());
+}
+
+void FSFloaterSearch::onBtnGroupProfile()
+{
+ LLGroupActions::show(getSelectedID());
+}
+
+void FSFloaterSearch::onBtnGroupChat()
+{
+ LLGroupActions::startIM(getSelectedID());
+}
+
+void FSFloaterSearch::onBtnGroupJoin()
+{
+ LLGroupActions::join(getSelectedID());
+}
+
+void FSFloaterSearch::onBtnTeleport()
+{
+ if (!mParcelGlobal.isExactlyZero())
+ {
+ gAgent.teleportViaLocation(mParcelGlobal);
+ LLFloaterWorldMap::getInstance()->trackLocation(mParcelGlobal);
+ /// <FS:CR> What should we do when when we teleport? The default (1) is to close the floater,
+ /// the user may elect to minimize the floater (2), or to do nothing (any other setting)
+ static LLCachedControl<U32> teleport_action(gSavedSettings, "FSLegacySearchActionOnTeleport");
+ if (teleport_action == 1)
+ {
+ closeFloater();
+ }
+ else if (teleport_action == 2)
+ {
+ setMinimized(TRUE);
+ }
+ }
+}
+
+void FSFloaterSearch::onBtnMap()
+{
+ if (!mParcelGlobal.isExactlyZero())
+ {
+ LLFloaterWorldMap::getInstance()->trackLocation(mParcelGlobal);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
+}
+
+void FSFloaterSearch::onBtnEventReminder()
+{
+ gEventNotifier.add(mEventID);
+}
+
+////////////////////////////////////////
+// People Search Panel //
+////////////////////////////////////////
+
+static LLPanelInjector<FSPanelSearchPeople> t_panel_fs_search_people("panel_ls_people");
+
+FSPanelSearchPeople::FSPanelSearchPeople() : FSSearchPanelBase()
+, mQueryID(nullptr)
+, mStartSearch(0)
+, mResultsReceived(0)
+, mResultsContent()
+, mAvatarNameCallbackConnection()
+{
+}
+
+FSPanelSearchPeople::~FSPanelSearchPeople()
+{
+ if (mAvatarNameCallbackConnection.connected())
+ {
+ mAvatarNameCallbackConnection.disconnect();
+ }
+}
+
+BOOL FSPanelSearchPeople::postBuild()
+{
+ mSearchComboBox = findChild<LLSearchComboBox>("people_edit");
+ mSearchResults = findChild<LLScrollListCtrl>("search_results_people");
+ if (mSearchComboBox)
+ {
+ mSearchComboBox->setCommitCallback(boost::bind(&FSPanelSearchPeople::onBtnFind, this));
+ fillSearchComboBox(mSearchComboBox);
+ }
+ if (mSearchResults)
+ {
+ mSearchResults->setCommitCallback(boost::bind(&FSPanelSearchPeople::onSelectItem, this));
+ mSearchResults->setEnabled(FALSE);
+ mSearchResults->setCommentText(LLTrans::getString("no_results"));
+ mSearchResults->setContextMenu(LLScrollListCtrl::MENU_AVATAR);
+ }
+
+ childSetAction("people_next", boost::bind(&FSPanelSearchPeople::onBtnNext, this));
+ childSetAction("people_back", boost::bind(&FSPanelSearchPeople::onBtnBack, this));
+ getChildView("people_next")->setEnabled(FALSE);
+ getChildView("people_back")->setEnabled(FALSE);
+
+ return TRUE;
+}
+
+void FSPanelSearchPeople::focusDefaultElement()
+{
+ mSearchComboBox->focusTextEntry();
+}
+
+void FSPanelSearchPeople::find()
+{
+ std::string text = mSearchComboBox->getSimple();
+ boost::trim(text);
+
+ if (text.size() <= MIN_SEARCH_STRING_SIZE)
+ {
+ mSearchResults->setCommentText(LLTrans::getString("search_short"));
+ return;
+ }
+
+ if (LLUUID::validate(text))
+ {
+ LLUUID id(text);
+
+ mSearchResults->deleteAllItems();
+ mSearchResults->setCommentText(LLTrans::getString("searching"));
+ mResultsReceived = 0;
+ mNumResultsReturned = 0;
+
+ if (mAvatarNameCallbackConnection.connected())
+ {
+ mAvatarNameCallbackConnection.disconnect();
+ }
+ mAvatarNameCallbackConnection = LLAvatarNameCache::get(id, boost::bind(&FSPanelSearchPeople::onAvatarNameCallback, this, _1, _2));
+
+ return;
+ }
+
+ LLStringUtil::replaceChar(text, '.', ' ');
+
+ mResultsReceived = 0;
+ if (mQueryID.notNull())
+ {
+ mQueryID.setNull();
+ }
+ mQueryID.generate();
+
+ if (mStartSearch < 0)
+ {
+ mStartSearch = 0;
+ }
+
+ gMessageSystem->newMessage("DirFindQuery");
+ gMessageSystem->nextBlock("AgentData");
+ gMessageSystem->addUUID("AgentID", gAgentID);
+ gMessageSystem->addUUID("SessionID", gAgentSessionID);
+ gMessageSystem->nextBlock("QueryData");
+ gMessageSystem->addUUID("QueryID", getQueryID());
+ gMessageSystem->addString("QueryText", text);
+ gMessageSystem->addU32("QueryFlags", DFQ_PEOPLE);
+ gMessageSystem->addS32("QueryStart", mStartSearch);
+ gAgent.sendReliableMessage();
+ LL_INFOS("Search") << "Firing off search request: " << getQueryID() << LL_ENDL;
+
+ mSearchResults->deleteAllItems();
+ mSearchResults->setCommentText(LLTrans::getString("searching"));
+ mNumResultsReturned = 0;
+}
+
+void FSPanelSearchPeople::onBtnFind()
+{
+ std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
+ auto elapsed = now - lastRequestTime;
+ U64 elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
+ if(elapsedMS < REQUEST_MIN_ELAPSED_TIME) return;
+ lastRequestTime = now;
+
+ std::string text = mSearchComboBox->getSimple();
+
+ if (!text.empty())
+ {
+ LLSearchHistory::getInstance()->addEntry(text);
+ }
+
+ resetSearch();
+
+ find();
+}
+
+void FSPanelSearchPeople::onBtnNext()
+{
+ mStartSearch += RESULT_PAGE_SIZE;
+ getChildView("people_back")->setEnabled(TRUE);
+
+ find();
+}
+
+void FSPanelSearchPeople::onBtnBack()
+{
+ mStartSearch -= RESULT_PAGE_SIZE;
+ getChildView("people_back")->setEnabled(mStartSearch > 0);
+
+ find();
+}
+
+void FSPanelSearchPeople::resetSearch()
+{
+ mStartSearch = 0;
+ getChildView("people_back")->setEnabled(FALSE);
+ getChildView("people_next")->setEnabled(FALSE);
+}
+
+S32 FSPanelSearchPeople::showNextButton(S32 rows)
+{
+ bool show_next_button = (mResultsReceived > RESULT_PAGE_SIZE);
+ getChildView("people_next")->setEnabled(show_next_button);
+ if (show_next_button)
+ {
+ rows -= (mResultsReceived - RESULT_PAGE_SIZE);
+ }
+ return rows;
+}
+
+void FSPanelSearchPeople::onSelectItem()
+{
+ if (!mSearchResults)
+ {
+ return;
+ }
+ FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search");
+ if (search_instance)
+ {
+ search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_AVATAR);
+ }
+}
+
+// static
+void FSPanelSearchPeople::processSearchReply(LLMessageSystem* msg, void**)
+{
+ LLUUID query_id;
+ std::string first_name;
+ std::string last_name;
+ LLUUID agent_id;
+
+ msg->getUUIDFast(_PREHASH_QueryData, _PREHASH_QueryID, query_id);
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id);
+
+ // This result is not for us.
+ if (agent_id != gAgentID)
+ {
+ return;
+ }
+ LL_INFOS("Search") << "received search results - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL;
+
+ FSPanelSearchPeople* self = FSFloaterSearch::getSearchPanel<FSPanelSearchPeople>("panel_ls_people");
+
+ // floater is closed or these are not results from our last request
+ if (!self || query_id != self->getQueryID())
+ {
+ return;
+ }
+
+ LLScrollListCtrl* search_results = self->getChild<LLScrollListCtrl>("search_results_people");
+
+ if (self->mNumResultsReturned++ == 0)
+ {
+ search_results->deleteAllItems();
+ }
+
+ // Check for status messages
+ if (msg->getNumberOfBlocks("StatusData"))
+ {
+ U32 status;
+ msg->getU32("StatusData", "Status", status);
+ if (status & STATUS_SEARCH_PLACES_FOUNDNONE)
+ {
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("people_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ return;
+ }
+ else if (status & STATUS_SEARCH_PLACES_SHORTSTRING)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_short"));
+ return;
+ }
+ else if (status & STATUS_SEARCH_PLACES_BANNEDWORD)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_banned"));
+ return;
+ }
+ else if (status & STATUS_SEARCH_PLACES_SEARCHDISABLED)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_disabled"));
+ return;
+ }
+ }
+
+ bool found_one = false;
+ S32 num_new_rows = msg->getNumberOfBlocksFast(_PREHASH_QueryReplies);
+ if (num_new_rows == 0 && self->mResultsReceived == 0)
+ {
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("people_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ }
+
+ self->mResultsReceived += num_new_rows;
+ num_new_rows = self->showNextButton(num_new_rows);
+
+ for (S32 i = 0; i < num_new_rows; i++)
+ {
+ msg->getStringFast( _PREHASH_QueryReplies, _PREHASH_FirstName, first_name, i);
+ msg->getStringFast( _PREHASH_QueryReplies, _PREHASH_LastName, last_name, i);
+ msg->getUUIDFast( _PREHASH_QueryReplies, _PREHASH_AgentID, agent_id, i);
+ //msg->getU8Fast( _PREHASH_QueryReplies, _PREHASH_Online, online, i);
+
+ if (agent_id.isNull())
+ {
+ LL_INFOS("Search") << "Null result returned for QueryID: " << query_id << LL_ENDL;
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("people_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ }
+ else
+ {
+ LL_DEBUGS("Search") << "Got: " << first_name << " " << last_name << " AgentID: " << agent_id << LL_ENDL;
+ search_results->setEnabled(TRUE);
+ found_one = true;
+
+ std::string avatar_name;
+ avatar_name = LLCacheName::buildFullName(first_name, last_name);
+
+ LLSD content;
+ LLSD element;
+
+ element["id"] = agent_id;
+
+ element["columns"][0]["column"] = "icon";
+ element["columns"][0]["type"] = "icon";
+ element["columns"][0]["value"] = "icon_avatar_offline.tga";
+
+ element["columns"][1]["column"] = "username";
+ element["columns"][1]["value"] = avatar_name;
+
+ content["name"] = avatar_name;
+
+ search_results->addElement(element, ADD_BOTTOM);
+ self->mResultsContent[agent_id.asString()] = content;
+ }
+ }
+ if (found_one)
+ {
+ search_results->selectFirstItem();
+ search_results->setFocus(TRUE);
+ self->onSelectItem();
+ }
+}
+
+void FSPanelSearchPeople::onAvatarNameCallback(const LLUUID& id, const LLAvatarName& av_name)
+{
+ if (mAvatarNameCallbackConnection.connected())
+ {
+ mAvatarNameCallbackConnection.disconnect();
+ }
+
+ LLScrollListCtrl* search_results = getChild<LLScrollListCtrl>("search_results_people");
+
+ if (av_name.getAccountName() != "(?\?\?).(?\?\?)")
+ {
+ LLSD content;
+ LLSD data;
+ data["id"] = id;
+
+ data["columns"][0]["column"] = "icon";
+ data["columns"][0]["type"] = "icon";
+ data["columns"][0]["value"] = "icon_avatar_offline.tga";
+
+ data["columns"][1]["name"] = "username";
+ data["columns"][1]["value"] = av_name.getUserName();
+
+ content["name"] = av_name.getUserName();
+
+ search_results->addElement(data);
+
+ mResultsContent[id.asString()] = content;
+ mResultsReceived = 1;
+ mNumResultsReturned = 1;
+
+ search_results->setEnabled(TRUE);
+ search_results->selectFirstItem();
+ search_results->setFocus(TRUE);
+ onSelectItem();
+ }
+ else
+ {
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = getChild<LLUICtrl>("people_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ }
+}
+
+////////////////////////////////////////
+// Groups Search Panel //
+////////////////////////////////////////
+
+static LLPanelInjector<FSPanelSearchGroups> t_panel_fs_search_groups("panel_ls_groups");
+
+FSPanelSearchGroups::FSPanelSearchGroups() : FSSearchPanelBase()
+, mQueryID(nullptr)
+, mStartSearch(0)
+, mResultsReceived(0)
+, mResultsContent()
+{
+}
+
+FSPanelSearchGroups::~FSPanelSearchGroups()
+{
+}
+
+BOOL FSPanelSearchGroups::postBuild()
+{
+ mSearchComboBox = findChild<LLSearchComboBox>("groups_edit");
+ mSearchResults = findChild<LLScrollListCtrl>("search_results_groups");
+ if (mSearchComboBox)
+ {
+ mSearchComboBox->setCommitCallback(boost::bind(&FSPanelSearchGroups::onBtnFind, this));
+ fillSearchComboBox(mSearchComboBox);
+ }
+ if (mSearchResults)
+ {
+ mSearchResults->setCommitCallback(boost::bind(&FSPanelSearchGroups::onSelectItem, this));
+ mSearchResults->setEnabled(FALSE);
+ mSearchResults->setCommentText(LLTrans::getString("no_results"));
+ }
+
+ childSetAction("groups_next", boost::bind(&FSPanelSearchGroups::onBtnNext, this));
+ childSetAction("groups_back", boost::bind(&FSPanelSearchGroups::onBtnBack, this));
+ getChildView("groups_next")->setEnabled(FALSE);
+ getChildView("groups_back")->setEnabled(FALSE);
+
+ lastRequestTime = std::chrono::system_clock::now();
+
+ return TRUE;
+}
+
+void FSPanelSearchGroups::focusDefaultElement()
+{
+ mSearchComboBox->focusTextEntry();
+}
+
+void FSPanelSearchGroups::find()
+{
+ std::string text = filterShortWords(mSearchComboBox->getSimple());
+ if (text.size() == 0)
+ {
+ mSearchResults->setCommentText(LLTrans::getString("search_short"));
+ return;
+ }
+
+ static LLUICachedControl<bool> inc_pg("ShowPGSims", 1);
+ static LLUICachedControl<bool> inc_mature("ShowMatureSims", 0);
+ static LLUICachedControl<bool> inc_adult("ShowAdultSims", 0);
+ if (!(inc_pg || inc_mature || inc_adult))
+ {
+ LLNotificationsUtil::add("NoContentToSearch");
+ return;
+ }
+ U32 scope = 0;
+ if (gAgent.wantsPGOnly())
+ {
+ scope |= DFQ_PG_SIMS_ONLY;
+ }
+ bool adult_enabled = gAgent.canAccessAdult();
+ bool mature_enabled = gAgent.canAccessMature();
+ if (inc_pg)
+ {
+ scope |= DFQ_INC_PG;
+ }
+ if (inc_mature && mature_enabled)
+ {
+ scope |= DFQ_INC_MATURE;
+ }
+ if (inc_adult && adult_enabled)
+ {
+ scope |= DFQ_INC_ADULT;
+ }
+ scope |= DFQ_GROUPS;
+
+ mResultsReceived = 0;
+ if (mQueryID.notNull())
+ {
+ mQueryID.setNull();
+ }
+ mQueryID.generate();
+
+ if (mStartSearch < 0)
+ {
+ mStartSearch = 0;
+ }
+
+ gMessageSystem->newMessage("DirFindQuery");
+ gMessageSystem->nextBlock("AgentData");
+ gMessageSystem->addUUID("AgentID", gAgentID);
+ gMessageSystem->addUUID("SessionID", gAgentSessionID);
+ gMessageSystem->nextBlock("QueryData");
+ gMessageSystem->addUUID("QueryID", getQueryID());
+ gMessageSystem->addString("QueryText", text);
+ gMessageSystem->addU32("QueryFlags", scope);
+ gMessageSystem->addS32("QueryStart", mStartSearch);
+ gAgent.sendReliableMessage();
+ LL_DEBUGS("Search") << "Firing off search request: " << getQueryID() << LL_ENDL;
+
+ mSearchResults->deleteAllItems();
+ mSearchResults->setCommentText(LLTrans::getString("searching"));
+ mNumResultsReturned = 0;
+}
+
+void FSPanelSearchGroups::onBtnFind()
+{
+ std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
+ auto elapsed = now - lastRequestTime;
+ U64 elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
+ if(elapsedMS < REQUEST_MIN_ELAPSED_TIME) return;
+ lastRequestTime = now;
+
+ std::string text = mSearchComboBox->getSimple();
+ if (!text.empty())
+ {
+ LLSearchHistory::getInstance()->addEntry(text);
+ }
+
+ resetSearch();
+
+ find();
+}
+
+void FSPanelSearchGroups::onBtnNext()
+{
+ mStartSearch += RESULT_PAGE_SIZE;
+ getChildView("groups_back")->setEnabled(TRUE);
+
+ find();
+}
+
+void FSPanelSearchGroups::onBtnBack()
+{
+ mStartSearch -= RESULT_PAGE_SIZE;
+ getChildView("groups_back")->setEnabled(mStartSearch > 0);
+
+ find();
+}
+
+void FSPanelSearchGroups::resetSearch()
+{
+ mStartSearch = 0;
+ getChildView("groups_back")->setEnabled(FALSE);
+ getChildView("groups_next")->setEnabled(FALSE);
+}
+
+S32 FSPanelSearchGroups::showNextButton(S32 rows)
+{
+ bool show_next_button = (mResultsReceived > RESULT_PAGE_SIZE);
+ getChildView("groups_next")->setEnabled(show_next_button);
+ if (show_next_button)
+ {
+ rows -= (mResultsReceived - RESULT_PAGE_SIZE);
+ }
+ return rows;
+}
+
+void FSPanelSearchGroups::onSelectItem()
+{
+ if (!mSearchResults)
+ {
+ return;
+ }
+ FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search");
+ if (search_instance)
+ {
+ search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_GROUP);
+ }
+}
+
+// static
+void FSPanelSearchGroups::processSearchReply(LLMessageSystem* msg, void**)
+{
+ LLUUID query_id;
+ LLUUID group_id;
+ LLUUID agent_id;
+ std::string group_name;
+ S32 members;
+ F32 search_order;
+
+ msg->getUUIDFast( _PREHASH_QueryData, _PREHASH_QueryID, query_id);
+ msg->getUUIDFast( _PREHASH_AgentData, _PREHASH_AgentID, agent_id);
+
+ // Not for us
+ if (agent_id != gAgentID)
+ {
+ return;
+ }
+ LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL;
+
+ FSPanelSearchGroups* self = FSFloaterSearch::getSearchPanel<FSPanelSearchGroups>("panel_ls_groups");
+
+ // floater is closed or these are not results from our last request
+ if (!self || query_id != self->mQueryID)
+ {
+ return;
+ }
+
+ LLScrollListCtrl* search_results = self->getChild<LLScrollListCtrl>("search_results_groups");
+
+ // Clear "Searching" label on first results
+ if (self->mNumResultsReturned++ == 0)
+ {
+ search_results->deleteAllItems();
+ }
+
+ // Check for status messages
+ if (msg->getNumberOfBlocks("StatusData"))
+ {
+ U32 status;
+ msg->getU32("StatusData", "Status", status);
+ if (status & STATUS_SEARCH_PLACES_FOUNDNONE)
+ {
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("groups_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ return;
+ }
+ else if(status & STATUS_SEARCH_PLACES_SHORTSTRING)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_short"));
+ return;
+ }
+ else if (status & STATUS_SEARCH_PLACES_BANNEDWORD)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_banned"));
+ return;
+ }
+ else if (status & STATUS_SEARCH_PLACES_SEARCHDISABLED)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_disabled"));
+ return;
+ }
+ }
+
+ bool found_one = false;
+ S32 num_new_rows = msg->getNumberOfBlocksFast(_PREHASH_QueryReplies);
+ if (num_new_rows == 0 && self->mResultsReceived == 0)
+ {
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("groups_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ }
+
+ self->mResultsReceived += num_new_rows;
+ num_new_rows = self->showNextButton(num_new_rows);
+
+ for (S32 i = 0; i < num_new_rows; i++)
+ {
+ msg->getUUIDFast( _PREHASH_QueryReplies, _PREHASH_GroupID, group_id, i);
+ msg->getStringFast( _PREHASH_QueryReplies, _PREHASH_GroupName, group_name, i);
+ msg->getS32Fast( _PREHASH_QueryReplies, _PREHASH_Members, members, i);
+ msg->getF32Fast( _PREHASH_QueryReplies, _PREHASH_SearchOrder, search_order,i);
+ if (group_id.isNull())
+ {
+ LL_DEBUGS("Search") << "No results returned for QueryID: " << query_id << LL_ENDL;
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("groups_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ }
+ else
+ {
+ LL_DEBUGS("Search") << "Got: " << group_name << " GroupID: " << group_id << LL_ENDL;
+ search_results->setEnabled(TRUE);
+ found_one = true;
+
+ LLSD content;
+ LLSD element;
+
+ element["id"] = group_id;
+
+ element["columns"][0]["column"] = "icon";
+ element["columns"][0]["type"] = "icon";
+ element["columns"][0]["value"] = "Icon_Group";
+
+ element["columns"][1]["column"] = "group_name";
+ element["columns"][1]["value"] = group_name;
+
+ element["columns"][2]["column"] = "members";
+ element["columns"][2]["value"] = members;
+
+ element["columns"][3]["column"] = "score";
+ element["columns"][3]["value"] = search_order;
+
+ content["name"] = group_name;
+
+ search_results->addElement(element, ADD_BOTTOM);
+ self->mResultsContent[group_id.asString()] = content;
+ }
+ }
+ if (found_one)
+ {
+ search_results->selectFirstItem();
+ search_results->setFocus(TRUE);
+ self->onSelectItem();
+ }
+}
+
+////////////////////////////////////////
+// Places Search Panel //
+////////////////////////////////////////
+
+static LLPanelInjector<FSPanelSearchPlaces> t_panel_fs_search_places("panel_ls_places");
+
+FSPanelSearchPlaces::FSPanelSearchPlaces() : FSSearchPanelBase()
+, mQueryID(nullptr)
+, mStartSearch(0)
+, mResultsReceived(0)
+, mResultsContent()
+{
+ mCommitCallbackRegistrar.add("CommitSearch", boost::bind(&FSPanelSearchPlaces::find, this));
+}
+
+FSPanelSearchPlaces::~FSPanelSearchPlaces()
+{
+}
+
+BOOL FSPanelSearchPlaces::postBuild()
+{
+ mSearchComboBox = findChild<LLSearchComboBox>("places_edit");
+ mSearchResults = findChild<LLScrollListCtrl>("search_results_places");
+ mPlacesCategory = findChild<LLComboBox>("places_category");
+ if (mSearchComboBox)
+ {
+ mSearchComboBox->setCommitCallback(boost::bind(&FSPanelSearchPlaces::onBtnFind, this));
+ fillSearchComboBox(mSearchComboBox);
+ }
+ if (mSearchResults)
+ {
+ mSearchResults->setCommitCallback(boost::bind(&FSPanelSearchPlaces::onSelectItem, this));
+ mSearchResults->setEnabled(FALSE);
+ mSearchResults->setCommentText(LLTrans::getString("no_results"));
+ }
+ if (mPlacesCategory)
+ {
+ mPlacesCategory->add(LLTrans::getString("all_categories"), LLSD("any"));
+ mPlacesCategory->addSeparator();
+ for (int category = LLParcel::C_LINDEN; category < LLParcel::C_COUNT; category++)
+ {
+ LLParcel::ECategory eCategory = (LLParcel::ECategory)category;
+ mPlacesCategory->add(LLTrans::getString(LLParcel::getCategoryUIString(eCategory)), LLParcel::getCategoryString(eCategory));
+ }
+ }
+ childSetAction("places_next", boost::bind(&FSPanelSearchPlaces::onBtnNext, this));
+ childSetAction("places_back", boost::bind(&FSPanelSearchPlaces::onBtnBack, this));
+ getChildView("places_next")->setEnabled(FALSE);
+ getChildView("places_back")->setEnabled(FALSE);
+
+ return TRUE;
+}
+
+void FSPanelSearchPlaces::focusDefaultElement()
+{
+ mSearchComboBox->focusTextEntry();
+}
+
+void FSPanelSearchPlaces::find()
+{
+ std::string text = filterShortWords(mSearchComboBox->getSimple());
+ if (text.empty())
+ {
+ mSearchResults->setCommentText(LLTrans::getString("search_short"));
+ return;
+ }
+
+ static LLUICachedControl<bool> inc_pg("ShowPGSims", 1);
+ static LLUICachedControl<bool> inc_mature("ShowMatureSims", 0);
+ static LLUICachedControl<bool> inc_adult("ShowAdultSims", 0);
+ if (!(inc_pg || inc_mature || inc_adult))
+ {
+ LLNotificationsUtil::add("NoContentToSearch");
+ return;
+ }
+ S8 category;
+ std::string category_string = mPlacesCategory->getSelectedValue();
+ if (category_string == "any")
+ {
+ category = LLParcel::C_ANY;
+ }
+ else
+ {
+ category = LLParcel::getCategoryFromString(category_string);
+ }
+ U32 scope = 0;
+ if (gAgent.wantsPGOnly())
+ {
+ scope |= DFQ_PG_SIMS_ONLY;
+ }
+ bool adult_enabled = gAgent.canAccessAdult();
+ bool mature_enabled = gAgent.canAccessMature();
+ if (inc_pg)
+ {
+ scope |= DFQ_INC_PG;
+ }
+ if (inc_mature && mature_enabled)
+ {
+ scope |= DFQ_INC_MATURE;
+ }
+ if (inc_adult && adult_enabled)
+ {
+ scope |= DFQ_INC_ADULT;
+ }
+ scope |= DFQ_DWELL_SORT;
+
+ mResultsReceived = 0;
+ if (mQueryID.notNull())
+ {
+ mQueryID.setNull();
+ }
+ mQueryID.generate();
+
+ if (mStartSearch < 0)
+ {
+ mStartSearch = 0;
+ }
+
+ gMessageSystem->newMessage("DirPlacesQuery");
+ gMessageSystem->nextBlock("AgentData");
+ gMessageSystem->addUUID("AgentID", gAgentID);
+ gMessageSystem->addUUID("SessionID", gAgentSessionID);
+ gMessageSystem->nextBlock("QueryData");
+ gMessageSystem->addUUID("QueryID", getQueryID());
+ gMessageSystem->addString("QueryText", text);
+ gMessageSystem->addU32("QueryFlags", scope);
+ gMessageSystem->addS8("Category", category);
+ // TODO: Search filter by region name.
+ gMessageSystem->addString("SimName", "");
+ gMessageSystem->addS32("QueryStart", mStartSearch);
+ gAgent.sendReliableMessage();
+ LL_INFOS("Search") << "Firing off places search request: " << getQueryID() << LL_ENDL;
+
+ mSearchResults->deleteAllItems();
+ mSearchResults->setCommentText(LLTrans::getString("searching"));
+ mNumResultsReturned = 0;
+}
+
+void FSPanelSearchPlaces::onBtnFind()
+{
+ std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
+ auto elapsed = now - lastRequestTime;
+ U64 elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
+ if(elapsedMS < REQUEST_MIN_ELAPSED_TIME) return;
+ lastRequestTime = now;
+
+ std::string text = mSearchComboBox->getSimple();
+ if (!text.empty())
+ {
+ LLSearchHistory::getInstance()->addEntry(text);
+ }
+
+ resetSearch();
+
+ find();
+}
+
+void FSPanelSearchPlaces::onBtnNext()
+{
+ mStartSearch += RESULT_PAGE_SIZE;
+ getChildView("places_back")->setEnabled(TRUE);
+
+ find();
+}
+
+void FSPanelSearchPlaces::onBtnBack()
+{
+ mStartSearch -= RESULT_PAGE_SIZE;
+ getChildView("places_back")->setEnabled(mStartSearch > 0);
+
+ find();
+}
+
+void FSPanelSearchPlaces::resetSearch()
+{
+ mStartSearch = 0;
+ getChildView("places_back")->setEnabled(FALSE);
+ getChildView("places_next")->setEnabled(FALSE);
+}
+
+S32 FSPanelSearchPlaces::showNextButton(S32 rows)
+{
+ bool show_next_button = (mResultsReceived > RESULT_PAGE_SIZE);
+ getChildView("places_next")->setEnabled(show_next_button);
+ if (show_next_button)
+ {
+ rows -= (mResultsReceived - RESULT_PAGE_SIZE);
+ }
+ return rows;
+}
+
+void FSPanelSearchPlaces::onSelectItem()
+{
+ if (!mSearchResults)
+ {
+ return;
+ }
+ FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search");
+ if (search_instance)
+ {
+ search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_PLACE);
+ }
+}
+
+// static
+void FSPanelSearchPlaces::processSearchReply(LLMessageSystem* msg, void**)
+{
+ LLUUID agent_id;
+ LLUUID query_id;
+ LLUUID parcel_id;
+ std::string name;
+ BOOL for_sale;
+ BOOL auction;
+ F32 dwell;
+
+ msg->getUUID("AgentData", "AgentID", agent_id);
+ msg->getUUID("QueryData", "QueryID", query_id);
+
+ // Not for us
+ if (agent_id != gAgentID)
+ {
+ return;
+ }
+ LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL;
+
+ FSPanelSearchPlaces* self = FSFloaterSearch::getSearchPanel<FSPanelSearchPlaces>("panel_ls_places");
+
+ // floater is closed or these are not results from our last request
+ if (!self || query_id != self->getQueryID())
+ {
+ return;
+ }
+
+ LLScrollListCtrl* search_results = self->getChild<LLScrollListCtrl>("search_results_places");
+
+ // Clear "Searching" label on first results
+ if (self->mNumResultsReturned++ == 0)
+ {
+ search_results->deleteAllItems();
+ }
+
+ // Check for status messages
+ if (msg->getNumberOfBlocks("StatusData"))
+ {
+ U32 status;
+ msg->getU32("StatusData", "Status", status);
+ if (status & STATUS_SEARCH_PLACES_FOUNDNONE)
+ {
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("places_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ return;
+ }
+ else if(status & STATUS_SEARCH_PLACES_SHORTSTRING)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_short"));
+ return;
+ }
+ else if (status & STATUS_SEARCH_PLACES_BANNEDWORD)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_banned"));
+ return;
+ }
+ else if (status & STATUS_SEARCH_PLACES_SEARCHDISABLED)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_disabled"));
+ return;
+ }
+ else if (status & STATUS_SEARCH_PLACES_ESTATEEMPTY)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_disabled"));
+ return;
+ }
+ }
+
+ bool found_one = false;
+ S32 num_new_rows = msg->getNumberOfBlocks("QueryReplies");
+ if (num_new_rows == 0 && self->mResultsReceived == 0)
+ {
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("places_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ }
+
+ self->mResultsReceived += num_new_rows;
+ num_new_rows = self->showNextButton(num_new_rows);
+
+ for (S32 i = 0; i < num_new_rows; i++)
+ {
+ msg->getUUID( "QueryReplies", "ParcelID", parcel_id, i);
+ msg->getString( "QueryReplies", "Name", name, i);
+ msg->getBOOL( "QueryReplies", "ForSale", for_sale,i);
+ msg->getBOOL( "QueryReplies", "Auction", auction, i);
+ msg->getF32( "QueryReplies", "Dwell", dwell, i);
+ if (parcel_id.isNull())
+ {
+ LL_DEBUGS("Search") << "Null result returned for QueryID: " << query_id << LL_ENDL;
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("places_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ }
+ else
+ {
+ LL_DEBUGS("Search") << "Got: " << name << " ParcelID: " << parcel_id << LL_ENDL;
+ search_results->setEnabled(TRUE);
+ found_one = true;
+
+ LLSD content;
+ LLSD element;
+
+ element["id"] = parcel_id;
+
+ if (auction)
+ {
+ element["columns"][0]["column"] = "icon";
+ element["columns"][0]["type"] = "icon";
+ element["columns"][0]["value"] = "Icon_Auction";
+ }
+ else if (for_sale)
+ {
+ element["columns"][0]["column"] = "icon";
+ element["columns"][0]["type"] = "icon";
+ element["columns"][0]["value"] = "Icon_For_Sale";
+ }
+ else
+ {
+ element["columns"][0]["column"] = "icon";
+ element["columns"][0]["type"] = "icon";
+ element["columns"][0]["value"] = "Icon_Place";
+ }
+
+ element["columns"][1]["column"] = "place_name";
+ element["columns"][1]["value"] = name;
+
+ content["name"] = name;
+
+ std::string buffer = llformat("%.0f", (F64)dwell);
+ element["columns"][2]["column"] = "dwell";
+ element["columns"][2]["value"] = buffer;
+
+ search_results->addElement(element, ADD_BOTTOM);
+ self->mResultsContent[parcel_id.asString()] = content;
+ }
+ }
+ if (found_one)
+ {
+ search_results->selectFirstItem();
+ search_results->setFocus(TRUE);
+ self->onSelectItem();
+ }
+}
+
+////////////////////////////////////////
+// Land Search Panel //
+////////////////////////////////////////
+
+static LLPanelInjector<FSPanelSearchLand> t_panel_fs_search_land("panel_ls_land");
+
+FSPanelSearchLand::FSPanelSearchLand() : FSSearchPanelBase()
+, mQueryID(nullptr)
+, mStartSearch(0)
+, mResultsReceived(0)
+, mResultsContent()
+{
+ mCommitCallbackRegistrar.add("CommitSearch", boost::bind(&FSPanelSearchLand::find, this));
+}
+
+FSPanelSearchLand::~FSPanelSearchLand()
+{
+}
+
+BOOL FSPanelSearchLand::postBuild()
+{
+ mSearchResults = getChild<LLScrollListCtrl>("search_results_land");
+ mPriceEditor = findChild<LLLineEditor>("price_edit");
+ mAreaEditor = findChild<LLLineEditor>("area_edit");
+ if (mSearchResults)
+ {
+ mSearchResults->setCommitCallback(boost::bind(&FSPanelSearchLand::onSelectItem, this));
+ mSearchResults->setEnabled(FALSE);
+ mSearchResults->setCommentText(LLTrans::getString("no_results"));
+ }
+ if (mPriceEditor)
+ {
+ mPriceEditor->setCommitOnFocusLost(false);
+ mPriceEditor->setCommitCallback(boost::bind(&FSPanelSearchLand::onBtnFind, this));
+ }
+ if (mAreaEditor)
+ {
+ mAreaEditor->setCommitOnFocusLost(false);
+ mAreaEditor->setCommitCallback(boost::bind(&FSPanelSearchLand::find, this));
+ }
+ childSetAction("land_find", boost::bind(&FSPanelSearchLand::onBtnFind, this));
+ childSetAction("land_next", boost::bind(&FSPanelSearchLand::onBtnNext, this));
+ childSetAction("land_back", boost::bind(&FSPanelSearchLand::onBtnBack, this));
+
+ getChildView("land_next")->setEnabled(FALSE);
+ getChildView("land_back")->setEnabled(FALSE);
+
+ return TRUE;
+}
+
+void FSPanelSearchLand::find()
+{
+ static LLUICachedControl<bool> inc_pg("ShowPGLand", 1);
+ static LLUICachedControl<bool> inc_mature("ShowMatureLand", 0);
+ static LLUICachedControl<bool> inc_adult("ShowAdultLand", 0);
+ static LLUICachedControl<bool> limit_price("FindLandPrice", 1);
+ static LLUICachedControl<bool> limit_area("FindLandArea", 1);
+ if (!(inc_pg || inc_mature || inc_adult))
+ {
+ LLNotificationsUtil::add("NoContentToSearch");
+ return;
+ }
+
+ U32 category = ST_ALL;
+ const std::string& selection = findChild<LLComboBox>("land_category")->getSelectedValue().asString();
+ if (!selection.empty())
+ {
+ if (selection == "Auction")
+ {
+ category = ST_AUCTION;
+ }
+ else if (selection == "Mainland")
+ {
+ category = ST_MAINLAND;
+ }
+ else if (selection == "Estate")
+ {
+ category = ST_ESTATE;
+ }
+ }
+
+ U32 scope = 0;
+ if (gAgent.wantsPGOnly())
+ {
+ scope |= DFQ_PG_SIMS_ONLY;
+ }
+ bool mature_enabled = gAgent.canAccessMature();
+ bool adult_enabled = gAgent.canAccessAdult();
+ if (inc_pg)
+ {
+ scope |= DFQ_INC_PG;
+ }
+ if (inc_mature && mature_enabled)
+ {
+ scope |= DFQ_INC_MATURE;
+ }
+ if (inc_adult && adult_enabled)
+ {
+ scope |= DFQ_INC_ADULT;
+ }
+ const std::string& sort = findChild<LLComboBox>("land_sort_combo")->getSelectedValue().asString();
+ if (!sort.empty())
+ {
+ if (sort == "Name")
+ {
+ scope |= DFQ_NAME_SORT;
+ }
+ else if (sort == "Price")
+ {
+ scope |= DFQ_PRICE_SORT;
+ }
+ else if (sort == "PPM")
+ {
+ scope |= DFQ_PER_METER_SORT;
+ }
+ else if (sort == "Area")
+ {
+ scope |= DFQ_AREA_SORT;
+ }
+ }
+ else
+ {
+ scope |= DFQ_PRICE_SORT;
+ }
+ if (childGetValue("ascending_check").asBoolean())
+ {
+ scope |= DFQ_SORT_ASC;
+ }
+ if (limit_price)
+ {
+ scope |= DFQ_LIMIT_BY_PRICE;
+ }
+ if (limit_area)
+ {
+ scope |= DFQ_LIMIT_BY_AREA;
+ }
+ S32 price = childGetValue("edit_price").asInteger();
+ S32 area = childGetValue("edit_area").asInteger();
+
+ mResultsReceived = 0;
+ if (mQueryID.notNull())
+ {
+ mQueryID.setNull();
+ }
+ mQueryID.generate();
+
+ if (mStartSearch < 0)
+ {
+ mStartSearch = 0;
+ }
+
+ gMessageSystem->newMessage("DirLandQuery");
+ gMessageSystem->nextBlock("AgentData");
+ gMessageSystem->addUUID("AgentID", gAgentID);
+ gMessageSystem->addUUID("SessionID", gAgentSessionID);
+ gMessageSystem->nextBlock("QueryData");
+ gMessageSystem->addUUID("QueryID", getQueryID());
+ gMessageSystem->addU32("QueryFlags", scope);
+ gMessageSystem->addU32("SearchType", category);
+ gMessageSystem->addS32("Price", price);
+ gMessageSystem->addS32("Area", area);
+ gMessageSystem->addS32("QueryStart", mStartSearch);
+ gAgent.sendReliableMessage();
+ LL_DEBUGS("Search") << "Firing off places search request: " << getQueryID() << category << LL_ENDL;
+
+ mSearchResults->deleteAllItems();
+ mSearchResults->setCommentText(LLTrans::getString("searching"));
+ mNumResultsReturned = 0;
+}
+
+void FSPanelSearchLand::onBtnFind()
+{
+ std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
+ auto elapsed = now - lastRequestTime;
+ U64 elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
+ if(elapsedMS < REQUEST_MIN_ELAPSED_TIME) return;
+ lastRequestTime = now;
+
+ resetSearch();
+
+ find();
+}
+
+void FSPanelSearchLand::onBtnNext()
+{
+ mStartSearch += RESULT_PAGE_SIZE;
+ getChildView("land_back")->setEnabled(TRUE);
+
+ find();
+}
+
+void FSPanelSearchLand::onBtnBack()
+{
+ mStartSearch -= RESULT_PAGE_SIZE;
+ getChildView("land_back")->setEnabled(mStartSearch > 0);
+
+ find();
+}
+
+void FSPanelSearchLand::resetSearch()
+{
+ mStartSearch = 0;
+ getChildView("land_back")->setEnabled(FALSE);
+ getChildView("land_next")->setEnabled(FALSE);
+}
+
+S32 FSPanelSearchLand::showNextButton(S32 rows)
+{
+ bool show_next_button = (mResultsReceived > RESULT_PAGE_SIZE);
+ getChildView("land_next")->setEnabled(show_next_button);
+ if (show_next_button)
+ {
+ rows -= (mResultsReceived - RESULT_PAGE_SIZE);
+ }
+ return rows;
+}
+
+void FSPanelSearchLand::onSelectItem()
+{
+ if (!mSearchResults)
+ {
+ return;
+ }
+ FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search");
+ if (search_instance)
+ {
+ search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_PLACE);
+ }
+}
+
+// static
+void FSPanelSearchLand::processSearchReply(LLMessageSystem* msg, void**)
+{
+ LLUUID agent_id;
+ LLUUID query_id;
+ LLUUID parcel_id;
+ std::string name;
+ std::string land_sku;
+ std::string land_type;
+ BOOL auction;
+ BOOL for_sale;
+ S32 price;
+ S32 area;
+
+ msg->getUUID("AgentData", "AgentID", agent_id);
+ msg->getUUID("QueryData", "QueryID", query_id);
+
+ // Not for us
+ if (agent_id != gAgentID)
+ {
+ return;
+ }
+ LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL;
+
+ FSPanelSearchLand* self = FSFloaterSearch::getSearchPanel<FSPanelSearchLand>("panel_ls_land");
+
+ // floater is closed or these are not results from our last request
+ if (!self || query_id != self->mQueryID)
+ {
+ return;
+ }
+
+ LLScrollListCtrl* search_results = self->getChild<LLScrollListCtrl>("search_results_land");
+ // clear "Searching" label on first results
+ if (self->mNumResultsReturned++ == 0)
+ {
+ search_results->deleteAllItems();
+ }
+
+ static LLUICachedControl<bool> use_price("FindLandPrice", 1);
+ static LLUICachedControl<bool> use_area("FindLandArea", 1);
+ S32 limit_price = self->childGetValue("edit_price").asInteger();
+ S32 limit_area = self->childGetValue("edit_area").asInteger();
+
+ bool found_one = false;
+ S32 num_new_rows = msg->getNumberOfBlocks("QueryReplies");
+ if (num_new_rows == 0 && self->mResultsReceived == 0)
+ {
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("events_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ }
+ self->mResultsReceived += num_new_rows;
+
+ S32 not_auction = 0;
+ for (S32 i = 0; i < num_new_rows; i++)
+ {
+ msg->getUUID( "QueryReplies", "ParcelID", parcel_id, i);
+ msg->getString( "QueryReplies", "Name", name, i);
+ msg->getBOOL( "QueryReplies", "Auction", auction, i);
+ msg->getBOOL( "QueryReplies", "ForSale", for_sale, i);
+ msg->getS32( "QueryReplies", "SalePrice", price, i);
+ msg->getS32( "QueryReplies", "ActualArea", area, i);
+ if (parcel_id.isNull())
+ {
+ LL_DEBUGS("Search") << "Null result returned for QueryID: " << query_id << LL_ENDL;
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("no_results"));
+ }
+ else
+ {
+ LL_DEBUGS("Search") << "Got: " << name << " ClassifiedID: " << parcel_id << LL_ENDL;
+ search_results->setEnabled(TRUE);
+ found_one = true;
+ if (msg->getSizeFast(_PREHASH_QueryReplies, i, _PREHASH_ProductSKU) > 0)
+ {
+ msg->getStringFast( _PREHASH_QueryReplies, _PREHASH_ProductSKU, land_sku, i);
+ land_type = LLProductInfoRequestManager::instance().getDescriptionForSku(land_sku);
+ }
+ else
+ {
+ land_sku.clear();
+ land_type = LLTrans::getString("land_type_unknown");
+ }
+ if (parcel_id.isNull())
+ {
+ continue;
+ }
+ if (use_price && (price > limit_price))
+ {
+ continue;
+ }
+ if (use_area && (area < limit_area))
+ {
+ continue;
+ }
+
+ LLSD content;
+ LLSD element;
+
+ element["id"] = parcel_id;
+ if (auction)
+ {
+ element["columns"][0]["column"] = "icon";
+ element["columns"][0]["type"] = "icon";
+ element["columns"][0]["value"] = "Icon_Auction";
+ }
+ else if (for_sale)
+ {
+ element["columns"][0]["column"] = "icon";
+ element["columns"][0]["type"] = "icon";
+ element["columns"][0]["value"] = "Icon_For_Sale";
+ }
+ else
+ {
+ element["columns"][0]["column"] = "icon";
+ element["columns"][0]["type"] = "icon";
+ element["columns"][0]["value"] = "Icon_Place";
+ }
+
+ element["columns"][1]["column"] = "land_name";
+ element["columns"][1]["value"] = name;
+
+ content["place_name"] = name;
+
+ std::string buffer = "Auction";
+ if (!auction)
+ {
+ buffer = llformat("%d", price);
+ not_auction++;
+ }
+ element["columns"][2]["column"] = "price";
+ element["columns"][2]["value"] = price;
+
+ element["columns"][3]["column"] = "area";
+ element["columns"][3]["value"] = area;
+ if (!auction)
+ {
+ F32 ppm;
+ if (area > 0)
+ {
+ ppm = (F32)price / (F32)area;
+ }
+ else
+ {
+ ppm = 0.f;
+ }
+ std::string ppm_buffer = llformat("%.1f", ppm);
+ element["columns"][4]["column"] = "ppm";
+ element["columns"][4]["value"] = ppm_buffer;
+ }
+ else
+ {
+ element["columns"][4]["column"] = "ppm";
+ element["columns"][4]["value"] = "1.0";
+ }
+
+ element["columns"][5]["column"] = "land_type";
+ element["columns"][5]["value"] = land_type;
+
+ search_results->addElement(element, ADD_BOTTOM);
+ self->mResultsContent[parcel_id.asString()] = content;
+ }
+ // We test against non-auction properties because they don't count towards the page limit.
+ self->showNextButton(not_auction);
+ }
+ if (found_one)
+ {
+ search_results->selectFirstItem();
+ search_results->setFocus(TRUE);
+ self->onSelectItem();
+ }
+}
+
+////////////////////////////////////////
+// Classifieds Search Panel //
+////////////////////////////////////////
+
+static LLPanelInjector<FSPanelSearchClassifieds> t_panel_fs_search_classifieds("panel_ls_classifieds");
+
+FSPanelSearchClassifieds::FSPanelSearchClassifieds() : FSSearchPanelBase()
+, mQueryID(nullptr)
+, mStartSearch(0)
+, mResultsReceived(0)
+, mResultsContent()
+{
+ mCommitCallbackRegistrar.add("CommitSearch", boost::bind(&FSPanelSearchClassifieds::find, this));
+}
+
+FSPanelSearchClassifieds::~FSPanelSearchClassifieds()
+{
+}
+
+BOOL FSPanelSearchClassifieds::postBuild()
+{
+ mSearchComboBox = findChild<LLSearchComboBox>("classifieds_edit");
+ mSearchResults = getChild<LLScrollListCtrl>("search_results_classifieds");
+ if (mSearchComboBox)
+ {
+ mSearchComboBox->setCommitCallback(boost::bind(&FSPanelSearchClassifieds::onBtnFind, this));
+ fillSearchComboBox(mSearchComboBox);
+ }
+ if (mSearchResults)
+ {
+ mSearchResults->setCommitCallback(boost::bind(&FSPanelSearchClassifieds::onSelectItem, this));
+ mSearchResults->setEnabled(FALSE);
+ mSearchResults->setCommentText(LLTrans::getString("no_results"));
+ }
+
+ mClassifiedsCategory = getChild<LLComboBox>("classifieds_category");
+ if (mClassifiedsCategory)
+ {
+ LLClassifiedInfo::cat_map::iterator iter;
+ mClassifiedsCategory->add(LLTrans::getString("all_categories"), LLSD(0));
+ mClassifiedsCategory->addSeparator();
+ for (iter = LLClassifiedInfo::sCategories.begin();
+ iter != LLClassifiedInfo::sCategories.end();
+ iter++)
+ {
+ mClassifiedsCategory->add(LLTrans::getString(iter->second), LLSD((S32)iter->first));
+ }
+ }
+ childSetAction("classifieds_next", boost::bind(&FSPanelSearchClassifieds::onBtnNext, this));
+ childSetAction("classifieds_back", boost::bind(&FSPanelSearchClassifieds::onBtnBack, this));
+
+ getChildView("classifieds_next")->setEnabled(FALSE);
+ getChildView("classifieds_back")->setEnabled(FALSE);
+
+ return TRUE;
+}
+
+void FSPanelSearchClassifieds::focusDefaultElement()
+{
+ mSearchComboBox->focusTextEntry();
+}
+
+void FSPanelSearchClassifieds::find()
+{
+ std::string text = filterShortWords(mSearchComboBox->getSimple());
+ if (text.size() == 0)
+ {
+ mSearchResults->setCommentText(LLTrans::getString("search_short"));
+ return;
+ }
+
+ static LLUICachedControl<bool> inc_pg("ShowPGClassifieds", 1);
+ static LLUICachedControl<bool> inc_mature("ShowMatureClassifieds", 0);
+ static LLUICachedControl<bool> inc_adult("ShowAdultClassifieds", 0);
+ if (!(inc_pg || inc_mature || inc_adult))
+ {
+ LLNotificationsUtil::add("NoContentToSearch");
+ return;
+ }
+ U32 category = mClassifiedsCategory->getValue().asInteger();
+ BOOL auto_renew = FALSE;
+ U32 flags = pack_classified_flags_request(auto_renew, inc_pg, inc_mature, inc_adult);
+
+ mResultsReceived = 0;
+ if (mQueryID.notNull())
+ {
+ mQueryID.setNull();
+ }
+ mQueryID.generate();
+
+ if (mStartSearch < 0)
+ {
+ mStartSearch = 0;
+ }
+
+ gMessageSystem->newMessageFast(_PREHASH_DirClassifiedQuery);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
+ gMessageSystem->nextBlockFast(_PREHASH_QueryData);
+ gMessageSystem->addUUIDFast(_PREHASH_QueryID, getQueryID());
+ gMessageSystem->addStringFast(_PREHASH_QueryText, text);
+ gMessageSystem->addU32Fast(_PREHASH_QueryFlags, flags);
+ gMessageSystem->addU32Fast(_PREHASH_Category, category);
+ gMessageSystem->addS32Fast(_PREHASH_QueryStart, mStartSearch);
+ gAgent.sendReliableMessage();
+ LL_DEBUGS("Search") << "Firing off classified ad search request: " << getQueryID() << LL_ENDL;
+
+ mSearchResults->deleteAllItems();
+ mSearchResults->setCommentText(LLTrans::getString("searching"));
+ mNumResultsReturned = 0;
+}
+
+void FSPanelSearchClassifieds::onBtnFind()
+{
+ std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
+ auto elapsed = now - lastRequestTime;
+ U64 elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
+ if(elapsedMS < REQUEST_MIN_ELAPSED_TIME) return;
+ lastRequestTime = now;
+
+ std::string text = mSearchComboBox->getSimple();
+ if (!text.empty())
+ {
+ LLSearchHistory::getInstance()->addEntry(text);
+ }
+
+ resetSearch();
+
+ find();
+}
+
+void FSPanelSearchClassifieds::onBtnNext()
+{
+ mStartSearch += RESULT_PAGE_SIZE;
+ getChildView("classifieds_back")->setEnabled(TRUE);
+
+ find();
+}
+
+void FSPanelSearchClassifieds::onBtnBack()
+{
+ mStartSearch -= RESULT_PAGE_SIZE;
+ getChildView("classifieds_back")->setEnabled(mStartSearch > 0);
+
+ find();
+}
+
+void FSPanelSearchClassifieds::resetSearch()
+{
+ mStartSearch = 0;
+ getChildView("classifieds_back")->setEnabled(FALSE);
+ getChildView("classifieds_next")->setEnabled(FALSE);
+}
+
+S32 FSPanelSearchClassifieds::showNextButton(S32 rows)
+{
+ bool show_next_button = (mResultsReceived > RESULT_PAGE_SIZE);
+ getChildView("classifieds_next")->setEnabled(show_next_button);
+ if (show_next_button)
+ {
+ rows -= (mResultsReceived - RESULT_PAGE_SIZE);
+ }
+ return rows;
+}
+
+void FSPanelSearchClassifieds::onSelectItem()
+{
+ if (!mSearchResults)
+ {
+ return;
+ }
+ FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search");
+ if (search_instance)
+ {
+ search_instance->FSFloaterSearch::onSelectedItem(mSearchResults->getSelectedValue(), FSFloaterSearch::SC_CLASSIFIED);
+ }
+}
+
+// static
+void FSPanelSearchClassifieds::processSearchReply(LLMessageSystem* msg, void**)
+{
+ LLUUID agent_id;
+ LLUUID query_id;
+ LLUUID classified_id;
+ std::string name;
+ U32 creation_date;
+ U32 expiration_date;
+ S32 price_for_listing;
+
+ msg->getUUID("AgentData", "AgentID", agent_id);
+ msg->getUUID("QueryData", "QueryID", query_id);
+
+ // Not for us
+ if (agent_id != gAgentID)
+ {
+ return;
+ }
+ LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL;
+
+ FSPanelSearchClassifieds* self = FSFloaterSearch::getSearchPanel<FSPanelSearchClassifieds>("panel_ls_classifieds");
+
+ if (msg->getNumberOfBlocks("StatusData"))
+ {
+ U32 status;
+ msg->getU32("StatusData", "Status", status);
+ if (status & STATUS_SEARCH_CLASSIFIEDS_BANNEDWORD)
+ {
+ LLNotificationsUtil::add("SearchWordBanned");
+ }
+ }
+
+ // floater is closed or these are not results from our last request
+ if (!self || query_id != self->mQueryID)
+ {
+ return;
+ }
+
+ LLScrollListCtrl* search_results = self->getChild<LLScrollListCtrl>("search_results_classifieds");
+
+ // Clear "Searching" label on first results
+ if (self->mNumResultsReturned++ == 0)
+ {
+ search_results->deleteAllItems();
+ }
+
+ // Check for status messages
+ if (msg->getNumberOfBlocks("StatusData"))
+ {
+ U32 status;
+ msg->getU32("StatusData", "Status", status);
+ if (status & STATUS_SEARCH_PLACES_FOUNDNONE)
+ {
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("classifieds_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ return;
+ }
+ else if(status & STATUS_SEARCH_PLACES_SHORTSTRING)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_short"));
+ return;
+ }
+ else if (status & STATUS_SEARCH_CLASSIFIEDS_BANNEDWORD)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_banned"));
+ return;
+ }
+ else if (status & STATUS_SEARCH_PLACES_SEARCHDISABLED)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_disabled"));
+ return;
+ }
+ }
+
+ bool found_one = false;
+ S32 num_new_rows = msg->getNumberOfBlocks("QueryReplies");
+ if (num_new_rows == 0 && self->mResultsReceived == 0)
+ {
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("classifieds_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ }
+ self->mResultsReceived += num_new_rows;
+ num_new_rows = self->showNextButton(num_new_rows);
+
+ for (S32 i = 0; i < num_new_rows; i++)
+ {
+ msg->getUUID( "QueryReplies", "ClassifiedID", classified_id, i);
+ msg->getString( "QueryReplies", "Name", name, i);
+ msg->getU32( "QueryReplies", "CreationDate", creation_date, i);
+ msg->getU32( "QueryReplies", "ExpirationDate", expiration_date,i);
+ msg->getS32( "QueryReplies", "PriceForListing", price_for_listing,i);
+ if (classified_id.isNull())
+ {
+ LL_DEBUGS("Search") << "Null result returned for QueryID: " << query_id << LL_ENDL;
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("classifieds_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ }
+ else
+ {
+ LL_DEBUGS("Search") << "Got: " << name << " ClassifiedID: " << classified_id << LL_ENDL;
+ search_results->setEnabled(TRUE);
+ found_one = true;
+
+ LLSD content;
+ LLSD element;
+
+ element["id"] = classified_id;
+
+ element["columns"][0]["column"] = "icon";
+ element["columns"][0]["type"] = "icon";
+ element["columns"][0]["value"] = "icon_top_pick.tga";
+
+ element["columns"][1]["column"] = "classified_name";
+ element["columns"][1]["value"] = name;
+
+ element["columns"][2]["column"] = "price";
+ element["columns"][2]["value"] = price_for_listing;
+
+ content["name"] = name;
+
+ search_results->addElement(element, ADD_BOTTOM);
+ self->mResultsContent[classified_id.asString()] = content;
+ }
+ }
+ if (found_one)
+ {
+ search_results->selectFirstItem();
+ search_results->setFocus(TRUE);
+ self->onSelectItem();
+ }
+}
+
+////////////////////////////////////////
+// Events Search Panel //
+////////////////////////////////////////
+
+static LLPanelInjector<FSPanelSearchEvents> t_panel_fs_search_events("panel_ls_events");
+
+FSPanelSearchEvents::FSPanelSearchEvents() : FSSearchPanelBase()
+, mQueryID(nullptr)
+, mResultsReceived(0)
+, mStartSearch(0)
+, mDay(0)
+, mResultsContent()
+{
+ mCommitCallbackRegistrar.add("CommitSearch", boost::bind(&FSPanelSearchEvents::find, this));
+}
+
+FSPanelSearchEvents::~FSPanelSearchEvents()
+{
+}
+
+BOOL FSPanelSearchEvents::postBuild()
+{
+ mSearchComboBox = findChild<LLSearchComboBox>("events_edit");
+ mSearchResults = getChild<LLScrollListCtrl>("search_results_events");
+ mEventsMode = findChild<LLRadioGroup>("events_search_mode");
+ if (mSearchComboBox)
+ {
+ mSearchComboBox->setCommitCallback(boost::bind(&FSPanelSearchEvents::onBtnFind, this));
+ fillSearchComboBox(mSearchComboBox);
+ }
+ if (mSearchResults)
+ {
+ mSearchResults->setCommitCallback(boost::bind(&FSPanelSearchEvents::onSelectItem, this));
+ mSearchResults->setEnabled(FALSE);
+ mSearchResults->setCommentText(LLTrans::getString("no_results"));
+ }
+ if (mEventsMode)
+ {
+ mEventsMode->setCommitCallback(boost::bind(&FSPanelSearchEvents::onSearchModeChanged, this));
+ mEventsMode->selectFirstItem();
+ }
+
+ childSetAction("events_next", boost::bind(&FSPanelSearchEvents::onBtnNext, this));
+ childSetAction("events_back", boost::bind(&FSPanelSearchEvents::onBtnBack, this));
+ childSetAction("events_tomorrow", boost::bind(&FSPanelSearchEvents::onBtnTomorrow, this));
+ childSetAction("events_yesterday", boost::bind(&FSPanelSearchEvents::onBtnYesterday, this));
+ childSetAction("events_today", boost::bind(&FSPanelSearchEvents::onBtnToday, this));
+
+ getChildView("events_next")->setEnabled(FALSE);
+ getChildView("events_back")->setEnabled(FALSE);
+ getChildView("events_tomorrow")->setEnabled(FALSE);
+ getChildView("events_yesterday")->setEnabled(FALSE);
+ getChildView("events_today")->setEnabled(FALSE);
+ setDay(0);
+
+ return TRUE;
+}
+
+void FSPanelSearchEvents::focusDefaultElement()
+{
+ mSearchComboBox->focusTextEntry();
+}
+
+void FSPanelSearchEvents::find()
+{
+ std::string text = filterShortWords(mSearchComboBox->getSimple());
+
+ static LLUICachedControl<bool> inc_pg("ShowPGEvents", 1);
+ static LLUICachedControl<bool> inc_mature("ShowMatureEvents", 0);
+ static LLUICachedControl<bool> inc_adult("ShowAdultEvents", 0);
+ if (!(inc_pg || inc_mature || inc_adult))
+ {
+ LLNotificationsUtil::add("NoContentToSearch");
+ return;
+ }
+
+ U32 category = findChild<LLComboBox>("events_category")->getSelectedValue().asInteger();
+ U32 scope = DFQ_DATE_EVENTS;
+ if (gAgent.wantsPGOnly())
+ {
+ scope |= DFQ_PG_SIMS_ONLY;
+ }
+ bool mature_enabled = gAgent.canAccessMature();
+ bool adult_enabled = gAgent.canAccessAdult();
+ if (inc_pg)
+ {
+ scope |= DFQ_INC_PG;
+ }
+ if (inc_mature && mature_enabled)
+ {
+ scope |= DFQ_INC_MATURE;
+ }
+ if (inc_adult && adult_enabled)
+ {
+ scope |= DFQ_INC_ADULT;
+ }
+
+ std::ostringstream string;
+
+ if ("current" == childGetValue("events_search_mode").asString())
+ {
+ string << "u|";
+ }
+ else
+ {
+ string << mDay << "|";
+ }
+ string << category << "|";
+ string << text;
+
+ mResultsReceived = 0;
+ if (mQueryID.notNull())
+ {
+ mQueryID.setNull();
+ }
+ mQueryID.generate();
+
+ if (mStartSearch < 0)
+ {
+ mStartSearch = 0;
+ }
+
+ gMessageSystem->newMessage("DirFindQuery");
+ gMessageSystem->nextBlock("AgentData");
+ gMessageSystem->addUUID("AgentID", gAgentID);
+ gMessageSystem->addUUID("SessionID", gAgentSessionID);
+ gMessageSystem->nextBlock("QueryData");
+ gMessageSystem->addUUID("QueryID", getQueryID());
+ gMessageSystem->addString("QueryText", string.str());
+ gMessageSystem->addU32("QueryFlags", scope);
+ gMessageSystem->addS32("QueryStart", mStartSearch);
+ gAgent.sendReliableMessage();
+ LL_INFOS("Search") << "Firing off search request: " << getQueryID() << " Search Text: " << string.str() << LL_ENDL;
+
+ mSearchResults->deleteAllItems();
+ mSearchResults->setCommentText(LLTrans::getString("searching"));
+ mNumResultsReturned = 0;
+}
+
+void FSPanelSearchEvents::onBtnFind()
+{
+ std::chrono::time_point<std::chrono::system_clock> now = std::chrono::system_clock::now();
+ auto elapsed = now - lastRequestTime;
+ U64 elapsedMS = std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
+ if(elapsedMS < REQUEST_MIN_ELAPSED_TIME) return;
+ lastRequestTime = now;
+
+ std::string text = mSearchComboBox->getSimple();
+ if (!text.empty())
+ {
+ LLSearchHistory::getInstance()->addEntry(text);
+ }
+
+ resetSearch();
+
+ find();
+}
+
+void FSPanelSearchEvents::onBtnNext()
+{
+ mStartSearch += RESULT_PAGE_SIZE;
+ getChildView("events_back")->setEnabled(TRUE);
+
+ find();
+}
+
+void FSPanelSearchEvents::onBtnBack()
+{
+ mStartSearch -= RESULT_PAGE_SIZE;
+ getChildView("events_back")->setEnabled(mStartSearch > 0);
+
+ find();
+}
+
+void FSPanelSearchEvents::onBtnTomorrow()
+{
+ resetSearch();
+ setDay(mDay + 1);
+
+ find();
+}
+
+void FSPanelSearchEvents::onBtnYesterday()
+{
+ resetSearch();
+ setDay(mDay - 1);
+
+ find();
+}
+
+void FSPanelSearchEvents::onBtnToday()
+{
+ resetSearch();
+ setDay(0);
+
+ find();
+}
+
+void FSPanelSearchEvents::resetSearch()
+{
+ mStartSearch = 0;
+ getChildView("events_back")->setEnabled(FALSE);
+ getChildView("events_next")->setEnabled(FALSE);
+}
+
+void FSPanelSearchEvents::onSearchModeChanged()
+{
+ if (mEventsMode->getValue().asString() == "current")
+ {
+ getChildView("events_yesterday")->setEnabled(FALSE);
+ getChildView("events_tomorrow")->setEnabled(FALSE);
+ getChildView("events_today")->setEnabled(FALSE);
+ }
+ else
+ {
+ getChildView("events_yesterday")->setEnabled(TRUE);
+ getChildView("events_tomorrow")->setEnabled(TRUE);
+ getChildView("events_today")->setEnabled(TRUE);
+ }
+}
+
+void FSPanelSearchEvents::setDay(S32 day)
+{
+ mDay = day;
+ struct tm* internal_time;
+
+ time_t utc = time_corrected();
+ utc += day * 24 * 60 * 60;
+ internal_time = utc_to_pacific_time(utc, is_daylight_savings());
+ std::string buffer = llformat("%d/%d", 1 + internal_time->tm_mon, internal_time->tm_mday);
+ childSetValue("events_date", buffer);
+}
+
+S32 FSPanelSearchEvents::showNextButton(S32 rows)
+{
+ bool show_next_button = (mResultsReceived > RESULT_PAGE_SIZE);
+ getChildView("events_next")->setEnabled(show_next_button);
+ if (show_next_button)
+ {
+ rows -= (mResultsReceived - RESULT_PAGE_SIZE);
+ }
+ return rows;
+}
+
+void FSPanelSearchEvents::onSelectItem()
+{
+ if (!mSearchResults)
+ {
+ return;
+ }
+ S32 event_id = mSearchResults->getSelectedValue();
+ FSFloaterSearch* search_instance = LLFloaterReg::findTypedInstance<FSFloaterSearch>("search");
+ if (search_instance)
+ {
+ search_instance->FSFloaterSearch::onSelectedEvent(event_id);
+ }
+}
+
+// static
+void FSPanelSearchEvents::processSearchReply(LLMessageSystem* msg, void**)
+{
+ LLUUID agent_id;
+ LLUUID query_id;
+ LLUUID owner_id;
+ std::string name;
+ std::string date;
+
+ msg->getUUID("AgentData", "AgentID", agent_id);
+ msg->getUUID("QueryData", "QueryID", query_id);
+
+ // Not for us
+ if (agent_id != gAgentID)
+ {
+ return;
+ }
+ LL_DEBUGS("Search") << "received directory request - QueryID: " << query_id << " AgentID: " << agent_id << LL_ENDL;
+
+ FSPanelSearchEvents* self = FSFloaterSearch::getSearchPanel<FSPanelSearchEvents>("panel_ls_events");
+
+ // floater is closed or these are not results from our last request
+ if (!self || query_id != self->mQueryID)
+ {
+ return;
+ }
+
+ LLScrollListCtrl* search_results = self->getChild<LLScrollListCtrl>("search_results_events");
+
+ // Clear "Searching" label on first results
+ if (self->mNumResultsReturned++ == 0)
+ {
+ search_results->deleteAllItems();
+ }
+ // Check for status messages
+ if (msg->getNumberOfBlocks("StatusData"))
+ {
+ U32 status;
+ msg->getU32("StatusData", "Status", status);
+ if (status & STATUS_SEARCH_EVENTS_FOUNDNONE)
+ {
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("events_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ return;
+ }
+ else if(status & STATUS_SEARCH_EVENTS_SHORTSTRING)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_short"));
+ return;
+ }
+ else if (status & STATUS_SEARCH_EVENTS_BANNEDWORD)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_banned"));
+ return;
+ }
+ else if (status & STATUS_SEARCH_EVENTS_SEARCHDISABLED)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_disabled"));
+ return;
+ }
+ else if (status & STATUS_SEARCH_EVENTS_NODATEOFFSET)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_no_date_offset"));
+ return;
+ }
+ else if (status & STATUS_SEARCH_EVENTS_NOCATEGORY)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_no_events_category"));
+ return;
+ }
+ else if (status & STATUS_SEARCH_EVENTS_NOQUERY)
+ {
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("search_no_query"));
+ return;
+ }
+ }
+
+ S32 num_new_rows = msg->getNumberOfBlocks("QueryReplies");
+ if (num_new_rows == 0 && self->mResultsReceived == 0)
+ {
+ LLStringUtil::format_map_t map;
+ map["[TEXT]"] = self->getChild<LLUICtrl>("events_edit")->getValue().asString();
+ search_results->setEnabled(FALSE);
+ search_results->setCommentText(LLTrans::getString("not_found", map));
+ }
+
+ self->mResultsReceived += num_new_rows;
+ num_new_rows = self->showNextButton(num_new_rows);
+ static LLUICachedControl<bool> inc_pg("ShowPGEvents", 1);
+ static LLUICachedControl<bool> inc_mature("ShowMatureEvents", 0);
+ static LLUICachedControl<bool> inc_adult("ShowAdultEvents", 0);
+ bool found_one = false;
+
+ for (S32 i = 0; i < num_new_rows; i++)
+ {
+ U32 event_id;
+ U32 unix_time;
+ U32 event_flags;
+
+ msg->getUUID( "QueryReplies", "OwnerID", owner_id, i);
+ msg->getString( "QueryReplies", "Name", name, i);
+ msg->getU32( "QueryReplies", "EventID", event_id, i);
+ msg->getString( "QueryReplies", "Date", date, i);
+ msg->getU32( "QueryReplies", "UnixTime", unix_time, i);
+ msg->getU32( "QueryReplies", "EventFlags", event_flags,i);
+
+ // Skip empty events...
+ if (owner_id.isNull())
+ {
+ LL_INFOS("Search") << "Skipped " << event_id << " because of a nullptr owner result" << LL_ENDL;
+ continue;
+ }
+ // Skips events that don't match our scope...
+ if (((event_flags & (EVENT_FLAG_ADULT | EVENT_FLAG_MATURE)) == EVENT_FLAG_NONE) && !inc_pg)
+ {
+ LL_INFOS("Search") << "Skipped " << event_id << " because it was out of scope" << LL_ENDL;
+ continue;
+ }
+ if ((event_flags & EVENT_FLAG_MATURE) && !inc_mature)
+ {
+ LL_INFOS("Search") << "Skipped " << event_id << " because it was out of scope" << LL_ENDL;
+ continue;
+ }
+ if ((event_flags & EVENT_FLAG_ADULT) && !inc_adult)
+ {
+ LL_INFOS("Search") << "Skipped " << event_id << " because it was out of scope" << LL_ENDL;
+ continue;
+ }
+ search_results->setEnabled(TRUE);
+ found_one = true;
+
+ LLSD content;
+ LLSD element;
+
+ element["id"] = llformat("%u", event_id);
+
+ if (event_flags == EVENT_FLAG_ADULT)
+ {
+ element["columns"][0]["column"] = "icon";
+ element["columns"][0]["type"] = "icon";
+ element["columns"][0]["value"] = "Icon_Legacy_Event_Adult";
+ }
+ else if (event_flags == EVENT_FLAG_MATURE)
+ {
+ element["columns"][0]["column"] = "icon";
+ element["columns"][0]["type"] = "icon";
+ element["columns"][0]["value"] = "Icon_Legacy_Event_Mature";
+ }
+ else
+ {
+ element["columns"][0]["column"] = "icon";
+ element["columns"][0]["type"] = "icon";
+ element["columns"][0]["value"] = "Icon_Legacy_Event_PG";
+ }
+ element["columns"][1]["column"] = "name";
+ element["columns"][1]["value"] = name;
+
+ element["columns"][2]["column"] = "date";
+ element["columns"][2]["value"] = date;
+
+ element["columns"][3]["column"] = "time";
+ element["columns"][3]["value"] = llformat("%u", unix_time);
+
+ content["name"] = name;
+ content["event_id"] = (S32)event_id;
+
+ search_results->addElement(element, ADD_BOTTOM);
+ std::string event = llformat("%u", event_id);
+ self->mResultsContent[event] = content;
+ }
+ if (found_one)
+ {
+ search_results->selectFirstItem();
+ search_results->setFocus(TRUE);
+ self->onSelectItem();
+ }
+}
+
+////////////////////////////////////////
+// WebSearch Panel //
+////////////////////////////////////////
+
+static LLPanelInjector<FSPanelSearchWeb> t_panel_fs_search_web("panel_ls_web");
+
+FSPanelSearchWeb::FSPanelSearchWeb() : FSSearchPanelBase()
+, mWebBrowser(nullptr)
+, mResetFocusOnLoad(false)
+{
+ // Second Life grids use a different URL format now
+ mCategoryPaths = LLSD::emptyMap();
+ if (LLGridManager::getInstance()->isInSecondlife())
+ {
+ // declare a map that transforms a category name into
+ // the parameter list that is used to search that category
+ mCategoryPaths["people"] = "collection_chosen=people";
+ mCategoryPaths["places"] = "collection_chosen=places";
+ mCategoryPaths["events"] = "collection_chosen=events";
+ mCategoryPaths["groups"] = "collection_chosen=groups";
+ mCategoryPaths["destinations"] = "collection_chosen=destinations";
+
+ mCategoryPaths["classifieds"] = "search_type=classified";
+ mCategoryPaths["wiki"] = "search/wiki"; // not sure if this is still a thing in the new search
+
+ mCategoryPaths["all"] = mCategoryPaths["people"].asString() + "&" +
+ mCategoryPaths["places"].asString() + "&" +
+ mCategoryPaths["events"].asString() + "&" +
+ mCategoryPaths["groups"].asString() + "&" +
+ mCategoryPaths["destinations"].asString();
+ }
+ // OpenSim currently still uses the old URL format
+ else
+ {
+ // declare a map that transforms a category name into
+ // the URL suffix that is used to search that category
+ mCategoryPaths["all"] = "search";
+ mCategoryPaths["people"] = "search/people";
+ mCategoryPaths["places"] = "search/places";
+ mCategoryPaths["events"] = "search/events";
+ mCategoryPaths["groups"] = "search/groups";
+ mCategoryPaths["wiki"] = "search/wiki";
+ mCategoryPaths["destinations"] = "destinations";
+ mCategoryPaths["classifieds"] = "classifieds";
+ }
+}
+
+BOOL FSPanelSearchWeb::postBuild()
+{
+ mWebBrowser = getChild<LLMediaCtrl>("search_browser");
+ return TRUE;
+}
+
+void FSPanelSearchWeb::loadURL(const SearchQuery &p)
+{
+ if (!mWebBrowser || !p.validateBlock())
+ {
+ return;
+ }
+
+ // CATEGORY is no longer used as part of the path on Second Life grids
+ LLSD subs = LLSD().with("CATEGORY", "");
+
+ // on OpenSim grids it probably is currently still being used, so keep the old behavior
+ if (!LLGridManager::getInstance()->isInSecondlife())
+ {
+ // work out the subdir to use based on the requested category
+ LLSD subs = LLSD().with("CATEGORY", (mCategoryPaths.has(p.category.getValue()) ? mCategoryPaths[p.category.getValue()].asString() : mCategoryPaths["all"].asString()));
+ }
+
+ // add the search query string
+ subs["QUERY"] = LLURI::escape(p.query.getValue());
+
+ // add the permissions token that login.cgi gave us
+ // We use "search_token", and fallback to "auth_token" if not present.
+ LLSD search_token = LLLoginInstance::getInstance()->getResponse("search_token");
+ if (search_token.asString().empty())
+ {
+ search_token = LLLoginInstance::getInstance()->getResponse("auth_token");
+ }
+ subs["AUTH_TOKEN"] = search_token.asString();
+
+ // add the user's preferred maturity (can be changed via prefs)
+ std::string maturity;
+
+ // on Second Life grids, the maturity level is now a "&maturity" parameter that's not in the provided search URL
+ if (LLGridManager::getInstance()->isInSecondlife())
+ {
+ if (gAgent.prefersAdult())
+ {
+ maturity = "gma"; // PG,Mature,Adult
+ }
+ else if (gAgent.prefersMature())
+ {
+ maturity = "gm"; // PG,Mature
+ }
+ else
+ {
+ maturity = "g"; // PG
+ }
+
+ // not used on the SL search anymore, so clear out the respective parameter
+ subs["MATURITY"] = "";
+ }
+ // OpenSim probably still uses the old maturity variant, so keep the old behavior here
+ else
+ {
+ if (gAgent.prefersAdult())
+ {
+ maturity = "42"; // PG,Mature,Adult
+ }
+ else if (gAgent.prefersMature())
+ {
+ maturity = "21"; // PG,Mature
+ }
+ else
+ {
+ maturity = "13"; // PG
+ }
+ subs["MATURITY"] = maturity;
+ }
+
+ // add the user's god status
+ subs["GODLIKE"] = gAgent.isGodlike() ? "1" : "0";
+
+ // Get the search URL and expand all of the substitutions
+ // (also adds things like [LANGUAGE], [VERSION], [OS], etc.)
+
+ // add the maturity and category variables to the new Second Life search URL
+ //std::string url = gAgent.getRegion() != nullptr ? gAgent.getRegion()->getSearchServerURL() : gSavedSettings.getString(LLGridManager::getInstance()->isInOpenSim() ? "OpenSimSearchURL" : "SearchURL");
+
+ std::string url = gSavedSettings.getString("SearchURL");
+
+ if (LLGridManager::getInstance()->isInSecondlife())
+ {
+ url.append("&maturity=" + maturity + "&" + mCategoryPaths[p.category.getValue()].asString());
+ }
+
+ url = LLWeb::expandURLSubstitutions(url, subs);
+
+ // Finally, load the URL in the webpanel
+ mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
+}
+
+void FSPanelSearchWeb::focusDefaultElement()
+{
+ mWebBrowser->setFocus(TRUE);
+}
+
+void FSPanelSearchWeb::draw()
+{
+ if (mResetFocusOnLoad)
+ {
+ focusDefaultElement();
+ mResetFocusOnLoad = false;
+ }
+
+ FSSearchPanelBase::draw();
+}
+
+////////////////////////////////////////
+// Local functions //
+////////////////////////////////////////
+
+std::string filterShortWords(std::string query_string)
+{
+ if (query_string.length() < 1)
+ {
+ return "";
+ }
+
+ std::string final_query;
+ bool filtered = false;
+ boost::char_separator<char> sep(" ");
+ boost::tokenizer<boost::char_separator<char> > tokens(query_string, sep);
+ boost::tokenizer<boost::char_separator<char> >::iterator iter = tokens.begin();
+ boost::tokenizer<boost::char_separator<char> >::iterator last = tokens.end();
+ boost::tokenizer<boost::char_separator<char> >::iterator temp;
+ for (; iter != last; ++iter)
+ {
+ if ((*iter).length() > MIN_SEARCH_STRING_SIZE)
+ {
+ final_query.append((*iter));
+ temp = iter; ++temp;
+ if (temp != last)
+ {
+ final_query.append(" ");
+ }
+ }
+ else
+ {
+ filtered = true;
+ }
+ }
+
+ if (filtered)
+ {
+ LLSD args = LLSD().with("FINALQUERY", final_query);
+ LLNotificationsUtil::add("SeachFilteredOnShortWords", args);
+ }
+
+ return final_query;
+}
+
+void fillSearchComboBox(LLSearchComboBox* search_combo)
+{
+ if (search_combo == nullptr)
+ {
+ return;
+ }
+
+ LLSearchHistory::getInstance()->load();
+
+ LLSearchHistory::search_history_list_t search_list =
+ LLSearchHistory::getInstance()->getSearchHistoryList();
+ LLSearchHistory::search_history_list_t::const_iterator it = search_list.begin();
+ for ( ; search_list.end() != it; ++it)
+ {
+ LLSearchHistory::LLSearchHistoryItem item = *it;
+ search_combo->add(item.search_query);
+ }
+}
diff --git a/indra/newview/fsfloatersearch.h b/indra/newview/fsfloatersearch.h
new file mode 100644
index 0000000000..61cef8bab9
--- /dev/null
+++ b/indra/newview/fsfloatersearch.h
@@ -0,0 +1,404 @@
+/**
+ * @file fsfloatersearch.h
+ * @brief Firestorm search definitions
+ *
+ * $LicenseInfo:firstyear=2012&license=fsviewerlgpl$
+ * Phoenix Firestorm Viewer Source Code
+ * Copyright (C) 2012, Cinder Roxley <cinder.roxley@phoenixviewer.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * The Phoenix Firestorm Project, Inc., 1831 Oakwood Drive, Fairmont, Minnesota 56031-3225 USA
+ * http://www.firestormviewer.org
+ * $/LicenseInfo$
+ */
+
+#ifndef FS_FLOATERSEARCH_H
+#define FS_FLOATERSEARCH_H
+
+#include "llfloater.h"
+#include "lliconctrl.h"
+#include "lltexteditor.h"
+#include "lltexturectrl.h"
+#include "llremoteparcelrequest.h"
+#include "llavatarpropertiesprocessor.h"
+#include "llgroupmgr.h"
+#include "llavatarnamecache.h"
+#include "llmediactrl.h"
+#include "llradiogroup.h"
+#include "llsearchcombobox.h"
+#include "llscrolllistctrl.h"
+#include "lltabcontainer.h"
+#include "lleventnotifier.h"
+
+class FSSearchRemoteParcelInfoObserver;
+class LLAvatarPropertiesObserver;
+class LLGroupMgrObserver;
+class LLSearchEditor;
+class LLSearchComboBox;
+class FSFloaterSearch;
+class LLPanelProfile;
+class FSScrollListCtrl;
+
+struct SearchQuery : public LLInitParam::Block<SearchQuery>
+{
+ Optional<std::string> category;
+ Optional<std::string> query;
+
+ SearchQuery();
+};
+
+///////////////////////////////
+// Search Panels //
+///////////////////////////////
+
+class FSSearchPanelBase : public LLPanel
+{
+public:
+ FSSearchPanelBase() : LLPanel() { }
+ virtual ~FSSearchPanelBase() = default;
+ virtual void focusDefaultElement() { }
+};
+
+class FSPanelSearchPeople : public FSSearchPanelBase
+{
+ LOG_CLASS(FSFloaterSearch);
+public:
+ FSPanelSearchPeople();
+ static void processSearchReply(LLMessageSystem* msg, void**);
+
+ /*virtual*/ void focusDefaultElement();
+
+protected:
+ const S32& getNumResultsReturned() const { return mNumResultsReturned; };
+ const S32& getNumResultsReceived() const { return mResultsReceived; };
+
+private:
+ /*virtual*/ BOOL postBuild();
+ virtual ~FSPanelSearchPeople();
+
+ void onBtnFind();
+ void onSelectItem();
+ void onBtnNext();
+ void onBtnBack();
+
+ void find();
+ void resetSearch();
+ S32 showNextButton(S32);
+
+ const LLUUID& getQueryID() const { return mQueryID; }
+
+ void onAvatarNameCallback(const LLUUID& id, const LLAvatarName& av_name);
+
+ typedef boost::signals2::connection avatar_name_callback_connection_t;
+ avatar_name_callback_connection_t mAvatarNameCallbackConnection;
+
+ S32 mNumResultsReturned;
+ S32 mStartSearch;
+ S32 mResultsReceived;
+ LLSD mResultsContent;
+ LLUUID mQueryID;
+
+ LLSearchComboBox* mSearchComboBox;
+ LLScrollListCtrl* mSearchResults;
+};
+
+class FSPanelSearchGroups : public FSSearchPanelBase
+{
+ LOG_CLASS(FSFloaterSearch);
+public:
+ FSPanelSearchGroups();
+ static void processSearchReply(LLMessageSystem* msg, void**);
+
+ /*virtual*/ void focusDefaultElement();
+
+private:
+ /*virtual*/ BOOL postBuild();
+ virtual ~FSPanelSearchGroups();
+
+ void onBtnFind();
+ void onSelectItem();
+ void onBtnNext();
+ void onBtnBack();
+
+ void find();
+ void resetSearch();
+ S32 showNextButton(S32);
+
+ const LLUUID& getQueryID() const { return mQueryID; }
+
+ S32 mNumResultsReturned;
+ S32 mStartSearch;
+ S32 mResultsReceived;
+ LLSD mResultsContent;
+ LLUUID mQueryID;
+
+ LLSearchComboBox* mSearchComboBox;
+ LLScrollListCtrl* mSearchResults;
+};
+
+class FSPanelSearchPlaces : public FSSearchPanelBase
+{
+ LOG_CLASS(FSFloaterSearch);
+public:
+ FSPanelSearchPlaces();
+ static void processSearchReply(LLMessageSystem* msg, void**);
+
+ /*virtual*/ void focusDefaultElement();
+
+private:
+ /*virtual*/ BOOL postBuild();
+ virtual ~FSPanelSearchPlaces();
+
+ void onBtnFind();
+ void onSelectItem();
+ void onBtnNext();
+ void onBtnBack();
+
+ void find();
+ void resetSearch();
+ S32 showNextButton(S32);
+
+ const LLUUID& getQueryID() const { return mQueryID; }
+
+ S32 mNumResultsReturned;
+ S32 mStartSearch;
+ S32 mResultsReceived;
+ LLSD mResultsContent;
+ LLUUID mQueryID;
+
+ LLSearchComboBox* mSearchComboBox;
+ LLScrollListCtrl* mSearchResults;
+ LLComboBox* mPlacesCategory;
+};
+
+class FSPanelSearchLand : public FSSearchPanelBase
+{
+ LOG_CLASS(FSFloaterSearch);
+public:
+ FSPanelSearchLand();
+ static void processSearchReply(LLMessageSystem* msg, void**);
+
+private:
+ /*virtual*/ BOOL postBuild();
+ virtual ~FSPanelSearchLand();
+
+ void onBtnFind();
+ void onSelectItem();
+ void onBtnNext();
+ void onBtnBack();
+
+ void find();
+ void resetSearch();
+ S32 showNextButton(S32);
+
+ const LLUUID& getQueryID() const { return mQueryID; }
+
+ S32 mNumResultsReturned;
+ S32 mStartSearch;
+ S32 mResultsReceived;
+ LLSD mResultsContent;
+ LLUUID mQueryID;
+
+ LLLineEditor* mPriceEditor;
+ LLLineEditor* mAreaEditor;
+ LLScrollListCtrl* mSearchResults;
+};
+
+class FSPanelSearchClassifieds : public FSSearchPanelBase
+{
+ LOG_CLASS(FSFloaterSearch);
+public:
+ FSPanelSearchClassifieds();
+ static void processSearchReply(LLMessageSystem* msg, void**);
+
+ /*virtual*/ void focusDefaultElement();
+
+private:
+ /*virtual*/ BOOL postBuild();
+ virtual ~FSPanelSearchClassifieds();
+
+ void onBtnFind();
+ void onSelectItem();
+ void onBtnNext();
+ void onBtnBack();
+
+ void find();
+ void resetSearch();
+ S32 showNextButton(S32);
+
+ const LLUUID& getQueryID() const { return mQueryID; }
+
+ S32 mNumResultsReturned;
+ S32 mStartSearch;
+ S32 mResultsReceived;
+ LLSD mResultsContent;
+ LLUUID mQueryID;
+
+ LLSearchComboBox* mSearchComboBox;
+ LLScrollListCtrl* mSearchResults;
+ LLComboBox* mClassifiedsCategory;
+};
+
+class FSPanelSearchEvents : public FSSearchPanelBase
+{
+ LOG_CLASS(FSFloaterSearch);
+public:
+ FSPanelSearchEvents();
+ static void processSearchReply(LLMessageSystem* msg, void**);
+
+ /*virtual*/ void focusDefaultElement();
+
+private:
+ /*virtual*/ BOOL postBuild();
+ virtual ~FSPanelSearchEvents();
+
+ void onBtnFind();
+ void onSelectItem();
+ void onBtnNext();
+ void onBtnBack();
+ void onBtnTomorrow();
+ void onBtnYesterday();
+ void onBtnToday();
+
+ void find();
+ void setDay(S32 day);
+ void onSearchModeChanged();
+ void resetSearch();
+ S32 showNextButton(S32);
+
+ const LLUUID& getQueryID() const { return mQueryID; }
+
+ S32 mNumResultsReturned;
+ S32 mResultsReceived;
+ S32 mStartSearch;
+ S32 mDay;
+ LLSD mResultsContent;
+ LLUUID mQueryID;
+
+ LLSearchComboBox* mSearchComboBox;
+ LLScrollListCtrl* mSearchResults;
+ LLRadioGroup* mEventsMode;
+};
+
+class FSPanelSearchWeb : public FSSearchPanelBase
+{
+ LOG_CLASS(FSFloaterSearch);
+public:
+ FSPanelSearchWeb();
+ /*virtual*/ BOOL postBuild();
+ void loadURL(const SearchQuery &query);
+ /*virtual*/ void focusDefaultElement();
+ /*virtual*/ void draw();
+ void resetFocusOnLoad() { mResetFocusOnLoad = true; }
+
+private:
+ virtual ~FSPanelSearchWeb() {};
+
+ LLMediaCtrl* mWebBrowser;
+ LLSD mCategoryPaths;
+
+ bool mResetFocusOnLoad;
+};
+
+class FSFloaterSearch : public LLFloater
+{
+ LOG_CLASS(FSFloaterSearch);
+public:
+ typedef enum e_search_category
+ {
+ SC_AVATAR,
+ SC_GROUP,
+ SC_PLACE,
+ SC_CLASSIFIED
+ } ESearchCategory;
+
+ struct _Params : public LLInitParam::Block<_Params, LLFloater::Params>
+ {
+ Optional<SearchQuery> search;
+ };
+
+ typedef LLSDParamAdapter<_Params> Params;
+
+ FSFloaterSearch(const Params& key);
+ ~FSFloaterSearch();
+ void onOpen(const LLSD& key);
+ BOOL postBuild();
+
+ void avatarNameUpdatedCallback(const LLUUID& id, const LLAvatarName& av_name);
+ void groupNameUpdatedCallback(const LLUUID& id, const std::string& name, bool is_group);
+ void onSelectedItem(const LLUUID& selected_item, ESearchCategory type);
+ void onSelectedEvent(const S32 selected_event);
+ void displayParcelDetails(const LLParcelData& parcel_data);
+ void displayClassifiedDetails(LLAvatarClassifiedInfo*& c_info);
+ void displayAvatarDetails(LLAvatarData* avatar_data);
+ void displayGroupDetails(LLGroupMgrGroupData*& group_data);
+ bool displayEventDetails(LLEventStruct event);
+ void displayEventParcelImage(const LLParcelData& parcel_data);
+ void setLoadingProgress(bool started);
+
+ template <class T>
+ static T* getSearchPanel(const std::string& panel_name);
+
+private:
+ virtual void onClose(bool app_quitting);
+ const LLUUID& getSelectedID() { return mSelectedID; }
+ LLVector3d mParcelGlobal;
+ LLUUID mSelectedID;
+ U32 mEventID;
+ bool mHasSelection;
+
+ void resetVerbs();
+ void flushDetails();
+ void onTabChange();
+ void onBtnPeopleProfile();
+ void onBtnPeopleIM();
+ void onBtnPeopleFriend();
+ void onBtnGroupProfile();
+ void onBtnGroupChat();
+ void onBtnGroupJoin();
+ void onBtnEventReminder();
+ void onBtnTeleport();
+ void onBtnMap();
+
+ void regionHandleCallback(U64 region_handle, LLVector3d pos_global);
+
+ FSSearchRemoteParcelInfoObserver* mRemoteParcelObserver;
+ FSSearchRemoteParcelInfoObserver* mRemoteParcelEventLocationObserver;
+ LLAvatarPropertiesObserver* mAvatarPropertiesObserver;
+ LLGroupMgrObserver* mGroupPropertiesRequest;
+ boost::signals2::connection mEventNotifierConnection;
+
+ FSPanelSearchPeople* mPanelPeople;
+ FSPanelSearchGroups* mPanelGroups;
+ FSPanelSearchPlaces* mPanelPlaces;
+ FSPanelSearchEvents* mPanelEvents;
+ FSPanelSearchLand* mPanelLand;
+ FSPanelSearchClassifieds* mPanelClassifieds;
+ FSPanelSearchWeb* mPanelWeb;
+
+ LLPanel* mDetailsPanel;
+ LLTextEditor* mDetailTitle;
+ LLTextEditor* mDetailDesc;
+ LLTextEditor* mDetailAux1;
+ LLTextEditor* mDetailAux2;
+ LLTextEditor* mDetailLocation;
+ LLTextureCtrl* mDetailSnapshot;
+ LLTextureCtrl* mDetailSnapshotParcel;
+ LLIconCtrl* mDetailMaturity;
+ LLTabContainer* mTabContainer;
+};
+
+#endif // FS_FLOATERSEARCH_H
diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp
index 72bdbb6975..715649e844 100644
--- a/indra/newview/llavatarpropertiesprocessor.cpp
+++ b/indra/newview/llavatarpropertiesprocessor.cpp
@@ -468,6 +468,8 @@ void LLAvatarPropertiesProcessor::processClassifiedInfoReply(LLMessageSystem* ms
// Request processed, no longer pending
self->removePendingRequest(c_info.creator_id, APT_CLASSIFIED_INFO);
self->notifyObservers(c_info.creator_id, &c_info, APT_CLASSIFIED_INFO);
+ self->removePendingRequest(c_info.classified_id, APT_CLASSIFIED_INFO);
+ self->notifyObservers(c_info.classified_id, &c_info, APT_CLASSIFIED_INFO);
}
diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h
index 0a1445419e..c73cc69e62 100644
--- a/indra/newview/llavatarpropertiesprocessor.h
+++ b/indra/newview/llavatarpropertiesprocessor.h
@@ -52,6 +52,9 @@ enum EAvatarProcessorType
{
APT_PROPERTIES_LEGACY, // APT_PROPERTIES via udp request (Truncates data!!!)
APT_PROPERTIES, // APT_PROPERTIES via http request
+ APT_NOTES,
+ APT_GROUPS,
+ APT_PICKS,
APT_PICK_INFO,
APT_TEXTURES,
APT_CLASSIFIEDS,
@@ -105,6 +108,24 @@ struct LLAvatarData
typedef std::pair<LLUUID, std::string> pick_data_t;
typedef std::list< pick_data_t> picks_list_t;
picks_list_t picks_list;
+ BOOL allow_publish;
+ LLAvatarData() = default;
+ LLAvatarData(const LLAvatarLegacyData& legacy_data)
+ {
+ agent_id = legacy_data.agent_id;
+ avatar_id = legacy_data.avatar_id;
+ image_id = legacy_data.image_id;
+ fl_image_id = legacy_data.fl_image_id;
+ partner_id = legacy_data.partner_id;
+ about_text = legacy_data.about_text;
+ fl_about_text = legacy_data.fl_about_text;
+ born_on = legacy_data.born_on;
+ profile_url = legacy_data.profile_url;
+ caption_index = legacy_data.caption_index;
+ caption_text = legacy_data.caption_text;
+ customer_type = legacy_data.customer_type;
+ flags = legacy_data.flags;
+ }
};
struct LLAvatarData::LLGroupData
@@ -140,6 +161,45 @@ struct LLPickData
LLUUID session_id;
};
+struct LLAvatarPicks
+{
+ LLUUID agent_id;
+ LLUUID target_id; //target id
+
+ typedef std::pair<LLUUID,std::string> pick_data_t;
+ typedef std::list< pick_data_t> picks_list_t;
+ picks_list_t picks_list;
+};
+
+struct LLAvatarNotes
+{
+ LLUUID agent_id;
+ LLUUID target_id; //target id
+ std::string notes;
+};
+
+struct LLAvatarGroups
+{
+ LLUUID agent_id;
+ LLUUID avatar_id; //target id
+ BOOL list_in_profile;
+
+ struct LLGroupData;
+ typedef std::list<LLGroupData> group_list_t;
+
+ group_list_t group_list;
+
+ struct LLGroupData
+ {
+ U64 group_powers;
+ BOOL accept_notices;
+ std::string group_title;
+ LLUUID group_id;
+ std::string group_name;
+ LLUUID group_insignia_id;
+ };
+};
+
struct LLAvatarClassifieds
{
LLUUID agent_id;
diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp
index d46b49362a..93389bbc0f 100644
--- a/indra/newview/lleventnotifier.cpp
+++ b/indra/newview/lleventnotifier.cpp
@@ -182,6 +182,23 @@ bool LLEventNotifier::add(U32 eventId, F64 eventEpoch, const std::string& eventD
}
+bool LLEventNotifier::add(const LLEventStruct& event)
+{
+ if (mNewEventSignal(event)) return false;
+ LLEventNotification *new_enp = new LLEventNotification(event.eventId, event.eventEpoch, event.eventDateStr, event.eventName);
+
+ LL_INFOS() << "Add event " << event.eventName << " id " << event.eventId << " date " << event.eventDateStr << LL_ENDL;
+ if(!new_enp->isValid())
+ {
+ delete new_enp;
+ return false;
+ }
+
+ mEventNotifications[new_enp->getEventID()] = new_enp;
+ return true;
+
+}
+
void LLEventNotifier::add(U32 eventId)
{
@@ -211,7 +228,21 @@ void LLEventNotifier::processEventInfoReply(LLMessageSystem *msg, void **)
msg->getString("EventData", "Date", eventd_date);
msg->getU32("EventData", "DateUTC", event_time_utc);
- gEventNotifier.add(event_id, (F64)event_time_utc, eventd_date, event_name);
+ //gEventNotifier.add(event_id, (F64)event_time_utc, eventd_date, event_name);
+
+ LLEventStruct event(event_id, (F64)event_time_utc, eventd_date, event_name);
+ msg->getString("EventData", "Creator", event.creator);
+ msg->getString("EventData", "Category", event.category);
+ msg->getString("EventData", "Desc", event.desc);
+ msg->getU32("EventData", "Duration", event.duration);
+ msg->getU32("EventData", "Cover", event.cover);
+ msg->getU32("EventData", "Amount", event.amount);
+ msg->getString("EventData", "SimName", event.simName);
+ msg->getVector3d("EventData", "GlobalPos", event.globalPos);
+ msg->getU32("EventData", "EventFlags", event.flags);
+
+ gEventNotifier.add(event);
+
}
@@ -249,16 +280,21 @@ void LLEventNotifier::load(const LLSD& event_options)
substitution["datetime"] = date;
LLStringUtil::format(dateStr, substitution);
- add(response["event_id"].asInteger(), response["event_date_ut"], dateStr, response["event_name"].asString());
+ //add(response["event_id"].asInteger(), response["event_date_ut"], dateStr, response["event_name"].asString());
+ LLEventStruct event(response["event_id"].asInteger(), response["event_date_ut"], dateStr, response["event_name"].asString());
+ add(event);
}
else
{
- add(response["event_id"].asInteger(), response["event_date_ut"], response["event_date"].asString(), response["event_name"].asString());
+ //add(response["event_id"].asInteger(), response["event_date_ut"], response["event_date"].asString(), response["event_name"].asString());
+ LLEventStruct event(response["event_id"].asInteger(), response["event_date_ut"], response["event_date"].asString(), response["event_name"].asString());
+ add(event);
}
}
}
+
BOOL LLEventNotifier::hasNotification(const U32 event_id)
{
if (mEventNotifications.find(event_id) != mEventNotifications.end())
@@ -287,21 +323,21 @@ void LLEventNotifier::remove(const U32 event_id)
void LLEventNotifier::serverPushRequest(U32 event_id, bool add)
{
// Push up a message to tell the server we have this notification.
- gMessageSystem->newMessage(add?"EventNotificationAddRequest":"EventNotificationRemoveRequest");
+ gMessageSystem->newMessageFast(add ? _PREHASH_EventNotificationAddRequest : _PREHASH_EventNotificationRemoveRequest);
gMessageSystem->nextBlockFast(_PREHASH_AgentData);
gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- gMessageSystem->nextBlock("EventData");
- gMessageSystem->addU32("EventID", event_id);
+ gMessageSystem->nextBlockFast(_PREHASH_EventData);
+ gMessageSystem->addU32Fast(_PREHASH_EventID, event_id);
gAgent.sendReliableMessage();
}
-LLEventNotification::LLEventNotification(U32 eventId, F64 eventEpoch, const std::string& eventDateStr, const std::string &eventName) :
+LLEventNotification::LLEventNotification(U32 eventId, F64 eventEpoch, std::string eventDateStr, std::string eventName) :
mEventID(eventId),
- mEventName(eventName),
+ mEventName(std::move(eventName)),
mEventDateEpoch(eventEpoch),
- mEventDateStr(eventDateStr)
+ mEventDateStr(std::move(eventDateStr))
{
}
diff --git a/indra/newview/lleventnotifier.h b/indra/newview/lleventnotifier.h
index b928969d2f..d8ab2bafce 100644
--- a/indra/newview/lleventnotifier.h
+++ b/indra/newview/lleventnotifier.h
@@ -27,12 +27,31 @@
#ifndef LL_LLEVENTNOTIFIER_H
#define LL_LLEVENTNOTIFIER_H
+#include <utility>
#include "llframetimer.h"
#include "v3dmath.h"
class LLEventNotification;
class LLMessageSystem;
+typedef struct event_st{
+ U32 eventId = 0;
+ F64 eventEpoch = 0.0;
+ std::string eventDateStr;
+ std::string eventName;
+ std::string creator;
+ std::string category;
+ std::string desc;
+ U32 duration = 0;
+ U32 cover = 0;
+ U32 amount = 0;
+ std::string simName;
+ LLVector3d globalPos;
+ U32 flags = 0;
+ event_st(U32 id, F64 epoch, std::string date_str, std::string name)
+ : eventId(id), eventEpoch(epoch), eventDateStr(std::move(date_str)), eventName(std::move(name)){}
+ event_st() = default;
+} LLEventStruct;
class LLEventNotifier
{
@@ -41,6 +60,7 @@ public:
virtual ~LLEventNotifier();
void update(); // Notify the user of the event if it's coming up
+ bool add(const LLEventStruct& event);
bool add(U32 eventId, F64 eventEpoch, const std::string& eventDateStr, const std::string &eventName);
void add(U32 eventId);
@@ -56,6 +76,13 @@ public:
static void processEventInfoReply(LLMessageSystem *msg, void **);
+ typedef boost::signals2::signal<bool(LLEventStruct event)> new_event_signal_t;
+ new_event_signal_t mNewEventSignal;
+ boost::signals2::connection setNewEventCallback(const new_event_signal_t::slot_type& cb)
+ {
+ return mNewEventSignal.connect(cb);
+ };
+
protected:
en_map mEventNotifications;
LLFrameTimer mNotificationTimer;
@@ -65,7 +92,7 @@ protected:
class LLEventNotification
{
public:
- LLEventNotification(U32 eventId, F64 eventEpoch, const std::string& eventDateStr, const std::string &eventName);
+ LLEventNotification(U32 eventId, F64 eventEpoch, std::string eventDateStr, std::string eventName);
U32 getEventID() const { return mEventID; }
diff --git a/indra/newview/llpanelprofileclassifieds.h b/indra/newview/llpanelprofileclassifieds.h
index d1aa5f55e3..76e6eb6808 100644
--- a/indra/newview/llpanelprofileclassifieds.h
+++ b/indra/newview/llpanelprofileclassifieds.h
@@ -324,8 +324,11 @@ private:
S32 mPriceForListing;
+public:
static void handleSearchStatResponse(LLUUID classifiedId, LLSD result);
+private:
+
typedef std::list<LLPanelProfileClassified*> panel_list_t;
static panel_list_t sAllPanels;
diff --git a/indra/newview/llsearchcombobox.h b/indra/newview/llsearchcombobox.h
index ff9c74a6a8..891237e92e 100644
--- a/indra/newview/llsearchcombobox.h
+++ b/indra/newview/llsearchcombobox.h
@@ -61,6 +61,11 @@ public:
~LLSearchComboBox();
+ /**
+ * Sets focus to text box
+ */
+ void focusTextEntry();
+
protected:
LLSearchComboBox(const Params&p);
@@ -93,11 +98,6 @@ protected:
*/
void onSelectionCommit();
- /**
- * Sets focus to text box
- */
- void focusTextEntry();
-
LLButton* mSearchButton;
};
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index c5a22d08f3..96ff0fceb4 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -215,6 +215,9 @@
#include "lldxhardware.h"
#endif
+#include "fsfloatersearch.h"
+
+
//
// exported globals
//
@@ -2779,6 +2782,14 @@ void register_viewer_callbacks(LLMessageSystem* msg)
msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply);
+ // directory search
+ msg->setHandlerFuncFast(_PREHASH_DirPeopleReply, FSPanelSearchPeople::processSearchReply);
+ msg->setHandlerFuncFast(_PREHASH_DirPlacesReply, FSPanelSearchPlaces::processSearchReply);
+ msg->setHandlerFuncFast(_PREHASH_DirGroupsReply, FSPanelSearchGroups::processSearchReply);
+ msg->setHandlerFuncFast(_PREHASH_DirEventsReply, FSPanelSearchEvents::processSearchReply);
+ msg->setHandlerFuncFast(_PREHASH_DirLandReply, FSPanelSearchLand::processSearchReply);
+ msg->setHandlerFuncFast(_PREHASH_DirClassifiedReply, FSPanelSearchClassifieds::processSearchReply);
+
msg->setHandlerFunc("MapBlockReply", LLWorldMapMessage::processMapBlockReply);
msg->setHandlerFunc("MapItemReply", LLWorldMapMessage::processMapItemReply);
msg->setHandlerFunc("EventInfoReply", LLEventNotifier::processEventInfoReply);
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 38fde25ebb..945d75351c 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -174,6 +174,8 @@
#include "llscriptfloater.h"
#include "llsyswellwindow.h"
+#include "fsfloatersearch.h"
+
// *NOTE: Please add files in alphabetical order to keep merges easy.
// handle secondlife:///app/openfloater/{NAME} URLs
@@ -490,7 +492,8 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>);
LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>);
LLFloaterReg::add("simple_snapshot", "floater_simple_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSimpleSnapshot>);
- LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
+ LLFloaterReg::add("search", "floater_fs_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<FSFloaterSearch>);
+ //LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
LLFloaterReg::add("profile", "floater_profile.xml",(LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProfile>);
LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>);
diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp
index 4d7d331433..c63f7338ed 100644
--- a/indra/newview/llviewerinput.cpp
+++ b/indra/newview/llviewerinput.cpp
@@ -48,6 +48,9 @@
#include "llinitparam.h"
#include "llselectmgr.h"
+#include "llfloaterwebcontent.h"
+#include "fsfloatersearch.h"
+
//
// Constants
//
@@ -648,6 +651,12 @@ bool start_chat( EKeystate s )
bool start_gesture( EKeystate s )
{
+ LLFloater* focused_floater = gFloaterView->getFocusedFloater();
+ if (focused_floater && (dynamic_cast<LLFloaterWebContent*>(focused_floater) || dynamic_cast<FSFloaterSearch*>(focused_floater)))
+ {
+ return true;
+ }
+
LLUICtrl* focus_ctrlp = dynamic_cast<LLUICtrl*>(gFocusMgr.getKeyboardFocus());
if (KEYSTATE_UP == s &&
! (focus_ctrlp && focus_ctrlp->acceptsTextInput()))
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 2ca27e0e1a..88ff6a28b4 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -72,6 +72,7 @@
#include "llfloaterpay.h"
#include "llfloaterreporter.h"
#include "llfloatersearch.h"
+#include "fsfloatersearch.h"
#include "llfloaterscriptdebug.h"
#include "llfloatersnapshot.h"
#include "llfloatertools.h"
diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp
index 16ddc2f89c..b8c9594aa7 100644
--- a/indra/newview/llviewernetwork.cpp
+++ b/indra/newview/llviewernetwork.cpp
@@ -629,6 +629,18 @@ bool LLGridManager::isInProductionGrid()
return mIsInProductionGrid;
}
+bool LLGridManager::isInSecondlife()
+{
+ //return (isInSLMain() || isInSLBeta());
+ return true;
+}
+
+bool LLGridManager::isInOpenSim()
+{
+ // FIX THIS TO SUPPORT OPENSIM
+ return false;
+}
+
bool LLGridManager::isSystemGrid(const std::string& grid)
{
std::string grid_name = getGrid(grid);
diff --git a/indra/newview/llviewernetwork.h b/indra/newview/llviewernetwork.h
index 2ed663e038..7d9c70994c 100644
--- a/indra/newview/llviewernetwork.h
+++ b/indra/newview/llviewernetwork.h
@@ -174,6 +174,20 @@ class LLGridManager : public LLSingleton<LLGridManager>
//@}
+ typedef enum e_grid_platform {
+ NOPLATFORM = 0,
+ SLMAIN,
+ SLBETA,
+ OPENSIM,
+ HALCYON
+ } EGridPlatform;
+
+ typedef enum e_add_grid {
+ ADD_MANUAL = 0,
+ ADD_HYPERGRID,
+ ADD_LINK
+ } EAddGridType;
+
/* ================================================================
* @name Selecting the current grid
* @{
@@ -198,6 +212,11 @@ class LLGridManager : public LLSingleton<LLGridManager>
/// Is the selected grid one of the hard-coded default grids (Agni or Aditi)
bool isSystemGrid() { return isSystemGrid(mGrid); }
+ /// Is the selected grid Second Life?
+ bool isInSecondlife();
+
+ bool isInOpenSim();
+
/// Is the selected grid a production grid?
bool isInProductionGrid();
/**
diff --git a/indra/newview/skins/default/textures/icon_auction.tga b/indra/newview/skins/default/textures/icon_auction.tga
new file mode 100644
index 0000000000..baf7d0d000
--- /dev/null
+++ b/indra/newview/skins/default/textures/icon_auction.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/icon_group.tga b/indra/newview/skins/default/textures/icon_group.tga
new file mode 100644
index 0000000000..79cd71689d
--- /dev/null
+++ b/indra/newview/skins/default/textures/icon_group.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/icon_legacy_event.tga b/indra/newview/skins/default/textures/icon_legacy_event.tga
new file mode 100644
index 0000000000..7805dbce60
--- /dev/null
+++ b/indra/newview/skins/default/textures/icon_legacy_event.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/icon_legacy_event_adult.tga b/indra/newview/skins/default/textures/icon_legacy_event_adult.tga
new file mode 100644
index 0000000000..c344fb1e78
--- /dev/null
+++ b/indra/newview/skins/default/textures/icon_legacy_event_adult.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/icon_legacy_event_mature.tga b/indra/newview/skins/default/textures/icon_legacy_event_mature.tga
new file mode 100644
index 0000000000..61c879bc92
--- /dev/null
+++ b/indra/newview/skins/default/textures/icon_legacy_event_mature.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/icon_place.tga b/indra/newview/skins/default/textures/icon_place.tga
new file mode 100644
index 0000000000..e10655c6ec
--- /dev/null
+++ b/indra/newview/skins/default/textures/icon_place.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_1.png b/indra/newview/skins/default/textures/icons/ProgressLarge_1.png
new file mode 100644
index 0000000000..ff277fc431
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ProgressLarge_1.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_10.png b/indra/newview/skins/default/textures/icons/ProgressLarge_10.png
new file mode 100644
index 0000000000..1c94e21d89
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ProgressLarge_10.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_11.png b/indra/newview/skins/default/textures/icons/ProgressLarge_11.png
new file mode 100644
index 0000000000..89bea9b474
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ProgressLarge_11.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_12.png b/indra/newview/skins/default/textures/icons/ProgressLarge_12.png
new file mode 100644
index 0000000000..da38475ba4
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ProgressLarge_12.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_2.png b/indra/newview/skins/default/textures/icons/ProgressLarge_2.png
new file mode 100644
index 0000000000..c024275ebe
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ProgressLarge_2.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_3.png b/indra/newview/skins/default/textures/icons/ProgressLarge_3.png
new file mode 100644
index 0000000000..87b931e72e
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ProgressLarge_3.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_4.png b/indra/newview/skins/default/textures/icons/ProgressLarge_4.png
new file mode 100644
index 0000000000..6dbef74361
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ProgressLarge_4.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_5.png b/indra/newview/skins/default/textures/icons/ProgressLarge_5.png
new file mode 100644
index 0000000000..daccf9b375
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ProgressLarge_5.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_6.png b/indra/newview/skins/default/textures/icons/ProgressLarge_6.png
new file mode 100644
index 0000000000..cafddcb88d
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ProgressLarge_6.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_7.png b/indra/newview/skins/default/textures/icons/ProgressLarge_7.png
new file mode 100644
index 0000000000..8acf6472d4
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ProgressLarge_7.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_8.png b/indra/newview/skins/default/textures/icons/ProgressLarge_8.png
new file mode 100644
index 0000000000..df0e825cef
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ProgressLarge_8.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/icons/ProgressLarge_9.png b/indra/newview/skins/default/textures/icons/ProgressLarge_9.png
new file mode 100644
index 0000000000..293a7b8f5c
--- /dev/null
+++ b/indra/newview/skins/default/textures/icons/ProgressLarge_9.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/megapahit/icon_group.png b/indra/newview/skins/default/textures/megapahit/icon_group.png
new file mode 100644
index 0000000000..f3872dea3f
--- /dev/null
+++ b/indra/newview/skins/default/textures/megapahit/icon_group.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/megapahit/icon_land_auction.png b/indra/newview/skins/default/textures/megapahit/icon_land_auction.png
new file mode 100644
index 0000000000..550703968f
--- /dev/null
+++ b/indra/newview/skins/default/textures/megapahit/icon_land_auction.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/megapahit/icon_land_forsale.png b/indra/newview/skins/default/textures/megapahit/icon_land_forsale.png
new file mode 100644
index 0000000000..209bb868ea
--- /dev/null
+++ b/indra/newview/skins/default/textures/megapahit/icon_land_forsale.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/megapahit/icon_place.png b/indra/newview/skins/default/textures/megapahit/icon_place.png
new file mode 100644
index 0000000000..60cf42424a
--- /dev/null
+++ b/indra/newview/skins/default/textures/megapahit/icon_place.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 968910d304..11eafcb45d 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -87,7 +87,7 @@ with the same filename but different name
<texture name="BreadCrumbBtn_Left_Off" file_name="widgets/BreadCrumbBtn_Left_Off.png" preload="false"/>
<texture name="BreadCrumbBtn_Left_Over" file_name="widgets/BreadCrumbBtn_Left_Over.png" preload="false"/>
<texture name="BreadCrumbBtn_Left_Press" file_name="widgets/BreadCrumbBtn_Left_Press.png" preload="false"/>
-
+
<texture name="BreadCrumbBtn_Middle_Disabled" file_name="widgets/BreadCrumbBtn_Middle_Disabled.png" preload="false"/>
<texture name="BreadCrumbBtn_Middle_Off" file_name="widgets/BreadCrumbBtn_Middle_Off.png" preload="false"/>
<texture name="BreadCrumbBtn_Middle_Over" file_name="widgets/BreadCrumbBtn_Middle_Over.png" preload="false"/>
@@ -192,7 +192,7 @@ with the same filename but different name
<texture name="Copy" file_name="icons/Copy.png" preload="false" />
<texture name="CopyBright" file_name="icons/CopyBright.png" preload="false" />
-
+
<texture name="DisclosureArrow_Opened_Off" file_name="widgets/DisclosureArrow_Opened_Off.png" preload="true" />
<texture name="ChatBarHandle" file_name="bottomtray/ChatBarHandle.png" preload="false" />
@@ -244,7 +244,7 @@ with the same filename but different name
<texture name="Group_Notices" file_name="icons/Group_Notices.png" preload="false" />
<texture name="Hand" file_name="icons/hand.png" preload="false" />
-
+
<texture name="Help_Press" file_name="navbar/Help_Press.png" preload="false" />
<texture name="Hierarchy_View_Disabled" file_name="icons/Hierarchy_View_Disabled.png" preload="false" />
@@ -257,16 +257,16 @@ with the same filename but different name
<texture name="Icon_Close_Foreground" file_name="windows/Icon_Close_Foreground.png" preload="true" />
<texture name="Icon_Close_Press" file_name="windows/Icon_Close_Press.png" preload="true" />
<texture name="Icon_Close_Toast" file_name="windows/Icon_Close_Toast.png" preload="true" />
-
+
<texture name="Icon_Copy" file_name="icons/copy_clipboard.png" preload="true" />
-
+
<texture name="Icon_Delete" file_name="icons/delete_icon.png" preload="true" />
<texture name="Icon_Dock_Foreground" file_name="windows/Icon_Dock_Foreground.png" preload="true" />
<texture name="Icon_Dock_Press" file_name="windows/Icon_Dock_Press.png" preload="true" />
<texture name="Icon_File_Upload" file_name="icons/file_upload.png" preload="true" />
-
+
<texture name="Icon_For_Sale" file_name="icons/Icon_For_Sale.png" preload="false" />
<texture name="Icon_Gear_Background" file_name="windows/Icon_Gear_Background.png" preload="false" />
@@ -279,14 +279,14 @@ with the same filename but different name
<texture name="Icon_Minimize_Foreground" file_name="windows/Icon_Minimize_Foreground.png" preload="true" />
<texture name="Icon_Minimize_Press" file_name="windows/Icon_Minimize_Press.png" preload="true" />
-
+
<texture name="Icon_Paste" file_name="icons/paste_clipboard.png" preload="true" />
<texture name="Icon_Restore_Foreground" file_name="windows/Icon_Restore_Foreground.png" preload="false" />
<texture name="Icon_Restore_Press" file_name="windows/Icon_Restore_Press.png" preload="false" />
<texture name="Icon_Snapshot" file_name="icons/snapshot_icon.png" preload="true" />
-
+
<texture name="Icon_Use_Texture" file_name="icons/texture_icon.png" preload="true" />
<texture name="Info" file_name="icons/Info.png" preload="false" />
@@ -320,7 +320,7 @@ with the same filename but different name
<texture name="Inv_LostOpen" file_name="icons/Inv_LostOpen.png" preload="false" />
<texture name="Inv_Landmark" file_name="icons/Inv_Landmark.png" preload="false" />
<texture name="Inv_Material" file_name="icons/Inv_Material.png" preload="false" />
- <texture name="Inv_Mesh" file_name="icons/Inv_Mesh.png" preload="false" />
+ <texture name="Inv_Mesh" file_name="icons/Inv_Mesh.png" preload="false" />
<texture name="Inv_Notecard" file_name="icons/Inv_Notecard.png" preload="false" />
<texture name="Inv_Object" file_name="icons/Inv_Object.png" preload="false" />
<texture name="Inv_Object_Multi" file_name="icons/Inv_Object_Multi.png" preload="false" />
@@ -375,7 +375,7 @@ with the same filename but different name
<texture name="Locked_Icon" file_name="icons/Locked_Icon.png" preload="false" />
<texture name="Map_Placeholder_Icon" file_name="icons/map_placeholder.png" preload="true" />
-
+
<texture name="Marketplace_Dropzone_Background" file_name="widgets/Marketplace_Dropzone_Background.png" preload="true" />
<texture name="MarketplaceBtn_Off" file_name="widgets/MarketplaceBtn_Off.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" />
<texture name="MarketplaceBtn_Selected" file_name="widgets/MarketplaceBtn_Selected.png" preload="true" scale.left="30" scale.top="19" scale.right="35" scale.bottom="4" />
@@ -391,7 +391,7 @@ with the same filename but different name
<texture name="ModelImport_Status_Good" file_name="green_checkmark.png" preload="false"/>
<texture name="ModelImport_Status_Warning" file_name="lag_status_warning.tga" preload="false"/>
<texture name="ModelImport_Status_Error" file_name="red_x.png" preload="false"/>
-
+
<texture name="MouseLook_View_Off" file_name="bottomtray/Mouselook_View_Off.png" preload="false" />
<texture name="MouseLook_View_On" file_name="bottomtray/Mouselook_View_On.png" preload="false" />
@@ -547,7 +547,7 @@ with the same filename but different name
<texture name="Profile_Perm_Objects_Enabled" file_name="icons/Profile_Perm_Objects_Enabled.png" preload="true"/>
<texture name="Profile_Perm_Online_Disabled" file_name="icons/Profile_Perm_Online_Disabled.png" preload="true"/>
<texture name="Profile_Perm_Online_Enabled" file_name="icons/Profile_Perm_Online_Enabled.png" preload="true"/>
-
+
<texture name="ProgressBar" file_name="widgets/ProgressBar.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" />
<texture name="ProgressBarSolid" file_name="widgets/ProgressBarSolid.png" preload="true" scale.left="4" scale.top="11" scale.right="48" scale.bottom="3" />
<texture name="ProgressTrack" file_name="widgets/ProgressTrack.png" preload="true" scale.left="4" scale.top="13" scale.right="148" scale.bottom="2" />
@@ -740,7 +740,7 @@ with the same filename but different name
<texture name="UpArrow_Off" file_name="icons/UpArrow_Off.png" preload="false" />
<texture name="Video_URL_Off" file_name="icons/Video_URL_Off.png" preload="true" />
-
+
<texture name="Vertical Drag Handle" file_name="widgets/vertical_drag_handle.png" scale.left="2" scale.right="7" scale.bottom="8" scale.top="120" scale_type="scale_outer"/>
<texture name="VirtualTrackball_Moon_Back" file_name="widgets/track_control_moon_back.png" />
@@ -756,7 +756,7 @@ with the same filename but different name
<texture name="VirtualTrackball_Sphere" file_name="widgets/track_control_sphere.png" />
<texture name="VirtualTrackball_Sun_Back" file_name="widgets/track_control_sun_back.png" />
<texture name="VirtualTrackball_Sun_Front" file_name="widgets/track_control_sun_front.png" />
-
+
<texture name="Volume_Background" file_name="windows/Volume_Background.png" preload="false"
scale.left="6" scale.top="33" scale.right="63" scale.bottom="10" />
@@ -765,7 +765,7 @@ with the same filename but different name
<texture name="VoicePTT_Lvl3" file_name="bottomtray/VoicePTT_Lvl3.png" preload="false" />
<texture name="VoicePTT_Off" file_name="bottomtray/VoicePTT_Off.png" preload="false" />
<texture name="VoicePTT_On" file_name="bottomtray/VoicePTT_On.png" preload="false" />
-
+
<texture name="Wearables_Divider" file_name="windows/Wearables_Divider.png" preload="false" />
<texture name="Add_Icon" file_name="icons/add_icon.png" preload="false" />
@@ -880,7 +880,7 @@ with the same filename but different name
<texture name="buy_off" file_name="widgets/buy_off.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/>
<texture name="buy_over" file_name="widgets/buy_over.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/>
<texture name="buy_press" file_name="widgets/buy_press.png" preload="true" scale.left="2" scale.top="15" scale.right="67" scale.bottom="4"/>
-
+
<texture name="hint_background" file_name="windows/hint_background.png" preload="false" scale.left="8" scale.top="70" scale.right="195" scale.bottom="11"/>
<texture name="hint_arrow_left" file_name="windows/hint_arrow_left.png" preload="false"/>
<texture name="hint_arrow_right" file_name="windows/hint_arrow_right.png" preload="false"/>
@@ -907,4 +907,26 @@ with the same filename but different name
<texture name="Single_Folder_Up" file_name="icons/single_folder_up.png" preload="true"/>
<texture name="Icon_Color_Palette" file_name="icons/Icon_Color_Palette.png" preload="false"/>
<texture name="Icon_Font_Size" file_name="icons/Icon_Font_Size.png" preload="false"/>
+
+ <texture name="Icon_Place" file_name="megapahit/icon_place.png" preload="false" />
+ <texture name="Icon_Auction" file_name="megapahit/icon_land_auction.png" preload="false" />
+ <texture name="Icon_For_Sale" file_name="megapahit/icon_land_forsale.png" preload="false" />
+ <texture name="Icon_Group" file_name="megapahit/icon_group.png" preload="false" />
+ <texture name="Icon_Legacy_Event_PG" file_name="icons/Parcel_PG_Dark.png" preload="false" />
+ <texture name="Icon_Legacy_Event_Mature" file_name="icons/Parcel_M_Dark.png" preload="false" />
+ <texture name="Icon_Legacy_Event_Adult" file_name="icons/Parcel_R_Dark.png" preload="false" />
+
+ <texture name="ProgressLarge_1" file_name="icons/ProgressLarge_1.png" preload="true" />
+ <texture name="ProgressLarge_2" file_name="icons/ProgressLarge_2.png" preload="true" />
+ <texture name="ProgressLarge_3" file_name="icons/ProgressLarge_3.png" preload="true" />
+ <texture name="ProgressLarge_4" file_name="icons/ProgressLarge_4.png" preload="true" />
+ <texture name="ProgressLarge_5" file_name="icons/ProgressLarge_5.png" preload="true" />
+ <texture name="ProgressLarge_6" file_name="icons/ProgressLarge_6.png" preload="true" />
+ <texture name="ProgressLarge_7" file_name="icons/ProgressLarge_7.png" preload="true" />
+ <texture name="ProgressLarge_8" file_name="icons/ProgressLarge_8.png" preload="true" />
+ <texture name="ProgressLarge_9" file_name="icons/ProgressLarge_9.png" preload="true" />
+ <texture name="ProgressLarge_10" file_name="icons/ProgressLarge_10.png" preload="true" />
+ <texture name="ProgressLarge_11" file_name="icons/ProgressLarge_11.png" preload="true" />
+ <texture name="ProgressLarge_12" file_name="icons/ProgressLarge_12.png" preload="true" />
+
</textures>
diff --git a/indra/newview/skins/default/xui/en/floater_fs_search.xml b/indra/newview/skins/default/xui/en/floater_fs_search.xml
new file mode 100644
index 0000000000..2372bc03ba
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_fs_search.xml
@@ -0,0 +1,337 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_resize="true"
+ default_tab_group="1"
+ height="590"
+ help_topic="search"
+ layout="topleft"
+ legacy_header_height="0"
+ min_height="590"
+ min_width="660"
+ name="floater_search"
+ positioning="centered"
+ save_rect="true"
+ single_instance="true"
+ title="SEARCH"
+ width="780">
+ <!-- Strings -->
+ <floater.string name="string.location">
+ Location: [LOCATION]
+ </floater.string>
+ <floater.string name="string.traffic">
+ Traffic: [DWELL]
+ </floater.string>
+ <floater.string name="string.area">
+ Area: [AREA]
+ </floater.string>
+ <floater.string name="string.members">
+ Members: [MEMBER_COUNT]
+ </floater.string>
+ <floater.string name="string.founder">
+ Founder: [FOUNDER]
+ </floater.string>
+ <floater.string name="string.age">
+ Age: [AGE]
+ </floater.string>
+ <floater.string name="string.partner">
+ Partner: [PARTNER]
+ </floater.string>
+ <floater.string name="string.listing_price">
+ Listing Price: [LISTING_PRICE]
+ </floater.string>
+ <floater.string name="string.slurl">
+ [SLURL]
+ </floater.string>
+ <floater.string name="string.duration">
+ Duration: [DURATION]
+ </floater.string>
+ <floater.string name="string.covercharge">
+ Cover: [COVERCHARGE]
+ </floater.string>
+ <!-- Tab time -->
+ <tab_container
+ layout="topleft"
+ follows="all"
+ top="1"
+ left="0"
+ name="ls_tabs"
+ tab_min_width="90"
+ tab_position="top"
+ width="780"
+ height="585">
+ <panel
+ class="panel_ls_web"
+ filename="panel_fs_search_legacy_web.xml"
+ label="Websearch"
+ layout="topleft"
+ name="panel_ls_web" />
+ <panel
+ class="panel_ls_people"
+ filename="panel_fs_search_legacy_people.xml"
+ label="People"
+ layout="topleft"
+ name="panel_ls_people" />
+ <panel
+ class="panel_ls_groups"
+ filename="panel_fs_search_legacy_groups.xml"
+ label="Groups"
+ layout="topleft"
+ name="panel_ls_groups" />
+ <panel
+ class="panel_ls_places"
+ filename="panel_fs_search_legacy_places.xml"
+ label="Places"
+ layout="topleft"
+ name="panel_ls_places" />
+ <panel
+ class="panel_ls_land"
+ filename="panel_fs_search_legacy_land.xml"
+ label="Land Sales"
+ layout="topleft"
+ name="panel_ls_land" />
+ <panel
+ class="panel_ls_events"
+ filename="panel_fs_search_legacy_events.xml"
+ label="Events"
+ layout="topleft"
+ name="panel_ls_events" />
+ <panel
+ class="panel_ls_classifieds"
+ filename="panel_fs_search_legacy_classifieds.xml"
+ label="Classifieds"
+ layout="topleft"
+ name="panel_ls_classifieds" />
+ </tab_container>
+ <!-- Details/Action Panes -->
+ <panel
+ border="true"
+ follows="top|right|bottom"
+ height="508"
+ layout="topleft"
+ left="412"
+ top="80"
+ width="366"
+ name="panel_ls_details">
+ <text_editor
+ left="12"
+ top="5"
+ height="24"
+ width="340"
+ layout="topleft"
+ follows="left|top|right"
+ name="title"
+ bg_visible="false"
+ border_visible="false"
+ allow_scroll="false"
+ h_pad="0"
+ v_pad="0"
+ halign="center"
+ enabled="false"
+ use_ellipses="true"
+ font="SansSerifHugeBold"
+ value="Undefined name" />
+ <texture_picker
+ enabled="false"
+ fallback_image="Generic_Person_Large"
+ follows="left|top|right"
+ height="210"
+ layout="topleft"
+ left="78"
+ name="snapshot"
+ top_pad="4"
+ width="210"/>
+ <texture_picker
+ enabled="false"
+ fallback_image="default_land_picture.j2c"
+ follows="left|top|right"
+ height="210"
+ layout="topleft"
+ left_delta="0"
+ name="snapshot_parcel"
+ top_delta="0"
+ visible="false"
+ width="210"/>
+ <text_editor
+ left="20"
+ top_pad="2"
+ height="16"
+ width="180"
+ layout="topleft"
+ follows="left|top|right"
+ name="aux1"
+ bg_visible="false"
+ border_visible="false"
+ h_pad="0"
+ v_pad="0"
+ word_wrap="true"
+ enabled="false"
+ max_length="117"
+ allow_scroll="false"
+ parse_urls="true"
+ value="Auxilary info field 1"/>
+ <text_editor
+ left_pad="4"
+ top_delta="0"
+ height="16"
+ width="140"
+ layout="topleft"
+ follows="left|top|right"
+ name="aux2"
+ bg_visible="false"
+ border_visible="false"
+ h_pad="0"
+ v_pad="0"
+ word_wrap="true"
+ enabled="false"
+ max_length="117"
+ allow_scroll="false"
+ parse_urls="true"
+ value="Auxilary info field 2"/>
+ <icon
+ follows="top|right"
+ height="16"
+ image_name="Unknown_Icon"
+ layout="topleft"
+ left="20"
+ top_pad="2"
+ name="maturity_icon"
+ width="18" />
+ <text_editor
+ left_pad="4"
+ top_delta="0"
+ height="28"
+ width="302"
+ layout="topleft"
+ follows="left|top|right"
+ name="location"
+ bg_visible="false"
+ border_visible="false"
+ h_pad="0"
+ v_pad="0"
+ word_wrap="true"
+ enabled="false"
+ max_length="117"
+ allow_scroll="false"
+ parse_urls="true"
+ value="Location info field"/>
+ <text_editor
+ left="20"
+ top_pad="12"
+ height="154"
+ width="324"
+ layout="topleft"
+ follows="left|top|right"
+ name="desc"
+ bg_visible="false"
+ border_visible="false"
+ h_pad="0"
+ v_pad="0"
+ word_wrap="true"
+ parse_urls="true"
+ enabled="false"
+ max_length="1000"
+ trusted_content="false"
+ value="You unlock this door with the key of imagination. Beyond it is another dimension: a dimension of sound, a dimension of sight, a dimension of mind. You're moving into a land of both shadow and substance, of things and ideas; you've just crossed over into the Twilight Zone. What you are about to see is real; the litigants on the screen are not actors. They are genuine citizens who, having filed their claims in a real small claims court, have been persuaded to drop their suits there and have them settled here, in this forum... the People's Court."/>
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Open Profile"
+ name="people_profile_btn"
+ top="484"
+ left="3"
+ width="120" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Send Message"
+ name="people_message_btn"
+ width="120"
+ left_pad="1" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Add Friend"
+ name="people_friend_btn"
+ width="120"
+ left_pad="1" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Open Profile"
+ name="group_profile_btn"
+ top="484"
+ left="3"
+ width="120" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Join Chat"
+ name="group_message_btn"
+ width="120"
+ left_pad="1" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Join Group"
+ name="group_join_btn"
+ width="120"
+ left_pad="1" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Teleport"
+ name="teleport_btn"
+ top="484"
+ left="3"
+ width="120" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Show on Map"
+ name="map_btn"
+ width="120"
+ left_pad="1" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Remind me"
+ name="event_reminder_btn"
+ width="120"
+ left_pad="1" />
+ <loading_indicator
+ left="134"
+ top="320"
+ follows="left|top|right"
+ mouse_opaque="false"
+ name="loading"
+ images_per_sec="1.0"
+ tab_stop="false"
+ height="100"
+ width="100"
+ visible="false" >
+ <images>
+ <image name="ProgressLarge_1"/>
+ <image name="ProgressLarge_2"/>
+ <image name="ProgressLarge_3"/>
+ <image name="ProgressLarge_4"/>
+ <image name="ProgressLarge_5"/>
+ <image name="ProgressLarge_6"/>
+ <image name="ProgressLarge_7"/>
+ <image name="ProgressLarge_8"/>
+ <image name="ProgressLarge_9"/>
+ <image name="ProgressLarge_10"/>
+ <image name="ProgressLarge_11"/>
+ <image name="ProgressLarge_12"/>
+ </images>
+ </loading_indicator>
+ </panel>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_world_map.xml b/indra/newview/skins/default/xui/en/floater_world_map.xml
index 2298005d73..3acae704c6 100644
--- a/indra/newview/skins/default/xui/en/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/en/floater_world_map.xml
@@ -86,7 +86,7 @@
height="22"
width="238"
follows="right|top"
- top="6"
+ top="6"
background_visible="false"
bg_alpha_color="DkGray2">
<text
@@ -605,7 +605,7 @@
Location:
</text>
<spinner
- control_name="Teleport_Coordinate_X"
+ control_name="teleport_coordinate_x"
decimal_digits="0"
follows="right|bottom"
height="23"
@@ -617,11 +617,11 @@
min_val="0"
name="teleport_coordinate_x"
width="44" >
- <spinner.commit_callback
+ <spinner.commit_callback
function="WMap.Coordinates" />
</spinner>
<spinner
- control_name="Teleport_Coordinate_Y"
+ control_name="teleport_coordinate_y"
decimal_digits="0"
follows="right|bottom"
height="23"
@@ -637,7 +637,7 @@
function="WMap.Coordinates" />
</spinner>
<spinner
- control_name="Teleport_Coordinate_Z"
+ control_name="teleport_coordinate_z"
decimal_digits="0"
follows="right|bottom"
height="23"
diff --git a/indra/newview/skins/default/xui/en/panel_fs_search_legacy_classifieds.xml b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_classifieds.xml
new file mode 100644
index 0000000000..66c35558b1
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_classifieds.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ follows="all"
+ height="566"
+ layout="topleft"
+ left="1"
+ width="780"
+ label="Classifieds"
+ name="panel_ls_classifieds">
+ <panel
+ border="false"
+ follows="top|left|right"
+ height="53"
+ layout="topleft"
+ left="0"
+ width="780"
+ name="panel_ls_input">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ top_pad="5"
+ layout="topleft"
+ left="6"
+ name="search_text"
+ top="12"
+ height="16"
+ width="156">
+ Enter search terms:
+ </text>
+ <search_combo_box
+ layout="topleft"
+ follows="left|top|right"
+ height="23"
+ left_delta="0"
+ name="classifieds_edit"
+ top="29"
+ width="651" />
+ <combo_box
+ follows="right|top"
+ layout="topleft"
+ height="23"
+ allow_text_entry="false"
+ top_delta="0"
+ left_pad="2"
+ name="classifieds_category"
+ width="122">
+ <combo_box.commit_callback
+ function="CommitSearch" />
+ </combo_box>
+ <check_box
+ control_name="ShowPGClassifieds"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left="660"
+ name="pg_all"
+ top="12"
+ width="15">
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_PG_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_general"
+ top_delta="-1"
+ width="18"/>
+ <check_box
+ control_name="ShowMatureClassifieds"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left_pad="2"
+ name="mature_all"
+ top_delta="1"
+ width="15">
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_M_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_moderate"
+ top_delta="-1"
+ width="18"/>
+ <check_box
+ control_name="ShowAdultClassifieds"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left_pad="2"
+ name="adult_all"
+ top_delta="1"
+ width="15">
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_R_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_adult"
+ top_delta="-1"
+ width="18"/>
+ </panel>
+ <!-- Search Pane -->
+ <panel
+ border="true"
+ follows="all"
+ height="510"
+ layout="topleft"
+ left="1"
+ width="410"
+ top_pad="1"
+ name="panel_ls_scrolllist">
+ <scroll_list
+ draw_heading="true"
+ follows="all"
+ height="485"
+ layout="topleft"
+ left="0"
+ name="search_results_classifieds"
+ top="0"
+ width="410">
+ <columns
+ label=""
+ name="icon"
+ width="20" />
+ <columns
+ label="Name"
+ name="classified_name"
+ relwidth="0.70" />
+ <columns
+ label="Listing Price"
+ name="price"
+ relwidth="0.3"/>
+ </scroll_list>
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Back"
+ name="classifieds_back"
+ top_pad="2"
+ left="3"
+ width="100" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Next"
+ name="classifieds_next"
+ width="100"
+ left_pad="1" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_fs_search_legacy_events.xml b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_events.xml
new file mode 100644
index 0000000000..57cb4990e4
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_events.xml
@@ -0,0 +1,258 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ follows="all"
+ height="566"
+ layout="topleft"
+ left="1"
+ width="780"
+ label="Events"
+ name="panel_ls_events">
+ <panel
+ border="false"
+ follows="top|left|right"
+ height="53"
+ layout="topleft"
+ left="0"
+ width="780"
+ name="panel_ls_input">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ top_pad="5"
+ layout="topleft"
+ left="6"
+ name="search_text"
+ top="12"
+ height="16"
+ width="156">
+ Enter search terms:
+ </text>
+ <radio_group
+ left_pad="20"
+ height="16"
+ width="300"
+ layout="topleft"
+ name="events_search_mode">
+ <radio_item
+ height="16"
+ label="Ongoing and Upcoming"
+ layout="topleft"
+ name="current"
+ value="current"
+ top_pad="0"
+ width="120" />
+ <radio_item
+ height="16"
+ label="By Date"
+ layout="topleft"
+ name="date"
+ value="date"
+ left_pad="70"
+ width="120" />
+ <radio_group.commit_callback
+ function="CommitSearch" />
+ </radio_group>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ top_delta="0"
+ layout="topleft"
+ left_pad="5"
+ name="events_date"
+ font.style="BOLD"
+ height="16"
+ width="80">
+ 4/20
+ </text>
+ <search_combo_box
+ layout="topleft"
+ follows="left|top|right"
+ height="23"
+ left="6"
+ name="events_edit"
+ top="29"
+ width="651" />
+ <combo_box
+ follows="right|top"
+ layout="topleft"
+ height="23"
+ top_delta="0"
+ left_pad="2"
+ name="events_category"
+ width="122">
+ <combo_box.item label="Any Category" name="any" value="0" />
+ <combo_box.item label="" value="filter_separator" enabled="false" />
+ <combo_box.item label="Discussion" name="discussion" value="18" />
+ <combo_box.item label="Sports" name="sports" value="19" />
+ <combo_box.item label="Live DJ" name="dj" value="30" />
+ <combo_box.item label="Live Music" name="music" value="20" />
+ <!-- <combo_box.item label="???" name="mystery_category" value="21" /> -->
+ <combo_box.item label="Commercial" name="commercial" value="22" />
+ <combo_box.item label="Nightlife/Entertainment" name="nightlife" value="23" />
+ <combo_box.item label="Games/Contests" name="games" value="24" />
+ <combo_box.item label="Pageants" name="pageants" value="25" />
+ <combo_box.item label="Education" name="education" value="26" />
+ <combo_box.item label="Arts and Culture" name="arts" value="27" />
+ <combo_box.item label="Charity/Support Groups" name="charity" value="28" />
+ <combo_box.item label="Miscellaneous" name="misc" value="29" />
+ <combo_box.commit_callback
+ function="CommitSearch" />
+ </combo_box>
+ <check_box
+ control_name="ShowPGEvents"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left="660"
+ name="pg_all"
+ top="12"
+ width="15" >
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_PG_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_general"
+ top_delta="-1"
+ width="18"/>
+ <check_box
+ control_name="ShowMatureEvents"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left_pad="2"
+ name="mature_all"
+ top_delta="1"
+ width="15">
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_M_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_moderate"
+ top_delta="-1"
+ width="18"/>
+ <check_box
+ control_name="ShowAdultEvents"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left_pad="2"
+ name="adult_all"
+ top_delta="1"
+ width="15">
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_R_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_adult"
+ top_delta="-1"
+ width="18"/>
+ </panel>
+ <!-- Search Pane -->
+ <panel
+ border="true"
+ follows="all"
+ height="510"
+ layout="topleft"
+ left="1"
+ width="410"
+ top_pad="1"
+ name="panel_ls_scrolllist">
+ <scroll_list
+ draw_heading="true"
+ follows="all"
+ height="485"
+ layout="topleft"
+ left="0"
+ name="search_results_events"
+ sort_ascending="true"
+ sort_column="3"
+ top="0"
+ width="410">
+ <columns
+ label=""
+ name="icon"
+ width="20" />
+ <columns
+ label="Event Name"
+ name="name"
+ relwidth="0.72" />
+ <columns
+ label="Date/Time"
+ name="date"
+ sort_column="time"
+ relwidth="0.28" />
+ <columns
+ label="Time"
+ name="time"
+ width="0"/>
+ </scroll_list>
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Yesterday"
+ name="events_yesterday"
+ top_pad="2"
+ left="3"
+ width="100" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Today"
+ name="events_today"
+ width="100"
+ left_pad="1" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Tomorrow"
+ name="events_tomorrow"
+ width="100"
+ left_pad="1" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ image_bottom_pad="2"
+ image_overlay="Arrow_Left_Off"
+ image_overlay_alignment="left"
+ label="Back"
+ name="events_back"
+ width="25"
+ left_pad="1" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ image_bottom_pad="2"
+ image_overlay="Arrow_Right_Off"
+ image_overlay_alignment="left"
+ label="Next"
+ name="events_next"
+ width="25"
+ left_pad="1" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_fs_search_legacy_groups.xml b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_groups.xml
new file mode 100644
index 0000000000..90001952f7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_groups.xml
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ follows="all"
+ height="566"
+ layout="topleft"
+ left="1"
+ width="780"
+ label="Groups"
+ name="panel_ls_groups">
+ <panel
+ border="false"
+ follows="top|left|right"
+ height="53"
+ layout="topleft"
+ left="0"
+ width="780"
+ name="panel_ls_input">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ top_pad="5"
+ layout="topleft"
+ left="6"
+ name="search_text"
+ top="12"
+ height="16"
+ width="156">
+ Enter search terms:
+ </text>
+ <search_combo_box
+ layout="topleft"
+ follows="left|top|right"
+ height="23"
+ left_delta="0"
+ name="groups_edit"
+ top="29"
+ width="770">
+ </search_combo_box>
+ <check_box
+ control_name="ShowPGGroups"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left="660"
+ name="pg_all"
+ top="12"
+ width="15"
+ visible="false"/>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_PG_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_general"
+ top_delta="-1"
+ width="18"
+ visible="false"/>
+ <check_box
+ control_name="ShowMatureGroups"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left_pad="2"
+ name="mature_all"
+ top_delta="1"
+ width="15"
+ visible="false"/>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_M_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_moderate"
+ top_delta="-1"
+ width="18"
+ visible="false"/>
+ <check_box
+ control_name="ShowAdultGroups"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left_pad="2"
+ name="adult_all"
+ top_delta="1"
+ width="15"
+ visible="false"/>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_R_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_adult"
+ top_delta="-1"
+ width="18"
+ visible="false"/>
+ </panel>
+ <!-- Search Pane -->
+ <panel
+ border="true"
+ follows="all"
+ height="510"
+ layout="topleft"
+ left="1"
+ width="410"
+ top_pad="1"
+ name="panel_ls_scrolllist">
+ <scroll_list
+ draw_heading="true"
+ follows="all"
+ height="485"
+ layout="topleft"
+ left="0"
+ name="search_results_groups"
+ top="0"
+ width="410">
+ <columns
+ label=""
+ name="icon"
+ width="20" />
+ <columns
+ label="Group Name"
+ name="group_name"
+ relwidth="0.72" />
+ <columns
+ label="Members"
+ name="members"
+ relwidth="0.25" />
+ <columns
+ label="Score"
+ name="score"
+ width="0" />
+ </scroll_list>
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Back"
+ name="groups_back"
+ top_pad="2"
+ left="3"
+ width="100" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Next"
+ name="groups_next"
+ width="100"
+ left_pad="1" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_fs_search_legacy_land.xml b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_land.xml
new file mode 100644
index 0000000000..bb03a1e999
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_land.xml
@@ -0,0 +1,281 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ follows="all"
+ height="566"
+ layout="topleft"
+ left="1"
+ width="780"
+ label="Land Sales"
+ name="panel_ls_land">
+ <panel
+ border="false"
+ follows="top|left|right"
+ height="53"
+ layout="topleft"
+ left="0"
+ width="780"
+ name="panel_ls_input">
+ <check_box
+ control_name="ShowPGLand"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left="660"
+ name="pg_all"
+ top="12"
+ width="15">
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_PG_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_general"
+ top_delta="-1"
+ width="18"/>
+ <check_box
+ control_name="ShowMatureLand"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left_pad="2"
+ name="mature_all"
+ top_delta="1"
+ width="15">
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_M_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_moderate"
+ top_delta="-1"
+ width="18"/>
+ <check_box
+ control_name="ShowAdultLand"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left_pad="2"
+ name="adult_all"
+ top_delta="1"
+ width="15">
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_R_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_adult"
+ top_delta="-1"
+ width="18"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left="6"
+ name="search_text"
+ top="12"
+ height="16"
+ width="256">
+ Enter search terms:
+ </text>
+ <combo_box
+ control_name="FindLandType"
+ follows="left|top"
+ layout="topleft"
+ height="23"
+ allow_text_entry="false"
+ top_pad="2"
+ left="6"
+ name="land_category"
+ width="122">
+ <combo_box.item label="All Categories" name="All" value="All"/>
+ <combo_box.item label="Auction" name="Auction" value="Auction"/>
+ <combo_box.item label="Mainland Sales" name="Mainland" value="Mainland"/>
+ <combo_box.item label="Estate Sales" name="Estate" value="Estate"/>
+ <combo_box.commit_callback
+ function="CommitSearch" />
+ </combo_box>
+ <check_box
+ control_name="FindLandPrice"
+ follows="left|top"
+ height="16"
+ label="Price &lt;"
+ layout="topleft"
+ left_pad="3"
+ name="price_check"
+ top_delta="3"
+ width="40" >
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <line_editor
+ enabled_control="FindLandPrice"
+ bevel_style="none"
+ border_style="line"
+ border.border_thickness="0"
+ commit_on_focus_lost="false"
+ follows="left|top"
+ height="18"
+ left_pad="20"
+ name="edit_price"
+ top_delta="-1"
+ width="40" >
+ <line_editor.commit_callback
+ function="CommitSearch" />
+ </line_editor>
+ <check_box
+ control_name="FindLandArea"
+ follows="left|top"
+ height="16"
+ label="Area &gt;"
+ layout="topleft"
+ left_pad="3"
+ name="area_check"
+ top_delta="1"
+ width="40" >
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <line_editor
+ enabled_control="FindLandArea"
+ bevel_style="none"
+ border_style="line"
+ border.border_thickness="0"
+ commit_on_focus_lost="false"
+ follows="left|top"
+ height="18"
+ left_pad="20"
+ name="edit_area"
+ top_delta="-1"
+ width="40" >
+ <line_editor.commit_callback
+ function="CommitSearch" />
+ </line_editor>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left="365"
+ name="sort_text"
+ top="12"
+ height="16"
+ width="98">
+ Sort results by:
+ </text>
+ <check_box
+ follows="left|top"
+ height="16"
+ label="Ascending"
+ layout="topleft"
+ left_pad="3"
+ name="ascending_check"
+ width="100" >
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <combo_box
+ follows="left|top"
+ layout="topleft"
+ height="23"
+ allow_text_entry="false"
+ left_delta="-102"
+ top_pad="1"
+ name="land_sort_combo"
+ width="118">
+ <combo_box.item label="Name" name="Name_item" value="Name"/>
+ <combo_box.item label="Price" name="Price_item" value="Price"/>
+ <combo_box.item label="Price per meter" name="PPM_item" value="PPM"/>
+ <combo_box.item label="Area" name="Area_item" value="Area"/>
+ <combo_box.commit_callback
+ function="CommitSearch" />
+ </combo_box>
+ <button
+ follows="top|right"
+ height="23"
+ label="Search"
+ layout="topleft"
+ left="678"
+ top_delta="0"
+ name="land_find"
+ width="100" />
+ </panel>
+ <!-- Search Pane -->
+ <panel
+ border="true"
+ follows="all"
+ height="510"
+ layout="topleft"
+ left="1"
+ width="410"
+ top_pad="1"
+ name="panel_ls_scrolllist">
+ <scroll_list
+ draw_heading="true"
+ follows="all"
+ height="485"
+ layout="topleft"
+ left="0"
+ name="search_results_land"
+ top="0"
+ width="410">
+ <columns
+ label=""
+ name="icon"
+ width="20" />
+ <columns
+ label="Name"
+ name="land_name"
+ relwidth="0.45" />
+ <columns
+ label="Price"
+ name="price"
+ relwidth="0.1" />
+ <columns
+ label="Area"
+ name="area"
+ relwidth="0.1" />
+ <columns
+ label="L$/m"
+ name="ppm"
+ relwidth="0.1" />
+ <columns
+ label="Type"
+ name="land_type"
+ relwidth="0.2" />
+ </scroll_list>
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Back"
+ name="land_back"
+ top_pad="2"
+ left="3"
+ width="100" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Next"
+ name="land_next"
+ width="100"
+ left_pad="1" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_fs_search_legacy_people.xml b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_people.xml
new file mode 100644
index 0000000000..28df02a7e3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_people.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ follows="all"
+ height="566"
+ layout="topleft"
+ left="1"
+ width="780"
+ label="People"
+ name="panel_ls_people">
+ <panel
+ border="false"
+ follows="top|left|right"
+ height="53"
+ layout="topleft"
+ left="0"
+ width="780"
+ name="panel_ls_input">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ top_pad="5"
+ layout="topleft"
+ left="6"
+ name="search_text"
+ top="12"
+ height="16"
+ width="156">
+ Enter search terms:
+ </text>
+ <search_combo_box
+ layout="topleft"
+ follows="left|top|right"
+ height="23"
+ left_delta="0"
+ name="people_edit"
+ top="29"
+ width="770">
+ </search_combo_box>
+ </panel>
+ <!-- Search Pane -->
+ <panel
+ border="true"
+ follows="all"
+ height="510"
+ layout="topleft"
+ left="1"
+ width="410"
+ top_pad="1"
+ name="panel_ls_scrolllist">
+ <scroll_list
+ content_type="Agents"
+ draw_heading="true"
+ follows="all"
+ height="485"
+ layout="topleft"
+ left="0"
+ name="search_results_people"
+ top="0"
+ width="410">
+ <columns
+ label=""
+ name="icon"
+ width="20" />
+ <columns
+ label="Name"
+ name="username"
+ relwidth="1" />
+ </scroll_list>
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Back"
+ name="people_back"
+ top_pad="2"
+ left="3"
+ width="100" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Next"
+ name="people_next"
+ width="100"
+ left_pad="1" />
+ </panel>
+</panel> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_fs_search_legacy_places.xml b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_places.xml
new file mode 100644
index 0000000000..09c142b8fc
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_places.xml
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ follows="all"
+ height="566"
+ layout="topleft"
+ left="1"
+ width="780"
+ label="Places"
+ name="panel_ls_places">
+ <panel
+ border="false"
+ follows="top|left|right"
+ height="53"
+ layout="topleft"
+ left="0"
+ width="780"
+ name="panel_ls_input">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ top_pad="5"
+ layout="topleft"
+ left="6"
+ name="search_text"
+ top="12"
+ height="16"
+ width="156">
+ Enter search terms:
+ </text>
+ <search_combo_box
+ layout="topleft"
+ follows="left|top|right"
+ height="23"
+ left_delta="0"
+ name="places_edit"
+ top="29"
+ width="651" />
+ <combo_box
+ follows="right|top"
+ layout="topleft"
+ height="23"
+ allow_text_entry="false"
+ top_delta="0"
+ left_pad="2"
+ name="places_category"
+ width="122">
+ <combo_box.commit_callback
+ function="CommitSearch" />
+ </combo_box>
+ <check_box
+ control_name="ShowPGSims"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left="660"
+ name="pg_all"
+ top="12"
+ width="15">
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_PG_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_general"
+ top_delta="-1"
+ width="18"/>
+ <check_box
+ control_name="ShowMatureSims"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left_pad="2"
+ name="mature_all"
+ top_delta="1"
+ width="15">
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_M_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_moderate"
+ top_delta="-1"
+ width="18"/>
+ <check_box
+ control_name="ShowAdultSims"
+ follows="right|top"
+ height="16"
+ label=""
+ layout="topleft"
+ left_pad="2"
+ name="adult_all"
+ top_delta="1"
+ width="15">
+ <check_box.commit_callback
+ function="CommitSearch" />
+ </check_box>
+ <icon
+ follows="right|top"
+ height="16"
+ image_name="Parcel_R_Dark"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_adult"
+ top_delta="-1"
+ width="18"/>
+ </panel>
+ <!-- Search Pane -->
+ <panel
+ border="true"
+ follows="all"
+ height="510"
+ layout="topleft"
+ left="1"
+ width="410"
+ top_pad="1"
+ name="panel_ls_scrolllist">
+ <scroll_list
+ draw_heading="true"
+ follows="all"
+ height="485"
+ layout="topleft"
+ left="0"
+ name="search_results_places"
+ top="0"
+ width="410">
+ <columns
+ label=""
+ name="icon"
+ width="20" />
+ <columns
+ label="Name"
+ name="place_name"
+ relwidth="0.81" />
+ <columns
+ label="Traffic"
+ name="dwell"
+ relwidth="0.16" />
+ </scroll_list>
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Back"
+ name="places_back"
+ top_pad="2"
+ left="3"
+ width="100" />
+ <button
+ layout="topleft"
+ follows="left|bottom"
+ height="23"
+ label="Next"
+ name="places_next"
+ width="100"
+ left_pad="1" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_fs_search_legacy_web.xml b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_web.xml
new file mode 100644
index 0000000000..382a5e8945
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_fs_search_legacy_web.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+border="false"
+follows="all"
+height="566"
+layout="topleft"
+left="1"
+width="780"
+label="Websearch"
+name="panel_ls_web">
+ <web_browser
+ top="5"
+ bottom="-1"
+ left="5"
+ right="-5"
+ layout="topleft"
+ follows="all"
+ name="search_browser"
+ trusted_content="true"
+ start_url="about:blank" />
+</panel> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 1bc8ddc626..daa49eaa2c 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -71,7 +71,7 @@ Voice Server Version: [VOICE_VERSION]
<string name="LocalTime">[month, datetime, local] [day, datetime, local] [year, datetime, local] [hour, datetime, local]:[min, datetime, local]:[second,datetime, local]</string>
<string name="ErrorFetchingServerReleaseNotesURL">Error fetching server release notes URL.</string>
<string name="BuildConfiguration">Build Configuration</string>
-
+
<!-- progress -->
<string name="ProgressRestoring">Restoring...</string>
<string name="ProgressChangingResolution">Changing resolution...</string>
@@ -114,10 +114,10 @@ Voice Server Version: [VOICE_VERSION]
<string name="LoginFailedHeader">Login failed.</string>
<string name="Quit">Quit</string>
<string name="create_account_url">http://join.secondlife.com/?sourceid=[sourceid]</string>
-
+
<string name="AgniGridLabel">Second Life Main Grid (Agni)</string>
<string name="AditiGridLabel">Second Life Beta Test Grid (Aditi)</string>
-
+
<string name="ViewerDownloadURL">http://secondlife.com/download</string>
<string name="LoginFailedViewerNotPermitted">
The viewer you are using can no longer access Second Life. Please visit the following page to download a new viewer:
@@ -209,7 +209,7 @@ If you feel this is an error, please contact support@secondlife.com</string>
<string name="YouHaveBeenDisconnected">You have been disconnected from the region you were in.</string>
<string name="SentToInvalidRegion">You were sent to an invalid region.</string>
<string name="TestingDisconnect">Testing viewer disconnect</string>
-
+
<!-- SLShare: User Friendly Filter Names Translation -->
<string name="BlackAndWhite">Black &amp; White</string>
<string name="Colors1970">1970&apos;s Colors</string>
@@ -222,7 +222,7 @@ If you feel this is an error, please contact support@secondlife.com</string>
<string name="LensFlare">Lens Flare</string>
<string name="Miniature">Miniature</string>
<string name="Toycamera">Toy Camera</string>
-
+
<!-- Tooltip -->
<string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar -->
<string name="TooltipNoName">(no name)</string> <!-- No name on an object -->
@@ -259,10 +259,10 @@ If you feel this is an error, please contact support@secondlife.com</string>
<string name="TooltipOutboxMixedStock">All items in a stock folder must have the same type and permission</string>
<string name="TooltipOutfitNotInInventory">You can only put items or outfits from your personal inventory into "My outfits"</string>
<string name="TooltipCantCreateOutfit">One or more items can't be used inside "My outfits"</string>
-
+
<string name="TooltipDragOntoOwnChild">You can't move a folder into its child</string>
<string name="TooltipDragOntoSelf">You can't move a folder into itself</string>
-
+
<!-- tooltips for Urls -->
<string name="TooltipHttpUrl">Click to view this web page</string>
<string name="TooltipSLURL">Click to view this location's information</string>
@@ -370,7 +370,7 @@ are allowed.
<string name="AssetUploadServerDifficulties">The server is experiencing unexpected difficulties.</string>
<string name="AssetUploadServerUnavaliable">Service not available or upload timeout was reached.</string>
<string name="AssetUploadRequestInvalid">
-Error in upload request. Please visit
+Error in upload request. Please visit
http://secondlife.com/support for help fixing this problem.
</string>
@@ -534,7 +534,7 @@ http://secondlife.com/support for help fixing this problem.
<string name="ChangeYourDefaultAnimations">Change your default animations</string>
<string name="ForceSitAvatar">Force your avatar to sit</string>
<string name="ChangeEnvSettings">Change your environment settings</string>
-
+
<string name="NotConnected">Not Connected</string>
<string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name -->
<string name="JoinAnExperience"/><!-- intentionally blank -->
@@ -2320,7 +2320,7 @@ For AI Character: Get the closest navigable point to the point provided.
<!-- inventory -->
<string name="InventoryNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search].</string>
- <string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string>
+ <string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string>
<string name="PlacesNoMatchingItems">To add a place to your landmarks, click the star to the right of the location name.</string>
<string name="FavoritesNoMatchingItems">To add a place to your favorites, click the star to the right of the location name, then save the landmark to "Favorites bar".</string>
<string name="MarketplaceNoListing">You have no listings yet.</string>
@@ -2503,7 +2503,7 @@ If you continue to receive this message, please contact Second Life support for
<string name="InvFolder Materials">Materials</string>
<!-- are used for Friends and Friends/All folders in Inventory "Calling cards" folder. See EXT-694-->
- <string name="InvFolder Friends">Friends</string>
+ <string name="InvFolder Friends">Friends</string>
<string name="InvFolder All">All</string>
<string name="no_attachments">No attachments worn</string>
@@ -2672,7 +2672,7 @@ If you continue to receive this message, please contact Second Life support for
<string name="UploadFailed">File upload failed: </string>
<string name="ObjectOutOfRange">Script (object out of range)</string>
<string name="ScriptWasDeleted">Script (deleted from inventory)</string>
-
+
<!-- god tools -->
<string name="GodToolsObjectOwnedBy">Object [OBJECT] owned by [OWNER]</string>
@@ -2942,12 +2942,14 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .anim
<string name="Linden Location">Linden Location</string>
<string name="Adult">Adult</string>
<string name="Arts&amp;Culture">Arts &amp; Culture</string>
+ <string name="Arts and Culture">Arts &amp; Culture</string>
<string name="Business">Business</string>
<string name="Educational">Educational</string>
<string name="Gaming">Gaming</string>
<string name="Hangout">Hangout</string>
<string name="Newcomer Friendly">Newcomer Friendly</string>
<string name="Parks&amp;Nature">Parks &amp; Nature</string>
+ <string name="Parks and Nature">Parks &amp; Nature</string>
<string name="Residential">Residential</string>
<!--<string name="Shopping">Shopping</string> -->
<string name="Stage">Stage</string>
@@ -3848,7 +3850,7 @@ Please reinstall viewer from https://secondlife.com/support/downloads/ and cont
<string name="uploading_costs">Uploading costs L$ [AMOUNT]</string>
<string name="this_costs">This costs L$ [AMOUNT]</string>
-
+
<string name="buying_selected_land">This land costs</string>
<string name="this_object_costs">This item costs</string>
<string name="giving">You want to give</string>
@@ -3929,7 +3931,7 @@ Abuse Report</string>
<string name="New Daycycle">New Daycycle</string>
<string name="New Water">New Water</string>
<string name="New Sky">New Sky</string>
-
+
<string name="/bow">/bow</string>
<string name="/clap">/clap</string>
@@ -4011,7 +4013,7 @@ Please check http://status.secondlifegrid.net to see if there is a known problem
<string name="Accounting">Accounting</string>
<string name="Notices">Notices</string>
<string name="Chat">Chat</string>
-
+
<!-- SL Membership -->
<string name="BaseMembership">Base</string>
<string name="PremiumMembership">Premium</string>
@@ -4177,7 +4179,7 @@ Try enclosing path to the editor with double quotes.
<!-- commands -->
- <string
+ <string
name="Command_360_Capture_Label">360 snapshot</string>
<string name="Command_AboutLand_Label">About land</string>
<string name="Command_Appearance_Label">Outfits</string>
@@ -4210,7 +4212,7 @@ name="Command_360_Capture_Label">360 snapshot</string>
<string name="Command_View_Label">Camera controls</string>
<string name="Command_Voice_Label">Voice settings</string>
- <string
+ <string
name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<string name="Command_AboutLand_Tooltip">Information about the land you're visiting</string>
<string name="Command_Appearance_Tooltip">Change your avatar</string>
@@ -4275,7 +4277,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<!-- Spell check settings floater -->
<string name="UserDictionary">[User]</string>
-
+
<!-- Experience Tools strings -->
<string name="experience_tools_experience">Experience</string>
<string name="ExperienceNameNull">(no experience)</string>
@@ -4311,7 +4313,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<!-- PBR Materials -->
<string name="Material Texture Name Header">Textures present this material: </string>
-
+
<!-- Conversation log messages -->
<string name="logging_calls_disabled_log_empty">
Conversations are not being logged. To begin keeping a log, choose "Save: Log only" or "Save: Log and transcripts" under Preferences > Chat.
@@ -4334,7 +4336,7 @@ name="Command_360_Capture_Tooltip">Capture a 360 equirectangular image</string>
<string name="Default">Default</string>
<string name="none_paren_cap">(None)</string>
<string name="no_limit">No limit</string>
-
+
<string name="Mav_Details_MAV_FOUND_DEGENERATE_TRIANGLES">
The physics shape contains triangles which are too small. Try simplifying the physics model.
</string>
@@ -4374,4 +4376,20 @@ and report the problem.
[https://community.secondlife.com/knowledgebase/english/error-messages-r520/#Section__3 Knowledge Base]
</string>
+ <!-- megapahit strings -->
+ <string name="not_found">&apos;[TEXT]&apos; not found</string>
+ <string name="no_results">No results</string>
+ <string name="searching">Searching...</string>
+ <string name="all_categories">All Categories</string>
+ <string name="search_banned">Some terms in your search query were excluded due to content restrictions as clarified in the Community Standards.</string>
+ <string name="search_short">Your search terms were too short so no search was performed.</string>
+ <string name="search_disabled">Legacy Search has been disabled in this region.</string>
+ <string name="NotifyIncomingMessage">Incoming message from [NAME]...</string>
+ <string name="NearbyChatTitleChannel">Nearby chat (on channel [CHANNEL])</string>
+ <string name="AvatarTyping">Typing</string>
+ <string name="UnknownAvatar">Unknown Avatar</string>
+ <string name="NotAvailableOnPlatform">Not available on this platform</string>
+ <string name="NowPlaying">Now Playing</string>
+ <string name="GridInfoTitle">GRID INFO</string>
+
</strings>