aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llpaneldirbrowser.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llpaneldirbrowser.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llpaneldirbrowser.cpp')
-rw-r--r--linden/indra/newview/llpaneldirbrowser.cpp1338
1 files changed, 1338 insertions, 0 deletions
diff --git a/linden/indra/newview/llpaneldirbrowser.cpp b/linden/indra/newview/llpaneldirbrowser.cpp
new file mode 100644
index 0000000..a7a3895
--- /dev/null
+++ b/linden/indra/newview/llpaneldirbrowser.cpp
@@ -0,0 +1,1338 @@
1/**
2 * @file llpaneldirbrowser.cpp
3 * @brief LLPanelDirBrowser class implementation
4 *
5 * Copyright (c) 2001-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28// Base class for the various search panels/results browsers
29// in the Find floater. For example, Find > Popular Places
30// is derived from this.
31
32#include "llviewerprecompiledheaders.h"
33
34#include "llpaneldirbrowser.h"
35
36// linden library includes
37#include "lldir.h"
38#include "lleventflags.h"
39#include "llfontgl.h"
40#include "llqueryflags.h"
41#include "message.h"
42
43// viewer project includes
44#include "llagent.h"
45#include "llbutton.h"
46#include "llcheckboxctrl.h"
47#include "llcombobox.h"
48#include "llfloateravatarinfo.h"
49#include "llfloaterdirectory.h"
50#include "lllineeditor.h"
51#include "llmenucommands.h"
52#include "llmenugl.h"
53#include "llpanelavatar.h"
54#include "llpanelevent.h"
55#include "llpanelgroup.h"
56#include "llpanelclassified.h"
57#include "llpanelpick.h"
58#include "llpanelplace.h"
59#include "llpaneldirland.h"
60#include "llscrolllistctrl.h"
61#include "lltextbox.h"
62#include "lluiconstants.h"
63#include "llviewercontrol.h"
64#include "llviewerimagelist.h"
65#include "llviewermessage.h"
66#include "llvieweruictrlfactory.h"
67
68
69//
70// Globals
71//
72
73LLMap< const LLUUID, LLPanelDirBrowser* > gDirBrowserInstances;
74
75LLPanelDirBrowser::LLPanelDirBrowser(const std::string& name, LLFloaterDirectory* floater)
76: LLPanel(name),
77 mSearchID(),
78 mWantSelectID(),
79 mCurrentSortColumn("name"),
80 mCurrentSortAscending(TRUE),
81 mSearchStart(0),
82 mResultsPerPage(100),
83 mResultsReceived(0),
84 mMinSearchChars(1),
85 mResultsContents(),
86 mHaveSearchResults(FALSE),
87 mDidAutoSelect(TRUE),
88 mLastResultTimer(),
89 mFloaterDirectory(floater)
90{
91 //updateResultCount();
92}
93
94BOOL LLPanelDirBrowser::postBuild()
95{
96 childSetCommitCallback("results", onCommitList, this);
97
98 childSetAction("< Prev", onClickPrev, this);
99 childHide("< Prev");
100
101 childSetAction("Next >", onClickNext, this);
102 childHide("Next >");
103
104 return TRUE;
105}
106
107LLPanelDirBrowser::~LLPanelDirBrowser()
108{
109 // Children all cleaned up by default view destructor.
110
111 gDirBrowserInstances.removeData(mSearchID);
112}
113
114
115// virtual
116void LLPanelDirBrowser::draw()
117{
118 // HACK: If the results panel has data, we want to select the first
119 // item. Unfortunately, we don't know when the find is actually done,
120 // so only do this if it's been some time since the last packet of
121 // results was received.
122 if (getVisible() && mLastResultTimer.getElapsedTimeF32() > 0.5)
123 {
124 if (!mDidAutoSelect &&
125 !childHasFocus("results"))
126 {
127 LLCtrlListInterface *list = childGetListInterface("results");
128 if (list)
129 {
130 list->selectFirstItem(); // select first item by default
131 childSetFocus("results", TRUE);
132 // Request specific data from the server
133 onCommitList(NULL, this);
134 }
135 }
136 mDidAutoSelect = TRUE;
137 }
138
139 LLPanel::draw();
140}
141
142
143// virtual
144void LLPanelDirBrowser::nextPage()
145{
146 mSearchStart += mResultsPerPage;
147 childShow("< Prev");
148
149 performQuery();
150}
151
152
153// virtual
154void LLPanelDirBrowser::prevPage()
155{
156 mSearchStart -= mResultsPerPage;
157 childSetVisible("< Prev", mSearchStart > 0);
158
159 performQuery();
160}
161
162
163void LLPanelDirBrowser::resetSearchStart()
164{
165 mSearchStart = 0;
166 childHide("Next >");
167 childHide("< Prev");
168}
169
170// protected
171void LLPanelDirBrowser::updateResultCount()
172{
173 LLCtrlListInterface *list = childGetListInterface("results");
174 if (!list) return;
175
176 S32 result_count = list->getItemCount();
177 LLString result_text;
178
179 if (!mHaveSearchResults) result_count = 0;
180
181 if (childIsVisible("Next >"))
182 {
183 // Item count be off by a few if bogus items sent from database
184 // Just use the number of results per page. JC
185 result_text = llformat(">%d found", mResultsPerPage);
186 }
187 else
188 {
189 result_text = llformat("%d found", result_count);
190 }
191
192 childSetValue("result_text", result_text);
193
194 if (result_count == 0)
195 {
196 // add none found response
197 if (list->getItemCount() == 0)
198 {
199 list->addSimpleElement("None found.");
200 list->operateOnAll(LLCtrlListInterface::OP_DESELECT);
201 }
202 }
203 else
204 {
205 childEnable("results");
206 }
207}
208
209// static
210void LLPanelDirBrowser::onClickPrev(void* data)
211{
212 LLPanelDirBrowser* self = (LLPanelDirBrowser*)data;
213 self->prevPage();
214}
215
216
217// static
218void LLPanelDirBrowser::onClickNext(void* data)
219{
220 LLPanelDirBrowser* self = (LLPanelDirBrowser*)data;
221 self->nextPage();
222}
223
224
225void LLPanelDirBrowser::selectByUUID(const LLUUID& id)
226{
227 LLCtrlListInterface *list = childGetListInterface("results");
228 if (!list) return;
229 BOOL found = list->setCurrentByID(id);
230 if (found)
231 {
232 // we got it, don't wait for network
233 // Don't bother looking for this in the draw loop.
234 mWantSelectID.setNull();
235 // Make sure UI updates.
236 onCommitList(NULL, this);
237 }
238 else
239 {
240 // waiting for this item from the network
241 mWantSelectID = id;
242 }
243}
244
245void LLPanelDirBrowser::selectEventByID(S32 event_id)
246{
247 if (mFloaterDirectory)
248 {
249 if (mFloaterDirectory->mPanelEventp)
250 {
251 mFloaterDirectory->mPanelEventp->setVisible(TRUE);
252 mFloaterDirectory->mPanelEventp->setEventID(event_id);
253 }
254 }
255}
256
257U32 LLPanelDirBrowser::getSelectedEventID() const
258{
259 if (mFloaterDirectory)
260 {
261 if (mFloaterDirectory->mPanelEventp)
262 {
263 return mFloaterDirectory->mPanelEventp->getEventID();
264 }
265 }
266 return 0;
267}
268
269void LLPanelDirBrowser::getSelectedInfo(LLUUID* id, S32 *type)
270{
271 LLCtrlListInterface *list = childGetListInterface("results");
272 if (!list) return;
273
274 LLSD id_sd = childGetValue("results");
275
276 *id = id_sd.asUUID();
277
278 LLString id_str = id_sd.asString();
279 *type = mResultsContents[id_str]["type"];
280}
281
282
283// static
284void LLPanelDirBrowser::onCommitList(LLUICtrl* ctrl, void* data)
285{
286 LLPanelDirBrowser* self = (LLPanelDirBrowser*)data;
287 LLCtrlListInterface *list = self->childGetListInterface("results");
288 if (!list) return;
289
290 // Start with everyone invisible
291 if (self->mFloaterDirectory)
292 {
293 if (self->mFloaterDirectory->mPanelAvatarp) self->mFloaterDirectory->mPanelAvatarp->setVisible(FALSE);
294 if (self->mFloaterDirectory->mPanelEventp) self->mFloaterDirectory->mPanelEventp->setVisible(FALSE);
295 if (self->mFloaterDirectory->mPanelGroupp) self->mFloaterDirectory->mPanelGroupp->setVisible(FALSE);
296 if (self->mFloaterDirectory->mPanelGroupHolderp) self->mFloaterDirectory->mPanelGroupHolderp->setVisible(FALSE);
297 if (self->mFloaterDirectory->mPanelPlacep) self->mFloaterDirectory->mPanelPlacep->setVisible(FALSE);
298 if (self->mFloaterDirectory->mPanelPlaceSmallp) self->mFloaterDirectory->mPanelPlaceSmallp->setVisible(FALSE);
299 if (self->mFloaterDirectory->mPanelClassifiedp) self->mFloaterDirectory->mPanelClassifiedp->setVisible(FALSE);
300 }
301
302 if (FALSE == list->getCanSelect())
303 {
304 return;
305 }
306
307 LLString id_str = self->childGetValue("results").asString();
308 if (id_str.empty())
309 {
310 return;
311 }
312
313 LLUUID id = list->getCurrentID();
314 S32 type = self->mResultsContents[id_str]["type"];
315 LLString name = self->mResultsContents[id_str]["name"].asString();
316
317 switch(type)
318 {
319 case ONLINE_CODE:
320 if (self->mFloaterDirectory && self->mFloaterDirectory->mPanelAvatarp)
321 {
322 self->mFloaterDirectory->mPanelAvatarp->setVisible(TRUE);
323 self->mFloaterDirectory->mPanelAvatarp->setAvatarID(id, name, ONLINE_STATUS_YES);
324 self->mFloaterDirectory->mPanelAvatarp->disableRate();
325 }
326 break;
327 case OFFLINE_CODE:
328 if (self->mFloaterDirectory && self->mFloaterDirectory->mPanelAvatarp)
329 {
330 self->mFloaterDirectory->mPanelAvatarp->setVisible(TRUE);
331 self->mFloaterDirectory->mPanelAvatarp->setAvatarID(id, name, ONLINE_STATUS_NO);
332 self->mFloaterDirectory->mPanelAvatarp->disableRate();
333 }
334 break;
335 case EVENT_CODE:
336 {
337 U32 event_id = (U32)self->mResultsContents[id_str]["event_id"].asInteger();
338 self->showEvent(event_id);
339 }
340 break;
341 case GROUP_CODE:
342 if (self->mFloaterDirectory && self->mFloaterDirectory->mPanelGroupHolderp)
343 {
344 self->mFloaterDirectory->mPanelGroupHolderp->setVisible(TRUE);
345 }
346 if (self->mFloaterDirectory && self->mFloaterDirectory->mPanelGroupp)
347 {
348 self->mFloaterDirectory->mPanelGroupp->setVisible(TRUE);
349 self->mFloaterDirectory->mPanelGroupp->setGroupID(id);
350 }
351 break;
352 case CLASSIFIED_CODE:
353 if (self->mFloaterDirectory && self->mFloaterDirectory->mPanelClassifiedp)
354 {
355 self->mFloaterDirectory->mPanelClassifiedp->setVisible(TRUE);
356 self->mFloaterDirectory->mPanelClassifiedp->setClassifiedID(id);
357 self->mFloaterDirectory->mPanelClassifiedp->sendClassifiedInfoRequest();
358 }
359 break;
360 case FOR_SALE_CODE:
361 case AUCTION_CODE:
362 if (self->mFloaterDirectory && self->mFloaterDirectory->mPanelPlaceSmallp)
363 {
364 self->mFloaterDirectory->mPanelPlaceSmallp->setVisible(TRUE);
365 self->mFloaterDirectory->mPanelPlaceSmallp->setParcelID(id);
366 self->mFloaterDirectory->mPanelPlaceSmallp->sendParcelInfoRequest();
367 }
368 break;
369 case PLACE_CODE:
370 case POPULAR_CODE:
371 if (self->mFloaterDirectory && self->mFloaterDirectory->mPanelPlacep)
372 {
373 self->mFloaterDirectory->mPanelPlacep->setVisible(TRUE);
374 self->mFloaterDirectory->mPanelPlacep->setParcelID(id);
375 self->mFloaterDirectory->mPanelPlacep->sendParcelInfoRequest();
376 }
377 break;
378 default:
379 {
380 llwarns << "Unknown event type!" << llendl;
381 }
382 break;
383 }
384}
385
386
387void LLPanelDirBrowser::showEvent(const U32 event_id)
388{
389 // Start with everyone invisible
390 if (mFloaterDirectory)
391 {
392 if (mFloaterDirectory->mPanelAvatarp) mFloaterDirectory->mPanelAvatarp->setVisible(FALSE);
393 if (mFloaterDirectory->mPanelGroupp) mFloaterDirectory->mPanelGroupp->setVisible(FALSE);
394 if (mFloaterDirectory->mPanelGroupHolderp) mFloaterDirectory->mPanelGroupHolderp->setVisible(FALSE);
395 if (mFloaterDirectory->mPanelPlacep) mFloaterDirectory->mPanelPlacep->setVisible(FALSE);
396 if (mFloaterDirectory->mPanelPlaceSmallp) mFloaterDirectory->mPanelPlaceSmallp->setVisible(FALSE);
397 if (mFloaterDirectory->mPanelClassifiedp) mFloaterDirectory->mPanelClassifiedp->setVisible(FALSE);
398 if (mFloaterDirectory->mPanelEventp)
399 {
400 mFloaterDirectory->mPanelEventp->setVisible(TRUE);
401 mFloaterDirectory->mPanelEventp->setEventID(event_id);
402 }
403 }
404}
405
406void LLPanelDirBrowser::processDirPeopleReply(LLMessageSystem *msg, void**)
407{
408 LLUUID query_id;
409 char first_name[DB_FIRST_NAME_BUF_SIZE];
410 char last_name[DB_LAST_NAME_BUF_SIZE];
411 LLUUID agent_id;
412 U8 online;
413
414 msg->getUUIDFast(_PREHASH_QueryData,_PREHASH_QueryID, query_id);
415
416 LLPanelDirBrowser* self;
417 self = gDirBrowserInstances.getIfThere(query_id);
418 if (!self)
419 {
420 // data from an old query
421 return;
422 }
423
424 self->mHaveSearchResults = TRUE;
425
426 LLCtrlListInterface *list = self->childGetListInterface("results");
427 if (!list) return;
428
429 if (!list->getCanSelect())
430 {
431 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
432 self->mResultsContents = LLSD();
433 }
434
435 S32 rows = msg->getNumberOfBlocksFast(_PREHASH_QueryReplies);
436 self->mResultsReceived += rows;
437
438 rows = self->showNextButton(rows);
439
440 LLString online_type = llformat("%d", ONLINE_CODE);
441 LLString offline_type = llformat("%d", OFFLINE_CODE);
442
443 for (S32 i = 0; i < rows; i++)
444 {
445 msg->getStringFast(_PREHASH_QueryReplies,_PREHASH_FirstName, DB_FIRST_NAME_BUF_SIZE, first_name, i);
446 msg->getStringFast(_PREHASH_QueryReplies,_PREHASH_LastName, DB_LAST_NAME_BUF_SIZE, last_name, i);
447 msg->getUUIDFast( _PREHASH_QueryReplies,_PREHASH_AgentID, agent_id, i);
448 msg->getU8Fast( _PREHASH_QueryReplies,_PREHASH_Online, online, i);
449 // unused
450 // msg->getStringFast(_PREHASH_QueryReplies,_PREHASH_Group, DB_GROUP_NAME_BUF_SIZE, group, i);
451 // msg->getS32Fast( _PREHASH_QueryReplies,_PREHASH_Reputation, reputation, i);
452
453 if (agent_id.isNull())
454 {
455 continue;
456 }
457
458 LLSD content;
459
460 LLSD row;
461 row["id"] = agent_id;
462
463 LLUUID image_id;
464 if (online)
465 {
466 image_id.set( gViewerArt.getString("icon_avatar_online.tga") );
467 row["columns"][0]["column"] = "icon";
468 row["columns"][0]["type"] = "icon";
469 row["columns"][0]["value"] = image_id;
470
471 content["type"] = ONLINE_CODE;
472 }
473 else
474 {
475 image_id.set( gViewerArt.getString("icon_avatar_offline.tga") );
476 row["columns"][0]["column"] = "icon";
477 row["columns"][0]["type"] = "icon";
478 row["columns"][0]["value"] = image_id;
479
480 content["type"] = OFFLINE_CODE;
481 }
482
483 LLString fullname = LLString(first_name) + " " + LLString(last_name);
484 row["columns"][1]["column"] = "name";
485 row["columns"][1]["value"] = fullname;
486 row["columns"][1]["font"] = "SANSSERIF";
487
488 content["name"] = fullname;
489
490 if (online)
491 {
492 row["columns"][2]["column"] = "online";
493 row["columns"][2]["value"] = "yes";
494 row["columns"][2]["font"] = "SANSSERIFSMALL";
495 }
496 else
497 {
498 row["columns"][2]["column"] = "online";
499 row["columns"][2]["value"] = "no";
500 row["columns"][2]["font"] = "SANSSERIFSMALL";
501 }
502
503 list->addElement(row);
504
505 LLString id_str = agent_id.getString();
506 self->mResultsContents[id_str] = content;
507 }
508
509 list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending);
510 self->updateResultCount();
511
512 // Poke the result received timer
513 self->mLastResultTimer.reset();
514 self->mDidAutoSelect = FALSE;
515}
516
517
518void LLPanelDirBrowser::processDirPlacesReply(LLMessageSystem* msg, void**)
519{
520 LLUUID agent_id;
521 LLUUID query_id;
522 LLUUID parcel_id;
523 char name[MAX_STRING];
524 BOOL is_for_sale;
525 BOOL is_auction;
526 BOOL is_newbie;
527 F32 dwell;
528
529 msg->getUUID("AgentData", "AgentID", agent_id);
530 msg->getUUID("QueryData", "QueryID", query_id );
531
532 LLPanelDirBrowser* self;
533 self = gDirBrowserInstances.getIfThere(query_id);
534 if (!self)
535 {
536 // data from an old query
537 return;
538 }
539
540 self->mHaveSearchResults = TRUE;
541
542 LLCtrlListInterface *list = self->childGetListInterface("results");
543 if (!list) return;
544
545 if (!list->getCanSelect())
546 {
547 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
548 self->mResultsContents = LLSD();
549 }
550
551 S32 i;
552 S32 count = msg->getNumberOfBlocks("QueryReplies");
553 self->mResultsReceived += count;
554
555 count = self->showNextButton(count);
556
557 for (i = 0; i < count ; i++)
558 {
559 msg->getUUID("QueryReplies", "ParcelID", parcel_id, i);
560 msg->getString("QueryReplies", "Name", MAX_STRING, name, i);
561 msg->getBOOL("QueryReplies", "ForSale", is_for_sale, i);
562 msg->getBOOL("QueryReplies", "Auction", is_auction, i);
563 msg->getBOOL("QueryReplies", "ReservedNewbie", is_newbie, i);
564 msg->getF32("QueryReplies", "Dwell", dwell, i);
565
566 if (parcel_id.isNull())
567 {
568 continue;
569 }
570
571 LLSD content;
572 S32 type;
573
574 LLSD row = self->createLandSale(parcel_id, is_auction, is_for_sale, is_newbie, name, &type);
575
576 content["type"] = type;
577 content["name"] = name;
578
579 LLString buffer = llformat("%.0f", (F64)dwell);
580 row["columns"][3]["column"] = "dwell";
581 row["columns"][3]["value"] = buffer;
582 row["columns"][3]["font"] = "SANSSERIFSMALL";
583
584 list->addElement(row);
585
586 LLString id_str = parcel_id.getString();
587 self->mResultsContents[id_str] = content;
588 }
589
590 list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending);
591 self->updateResultCount();
592
593 // Poke the result received timer
594 self->mLastResultTimer.reset();
595 self->mDidAutoSelect = FALSE;
596}
597
598
599
600void LLPanelDirBrowser::processDirPopularReply(LLMessageSystem *msg, void**)
601{
602 LLUUID agent_id;
603 LLUUID query_id;
604 LLUUID parcel_id;
605 char name[MAX_STRING];
606 F32 dwell;
607
608 msg->getUUID("AgentData", "AgentID", agent_id);
609 msg->getUUID("QueryData", "QueryID", query_id );
610
611 LLPanelDirBrowser* self;
612 self = gDirBrowserInstances.getIfThere(query_id);
613 if (!self)
614 {
615 // data from an old query
616 return;
617 }
618
619 self->mHaveSearchResults = TRUE;
620
621 LLCtrlListInterface *list = self->childGetListInterface("results");
622 if (!list) return;
623
624 if (!list->getCanSelect())
625 {
626 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
627 self->mResultsContents = LLSD();
628 }
629
630 S32 i;
631 S32 count = msg->getNumberOfBlocks("QueryReplies");
632 self->mResultsReceived += count;
633 for (i = 0; i < count; i++)
634 {
635 msg->getUUID( "QueryReplies", "ParcelID", parcel_id, i);
636 msg->getString( "QueryReplies", "Name", MAX_STRING, name, i);
637 msg->getF32( "QueryReplies", "Dwell", dwell, i);
638
639 if (parcel_id.isNull())
640 {
641 continue;
642 }
643
644 LLSD content;
645 content["type"] = POPULAR_CODE;
646 content["name"] = name;
647
648 LLSD row;
649 row["id"] = parcel_id;
650
651 LLUUID image_id;
652 image_id.set( gViewerArt.getString("icon_popular.tga") );
653 row["columns"][0]["column"] = "icon";
654 row["columns"][0]["type"] = "icon";
655 row["columns"][0]["value"] = image_id;
656
657 row["columns"][1]["column"] = "name";
658 row["columns"][1]["value"] = name;
659 row["columns"][1]["font"] = "SANSSERIF";
660
661 LLString buffer = llformat("%.0f", dwell);
662 row["columns"][2]["column"] = "dwell";
663 row["columns"][2]["value"] = buffer;
664 row["columns"][2]["font"] = "SANSSERIFSMALL";
665
666 list->addElement(row);
667
668 LLString id_str = parcel_id.getString();
669 self->mResultsContents[id_str] = content;
670 }
671
672 list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending);
673 self->updateResultCount();
674
675 // Poke the result received timer
676 self->mLastResultTimer.reset();
677 self->mDidAutoSelect = FALSE;
678}
679
680
681void LLPanelDirBrowser::processDirEventsReply(LLMessageSystem* msg, void**)
682{
683 LLUUID agent_id;
684 LLUUID query_id;
685 LLUUID owner_id;
686 char name[MAX_STRING];
687 char date[MAX_STRING];
688 BOOL show_mature = gSavedSettings.getBOOL("ShowMatureEvents");
689
690 msg->getUUID("AgentData", "AgentID", agent_id);
691 msg->getUUID("QueryData", "QueryID", query_id );
692
693 LLPanelDirBrowser* self;
694 self = gDirBrowserInstances.getIfThere(query_id);
695 if (!self)
696 {
697 return;
698 }
699
700 self->mHaveSearchResults = TRUE;
701
702 LLCtrlListInterface *list = self->childGetListInterface("results");
703 if (!list) return;
704
705 if (!list->getCanSelect())
706 {
707 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
708 self->mResultsContents = LLSD();
709 }
710
711 S32 rows = msg->getNumberOfBlocks("QueryReplies");
712 self->mResultsReceived += rows;
713
714 rows = self->showNextButton(rows);
715
716 for (S32 i = 0; i < rows; i++)
717 {
718 U32 event_id;
719 U32 unix_time;
720 U32 event_flags;
721
722 msg->getUUID("QueryReplies", "OwnerID", owner_id, i);
723 msg->getString("QueryReplies", "Name", MAX_STRING, name, i);
724 msg->getU32("QueryReplies", "EventID", event_id, i);
725 msg->getString("QueryReplies", "Date", MAX_STRING, date, i);
726 msg->getU32("QueryReplies", "UnixTime", unix_time, i);
727 msg->getU32("QueryReplies", "EventFlags", event_flags, i);
728
729 // Skip empty events
730 if (owner_id.isNull())
731 {
732 //RN: should this check event_id instead?
733 llwarns << "skipped event due to owner_id null, event_id " << event_id << llendl;
734 continue;
735 }
736 // Skip mature events if not showing
737 if (!show_mature
738 && (event_flags & EVENT_FLAG_MATURE))
739 {
740 llwarns << "Skipped due to maturity, event_id " << event_id << llendl;
741 continue;
742 }
743
744 LLSD content;
745
746 content["type"] = EVENT_CODE;
747 content["name"] = name;
748 content["event_id"] = (S32)event_id;
749
750 LLSD row;
751 row["id"] = llformat("%u", event_id);
752
753 // Column 0 - event icon
754 LLUUID image_id;
755 if (event_flags & EVENT_FLAG_MATURE)
756 {
757 image_id.set( gViewerArt.getString("icon_event_mature.tga") );
758 row["columns"][0]["column"] = "icon";
759 row["columns"][0]["type"] = "icon";
760 row["columns"][0]["value"] = image_id;
761 }
762 else
763 {
764 image_id.set( gViewerArt.getString("icon_event.tga") );
765 row["columns"][0]["column"] = "icon";
766 row["columns"][0]["type"] = "icon";
767 row["columns"][0]["value"] = image_id;
768 }
769
770 row["columns"][1]["column"] = "name";
771 row["columns"][1]["value"] = name;
772 row["columns"][1]["font"] = "SANSSERIF";
773
774 row["columns"][2]["column"] = "date";
775 row["columns"][2]["value"] = date;
776 row["columns"][2]["font"] = "SANSSERIFSMALL";
777
778 row["columns"][3]["column"] = "time";
779 row["columns"][3]["value"] = llformat("%u", unix_time);
780 row["columns"][3]["font"] = "SANSSERIFSMALL";
781
782 list->addElement(row, ADD_SORTED);
783
784 LLString id_str = llformat("%u", event_id);
785 self->mResultsContents[id_str] = content;
786 }
787
788 list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending);
789 self->updateResultCount();
790
791 // Poke the result received timer
792 self->mLastResultTimer.reset();
793 self->mDidAutoSelect = FALSE;
794}
795
796
797// static
798void LLPanelDirBrowser::processDirGroupsReply(LLMessageSystem* msg, void**)
799{
800 S32 i;
801
802 LLUUID query_id;
803 LLUUID group_id;
804 char group_name[DB_GROUP_NAME_BUF_SIZE];
805 S32 members;
806 BOOL open_enrollment;
807 S32 membership_fee;
808
809 msg->getUUIDFast(_PREHASH_QueryData,_PREHASH_QueryID, query_id );
810
811 LLPanelDirBrowser* self;
812 self = gDirBrowserInstances.getIfThere(query_id);
813 if (!self)
814 {
815 return;
816 }
817
818 self->mHaveSearchResults = TRUE;
819
820 LLCtrlListInterface *list = self->childGetListInterface("results");
821 if (!list) return;
822
823 if (!list->getCanSelect())
824 {
825 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
826 self->mResultsContents = LLSD();
827 }
828
829 S32 rows = msg->getNumberOfBlocksFast(_PREHASH_QueryReplies);
830 self->mResultsReceived += rows;
831
832 rows = self->showNextButton(rows);
833
834 for (i = 0; i < rows; i++)
835 {
836 msg->getUUIDFast(_PREHASH_QueryReplies, _PREHASH_GroupID, group_id, i );
837 msg->getStringFast(_PREHASH_QueryReplies, _PREHASH_GroupName, DB_GROUP_NAME_BUF_SIZE, group_name, i);
838 msg->getS32Fast(_PREHASH_QueryReplies, _PREHASH_Members, members, i );
839 msg->getBOOLFast(_PREHASH_QueryReplies, _PREHASH_OpenEnrollment, open_enrollment, i );
840 msg->getS32Fast(_PREHASH_QueryReplies, _PREHASH_MembershipFee, membership_fee, i );
841
842 if (group_id.isNull())
843 {
844 continue;
845 }
846
847 LLSD content;
848 content["type"] = GROUP_CODE;
849 content["name"] = group_name;
850
851 LLSD row;
852 row["id"] = group_id;
853
854 LLUUID image_id;
855 image_id.set( gViewerArt.getString("icon_group.tga") );
856 row["columns"][0]["column"] = "icon";
857 row["columns"][0]["type"] = "icon";
858 row["columns"][0]["value"] = image_id;
859
860 row["columns"][1]["column"] = "name";
861 row["columns"][1]["value"] = group_name;
862 row["columns"][1]["font"] = "SANSSERIF";
863
864 row["columns"][2]["column"] = "members";
865 row["columns"][2]["value"] = members;
866 row["columns"][2]["font"] = "SANSSERIFSMALL";
867
868 list->addElement(row);
869 LLString id_str = group_id.getString();
870 self->mResultsContents[id_str] = content;
871 }
872 list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending);
873 self->updateResultCount();
874
875 // Poke the result received timer
876 self->mLastResultTimer.reset();
877 self->mDidAutoSelect = FALSE;
878}
879
880
881// static
882void LLPanelDirBrowser::processDirClassifiedReply(LLMessageSystem* msg, void**)
883{
884 S32 i;
885 S32 num_new_rows;
886
887 LLUUID agent_id;
888 LLUUID query_id;
889
890 msg->getUUID("AgentData", "AgentID", agent_id);
891 if (agent_id != gAgent.getID())
892 {
893 llwarns << "Message for wrong agent " << agent_id
894 << " in processDirClassifiedReply" << llendl;
895 return;
896 }
897
898 msg->getUUID("QueryData", "QueryID", query_id);
899 LLPanelDirBrowser* self = gDirBrowserInstances.getIfThere(query_id);
900 if (!self)
901 {
902 return;
903 }
904
905 self->mHaveSearchResults = TRUE;
906
907 LLCtrlListInterface *list = self->childGetListInterface("results");
908 if (!list) return;
909
910 if (!list->getCanSelect())
911 {
912 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
913 self->mResultsContents = LLSD();
914 }
915
916 num_new_rows = msg->getNumberOfBlocksFast(_PREHASH_QueryReplies);
917 self->mResultsReceived += num_new_rows;
918
919 num_new_rows = self->showNextButton(num_new_rows);
920 for (i = 0; i < num_new_rows; i++)
921 {
922 LLUUID classified_id;
923 char name[DB_PARCEL_NAME_SIZE];
924 U32 creation_date = 0; // unix timestamp
925 U32 expiration_date = 0; // future use
926 S32 price_for_listing = 0;
927 msg->getUUID("QueryReplies", "ClassifiedID", classified_id, i);
928 msg->getString("QueryReplies", "Name", DB_PARCEL_NAME_SIZE, name, i);
929 msg->getU32("QueryReplies","CreationDate",creation_date,i);
930 msg->getU32("QueryReplies","ExpirationDate",expiration_date,i);
931 msg->getS32("QueryReplies","PriceForListing",price_for_listing,i);
932
933 if ( classified_id.notNull() )
934 {
935 self->addClassified(list, classified_id, name, creation_date, price_for_listing);
936
937 LLSD content;
938 content["type"] = CLASSIFIED_CODE;
939 content["name"] = name;
940
941 LLString id_str = classified_id.getString();
942 self->mResultsContents[id_str] = content;
943 }
944 }
945 // The server does the initial sort, by price paid per listing and date. JC
946 self->updateResultCount();
947
948 // Poke the result received timer
949 self->mLastResultTimer.reset();
950 self->mDidAutoSelect = FALSE;
951}
952
953void LLPanelDirBrowser::processDirLandReply(LLMessageSystem *msg, void**)
954{
955 LLUUID agent_id;
956 LLUUID query_id;
957 LLUUID parcel_id;
958 char name[MAX_STRING];
959 BOOL auction;
960 BOOL for_sale;
961 S32 sale_price;
962 S32 actual_area;
963 BOOL is_newbie;
964
965 msg->getUUID("AgentData", "AgentID", agent_id);
966 msg->getUUID("QueryData", "QueryID", query_id );
967
968 LLPanelDirBrowser* browser;
969 browser = gDirBrowserInstances.getIfThere(query_id);
970 if (!browser)
971 {
972 // data from an old query
973 return;
974 }
975
976 // Only handled by LLPanelDirLand
977 LLPanelDirLand* self = (LLPanelDirLand*)browser;
978
979 self->mHaveSearchResults = TRUE;
980
981 LLCtrlListInterface *list = self->childGetListInterface("results");
982 if (!list) return;
983
984 if (!list->getCanSelect())
985 {
986 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
987 self->mResultsContents = LLSD();
988 }
989
990 BOOL use_price = gSavedSettings.getBOOL("FindLandPrice");
991 S32 limit_price = self->childGetValue("priceedit").asInteger();
992
993 BOOL use_area = gSavedSettings.getBOOL("FindLandArea");
994 S32 limit_area = self->childGetValue("areaedit").asInteger();
995
996 S32 i;
997 S32 count = msg->getNumberOfBlocks("QueryReplies");
998 self->mResultsReceived += count;
999
1000 S32 non_auction_count = 0;
1001 for (i = 0; i < count; i++)
1002 {
1003 msg->getUUID( "QueryReplies", "ParcelID", parcel_id, i);
1004 msg->getString( "QueryReplies", "Name", MAX_STRING, name, i);
1005 msg->getBOOL( "QueryReplies", "Auction", auction, i);
1006 msg->getBOOL( "QueryReplies", "ForSale", for_sale, i);
1007 msg->getBOOL( "QueryReplies", "ReservedNewbie", is_newbie, i);
1008 msg->getS32( "QueryReplies", "SalePrice", sale_price, i);
1009 msg->getS32( "QueryReplies", "ActualArea", actual_area, i);
1010
1011 if (parcel_id.isNull()) continue;
1012
1013 if (use_price && (sale_price > limit_price)) continue;
1014
1015 if (use_area && (actual_area < limit_area)) continue;
1016
1017 LLSD content;
1018 S32 type;
1019
1020 LLSD row = self->createLandSale(parcel_id, auction, for_sale, is_newbie, name, &type);
1021
1022 content["type"] = type;
1023 content["name"] = name;
1024
1025 LLString buffer = "Auction";
1026 if (!auction)
1027 {
1028 buffer = llformat("%d", sale_price);
1029 non_auction_count++;
1030 }
1031 row["columns"][3]["column"] = "price";
1032 row["columns"][3]["value"] = buffer;
1033 row["columns"][3]["font"] = "SANSSERIFSMALL";
1034
1035 buffer = llformat("%d", actual_area);
1036 row["columns"][4]["column"] = "area";
1037 row["columns"][4]["value"] = buffer;
1038 row["columns"][4]["font"] = "SANSSERIFSMALL";
1039
1040 if (!auction)
1041 {
1042 F32 price_per_meter;
1043 if (actual_area > 0)
1044 {
1045 price_per_meter = (F32)sale_price / (F32)actual_area;
1046 }
1047 else
1048 {
1049 price_per_meter = 0.f;
1050 }
1051 // Prices are usually L$1 - L$10 / meter
1052 buffer = llformat("%.1f", price_per_meter);
1053 row["columns"][5]["column"] = "per_meter";
1054 row["columns"][5]["value"] = buffer;
1055 row["columns"][5]["font"] = "SANSSERIFSMALL";
1056 }
1057 else
1058 {
1059 // Auctions start at L$1 per meter
1060 row["columns"][5]["column"] = "per_meter";
1061 row["columns"][5]["value"] = "1.0";
1062 row["columns"][5]["font"] = "SANSSERIFSMALL";
1063 }
1064
1065 list->addElement(row);
1066 LLString id_str = parcel_id.getString();
1067 self->mResultsContents[id_str] = content;
1068 }
1069
1070 // All auction results are shown on the first page
1071 // But they don't count towards the 100 / page limit
1072 // So figure out the next button here, when we know how many aren't auctions
1073 count = self->showNextButton(non_auction_count);
1074
1075 // Empty string will sort by current sort options.
1076 list->sortByColumn("",FALSE);
1077 self->updateResultCount();
1078
1079 // Poke the result received timer
1080 self->mLastResultTimer.reset();
1081 self->mDidAutoSelect = FALSE;
1082}
1083
1084void LLPanelDirBrowser::addClassified(LLCtrlListInterface *list, const LLUUID& pick_id, const char* name, const U32 creation_date, const S32 price_for_listing)
1085{
1086 LLString type = llformat("%d", CLASSIFIED_CODE);
1087
1088 LLSD row;
1089 row["id"] = pick_id;
1090
1091 LLUUID image_id;
1092 image_id.set( gViewerArt.getString("icon_top_pick.tga") );
1093 row["columns"][0]["column"] = "icon";
1094 row["columns"][0]["type"] = "icon";
1095 row["columns"][0]["value"] = image_id;
1096
1097 row["columns"][1]["column"] = "name";
1098 row["columns"][1]["value"] = name;
1099 row["columns"][1]["font"] = "SANSSERIF";
1100
1101 row["columns"][2]["column"] = "price";
1102 row["columns"][2]["value"] = price_for_listing;
1103 row["columns"][2]["font"] = "SANSSERIFSMALL";
1104
1105 list->addElement(row);
1106}
1107
1108LLSD LLPanelDirBrowser::createLandSale(const LLUUID& parcel_id, BOOL is_auction, BOOL is_for_sale, BOOL is_newbie, const LLString& name, S32 *type)
1109{
1110 LLSD row;
1111 row["id"] = parcel_id;
1112 LLUUID image_id;
1113
1114 // Icon and type
1115 if(is_auction)
1116 {
1117 image_id.set( gViewerArt.getString("icon_auction.tga") );
1118 row["columns"][0]["column"] = "icon";
1119 row["columns"][0]["type"] = "icon";
1120 row["columns"][0]["value"] = image_id;
1121
1122 *type = AUCTION_CODE;
1123 }
1124 else if (is_for_sale)
1125 {
1126 if(is_newbie)
1127 {
1128 image_id.set( gViewerArt.getString("icon_land_for_landless.tga") );
1129 row["columns"][0]["column"] = "icon";
1130 row["columns"][0]["type"] = "icon";
1131 row["columns"][0]["value"] = image_id;
1132
1133 *type = FOR_SALE_CODE;
1134 }
1135 else
1136 {
1137 image_id.set( gViewerArt.getString("icon_for_sale.tga") );
1138 row["columns"][0]["column"] = "icon";
1139 row["columns"][0]["type"] = "icon";
1140 row["columns"][0]["value"] = image_id;
1141
1142 *type = FOR_SALE_CODE;
1143 }
1144 }
1145 else
1146 {
1147 image_id.set( gViewerArt.getString("icon_place.tga") );
1148 row["columns"][0]["column"] = "icon";
1149 row["columns"][0]["type"] = "icon";
1150 row["columns"][0]["value"] = image_id;
1151
1152 *type = PLACE_CODE;
1153 }
1154
1155 row["columns"][2]["column"] = "name";
1156 row["columns"][2]["value"] = name;
1157 row["columns"][2]["font"] = "SANSSERIF";
1158
1159 return row;
1160}
1161
1162void LLPanelDirBrowser::newClassified()
1163{
1164 LLCtrlListInterface *list = childGetListInterface("results");
1165 if (!list) return;
1166
1167 if (mFloaterDirectory->mPanelClassifiedp)
1168 {
1169 // Clear the panel on the right
1170 mFloaterDirectory->mPanelClassifiedp->reset();
1171
1172 // Set up the classified with the info we've created
1173 // and a sane default position.
1174 mFloaterDirectory->mPanelClassifiedp->initNewClassified();
1175
1176 // We need the ID to select in the list.
1177 LLUUID classified_id = mFloaterDirectory->mPanelClassifiedp->getClassifiedID();
1178
1179 // Put it in the list on the left
1180 addClassified(list, classified_id, mFloaterDirectory->mPanelClassifiedp->getClassifiedName().c_str(),0,0);
1181
1182 // Select it.
1183 list->setCurrentByID(classified_id);
1184
1185 // Make the right panel visible (should already be)
1186 mFloaterDirectory->mPanelClassifiedp->setVisible(TRUE);
1187 }
1188}
1189
1190void LLPanelDirBrowser::renameClassified(const LLUUID& classified_id, const char* name)
1191{
1192 // TomY What, really?
1193 /*LLScrollListItem* row;
1194 for (row = mResultsList->getFirstData(); row; row = mResultsList->getNextData())
1195 {
1196 if (row->getUUID() == classified_id)
1197 {
1198 const LLScrollListCell* column;
1199 LLScrollListText* text;
1200
1201 // icon
1202 // type
1203 column = row->getColumn(2); // name (visible)
1204 text = (LLScrollListText*)column;
1205 text->setText(name);
1206
1207 column = row->getColumn(3); // name (invisible)
1208 text = (LLScrollListText*)column;
1209 text->setText(name);
1210 }
1211 }*/
1212}
1213
1214
1215void LLPanelDirBrowser::setupNewSearch()
1216{
1217 LLCtrlListInterface *list = childGetListInterface("results");
1218 if (!list) return;
1219
1220 gDirBrowserInstances.removeData(mSearchID);
1221 // Make a new query ID
1222 mSearchID.generate();
1223
1224 gDirBrowserInstances.addData(mSearchID, this);
1225
1226 // ready the list for results
1227 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
1228 list->addSimpleElement("Searching...");
1229 childDisable("results");
1230
1231 mResultsReceived = 0;
1232 mHaveSearchResults = FALSE;
1233
1234 // Set all panels to be invisible
1235 if (mFloaterDirectory->mPanelAvatarp) mFloaterDirectory->mPanelAvatarp->setVisible(FALSE);
1236 if (mFloaterDirectory->mPanelEventp) mFloaterDirectory->mPanelEventp->setVisible(FALSE);
1237 if (mFloaterDirectory->mPanelGroupp) mFloaterDirectory->mPanelGroupp->setVisible(FALSE);
1238 if (mFloaterDirectory->mPanelGroupHolderp) mFloaterDirectory->mPanelGroupHolderp->setVisible(FALSE);
1239 if (mFloaterDirectory->mPanelPlacep) mFloaterDirectory->mPanelPlacep->setVisible(FALSE);
1240 if (mFloaterDirectory->mPanelPlaceSmallp) mFloaterDirectory->mPanelPlaceSmallp->setVisible(FALSE);
1241 if (mFloaterDirectory->mPanelClassifiedp) mFloaterDirectory->mPanelClassifiedp->setVisible(FALSE);
1242
1243 updateResultCount();
1244}
1245
1246
1247// static
1248void LLPanelDirBrowser::onClickSearchCore(void* userdata)
1249{
1250 LLPanelDirBrowser* self = (LLPanelDirBrowser*)userdata;
1251 if (!self) return;
1252
1253 self->resetSearchStart();
1254 self->performQuery();
1255}
1256
1257
1258// static
1259void LLPanelDirBrowser::sendDirFindQuery(
1260 LLMessageSystem* msg,
1261 const LLUUID& query_id,
1262 const LLString& text,
1263 U32 flags,
1264 S32 query_start)
1265{
1266 msg->newMessage("DirFindQuery");
1267 msg->nextBlock("AgentData");
1268 msg->addUUID("AgentID", gAgent.getID());
1269 msg->addUUID("SessionID", gAgent.getSessionID());
1270 msg->nextBlock("QueryData");
1271 msg->addUUID("QueryID", query_id);
1272 msg->addString("QueryText", text);
1273 msg->addU32("QueryFlags", flags);
1274 msg->addS32("QueryStart", query_start);
1275 gAgent.sendReliableMessage();
1276}
1277
1278
1279void LLPanelDirBrowser::addHelpText(const char* text)
1280{
1281 LLCtrlListInterface *list = childGetListInterface("results");
1282 if (!list) return;
1283
1284 list->addSimpleElement(text);
1285 childDisable("results");
1286}
1287
1288
1289BOOL enable_never(void*)
1290{
1291 return FALSE;
1292}
1293
1294void LLPanelDirBrowser::onKeystrokeName(LLLineEditor* line, void* data)
1295{
1296 LLPanelDirBrowser *self = (LLPanelDirBrowser*)data;
1297 if (line->getLength() >= (S32)self->mMinSearchChars)
1298 {
1299 self->setDefaultBtn( "Search" );
1300 self->childEnable("Search");
1301 }
1302 else
1303 {
1304 self->setDefaultBtn();
1305 self->childDisable("Search");
1306 }
1307}
1308
1309void LLPanelDirBrowser::onVisibilityChange(BOOL curVisibilityIn)
1310{
1311 if (curVisibilityIn)
1312 {
1313 onCommitList(NULL, this);
1314 }
1315}
1316
1317S32 LLPanelDirBrowser::showNextButton(S32 rows)
1318{
1319 // HACK: This hack doesn't work for llpaneldirfind (ALL)
1320 // because other data is being returned as well.
1321 if ( getName() != "all_panel")
1322 {
1323 // HACK: The (mResultsPerPage)+1th entry indicates there are 'more'
1324 bool show_next = (mResultsReceived > mResultsPerPage);
1325 childSetVisible("Next >", show_next);
1326 if (show_next)
1327 {
1328 rows -= (mResultsReceived - mResultsPerPage);
1329 }
1330 }
1331 else
1332 {
1333 // Hide page buttons
1334 childHide("Next >");
1335 childHide("< Prev");
1336 }
1337 return rows;
1338}