1332 lines
34 KiB
C++
1332 lines
34 KiB
C++
/**
|
|
* @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 "llappviewer.h" // for gPacificDaylightTime
|
|
#include "llbutton.h"
|
|
#include "llcheckboxctrl.h"
|
|
#include "llcombobox.h"
|
|
#include "llfloateravatarinfo.h"
|
|
#include "llfloaterdirectory.h"
|
|
#include "lllineeditor.h"
|
|
#include "llmenucommands.h"
|
|
#include "llmenugl.h"
|
|
#include "llnotificationsutil.h"
|
|
#include "llpanelavatar.h"
|
|
#include "llpanelevent.h"
|
|
#include "llpanelgroup.h"
|
|
#include "llpanelclassified.h"
|
|
#include "llpanelpick.h"
|
|
#include "llpanelplace.h"
|
|
#include "llpaneldirland.h"
|
|
#include "llproductinforequest.h"
|
|
#include "llscrolllistctrl.h"
|
|
#include "lltextbox.h"
|
|
#include "lltrans.h"
|
|
#include "lluiconstants.h"
|
|
#include "llviewercontrol.h"
|
|
#include "llviewertexturelist.h"
|
|
#include "llviewermessage.h"
|
|
#include "lluictrlfactory.h"
|
|
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
|
|
LLMap< const LLUUID, LLPanelDirBrowser* > gDirBrowserInstances;
|
|
|
|
LLPanelDirBrowser::LLPanelDirBrowser(const std::string& name, LLFloaterDirectory* floater)
|
|
: LLPanel(name),
|
|
mSearchID(),
|
|
mWantSelectID(),
|
|
mCurrentSortColumn("name"),
|
|
mCurrentSortAscending(TRUE),
|
|
mSearchStart(0),
|
|
mResultsPerPage(100),
|
|
mResultsReceived(0),
|
|
mMinSearchChars(1),
|
|
mResultsContents(),
|
|
mHaveSearchResults(FALSE),
|
|
mDidAutoSelect(TRUE),
|
|
mLastResultTimer(),
|
|
mFloaterDirectory(floater)
|
|
{
|
|
//updateResultCount();
|
|
}
|
|
|
|
BOOL LLPanelDirBrowser::postBuild()
|
|
{
|
|
if (LLUICtrl* ctrl = findChild<LLUICtrl>("results"))
|
|
ctrl->setCommitCallback(onCommitList, this);
|
|
|
|
if (LLButton* btn = findChild<LLButton>("< Prev"))
|
|
{
|
|
childSetAction("< Prev", onClickPrev, this);
|
|
btn->setVisible(false);
|
|
}
|
|
|
|
if (LLButton* btn = findChild<LLButton>("Next >"))
|
|
{
|
|
childSetAction("Next >", onClickNext, this);
|
|
btn->setVisible(false);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
LLPanelDirBrowser::~LLPanelDirBrowser()
|
|
{
|
|
// Children all cleaned up by default view destructor.
|
|
|
|
gDirBrowserInstances.removeData(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 &&
|
|
hasChild("results") && !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;
|
|
childShow("< Prev");
|
|
|
|
performQuery();
|
|
}
|
|
|
|
|
|
// virtual
|
|
void LLPanelDirBrowser::prevPage()
|
|
{
|
|
mSearchStart -= mResultsPerPage;
|
|
if (LLUICtrl* ctrl = findChild<LLUICtrl>("< Prev"))
|
|
ctrl->setVisible(mSearchStart > 0);
|
|
|
|
performQuery();
|
|
}
|
|
|
|
|
|
void LLPanelDirBrowser::resetSearchStart()
|
|
{
|
|
mSearchStart = 0;
|
|
if (LLUICtrl* ctrl = findChild<LLUICtrl>("Next >"))
|
|
ctrl->setVisible(false);
|
|
if (LLUICtrl* ctrl = findChild<LLUICtrl>("< Prev"))
|
|
ctrl->setVisible(false);
|
|
}
|
|
|
|
// protected
|
|
void LLPanelDirBrowser::updateResultCount()
|
|
{
|
|
LLScrollListCtrl* list = findChild<LLScrollListCtrl>("results");
|
|
if (!list) return;
|
|
|
|
S32 result_count = list->getItemCount();
|
|
std::string result_text;
|
|
|
|
if (!mHaveSearchResults) result_count = 0;
|
|
|
|
if (childIsVisible("Next >"))
|
|
{
|
|
// 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(LLTrans::getString("NoneFound"));
|
|
list->operateOnAll(LLCtrlListInterface::OP_DESELECT);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
list->setEnabled(true);
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
|
|
// These check boxes can only be checked if you have the right access to use them
|
|
std::string control_name_pg = getChild<LLCheckBoxCtrl>("incpg")->getControlName();
|
|
std::string control_name_mature = getChild<LLCheckBoxCtrl>("incmature")->getControlName();
|
|
std::string control_name_adult = getChild<LLCheckBoxCtrl>("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);
|
|
|
|
// Teens don't get mature/adult choices
|
|
if (gAgent.wantsPGOnly())
|
|
{
|
|
childHide("incmature");
|
|
childHide("incadult");
|
|
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)
|
|
{
|
|
LLScrollListCtrl* list = findChild<LLScrollListCtrl>("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);
|
|
}
|
|
}
|
|
}
|
|
|
|
U32 LLPanelDirBrowser::getSelectedEventID() const
|
|
{
|
|
if (mFloaterDirectory)
|
|
{
|
|
if (mFloaterDirectory->mPanelEventp)
|
|
{
|
|
return mFloaterDirectory->mPanelEventp->getEventID();
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void LLPanelDirBrowser::getSelectedInfo(LLUUID* id, S32 *type)
|
|
{
|
|
LLScrollListCtrl* list = findChild<LLScrollListCtrl>("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;
|
|
LLScrollListCtrl* list = self->findChild<LLScrollListCtrl>("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);
|
|
|
|
if (type == FOR_SALE_CODE)
|
|
{
|
|
std::string land_type = self->mResultsContents[id_str]["landtype"].asString();
|
|
if (self->mFloaterDirectory && self->mFloaterDirectory->mPanelPlaceSmallp)
|
|
{
|
|
self->mFloaterDirectory->mPanelPlaceSmallp->setLandTypeString(land_type);
|
|
}
|
|
}
|
|
}
|
|
|
|
void LLPanelDirBrowser::showDetailPanel(S32 type, LLSD id)
|
|
{
|
|
switch(type)
|
|
{
|
|
case AVATAR_CODE:
|
|
if (mFloaterDirectory && mFloaterDirectory->mPanelAvatarp)
|
|
{
|
|
mFloaterDirectory->mPanelAvatarp->setVisible(TRUE);
|
|
mFloaterDirectory->mPanelAvatarp->setAvatarID(id.asUUID(), LLStringUtil::null, ONLINE_STATUS_NO);
|
|
}
|
|
break;
|
|
case EVENT_CODE:
|
|
{
|
|
U32 event_id = (U32)id.asInteger();
|
|
showEvent(event_id);
|
|
}
|
|
break;
|
|
case GROUP_CODE:
|
|
if (mFloaterDirectory && mFloaterDirectory->mPanelGroupHolderp)
|
|
{
|
|
mFloaterDirectory->mPanelGroupHolderp->setVisible(TRUE);
|
|
}
|
|
if (mFloaterDirectory && mFloaterDirectory->mPanelGroupp)
|
|
{
|
|
mFloaterDirectory->mPanelGroupp->setVisible(TRUE);
|
|
mFloaterDirectory->mPanelGroupp->setGroupID(id.asUUID());
|
|
}
|
|
break;
|
|
case CLASSIFIED_CODE:
|
|
if (mFloaterDirectory && mFloaterDirectory->mPanelClassifiedp)
|
|
{
|
|
mFloaterDirectory->mPanelClassifiedp->setVisible(TRUE);
|
|
mFloaterDirectory->mPanelClassifiedp->setClassifiedID(id.asUUID());
|
|
mFloaterDirectory->mPanelClassifiedp->sendClassifiedInfoRequest();
|
|
}
|
|
break;
|
|
case FOR_SALE_CODE:
|
|
case AUCTION_CODE:
|
|
if (mFloaterDirectory && mFloaterDirectory->mPanelPlaceSmallp)
|
|
{
|
|
mFloaterDirectory->mPanelPlaceSmallp->setVisible(TRUE);
|
|
mFloaterDirectory->mPanelPlaceSmallp->resetLocation();
|
|
mFloaterDirectory->mPanelPlaceSmallp->setParcelID(id.asUUID());
|
|
}
|
|
break;
|
|
case PLACE_CODE:
|
|
case POPULAR_CODE:
|
|
if (mFloaterDirectory && mFloaterDirectory->mPanelPlacep)
|
|
{
|
|
mFloaterDirectory->mPanelPlacep->setVisible(TRUE);
|
|
mFloaterDirectory->mPanelPlacep->resetLocation();
|
|
mFloaterDirectory->mPanelPlacep->setParcelID(id.asUUID());
|
|
}
|
|
break;
|
|
default:
|
|
{
|
|
llwarns << "Unknown event type!" << llendl;
|
|
}
|
|
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;
|
|
self = gDirBrowserInstances.getIfThere(query_id);
|
|
if (!self)
|
|
{
|
|
// data from an old query
|
|
return;
|
|
}
|
|
|
|
self->mHaveSearchResults = TRUE;
|
|
|
|
LLScrollListCtrl* list = self->findChild<LLScrollListCtrl>("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;
|
|
BOOL is_auction;
|
|
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;
|
|
self = gDirBrowserInstances.getIfThere(query_id);
|
|
if (!self)
|
|
{
|
|
// data from an old query
|
|
return;
|
|
}
|
|
|
|
self->mHaveSearchResults = TRUE;
|
|
|
|
LLScrollListCtrl* list = self->findChild<LLScrollListCtrl>("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"] = "SANSSERIF_SMALL";
|
|
|
|
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;
|
|
self = gDirBrowserInstances.getIfThere(query_id);
|
|
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;
|
|
|
|
LLScrollListCtrl* list = self->findChild<LLScrollListCtrl>("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?
|
|
llwarns << "skipped event due to owner_id null, event_id " << event_id << llendl;
|
|
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";
|
|
|
|
struct tm* t = utc_to_pacific_time(unix_time, gPacificDaylightTime);
|
|
std::string format = "%m-%d ";
|
|
format += gSavedSettings.getString("ShortTimeFormat");
|
|
timeStructToFormattedString(t, format, date);
|
|
|
|
row["columns"][2]["column"] = "date";
|
|
row["columns"][2]["value"] = date;
|
|
row["columns"][2]["font"] = "SANSSERIF_SMALL";
|
|
|
|
row["columns"][3]["column"] = "time";
|
|
row["columns"][3]["value"] = llformat("%u", unix_time);
|
|
row["columns"][3]["font"] = "SANSSERIF_SMALL";
|
|
|
|
list->addElement(row, 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;
|
|
self = gDirBrowserInstances.getIfThere(query_id);
|
|
if (!self)
|
|
{
|
|
return;
|
|
}
|
|
|
|
self->mHaveSearchResults = TRUE;
|
|
|
|
LLScrollListCtrl* list = self->findChild<LLScrollListCtrl>("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"] = "SANSSERIF_SMALL";
|
|
|
|
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())
|
|
{
|
|
llwarns << "Message for wrong agent " << agent_id
|
|
<< " in processDirClassifiedReply" << llendl;
|
|
return;
|
|
}
|
|
|
|
msg->getUUID("QueryData", "QueryID", query_id);
|
|
LLPanelDirBrowser* self = gDirBrowserInstances.getIfThere(query_id);
|
|
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;
|
|
|
|
LLScrollListCtrl* list = self->findChild<LLScrollListCtrl>("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;
|
|
BOOL for_sale;
|
|
S32 sale_price;
|
|
S32 actual_area;
|
|
|
|
msg->getUUID("AgentData", "AgentID", agent_id);
|
|
msg->getUUID("QueryData", "QueryID", query_id );
|
|
|
|
LLPanelDirBrowser* browser;
|
|
browser = gDirBrowserInstances.getIfThere(query_id);
|
|
if (!browser)
|
|
{
|
|
// data from an old query
|
|
return;
|
|
}
|
|
|
|
// Only handled by LLPanelDirLand
|
|
LLPanelDirLand* self = (LLPanelDirLand*)browser;
|
|
|
|
self->mHaveSearchResults = TRUE;
|
|
|
|
LLScrollListCtrl* list = self->findChild<LLScrollListCtrl>("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);
|
|
llinfos << "Land sku: " << land_sku << llendl;
|
|
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"] = "SANSSERIF_SMALL";
|
|
|
|
buffer = llformat("%d", actual_area);
|
|
row["columns"][4]["column"] = "area";
|
|
row["columns"][4]["value"] = buffer;
|
|
row["columns"][4]["font"] = "SANSSERIF_SMALL";
|
|
|
|
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"] = "SANSSERIF_SMALL";
|
|
}
|
|
else
|
|
{
|
|
// Auctions start at L$1 per meter
|
|
row["columns"][5]["column"] = "per_meter";
|
|
row["columns"][5]["value"] = "1.0";
|
|
row["columns"][5]["font"] = "SANSSERIF_SMALL";
|
|
}
|
|
|
|
row["columns"][6]["column"] = "landtype";
|
|
row["columns"][6]["value"] = land_type;
|
|
row["columns"][6]["font"] = "SANSSERIF_SMALL";
|
|
|
|
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"] = "SANSSERIF_SMALL";
|
|
|
|
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::newClassified()
|
|
{
|
|
LLScrollListCtrl* list = findChild<LLScrollListCtrl>("results");
|
|
if (!list) return;
|
|
|
|
if (mFloaterDirectory->mPanelClassifiedp)
|
|
{
|
|
// Clear the panel on the right
|
|
mFloaterDirectory->mPanelClassifiedp->reset();
|
|
|
|
// Set up the classified with the info we've created
|
|
// and a sane default position.
|
|
mFloaterDirectory->mPanelClassifiedp->initNewClassified();
|
|
|
|
// We need the ID to select in the list.
|
|
LLUUID classified_id = mFloaterDirectory->mPanelClassifiedp->getClassifiedID();
|
|
|
|
// Put it in the list on the left
|
|
addClassified(list, classified_id, mFloaterDirectory->mPanelClassifiedp->getClassifiedName(),0,0);
|
|
|
|
// Select it.
|
|
list->setCurrentByID(classified_id);
|
|
|
|
// Make the right panel visible (should already be)
|
|
mFloaterDirectory->mPanelClassifiedp->setVisible(TRUE);
|
|
}
|
|
}
|
|
|
|
void LLPanelDirBrowser::setupNewSearch()
|
|
{
|
|
gDirBrowserInstances.removeData(mSearchID);
|
|
// Make a new query ID
|
|
mSearchID.generate();
|
|
|
|
gDirBrowserInstances.addData(mSearchID, this);
|
|
|
|
// ready the list for results
|
|
if (LLScrollListCtrl* list = findChild<LLScrollListCtrl>("results"))
|
|
{
|
|
list->operateOnAll(LLCtrlListInterface::OP_DELETE);
|
|
list->setCommentText(LLTrans::getString("Searching"));
|
|
list->setEnabled(false);
|
|
}
|
|
|
|
mResultsReceived = 0;
|
|
mHaveSearchResults = FALSE;
|
|
|
|
// Set all panels to be invisible
|
|
mFloaterDirectory->hideAllDetailPanels();
|
|
|
|
updateResultCount();
|
|
}
|
|
|
|
|
|
// static
|
|
// called from calssifieds, events, groups, land, people, and places
|
|
void LLPanelDirBrowser::onClickSearchCore(void* userdata)
|
|
{
|
|
LLPanelDirBrowser* self = (LLPanelDirBrowser*)userdata;
|
|
if (!self) return;
|
|
|
|
self->resetSearchStart();
|
|
self->performQuery();
|
|
|
|
LLFloaterDirectory::sOldSearchCount++;
|
|
}
|
|
|
|
|
|
// 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::handleVisibilityChange(BOOL new_visibility)
|
|
{
|
|
if (new_visibility)
|
|
{
|
|
onCommitList(NULL, this);
|
|
}
|
|
LLPanel::handleVisibilityChange(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
|
|
childHide("Next >");
|
|
childHide("< Prev");
|
|
}
|
|
return rows;
|
|
}
|