123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826 |
- /**
- * @file hbfloaterareasearch.cpp
- * @brief HBFloaterAreaSearch class implementation
- *
- * This class implements a floater where all surroundind objects are listed.
- *
- * $LicenseInfo:firstyear=2009&license=viewergpl$
- *
- * Original code Copyright (c) 2009 Modular Systems Ltd. All rights reserved.
- * Rewritten/augmented code Copyright (c) 2010-2019 Henri Beauchamp.
- *
- * 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$
- *
- * Revision history:
- * - Initial backport from Emerald viewer, modified, debugged, optimized and
- * improved by Henri Beauchamp - Feb 2010.
- * - Speed optimization by Henri Beauchamp - Jul 2011.
- * - Tracked object info added by Henri Beauchamp - Nov 2011.
- * - Further modified and augmented with mutes, derender, report & inspect
- * functions. Henri Beauchamp - May 2013.
- * - Full rewrite by Henri Beauchamp - Aug 2014.
- * - Another partial rewrite by Henri Beauchamp - Nov 2016.
- * - Yet another large rewrite, with proper exclusion of attachments and
- * viewer-side only objects to avoid fake "pending" requests and to prevent
- * sending to the server the bogus/spammy/useless messages corresponding to
- * them. Fixed the bug that caused group-owned objects to stay forever in the
- * "pending" requests list. Added the "Show", "Mute particles", "Mute owner"
- * and "Copy UUID" action. Changed input lines for search input lines.
- * Henri Beauchamp - Jan 2019.
- * - On "Refresh", clear the cached objects list so that any renamed object
- * will be properly refreshed. Henri Beauchamp - Apr 2021.
- */
- #include "llviewerprecompiledheaders.h"
- #include "hbfloaterareasearch.h"
- #include "llcachename.h"
- #include "llcombobox.h"
- #include "lllineeditor.h"
- #include "llscrolllistctrl.h"
- #include "lltabcontainer.h"
- #include "lluictrlfactory.h"
- #include "llagent.h"
- #include "llappviewer.h" // For gFrameTimeSeconds
- #include "llfloaterinspect.h"
- #include "llfloatermute.h"
- #include "llfloaterreporter.h"
- #include "lltracker.h"
- #include "llselectmgr.h"
- #include "llviewercontrol.h"
- #include "llviewerobjectlist.h"
- #include "llviewerwindow.h" // For gWindowp
- // static variables
- F32 HBFloaterAreaSearch::sLastUpdateTime = 0.f;
- bool HBFloaterAreaSearch::sIsDirty = false;
- bool HBFloaterAreaSearch::sUpdateDone = false;
- bool HBFloaterAreaSearch::sTracking = false;
- LLUUID HBFloaterAreaSearch::sTrackingObjectID;
- LLVector3d HBFloaterAreaSearch::sTrackingLocation;
- std::string HBFloaterAreaSearch::sTrackingInfoLine;
- HBFloaterAreaSearch::object_details_map_t HBFloaterAreaSearch::sObjectDetails;
- // Minimum interval between idle updates (and list refreshes) in seconds:
- constexpr F32 MIN_REFRESH_INTERVAL = 0.25f;
- // Interval of time between auto-refresh of stalled objects details requests in
- // seconds:
- constexpr F32 AUTO_REFRESH_INTERVAL = 10.f;
- HBFloaterAreaSearch::HBFloaterAreaSearch(const LLSD&)
- {
- LLUICtrlFactory::getInstance()->buildFloater(this,
- "floater_area_search.xml");
- }
- //virtual
- bool HBFloaterAreaSearch::postBuild()
- {
- mResultsList = getChild<LLScrollListCtrl>("result_list");
- mResultsList->setCommitCallback(onSelectResult);
- mResultsList->setDoubleClickCallback(onDoubleClickResult);
- mResultsList->setCallbackUserData(this);
- mResultsList->sortByColumn("name", true);
- mCounterText = getChild<LLTextBox>("counter");
- if (sTracking)
- {
- mCounterText->setText(sTrackingInfoLine);
- }
- mMuteFlyoutBtn = getChild<LLFlyoutButton>("mute");
- mMuteFlyoutBtn->setCommitCallback(onClickMute);
- mMuteFlyoutBtn->setCallbackUserData(this);
- mDerenderBtn = getChild<LLButton>("derender");
- mDerenderBtn->setClickedCallback(onClickDerender, this);
-
- mReportBtn = getChild<LLButton>("report");
- mReportBtn->setClickedCallback(onClickReport, this);
- mShowBtn = getChild<LLButton>("show");
- mShowBtn->setClickedCallback(onClickShow, this);
- mInspectFlyoutBtn = getChild<LLFlyoutButton>("inspect");
- mInspectFlyoutBtn->setCommitCallback(onClickInspect);
- mInspectFlyoutBtn->setCallbackUserData(this);
- mRefreshBtn = getChild<LLButton>("refresh");
- mRefreshBtn->setClickedCallback(onClickRefresh, this);
- childSetAction("close", onClickClose, this);
- mNameInputLine = getChild<LLSearchEditor>("name_query");
- mNameInputLine->setSearchCallback(onSearchEdit, mNameInputLine);
- mDescInputLine = getChild<LLSearchEditor>("desc_query");
- mDescInputLine->setSearchCallback(onSearchEdit, mDescInputLine);
- mOwnerInputLine = getChild<LLSearchEditor>("owner_query");
- mOwnerInputLine->setSearchCallback(onSearchEdit, mOwnerInputLine);
- mGroupInputLine = getChild<LLSearchEditor>("group_query");
- mGroupInputLine->setSearchCallback(onSearchEdit, mGroupInputLine);
- sIsDirty = true;
- return true;
- }
- //virtual
- void HBFloaterAreaSearch::draw()
- {
- if (sTracking)
- {
- F32 dist = 3.f;
- if (gTracker.getTrackingStatus() == LLTracker::TRACKING_LOCATION)
- {
- dist = fabsf((F32)(gTracker.getTrackedPositionGlobal() -
- sTrackingLocation).length());
- }
- if (dist > 2.f)
- {
- // Tracker stopped or tracking another location
- sTracking = false;
- sIsDirty = true;
- sTrackingInfoLine.clear();
- }
- }
- if (sIsDirty && sUpdateDone && getVisible() && !isMinimized())
- {
- uuid_vec_t selected = mResultsList->getSelectedIDs();
- S32 scrollpos = mResultsList->getScrollPos();
- mResultsList->deleteAllItems();
- LLViewerObject* objectp;
- const LLViewerRegion* our_region = gAgent.getRegion();
- bool searching_uuid = mSearchUUID.notNull();
- if (searching_uuid)
- {
- objectp = gObjectList.findObject(mSearchUUID);
- if (objectp)
- {
- objectp = objectp->getRootEdit();
- }
- if (isObjectOfInterest(objectp) && !objectp->isDead() &&
- objectp->getRegion() == our_region)
- {
- const LLUUID& object_id = objectp->getID();
- if (checkObjectDetails(object_id))
- {
- addInResultsList(object_id, false);
- }
- }
- }
- S32 total= 0;
- S32 pending = 0;
- for (object_details_map_t::iterator it = sObjectDetails.begin();
- it != sObjectDetails.end(); )
- {
- object_details_map_t::iterator cur_it = it++;
- const LLUUID& object_id = cur_it->first;
- objectp = gObjectList.findObject(object_id);
- if (!objectp || objectp->isDead() ||
- objectp->getRegion() != our_region)
- {
- sObjectDetails.erase(cur_it);
- continue;
- }
- if (!cur_it->second.valid())
- {
- ++pending;
- }
- else if (!searching_uuid)
- {
- addInResultsList(object_id, true);
- }
- ++total;
- }
- mResultsList->sortItems();
- mResultsList->selectMultiple(selected);
- mResultsList->setScrollPos(scrollpos);
- if (!sTracking)
- {
- mCounterText->setText(llformat("%d listed/%d pending/%d total",
- mResultsList->getItemCount(), pending,
- total));
- }
- setButtonsStatus();
- sIsDirty = sUpdateDone = false;
- }
- LLFloater::draw();
- }
- void HBFloaterAreaSearch::addInResultsList(const LLUUID& object_id,
- bool match_filters)
- {
- HBObjectDetails* details = &sObjectDetails[object_id];
- if (!details->valid())
- {
- // We did not yet receive the details for this object.
- return;
- }
- std::string tmp;
- std::string object_name = details->name;
- if (match_filters && !mSearchedName.empty())
- {
- tmp = object_name;
- LLStringUtil::toLower(tmp);
- if (tmp.find(mSearchedName) == std::string::npos)
- {
- return; // Failed name filter match
- }
- }
- std::string object_desc = details->desc;
- if (match_filters && !mSearchedDesc.empty())
- {
- tmp = object_desc;
- LLStringUtil::toLower(tmp);
- if (tmp.find(mSearchedDesc) == std::string::npos)
- {
- return; // Failed description filter match
- }
- }
- std::string object_owner;
- if (gCacheNamep)
- {
- const LLUUID& owner_id = details->owner_id;
- // Note: a valid entry always got either a non-null owner or group Id
- if (owner_id.isNull())
- {
- gCacheNamep->getGroupName(details->group_id, object_owner);
- }
- else
- {
- gCacheNamep->getFullName(owner_id, object_owner);
- }
- }
- if (match_filters && !mSearchedOwner.empty())
- {
- tmp = object_owner;
- LLStringUtil::toLower(tmp);
- if (tmp.find(mSearchedOwner) == std::string::npos)
- {
- return; // Failed owner name filter match
- }
- }
- std::string object_group;
- if (gCacheNamep && details->group_id.notNull())
- {
- gCacheNamep->getGroupName(details->group_id, object_group);
- }
- if (match_filters && !mSearchedGroup.empty())
- {
- tmp = object_group;
- LLStringUtil::toLower(tmp);
- if (tmp.find(mSearchedGroup) == std::string::npos)
- {
- return; // Failed group name filter match
- }
- }
- std::string style;
- if (sTracking && object_id == sTrackingObjectID)
- {
- style = "BOLD";
- }
- else
- {
- style = "NORMAL";
- }
- LLSD element;
- element["id"] = object_id;
- LLSD& column_name = element["columns"][LIST_OBJECT_NAME];
- column_name["column"] = "name";
- column_name["type"] = "text";
- column_name["value"] = object_name;
- column_name["font-style"] = style;
- if (object_id == mSearchUUID)
- {
- column_name["color"] = LLColor4::red2.getValue();
- }
- LLSD& column_desc = element["columns"][LIST_OBJECT_DESC];
- column_desc["column"] = "description";
- column_desc["type"] = "text";
- column_desc["value"] = object_desc;
- column_desc["font-style"] = style;
- LLSD& column_owner = element["columns"][LIST_OBJECT_OWNER];
- column_owner["column"] = "owner";
- column_owner["type"] = "text";
- column_owner["value"] = object_owner;
- column_owner["font-style"] = style;
- LLSD& column_group = element["columns"][LIST_OBJECT_GROUP];
- column_group["column"] = "group";
- column_group["type"] = "text";
- column_group["value"] = object_group;
- column_group["font-style"] = style;
- mResultsList->addElement(element, ADD_BOTTOM);
- }
- void HBFloaterAreaSearch::setButtonsStatus()
- {
- LLScrollListItem* item = mResultsList->getFirstSelected();
- if (item)
- {
- object_details_map_t::iterator it =
- sObjectDetails.find(item->getUUID());
- bool is_ours = it != sObjectDetails.end() &&
- it->second.owner_id == gAgentID;
- mMuteFlyoutBtn->setEnabled(!is_ours);
- mDerenderBtn->setEnabled(true);
- mReportBtn->setEnabled(!is_ours);
- mShowBtn->setEnabled(true);
- mInspectFlyoutBtn->setEnabled(true);
- }
- else
- {
- mMuteFlyoutBtn->setEnabled(false);
- mDerenderBtn->setEnabled(false);
- mReportBtn->setEnabled(false);
- mShowBtn->setEnabled(false);
- mInspectFlyoutBtn->setEnabled(false);
- }
- }
- //static
- void HBFloaterAreaSearch::newRegion()
- {
- // We changed region so we can clear the object details cache.
- sObjectDetails.clear();
- sTracking = false;
- sIsDirty = true;
- HBFloaterAreaSearch* self = findInstance();
- if (self)
- {
- self->mResultsList->deleteAllItems();
- self->mCounterText->setText(self->getString("counter_text"));
- }
- }
- //static
- bool HBFloaterAreaSearch::isObjectOfInterest(LLViewerObject* objectp)
- {
- if (!objectp) return false;
- LLPCode pcode = objectp->getPCode();
- // Reject all avatars and all viewer-side only objects
- if (pcode != LL_PCODE_VOLUME && pcode != LL_PCODE_LEGACY_GRASS &&
- pcode != LL_PCODE_LEGACY_TREE)
- {
- return false;
- }
- // Reject temporary objects, attachments and child primitives
- return !objectp->flagTemporaryOnRez() && !objectp->isAttachment() &&
- objectp->isRoot();
- }
- //static
- void HBFloaterAreaSearch::idleUpdate()
- {
- if (gFrameTimeSeconds - sLastUpdateTime >= MIN_REFRESH_INTERVAL &&
- findInstance())
- {
- const LLViewerRegion* our_region = gAgent.getRegion();
- for (S32 i = 0, count = gObjectList.getNumObjects(); i < count; ++i)
- {
- LLViewerObject* objectp = gObjectList.getObject(i);
- if (isObjectOfInterest(objectp) &&
- objectp->getRegion() == our_region)
- {
- if (!checkObjectDetails(objectp->getID()))
- {
- sIsDirty = true;
- }
- }
- }
- sLastUpdateTime = gFrameTimeSeconds;
- sUpdateDone = true;
- }
- }
- //static
- bool HBFloaterAreaSearch::checkObjectDetails(const LLUUID& object_id)
- {
- HBObjectDetails* details;
- object_details_map_t::iterator it = sObjectDetails.find(object_id);
- if (it == sObjectDetails.end())
- {
- details = &sObjectDetails[object_id];
- }
- else
- {
- details = &it->second;
- }
- if (details->valid())
- {
- return true;
- }
- if (gFrameTimeSeconds - details->time_stamp > AUTO_REFRESH_INTERVAL)
- {
- details->time_stamp = gFrameTimeSeconds;
- LLMessageSystem* msg = gMessageSystemp;
- msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgentID);
- msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addU32Fast(_PREHASH_RequestFlags, 0);
- msg->addUUIDFast(_PREHASH_ObjectID, object_id);
- gAgent.sendReliableMessage();
- LL_DEBUGS("AreaSearch") << "Sent data request for object " << object_id
- << LL_ENDL;
- }
- return false;
- }
- //static
- void HBFloaterAreaSearch::processObjectPropertiesFamily(LLMessageSystem* msg)
- {
- if (!msg || !findInstance()) return;
- LLUUID object_id;
- msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_ObjectID, object_id);
- bool exists = sObjectDetails.count(object_id) != 0;
- if (!exists)
- {
- LLViewerObject* objectp = gObjectList.findObject(object_id);
- if (!isObjectOfInterest(objectp) || objectp->isDead() ||
- objectp->getRegion() != gAgent.getRegion())
- {
- LL_DEBUGS("AreaSearch") << "Rejected info for object "
- << object_id << LL_ENDL;
- return; // Not an interesting object for us
- }
- }
- // Update the object's details whether they were requested or not (to avoid
- // having to request them later).
- HBObjectDetails* details = &sObjectDetails[object_id];
- details->time_stamp = gFrameTimeSeconds;
- msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, details->owner_id);
- msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_GroupID, details->group_id);
- msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, details->name);
- msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description,
- details->desc);
- if (gCacheNamep)
- {
- if (details->owner_id.notNull())
- {
- gCacheNamep->get(details->owner_id, false,
- boost::bind(&HBFloaterAreaSearch::setDirty));
- }
- if (details->group_id.notNull())
- {
- gCacheNamep->get(details->group_id, true,
- boost::bind(&HBFloaterAreaSearch::setDirty));
- }
- }
- LL_DEBUGS("AreaSearch") << "Got info for " << (exists ? "requested" : "new")
- << " object " << object_id << LL_ENDL;
- sIsDirty = true;
- }
- //static
- void HBFloaterAreaSearch::onSelectResult(LLUICtrl*, void* userdata)
- {
- HBFloaterAreaSearch* self = (HBFloaterAreaSearch*)userdata;
- if (self)
- {
- self->setButtonsStatus();
- }
- }
- //static
- void HBFloaterAreaSearch::onDoubleClickResult(void* userdata)
- {
- HBFloaterAreaSearch* self = (HBFloaterAreaSearch*)userdata;
- if (!self) return;
- LLScrollListItem* item = self->mResultsList->getFirstSelected();
- if (!item) return;
- LLUUID object_id = item->getUUID();
- LLViewerObject* objectp = gObjectList.findObject(object_id);
- if (objectp)
- {
- sTrackingObjectID = object_id;
- sTrackingLocation = objectp->getPositionGlobal();
- LLVector3 region_pos = objectp->getPositionRegion();
- sTrackingInfoLine = llformat("Tracking object at position: %d, %d, %d",
- (S32)region_pos.mV[VX],
- (S32)region_pos.mV[VY],
- (S32)region_pos.mV[VZ]);
- self->mCounterText->setText(sTrackingInfoLine);
- gTracker.trackLocation(sTrackingLocation,
- sObjectDetails[object_id].name, "",
- LLTracker::LOCATION_ITEM);
- sTracking = sIsDirty = true;
- }
- }
- //static
- void HBFloaterAreaSearch::onClickDerender(void* userdata)
- {
- HBFloaterAreaSearch* self = (HBFloaterAreaSearch*)userdata;
- if (!self) return;
- LLScrollListItem* item = self->mResultsList->getFirstSelected();
- if (!item) return;
- LLUUID object_id = item->getUUID();
- LLViewerObject* objectp = gObjectList.findObject(object_id);
- if (objectp)
- {
- // Make sure the object is not selected
- gSelectMgr.removeObjectFromSelections(object_id);
- // Remove the object from the list
- sObjectDetails.erase(object_id);
- // Mark the list as dirty
- sIsDirty = true;
- // Derender by killing the object.
- gObjectList.killObject(objectp);
- }
- }
- //static
- void HBFloaterAreaSearch::onClickMute(LLUICtrl* ctrl, void* userdata)
- {
- HBFloaterAreaSearch* self = (HBFloaterAreaSearch*)userdata;
- if (!self || !ctrl) return;
- LLScrollListItem* item = self->mResultsList->getFirstSelected();
- if (!item) return;
- LLUUID object_id = item->getUUID();
- object_details_map_t::iterator it = sObjectDetails.find(object_id);
- if (it == sObjectDetails.end() || it->second.owner_id == gAgentID)
- {
- return; // Abort !
- }
- std::string operation = ctrl->getValue().asString();
- if (operation == "mute_by_name")
- {
- std::string name = it->second.name;
- if (!name.empty())
- {
- LLMute mute(LLUUID::null, name, LLMute::BY_NAME);
- if (LLMuteList::add(mute))
- {
- LLFloaterMute::selectMute(name);
- }
- }
- }
- else if (operation == "mute_particles")
- {
- if (gCacheNamep)
- {
- LLUUID owner_id = it->second.owner_id;
- const LLUUID& group_id = it->second.group_id;
- bool group_owned = owner_id.isNull() && group_id.notNull();
- std::string object_owner;
- if (group_owned)
- {
- gCacheNamep->getGroupName(group_id, object_owner);
- owner_id = group_id;
- }
- else
- {
- gCacheNamep->getFullName(owner_id, object_owner);
- }
- LLMute::EType type = group_owned ? LLMute::GROUP : LLMute::AGENT;
- LLMute mute(owner_id, object_owner, type);
- if (LLMuteList::add(mute, LLMute::flagParticles))
- {
- LLFloaterMute::selectMute(mute.mID);
- }
- }
- }
- else if (operation == "mute_owner")
- {
- if (gCacheNamep)
- {
- LLUUID owner_id = it->second.owner_id;
- const LLUUID& group_id = it->second.group_id;
- bool group_owned = owner_id.isNull() && group_id.notNull();
- std::string object_owner;
- if (group_owned)
- {
- gCacheNamep->getGroupName(group_id, object_owner);
- owner_id = group_id;
- }
- else
- {
- gCacheNamep->getFullName(owner_id, object_owner);
- }
- LLMute::EType type = group_owned ? LLMute::GROUP : LLMute::AGENT;
- LLMute mute(owner_id, object_owner, type);
- if (LLMuteList::add(mute))
- {
- LLFloaterMute::selectMute(mute.mID);
- }
- }
- }
- else
- {
- LLMute mute(object_id, it->second.name, LLMute::OBJECT);
- if (LLMuteList::add(mute))
- {
- LLFloaterMute::selectMute(mute.mID);
- }
- }
- }
- //static
- void HBFloaterAreaSearch::onClickReport(void* userdata)
- {
- HBFloaterAreaSearch* self = (HBFloaterAreaSearch*)userdata;
- if (!self) return;
- LLScrollListItem* item = self->mResultsList->getFirstSelected();
- if (item)
- {
- LLFloaterReporter::showFromObject(item->getUUID());
- }
- }
- //static
- void HBFloaterAreaSearch::onClickShow(void* userdata)
- {
- HBFloaterAreaSearch* self = (HBFloaterAreaSearch*)userdata;
- if (!self) return;
- LLScrollListItem* item = self->mResultsList->getFirstSelected();
- if (item)
- {
- gAgent.lookAtObject(item->getUUID(), CAMERA_POSITION_OBJECT);
- }
- }
- //static
- void HBFloaterAreaSearch::onClickInspect(LLUICtrl* ctrl, void* userdata)
- {
- HBFloaterAreaSearch* self = (HBFloaterAreaSearch*)userdata;
- if (!self || !ctrl || !gWindowp) return;
- LLScrollListItem* item = self->mResultsList->getFirstSelected();
- if (!item) return;
- LLUUID object_id = item->getUUID();
- std::string operation = ctrl->getValue().asString();
- if (operation == "copy_uuid")
- {
- gWindowp->copyTextToClipboard(utf8str_to_wstring(object_id.asString()));
- }
- else if (operation == "debug")
- {
- LLViewerObject* objectp = gObjectList.findObject(object_id);
- if (objectp)
- {
- objectp->toggleDebugUpdateMsg();
- }
- }
- else
- {
- LLViewerObject* objectp = gObjectList.findObject(object_id);
- if (objectp)
- {
- std::vector<LLViewerObject*> objects;
- objects.push_back(objectp);
- gSelectMgr.selectObjectAndFamily(objects);
- LLFloaterInspect::show();
- }
- }
- }
- //static
- void HBFloaterAreaSearch::onClickRefresh(void* userdata)
- {
- sObjectDetails.clear();
- sTracking = false;
- sIsDirty = true;
- }
- //static
- void HBFloaterAreaSearch::onClickClose(void* userdata)
- {
- HBFloaterAreaSearch* self = (HBFloaterAreaSearch*)userdata;
- if (self)
- {
- self->close();
- }
- }
- //static
- void HBFloaterAreaSearch::onSearchEdit(const std::string& search_string,
- void* userdata)
- {
- HBFloaterAreaSearch* self = findInstance();
- LLSearchEditor* search = (LLSearchEditor*)userdata;
- if (self && search)
- {
- std::string text = search_string;
- LLStringUtil::toLower(text);
- if (search == self->mNameInputLine)
- {
- if (LLUUID::validate(text))
- {
- self->mSearchUUID.set(text);
- self->mSearchedName.clear();
- self->mDescInputLine->clear();
- self->mDescInputLine->setEnabled(false);
- self->mOwnerInputLine->clear();
- self->mOwnerInputLine->setEnabled(false);
- self->mGroupInputLine->clear();
- self->mGroupInputLine->setEnabled(false);
- }
- else
- {
- self->mSearchedName = text;
- self->mSearchUUID.setNull();
- self->mDescInputLine->setText(self->mSearchedDesc);
- self->mDescInputLine->setEnabled(true);
- self->mOwnerInputLine->setEnabled(true);
- self->mOwnerInputLine->setText(self->mSearchedOwner);
- self->mGroupInputLine->setEnabled(true);
- self->mGroupInputLine->setText(self->mSearchedGroup);
- }
- }
- else if (search == self->mDescInputLine)
- {
- self->mSearchedDesc = text;
- }
- else if (search == self->mOwnerInputLine)
- {
- self->mSearchedOwner = text;
- }
- else if (search == self->mGroupInputLine)
- {
- self->mSearchedGroup = text;
- }
- if (text.length() > 2)
- {
- setDirty();
- }
- }
- }
|