From d294d568d1c97650bba4c388c8a7eab5a5c49c94 Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Tue, 21 Oct 2025 22:05:07 +0300 Subject: [PATCH 001/104] #4411 WIP initial restoring of Legacy Search --- indra/newview/CMakeLists.txt | 18 + indra/newview/app_settings/settings.xml | 13 + indra/newview/lleventnotifier.cpp | 71 +- indra/newview/lleventnotifier.h | 25 +- indra/newview/llfloaterdirectory.cpp | 99 ++ indra/newview/llfloaterdirectory.h | 82 ++ indra/newview/llpanelclassified.cpp | 4 +- indra/newview/llpaneldirbrowser.cpp | 1240 +++++++++++++++++ indra/newview/llpaneldirbrowser.h | 180 +++ indra/newview/llpaneldirclassified.cpp | 145 ++ indra/newview/llpaneldirclassified.h | 59 + indra/newview/llpaneldirevents.cpp | 280 ++++ indra/newview/llpaneldirevents.h | 68 + indra/newview/llpaneldirgroups.cpp | 93 ++ indra/newview/llpaneldirgroups.h | 45 + indra/newview/llpaneldirland.cpp | 268 ++++ indra/newview/llpaneldirland.h | 61 + indra/newview/llpaneldirpeople.cpp | 106 ++ indra/newview/llpaneldirpeople.h | 48 + indra/newview/llpaneldirplaces.cpp | 214 +++ indra/newview/llpaneldirplaces.h | 55 + indra/newview/llpaneleventinfo.cpp | 213 +++ indra/newview/llpaneleventinfo.h | 76 + indra/newview/llpanelgroup.cpp | 6 + indra/newview/llpanelgroup.h | 1 + indra/newview/llpanelplaces.cpp | 9 +- indra/newview/llpanelplaces.h | 2 + indra/newview/llpanelprofile.cpp | 14 +- indra/newview/llpanelprofile.h | 3 + indra/newview/llstartup.cpp | 8 + indra/newview/llviewerfloaterreg.cpp | 2 + .../skins/default/textures/icon_auction.tga | Bin 0 -> 1068 bytes .../skins/default/textures/icon_event.tga | Bin 0 -> 1068 bytes .../default/textures/icon_event_adult.tga | Bin 0 -> 648 bytes .../default/textures/icon_event_mature.tga | Bin 0 -> 1068 bytes .../skins/default/textures/icon_place.tga | Bin 0 -> 1068 bytes .../skins/default/textures/textures.xml | 6 + .../default/xui/en/floater_directory.xml | 139 ++ .../skins/default/xui/en/menu_viewer.xml | 8 +- .../default/xui/en/panel_dir_classified.xml | 197 +++ .../skins/default/xui/en/panel_dir_events.xml | 286 ++++ .../skins/default/xui/en/panel_dir_groups.xml | 122 ++ .../skins/default/xui/en/panel_dir_land.xml | 216 +++ .../skins/default/xui/en/panel_dir_people.xml | 114 ++ .../skins/default/xui/en/panel_dir_places.xml | 204 +++ .../skins/default/xui/en/panel_event_info.xml | 221 +++ 46 files changed, 4997 insertions(+), 24 deletions(-) create mode 100644 indra/newview/llfloaterdirectory.cpp create mode 100644 indra/newview/llfloaterdirectory.h create mode 100644 indra/newview/llpaneldirbrowser.cpp create mode 100644 indra/newview/llpaneldirbrowser.h create mode 100644 indra/newview/llpaneldirclassified.cpp create mode 100644 indra/newview/llpaneldirclassified.h create mode 100644 indra/newview/llpaneldirevents.cpp create mode 100644 indra/newview/llpaneldirevents.h create mode 100644 indra/newview/llpaneldirgroups.cpp create mode 100644 indra/newview/llpaneldirgroups.h create mode 100644 indra/newview/llpaneldirland.cpp create mode 100644 indra/newview/llpaneldirland.h create mode 100644 indra/newview/llpaneldirpeople.cpp create mode 100644 indra/newview/llpaneldirpeople.h create mode 100644 indra/newview/llpaneldirplaces.cpp create mode 100644 indra/newview/llpaneldirplaces.h create mode 100644 indra/newview/llpaneleventinfo.cpp create mode 100644 indra/newview/llpaneleventinfo.h create mode 100644 indra/newview/skins/default/textures/icon_auction.tga create mode 100644 indra/newview/skins/default/textures/icon_event.tga create mode 100644 indra/newview/skins/default/textures/icon_event_adult.tga create mode 100644 indra/newview/skins/default/textures/icon_event_mature.tga create mode 100644 indra/newview/skins/default/textures/icon_place.tga create mode 100644 indra/newview/skins/default/xui/en/floater_directory.xml create mode 100644 indra/newview/skins/default/xui/en/panel_dir_classified.xml create mode 100644 indra/newview/skins/default/xui/en/panel_dir_events.xml create mode 100644 indra/newview/skins/default/xui/en/panel_dir_groups.xml create mode 100644 indra/newview/skins/default/xui/en/panel_dir_land.xml create mode 100644 indra/newview/skins/default/xui/en/panel_dir_people.xml create mode 100644 indra/newview/skins/default/xui/en/panel_dir_places.xml create mode 100644 indra/newview/skins/default/xui/en/panel_event_info.xml diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 8869f4b1f60..be9df8a6dff 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,19 @@ set(viewer_SOURCE_FILES llpanelblockedlist.cpp llpanelclassified.cpp llpanelcontents.cpp + llpaneldirbrowser.cpp + llpaneldirclassified.cpp + llpaneldirevents.cpp + llpaneldirgroups.cpp + llpaneldirland.cpp + llpaneldirpeople.cpp + llpaneldirplaces.cpp llpaneleditsky.cpp llpaneleditwater.cpp llpaneleditwearable.cpp llpanelemojicomplete.cpp llpanelenvironment.cpp + llpaneleventinfo.cpp llpanelexperiencelisteditor.cpp llpanelexperiencelog.cpp llpanelexperiencepicker.cpp @@ -894,6 +903,7 @@ set(viewer_HEADER_FILES llfloatercreatelandmark.h llfloaterdeleteprefpreset.h llfloaterdestinations.h + llfloaterdirectory.h llfloaterdisplayname.h llfloatereditenvironmentbase.h llfloatereditextdaycycle.h @@ -1108,11 +1118,19 @@ set(viewer_HEADER_FILES llpanelblockedlist.h llpanelclassified.h llpanelcontents.h + llpaneldirbrowser.h + llpaneldirclassified.h + llpaneldirevents.h + llpaneldirgroups.h + llpaneldirland.h + llpaneldirpeople.h + llpaneldirplaces.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 d6a1fbd124f..98bf49b55a3 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11146,6 +11146,19 @@ Value 0 + ShowPGEvents + + Comment + Display results of find events that are flagged as general + Persist + 1 + HideFromEditor + 1 + Type + Boolean + Value + 1 + ShowNearClip Comment diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp index 25983f4add3..66a922e288d 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 030c9abb871..2a9295129d1 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 @@ class LLEventNotifier 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 @@ class LLEventNotifier static void processEventInfoReply(LLMessageSystem *msg, void **); + typedef boost::signals2::signal 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 00000000000..04a6a45af32 --- /dev/null +++ b/indra/newview/llfloaterdirectory.cpp @@ -0,0 +1,99 @@ +/** + * @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 "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), + mMinimizing(false), + mPanelAvatarp(nullptr), + mPanelGroupp(nullptr), + mPanelPlacep(nullptr), + mPanelClassifiedp(nullptr), + mPanelEventp(nullptr) +{ +} + +LLFloaterDirectory::~LLFloaterDirectory() +{ +} + +bool LLFloaterDirectory::postBuild() +{ + const std::vector 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(panel_name)) + { + panel_tab->setFloaterDirectory(this); + } + } + + mPanelAvatarp = findChild("panel_profile_secondlife"); + mPanelAvatarp->setAllowEdit(false); + mPanelGroupp = findChild("panel_group_info_sidetray"); + mPanelGroupp->hideBackBtn(); + mPanelPlacep = findChild("panel_places"); + mPanelPlacep->hideBackBtn(); + mPanelClassifiedp = findChild("panel_classified_info"); + mPanelClassifiedp->setBackgroundVisible(false); + mPanelEventp = findChild("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 00000000000..c7dd243007f --- /dev/null +++ b/indra/newview/llfloaterdirectory.h @@ -0,0 +1,82 @@ +/** + * @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: + bool mMinimizing; // HACK: see reshape() for details + static LLFloaterDirectory *sInstance; +}; + +//extern BOOL gDisplayEventHack; + +#endif // LL_LLDIRECTORYFLOATER_H diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 449a670de97..aefda39fb97 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 00000000000..2ef7bb122d0 --- /dev/null +++ b/indra/newview/llpaneldirbrowser.cpp @@ -0,0 +1,1240 @@ +/** + * @file llpaneldirbrowser.cpp + * @brief LLPanelDirBrowser class implementation + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// 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 "llfontgl.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 "lluiconstants.h" +#include "llviewercontrol.h" +#include "llviewermessage.h" +#include "llfloaterdirectory.h" +#include "llpanelprofile.h" +#include "llpanelplaces.h" +#include "llpaneleventinfo.h" + + +std::map gDirBrowserInstances; + +LLPanelDirBrowser::LLPanelDirBrowser() +: LLPanel(), + mSearchID(), + mWantSelectID(), + mCurrentSortColumn("name"), + mCurrentSortAscending(true), + mSearchStart(0), + mResultsPerPage(100), + mResultsReceived(0), + mMinSearchChars(1), + mResultsContents(), + mHaveSearchResults(false), + mDidAutoSelect(true), + mLastResultTimer(), + mFloaterDirectory(nullptr) +{ +} + +bool LLPanelDirBrowser::postBuild() +{ + childSetCommitCallback("results", onCommitList, this); + + childSetAction("< Prev", onClickPrev, this); + childSetVisible("< Prev", false); + + childSetAction("Next >", onClickNext, this); + childSetVisible("Next >", 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; + childSetVisible("< Prev", true); + + performQuery(); +} + + +// virtual +void LLPanelDirBrowser::prevPage() +{ + mSearchStart -= mResultsPerPage; + childSetVisible("< Prev", mSearchStart > 0); + + performQuery(); +} + + +void LLPanelDirBrowser::resetSearchStart() +{ + mSearchStart = 0; + childSetVisible("Next >", false); + childSetVisible("< Prev", false); +} + +// protected +void LLPanelDirBrowser::updateResultCount() +{ + LLScrollListCtrl* list = getChild("results"); + + S32 result_count = list->getItemCount(); + std::string result_text; + + if (!mHaveSearchResults) result_count = 0; + + LLView* viewp = getChild("Next >"); + if (viewp && viewp->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 +void LLPanelDirBrowser::onClickPrev(void* data) +{ + LLPanelDirBrowser* self = (LLPanelDirBrowser*)data; + self->prevPage(); +} + + +// static +void LLPanelDirBrowser::onClickNext(void* data) +{ + LLPanelDirBrowser* self = (LLPanelDirBrowser*)data; + self->nextPage(); +} + +// 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::updateMaturityCheckbox() +{ + BOOL godlike = gAgent.isGodlike(); + // You only have a choice if your maturity is 'mature' or higher. + // Logic: if you're not at least mature, hide the mature and adult options + // After that, enable only the options you can legitimately choose. + // If you're PG only, show you the checkbox but don't let you change it. + // If you're God, you have everything. + bool mature_enabled = gAgent.canAccessMature() || godlike; + bool adult_enabled = gAgent.canAccessAdult() || godlike; + + // TODO: fix maturity settings + // These check boxes can only be checked if you have the right access to use them + //std::string control_name_pg = getChild("incpg")->getControlName(); + //std::string control_name_mature = getChild("incmature")->getControlName(); + //std::string control_name_adult = getChild("incadult")->getControlName(); + + //childSetValue("incpg", gSavedSettings.getBOOL(control_name_pg)); + //childSetValue("incmature", gSavedSettings.getBOOL(control_name_mature) && mature_enabled); + //childSetValue("incadult", gSavedSettings.getBOOL(control_name_adult) && adult_enabled); + + childSetValue("incpg", true); + childSetValue("incmature", true); + childSetValue("incadult", true); + + // Teens don't get mature/adult choices + if (gAgent.wantsPGOnly()) + { + childSetVisible("incmature", false); + childSetVisible("incadult", false); + childSetValue("incpg", TRUE); + childDisable("incpg"); + } + + childSetEnabled("incmature", mature_enabled); + childSetEnabled("incadult", adult_enabled); + + if (mature_enabled) + { + childEnable("incpg"); + childSetVisible("incpg", TRUE); + childSetVisible("incmature", TRUE); + childSetVisible("incadult", TRUE); + } +} + +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"][3]["column"] = "dwell"; + row["columns"][3]["value"] = buffer; + row["columns"][3]["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); + LL_INFOS() << "Land sku: " << land_sku << LL_ENDL; + 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"][3]["column"] = "price"; + row["columns"][3]["value"] = buffer; + row["columns"][3]["font"] = "SANSSERIFSMALL"; + + buffer = llformat("%d", actual_area); + row["columns"][4]["column"] = "area"; + row["columns"][4]["value"] = buffer; + row["columns"][4]["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"][5]["column"] = "per_meter"; + row["columns"][5]["value"] = buffer; + row["columns"][5]["font"] = "SANSSERIFSMALL"; + } + else + { + // Auctions start at L$1 per meter + row["columns"][5]["column"] = "per_meter"; + row["columns"][5]["value"] = "1.0"; + row["columns"][5]["font"] = "SANSSERIFSMALL"; + } + + row["columns"][6]["column"] = "landtype"; + row["columns"][6]["value"] = land_type; + row["columns"][6]["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"][2]["column"] = "name"; + row["columns"][2]["value"] = name; + row["columns"][2]["font"] = "SANSSERIF"; + + return row; +} + +void LLPanelDirBrowser::setupNewSearch() +{ + LLScrollListCtrl* list = getChild("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(std::string("Searching...")); // *TODO: Translate + childDisable("results"); + + 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); + childSetVisible("Next >", show_next); + if (show_next) + { + rows -= (mResultsReceived - mResultsPerPage); + } + } + else + { + // Hide page buttons + childSetVisible("Next >", false); + childSetVisible("< Prev", false); + } + return rows; +} diff --git a/indra/newview/llpaneldirbrowser.h b/indra/newview/llpaneldirbrowser.h new file mode 100644 index 00000000000..b6aa5647254 --- /dev/null +++ b/indra/newview/llpaneldirbrowser.h @@ -0,0 +1,180 @@ +/** + * @file llpaneldirbrowser.h + * @brief LLPanelDirBrowser class definition + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// Base class for the various search panels/results browsers +// in the Find floater. For example, Find > Popular Places +// is derived from this. + +#ifndef LL_LLPANELDIRBROWSER_H +#define LL_LLPANELDIRBROWSER_H + +#include "llpanel.h" + +#include "lluuid.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. + virtual void draw(); + + virtual void onVisibilityChange(BOOL curVisibilityIn); + + // 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); + + // Prev/Next page buttons + static void onClickNext(void* data); + static void onClickPrev(void* data); + + 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 ); + + // Logic to control maturity checkboxes in Classified/Events/Places/'Land for Sale' tabs. + void updateMaturityCheckbox(); + +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; +}; + +// 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 gDirBrowserInstances; + +#endif // LL_LLPANELDIRBROWSER_H diff --git a/indra/newview/llpaneldirclassified.cpp b/indra/newview/llpaneldirclassified.cpp new file mode 100644 index 00000000000..9ce6b88b25b --- /dev/null +++ b/indra/newview/llpaneldirclassified.cpp @@ -0,0 +1,145 @@ +/** + * @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 t_panel_dir_classified("panel_dir_classified"); + +LLPanelDirClassified::LLPanelDirClassified() +: LLPanelDirBrowser() +{ +} + +bool LLPanelDirClassified::postBuild() +{ + LLPanelDirBrowser::postBuild(); + + // Teens don't get mature checkbox + if (gAgent.wantsPGOnly()) + { + childSetValue("incmature", FALSE); + childSetValue("incadult", FALSE); + childSetVisible("incmature", false); + childSetVisible("incadult", false); + childSetValue("incpg", TRUE); + childDisable("incpg"); + } + + bool mature_enabled = gAgent.canAccessMature(); + if (!mature_enabled) + { + childSetValue("incmature", FALSE); + childDisable("incmature"); + } + + bool adult_enabled = gAgent.canAccessAdult(); + if (!adult_enabled) + { + childSetValue("incadult", FALSE); + childDisable("incadult"); + } + + childSetAction("Search", onClickSearchCore, this); + + return true; +} + +LLPanelDirClassified::~LLPanelDirClassified() +{ +} + +void LLPanelDirClassified::draw() +{ + refresh(); + + LLPanelDirBrowser::draw(); +} + +void LLPanelDirClassified::refresh() +{ + updateMaturityCheckbox(); +} + +void LLPanelDirClassified::performQuery() +{ + BOOL inc_pg = childGetValue("incpg").asBoolean(); + BOOL inc_mature = childGetValue("incmature").asBoolean(); + BOOL inc_adult = childGetValue("incadult").asBoolean(); + 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, inc_adult); + //if (gAgent.isTeen()) query_flags |= DFQ_PG_SIMS_ONLY; + + 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 00000000000..76c3d8635a2 --- /dev/null +++ b/indra/newview/llpaneldirclassified.h @@ -0,0 +1,59 @@ +/** + * @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(); + + /*virtual*/ void draw(); + + bool postBuild(); + + void refresh(); + + // 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 00000000000..07a76e050b9 --- /dev/null +++ b/indra/newview/llpaneldirevents.cpp @@ -0,0 +1,280 @@ +/** + * @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 + +// 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 t_panel_dir_events("panel_dir_events"); + +LLPanelDirEvents::LLPanelDirEvents() + : LLPanelDirBrowser(), + mDoneQuery(FALSE), + mDay(0) +{ + // more results per page for this + mResultsPerPage = 200; +} + +bool LLPanelDirEvents::postBuild() +{ + LLPanelDirBrowser::postBuild(); + + childSetCommitCallback("date_mode", onDateModeCallback, this); + + childSetAction("<<", onBackBtn, this); + childSetAction(">>", onForwardBtn, this); + + childSetAction("Today", onClickToday, 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::draw() +{ + refresh(); + + LLPanelDirBrowser::draw(); +} + +void LLPanelDirEvents::refresh() +{ + updateMaturityCheckbox(); +} + + +void LLPanelDirEvents::setDay(S32 day) +{ + mDay = day; + + // Get time UTC + time_t utc_time = time_corrected(); + + // Correct for offset + utc_time += day * 24 * 60 * 60; + + // 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 * 24 * 60 * 60; + + // 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; + + mDoneQuery = TRUE; + + U32 scope = DFQ_DATE_EVENTS; + if ( gAgent.wantsPGOnly()) scope |= DFQ_PG_SIMS_ONLY; + if ( childGetValue("incpg").asBoolean() ) scope |= DFQ_INC_PG; + if ( childGetValue("incmature").asBoolean() ) scope |= DFQ_INC_MATURE; + if ( childGetValue("incadult").asBoolean() ) scope |= DFQ_INC_ADULT; + + // Add old query flags in case we are talking to an old server + if ( childGetValue("incpg").asBoolean() && !childGetValue("incmature").asBoolean()) + { + scope |= DFQ_PG_EVENTS_ONLY; + } + + 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("Today"); + self->childEnable(">>"); + self->childEnable("<<"); + } + else + { + self->childDisable("Today"); + self->childDisable(">>"); + self->childDisable("<<"); + } +} + +// static +void LLPanelDirEvents::onClickToday(void *userdata) +{ + LLPanelDirEvents *self = (LLPanelDirEvents *)userdata; + self->resetSearchStart(); + self->setDay(0); + self->performQuery(); +} + + +// 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 00000000000..0383edbe6cf --- /dev/null +++ b/indra/newview/llpaneldirevents.h @@ -0,0 +1,68 @@ +/** + * @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(); + + /*virtual*/ void draw(); + + bool postBuild(); + + /*virtual*/ void performQuery(); + + void performQueryOrDelete(U32 event_id); + + void refresh(); + + // 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 onClickToday(void *userdata); + static void onCommitMature(LLUICtrl* ctrl, void* data); + static void onClickSearch(void *data); + +protected: + bool mDoneQuery; + S32 mDay; // 0 = today, 1 = tomorrow +}; + + +#endif diff --git a/indra/newview/llpaneldirgroups.cpp b/indra/newview/llpaneldirgroups.cpp new file mode 100644 index 00000000000..63ae0f59ab8 --- /dev/null +++ b/indra/newview/llpaneldirgroups.cpp @@ -0,0 +1,93 @@ +/** + * @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" +#include "message.h" + +static LLPanelInjector t_panel_dir_groups("panel_dir_groups"); + +LLPanelDirGroups::LLPanelDirGroups() + : LLPanelDirBrowser() +{ + mMinSearchChars = 3; +} + + +bool LLPanelDirGroups::postBuild() +{ + LLPanelDirBrowser::postBuild(); + + //getChild("name")->setKeystrokeCallback(boost::bind(&LLPanelDirBrowser::onKeystrokeName, _1, _2), NULL); + + childSetAction("Search", &LLPanelDirBrowser::onClickSearchCore, this); + //childDisable("Search"); + setDefaultBtn( "Search" ); + + return true; +} + +LLPanelDirGroups::~LLPanelDirGroups() +{ + // Children all cleaned up by default view destructor. +} + +// 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 00000000000..1e10353e2ad --- /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 00000000000..cce0e4656c7 --- /dev/null +++ b/indra/newview/llpaneldirland.cpp @@ -0,0 +1,268 @@ +/** + * @file llpaneldirland.cpp + * @brief Land For Sale and Auction in the Find directory. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpaneldirland.h" + +// linden library includes +#include "llfontgl.h" +#include "llparcel.h" +#include "llqueryflags.h" +#include "message.h" + +// viewer project includes +#include "llagent.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "lllineeditor.h" +#include "llnotificationsutil.h" +#include "llscrolllistctrl.h" +#include "llstatusbar.h" +#include "lluiconstants.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 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("priceedit"); + priceedit->setPrevalidateInput(LLTextValidate::validateNonNegativeS32); + + childSetEnabled("areaedit", gSavedSettings.getBOOL("FindLandArea")); + LLLineEditor* areaedit = getChild("areaedit"); + areaedit->setPrevalidateInput(LLTextValidate::validateNonNegativeS32); + + childSetAction("Search", onClickSearchCore, this); + setDefaultBtn("Search"); + + mCurrentSortColumn = "per_meter"; + + LLScrollListCtrl* results = getChild("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. +} + +// virtual +void LLPanelDirLand::draw() +{ + updateMaturityCheckbox(); + + LLPanelDirBrowser::draw(); +} + +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() +{ + BOOL inc_pg = childGetValue("incpg").asBoolean(); + BOOL inc_mature = childGetValue("incmature").asBoolean(); + BOOL inc_adult = childGetValue("incadult").asBoolean(); + 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("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 00000000000..50fc633f23d --- /dev/null +++ b/indra/newview/llpaneldirland.h @@ -0,0 +1,61 @@ +/** + * @file llpaneldirland.h + * @brief Land For Sale and Auction in the Find directory. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLPANELDIRLAND_H +#define LL_LLPANELDIRLAND_H + +#include "llpaneldirbrowser.h" + +class LLUICtrl; +class LLPanelDirBrowser; + +class LLPanelDirLand : public LLPanelDirBrowser +{ +public: + LLPanelDirLand(); + /*virtual*/ ~LLPanelDirLand(); + + /*virtual*/ void draw(); + + 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 00000000000..75226f3a09f --- /dev/null +++ b/indra/newview/llpaneldirpeople.cpp @@ -0,0 +1,106 @@ +/** + * @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 t_panel_dir_people("panel_dir_people"); + +LLPanelDirPeople::LLPanelDirPeople() +: LLPanelDirBrowser() +{ + mMinSearchChars = 3; +} + +bool LLPanelDirPeople::postBuild() +{ + LLPanelDirBrowser::postBuild(); + + //getChild("name")->setKeystrokeCallback(boost::bind(&LLPanelDirBrowser::onKeystrokeName, _1, _2), NULL); + + childSetAction("Search", &LLPanelDirBrowser::onClickSearchCore, this); + //childDisable("Search"); + 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 00000000000..a8a7d17cb23 --- /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 00000000000..2e221f393a7 --- /dev/null +++ b/indra/newview/llpaneldirplaces.cpp @@ -0,0 +1,214 @@ +/** + * @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" + +// linden library includes +#include "llfontgl.h" +#include "message.h" +#include "lldir.h" +#include "llparcel.h" +#include "llregionflags.h" +#include "llqueryflags.h" + +// viewer project includes +#include "llagent.h" +#include "llbutton.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "llfloaterdirectory.h" +#include "lllineeditor.h" +#include "llnotificationsutil.h" +#include "llviewerwindow.h" +#include "llpaneldirbrowser.h" +#include "llsearcheditor.h" +#include "lltextbox.h" +#include "llviewercontrol.h" + +static LLPanelInjector t_panel_dir_people("panel_dir_places"); + +LLPanelDirPlaces::LLPanelDirPlaces() + : LLPanelDirBrowser() +{ + mMinSearchChars = 3; +} + +bool LLPanelDirPlaces::postBuild() +{ + LLPanelDirBrowser::postBuild(); + + //getChild("name")->setKeystrokeCallback(boost::bind(&LLPanelDirBrowser::onKeystrokeName, _1, _2), NULL); + + childSetAction("Search", &LLPanelDirBrowser::onClickSearchCore, this); + //childDisable("Search"); + + mCurrentSortColumn = "dwell"; + mCurrentSortAscending = FALSE; + + childSetVisible("Category", true); + childSetEnabled("Category", true); + + // Don't prepopulate the places list, as it hurts the database as of 2006-12-04. JC + // initialQuery(); + + return true; +} + +LLPanelDirPlaces::~LLPanelDirPlaces() +{ + // MBW -- HACK!!! + // This looks like some sort of compiler bug. We have a mysterious crash during initialization on powerpc boxes. + // The crash seems unrelated to this code, but the commit that introduced it was narrowed down to this file. + // Adding llinfos calls to both the constructor and destructor here makes the crash go away, even though they don't get called before the point of the crash. + // This is wrong on many levels and scares the hell out of me. + LL_INFOS() << "called" << LL_ENDL; + // Children all cleaned up by default view destructor. +} + + +// virtual +void LLPanelDirPlaces::draw() +{ + updateMaturityCheckbox(); + + LLPanelDirBrowser::draw(); +} + +// 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(); + + if( gSavedSettings.getBOOL("ShowPGSims")) + { + flags |= DFQ_INC_PG; + } + + if( gSavedSettings.getBOOL("ShowMatureSims") && mature_enabled) + { + flags |= DFQ_INC_MATURE; + } + + if( gSavedSettings.getBOOL("ShowAdultSims") && adult_enabled) + { + flags |= DFQ_INC_ADULT; + } + + // Pack old query flag in case we are talking to an old server + if ( ((flags & DFQ_INC_PG) == DFQ_INC_PG) && !((flags & DFQ_INC_MATURE) == DFQ_INC_MATURE) ) + { + flags |= DFQ_PG_PARCELS_ONLY; + } + + 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 00000000000..9dea576e873 --- /dev/null +++ b/indra/newview/llpaneldirplaces.h @@ -0,0 +1,55 @@ +/** + * @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(); + + /*virtual*/ void draw(); + + bool postBuild(); + + static void onClickSearch(void *userdata); + + void performQuery(); + + // 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/llpaneleventinfo.cpp b/indra/newview/llpaneleventinfo.cpp new file mode 100644 index 00000000000..aaafbc6b327 --- /dev/null +++ b/indra/newview/llpaneleventinfo.cpp @@ -0,0 +1,213 @@ +/** + * @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 "message.h" +#include "llui.h" + +#include "llagent.h" +#include "llviewerwindow.h" +#include "llbutton.h" +#include "llcachename.h" +#include "lleventflags.h" +#include "llfloater.h" +#include "llfloaterreg.h" +#include "llfloaterworldmap.h" +#include "llinventorymodel.h" +#include "lltextbox.h" +#include "llviewertexteditor.h" +#include "lluiconstants.h" +#include "llviewercontrol.h" +#include "llweb.h" +#include "llworldmap.h" +#include "lluictrlfactory.h" + +static LLPanelInjector t_panel_event_info("panel_event_info"); + +LLPanelEventInfo::LLPanelEventInfo() + : LLPanel() +{ +} + + +LLPanelEventInfo::~LLPanelEventInfo() +{ + if (mEventInfoConnection.connected()) + { + mEventInfoConnection.disconnect(); + } +} + + +bool LLPanelEventInfo::postBuild() +{ + mTBName = getChild("event_name"); + + mTBCategory = getChild("event_category"); + mTBDate = getChild("event_date"); + mTBDuration = getChild("event_duration"); + mTBDesc = getChild("event_desc"); + mTBDesc->setWordWrap(TRUE); + + mTBRunBy = getChild("event_runby"); + mTBLocation = getChild("event_location"); + mTBCover = getChild("event_cover"); + + mTeleportBtn = getChild( "teleport_btn"); + mTeleportBtn->setClickedCallback(boost::bind(&LLPanelEventInfo::onClickTeleport, this)); + + mMapBtn = getChild( "map_btn"); + mMapBtn->setClickedCallback(boost::bind(&LLPanelEventInfo::onClickMap, this)); + + mNotifyBtn = getChild( "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); + mTBCategory->setText(event.mCategoryStr); + mTBDate->setText(event.mTimeStr); + mTBDesc->setText(event.mDesc); + + 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)); + } + + F32 global_x = (F32)event.mPosGlobal.mdV[VX]; + F32 global_y = (F32)event.mPosGlobal.mdV[VY]; + + S32 region_x = llround(global_x) % REGION_WIDTH_UNITS; + S32 region_y = llround(global_y) % REGION_WIDTH_UNITS; + S32 region_z = (S32)llround((F32)event.mPosGlobal.mdV[VZ]); + + std::string desc = event.mSimName + llformat(" (%d, %d, %d)", region_x, region_y, region_z); + mTBLocation->setText(desc); + + 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 00000000000..4f0e547493d --- /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 65aa1876b07..ecb66f9cea4 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(user_data); diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h index fa0e1d4104b..b43a93bc400 100644 --- a/indra/newview/llpanelgroup.h +++ b/indra/newview/llpanelgroup.h @@ -87,6 +87,7 @@ class LLPanelGroup : public LLPanel, 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 7deb1d9fd42..5435a79e16e 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(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 fc04d8d45db..8360380b22a 100644 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -81,6 +81,8 @@ class LLPanelPlaces : public LLPanel /*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 6ea9cd2b92f..ee94277ecca 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 c207a4162a3..f2e9c1341f1 100644 --- a/indra/newview/llpanelprofile.h +++ b/indra/newview/llpanelprofile.h @@ -111,6 +111,8 @@ class LLPanelProfileSecondLife 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 @@ class LLPanelProfileSecondLife 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 3786a9b1609..cec34635f69 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 3b35ca8db1b..a17c2f71df7 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" @@ -504,6 +505,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("simple_snapshot", "floater_simple_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("legacy_search", "floater_directory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("profile", "floater_profile.xml",(LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("guidebook", "floater_how_to.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("slapp_test", "floater_test_slapp.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); 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 0000000000000000000000000000000000000000..d121833b475fcfd92b3e2c7a536123f0fa611f08 GIT binary patch literal 1068 zcmZQzU}As)0R{mE1r8@W8wPwBsQN!Xj888}4x~4!#>a5t(=Xuio_^9#$~**l3s;QnChM^&lD)&LI6T z3{rzlFH8(157GzIo0NNzY%@S{-9O{i|2x3w2e||07JP1i*$-0-(p%ec=YMX+DKHHZ zC!`;w24pu#Z+*wZ{}t6Iz!t-~AsP4}|o>^n=n9NFS+sk>h|| iy~t*O+)K#KKzT3-2?})$^9=U%_tTAV^Yn4mV*mjCqF5>b literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..7805dbce60eb7c58bb99826157ed222813c27419 GIT binary patch literal 1068 zcmb7?&q~8U5XPtW(4M5=#iK9K-g*-cg$O~h(0_VtFVce`?LiS=$Oj9#^%ZtH-!|Wp zuA7Jp!zMG|@0;0dL@tDDAOpGSPws97VM{yG@xffYvkq-sL#~w42X&@_F8CHw_<9qs zKdSn!!KW)-MbH;Dcj+|6V;Ew^|#Ib7NNB*BG*v zLk$}AiX*VQs3&>MVYQS8X7YX4ruj(prUz=KftKe8>|2fdsy&mf=S)iv@c!O#cZ^NN zHT#c^DQ)DQeni34v65mBNO7&s5J7=kB|kc>NQsB<1b{;JG(`eWoFh_wh%Qi zWSm1;soJ&cO)Y)5H&OHj)-sG%vU!kzJ6zAL7l5QDl+Zn@JaVB{luRfU+1dHENiIy0 YF#2#F?j9#k&3$uwbMk!EOed%I2Uv>&3jhEB literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..61c879bc923c7d1ee625a3995012a3ddecca363d GIT binary patch literal 1068 zcmbW0Jqp4=5QW#+Smp>`KszffM2HZK3jQHtAyy*d1tj;;(i_?46l>nFZyA)&XofXp?iFV6=-Z<3JkIoFJ>+-}d7Q~;U+Q(n9pQeo&gKu{k#!wf z&B`3y{rTi|WXb6>z6T6EJbS-cJ%@W&)xcv{u)>$Wn{^@c_#N2ag|3G@eV9e7Sn+V4 z)G+IN;5&M<4?Wzj>^I5U1Mf{3t?~RHv*`nmy4i!_O#Z)QbgtvU^4YAm$u3=|%SCTL IO|ztLzMf}`#Q*>R literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..2170c984994e33bb169b499f44c54580bec595a6 GIT binary patch literal 1068 zcma))O-KSk6o7|J2{n{DN>mpiN-q*oXDy5<$doXWE^C2yvPDt^j~(nHMMz|q*0U^K zy>#%_Ey#jS5kXQAX@63$H>+dYvdPZ!@#g1!^O)Hoq>Hd-B~~)j0{}z~Lm&ydaUYO= z`zab>WEQch<*Ln@_Aj8@9RXsS0Q5GIHN=MutK}=_Ob3^s=Z=9mSE%oAF@tdu89?+( zM?P-)c_6MZ^>v6HnL-?h4e6EVkH%bkmR$>I0o^`C$Na(Vu?qFd-(@H@N+7<8Ak+lN zJ?9|vn1S>|8u)u2B6m?~|37ZRaYfy8{K{YGf1>{`LZMdp^{dq1f@sTUby>vv*HV3% zFVtK96V{h}{$HQ&GZJ&1XgNF0VRbvj_W#5C@02HBGwv8c3mb8BQ0}olb&K_)gzzdr z_9F|aMhf^BJbN_?+${(0Gq+S@HDNkr9*bK1&`k(}l_1;Wh`BUs@!R#2#=P8RzLxWI oar3&;RgUTX8@T5CSFXv&_!gzMwCMK)ygu*3ykmLVJLhqdAMMdz%K!iX literal 0 HcmV?d00001 diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index d650e7e791b..ff5737ab49a 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 + + + + + + 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 00000000000..143bfdc0d9a --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_directory.xml @@ -0,0 +1,139 @@ + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 081e5be0145..08521ebe81b 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 @@ - + + + + + Searching... + + + None Found. + + + Enter search terms: + + + + Any Category + + + Shopping + + + Land Rental + + + Property Rental + + + Special Attraction + + + New Products + + + Employment + + + Wanted + + + Service + + + Personal + + + + + + +