summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Nikolenko <maximnproductengine@lindenlab.com>2025-10-31 13:52:19 +0200
committerGitHub <noreply@github.com>2025-10-31 13:52:19 +0200
commite2a741dfd2db44df1de5ad3b23de2a9aba28db2b (patch)
tree588037645c4c75eddfcf47fe3ed3ec7030de5ca3
parentbd8fe9d63d8891501ee66a570724f17e4abcacfa (diff)
parent84b2861b9e99c5099ee82a12a566119b3de9417e (diff)
Merge pull request #4900 from secondlife/maxim/2025.08-legacy-search
Restore Legacy Search
-rw-r--r--indra/newview/CMakeLists.txt20
-rw-r--r--indra/newview/app_settings/settings.xml87
-rw-r--r--indra/newview/lleventnotifier.cpp71
-rw-r--r--indra/newview/lleventnotifier.h25
-rw-r--r--indra/newview/llfloaterdirectory.cpp100
-rw-r--r--indra/newview/llfloaterdirectory.h81
-rw-r--r--indra/newview/llpanelclassified.cpp4
-rw-r--r--indra/newview/llpaneldirbrowser.cpp1169
-rw-r--r--indra/newview/llpaneldirbrowser.h167
-rw-r--r--indra/newview/llpaneldirclassified.cpp109
-rw-r--r--indra/newview/llpaneldirclassified.h55
-rw-r--r--indra/newview/llpaneldirevents.cpp248
-rw-r--r--indra/newview/llpaneldirevents.h61
-rw-r--r--indra/newview/llpaneldirgroups.cpp90
-rw-r--r--indra/newview/llpaneldirgroups.h45
-rw-r--r--indra/newview/llpaneldirland.cpp247
-rw-r--r--indra/newview/llpaneldirland.h53
-rw-r--r--indra/newview/llpaneldirpeople.cpp105
-rw-r--r--indra/newview/llpaneldirpeople.h48
-rw-r--r--indra/newview/llpaneldirplaces.cpp185
-rw-r--r--indra/newview/llpaneldirplaces.h51
-rw-r--r--indra/newview/llpaneldirweb.cpp148
-rw-r--r--indra/newview/llpaneldirweb.h63
-rw-r--r--indra/newview/llpaneleventinfo.cpp195
-rw-r--r--indra/newview/llpaneleventinfo.h76
-rw-r--r--indra/newview/llpanelgroup.cpp6
-rw-r--r--indra/newview/llpanelgroup.h1
-rw-r--r--indra/newview/llpanelplaces.cpp9
-rw-r--r--indra/newview/llpanelplaces.h2
-rw-r--r--indra/newview/llpanelprofile.cpp14
-rw-r--r--indra/newview/llpanelprofile.h3
-rw-r--r--indra/newview/llstartup.cpp8
-rw-r--r--indra/newview/llviewerfloaterreg.cpp8
-rw-r--r--indra/newview/skins/default/textures/icon_auction.tgabin0 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/icon_event.tgabin0 -> 1068 bytes
-rw-r--r--indra/newview/skins/default/textures/icon_event_adult.tgabin0 -> 648 bytes
-rw-r--r--indra/newview/skins/default/textures/icon_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/textures.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_directory.xml150
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_classified_info.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_dir_classified.xml215
-rw-r--r--indra/newview/skins/default/xui/en/panel_dir_events.xml300
-rw-r--r--indra/newview/skins/default/xui/en/panel_dir_groups.xml129
-rw-r--r--indra/newview/skins/default/xui/en/panel_dir_land.xml268
-rw-r--r--indra/newview/skins/default/xui/en/panel_dir_people.xml120
-rw-r--r--indra/newview/skins/default/xui/en/panel_dir_places.xml215
-rw-r--r--indra/newview/skins/default/xui/en/panel_dir_web.xml76
-rw-r--r--indra/newview/skins/default/xui/en/panel_event_info.xml212
50 files changed, 5227 insertions, 27 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 8869f4b1f6..d56ac36190 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -219,6 +219,7 @@ set(viewer_SOURCE_FILES
llfloatercreatelandmark.cpp
llfloaterdeleteprefpreset.cpp
llfloaterdestinations.cpp
+ llfloaterdirectory.cpp
llfloaterdisplayname.cpp
llfloatereditenvironmentbase.cpp
llfloatereditextdaycycle.cpp
@@ -441,11 +442,20 @@ set(viewer_SOURCE_FILES
llpanelblockedlist.cpp
llpanelclassified.cpp
llpanelcontents.cpp
+ llpaneldirbrowser.cpp
+ llpaneldirclassified.cpp
+ llpaneldirevents.cpp
+ llpaneldirgroups.cpp
+ llpaneldirland.cpp
+ llpaneldirpeople.cpp
+ llpaneldirplaces.cpp
+ llpaneldirweb.cpp
llpaneleditsky.cpp
llpaneleditwater.cpp
llpaneleditwearable.cpp
llpanelemojicomplete.cpp
llpanelenvironment.cpp
+ llpaneleventinfo.cpp
llpanelexperiencelisteditor.cpp
llpanelexperiencelog.cpp
llpanelexperiencepicker.cpp
@@ -894,6 +904,7 @@ set(viewer_HEADER_FILES
llfloatercreatelandmark.h
llfloaterdeleteprefpreset.h
llfloaterdestinations.h
+ llfloaterdirectory.h
llfloaterdisplayname.h
llfloatereditenvironmentbase.h
llfloatereditextdaycycle.h
@@ -1108,11 +1119,20 @@ set(viewer_HEADER_FILES
llpanelblockedlist.h
llpanelclassified.h
llpanelcontents.h
+ llpaneldirbrowser.h
+ llpaneldirclassified.h
+ llpaneldirevents.h
+ llpaneldirgroups.h
+ llpaneldirland.h
+ llpaneldirpeople.h
+ llpaneldirplaces.h
+ llpaneldirweb.h
llpaneleditsky.h
llpaneleditwater.h
llpaneleditwearable.h
llpanelemojicomplete.h
llpanelenvironment.h
+ llpaneleventinfo.h
llpanelexperiencelisteditor.h
llpanelexperiencelog.h
llpanelexperiencepicker.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index d6a1fbd124..aca9910253 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -11107,6 +11107,45 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>ShowPGClassifieds</key>
+ <map>
+ <key>Comment</key>
+ <string>Display results of find classifieds that are flagged as general</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>HideFromEditor</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>ShowMatureClassifieds</key>
+ <map>
+ <key>Comment</key>
+ <string>Display results of find classifieds that are flagged as moderate</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>HideFromEditor</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>ShowAdultClassifieds</key>
+ <map>
+ <key>Comment</key>
+ <string>Display results of find classifieds that are flagged as adult</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>HideFromEditor</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>ShowPGSims</key>
<map>
<key>Comment</key>
@@ -11146,6 +11185,54 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>ShowPGEvents</key>
+ <map>
+ <key>Comment</key>
+ <string>Display results of find events that are flagged as general</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>HideFromEditor</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>ShowMatureGroups</key>
+ <map>
+ <key>Comment</key>
+ <string>Include groups that are flagged as mature to Search results</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>HideFromEditor</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>FindLandArea</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables filtering of land search results by area</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
+ <key>FindLandPrice</key>
+ <map>
+ <key>Comment</key>
+ <string>Enables filtering of land search results by price</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>ShowNearClip</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp
index 25983f4add..66a922e288 100644
--- a/indra/newview/lleventnotifier.cpp
+++ b/indra/newview/lleventnotifier.cpp
@@ -166,6 +166,14 @@ bool LLEventNotifier::handleResponse(U32 eventId, const LLSD& notification, cons
return true;
}
+bool LLEventNotifier::add(LLEventInfo event)
+{
+ if (mEventInfoSignal(event))
+ return false;
+
+ return add(event.mID, event.mUnixTime, event.mTimeStr, event.mName);
+}
+
bool LLEventNotifier::add(U32 eventId, F64 eventEpoch, const std::string& eventDateStr, const std::string &eventName)
{
LLEventNotification *new_enp = new LLEventNotification(eventId, eventEpoch, eventDateStr, eventName);
@@ -198,20 +206,9 @@ void LLEventNotifier::add(U32 eventId)
//static
void LLEventNotifier::processEventInfoReply(LLMessageSystem *msg, void **)
{
- // extract the agent id
- LLUUID agent_id;
- U32 event_id;
- std::string event_name;
- std::string eventd_date;
- U32 event_time_utc;
-
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id );
- msg->getU32("EventData", "EventID", event_id);
- msg->getString("EventData", "Name", event_name);
- 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);
+ LLEventInfo info;
+ info.unpack(msg);
+ gEventNotifier.add(info);
}
@@ -296,6 +293,52 @@ void LLEventNotifier::serverPushRequest(U32 event_id, bool add)
gAgent.sendReliableMessage();
}
+void LLEventInfo::unpack(LLMessageSystem* msg)
+{
+ U32 event_id;
+ msg->getU32("EventData", "EventID", event_id);
+ mID = event_id;
+
+ msg->getString("EventData", "Name", mName);
+
+ msg->getString("EventData", "Category", mCategoryStr);
+
+ msg->getString("EventData", "Date", mTimeStr);
+
+ U32 duration;
+ msg->getU32("EventData", "Duration", duration);
+ mDuration = duration;
+
+ U32 date;
+ msg->getU32("EventData", "DateUTC", date);
+ mUnixTime = date;
+
+ msg->getString("EventData", "Desc", mDesc);
+
+ std::string buffer;
+ msg->getString("EventData", "Creator", buffer);
+ mRunByID = LLUUID(buffer);
+
+ U32 foo;
+ msg->getU32("EventData", "Cover", foo);
+
+ mHasCover = foo ? true : false;
+ if (mHasCover)
+ {
+ U32 cover;
+ msg->getU32("EventData", "Amount", cover);
+ mCover = cover;
+ }
+
+ msg->getString("EventData", "SimName", mSimName);
+
+ msg->getVector3d("EventData", "GlobalPos", mPosGlobal);
+
+ // Mature content
+ U32 event_flags;
+ msg->getU32("EventData", "EventFlags", event_flags);
+ mEventFlags = event_flags;
+}
LLEventNotification::LLEventNotification(U32 eventId, F64 eventEpoch, const std::string& eventDateStr, const std::string &eventName) :
mEventID(eventId),
diff --git a/indra/newview/lleventnotifier.h b/indra/newview/lleventnotifier.h
index 030c9abb87..2a9295129d 100644
--- a/indra/newview/lleventnotifier.h
+++ b/indra/newview/lleventnotifier.h
@@ -33,6 +33,24 @@
class LLEventNotification;
class LLMessageSystem;
+struct LLEventInfo
+{
+ void unpack(LLMessageSystem* msg);
+
+ std::string mName;
+ U32 mID;
+ std::string mDesc;
+ std::string mCategoryStr;
+ U32 mDuration;
+ std::string mTimeStr;
+ LLUUID mRunByID;
+ std::string mSimName;
+ LLVector3d mPosGlobal;
+ F64 mUnixTime; // seconds from 1970
+ BOOL mHasCover;
+ U32 mCover;
+ U32 mEventFlags;
+};
class LLEventNotifier
{
@@ -42,6 +60,7 @@ public:
void update(); // Notify the user of the event if it's coming up
bool add(U32 eventId, F64 eventEpoch, const std::string& eventDateStr, const std::string &eventName);
+ bool add(LLEventInfo event);
void add(U32 eventId);
@@ -56,9 +75,13 @@ public:
static void processEventInfoReply(LLMessageSystem *msg, void **);
+ typedef boost::signals2::signal<bool(LLEventInfo event)> info_received_signal_t;
+ boost::signals2::connection setEventInfoCallback(const info_received_signal_t::slot_type& cb) { return mEventInfoSignal.connect(cb); };
+
protected:
en_map mEventNotifications;
- LLFrameTimer mNotificationTimer;
+ LLFrameTimer mNotificationTimer;
+ info_received_signal_t mEventInfoSignal;
};
diff --git a/indra/newview/llfloaterdirectory.cpp b/indra/newview/llfloaterdirectory.cpp
new file mode 100644
index 0000000000..e062ca7ac6
--- /dev/null
+++ b/indra/newview/llfloaterdirectory.cpp
@@ -0,0 +1,100 @@
+/**
+ * @file llfloaterdirectory.cpp
+ * @brief The legacy "Search" floater
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llfloaterdirectory.h"
+
+#include "llpaneldirevents.h"
+#include "llpaneleventinfo.h"
+#include "llpaneldirland.h"
+#include "llpaneldirpeople.h"
+#include "llpaneldirgroups.h"
+#include "llpaneldirplaces.h"
+#include "llpaneldirclassified.h"
+#include "llpaneldirweb.h"
+#include "llscrollbar.h"
+#include "llviewercontrol.h"
+#include "llpanelavatar.h"
+#include "llpanelclassified.h"
+#include "llpanelgroup.h"
+#include "llpanelplaces.h"
+#include "llpanelprofile.h"
+
+LLFloaterDirectory::LLFloaterDirectory(const std::string& name)
+: LLFloater(name),
+ mPanelAvatarp(nullptr),
+ mPanelGroupp(nullptr),
+ mPanelPlacep(nullptr),
+ mPanelClassifiedp(nullptr),
+ mPanelEventp(nullptr)
+{
+}
+
+LLFloaterDirectory::~LLFloaterDirectory()
+{
+}
+
+bool LLFloaterDirectory::postBuild()
+{
+ const std::vector<std::string> panel_names = {
+ "panel_dir_classified",
+ "panel_dir_events",
+ "panel_dir_places",
+ "panel_dir_land",
+ "panel_dir_people",
+ "panel_dir_groups" };
+
+ for (const std::string& panel_name : panel_names)
+ {
+ if (LLPanelDirBrowser* panel_tab = findChild<LLPanelDirBrowser>(panel_name))
+ {
+ panel_tab->setFloaterDirectory(this);
+ }
+ }
+ findChild<LLPanelDirWeb>("panel_dir_web")->setFloaterDirectory(this);
+
+ mPanelAvatarp = findChild<LLPanelProfileSecondLife>("panel_profile_secondlife");
+ mPanelAvatarp->setAllowEdit(false);
+ mPanelGroupp = findChild<LLPanelGroup>("panel_group_info_sidetray");
+ mPanelGroupp->hideBackBtn();
+ mPanelPlacep = findChild<LLPanelPlaces>("panel_places");
+ mPanelPlacep->hideBackBtn();
+ mPanelClassifiedp = findChild<LLPanelClassifiedInfo>("panel_classified_info");
+ mPanelClassifiedp->setBackgroundVisible(false);
+ mPanelEventp = findChild<LLPanelEventInfo>("panel_event_info");
+
+ return true;
+}
+
+void LLFloaterDirectory::hideAllDetailPanels()
+{
+ if (mPanelAvatarp) mPanelAvatarp->setVisible(false);
+ if (mPanelGroupp) mPanelGroupp->setVisible(false);
+ if (mPanelPlacep) mPanelPlacep->setVisible(false);
+ if (mPanelClassifiedp) mPanelClassifiedp->setVisible(false);
+ if (mPanelEventp) mPanelEventp->setVisible(false);
+}
diff --git a/indra/newview/llfloaterdirectory.h b/indra/newview/llfloaterdirectory.h
new file mode 100644
index 0000000000..de788443be
--- /dev/null
+++ b/indra/newview/llfloaterdirectory.h
@@ -0,0 +1,81 @@
+/**
+ * @file llfloaterdirectory.h
+ * @brief The legacy "Search" floater
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERDIRECTORY_H
+#define LL_LLFLOATERDIRECTORY_H
+
+#include "llfloater.h"
+#include "lltabcontainer.h"
+
+#include "llpaneldirevents.h"
+#include "llpaneldirland.h"
+#include "llpaneldirpeople.h"
+#include "llpaneldirgroups.h"
+#include "llpaneldirplaces.h"
+#include "llpaneldirclassified.h"
+
+class LLDirectoryCore;
+class LLPanelDirBrowser;
+
+class LLPanelDirAdvanced;
+class LLPanelDirClassified;
+class LLPanelDirEvents;
+class LLPanelDirGroups;
+class LLPanelDirLand;
+class LLPanelDirPeople;
+class LLPanelDirPlaces;
+
+class LLPanelProfileSecondLife;
+class LLPanelEventInfo;
+class LLPanelGroup;
+class LLPanelPlaces;
+class LLPanelClassifiedInfo;
+
+// Floater to find people, places, things
+class LLFloaterDirectory : public LLFloater
+{
+public:
+ LLFloaterDirectory(const std::string& name);
+ /*virtual*/ ~LLFloaterDirectory();
+
+ void hideAllDetailPanels();
+
+ bool postBuild() override;
+
+public:
+ LLPanelProfileSecondLife* mPanelAvatarp;
+ LLPanelEventInfo* mPanelEventp;
+ LLPanelGroup* mPanelGroupp;
+ LLPanelPlaces* mPanelPlacep;
+ LLPanelClassifiedInfo* mPanelClassifiedp;
+
+private:
+ static LLFloaterDirectory *sInstance;
+};
+
+//extern BOOL gDisplayEventHack;
+
+#endif // LL_LLDIRECTORYFLOATER_H
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index 449a670de9..aefda39fb9 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -153,8 +153,10 @@ void LLPanelClassifiedInfo::reshape(S32 width, S32 height, bool called_from_pare
void LLPanelClassifiedInfo::onOpen(const LLSD& key)
{
+ bool from_search = key.has("from_search") ? key["from_search"].asBoolean() : false;
+
LLUUID avatar_id = key["classified_creator_id"];
- if(avatar_id.isNull())
+ if(avatar_id.isNull() && !from_search)
{
return;
}
diff --git a/indra/newview/llpaneldirbrowser.cpp b/indra/newview/llpaneldirbrowser.cpp
new file mode 100644
index 0000000000..8468520c11
--- /dev/null
+++ b/indra/newview/llpaneldirbrowser.cpp
@@ -0,0 +1,1169 @@
+/**
+ * @file llpaneldirbrowser.cpp
+ * @brief Base class for panels in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+// Base class for the various search panels/results browsers
+// in the Find floater. For example, Find > Popular Places
+// is derived from this.
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpaneldirbrowser.h"
+
+// linden library includes
+#include "lldir.h"
+#include "lleventflags.h"
+#include "llqueryflags.h"
+#include "message.h"
+
+// viewer project includes
+#include "llagent.h"
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "lllineeditor.h"
+#include "llnotificationsutil.h"
+#include "llpanelavatar.h"
+#include "llpanelgroup.h"
+#include "llpanelclassified.h"
+#include "llpaneldirevents.h"
+#include "llpaneldirland.h"
+#include "llproductinforequest.h"
+#include "llscrolllistctrl.h"
+#include "lltextbox.h"
+#include "lltrans.h"
+#include "llviewercontrol.h"
+#include "llfloaterdirectory.h"
+#include "llpanelprofile.h"
+#include "llpanelplaces.h"
+#include "llpaneleventinfo.h"
+
+
+std::map<LLUUID, LLPanelDirBrowser*> gDirBrowserInstances;
+
+LLPanelDirBrowser::LLPanelDirBrowser()
+: LLPanel(),
+ mSearchID(),
+ mWantSelectID(),
+ mCurrentSortColumn("name"),
+ mCurrentSortAscending(true),
+ mSearchStart(0),
+ mResultsPerPage(RESULTS_PER_PAGE_DEFAULT),
+ mResultsReceived(0),
+ mMinSearchChars(1),
+ mResultsContents(),
+ mHaveSearchResults(false),
+ mDidAutoSelect(true),
+ mLastResultTimer(),
+ mFloaterDirectory(nullptr)
+{
+}
+
+bool LLPanelDirBrowser::postBuild()
+{
+ childSetCommitCallback("results", onCommitList, this);
+
+ mPrevPageBtn = getChild<LLButton>("prev_btn");
+ mNextPageBtn = getChild<LLButton>("next_btn");
+
+ mPrevPageBtn->setClickedCallback([this](LLUICtrl*, const LLSD&){ prevPage(); });
+ mPrevPageBtn->setVisible(false);
+
+ mNextPageBtn->setClickedCallback([this](LLUICtrl*, const LLSD&) { nextPage(); });
+ mNextPageBtn->setVisible(false);
+
+ return true;
+}
+
+LLPanelDirBrowser::~LLPanelDirBrowser()
+{
+ // Children all cleaned up by default view destructor.
+ gDirBrowserInstances.erase(mSearchID);
+}
+
+// virtual
+void LLPanelDirBrowser::draw()
+{
+ // HACK: If the results panel has data, we want to select the first
+ // item. Unfortunately, we don't know when the find is actually done,
+ // so only do this if it's been some time since the last packet of
+ // results was received.
+ if (mLastResultTimer.getElapsedTimeF32() > 0.5)
+ {
+ if (!mDidAutoSelect &&
+ !childHasFocus("results"))
+ {
+ LLCtrlListInterface *list = childGetListInterface("results");
+ if (list)
+ {
+ if (list->getCanSelect())
+ {
+ list->selectFirstItem(); // select first item by default
+ childSetFocus("results", true);
+ }
+ // Request specific data from the server
+ onCommitList(NULL, this);
+ }
+ }
+ mDidAutoSelect = true;
+ }
+
+ LLPanel::draw();
+}
+
+
+// virtual
+void LLPanelDirBrowser::nextPage()
+{
+ mSearchStart += mResultsPerPage;
+ mPrevPageBtn->setVisible(true);
+
+ performQuery();
+}
+
+
+// virtual
+void LLPanelDirBrowser::prevPage()
+{
+ mSearchStart -= mResultsPerPage;
+ mPrevPageBtn->setVisible(mSearchStart > 0);
+
+ performQuery();
+}
+
+
+void LLPanelDirBrowser::resetSearchStart()
+{
+ mSearchStart = 0;
+ mNextPageBtn->setVisible(false);
+ mPrevPageBtn->setVisible(false);
+}
+
+// protected
+void LLPanelDirBrowser::updateResultCount()
+{
+ LLScrollListCtrl* list = getChild<LLScrollListCtrl>("results");
+
+ S32 result_count = list->getItemCount();
+ std::string result_text;
+
+ if (!mHaveSearchResults) result_count = 0;
+
+ if (mNextPageBtn && mNextPageBtn->getVisible())
+ {
+ // Item count be off by a few if bogus items sent from database
+ // Just use the number of results per page. JC
+ result_text = llformat(">%d found", mResultsPerPage);
+ }
+ else
+ {
+ result_text = llformat("%d found", result_count);
+ }
+
+ childSetValue("result_text", result_text);
+
+ if (result_count == 0)
+ {
+ // add none found response
+ if (list->getItemCount() == 0)
+ {
+ list->setCommentText(std::string("None found.")); // *TODO: Translate
+ list->operateOnAll(LLCtrlListInterface::OP_DESELECT);
+ }
+ }
+ else
+ {
+ childEnable("results");
+ }
+}
+
+// static
+std::string LLPanelDirBrowser::filterShortWords(const std::string source_string, int shortest_word_length, bool& was_filtered)
+{
+ // degenerate case
+ if ( source_string.length() < 1 )
+ return "";
+
+ std::stringstream codec( source_string );
+ std::string each_word;
+ std::vector< std::string > all_words;
+
+ while( codec >> each_word )
+ all_words.push_back( each_word );
+
+ std::ostringstream dest_string( "" );
+
+ was_filtered = false;
+
+ std::vector< std::string >::iterator iter = all_words.begin();
+ while( iter != all_words.end() )
+ {
+ if ( (int)(*iter).length() >= shortest_word_length )
+ {
+ dest_string << *iter;
+ dest_string << " ";
+ }
+ else
+ {
+ was_filtered = true;
+ }
+
+ ++iter;
+ };
+
+ return dest_string.str();
+}
+
+void LLPanelDirBrowser::selectByUUID(const LLUUID& id)
+{
+ LLCtrlListInterface *list = childGetListInterface("results");
+ if (!list) return;
+ bool found = list->setCurrentByID(id);
+ if (found)
+ {
+ // we got it, don't wait for network
+ // Don't bother looking for this in the draw loop.
+ mWantSelectID.setNull();
+ // Make sure UI updates.
+ onCommitList(NULL, this);
+ }
+ else
+ {
+ // waiting for this item from the network
+ mWantSelectID = id;
+ }
+}
+
+void LLPanelDirBrowser::selectEventByID(S32 event_id)
+{
+ if (mFloaterDirectory)
+ {
+ if (mFloaterDirectory->mPanelEventp)
+ {
+ mFloaterDirectory->mPanelEventp->setVisible(true);
+ mFloaterDirectory->mPanelEventp->setEventID(event_id);
+ }
+ }
+}
+
+void LLPanelDirBrowser::getSelectedInfo(LLUUID* id, S32 *type)
+{
+ LLCtrlListInterface *list = childGetListInterface("results");
+ if (!list) return;
+
+ LLSD id_sd = childGetValue("results");
+
+ *id = id_sd.asUUID();
+
+ std::string id_str = id_sd.asString();
+ *type = mResultsContents[id_str]["type"];
+}
+
+
+// static
+void LLPanelDirBrowser::onCommitList(LLUICtrl* ctrl, void* data)
+{
+ LLPanelDirBrowser* self = (LLPanelDirBrowser*)data;
+ LLCtrlListInterface *list = self->childGetListInterface("results");
+ if (!list) return;
+
+ // Start with everyone invisible
+ if (self->mFloaterDirectory)
+ {
+ self->mFloaterDirectory->hideAllDetailPanels();
+ }
+
+ if (FALSE == list->getCanSelect())
+ {
+ return;
+ }
+
+ std::string id_str = self->childGetValue("results").asString();
+ if (id_str.empty())
+ {
+ return;
+ }
+
+ LLSD item_id = list->getCurrentID();
+ S32 type = self->mResultsContents[id_str]["type"];
+ if (type == EVENT_CODE)
+ {
+ // all but events use the UUID above
+ item_id = self->mResultsContents[id_str]["event_id"];
+ }
+ //std::string name = self->mResultsContents[id_str]["name"].asString();
+ self->showDetailPanel(type, item_id);
+}
+
+void LLPanelDirBrowser::showDetailPanel(S32 type, LLSD id)
+{
+ switch(type)
+ {
+ case AVATAR_CODE:
+ if (mFloaterDirectory && mFloaterDirectory->mPanelAvatarp)
+ {
+ mFloaterDirectory->mPanelAvatarp->setVisible(true);
+ mFloaterDirectory->mPanelAvatarp->onOpen(id);
+ mFloaterDirectory->mPanelAvatarp->updateData();
+ }
+ break;
+ case GROUP_CODE:
+ if (mFloaterDirectory && mFloaterDirectory->mPanelGroupp)
+ {
+ mFloaterDirectory->mPanelGroupp->setVisible(true);
+ mFloaterDirectory->mPanelGroupp->onOpen(LLSD().with("group_id", id));
+ }
+ break;
+ case PLACE_CODE:
+ case FOR_SALE_CODE:
+ case AUCTION_CODE:
+ if (mFloaterDirectory && mFloaterDirectory->mPanelPlacep)
+ {
+ mFloaterDirectory->mPanelPlacep->setVisible(true);
+ LLSD key;
+ key["type"] = "remote_place";
+ key["id"]= id;
+ mFloaterDirectory->mPanelPlacep->onOpen(key);
+ }
+ break;
+ case CLASSIFIED_CODE:
+ if (mFloaterDirectory && mFloaterDirectory->mPanelClassifiedp)
+ {
+ mFloaterDirectory->mPanelClassifiedp->setVisible(true);
+ LLSD key;
+ key["classified_id"] = id;
+ key["from_search"] = true;
+ mFloaterDirectory->mPanelClassifiedp->onOpen(key);
+ }
+ break;
+ case EVENT_CODE:
+ {
+ U32 event_id = (U32)id.asInteger();
+ showEvent(event_id);
+ }
+ break;
+ default:
+ {
+ LL_WARNS() << "Unknown event type!" << LL_ENDL;
+ }
+ break;
+ }
+}
+
+
+void LLPanelDirBrowser::showEvent(const U32 event_id)
+{
+ // Start with everyone invisible
+ if (mFloaterDirectory)
+ {
+ mFloaterDirectory->hideAllDetailPanels();
+ if (mFloaterDirectory->mPanelEventp)
+ {
+ mFloaterDirectory->mPanelEventp->setVisible(true);
+ mFloaterDirectory->mPanelEventp->setEventID(event_id);
+ }
+ }
+}
+
+void LLPanelDirBrowser::processDirPeopleReply(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);
+
+ LLPanelDirBrowser* self = get_if_there(gDirBrowserInstances, query_id, (LLPanelDirBrowser*)NULL);
+ if (!self)
+ {
+ // data from an old query
+ return;
+ }
+
+ self->mHaveSearchResults = TRUE;
+
+ LLCtrlListInterface *list = self->childGetListInterface("results");
+ if (!list) return;
+
+ if (!list->getCanSelect())
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ self->mResultsContents = LLSD();
+ }
+
+ S32 rows = msg->getNumberOfBlocksFast(_PREHASH_QueryReplies);
+ self->mResultsReceived += rows;
+
+ rows = self->showNextButton(rows);
+
+ for (S32 i = 0; i < 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);
+ // unused
+ // msg->getStringFast(_PREHASH_QueryReplies,_PREHASH_Group, group, i);
+ // msg->getS32Fast( _PREHASH_QueryReplies,_PREHASH_Reputation, reputation, i);
+
+ if (agent_id.isNull())
+ {
+ continue;
+ }
+
+ LLSD content;
+
+ LLSD row;
+ row["id"] = agent_id;
+
+ // We don't show online status in the finder anymore,
+ // so just use the 'offline' icon as the generic 'person' icon
+ row["columns"][0]["column"] = "icon";
+ row["columns"][0]["type"] = "icon";
+ row["columns"][0]["value"] = "icon_avatar_offline.tga";
+
+ content["type"] = AVATAR_CODE;
+
+ std::string fullname = first_name + " " + last_name;
+ row["columns"][1]["column"] = "name";
+ row["columns"][1]["value"] = fullname;
+ row["columns"][1]["font"] = "SANSSERIF";
+
+ content["name"] = fullname;
+
+ list->addElement(row);
+ self->mResultsContents[agent_id.asString()] = content;
+ }
+
+ list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending);
+ self->updateResultCount();
+
+ // Poke the result received timer
+ self->mLastResultTimer.reset();
+ self->mDidAutoSelect = false;
+}
+
+
+void LLPanelDirBrowser::processDirPlacesReply(LLMessageSystem* msg, void**)
+{
+ LLUUID agent_id;
+ LLUUID query_id;
+ LLUUID parcel_id;
+ std::string name;
+ bool is_for_sale = false;
+ bool is_auction = false;
+ F32 dwell;
+
+ msg->getUUID("AgentData", "AgentID", agent_id);
+ msg->getUUID("QueryData", "QueryID", query_id );
+
+ if (msg->getNumberOfBlocks("StatusData"))
+ {
+ U32 status;
+ msg->getU32("StatusData", "Status", status);
+ if (status & STATUS_SEARCH_PLACES_BANNEDWORD)
+ {
+ LLNotificationsUtil::add("SearchWordBanned");
+ }
+ }
+
+ LLPanelDirBrowser* self = get_if_there(gDirBrowserInstances, query_id, (LLPanelDirBrowser*)NULL);
+ if (!self)
+ {
+ // data from an old query
+ return;
+ }
+
+ self->mHaveSearchResults = TRUE;
+
+ LLCtrlListInterface *list = self->childGetListInterface("results");
+ if (!list) return;
+
+ if (!list->getCanSelect())
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ self->mResultsContents = LLSD();
+ }
+
+ S32 count = msg->getNumberOfBlocks("QueryReplies");
+ self->mResultsReceived += count;
+
+ count = self->showNextButton(count);
+
+ for (S32 i = 0; i < count ; i++)
+ {
+ msg->getUUID("QueryReplies", "ParcelID", parcel_id, i);
+ msg->getString("QueryReplies", "Name", name, i);
+ msg->getBOOL("QueryReplies", "ForSale", is_for_sale, i);
+ msg->getBOOL("QueryReplies", "Auction", is_auction, i);
+ msg->getF32("QueryReplies", "Dwell", dwell, i);
+
+ if (parcel_id.isNull())
+ {
+ continue;
+ }
+
+ LLSD content;
+ S32 type;
+
+ LLSD row = self->createLandSale(parcel_id, is_auction, is_for_sale, name, &type);
+
+ content["type"] = type;
+ content["name"] = name;
+
+ std::string buffer = llformat("%.0f", (F64)dwell);
+ row["columns"][2]["column"] = "dwell";
+ row["columns"][2]["value"] = buffer;
+ row["columns"][2]["font"] = "SansSerifSmall";
+
+ list->addElement(row);
+ self->mResultsContents[parcel_id.asString()] = content;
+ }
+
+ list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending);
+ self->updateResultCount();
+
+ // Poke the result received timer
+ self->mLastResultTimer.reset();
+ self->mDidAutoSelect = false;
+}
+
+
+void LLPanelDirBrowser::processDirEventsReply(LLMessageSystem* msg, void**)
+{
+ LLUUID agent_id;
+ LLUUID query_id;
+ LLUUID owner_id;
+ std::string name;
+ std::string date;
+ bool show_pg = gSavedSettings.getBOOL("ShowPGEvents");
+ bool show_mature = gSavedSettings.getBOOL("ShowMatureEvents");
+ bool show_adult = gSavedSettings.getBOOL("ShowAdultEvents");
+
+ msg->getUUID("AgentData", "AgentID", agent_id);
+ msg->getUUID("QueryData", "QueryID", query_id );
+
+ LLPanelDirBrowser* self = get_if_there(gDirBrowserInstances, query_id, (LLPanelDirBrowser*)NULL);
+ if (!self)
+ {
+ return;
+ }
+
+ if (msg->getNumberOfBlocks("StatusData"))
+ {
+ U32 status;
+ msg->getU32("StatusData", "Status", status);
+ if (status & STATUS_SEARCH_EVENTS_BANNEDWORD)
+ {
+ LLNotificationsUtil::add("SearchWordBanned");
+ }
+ }
+
+ self->mHaveSearchResults = TRUE;
+
+ LLCtrlListInterface *list = self->childGetListInterface("results");
+ if (!list) return;
+
+ if (!list->getCanSelect())
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ self->mResultsContents = LLSD();
+ }
+
+ S32 rows = msg->getNumberOfBlocks("QueryReplies");
+ self->mResultsReceived += rows;
+
+ rows = self->showNextButton(rows);
+
+ for (S32 i = 0; i < 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())
+ {
+ //RN: should this check event_id instead?
+ LL_WARNS() << "skipped event due to owner_id null, event_id " << event_id << LL_ENDL;
+ continue;
+ }
+
+ // skip events that don't match the flags
+ // there's no PG flag, so we make sure neither adult nor mature is set
+ if (((event_flags & (EVENT_FLAG_ADULT | EVENT_FLAG_MATURE)) == EVENT_FLAG_NONE) && !show_pg)
+ {
+ //llwarns << "Skipped pg event because we're not showing pg, event_id " << event_id << llendl;
+ continue;
+ }
+
+ if ((event_flags & EVENT_FLAG_MATURE) && !show_mature)
+ {
+ //llwarns << "Skipped mature event because we're not showing mature, event_id " << event_id << llendl;
+ continue;
+ }
+
+ if ((event_flags & EVENT_FLAG_ADULT) && !show_adult)
+ {
+ //llwarns << "Skipped adult event because we're not showing adult, event_id " << event_id << llendl;
+ continue;
+ }
+
+ LLSD content;
+
+ content["type"] = EVENT_CODE;
+ content["name"] = name;
+ content["event_id"] = (S32)event_id;
+
+ LLSD row;
+ row["id"] = llformat("%u", event_id);
+
+ // Column 0 - event icon
+ LLUUID image_id;
+ if (event_flags == EVENT_FLAG_ADULT)
+ {
+ row["columns"][0]["column"] = "icon";
+ row["columns"][0]["type"] = "icon";
+ row["columns"][0]["value"] = "icon_event_adult.tga";
+ }
+ else if (event_flags == EVENT_FLAG_MATURE)
+ {
+ row["columns"][0]["column"] = "icon";
+ row["columns"][0]["type"] = "icon";
+ row["columns"][0]["value"] = "icon_event_mature.tga";
+ }
+ else
+ {
+ row["columns"][0]["column"] = "icon";
+ row["columns"][0]["type"] = "icon";
+ row["columns"][0]["value"] = "icon_event.tga";
+ }
+
+ row["columns"][1]["column"] = "name";
+ row["columns"][1]["value"] = name;
+ row["columns"][1]["font"] = "SANSSERIF";
+
+ row["columns"][2]["column"] = "date";
+ row["columns"][2]["value"] = date;
+ row["columns"][2]["font"] = "SansSerifSmall";
+
+ row["columns"][3]["column"] = "time";
+ row["columns"][3]["value"] = llformat("%u", unix_time);
+ row["columns"][3]["font"] = "SansSerifSmall";
+
+ list->addElement(row, ADD_TOP /*ADD_SORTED*/);
+
+ std::string id_str = llformat("%u", event_id);
+ self->mResultsContents[id_str] = content;
+ }
+
+ list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending);
+ self->updateResultCount();
+
+ // Poke the result received timer
+ self->mLastResultTimer.reset();
+ self->mDidAutoSelect = false;
+}
+
+
+// static
+void LLPanelDirBrowser::processDirGroupsReply(LLMessageSystem* msg, void**)
+{
+ S32 i;
+
+ LLUUID query_id;
+ LLUUID group_id;
+ std::string group_name;
+ S32 members;
+ F32 search_order;
+
+ msg->getUUIDFast(_PREHASH_QueryData,_PREHASH_QueryID, query_id );
+
+ LLPanelDirBrowser* self = get_if_there(gDirBrowserInstances, query_id, (LLPanelDirBrowser*)NULL);
+ if (!self)
+ {
+ return;
+ }
+
+ self->mHaveSearchResults = TRUE;
+
+ LLCtrlListInterface *list = self->childGetListInterface("results");
+ if (!list) return;
+
+ if (!list->getCanSelect())
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ self->mResultsContents = LLSD();
+ }
+
+ S32 rows = msg->getNumberOfBlocksFast(_PREHASH_QueryReplies);
+ self->mResultsReceived += rows;
+
+ rows = self->showNextButton(rows);
+
+ for (i = 0; i < 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())
+ {
+ continue;
+ }
+
+ LLSD content;
+ content["type"] = GROUP_CODE;
+ content["name"] = group_name;
+
+ LLSD row;
+ row["id"] = group_id;
+
+ LLUUID image_id;
+ row["columns"][0]["column"] = "icon";
+ row["columns"][0]["type"] = "icon";
+ row["columns"][0]["value"] = "icon_group.tga";
+
+ row["columns"][1]["column"] = "name";
+ row["columns"][1]["value"] = group_name;
+ row["columns"][1]["font"] = "SANSSERIF";
+
+ row["columns"][2]["column"] = "members";
+ row["columns"][2]["value"] = members;
+ row["columns"][2]["font"] = "SansSerifSmall";
+
+ row["columns"][3]["column"] = "score";
+ row["columns"][3]["value"] = search_order;
+
+ list->addElement(row);
+ self->mResultsContents[group_id.asString()] = content;
+ }
+ list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending);
+ self->updateResultCount();
+
+ // Poke the result received timer
+ self->mLastResultTimer.reset();
+ self->mDidAutoSelect = false;
+}
+
+
+// static
+void LLPanelDirBrowser::processDirClassifiedReply(LLMessageSystem* msg, void**)
+{
+ S32 i;
+ S32 num_new_rows;
+
+ LLUUID agent_id;
+ LLUUID query_id;
+
+ msg->getUUID("AgentData", "AgentID", agent_id);
+ if (agent_id != gAgent.getID())
+ {
+ LL_WARNS() << "Message for wrong agent " << agent_id
+ << " in processDirClassifiedReply" << LL_ENDL;
+ return;
+ }
+
+ msg->getUUID("QueryData", "QueryID", query_id);
+ LLPanelDirBrowser* self = get_if_there(gDirBrowserInstances, query_id, (LLPanelDirBrowser*)NULL);
+ if (!self)
+ {
+ return;
+ }
+
+ if (msg->getNumberOfBlocks("StatusData"))
+ {
+ U32 status;
+ msg->getU32("StatusData", "Status", status);
+ if (status & STATUS_SEARCH_CLASSIFIEDS_BANNEDWORD)
+ {
+ LLNotificationsUtil::add("SearchWordBanned");
+ }
+ }
+
+ self->mHaveSearchResults = TRUE;
+
+ LLCtrlListInterface *list = self->childGetListInterface("results");
+ if (!list) return;
+
+ if (!list->getCanSelect())
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ self->mResultsContents = LLSD();
+ }
+
+ num_new_rows = msg->getNumberOfBlocksFast(_PREHASH_QueryReplies);
+ self->mResultsReceived += num_new_rows;
+
+ num_new_rows = self->showNextButton(num_new_rows);
+ for (i = 0; i < num_new_rows; i++)
+ {
+ LLUUID classified_id;
+ std::string name;
+ U32 creation_date = 0; // unix timestamp
+ U32 expiration_date = 0; // future use
+ S32 price_for_listing = 0;
+ 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.notNull() )
+ {
+ self->addClassified(list, classified_id, name, creation_date, price_for_listing);
+
+ LLSD content;
+ content["type"] = CLASSIFIED_CODE;
+ content["name"] = name;
+ self->mResultsContents[classified_id.asString()] = content;
+ }
+ }
+ // The server does the initial sort, by price paid per listing and date. JC
+ self->updateResultCount();
+
+ // Poke the result received timer
+ self->mLastResultTimer.reset();
+ self->mDidAutoSelect = false;
+}
+
+void LLPanelDirBrowser::processDirLandReply(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 = false;
+ bool for_sale = false;
+ S32 sale_price;
+ S32 actual_area;
+
+ msg->getUUID("AgentData", "AgentID", agent_id);
+ msg->getUUID("QueryData", "QueryID", query_id );
+
+ LLPanelDirBrowser* browser = get_if_there(gDirBrowserInstances, query_id, (LLPanelDirBrowser*)NULL);
+ if (!browser)
+ {
+ // data from an old query
+ return;
+ }
+
+ // Only handled by LLPanelDirLand
+ LLPanelDirLand* self = (LLPanelDirLand*)browser;
+
+ self->mHaveSearchResults = TRUE;
+
+ LLCtrlListInterface *list = self->childGetListInterface("results");
+ if (!list) return;
+
+ if (!list->getCanSelect())
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ self->mResultsContents = LLSD();
+ }
+
+ bool use_price = gSavedSettings.getBOOL("FindLandPrice");
+ S32 limit_price = self->childGetValue("priceedit").asInteger();
+
+ bool use_area = gSavedSettings.getBOOL("FindLandArea");
+ S32 limit_area = self->childGetValue("areaedit").asInteger();
+
+ S32 i;
+ S32 count = msg->getNumberOfBlocks("QueryReplies");
+ self->mResultsReceived += count;
+
+ S32 non_auction_count = 0;
+ for (i = 0; i < count; 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", sale_price, i);
+ msg->getS32("QueryReplies", "ActualArea", actual_area, i);
+
+ 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 && (sale_price > limit_price)) continue;
+
+ if (use_area && (actual_area < limit_area)) continue;
+
+ LLSD content;
+ S32 type;
+
+ LLSD row = self->createLandSale(parcel_id, auction, for_sale, name, &type);
+
+ content["type"] = type;
+ content["name"] = name;
+ content["landtype"] = land_type;
+
+ std::string buffer = "Auction";
+ if (!auction)
+ {
+ buffer = llformat("%d", sale_price);
+ non_auction_count++;
+ }
+ row["columns"][2]["column"] = "price";
+ row["columns"][2]["value"] = buffer;
+ row["columns"][2]["font"] = "SansSerifSmall";
+
+ buffer = llformat("%d", actual_area);
+ row["columns"][3]["column"] = "area";
+ row["columns"][3]["value"] = buffer;
+ row["columns"][3]["font"] = "SansSerifSmall";
+
+ if (!auction)
+ {
+ F32 price_per_meter;
+ if (actual_area > 0)
+ {
+ price_per_meter = (F32)sale_price / (F32)actual_area;
+ }
+ else
+ {
+ price_per_meter = 0.f;
+ }
+ // Prices are usually L$1 - L$10 / meter
+ buffer = llformat("%.1f", price_per_meter);
+ row["columns"][4]["column"] = "per_meter";
+ row["columns"][4]["value"] = buffer;
+ row["columns"][4]["font"] = "SansSerifSmall";
+ }
+ else
+ {
+ // Auctions start at L$1 per meter
+ row["columns"][4]["column"] = "per_meter";
+ row["columns"][4]["value"] = "1.0";
+ row["columns"][4]["font"] = "SansSerifSmall";
+ }
+
+ row["columns"][5]["column"] = "landtype";
+ row["columns"][5]["value"] = land_type;
+ row["columns"][5]["font"] = "SansSerifSmall";
+
+ list->addElement(row);
+ self->mResultsContents[parcel_id.asString()] = content;
+ }
+
+ // All auction results are shown on the first page
+ // But they don't count towards the 100 / page limit
+ // So figure out the next button here, when we know how many aren't auctions
+ count = self->showNextButton(non_auction_count);
+
+ self->updateResultCount();
+
+ // Poke the result received timer
+ self->mLastResultTimer.reset();
+ self->mDidAutoSelect = false;
+}
+
+void LLPanelDirBrowser::addClassified(LLCtrlListInterface *list, const LLUUID& pick_id, const std::string& name, const U32 creation_date, const S32 price_for_listing)
+{
+ std::string type = llformat("%d", CLASSIFIED_CODE);
+
+ LLSD row;
+ row["id"] = pick_id;
+
+ row["columns"][0]["column"] = "icon";
+ row["columns"][0]["type"] = "icon";
+ row["columns"][0]["value"] = "icon_top_pick.tga";
+
+ row["columns"][1]["column"] = "name";
+ row["columns"][1]["value"] = name;
+ row["columns"][1]["font"] = "SANSSERIF";
+
+ row["columns"][2]["column"] = "price";
+ row["columns"][2]["value"] = price_for_listing;
+ row["columns"][2]["font"] = "SansSerifSmall";
+
+ list->addElement(row);
+}
+
+LLSD LLPanelDirBrowser::createLandSale(const LLUUID& parcel_id, bool is_auction, bool is_for_sale, const std::string& name, S32 *type)
+{
+ LLSD row;
+ row["id"] = parcel_id;
+ LLUUID image_id;
+
+ // Icon and type
+ if(is_auction)
+ {
+ row["columns"][0]["column"] = "icon";
+ row["columns"][0]["type"] = "icon";
+ row["columns"][0]["value"] = "icon_auction.tga";
+
+ *type = AUCTION_CODE;
+ }
+ else if (is_for_sale)
+ {
+ row["columns"][0]["column"] = "icon";
+ row["columns"][0]["type"] = "icon";
+ row["columns"][0]["value"] = "icon_for_sale.tga";
+
+ *type = FOR_SALE_CODE;
+ }
+ else
+ {
+ row["columns"][0]["column"] = "icon";
+ row["columns"][0]["type"] = "icon";
+ row["columns"][0]["value"] = "icon_place.tga";
+
+ *type = PLACE_CODE;
+ }
+
+ row["columns"][1]["column"] = "name";
+ row["columns"][1]["value"] = name;
+ row["columns"][1]["font"] = "SANSSERIF";
+
+ return row;
+}
+
+void LLPanelDirBrowser::setupNewSearch()
+{
+ LLScrollListCtrl* list = getChild<LLScrollListCtrl>("results");
+
+ gDirBrowserInstances.erase(mSearchID);
+ // Make a new query ID
+ mSearchID.generate();
+
+ gDirBrowserInstances.emplace(mSearchID, this);
+
+ // ready the list for results
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ list->setCommentText(LLTrans::getString("Searching"));
+ list->setEnabled(false);
+
+ mResultsReceived = 0;
+ mHaveSearchResults = FALSE;
+
+ // Set all panels to be invisible
+ mFloaterDirectory->hideAllDetailPanels();
+
+ updateResultCount();
+}
+
+
+// static
+// called from calssifieds, events, groups, land, people, and places
+void LLPanelDirBrowser::onClickSearchCore(void* userdata)
+{
+ LLPanelDirBrowser* self = (LLPanelDirBrowser*)userdata;
+ if (!self) return;
+
+ self->resetSearchStart();
+ self->performQuery();
+}
+
+
+// static
+void LLPanelDirBrowser::sendDirFindQuery(
+ LLMessageSystem* msg,
+ const LLUUID& query_id,
+ const std::string& text,
+ U32 flags,
+ S32 query_start)
+{
+ msg->newMessage("DirFindQuery");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID());
+ msg->addUUID("SessionID", gAgent.getSessionID());
+ msg->nextBlock("QueryData");
+ msg->addUUID("QueryID", query_id);
+ msg->addString("QueryText", text);
+ msg->addU32("QueryFlags", flags);
+ msg->addS32("QueryStart", query_start);
+ gAgent.sendReliableMessage();
+}
+
+
+void LLPanelDirBrowser::onKeystrokeName(LLLineEditor* line, void* data)
+{
+ LLPanelDirBrowser *self = (LLPanelDirBrowser*)data;
+ if (line->getLength() >= (S32)self->mMinSearchChars)
+ {
+ self->setDefaultBtn( "Search" );
+ self->childEnable("Search");
+ }
+ else
+ {
+ self->setDefaultBtn();
+ self->childDisable("Search");
+ }
+}
+
+// setup results when shown
+void LLPanelDirBrowser::onVisibilityChange(bool new_visibility)
+{
+ if (new_visibility)
+ {
+ onCommitList(NULL, this);
+ }
+ LLPanel::onVisibilityChange(new_visibility);
+}
+
+S32 LLPanelDirBrowser::showNextButton(S32 rows)
+{
+ // HACK: This hack doesn't work for llpaneldirfind (ALL)
+ // because other data is being returned as well.
+ if ( getName() != "find_all_old_panel")
+ {
+ // HACK: The (mResultsPerPage)+1th entry indicates there are 'more'
+ bool show_next = (mResultsReceived > mResultsPerPage);
+ mNextPageBtn->setVisible(show_next);
+ if (show_next)
+ {
+ rows -= (mResultsReceived - mResultsPerPage);
+ }
+ }
+ else
+ {
+ // Hide page buttons
+ mNextPageBtn->setVisible(false);
+ mPrevPageBtn->setVisible(false);
+ }
+ return rows;
+}
diff --git a/indra/newview/llpaneldirbrowser.h b/indra/newview/llpaneldirbrowser.h
new file mode 100644
index 0000000000..cb947f8507
--- /dev/null
+++ b/indra/newview/llpaneldirbrowser.h
@@ -0,0 +1,167 @@
+/**
+ * @file llpaneldirbrowser.h
+ * @brief Base class for panels in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELDIRBROWSER_H
+#define LL_LLPANELDIRBROWSER_H
+
+#include "llpanel.h"
+
+#include "llframetimer.h"
+
+class LLMessageSystem;
+class LLFloaterDirectory;
+class LLLineEditor;
+
+class LLPanelDirBrowser: public LLPanel
+{
+public:
+ LLPanelDirBrowser();
+ virtual ~LLPanelDirBrowser();
+
+ bool postBuild() override;
+ void setFloaterDirectory(LLFloaterDirectory* floater) { mFloaterDirectory = floater; }
+
+ // Use to get periodic updates.
+ void draw() override;
+
+ void onVisibilityChange(bool curVisibilityIn) override;
+
+ // Redo your search for the prev/next page of results
+ virtual void prevPage();
+ virtual void nextPage();
+ void resetSearchStart();
+ // Do the current query (used by prevPage/nextPage)
+ virtual void performQuery() {};
+
+ const LLUUID& getSearchID() const { return mSearchID; }
+
+ // Select the line in the scroll list control with this ID,
+ // either now or when data arrives from the server.
+ void selectByUUID(const LLUUID& id);
+
+ void selectEventByID(S32 event_id);
+
+ void getSelectedInfo(LLUUID* id, S32 *type);
+
+ void showDetailPanel(S32 type, LLSD item_id);
+ // type is EVENT_CODE, PLACE_CODE, etc. from below.
+ // item_id is integer for events, UUID for all others.
+
+ // from llpaneldirbase
+ void setupNewSearch();
+
+ // default handler for clicking the search button resets the
+ // next/prev state and performs the query.
+ // Expects a pointer to an LLPanelDirBrowser object.
+ static void onClickSearchCore(void* userdata);
+
+ // query_start indicates the first result row to
+ // return, usually 0 or 100 or 200 because the searches
+ // return a max of 100 rows
+ static void sendDirFindQuery(
+ LLMessageSystem* msg,
+ const LLUUID& query_id,
+ const std::string& text,
+ U32 flags,
+ S32 query_start);
+
+ void showEvent(const U32 event_id);
+
+ static void onCommitList(LLUICtrl* ctrl, void* data);
+
+ static void processDirPeopleReply(LLMessageSystem* msg, void**);
+ static void processDirPlacesReply(LLMessageSystem* msg, void**);
+ static void processDirEventsReply(LLMessageSystem* msg, void**);
+ static void processDirGroupsReply(LLMessageSystem* msg, void**);
+ static void processDirClassifiedReply(LLMessageSystem* msg, void**);
+ static void processDirLandReply(LLMessageSystem *msg, void**);
+
+ std::string filterShortWords( const std::string source_string, int shortest_word_length, bool& was_filtered );
+
+protected:
+ void updateResultCount();
+
+ void addClassified(LLCtrlListInterface *list, const LLUUID& classified_id, const std::string& name, const U32 creation_date, const S32 price_for_listing);
+ LLSD createLandSale(const LLUUID& parcel_id, bool is_auction, bool is_for_sale, const std::string& name, S32 *type);
+
+ static void onKeystrokeName(LLLineEditor* line, void* data);
+
+ // If this is a search for a panel like "people_panel" (and not the "all" panel)
+ // optionally show the "Next" button. Return the actual number of
+ // rows to display.
+ S32 showNextButton(S32 rows);
+
+protected:
+ LLUUID mSearchID; // Unique ID for a pending search
+ LLUUID mWantSelectID; // scroll item to select on arrival
+ std::string mCurrentSortColumn;
+ bool mCurrentSortAscending;
+ // Some searches return a max of 100 items per page, so we can
+ // start the search from the 100th item rather than the 0th, etc.
+ S32 mSearchStart;
+ // Places is 100 per page, events is 200 per page
+ S32 mResultsPerPage;
+ S32 mResultsReceived;
+
+ U32 mMinSearchChars;
+
+ LLSD mResultsContents;
+
+ bool mHaveSearchResults;
+ bool mDidAutoSelect;
+ LLFrameTimer mLastResultTimer;
+
+ LLFloaterDirectory* mFloaterDirectory;
+ LLButton* mPrevPageBtn;
+ LLButton* mNextPageBtn;
+};
+
+constexpr S32 RESULTS_PER_PAGE_DEFAULT = 100;
+constexpr S32 RESULTS_PER_PAGE_EVENTS = 200;
+
+// Codes used for sorting by type.
+const S32 INVALID_CODE = -1;
+const S32 EVENT_CODE = 0;
+const S32 PLACE_CODE = 1;
+// We no longer show online vs. offline in search result icons.
+//const S32 ONLINE_CODE = 2;
+//const S32 OFFLINE_CODE = 3;
+const S32 AVATAR_CODE = 3;
+const S32 GROUP_CODE = 4;
+const S32 CLASSIFIED_CODE = 5;
+const S32 FOR_SALE_CODE = 6; // for sale place
+const S32 AUCTION_CODE = 7; // for auction place
+const S32 POPULAR_CODE = 8; // popular by dwell
+
+// mask values for search flags
+const S32 SEARCH_NONE = 0; // should try not to send this to the search engine
+const S32 SEARCH_PG = 1;
+const S32 SEARCH_MATURE = 2;
+const S32 SEARCH_ADULT = 4;
+
+extern std::map<LLUUID, LLPanelDirBrowser*> gDirBrowserInstances;
+
+#endif // LL_LLPANELDIRBROWSER_H
diff --git a/indra/newview/llpaneldirclassified.cpp b/indra/newview/llpaneldirclassified.cpp
new file mode 100644
index 0000000000..ca625b956b
--- /dev/null
+++ b/indra/newview/llpaneldirclassified.cpp
@@ -0,0 +1,109 @@
+/**
+ * @file llpaneldirclassified.cpp
+ * @brief Classified panel in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpaneldirclassified.h"
+
+#include "llclassifiedflags.h"
+
+#include "llfontgl.h"
+#include "message.h"
+#include "llqueryflags.h"
+
+#include "llagent.h"
+#include "llbutton.h"
+#include "llcontrol.h"
+#include "llcombobox.h"
+#include "llclassifiedinfo.h"
+#include "lluiconstants.h"
+#include "llpaneldirbrowser.h"
+#include "lltextbox.h"
+
+#include "llcheckboxctrl.h"
+#include "llfloaterdirectory.h"
+#include "lllineeditor.h"
+#include "llsearcheditor.h"
+#include "llviewermenu.h"
+#include "llnotificationsutil.h"
+
+static LLPanelInjector<LLPanelDirClassified> t_panel_dir_classified("panel_dir_classified");
+
+LLPanelDirClassified::LLPanelDirClassified()
+: LLPanelDirBrowser()
+{
+}
+
+bool LLPanelDirClassified::postBuild()
+{
+ LLPanelDirBrowser::postBuild();
+
+ childSetAction("Search", onClickSearchCore, this);
+ setDefaultBtn("Search");
+ return true;
+}
+
+LLPanelDirClassified::~LLPanelDirClassified()
+{
+}
+
+void LLPanelDirClassified::performQuery()
+{
+ static LLUICachedControl<bool> inc_pg("ShowPGClassifieds", true);
+ static LLUICachedControl<bool> inc_mature("ShowMatureClassifieds", false);
+ static LLUICachedControl<bool> inc_adult("ShowAdultClassifieds", false);
+
+ if (!(inc_pg || inc_mature || inc_adult))
+ {
+ LLNotificationsUtil::add("NoContentToSearch");
+ return;
+ }
+
+ // This sets mSearchID and clears the list of results
+ setupNewSearch();
+
+ // send the message
+ LLMessageSystem *msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_DirClassifiedQuery);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+ bool filter_auto_renew = false;
+ U32 query_flags = pack_classified_flags_request(filter_auto_renew, inc_pg,
+ inc_mature && gAgent.canAccessMature(),
+ inc_adult && gAgent.canAccessAdult());
+ U32 category = childGetValue("Category").asInteger();
+
+ msg->nextBlockFast(_PREHASH_QueryData);
+ msg->addUUIDFast(_PREHASH_QueryID, mSearchID );
+ msg->addStringFast(_PREHASH_QueryText, childGetValue("name").asString());
+ msg->addU32Fast(_PREHASH_QueryFlags, query_flags);
+ msg->addU32Fast(_PREHASH_Category, category);
+ msg->addS32Fast(_PREHASH_QueryStart,mSearchStart);
+
+ gAgent.sendReliableMessage();
+}
diff --git a/indra/newview/llpaneldirclassified.h b/indra/newview/llpaneldirclassified.h
new file mode 100644
index 0000000000..6682f73929
--- /dev/null
+++ b/indra/newview/llpaneldirclassified.h
@@ -0,0 +1,55 @@
+/**
+ * @file llpaneldirclassified.h
+ * @brief Classified panel in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELDIRCLASSIFIED_H
+#define LL_LLPANELDIRCLASSIFIED_H
+
+#include "llpaneldirbrowser.h"
+
+// UI class forward declarations
+class LLButton;
+class LLCheckBoxCtrl;
+class LLComboBox;
+class LLLineEditor;
+class LLScrollListCtrl;
+
+class LLPanelDirClassified : public LLPanelDirBrowser
+{
+public:
+ LLPanelDirClassified();
+ /*virtual*/ ~LLPanelDirClassified();
+
+ bool postBuild();
+
+ // Request the classifieds from the database
+ void performQuery();
+
+protected:
+ // onClickNext and onClickPrev are special case searches
+ static void onClickSearch(void *userdata);
+};
+
+#endif
diff --git a/indra/newview/llpaneldirevents.cpp b/indra/newview/llpaneldirevents.cpp
new file mode 100644
index 0000000000..63eba04296
--- /dev/null
+++ b/indra/newview/llpaneldirevents.cpp
@@ -0,0 +1,248 @@
+/**
+ * @file llpaneldirevents.cpp
+ * @brief Events panel in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpaneldirevents.h"
+
+#include <sstream>
+
+// linden library includes
+#include "message.h"
+#include "llqueryflags.h"
+
+// viewer project includes
+#include "llagent.h"
+#include "llviewercontrol.h"
+#include "llnotificationsutil.h"
+#include "llpaneldirbrowser.h"
+#include "llresmgr.h"
+#include "lluiconstants.h"
+#include "llappviewer.h"
+
+static LLPanelInjector<LLPanelDirEvents> t_panel_dir_events("panel_dir_events");
+
+constexpr S32 DAY_TO_SEC = 24 * 60 * 60;
+
+LLPanelDirEvents::LLPanelDirEvents()
+ : LLPanelDirBrowser(),
+ mDay(0)
+{
+ // more results per page for this
+ mResultsPerPage = RESULTS_PER_PAGE_EVENTS;
+}
+
+bool LLPanelDirEvents::postBuild()
+{
+ LLPanelDirBrowser::postBuild();
+
+ childSetCommitCallback("date_mode", onDateModeCallback, this);
+
+ childSetAction("back_btn", onBackBtn, this);
+ childSetAction("forward_btn", onForwardBtn, this);
+
+ childSetCommitCallback("mature", onCommitMature, this);
+
+ childSetAction("Search", LLPanelDirBrowser::onClickSearchCore, this);
+ setDefaultBtn("Search");
+
+ onDateModeCallback(NULL, this);
+
+ mCurrentSortColumn = "time";
+
+ setDay(0); // for today
+
+ return TRUE;
+}
+
+LLPanelDirEvents::~LLPanelDirEvents()
+{
+}
+
+void LLPanelDirEvents::setDay(S32 day)
+{
+ mDay = day;
+
+ // Get time UTC
+ time_t utc_time = time_corrected();
+
+ // Correct for offset
+ utc_time += day * DAY_TO_SEC;
+
+ // There's only one internal tm buffer.
+ struct tm* internal_time;
+
+ // Convert to Pacific, based on server's opinion of whether
+ // it's daylight savings time there.
+ internal_time = utc_to_pacific_time(utc_time, is_daylight_savings());
+
+ std::string buffer = llformat("%d/%d",
+ 1 + internal_time->tm_mon, // Jan = 0
+ internal_time->tm_mday); // 2001 = 101
+ childSetValue("date_text", buffer);
+}
+
+// virtual
+void LLPanelDirEvents::performQuery()
+{
+ // event_id 0 will perform no delete action.
+ performQueryOrDelete(0);
+}
+
+void LLPanelDirEvents::performQueryOrDelete(U32 event_id)
+{
+ S32 relative_day = mDay;
+ // Update the date field to show the date IN THE SERVER'S
+ // TIME ZONE, as that is what will be displayed in each event
+
+ // Get time UTC
+ time_t utc_time = time_corrected();
+
+ // Correct for offset
+ utc_time += relative_day * DAY_TO_SEC;
+
+ // There's only one internal tm buffer.
+ struct tm* internal_time;
+
+ // Convert to Pacific, based on server's opinion of whether
+ // it's daylight savings time there.
+ internal_time = utc_to_pacific_time(utc_time, is_daylight_savings());
+
+ std::string buffer = llformat("%d/%d",
+ 1 + internal_time->tm_mon, // Jan = 0
+ internal_time->tm_mday); // 2001 = 101
+ childSetValue("date_text", buffer);
+
+ // Record the relative day so back and forward buttons
+ // offset from this day.
+ mDay = relative_day;
+
+ static LLUICachedControl<bool> incpg("ShowPGEvents", true);
+ static LLUICachedControl<bool> incmature("ShowMatureEvents", false);
+ static LLUICachedControl<bool> incadult("ShowAdultEvents", false);
+
+ U32 scope = DFQ_DATE_EVENTS;
+ if (incpg) scope |= DFQ_INC_PG;
+ if (incmature && gAgent.canAccessMature()) scope |= DFQ_INC_MATURE;
+ if (incadult && gAgent.canAccessAdult()) scope |= DFQ_INC_ADULT;
+
+ if ( !( scope & (DFQ_INC_PG | DFQ_INC_MATURE | DFQ_INC_ADULT )))
+ {
+ LLNotificationsUtil::add("NoContentToSearch");
+ return;
+ }
+
+ setupNewSearch();
+
+ std::ostringstream params;
+
+ // Date mode for the search
+ if ("current" == childGetValue("date_mode").asString())
+ {
+ params << "u|";
+ }
+ else
+ {
+ params << mDay << "|";
+ }
+
+ // Categories are stored in the database in table indra.event_category
+ // XML must match.
+ U32 cat_id = childGetValue("category_combo").asInteger();
+
+ params << cat_id << "|";
+ params << childGetValue("event_search_text").asString();
+
+ // send the message
+ if (0 == event_id)
+ {
+ sendDirFindQuery(gMessageSystem, mSearchID, params.str(), scope, mSearchStart);
+ }
+ else
+ {
+ // This delete will also perform a query.
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessageFast(_PREHASH_EventGodDelete);
+
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlockFast(_PREHASH_EventData);
+ msg->addU32Fast(_PREHASH_EventID, event_id);
+
+ msg->nextBlockFast(_PREHASH_QueryData);
+ msg->addUUIDFast(_PREHASH_QueryID, mSearchID);
+ msg->addStringFast(_PREHASH_QueryText, params.str());
+ msg->addU32Fast(_PREHASH_QueryFlags, scope);
+ msg->addS32Fast(_PREHASH_QueryStart, mSearchStart);
+ gAgent.sendReliableMessage();
+ }
+}
+
+// static
+void LLPanelDirEvents::onDateModeCallback(LLUICtrl* ctrl, void *data)
+{
+ LLPanelDirEvents* self = (LLPanelDirEvents*)data;
+ if (self->childGetValue("date_mode").asString() == "date")
+ {
+ self->childEnable("forward_btn");
+ self->childEnable("back_btn");
+ }
+ else
+ {
+ self->childDisable("forward_btn");
+ self->childDisable("back_btn");
+ }
+}
+
+// static
+void LLPanelDirEvents::onBackBtn(void* data)
+{
+ LLPanelDirEvents* self = (LLPanelDirEvents*)data;
+ self->resetSearchStart();
+ self->setDay(self->mDay - 1);
+ self->performQuery();
+}
+
+
+// static
+void LLPanelDirEvents::onForwardBtn(void* data)
+{
+ LLPanelDirEvents* self = (LLPanelDirEvents*)data;
+ self->resetSearchStart();
+ self->setDay(self->mDay + 1);
+ self->performQuery();
+}
+
+
+// static
+void LLPanelDirEvents::onCommitMature(LLUICtrl* ctrl, void* data)
+{
+ // just perform another search
+ onClickSearchCore(data);
+}
diff --git a/indra/newview/llpaneldirevents.h b/indra/newview/llpaneldirevents.h
new file mode 100644
index 0000000000..596abc5f0e
--- /dev/null
+++ b/indra/newview/llpaneldirevents.h
@@ -0,0 +1,61 @@
+/**
+ * @file llpaneldirevents.h
+ * @brief Events panel in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELDIREVENTS_H
+#define LL_LLPANELDIREVENTS_H
+
+#include "llpaneldirbrowser.h"
+
+class LLUICtrl;
+class LLPanelDirBrowser;
+
+class LLPanelDirEvents : public LLPanelDirBrowser
+{
+public:
+ LLPanelDirEvents();
+ virtual ~LLPanelDirEvents();
+
+ bool postBuild() override;
+
+ /*virtual*/ void performQuery() override;
+
+ void performQueryOrDelete(U32 event_id);
+
+ // pass 0 for today, 1 for tomorrow
+ void setDay(S32 day);
+
+protected:
+ static void onDateModeCallback(LLUICtrl* ctrl, void *data);
+ static void onBackBtn(void* data);
+ static void onForwardBtn(void* data);
+ static void onCommitMature(LLUICtrl* ctrl, void* data);
+
+protected:
+ S32 mDay; // 0 = today, 1 = tomorrow
+};
+
+
+#endif
diff --git a/indra/newview/llpaneldirgroups.cpp b/indra/newview/llpaneldirgroups.cpp
new file mode 100644
index 0000000000..992d92091c
--- /dev/null
+++ b/indra/newview/llpaneldirgroups.cpp
@@ -0,0 +1,90 @@
+/**
+ * @file llpaneldirgroups.cpp
+ * @brief Groups panel in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpaneldirgroups.h"
+
+#include "llagent.h"
+#include "llqueryflags.h"
+#include "llviewercontrol.h"
+#include "llsearcheditor.h"
+
+static LLPanelInjector<LLPanelDirGroups> t_panel_dir_groups("panel_dir_groups");
+
+LLPanelDirGroups::LLPanelDirGroups()
+ : LLPanelDirBrowser()
+{
+ mMinSearchChars = 3;
+}
+
+
+bool LLPanelDirGroups::postBuild()
+{
+ LLPanelDirBrowser::postBuild();
+
+ //getChild<LLLineEditor>("name")->setKeystrokeCallback(boost::bind(&LLPanelDirBrowser::onKeystrokeName, _1, _2), NULL);
+
+ childSetAction("Search", &LLPanelDirBrowser::onClickSearchCore, this);
+ setDefaultBtn( "Search" );
+
+ return true;
+}
+
+LLPanelDirGroups::~LLPanelDirGroups()
+{
+}
+
+// virtual
+void LLPanelDirGroups::performQuery()
+{
+ if (childGetValue("name").asString().length() < mMinSearchChars)
+ {
+ return;
+ }
+
+ setupNewSearch();
+
+ // groups
+ U32 scope = DFQ_GROUPS;
+
+ // Check group mature filter.
+ if ( !gSavedSettings.getBOOL("ShowMatureGroups") || gAgent.isTeen() )
+ {
+ scope |= DFQ_FILTER_MATURE;
+ }
+
+ mCurrentSortColumn = "score";
+ mCurrentSortAscending = false;
+
+ // send the message
+ sendDirFindQuery(
+ gMessageSystem,
+ mSearchID,
+ childGetValue("name").asString(),
+ scope,
+ mSearchStart);
+}
diff --git a/indra/newview/llpaneldirgroups.h b/indra/newview/llpaneldirgroups.h
new file mode 100644
index 0000000000..1e10353e2a
--- /dev/null
+++ b/indra/newview/llpaneldirgroups.h
@@ -0,0 +1,45 @@
+/**
+ * @file llpaneldirgroups.h
+ * @brief Groups panel in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LLPANELDIRGROUPS_H
+#define LLPANELDIRGROUPS_H
+
+#include "llpaneldirbrowser.h"
+
+class LLPanelDirGroups : public LLPanelDirBrowser
+{
+public:
+ LLPanelDirGroups();
+ virtual ~LLPanelDirGroups();
+
+ /*virtual*/ bool postBuild();
+
+ /*virtual*/ void performQuery();
+
+ static void onClickSearch(void *userdata);
+};
+
+#endif
diff --git a/indra/newview/llpaneldirland.cpp b/indra/newview/llpaneldirland.cpp
new file mode 100644
index 0000000000..c4809fc2a6
--- /dev/null
+++ b/indra/newview/llpaneldirland.cpp
@@ -0,0 +1,247 @@
+/**
+ * @file llpaneldirland.cpp
+ * @brief Land panel in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpaneldirland.h"
+
+#include "llagent.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "lllineeditor.h"
+#include "llnotificationsutil.h"
+#include "llqueryflags.h"
+#include "llscrolllistctrl.h"
+#include "llstatusbar.h"
+#include "lltextbox.h"
+#include "llviewercontrol.h"
+#include "llviewermessage.h"
+
+//-----------------------------------------------------------------------------
+// Constants
+//-----------------------------------------------------------------------------
+
+static const char FIND_ALL[] = "All Types";
+static const char FIND_AUCTION[] = "Auction";
+static const char FIND_MAINLANDSALES[] = "Mainland Sales";
+static const char FIND_ESTATESALES[] = "Estate Sales";
+
+static LLPanelInjector<LLPanelDirLand> t_panel_dir_land("panel_dir_land");
+
+LLPanelDirLand::LLPanelDirLand()
+ : LLPanelDirBrowser()
+{
+}
+
+bool LLPanelDirLand::postBuild()
+{
+ LLPanelDirBrowser::postBuild();
+
+ childSetValue("type", gSavedSettings.getString("FindLandType"));
+
+ bool adult_enabled = gAgent.canAccessAdult();
+ bool mature_enabled = gAgent.canAccessMature();
+ childSetVisible("incpg", true);
+ if (!mature_enabled)
+ {
+ childSetValue("incmature", FALSE);
+ childDisable("incmature");
+ }
+ if (!adult_enabled)
+ {
+ childSetValue("incadult", FALSE);
+ childDisable("incadult");
+ }
+
+ childSetCommitCallback("pricecheck", onCommitPrice, this);
+ childSetCommitCallback("areacheck", onCommitArea, this);
+
+ if (gStatusBar)
+ {
+ childSetValue("priceedit", gStatusBar->getBalance());
+ }
+ childSetEnabled("priceedit", gSavedSettings.getBOOL("FindLandPrice"));
+ LLLineEditor* priceedit = getChild<LLLineEditor>("priceedit");
+ priceedit->setPrevalidateInput(LLTextValidate::validateNonNegativeS32);
+
+ childSetEnabled("areaedit", gSavedSettings.getBOOL("FindLandArea"));
+ LLLineEditor* areaedit = getChild<LLLineEditor>("areaedit");
+ areaedit->setPrevalidateInput(LLTextValidate::validateNonNegativeS32);
+
+ childSetAction("Search", onClickSearchCore, this);
+ setDefaultBtn("Search");
+
+ mCurrentSortColumn = "per_meter";
+
+ LLScrollListCtrl* results = getChild<LLScrollListCtrl>("results");
+ if (results)
+ {
+ results->setSortChangedCallback(boost::bind(&LLPanelDirLand::onClickSort, this));
+ results->sortByColumn(mCurrentSortColumn,mCurrentSortAscending);
+ }
+
+ return TRUE;
+}
+
+LLPanelDirLand::~LLPanelDirLand()
+{
+ // Children all cleaned up by default view destructor.
+}
+
+void LLPanelDirLand::onClickSort()
+{
+ performQuery();
+}
+
+// static
+void LLPanelDirLand::onCommitPrice(LLUICtrl* ctrl, void* data)
+{
+ LLPanelDirLand* self = (LLPanelDirLand*)data;
+ LLCheckBoxCtrl* check = (LLCheckBoxCtrl*)ctrl;
+
+ if (!self || !check) return;
+ self->childSetEnabled("priceedit", check->get());
+}
+
+// static
+void LLPanelDirLand::onCommitArea(LLUICtrl* ctrl, void* data)
+{
+ LLPanelDirLand* self = (LLPanelDirLand*)data;
+ LLCheckBoxCtrl* check = (LLCheckBoxCtrl*)ctrl;
+
+ if (!self || !check) return;
+ self->childSetEnabled("areaedit", check->get());
+}
+
+void LLPanelDirLand::performQuery()
+{
+ static LLUICachedControl<bool> inc_pg("ShowPGLand", true);
+ static LLUICachedControl<bool> inc_mature("ShowMatureLand", false);
+ static LLUICachedControl<bool> inc_adult("ShowAdultLand", false);
+ if (!(inc_pg || inc_mature || inc_adult))
+ {
+ LLNotificationsUtil::add("NoContentToSearch");
+ return;
+ }
+
+ LLMessageSystem* msg = gMessageSystem;
+
+ setupNewSearch();
+
+ // We could change the UI to allow arbitrary combinations of these options
+ U32 search_type = ST_ALL;
+ const std::string& type = childGetValue("type").asString();
+ if(!type.empty())
+ {
+ if (FIND_AUCTION == type) search_type = ST_AUCTION;
+ else if(FIND_MAINLANDSALES == type) search_type = ST_MAINLAND;
+ else if(FIND_ESTATESALES == type) search_type = ST_ESTATE;
+ }
+
+ U32 query_flags = 0x0;
+ if (gAgent.wantsPGOnly()) query_flags |= DFQ_PG_SIMS_ONLY;
+
+ bool adult_enabled = gAgent.canAccessAdult();
+ bool mature_enabled = gAgent.canAccessMature();
+
+ if (inc_pg)
+ {
+ query_flags |= DFQ_INC_PG;
+ }
+
+ if (inc_mature && mature_enabled)
+ {
+ query_flags |= DFQ_INC_MATURE;
+ }
+
+ if (inc_adult && adult_enabled)
+ {
+ query_flags |= DFQ_INC_ADULT;
+ }
+
+ // Add old flags in case we are talking to an old dataserver
+ if (inc_pg && !inc_mature)
+ {
+ query_flags |= DFQ_PG_SIMS_ONLY;
+ }
+
+ if (!inc_pg && inc_mature)
+ {
+ query_flags |= DFQ_MATURE_SIMS_ONLY;
+ }
+
+ LLScrollListCtrl* list = getChild<LLScrollListCtrl>("results");
+ if (list)
+ {
+ std::string sort_name = list->getSortColumnName();
+ BOOL sort_asc = list->getSortAscending();
+
+ if (sort_name == "name")
+ {
+ query_flags |= DFQ_NAME_SORT;
+ }
+ else if (sort_name == "price")
+ {
+ query_flags |= DFQ_PRICE_SORT;
+ }
+ else if (sort_name == "per_meter")
+ {
+ query_flags |= DFQ_PER_METER_SORT;
+ }
+ else if (sort_name == "area")
+ {
+ query_flags |= DFQ_AREA_SORT;
+ }
+
+ if (sort_asc)
+ {
+ query_flags |= DFQ_SORT_ASC;
+ }
+ }
+
+ if (childGetValue("pricecheck").asBoolean())
+ {
+ query_flags |= DFQ_LIMIT_BY_PRICE;
+ }
+
+ if (childGetValue("areacheck").asBoolean())
+ {
+ query_flags |= DFQ_LIMIT_BY_AREA;
+ }
+
+ msg->newMessage("DirLandQuery");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID());
+ msg->addUUID("SessionID", gAgent.getSessionID());
+ msg->nextBlock("QueryData");
+ msg->addUUID("QueryID", getSearchID());
+ msg->addU32("QueryFlags", query_flags);
+ msg->addU32("SearchType", search_type);
+ msg->addS32("Price", childGetValue("priceedit").asInteger());
+ msg->addS32("Area", childGetValue("areaedit").asInteger());
+ msg->addS32Fast(_PREHASH_QueryStart,mSearchStart);
+ gAgent.sendReliableMessage();
+}
diff --git a/indra/newview/llpaneldirland.h b/indra/newview/llpaneldirland.h
new file mode 100644
index 0000000000..197c4cdc3d
--- /dev/null
+++ b/indra/newview/llpaneldirland.h
@@ -0,0 +1,53 @@
+/**
+ * @file llpaneldirland.h
+ * @brief Land panel in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELDIRLAND_H
+#define LL_LLPANELDIRLAND_H
+
+#include "llpaneldirbrowser.h"
+
+class LLUICtrl;
+class LLPanelDirBrowser;
+
+class LLPanelDirLand : public LLPanelDirBrowser
+{
+public:
+ LLPanelDirLand();
+ /*virtual*/ ~LLPanelDirLand();
+
+ bool postBuild();
+
+ void performQuery();
+
+protected:
+ void onClickSort();
+ static void onCommitPrice(LLUICtrl* ctrl, void* data);
+ static void onCommitArea(LLUICtrl* ctrl, void* data);
+
+};
+
+
+#endif
diff --git a/indra/newview/llpaneldirpeople.cpp b/indra/newview/llpaneldirpeople.cpp
new file mode 100644
index 0000000000..6a55e3bc7c
--- /dev/null
+++ b/indra/newview/llpaneldirpeople.cpp
@@ -0,0 +1,105 @@
+/**
+ * @file llpaneldirpeople.cpp
+ * @brief People panel in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpaneldirpeople.h"
+#include "llviewerwindow.h"
+#include "llsearcheditor.h"
+
+// viewer project includes
+#include "llqueryflags.h"
+#include "llnotificationsutil.h"
+
+static LLPanelInjector<LLPanelDirPeople> t_panel_dir_people("panel_dir_people");
+
+LLPanelDirPeople::LLPanelDirPeople()
+: LLPanelDirBrowser()
+{
+ mMinSearchChars = 3;
+}
+
+bool LLPanelDirPeople::postBuild()
+{
+ LLPanelDirBrowser::postBuild();
+
+ //getChild<LLLineEditor>("name")->setKeystrokeCallback(boost::bind(&LLPanelDirBrowser::onKeystrokeName, _1, _2), NULL);
+
+ childSetAction("Search", &LLPanelDirBrowser::onClickSearchCore, this);
+ setDefaultBtn( "Search" );
+
+ return true;
+}
+
+LLPanelDirPeople::~LLPanelDirPeople()
+{
+}
+
+// virtual
+void LLPanelDirPeople::performQuery()
+{
+ if (childGetValue("name").asString().length() < mMinSearchChars)
+ {
+ return;
+ }
+
+ // filter short words out of the query string
+ // and indidate if we did have to filter it
+ // The shortest username is 2 characters long.
+ const S32 SHORTEST_WORD_LEN = 2;
+ bool query_was_filtered = false;
+ std::string query_string = LLPanelDirBrowser::filterShortWords(
+ childGetValue("name").asString(),
+ SHORTEST_WORD_LEN,
+ query_was_filtered );
+
+ // possible we threw away all the short words in the query so check length
+ if ( query_string.length() < mMinSearchChars )
+ {
+ LLNotificationsUtil::add("SeachFilteredOnShortWordsEmpty");
+ return;
+ };
+
+ // if we filtered something out, display a popup
+ if ( query_was_filtered )
+ {
+ LLSD args;
+ args["FINALQUERY"] = query_string;
+ LLNotificationsUtil::add("SeachFilteredOnShortWords", args);
+ };
+
+ setupNewSearch();
+
+ U32 scope = DFQ_PEOPLE;
+
+ // send the message
+ sendDirFindQuery(
+ gMessageSystem,
+ mSearchID,
+ query_string,
+ scope,
+ mSearchStart);
+}
diff --git a/indra/newview/llpaneldirpeople.h b/indra/newview/llpaneldirpeople.h
new file mode 100644
index 0000000000..a8a7d17cb2
--- /dev/null
+++ b/indra/newview/llpaneldirpeople.h
@@ -0,0 +1,48 @@
+/**
+ * @file llpaneldirpeople.h
+ * @brief People panel in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELDIRPEOPLE_H
+#define LL_LLPANELDIRPEOPLE_H
+
+#include "llpaneldirbrowser.h"
+class LLLineEditor;
+class LLFloaterDirectory;
+
+class LLPanelDirPeople : public LLPanelDirBrowser
+{
+public:
+ LLPanelDirPeople();
+ virtual ~LLPanelDirPeople();
+
+ /*virtual*/ bool postBuild();
+
+ /*virtual*/ void performQuery();
+
+ static void onClickSearch(void *userdata);
+ static void onKeystrokeName(LLLineEditor* line, void* data);
+};
+
+#endif
diff --git a/indra/newview/llpaneldirplaces.cpp b/indra/newview/llpaneldirplaces.cpp
new file mode 100644
index 0000000000..2d54566038
--- /dev/null
+++ b/indra/newview/llpaneldirplaces.cpp
@@ -0,0 +1,185 @@
+/**
+ * @file llpaneldirplaces.cpp
+ * @brief Places panel in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpaneldirplaces.h"
+
+#include "message.h"
+#include "llparcel.h"
+#include "llregionflags.h"
+#include "llqueryflags.h"
+
+#include "llagent.h"
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "llcombobox.h"
+#include "llfloaterdirectory.h"
+#include "lllineeditor.h"
+#include "llnotificationsutil.h"
+#include "llpaneldirbrowser.h"
+#include "llsearcheditor.h"
+#include "lltextbox.h"
+#include "llviewercontrol.h"
+
+static LLPanelInjector<LLPanelDirPlaces> t_panel_dir_people("panel_dir_places");
+
+LLPanelDirPlaces::LLPanelDirPlaces()
+ : LLPanelDirBrowser()
+{
+ mMinSearchChars = 3;
+}
+
+bool LLPanelDirPlaces::postBuild()
+{
+ LLPanelDirBrowser::postBuild();
+
+ //getChild<LLLineEditor>("name")->setKeystrokeCallback(boost::bind(&LLPanelDirBrowser::onKeystrokeName, _1, _2), NULL);
+
+ childSetAction("Search", &LLPanelDirBrowser::onClickSearchCore, this);
+ setDefaultBtn("Search");
+
+ mCurrentSortColumn = "dwell";
+ mCurrentSortAscending = false;
+
+ return true;
+}
+
+LLPanelDirPlaces::~LLPanelDirPlaces()
+{
+}
+
+// virtual
+void LLPanelDirPlaces::performQuery()
+{
+ std::string place_name = childGetValue("name").asString();
+ if (place_name.length() < mMinSearchChars)
+ {
+ return;
+ }
+
+ // "hi " is three chars but not a long-enough search
+ std::string query_string = place_name;
+ LLStringUtil::trim( query_string );
+ bool query_was_filtered = (query_string != place_name);
+
+ // possible we threw away all the short words in the query so check length
+ if ( query_string.length() < mMinSearchChars )
+ {
+ LLNotificationsUtil::add("SeachFilteredOnShortWordsEmpty");
+ return;
+ };
+
+ // if we filtered something out, display a popup
+ if ( query_was_filtered )
+ {
+ LLSD args;
+ args["FINALQUERY"] = query_string;
+ LLNotificationsUtil::add("SeachFilteredOnShortWords", args);
+ };
+
+ std::string catstring = childGetValue("Category").asString();
+
+ // Because LLParcel::C_ANY is -1, must do special check
+ S32 category = 0;
+ if (catstring == "any")
+ {
+ category = LLParcel::C_ANY;
+ }
+ else
+ {
+ category = LLParcel::getCategoryFromString(catstring);
+ }
+
+ U32 flags = 0x0;
+ bool adult_enabled = gAgent.canAccessAdult();
+ bool mature_enabled = gAgent.canAccessMature();
+
+ static LLUICachedControl<bool> inc_pg("ShowPGSims", true);
+ static LLUICachedControl<bool> inc_mature("ShowMatureSims", false);
+ static LLUICachedControl<bool> inc_adult("ShowAdultSims", false);
+
+ if (inc_pg)
+ {
+ flags |= DFQ_INC_PG;
+ }
+
+ if (inc_mature && mature_enabled)
+ {
+ flags |= DFQ_INC_MATURE;
+ }
+
+ if (inc_adult && adult_enabled)
+ {
+ flags |= DFQ_INC_ADULT;
+ }
+
+ if (0x0 == flags)
+ {
+ LLNotificationsUtil::add("NoContentToSearch");
+ return;
+ }
+
+ queryCore(query_string, category, flags);
+}
+
+void LLPanelDirPlaces::initialQuery()
+{
+ // All Linden locations in PG/Mature sims, any name.
+ U32 flags = DFQ_INC_PG | DFQ_INC_MATURE;
+ queryCore(LLStringUtil::null, LLParcel::C_LINDEN, flags);
+}
+
+void LLPanelDirPlaces::queryCore(const std::string& name, S32 category, U32 flags)
+{
+ setupNewSearch();
+
+// JC: Sorting by dwell severely impacts the performance of the query.
+// Instead of sorting on the dataserver, we sort locally once the results
+// are received.
+// IW: Re-enabled dwell sort based on new 3-character minimum description
+// Hopefully we'll move to next-gen Find before this becomes a big problem
+
+ flags |= DFQ_DWELL_SORT;
+
+ LLMessageSystem* msg = gMessageSystem;
+
+ msg->newMessage("DirPlacesQuery");
+ msg->nextBlock("AgentData");
+ msg->addUUID("AgentID", gAgent.getID());
+ msg->addUUID("SessionID", gAgent.getSessionID());
+ msg->nextBlock("QueryData");
+ msg->addUUID("QueryID", getSearchID());
+ msg->addString("QueryText", name);
+ msg->addU32("QueryFlags", flags);
+ msg->addS8("Category", (S8)category);
+ // No longer support queries by region name, too many regions
+ // for combobox, no easy way to do autocomplete. JC
+ msg->addString("SimName", "");
+ msg->addS32Fast(_PREHASH_QueryStart,mSearchStart);
+ gAgent.sendReliableMessage();
+}
+
diff --git a/indra/newview/llpaneldirplaces.h b/indra/newview/llpaneldirplaces.h
new file mode 100644
index 0000000000..069414ebf5
--- /dev/null
+++ b/indra/newview/llpaneldirplaces.h
@@ -0,0 +1,51 @@
+/**
+ * @file llpaneldirplaces.h
+ * @brief Places panel in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELDIRPLACES_H
+#define LL_LLPANELDIRPLACES_H
+
+#include "llpaneldirbrowser.h"
+
+class LLLineEditor;
+
+class LLPanelDirPlaces : public LLPanelDirBrowser
+{
+public:
+ LLPanelDirPlaces();
+ virtual ~LLPanelDirPlaces();
+
+ bool postBuild() override;
+
+ void performQuery() override;
+
+ // Initially fill in some data for the panel.
+ void initialQuery();
+
+private:
+ void queryCore(const std::string& name, S32 category, U32 flags);
+};
+
+#endif
diff --git a/indra/newview/llpaneldirweb.cpp b/indra/newview/llpaneldirweb.cpp
new file mode 100644
index 0000000000..9e76bb81a6
--- /dev/null
+++ b/indra/newview/llpaneldirweb.cpp
@@ -0,0 +1,148 @@
+/**
+ * @file llpaneldirweb.cpp
+ * @brief Web panel in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpaneldirweb.h"
+
+#include "llagent.h"
+#include "llbutton.h"
+#include "llfloaterdirectory.h"
+#include "lltextbox.h"
+#include "llviewercontrol.h"
+#include "llweb.h"
+
+static LLPanelInjector<LLPanelDirWeb> t_panel_dir_web("panel_dir_web");
+
+LLPanelDirWeb::LLPanelDirWeb()
+: LLPanel(),
+ mFloaterDirectory(nullptr),
+ mWebBrowser(nullptr)
+{
+}
+
+bool LLPanelDirWeb::postBuild()
+{
+ childSetAction("home_btn", onClickHome, this);
+
+ mBtnBack = getChild<LLButton>("back_btn");
+ mBtnForward = getChild<LLButton>("forward_btn");
+ mStatusBarText = getChild<LLTextBox>("statusbartext");
+
+ mBtnBack->setClickedCallback([this](LLUICtrl*, const LLSD&) { mWebBrowser->navigateBack(); });
+ mBtnForward->setClickedCallback([this](LLUICtrl*, const LLSD&) { mWebBrowser->navigateForward(); });
+
+ mWebBrowser = findChild<LLMediaCtrl>("web_search");
+ navigateToDefaultPage();
+ mWebBrowser->addObserver(this);
+
+ return true;
+}
+
+void LLPanelDirWeb::draw()
+{
+ // Asynchronous so we need to keep checking
+ mBtnBack->setEnabled(mWebBrowser->canNavigateBack());
+ mBtnForward->setEnabled(mWebBrowser->canNavigateForward());
+
+ LLPanel::draw();
+}
+
+LLPanelDirWeb::~LLPanelDirWeb()
+{
+}
+
+// When we show any browser-based view, we want to hide all
+// the right-side XUI detail panels.
+// virtual
+void LLPanelDirWeb::onVisibilityChange(bool new_visibility)
+{
+ if (new_visibility && mFloaterDirectory)
+ {
+ mFloaterDirectory->hideAllDetailPanels();
+ }
+ LLPanel::onVisibilityChange(new_visibility);
+}
+
+void LLPanelDirWeb::navigateToDefaultPage()
+{
+ std::string url = gSavedSettings.getString("SearchURL");
+
+ LLSD subs;
+ subs["QUERY"] = "";
+ subs["TYPE"] = "standard";
+ // Default to PG
+ std::string maturity = "g";
+ if (gAgent.prefersAdult())
+ {
+ // PG,Mature,Adult
+ maturity = "gma";
+ }
+ else if (gAgent.prefersMature())
+ {
+ // PG,Mature
+ maturity = "gm";
+ }
+ subs["MATURITY"] = maturity;
+ url = LLWeb::expandURLSubstitutions(url, subs);
+ mWebBrowser->navigateTo(url, HTTP_CONTENT_TEXT_HTML);
+}
+
+// static
+void LLPanelDirWeb::onClickHome( void* data )
+{
+ LLPanelDirWeb* self = (LLPanelDirWeb*)data;
+ if (!self)
+ return;
+ self->navigateToDefaultPage();
+}
+
+void LLPanelDirWeb::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
+{
+ if (event == MEDIA_EVENT_LOCATION_CHANGED)
+ {
+ const std::string url = self->getLocation();
+ if (url.length())
+ mStatusBarText->setText(url);
+ }
+ else if (event == MEDIA_EVENT_NAVIGATE_COMPLETE)
+ {
+ // we populate the status bar with URLs as they change so clear it now we're done
+ const std::string end_str = "";
+ mStatusBarText->setText(end_str);
+ }
+ else if (event == MEDIA_EVENT_STATUS_TEXT_CHANGED)
+ {
+ const std::string text = self->getStatusText();
+ if (text.length())
+ mStatusBarText->setText(text);
+ }
+ else if (event == MEDIA_EVENT_LINK_HOVERED)
+ {
+ const std::string link = self->getHoverLink();
+ mStatusBarText->setText(link);
+ }
+}
diff --git a/indra/newview/llpaneldirweb.h b/indra/newview/llpaneldirweb.h
new file mode 100644
index 0000000000..db7bdc4a6a
--- /dev/null
+++ b/indra/newview/llpaneldirweb.h
@@ -0,0 +1,63 @@
+/**
+ * @file llpaneldirweb.h
+ * @brief Web panel in the legacy Search directory.
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELDIRWEB_H
+#define LL_LLPANELDIRWEB_H
+
+#include "llpanel.h"
+#include "llmediactrl.h"
+
+class LLTextBox;
+class LLFloaterDirectory;
+class LLWebBrowserCtrlObserver;
+
+class LLPanelDirWeb : public LLPanel, public LLViewerMediaObserver
+{
+public:
+ LLPanelDirWeb();
+ ~LLPanelDirWeb();
+
+ bool postBuild() override;
+ void onVisibilityChange(bool new_visibility) override;
+ void draw() override;
+
+ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) override;
+
+ void navigateToDefaultPage();
+
+ void setFloaterDirectory(LLFloaterDirectory* floater) { mFloaterDirectory = floater; }
+
+protected:
+ static void onClickHome( void* data );
+
+ LLButton* mBtnBack;
+ LLButton* mBtnForward;
+ LLTextBox* mStatusBarText;
+ LLFloaterDirectory* mFloaterDirectory;
+ LLMediaCtrl* mWebBrowser;
+};
+
+#endif
diff --git a/indra/newview/llpaneleventinfo.cpp b/indra/newview/llpaneleventinfo.cpp
new file mode 100644
index 0000000000..43b20b3851
--- /dev/null
+++ b/indra/newview/llpaneleventinfo.cpp
@@ -0,0 +1,195 @@
+/**
+ * @file llpaneleventinfo.cpp
+ * @brief Info panel for events in the legacy Search
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpaneleventinfo.h"
+
+#include "llagent.h"
+#include "llbutton.h"
+#include "lleventflags.h"
+#include "llfloaterreg.h"
+#include "llfloaterworldmap.h"
+#include "lltextbox.h"
+#include "llviewertexteditor.h"
+#include "llworldmap.h"
+
+static LLPanelInjector<LLPanelEventInfo> t_panel_event_info("panel_event_info");
+
+LLPanelEventInfo::LLPanelEventInfo()
+ : LLPanel()
+{
+}
+
+LLPanelEventInfo::~LLPanelEventInfo()
+{
+ if (mEventInfoConnection.connected())
+ {
+ mEventInfoConnection.disconnect();
+ }
+}
+
+bool LLPanelEventInfo::postBuild()
+{
+ mTBName = getChild<LLTextBox>("event_name");
+
+ mTBCategory = getChild<LLTextBox>("event_category");
+ mTBDate = getChild<LLTextBox>("event_date");
+ mTBDuration = getChild<LLTextBox>("event_duration");
+ mTBDesc = getChild<LLTextEditor>("event_desc");
+ mTBDesc->setWordWrap(true);
+
+ mTBRunBy = getChild<LLTextBox>("event_runby");
+ mTBLocation = getChild<LLTextBox>("event_location");
+ mTBCover = getChild<LLTextBox>("event_cover");
+
+ mTeleportBtn = getChild<LLButton>( "teleport_btn");
+ mTeleportBtn->setClickedCallback(boost::bind(&LLPanelEventInfo::onClickTeleport, this));
+
+ mMapBtn = getChild<LLButton>( "map_btn");
+ mMapBtn->setClickedCallback(boost::bind(&LLPanelEventInfo::onClickMap, this));
+
+ mNotifyBtn = getChild<LLButton>( "notify_btn");
+ mNotifyBtn->setClickedCallback(boost::bind(&LLPanelEventInfo::onClickNotify, this));
+
+ mEventInfoConnection = gEventNotifier.setEventInfoCallback(boost::bind(&LLPanelEventInfo::processEventInfoReply, this, _1));
+
+ return true;
+}
+
+void LLPanelEventInfo::setEventID(const U32 event_id)
+{
+ mEventID = event_id;
+
+ if (event_id != 0)
+ {
+ sendEventInfoRequest();
+ }
+}
+
+void LLPanelEventInfo::sendEventInfoRequest()
+{
+ LLMessageSystem *msg = gMessageSystem;
+
+ msg->newMessageFast(_PREHASH_EventInfoRequest);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
+ msg->nextBlockFast(_PREHASH_EventData);
+ msg->addU32Fast(_PREHASH_EventID, mEventID);
+ gAgent.sendReliableMessage();
+}
+
+bool LLPanelEventInfo::processEventInfoReply(LLEventInfo event)
+{
+ if (event.mID != getEventID())
+ return false;
+
+ mTBName->setText(event.mName);
+ mTBName->setToolTip(event.mName);
+ mTBCategory->setText(event.mCategoryStr);
+ mTBDate->setText(event.mTimeStr);
+ mTBDesc->setText(event.mDesc);
+ mTBRunBy->setText(LLSLURL("agent", event.mRunByID, "inspect").getSLURLString());
+
+ mTBDuration->setText(llformat("%d:%.2d", event.mDuration / 60, event.mDuration % 60));
+
+ if (!event.mHasCover)
+ {
+ mTBCover->setText(getString("none"));
+ }
+ else
+ {
+ mTBCover->setText(llformat("%d", event.mCover));
+ }
+
+ mTBLocation->setText(LLSLURL(event.mSimName, event.mPosGlobal).getSLURLString());
+
+ if (event.mEventFlags & EVENT_FLAG_MATURE)
+ {
+ childSetVisible("event_mature_yes", true);
+ childSetVisible("event_mature_no", false);
+ }
+ else
+ {
+ childSetVisible("event_mature_yes", false);
+ childSetVisible("event_mature_no", true);
+ }
+
+ if (event.mUnixTime < time_corrected())
+ {
+ mNotifyBtn->setEnabled(false);
+ }
+ else
+ {
+ mNotifyBtn->setEnabled(true);
+ }
+
+ if (gEventNotifier.hasNotification(event.mID))
+ {
+ mNotifyBtn->setLabel(getString("dont_notify"));
+ }
+ else
+ {
+ mNotifyBtn->setLabel(getString("notify"));
+ }
+ mEventInfo = event;
+ return true;
+}
+
+void LLPanelEventInfo::onClickTeleport()
+{
+ LLFloaterWorldMap* world_map = LLFloaterWorldMap::getInstance();
+ if (world_map)
+ {
+ world_map->trackLocation(mEventInfo.mPosGlobal);
+ gAgent.teleportViaLocation(mEventInfo.mPosGlobal);
+ }
+}
+
+void LLPanelEventInfo::onClickMap()
+{
+ LLFloaterWorldMap* world_map = LLFloaterWorldMap::getInstance();
+ if (world_map)
+ {
+ world_map->trackLocation(mEventInfo.mPosGlobal);
+ LLFloaterReg::showInstance("world_map", "center");
+ }
+}
+
+void LLPanelEventInfo::onClickNotify()
+{
+ if (!gEventNotifier.hasNotification(mEventID))
+ {
+ gEventNotifier.add(mEventInfo.mID, mEventInfo.mUnixTime, mEventInfo.mTimeStr, mEventInfo.mName);
+ mNotifyBtn->setLabel(getString("dont_notify"));
+ }
+ else
+ {
+ gEventNotifier.remove(mEventInfo.mID);
+ mNotifyBtn->setLabel(getString("notify"));
+ }
+}
diff --git a/indra/newview/llpaneleventinfo.h b/indra/newview/llpaneleventinfo.h
new file mode 100644
index 0000000000..4f0e547493
--- /dev/null
+++ b/indra/newview/llpaneleventinfo.h
@@ -0,0 +1,76 @@
+/**
+ * @file llpaneleventinfo.h
+ * @brief Info panel for events in the legacy Search
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * 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
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELEVENTINFO_H
+#define LL_LLPANELEVENTINFO_H
+
+#include "lleventnotifier.h"
+
+class LLTextBox;
+class LLTextEditor;
+class LLButton;
+
+class LLPanelEventInfo : public LLPanel
+{
+public:
+ LLPanelEventInfo();
+ /*virtual*/ ~LLPanelEventInfo();
+
+ /*virtual*/ bool postBuild() override;
+
+ void setEventID(const U32 event_id);
+ void sendEventInfoRequest();
+
+ bool processEventInfoReply(LLEventInfo event);
+
+ U32 getEventID() { return mEventID; }
+
+protected:
+ void onClickTeleport();
+ void onClickMap();
+ void onClickNotify();
+
+protected:
+ LLTextBox* mTBName;
+ LLTextBox* mTBCategory;
+ LLTextBox* mTBDate;
+ LLTextBox* mTBDuration;
+ LLTextEditor* mTBDesc;
+
+ LLTextBox* mTBRunBy;
+ LLTextBox* mTBLocation;
+ LLTextBox* mTBCover;
+
+ LLButton* mTeleportBtn;
+ LLButton* mMapBtn;
+ LLButton* mNotifyBtn;
+
+ U32 mEventID;
+ LLEventInfo mEventInfo;
+ boost::signals2::connection mEventInfoConnection;
+};
+
+#endif // LL_LLPANELEVENTINFO_H
diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp
index 65aa1876b0..ecb66f9cea 100644
--- a/indra/newview/llpanelgroup.cpp
+++ b/indra/newview/llpanelgroup.cpp
@@ -231,6 +231,12 @@ void LLPanelGroup::onBackBtnClick()
}
}
+void LLPanelGroup::hideBackBtn()
+{
+ childSetVisible("back", false);
+ setBackgroundVisible(false);
+}
+
void LLPanelGroup::onBtnRefresh(void* user_data)
{
LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h
index fa0e1d4104..b43a93bc40 100644
--- a/indra/newview/llpanelgroup.h
+++ b/indra/newview/llpanelgroup.h
@@ -87,6 +87,7 @@ public:
const std::string& inventory_name,
LLOfferInfo* inventory_offer);
+ void hideBackBtn();
protected:
virtual void update(LLGroupChange gc);
diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp
index 7deb1d9fd4..5435a79e16 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -651,7 +651,7 @@ void LLPanelPlaces::onFilterEdit(const std::string& search_string, bool force_fi
void LLPanelPlaces::onTabSelected()
{
mActivePanel = dynamic_cast<LLPanelPlacesTab*>(mTabContainer->getCurrentPanel());
- if (!mActivePanel)
+ if (!mActivePanel || !mTabsCreated)
return;
onFilterEdit(mActivePanel->getFilterSubString(), true);
@@ -1335,6 +1335,13 @@ LLPanelPlaceInfo* LLPanelPlaces::getCurrentInfoPanel()
return NULL;
}
+void LLPanelPlaces::hideBackBtn()
+{
+ mPlaceProfileBackBtn->setVisible(false);
+ setBackgroundVisible(false);
+ mPlaceProfile->setBackgroundVisible(false);
+}
+
static bool is_agent_in_selected_parcel(LLParcel* parcel)
{
LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h
index fc04d8d45d..8360380b22 100644
--- a/indra/newview/llpanelplaces.h
+++ b/indra/newview/llpanelplaces.h
@@ -81,6 +81,8 @@ public:
/*virtual*/ S32 notifyParent(const LLSD& info);
+ void hideBackBtn();
+
private:
void onLandmarkLoaded(LLLandmark* landmark);
void onFilterEdit(const std::string& search_string, bool force_filter);
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index 6ea9cd2b92..ee94277ecc 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -693,6 +693,7 @@ LLPanelProfileSecondLife::LLPanelProfileSecondLife()
, mWaitingForImageUpload(false)
, mAllowPublish(false)
, mHideAge(false)
+ , mAllowEdit(true)
{
}
@@ -757,14 +758,15 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key)
LLUUID avatar_id = getAvatarId();
bool own_profile = getSelfProfile();
+ bool allow_edit = own_profile && mAllowEdit;
mGroupList->setShowNone(!own_profile);
- childSetVisible("notes_panel", !own_profile);
- childSetVisible("settings_panel", own_profile);
- childSetVisible("about_buttons_panel", own_profile);
+ childSetVisible("notes_panel", !allow_edit);
+ childSetVisible("settings_panel", allow_edit);
+ childSetVisible("about_buttons_panel", allow_edit);
- if (own_profile)
+ if (allow_edit)
{
// Group list control cannot toggle ForAgent loading
// Less than ideal, but viewing own profile via search is edge case
@@ -789,7 +791,7 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key)
mAgentActionMenuButton->setMenu("menu_profile_other.xml", LLMenuButton::MP_BOTTOM_RIGHT);
}
- mDescriptionEdit->setParseHTML(!own_profile);
+ mDescriptionEdit->setParseHTML(!allow_edit);
if (!own_profile)
{
@@ -1280,7 +1282,7 @@ void LLPanelProfileSecondLife::setLoaded()
{
mHideAgeCombo->setEnabled(true);
}
- mDescriptionEdit->setEnabled(true);
+ mDescriptionEdit->setEnabled(mAllowEdit);
}
}
diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h
index c207a4162a..f2e9c1341f 100644
--- a/indra/newview/llpanelprofile.h
+++ b/indra/newview/llpanelprofile.h
@@ -111,6 +111,8 @@ public:
void processProperties(void* data, EAvatarProcessorType type) override;
+ void setAllowEdit(bool allow_edit) { mAllowEdit = allow_edit; }
+
protected:
/**
* Process profile related data received from server.
@@ -207,6 +209,7 @@ private:
bool mWaitingForImageUpload;
bool mAllowPublish;
bool mHideAge;
+ bool mAllowEdit;
std::string mDescriptionText;
boost::signals2::connection mAvatarNameCacheConnection;
};
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 3786a9b160..cec34635f6 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -122,6 +122,7 @@
#include "llpanellogin.h"
#include "llmutelist.h"
#include "llavatarpropertiesprocessor.h"
+#include "llpaneldirbrowser.h"
#include "llpanelgrouplandmoney.h"
#include "llpanelgroupnotices.h"
#include "llparcel.h"
@@ -2871,6 +2872,13 @@ void register_viewer_callbacks(LLMessageSystem* msg)
msg->setHandlerFunc("AvatarPickerReply", LLFloaterAvatarPicker::processAvatarPickerReply);
+ msg->setHandlerFunc("DirPlacesReply", LLPanelDirBrowser::processDirPlacesReply);
+ msg->setHandlerFunc("DirPeopleReply", LLPanelDirBrowser::processDirPeopleReply);
+ msg->setHandlerFunc("DirEventsReply", LLPanelDirBrowser::processDirEventsReply);
+ msg->setHandlerFunc("DirGroupsReply", LLPanelDirBrowser::processDirGroupsReply);
+ msg->setHandlerFunc("DirClassifiedReply", LLPanelDirBrowser::processDirClassifiedReply);
+ msg->setHandlerFunc("DirLandReply", LLPanelDirBrowser::processDirLandReply);
+
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 3b35ca8db1..ab5235c3ad 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -67,6 +67,7 @@
#include "llfloatercreatelandmark.h"
#include "llfloaterdeleteprefpreset.h"
#include "llfloaterdestinations.h"
+#include "llfloaterdirectory.h"
#include "llfloaterdisplayname.h"
#include "llfloatereditextdaycycle.h"
#include "llfloateremojipicker.h"
@@ -231,7 +232,8 @@ public:
"upload_model",
"upload_script",
"upload_sound",
- "bulk_upload"
+ "bulk_upload",
+ "legacy_search"
};
return std::find(blacklist_clicked.begin(), blacklist_clicked.end(), fl_name) == blacklist_clicked.end();
}
@@ -283,7 +285,8 @@ public:
"upload_script",
"upload_sound",
"bulk_upload",
- "slapp_test"
+ "slapp_test",
+ "legacy_search"
};
return std::find(blacklist_untrusted.begin(), blacklist_untrusted.end(), fl_name) == blacklist_untrusted.end();
}
@@ -504,6 +507,7 @@ void LLViewerFloaterReg::registerFloaters()
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("legacy_search", "floater_directory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDirectory>);
LLFloaterReg::add("profile", "floater_profile.xml",(LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterProfile>);
LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHowTo>);
LLFloaterReg::add("slapp_test", "floater_test_slapp.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSLappTest>);
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..d121833b47
--- /dev/null
+++ b/indra/newview/skins/default/textures/icon_auction.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/icon_event.tga b/indra/newview/skins/default/textures/icon_event.tga
new file mode 100644
index 0000000000..7805dbce60
--- /dev/null
+++ b/indra/newview/skins/default/textures/icon_event.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/icon_event_adult.tga b/indra/newview/skins/default/textures/icon_event_adult.tga
new file mode 100644
index 0000000000..c344fb1e78
--- /dev/null
+++ b/indra/newview/skins/default/textures/icon_event_adult.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/icon_event_mature.tga b/indra/newview/skins/default/textures/icon_event_mature.tga
new file mode 100644
index 0000000000..61c879bc92
--- /dev/null
+++ b/indra/newview/skins/default/textures/icon_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..2170c98499
--- /dev/null
+++ b/indra/newview/skins/default/textures/icon_place.tga
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index d650e7e791..ff5737ab49 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -837,8 +837,14 @@ with the same filename but different name
<texture name="icon_avatar_online.tga" />
<texture name="icon_diurnal.tga" />
<texture name="icon_for_sale.tga" file_name="icons/Icon_For_Sale.png" />
+ <texture name="icon_auction.tga"/>
+ <texture name="icon_place.tga"/>
<texture name="icon_top_pick.tga" />
+ <texture name="icon_event.tga"/>
+ <texture name="icon_event_adult.tga"/>
+ <texture name="icon_event_mature.tga" />
+
<texture name="lag_status_critical.tga" />
<texture name="lag_status_good.tga" />
<texture name="lag_status_warning.tga" />
diff --git a/indra/newview/skins/default/xui/en/floater_directory.xml b/indra/newview/skins/default/xui/en/floater_directory.xml
new file mode 100644
index 0000000000..3274474337
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_directory.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ can_close="true"
+ can_drag_on_left="false"
+ single_instance="true"
+ can_resize="true"
+ height="570"
+ min_height="570"
+ width="780"
+ min_width="780"
+ name="directory"
+ title="Search">
+ <tab_container
+ top="0"
+ left="0"
+ follows="left|top|right|bottom"
+ height="550"
+ width="780"
+ mouse_opaque="false"
+ name="Directory Tabs"
+ tab_position="top">
+ <panel
+ border="false"
+ label="People"
+ filename="panel_dir_people.xml"
+ class="panel_dir_people"
+ name="panel_dir_people"
+ follows="left|top|right"
+ layout="topleft"
+ left="0"
+ top="0"
+ bottom="-1" />
+ <panel
+ border="false"
+ label="Groups"
+ filename="panel_dir_groups.xml"
+ class="panel_dir_groups"
+ name="panel_dir_groups"
+ follows="left|top|right"
+ layout="topleft"
+ left="0"
+ top="0"
+ bottom="-1" />
+ <panel
+ border="false"
+ label="Places"
+ filename="panel_dir_places.xml"
+ class="panel_dir_places"
+ name="panel_dir_places"
+ follows="left|top|right"
+ layout="topleft"
+ left="0"
+ top="0"
+ bottom="-1" />
+ <panel
+ border="false"
+ label="Land Sales"
+ filename="panel_dir_land.xml"
+ class="panel_dir_land"
+ name="panel_dir_land"
+ follows="left|top|right"
+ layout="topleft"
+ left="0"
+ top="0"
+ bottom="-1" />
+ <panel
+ border="false"
+ label="Events"
+ filename="panel_dir_events.xml"
+ class="panel_dir_events"
+ name="panel_dir_events"
+ follows="left|top|right"
+ layout="topleft"
+ left="0"
+ top="0"
+ bottom="-1" />
+ <panel
+ border="false"
+ label="Classifieds"
+ filename="panel_dir_classified.xml"
+ class="panel_dir_classified"
+ name="panel_dir_classified"
+ follows="left|top|right"
+ layout="topleft"
+ left="0"
+ top="0"
+ bottom="-1" />
+ <panel
+ border="false"
+ label="Web"
+ filename="panel_dir_web.xml"
+ class="panel_dir_web"
+ name="panel_dir_web"
+ follows="left|top|right"
+ layout="topleft"
+ left="0"
+ top="0"
+ bottom="-1" />
+</tab_container>
+ <panel
+ top="65"
+ follows="right|top"
+ height="486"
+ left="345"
+ visible="false"
+ name="panel_profile_secondlife"
+ class="panel_profile_secondlife"
+ filename="panel_profile_secondlife.xml"
+ width="425" />
+ <panel
+ top="70"
+ follows="bottom|right|top"
+ height="482"
+ left="345"
+ visible="false"
+ name="panel_group_info_sidetray"
+ class="panel_group_info_sidetray"
+ filename="panel_group_info_sidetray.xml"
+ width="425" />
+ <panel
+ top="70"
+ follows="bottom|right|top"
+ height="484"
+ left="345"
+ visible="false"
+ name="panel_places"
+ class="panel_places"
+ filename="panel_places.xml"
+ width="425" />
+ <panel
+ top="70"
+ follows="bottom|right|top"
+ height="481"
+ left="345"
+ visible="false"
+ name="panel_classified_info"
+ class="panel_classified_info"
+ filename="panel_classified_info.xml"
+ width="425" />
+ <panel
+ top="70"
+ follows="bottom|right|top"
+ height="480"
+ left="345"
+ visible="false"
+ name="panel_event_info"
+ class="panel_event_info"
+ filename="panel_event_info.xml"
+ width="425" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 081e5be014..08521ebe81 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -125,7 +125,6 @@
</menu_item_call>
<menu_item_separator/>
-
<menu_item_call
label="Preferences..."
name="Preferences"
@@ -688,6 +687,13 @@
<menu_item_check.on_click
function="Avatar.ToggleSearch"/>
</menu_item_check>
+ <menu_item_call
+ label="Legacy Search..."
+ name="LegacySearch">
+ <menu_item_call.on_click
+ function="Floater.Toggle"
+ parameter="legacy_search" />
+ </menu_item_call>
<menu_item_separator/>
<menu_item_call
label="Teleport home"
diff --git a/indra/newview/skins/default/xui/en/panel_classified_info.xml b/indra/newview/skins/default/xui/en/panel_classified_info.xml
index afd3f9410b..b05904cd28 100644
--- a/indra/newview/skins/default/xui/en/panel_classified_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_classified_info.xml
@@ -344,7 +344,6 @@
width="290"
height="215">
<text
- auto_resize="false"
follows="left|top"
font.style="BOLD"
height="10"
diff --git a/indra/newview/skins/default/xui/en/panel_dir_classified.xml b/indra/newview/skins/default/xui/en/panel_dir_classified.xml
new file mode 100644
index 0000000000..f4d3ccf748
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_dir_classified.xml
@@ -0,0 +1,215 @@
+<panel
+ border="true"
+ top="30"
+ follows="left|top|right|bottom"
+ height="533"
+ label="Classifieds"
+ left="1"
+ left_delta="68"
+ mouse_opaque="false"
+ name="panel_dir_classified"
+ width="778">
+ <string name="searching_text">
+ Searching...
+ </string>
+ <string name="not_found_text">
+ None Found.
+ </string>
+ <text
+ bg_visible="false"
+ border_visible="false"
+ top="8"
+ layout="topleft"
+ follows="left|top"
+ font="SansSerif"
+ h_pad="0"
+ halign="left"
+ height="16"
+ left="5"
+ mouse_opaque="true"
+ name="find"
+ v_pad="0"
+ width="150">
+ Enter search terms:
+ </text>
+ <combo_box
+ allow_text_entry="false"
+ top_delta="0"
+ left="525"
+ layout="topleft"
+ follows="right|top"
+ height="18"
+ max_chars="20"
+ mouse_opaque="true"
+ name="Category"
+ width="128">
+ <combo_item name="AnyCategory" value="0" label="Any Category"/>
+ <combo_item name="Shopping" value="1" label="Shopping"/>
+ <combo_item name="LandRental" value="2" label="Land Rental"/>
+ <combo_item name="PropertyRental" value="3" label="Property Rental"/>
+ <combo_item name="SpecialAttraction" value="4" label="Special Attraction"/>
+ <combo_item name="NewProducts" value="5" label="New Products"/>
+ <combo_item name="Employment" value="6" label="Employment"/>
+ <combo_item name="Wanted" value="7" label="Wanted"/>
+ <combo_item name="Service" value="8" label="Service"/>
+ <combo_item name="Personal" value="9" label="Personal"/>
+ </combo_box>
+ <check_box
+ left_pad="5"
+ control_name="ShowPGClassifieds"
+ follows="right|top"
+ layout="topleft"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="true"
+ label=""
+ mouse_opaque="true"
+ name="incpg"
+ width="15" />
+ <icon
+ follows="right|top"
+ height="16"
+ top_delta="-1"
+ image_name="Parcel_PG_Dark"
+ tool_tip="General"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_general"
+ width="16"/>
+ <check_box
+ left_pad="4"
+ top_delta="1"
+ layout="topleft"
+ control_name="ShowMatureClassifieds"
+ follows="right|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="true"
+ label=""
+ mouse_opaque="true"
+ name="incmature"
+ width="15" />
+ <icon
+ follows="right|top"
+ height="16"
+ top_delta="-1"
+ image_name="Parcel_M_Dark"
+ tool_tip="Moderate"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_moderate"
+ width="16"/>
+ <check_box
+ left_pad="4"
+ top_delta="1"
+ layout="topleft"
+ control_name="ShowAdultClassifieds"
+ follows="right|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label=""
+ mouse_opaque="true"
+ name="incadult"
+ width="15" />
+ <icon
+ follows="right|top"
+ height="16"
+ top_delta="-1"
+ image_name="Parcel_R_Dark"
+ tool_tip="Adult"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_adult"
+ width="16"/>
+ <line_editor
+ bevel_style="in"
+ border_style="line"
+ border_thickness="1"
+ top_pad="3"
+ follows="left|right|top"
+ layout="topleft"
+ font="SansSerif"
+ height="18"
+ left="5"
+ max_length="63"
+ mouse_opaque="true"
+ name="name"
+ width="650" />
+ <button
+ follows="right|top"
+ layout="topleft"
+ font="SansSerif"
+ halign="center"
+ height="20"
+ label="Search"
+ top_delta="0"
+ left_pad="5"
+ mouse_opaque="true"
+ name="Search"
+ width="105" />
+ <scroll_list
+ background_visible="true"
+ layout="topleft"
+ top_pad="3"
+ column_padding="0"
+ draw_border="true"
+ draw_heading="true"
+ follows="left|top|right|bottom"
+ height="450"
+ left="5"
+ mouse_opaque="true"
+ multi_select="false"
+ name="results"
+ search_column="2"
+ width="336">
+ <column label="" name="icon" width="24" />
+ <column label="" name="type" width="-1" />
+ <column label="Name" name="name" width="225" />
+ <column label="Price" name="price" width="55" />
+ </scroll_list>
+ <text
+ bg_visible="false"
+ border_visible="false"
+ bottom_delta="-20"
+ follows="left|bottom"
+ font="SansSerifSmall"
+ h_pad="0"
+ halign="left"
+ height="16"
+ left="4"
+ mouse_opaque="true"
+ name="result_text"
+ v_pad="0"
+ width="80" />
+ <button
+ image_overlay="Arrow_Left_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ hover_glow_amount="0.15"
+ tool_tip="Previous page"
+ follows="right|bottom"
+ height="22"
+ right="305"
+ bottom="-533"
+ name="prev_btn"
+ width="32" />
+ <button
+ image_overlay="Arrow_Right_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="Next page"
+ follows="right|bottom"
+ height="22"
+ layout="topleft"
+ left_pad="5"
+ name="next_btn"
+ top_delta="0"
+ width="32"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_dir_events.xml b/indra/newview/skins/default/xui/en/panel_dir_events.xml
new file mode 100644
index 0000000000..b194ce5646
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_dir_events.xml
@@ -0,0 +1,300 @@
+<panel
+ border="true"
+ top="30"
+ default_tab_group="1"
+ follows="left|top|right|bottom"
+ height="533"
+ label="Events"
+ left="1"
+ mouse_opaque="false"
+ name="panel_dir_events"
+ width="778">
+ <string name="searching_text">
+ Searching...
+ </string>
+ <string name="not_found_text">
+ None Found.
+ </string>
+ <text
+ bg_visible="false"
+ border_visible="false"
+ top="8"
+ layout="topleft"
+ follows="left|top"
+ font="SansSerif"
+ h_pad="0"
+ halign="left"
+ height="16"
+ left="5"
+ mouse_opaque="true"
+ name="find"
+ width="150">
+ Enter search terms:
+ </text>
+ <combo_box
+ allow_text_entry="false"
+ top_delta="0"
+ left="525"
+ layout="topleft"
+ follows="right|top"
+ height="18"
+ max_chars="20"
+ mouse_opaque="true"
+ name="category_combo"
+ width="128">
+ <combo_item name="All" value="0" label="Any Category"/>
+ <combo_item name="Discussion" value="18" label="Discussion"/>
+ <combo_item name="Sports" value="19" label="Sports"/>
+ <combo_item name="LiveMusic" value="20" label="Live Music"/>
+ <combo_item name="LiveDJ" value="30" label="Live DJ"/>
+ <combo_item name="Commercial" value="22" label="Commercial"/>
+ <combo_item name="Nightlife/Entertainment" value="23" label="Nightlife/Entertainment"/>
+ <combo_item name="Games/Contests" value="24" label="Games/Contests"/>
+ <combo_item name="Pageants" value="25" label="Pageants"/>
+ <combo_item name="Education" value="26" label="Education"/>
+ <combo_item name="ArtsandCulture" value="27" label="Arts and Culture"/>
+ <combo_item name="Charity/SupportGroups" value="28" label="Charity/Support Groups"/>
+ <combo_item name="Miscellaneous" value="29" label="Miscellaneous"/>
+ </combo_box>
+ <check_box
+ left_pad="5"
+ control_name="ShowPGEvents"
+ follows="right|top"
+ layout="topleft"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="true"
+ label=""
+ mouse_opaque="true"
+ name="incpg"
+ width="15" />
+ <icon
+ follows="right|top"
+ height="16"
+ top_delta="-1"
+ image_name="Parcel_PG_Dark"
+ tool_tip="General"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_general"
+ width="16"/>
+ <check_box
+ left_pad="4"
+ top_delta="1"
+ layout="topleft"
+ control_name="ShowMatureEvents"
+ follows="right|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="true"
+ label=""
+ mouse_opaque="true"
+ name="incmature"
+ width="15" />
+ <icon
+ follows="right|top"
+ height="16"
+ top_delta="-1"
+ image_name="Parcel_M_Dark"
+ tool_tip="Moderate"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_moderate"
+ width="16"/>
+ <check_box
+ left_pad="4"
+ top_delta="1"
+ layout="topleft"
+ control_name="ShowAdultEvents"
+ follows="right|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label=""
+ mouse_opaque="true"
+ name="incadult"
+ width="15" />
+ <icon
+ follows="right|top"
+ height="16"
+ top_delta="-1"
+ image_name="Parcel_R_Dark"
+ tool_tip="Adult"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_adult"
+ width="16"/>
+ <line_editor
+ bevel_style="in"
+ border_style="line"
+ border_thickness="1"
+ top_pad="3"
+ follows="left|right|top"
+ layout="topleft"
+ font="SansSerif"
+ height="18"
+ left="5"
+ max_length="63"
+ mouse_opaque="true"
+ name="event_search_text"
+ width="650" />
+ <button
+ follows="right|top"
+ layout="topleft"
+ font="SansSerif"
+ halign="center"
+ height="20"
+ label="Search"
+ top_delta="0"
+ left_pad="5"
+ mouse_opaque="true"
+ name="Search"
+ width="105" />
+ <scroll_list
+ background_visible="true"
+ layout="topleft"
+ top_pad="3"
+ column_padding="0"
+ draw_border="true"
+ draw_heading="true"
+ follows="left|top|right|bottom"
+ height="450"
+ left="5"
+ mouse_opaque="true"
+ multi_select="false"
+ name="results"
+ search_column="2"
+ width="336">
+ <column label="" name="icon" width="24" />
+ <column label="" name="type" width="-1" />
+ <column dynamicwidth="true" label="Name" name="name" />
+ <column label="Time (PT)" name="date" sort="time" width="106" />
+ <column label="" name="event_id" width="-1" />
+ <column label="Time" name="time" width="-1" />
+ </scroll_list>
+ <text
+ bg_visible="false"
+ border_visible="false"
+ bottom_delta="-20"
+ drop_shadow_visible="true"
+ follows="left|bottom"
+ font="SansSerifSmall"
+ h_pad="0"
+ halign="left"
+ height="16"
+ left="4"
+ mouse_opaque="true"
+ name="result_text"
+ v_pad="0"
+ width="80" />
+ <button
+ image_overlay="Arrow_Left_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ hover_glow_amount="0.15"
+ tool_tip="Previous page"
+ follows="right|bottom"
+ height="22"
+ right="305"
+ bottom="-533"
+ name="prev_btn"
+ width="32" />
+ <button
+ image_overlay="Arrow_Right_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="Next page"
+ follows="right|bottom"
+ height="22"
+ layout="topleft"
+ left_pad="5"
+ name="next_btn"
+ top_delta="0"
+ width="32"/>
+ <radio_group
+ top="5"
+ draw_border="false"
+ follows="top|left"
+ layout="topleft"
+ height="16"
+ left="160"
+ mouse_opaque="true"
+ name="date_mode"
+ initial_value="current"
+ width="200">
+ <radio_item
+ layout="topleft"
+ left="3"
+ top="0"
+ follows="left|top"
+ height="20"
+ mouse_opaque="true"
+ name="current"
+ width="170"
+ label="In-Progress &amp; Upcoming"/>
+ <radio_item
+ layout="topleft"
+ follows="left|top"
+ height="20"
+ top_delta="0"
+ left_delta="151"
+ mouse_opaque="true"
+ name="date"
+ width="56"
+ label="Date"/>
+ </radio_group>
+ <button
+ top="6"
+ left_pad="15"
+ layout="topleft"
+ follows="left|top"
+ font="SansSerif"
+ halign="center"
+ height="20"
+ label="&lt;&lt;"
+ label_selected="&lt;&lt;"
+ left_delta="54"
+ mouse_opaque="true"
+ name="back_btn"
+ tool_tip="Go back a day"
+ width="20" />
+ <text
+ top="8"
+ bg_visible="false"
+ border_visible="false"
+ left_pad="1"
+ layout="topleft"
+ drop_shadow_visible="true"
+ follows="left|top"
+ font="SansSerif"
+ h_pad="0"
+ halign="center"
+ height="14"
+ mouse_opaque="true"
+ name="date_text"
+ v_pad="0"
+ width="48">
+ 6/6
+ </text>
+ <button
+ top="6"
+ left_pad="1"
+ layout="topleft"
+ follows="left|top"
+ font="SansSerif"
+ halign="center"
+ height="20"
+ label="&gt;&gt;"
+ label_selected="&gt;&gt;"
+ left_delta="50"
+ mouse_opaque="true"
+ name="forward_btn"
+ tool_tip="Go forward a day"
+ width="20" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_dir_groups.xml b/indra/newview/skins/default/xui/en/panel_dir_groups.xml
new file mode 100644
index 0000000000..ed3f709005
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_dir_groups.xml
@@ -0,0 +1,129 @@
+<panel
+ border="true"
+ top="30"
+ follows="left|top|right|bottom"
+ height="533"
+ label="Groups"
+ left="1"
+ mouse_opaque="false"
+ name="panel_dir_groups"
+ width="778">
+ <button
+ image_overlay="Arrow_Left_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ hover_glow_amount="0.15"
+ tool_tip="Previous page"
+ follows="right|bottom"
+ height="22"
+ right="305"
+ bottom="-533"
+ name="prev_btn"
+ width="32" />
+ <button
+ image_overlay="Arrow_Right_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="Next page"
+ follows="right|bottom"
+ height="22"
+ layout="topleft"
+ left_pad="5"
+ name="next_btn"
+ top_delta="0"
+ width="32"/>
+ <text
+ bg_visible="false"
+ border_visible="false"
+ top="8"
+ layout="topleft"
+ follows="left|top"
+ font="SansSerif"
+ h_pad="0"
+ halign="left"
+ height="16"
+ left="5"
+ mouse_opaque="true"
+ name="find"
+ v_pad="0"
+ width="150">
+ Enter search terms:
+ </text>
+ <check_box
+ top_delta="0"
+ control_name="ShowMatureGroups"
+ follows="right|top"
+ layout="topleft"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label="Include Mature groups"
+ left="510"
+ mouse_opaque="true"
+ name="incmature"
+ width="100" />
+ <line_editor
+ bevel_style="in"
+ border_style="line"
+ border_thickness="1"
+ top_pad="5"
+ follows="left|right|top"
+ font="SansSerif"
+ height="18"
+ left="5"
+ max_length="63"
+ mouse_opaque="true"
+ name="name"
+ width="650" />
+ <button
+ follows="right|top"
+ layout="topleft"
+ font="SansSerif"
+ halign="center"
+ height="20"
+ label="Search"
+ top_delta="0"
+ left_pad="5"
+ mouse_opaque="true"
+ name="Search"
+ width="105" />
+ <scroll_list
+ background_visible="true"
+ layout="topleft"
+ top_pad="3"
+ column_padding="0"
+ draw_border="true"
+ draw_heading="true"
+ follows="left|top|right|bottom"
+ height="450"
+ left="5"
+ mouse_opaque="true"
+ multi_select="false"
+ name="results"
+ search_column="2"
+ width="336">
+ <column label="" name="icon" width="24" sort="score" sort_ascending="false" />
+ <column label="" name="type" width="-1" />
+ <column label="Name" name="name" dynamicwidth="true" />
+ <column label="Members" name="members" width="100" halign="left" sort_ascending="false" />
+ <column label="" name="score" width="-1"/>
+ </scroll_list>
+ <text
+ bg_visible="false"
+ border_visible="false"
+ bottom_delta="-20"
+ follows="left|bottom"
+ font="SansSerifSmall"
+ h_pad="0" halign="left"
+ height="16" left="4"
+ mouse_opaque="true"
+ name="result_text"
+ v_pad="0"
+ width="328" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_dir_land.xml b/indra/newview/skins/default/xui/en/panel_dir_land.xml
new file mode 100644
index 0000000000..61629f3033
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_dir_land.xml
@@ -0,0 +1,268 @@
+<panel border="true" top="30" follows="left|top|right|bottom" height="533"
+ label="Land Sales" left="1" mouse_opaque="false" name="panel_dir_land"
+ width="778">
+ <string name="searching_text">
+ Searching...
+ </string>
+ <string name="not_found_text">
+ None Found.
+ </string>
+ <text
+ bg_visible="false"
+ border_visible="false"
+ top="8"
+ layout="topleft"
+ follows="left|top"
+ font="SansSerif"
+ h_pad="0"
+ halign="left"
+ height="16"
+ left="5"
+ mouse_opaque="true"
+ name="find"
+ width="150">
+ Enter search terms:
+ </text>
+ <combo_box
+ allow_text_entry="false"
+ follows="top|right"
+ layout="topleft"
+ height="18"
+ top_delta="0"
+ left="525"
+ max_chars="20"
+ mouse_opaque="true"
+ name="type"
+ width="128">
+ <combo_item name="AllTypes" value="All Types" label="All Types"/>
+ <combo_item name="Auction" value="Auction" label="Auction"/>
+ <combo_item name="MainlandSales" value="Mainland Sales" label="For Sale - Mainland"/>
+ <combo_item name="EstateSales" value="Estate Sales" label="For Sale - Estate"/>
+ </combo_box>
+ <check_box
+ left_pad="5"
+ control_name="ShowPGLand"
+ follows="right|top"
+ layout="topleft"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="true"
+ label=""
+ mouse_opaque="true"
+ name="incpg"
+ width="15" />
+ <icon
+ follows="right|top"
+ height="16"
+ top_delta="-1"
+ image_name="Parcel_PG_Dark"
+ tool_tip="General"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_general"
+ width="16"/>
+ <check_box
+ left_pad="4"
+ top_delta="1"
+ layout="topleft"
+ control_name="ShowMatureLand"
+ follows="right|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="true"
+ label=""
+ mouse_opaque="true"
+ name="incmature"
+ width="15" />
+ <icon
+ follows="right|top"
+ height="16"
+ top_delta="-1"
+ image_name="Parcel_M_Dark"
+ tool_tip="Moderate"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_moderate"
+ width="16"/>
+ <check_box
+ left_pad="4"
+ top_delta="1"
+ layout="topleft"
+ control_name="ShowAdultLand"
+ follows="right|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label=""
+ mouse_opaque="true"
+ name="incadult"
+ width="15" />
+ <icon
+ follows="right|top"
+ height="16"
+ top_delta="-1"
+ image_name="Parcel_R_Dark"
+ tool_tip="Adult"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_adult"
+ width="16"/>
+ <check_box
+ top_pad="3"
+ layout="topleft"
+ control_name="FindLandPrice"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="true"
+ label="Price &#8804; "
+ left="5"
+ mouse_opaque="true"
+ name="pricecheck"
+ width="60" />
+ <line_editor
+ bevel_style="in"
+ border_style="line"
+ border_thickness="1"
+ follows="left|top"
+ layout="topleft"
+ font="SansSerifSmall"
+ height="16"
+ left_pad="1"
+ max_length="10"
+ mouse_opaque="true"
+ name="priceedit"
+ width="50" />
+ <text
+ bg_visible="false"
+ border_visible="false"
+ follows="left|top"
+ layout="topleft"
+ font="SansSerifSmall"
+ halign="left"
+ height="16"
+ left_pad="3"
+ mouse_opaque="true"
+ name="pricecheck_symbol"
+ width="15">
+ L$
+ </text>
+ <check_box
+ control_name="FindLandArea"
+ follows="left|top"
+ layout="topleft"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="true"
+ label="Area &#8805; "
+ left_pad="10"
+ mouse_opaque="true"
+ name="areacheck"
+ width="60" />
+ <line_editor
+ bevel_style="in"
+ border_style="line"
+ border_thickness="1"
+ follows="left|top"
+ layout="topleft"
+ font="SansSerifSmall"
+ height="16"
+ left_pad="1"
+ max_length="10"
+ mouse_opaque="true"
+ name="areaedit"
+ width="50" />
+ <text
+ bg_visible="false"
+ border_visible="false"
+ follows="left|top"
+ layout="topleft"
+ left_pad="3"
+ font="SansSerifSmall"
+ halign="left"
+ height="16"
+ mouse_opaque="true"
+ name="areacheck_symbol"
+ width="15">
+ m²
+ </text>
+ <button
+ follows="right|top"
+ layout="topleft"
+ font="SansSerif"
+ halign="center"
+ height="20"
+ label="Search"
+ top_delta="0"
+ left="660"
+ mouse_opaque="true"
+ name="Search"
+ width="105" />
+ <scroll_list
+ background_visible="true"
+ layout="topleft"
+ top_pad="3"
+ column_padding="0"
+ draw_border="true"
+ draw_heading="true"
+ follows="left|top|right|bottom"
+ height="450"
+ left="5"
+ mouse_opaque="true"
+ multi_select="false"
+ name="results"
+ search_column="2"
+ width="336">
+ <column label="" name="icon" width="24" />
+ <column dynamicwidth="true" label="Name" name="name" />
+ <column label="Type" name="landtype" width="50" />
+ <column label="L$ Price" name="price" width="65" />
+ <column label="Area" name="area" width="50" />
+ <column label="L$/m²" name="per_meter" width="65" />
+ </scroll_list>
+ <text
+ bg_visible="false"
+ border_visible="false"
+ bottom_delta="-20"
+ drop_shadow_visible="true"
+ follows="left|bottom"
+ font="SansSerifSmall"
+ h_pad="0"
+ halign="left"
+ height="16"
+ left="4"
+ mouse_opaque="true"
+ name="result_text"
+ v_pad="0"
+ width="328" />
+ <button
+ image_overlay="Arrow_Left_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ hover_glow_amount="0.15"
+ tool_tip="Previous page"
+ follows="right|bottom"
+ height="22"
+ right="305"
+ bottom="-533"
+ name="prev_btn"
+ width="32" />
+ <button
+ image_overlay="Arrow_Right_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="Next page"
+ follows="right|bottom"
+ height="22"
+ layout="topleft"
+ left_pad="5"
+ name="next_btn"
+ top_delta="0"
+ width="32"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_dir_people.xml b/indra/newview/skins/default/xui/en/panel_dir_people.xml
new file mode 100644
index 0000000000..fe1a7e9d94
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_dir_people.xml
@@ -0,0 +1,120 @@
+<panel
+ border="true"
+ top="30"
+ follows="left|top|right|bottom"
+ height="533"
+ label="People"
+ left="1"
+ mouse_opaque="false"
+ name="panel_dir_people"
+ width="778">
+ <string name="searching_text">
+ Searching...
+ </string>
+ <string name="not_found_text">
+ None Found.
+ </string>
+ <text
+ bg_visible="false"
+ border_visible="false"
+ top="8"
+ layout="topleft"
+ follows="left|top"
+ font="SansSerif"
+ h_pad="0"
+ halign="left"
+ height="16"
+ left="5"
+ mouse_opaque="true"
+ name="find"
+ width="150">
+ Enter search terms:
+ </text>
+ <line_editor
+ bevel_style="in"
+ border_style="line"
+ border_thickness="1"
+ top_pad="5"
+ follows="left|right|top"
+ font="SansSerif"
+ height="18"
+ left="5"
+ max_length="63"
+ mouse_opaque="true"
+ name="name"
+ width="650" />
+ <button
+ follows="right|top"
+ layout="topleft"
+ font="SansSerif"
+ top_delta="0"
+ left_pad="5"
+ height="20"
+ label="Search"
+ mouse_opaque="true"
+ name="Search"
+ width="105" />
+ <scroll_list
+ background_visible="true"
+ layout="topleft"
+ top_pad="3"
+ column_padding="0"
+ draw_border="true"
+ draw_heading="true"
+ follows="left|top|right|bottom"
+ height="450"
+ left="5"
+ mouse_opaque="true"
+ multi_select="false"
+ name="results"
+ search_column="2"
+ width="336">
+ <column label="" name="icon" width="24" />
+ <column label="" name="type" width="-1" />
+ <column label="Name" name="name" width="274" />
+ </scroll_list>
+ <text
+ bg_visible="false"
+ border_visible="false"
+ bottom_delta="-20"
+ follows="left|bottom"
+ font="SansSerifSmall"
+ h_pad="0"
+ halign="left"
+ height="16"
+ left="4"
+ mouse_opaque="true"
+ name="result_text"
+ v_pad="0"
+ width="328" />
+ <button
+ image_overlay="Arrow_Left_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ hover_glow_amount="0.15"
+ tool_tip="Previous page"
+ follows="right|bottom"
+ height="22"
+ right="305"
+ bottom="-533"
+ name="prev_btn"
+ width="32" />
+ <button
+ image_overlay="Arrow_Right_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="Next page"
+ follows="right|bottom"
+ height="22"
+ layout="topleft"
+ left_pad="5"
+ name="next_btn"
+ top_delta="0"
+ width="32"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_dir_places.xml b/indra/newview/skins/default/xui/en/panel_dir_places.xml
new file mode 100644
index 0000000000..d337f3addf
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_dir_places.xml
@@ -0,0 +1,215 @@
+<panel
+ border="true"
+ top="30"
+ follows="left|top|right|bottom"
+ height="533"
+ label="Places"
+ left="1"
+ mouse_opaque="false"
+ name="panel_dir_places"
+ width="778">
+ <string name="searching_text">
+ Searching...
+ </string>
+ <string name="not_found_text">
+ None Found.
+ </string>
+ <text
+ bg_visible="false"
+ border_visible="false"
+ top="8"
+ layout="topleft"
+ follows="left|top"
+ font="SansSerif"
+ h_pad="0"
+ halign="left"
+ height="16"
+ left="5"
+ mouse_opaque="true"
+ name="find"
+ width="150">
+ Enter search terms:
+ </text>
+ <combo_box
+ allow_text_entry="false"
+ follows="right|top"
+ layout="topleft"
+ height="18"
+ top_delta="0"
+ left="525"
+ max_chars="20"
+ mouse_opaque="true"
+ name="Category"
+ width="128">
+ <combo_item name="AnyCategory" value="any" label="Any Category"/>
+ <combo_item name="LindenLocation" value="linden" label="Linden Location"/>
+ <combo_item name="Arts&amp;Culture" value="arts" label="Arts &amp; Culture"/>
+ <combo_item name="Business" value="store" label="Business"/>
+ <combo_item name="Educational" value="educational" label="Educational"/>
+ <combo_item name="Gaming" value="game" label="Gaming"/>
+ <combo_item name="Hangout" value="gather" label="Hangout"/>
+ <combo_item name="NewcomerFriendly" value="newcomer" label="Newcomer Friendly"/>
+ <combo_item name="Parks&amp;Nature" value="park" label="Parks &amp; Nature"/>
+ <combo_item name="Residential" value="home" label="Residential"/>
+ <combo_item name="Shopping" value="shopping" label="Shopping"/>
+ <combo_item name="Adult" value="adult" label="Adult"/>
+ <combo_item name="Other" value="other" label="Other"/>
+ </combo_box>
+ <check_box
+ left_pad="5"
+ control_name="ShowPGSims"
+ follows="right|top"
+ layout="topleft"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="true"
+ label=""
+ mouse_opaque="true"
+ name="incpg"
+ width="15" />
+ <icon
+ follows="right|top"
+ height="16"
+ top_delta="-1"
+ image_name="Parcel_PG_Dark"
+ tool_tip="General"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_general"
+ width="16"/>
+ <check_box
+ left_pad="4"
+ top_delta="1"
+ layout="topleft"
+ control_name="ShowMatureSims"
+ follows="right|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="true"
+ label=""
+ mouse_opaque="true"
+ name="incmature"
+ width="15" />
+ <icon
+ follows="right|top"
+ height="16"
+ top_delta="-1"
+ image_name="Parcel_M_Dark"
+ tool_tip="Moderate"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_moderate"
+ width="16"/>
+ <check_box
+ left_pad="4"
+ top_delta="1"
+ layout="topleft"
+ control_name="ShowAdultSims"
+ follows="right|top"
+ font="SansSerifSmall"
+ height="16"
+ initial_value="false"
+ label=""
+ mouse_opaque="true"
+ name="incadult"
+ width="15" />
+ <icon
+ follows="right|top"
+ height="16"
+ top_delta="-1"
+ image_name="Parcel_R_Dark"
+ tool_tip="Adult"
+ layout="topleft"
+ left_pad="2"
+ name="rating_icon_adult"
+ width="16"/>
+ <line_editor
+ bevel_style="in"
+ border_style="line"
+ border_thickness="1"
+ top_pad="3"
+ follows="left|right|top"
+ layout="topleft"
+ font="SansSerif"
+ height="18"
+ left="5"
+ max_length="63"
+ mouse_opaque="true"
+ name="name"
+ width="650" />
+ <button
+ follows="right|top"
+ layout="topleft"
+ font="SansSerif"
+ halign="center"
+ height="20"
+ label="Search"
+ top_delta="0"
+ left_pad="5"
+ mouse_opaque="true"
+ name="Search"
+ width="105" />
+ <scroll_list
+ background_visible="true"
+ layout="topleft"
+ top_pad="3"
+ column_padding="0"
+ draw_border="true"
+ draw_heading="true"
+ follows="left|top|right|bottom"
+ height="450"
+ left="5"
+ mouse_opaque="true"
+ multi_select="false"
+ name="results"
+ search_column="2"
+ width="336">
+ <column label="" name="icon" width="24" />
+ <column dynamicwidth="true" label="Name" name="name" />
+ <column label="Traffic" name="dwell" width="75" />
+ </scroll_list>
+ <text
+ bg_visible="false"
+ border_visible="false"
+ bottom_delta="-20"
+ follows="left|bottom"
+ font="SansSerifSmall"
+ h_pad="0"
+ halign="left"
+ height="16"
+ left="4"
+ mouse_opaque="true"
+ name="result_text"
+ v_pad="0"
+ width="328" />
+ <button
+ image_overlay="Arrow_Left_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ hover_glow_amount="0.15"
+ tool_tip="Previous page"
+ follows="right|bottom"
+ height="22"
+ right="305"
+ bottom="-533"
+ name="prev_btn"
+ width="32" />
+ <button
+ image_overlay="Arrow_Right_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="Next page"
+ follows="right|bottom"
+ height="22"
+ layout="topleft"
+ left_pad="5"
+ name="next_btn"
+ top_delta="0"
+ width="32"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_dir_web.xml b/indra/newview/skins/default/xui/en/panel_dir_web.xml
new file mode 100644
index 0000000000..0dde67681a
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_dir_web.xml
@@ -0,0 +1,76 @@
+<panel
+ border="true"
+ top="30"
+ follows="all"
+ height="543"
+ label="Web"
+ left="1"
+ mouse_opaque="false"
+ name="panel_dir_web"
+ width="778">
+ <web_browser
+ top="0"
+ left="0"
+ height="515"
+ width="778"
+ follows="all"
+ layout="topleft"
+ name="web_search"
+ trusted_content="true"/>
+ <button
+ image_overlay="Arrow_Left_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ hover_glow_amount="0.15"
+ tool_tip="Navigate back"
+ follows="left|bottom"
+ height="22"
+ layout="topleft"
+ left="5"
+ name="back_btn"
+ top_pad="7"
+ width="22" />
+ <button
+ image_overlay="Arrow_Right_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ chrome="true"
+ tool_tip="Navigate forward"
+ follows="left|bottom"
+ height="22"
+ layout="topleft"
+ left_pad="5"
+ name="forward_btn"
+ top_delta="0"
+ width="22"/>
+ <button
+ name="home_btn"
+ follows="left|bottom"
+ image_overlay="Home_Off"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Disabled"
+ image_selected="PushButton_Selected"
+ image_unselected="PushButton_Off"
+ layout="topleft"
+ tool_tip="Search page"
+ left_pad="5"
+ height="22"
+ width="22"/>
+ <text
+ type="string"
+ length="200"
+ follows="bottom|left"
+ height="20"
+ layout="topleft"
+ left_pad="20"
+ top_delta="5"
+ name="statusbartext"
+ parse_urls="false"
+ text_color="0.4 0.4 0.4 1"
+ width="495"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_event_info.xml b/indra/newview/skins/default/xui/en/panel_event_info.xml
new file mode 100644
index 0000000000..b31918b919
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_event_info.xml
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ follows="all"
+ height="570"
+ left="0"
+ top="0"
+ name="panel_event_info"
+ title="Event"
+ width="330">
+ <string name="none">
+ none
+ </string>
+ <string name="notify">
+ Notify
+ </string>
+ <string name="dont_notify">
+ Don&apos;t Notify
+ </string>
+ <text
+ top="4"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerifBig"
+ left="5"
+ width="417"
+ height="18"
+ use_ellipses="true"
+ name="event_name">
+ (none)
+ </text>
+ <text
+ top_pad="10"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="20"
+ name="event_category_label">
+ Type:
+ </text>
+ <text
+ top_delta="0"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="120"
+ name="event_category">
+ (none)
+ </text>
+ <text
+ top_pad="10"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="20"
+ name="event_mature_label">
+ Mature Content:
+ </text>
+ <text
+ top_delta="0"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="120"
+ name="event_mature_yes"
+ visible="false">
+ Yes
+ </text>
+ <text
+ top_delta="0"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="120"
+ name="event_mature_no"
+ visible="false">
+ No
+ </text>
+ <text
+ top_pad="10"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="20"
+ name="event_date_label">
+ Date:
+ </text>
+ <text
+ top_delta="0"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="120"
+ name="event_date">
+ (none)
+ </text>
+ <text
+ top_pad="10"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="20"
+ name="event_duration_label">
+ Event Duration:
+ </text>
+ <text
+ top_delta="0"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="120"
+ name="event_duration">
+ (none)
+ </text>
+ <text
+ top_pad="10"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="20"
+ name="event_runby_label">
+ Run By:
+ </text>
+ <text
+ top_delta="0"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="116"
+ name="event_runby">
+ (none)
+ </text>
+ <text
+ top_pad="10"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="20"
+ name="event_location_label">
+ Location:
+ </text>
+ <text
+ top_delta="0"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="120"
+ name="event_location">
+ (none)
+ </text>
+ <text
+ top_pad="10"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="20"
+ name="event_cover_label">
+ Cover Charge:
+ </text>
+ <text
+ top_delta="0"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="120"
+ name="event_cover">
+ (none)
+ </text>
+ <text
+ top_pad="20"
+ follows="top|left"
+ layout="topleft"
+ font="SansSerif"
+ left="20"
+ name="event_desc_label">
+ Description:
+ </text>
+ <text_editor
+ top_pad="10"
+ follows="left|top"
+ layout="topleft"
+ height="220"
+ left="20"
+ enabled="false"
+ max_length="1024"
+ name="event_desc"
+ width="400" />
+ <button
+ bottom_delta="-24"
+ follows="left|top"
+ height="20"
+ label="Teleport"
+ left="20"
+ name="teleport_btn"
+ width="130" />
+ <button
+ bottom_delta="0"
+ follows="left|top"
+ height="20"
+ label="Show on Map"
+ left="155"
+ name="map_btn"
+ width="130" />
+ <button
+ bottom_delta="0"
+ follows="left|top"
+ height="20"
+ label="Notify"
+ left="290"
+ name="notify_btn"
+ width="130" />
+</panel>