llpaneldirbrowser.cpp

Go to the documentation of this file.
00001 
00032 // Base class for the various search panels/results browsers
00033 // in the Find floater.  For example, Find > Popular Places
00034 // is derived from this.
00035 
00036 #include "llviewerprecompiledheaders.h"
00037 
00038 #include "llpaneldirbrowser.h"
00039 
00040 // linden library includes
00041 #include "lldir.h"
00042 #include "lleventflags.h"
00043 #include "llfontgl.h"
00044 #include "llqueryflags.h"
00045 #include "message.h"
00046 
00047 // viewer project includes
00048 #include "llagent.h"
00049 #include "llbutton.h"
00050 #include "llcheckboxctrl.h"
00051 #include "llcombobox.h"
00052 #include "llfloateravatarinfo.h"
00053 #include "llfloaterdirectory.h" 
00054 #include "lllineeditor.h"
00055 #include "llmenucommands.h"
00056 #include "llmenugl.h"
00057 #include "llpanelavatar.h"
00058 #include "llpanelevent.h"
00059 #include "llpanelgroup.h"
00060 #include "llpanelclassified.h"
00061 #include "llpanelpick.h"
00062 #include "llpanelplace.h"
00063 #include "llpaneldirland.h"
00064 #include "llscrolllistctrl.h"
00065 #include "lltextbox.h"
00066 #include "lluiconstants.h"
00067 #include "llviewercontrol.h"
00068 #include "llviewerimagelist.h"
00069 #include "llviewermessage.h"
00070 #include "lluictrlfactory.h"
00071 
00072 #include <string>
00073 #include <sstream>
00074 #include <vector>
00075 #include <algorithm>
00076 
00077 
00078 //
00079 // Globals
00080 //
00081 
00082 LLMap< const LLUUID, LLPanelDirBrowser* > gDirBrowserInstances;
00083 
00084 LLPanelDirBrowser::LLPanelDirBrowser(const std::string& name, LLFloaterDirectory* floater)
00085 :       LLPanel(name),
00086         mSearchID(),
00087         mWantSelectID(),
00088         mCurrentSortColumn("name"),
00089         mCurrentSortAscending(TRUE),
00090         mSearchStart(0),
00091         mResultsPerPage(100),
00092         mResultsReceived(0),
00093         mMinSearchChars(1),
00094         mResultsContents(),
00095         mHaveSearchResults(FALSE),
00096         mDidAutoSelect(TRUE),
00097         mLastResultTimer(),
00098         mFloaterDirectory(floater)
00099 {
00100         //updateResultCount();
00101 }
00102 
00103 BOOL LLPanelDirBrowser::postBuild()
00104 {
00105         childSetCommitCallback("results", onCommitList, this);
00106 
00107         childSetAction("< Prev", onClickPrev, this);
00108         childHide("< Prev");
00109 
00110         childSetAction("Next >", onClickNext, this);
00111         childHide("Next >");
00112 
00113         return TRUE;
00114 }
00115 
00116 LLPanelDirBrowser::~LLPanelDirBrowser()
00117 {
00118         // Children all cleaned up by default view destructor.
00119 
00120         gDirBrowserInstances.removeData(mSearchID);
00121 }
00122 
00123 
00124 // virtual
00125 void LLPanelDirBrowser::draw()
00126 {
00127         // HACK: If the results panel has data, we want to select the first
00128         // item.  Unfortunately, we don't know when the find is actually done,
00129         // so only do this if it's been some time since the last packet of
00130         // results was received.
00131         if (mLastResultTimer.getElapsedTimeF32() > 0.5)
00132         {
00133                 if (!mDidAutoSelect &&
00134                         !childHasFocus("results"))
00135                 {
00136                         LLCtrlListInterface *list = childGetListInterface("results");
00137                         if (list)
00138                         {
00139                                 if (list->getCanSelect())
00140                                 {
00141                                         list->selectFirstItem(); // select first item by default
00142                                         childSetFocus("results", TRUE);
00143                                 }
00144                                 // Request specific data from the server
00145                                 onCommitList(NULL, this);
00146                         }
00147                 }
00148                 mDidAutoSelect = TRUE;
00149         }
00150         
00151         LLPanel::draw();
00152 }
00153 
00154 
00155 // virtual
00156 void LLPanelDirBrowser::nextPage()
00157 {
00158         mSearchStart += mResultsPerPage;
00159         childShow("< Prev");
00160 
00161         performQuery();
00162 }
00163 
00164 
00165 // virtual
00166 void LLPanelDirBrowser::prevPage()
00167 {
00168         mSearchStart -= mResultsPerPage;
00169         childSetVisible("< Prev", mSearchStart > 0);
00170 
00171         performQuery();
00172 }
00173 
00174 
00175 void LLPanelDirBrowser::resetSearchStart()
00176 {
00177         mSearchStart = 0;
00178         childHide("Next >");
00179         childHide("< Prev");
00180 }
00181 
00182 // protected
00183 void LLPanelDirBrowser::updateResultCount()
00184 {
00185         LLScrollListCtrl* list = getChild<LLScrollListCtrl>("results");
00186 
00187         S32 result_count = list->getItemCount();
00188         LLString result_text;
00189 
00190         if (!mHaveSearchResults) result_count = 0;
00191 
00192         if (childIsVisible("Next >")) 
00193         {
00194                 // Item count be off by a few if bogus items sent from database
00195                 // Just use the number of results per page. JC
00196                 result_text = llformat(">%d found", mResultsPerPage);
00197         }
00198         else 
00199         {
00200                 result_text = llformat("%d found", result_count);
00201         }
00202         
00203         childSetValue("result_text", result_text);
00204         
00205         if (result_count == 0)
00206         {
00207                 // add none found response
00208                 if (list->getItemCount() == 0)
00209                 {
00210                         list->addCommentText(getString("not_found_text"));
00211                         list->operateOnAll(LLCtrlListInterface::OP_DESELECT);
00212                 }
00213         }
00214         else
00215         {
00216                 childEnable("results");
00217         }
00218 }
00219 
00220 // static
00221 void LLPanelDirBrowser::onClickPrev(void* data)
00222 {
00223         LLPanelDirBrowser* self = (LLPanelDirBrowser*)data;
00224         self->prevPage();
00225 }
00226 
00227 
00228 // static
00229 void LLPanelDirBrowser::onClickNext(void* data)
00230 {
00231         LLPanelDirBrowser* self = (LLPanelDirBrowser*)data;
00232         self->nextPage();
00233 }
00234 
00235 // static
00236 std::string LLPanelDirBrowser::filterShortWords( const std::string source_string, 
00237                                                                                                                         int shortest_word_length, 
00238                                                                                                                                 bool& was_filtered )
00239 {
00240         // degenerate case
00241         if ( source_string.length() < 1 ) 
00242                 return "";
00243 
00244         std::stringstream codec( source_string );
00245         std::string each_word;
00246         std::vector< std::string > all_words;
00247     
00248         while( codec >> each_word )
00249         all_words.push_back( each_word );
00250 
00251         std::ostringstream dest_string( "" ); 
00252 
00253         was_filtered = false;
00254 
00255         std::vector< std::string >::iterator iter = all_words.begin();
00256         while( iter != all_words.end() )
00257         {
00258                 if ( (int)(*iter).length() >= shortest_word_length )
00259                 {
00260                         dest_string << *iter;
00261                         dest_string << " ";
00262                 }
00263                 else
00264                 {
00265                         was_filtered = true;
00266                 }
00267 
00268                 ++iter;
00269         };
00270 
00271         return dest_string.str();
00272 }
00273 
00274 void LLPanelDirBrowser::selectByUUID(const LLUUID& id)
00275 {
00276         LLCtrlListInterface *list = childGetListInterface("results");
00277         if (!list) return;
00278         BOOL found = list->setCurrentByID(id);
00279         if (found)
00280         {
00281                 // we got it, don't wait for network
00282                 // Don't bother looking for this in the draw loop.
00283                 mWantSelectID.setNull();
00284                 // Make sure UI updates.
00285                 onCommitList(NULL, this);
00286         }
00287         else
00288         {
00289                 // waiting for this item from the network
00290                 mWantSelectID = id;
00291         }
00292 }
00293 
00294 void LLPanelDirBrowser::selectEventByID(S32 event_id)
00295 {
00296         if (mFloaterDirectory)
00297         {
00298                 if (mFloaterDirectory->mPanelEventp)
00299                 {
00300                         mFloaterDirectory->mPanelEventp->setVisible(TRUE);
00301                         mFloaterDirectory->mPanelEventp->setEventID(event_id);
00302                 }
00303         }
00304 }
00305 
00306 U32 LLPanelDirBrowser::getSelectedEventID() const
00307 {
00308         if (mFloaterDirectory)
00309         {
00310                 if (mFloaterDirectory->mPanelEventp)
00311                 {
00312                         return mFloaterDirectory->mPanelEventp->getEventID();
00313                 }
00314         }
00315         return 0;
00316 }
00317 
00318 void LLPanelDirBrowser::getSelectedInfo(LLUUID* id, S32 *type)
00319 {
00320         LLCtrlListInterface *list = childGetListInterface("results");
00321         if (!list) return;
00322 
00323         LLSD id_sd = childGetValue("results");
00324 
00325         *id = id_sd.asUUID();
00326 
00327         LLString id_str = id_sd.asString();
00328         *type = mResultsContents[id_str]["type"];
00329 }
00330 
00331 
00332 // static
00333 void LLPanelDirBrowser::onCommitList(LLUICtrl* ctrl, void* data)
00334 {
00335         LLPanelDirBrowser* self = (LLPanelDirBrowser*)data;
00336         LLCtrlListInterface *list = self->childGetListInterface("results");
00337         if (!list) return;
00338 
00339         // Start with everyone invisible
00340         if (self->mFloaterDirectory)
00341         {
00342                 self->mFloaterDirectory->hideAllDetailPanels();
00343         }
00344         
00345         if (FALSE == list->getCanSelect())
00346         {
00347                 return;
00348         }
00349 
00350         LLString id_str = self->childGetValue("results").asString();
00351         if (id_str.empty())
00352         {
00353                 return;
00354         }
00355 
00356         LLSD item_id = list->getCurrentID();
00357         S32 type = self->mResultsContents[id_str]["type"];
00358         if (type == EVENT_CODE)
00359         {
00360                 // all but events use the UUID above
00361                 item_id = self->mResultsContents[id_str]["event_id"];
00362         }
00363 
00364         //LLString name = self->mResultsContents[id_str]["name"].asString();
00365         self->showDetailPanel(type, item_id);
00366 }
00367 
00368 void LLPanelDirBrowser::showDetailPanel(S32 type, LLSD id)
00369 {
00370         switch(type)
00371         {
00372         case AVATAR_CODE:
00373                 if (mFloaterDirectory && mFloaterDirectory->mPanelAvatarp)
00374                 {
00375                         mFloaterDirectory->mPanelAvatarp->setVisible(TRUE);
00376                         mFloaterDirectory->mPanelAvatarp->setAvatarID(id.asUUID(), "", ONLINE_STATUS_NO);
00377                 }
00378                 break;
00379         case EVENT_CODE:
00380                 {
00381                         U32 event_id = (U32)id.asInteger();
00382                         showEvent(event_id);
00383                 }
00384                 break;
00385         case GROUP_CODE:
00386                 if (mFloaterDirectory && mFloaterDirectory->mPanelGroupHolderp)
00387                 {
00388                         mFloaterDirectory->mPanelGroupHolderp->setVisible(TRUE);
00389                 }
00390                 if (mFloaterDirectory && mFloaterDirectory->mPanelGroupp)
00391                 {
00392                         mFloaterDirectory->mPanelGroupp->setVisible(TRUE);
00393                         mFloaterDirectory->mPanelGroupp->setGroupID(id.asUUID());
00394                 }
00395                 break;
00396         case CLASSIFIED_CODE:
00397                 if (mFloaterDirectory && mFloaterDirectory->mPanelClassifiedp)
00398                 {
00399                         mFloaterDirectory->mPanelClassifiedp->setVisible(TRUE);
00400                         mFloaterDirectory->mPanelClassifiedp->setClassifiedID(id.asUUID());
00401                         mFloaterDirectory->mPanelClassifiedp->sendClassifiedInfoRequest();
00402                 }
00403                 break;
00404         case FOR_SALE_CODE:
00405         case AUCTION_CODE:
00406                 if (mFloaterDirectory && mFloaterDirectory->mPanelPlaceSmallp)
00407                 {
00408                         mFloaterDirectory->mPanelPlaceSmallp->setVisible(TRUE);
00409                         mFloaterDirectory->mPanelPlaceSmallp->resetLocation();
00410                         mFloaterDirectory->mPanelPlaceSmallp->setParcelID(id.asUUID());
00411                 }
00412                 break;
00413         case PLACE_CODE:
00414         case POPULAR_CODE:
00415                 if (mFloaterDirectory && mFloaterDirectory->mPanelPlacep)
00416                 {
00417                         mFloaterDirectory->mPanelPlacep->setVisible(TRUE);
00418                         mFloaterDirectory->mPanelPlacep->resetLocation();
00419                         mFloaterDirectory->mPanelPlacep->setParcelID(id.asUUID());
00420                 }
00421                 break;
00422         default:
00423                 {
00424                         llwarns << "Unknown event type!" << llendl;
00425                 }
00426                 break;
00427         }
00428 }
00429 
00430 
00431 void LLPanelDirBrowser::showEvent(const U32 event_id)
00432 {
00433         // Start with everyone invisible
00434         if (mFloaterDirectory)
00435         {
00436                 mFloaterDirectory->hideAllDetailPanels();
00437                 if (mFloaterDirectory->mPanelEventp)
00438                 {
00439                         mFloaterDirectory->mPanelEventp->setVisible(TRUE);
00440                         mFloaterDirectory->mPanelEventp->setEventID(event_id);
00441                 }
00442         }
00443 }
00444 
00445 void LLPanelDirBrowser::processDirPeopleReply(LLMessageSystem *msg, void**)
00446 {
00447         LLUUID query_id;
00448         char   first_name[DB_FIRST_NAME_BUF_SIZE];      /* Flawfinder: ignore */
00449         char   last_name[DB_LAST_NAME_BUF_SIZE];        /* Flawfinder: ignore */
00450         LLUUID agent_id;
00451 
00452         msg->getUUIDFast(_PREHASH_QueryData,_PREHASH_QueryID, query_id);
00453 
00454         LLPanelDirBrowser* self;
00455         self = gDirBrowserInstances.getIfThere(query_id);
00456         if (!self) 
00457         {
00458                 // data from an old query
00459                 return;
00460         }
00461 
00462         self->mHaveSearchResults = TRUE;
00463 
00464         LLCtrlListInterface *list = self->childGetListInterface("results");
00465         if (!list) return;
00466 
00467         if (!list->getCanSelect())
00468         {
00469                 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
00470                 self->mResultsContents = LLSD();
00471         }
00472 
00473         S32 rows = msg->getNumberOfBlocksFast(_PREHASH_QueryReplies);
00474         self->mResultsReceived += rows;
00475 
00476         rows = self->showNextButton(rows);
00477 
00478         for (S32 i = 0; i < rows; i++)
00479         {                       
00480                 msg->getStringFast(_PREHASH_QueryReplies,_PREHASH_FirstName, DB_FIRST_NAME_BUF_SIZE, first_name, i);
00481                 msg->getStringFast(_PREHASH_QueryReplies,_PREHASH_LastName,     DB_LAST_NAME_BUF_SIZE, last_name, i);
00482                 msg->getUUIDFast(  _PREHASH_QueryReplies,_PREHASH_AgentID, agent_id, i);
00483                 // msg->getU8Fast(    _PREHASH_QueryReplies,_PREHASH_Online, online, i);
00484                 // unused
00485                 // msg->getStringFast(_PREHASH_QueryReplies,_PREHASH_Group, DB_GROUP_NAME_BUF_SIZE, group, i);
00486                 // msg->getS32Fast(   _PREHASH_QueryReplies,_PREHASH_Reputation, reputation, i);
00487 
00488                 if (agent_id.isNull())
00489                 {
00490                         continue;
00491                 }
00492 
00493                 LLSD content;
00494 
00495                 LLSD row;
00496                 row["id"] = agent_id;
00497 
00498                 // We don't show online status in the finder anymore,
00499                 // so just use the 'offline' icon as the generic 'person' icon
00500                 row["columns"][0]["column"] = "icon";
00501                 row["columns"][0]["type"] = "icon";
00502                 row["columns"][0]["value"] = "icon_avatar_offline.tga";
00503 
00504                 content["type"] = AVATAR_CODE;
00505 
00506                 LLString fullname = LLString(first_name) + " " + LLString(last_name);
00507                 row["columns"][1]["column"] = "name";
00508                 row["columns"][1]["value"] = fullname;
00509                 row["columns"][1]["font"] = "SANSSERIF";
00510 
00511                 content["name"] = fullname;
00512 
00513                 list->addElement(row);
00514                 self->mResultsContents[agent_id.asString()] = content;
00515         }
00516 
00517         list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending);
00518         self->updateResultCount();
00519 
00520         // Poke the result received timer
00521         self->mLastResultTimer.reset();
00522         self->mDidAutoSelect = FALSE;
00523 }
00524 
00525 
00526 void LLPanelDirBrowser::processDirPlacesReply(LLMessageSystem* msg, void**)
00527 {
00528         LLUUID  agent_id;
00529         LLUUID  query_id;
00530         LLUUID  parcel_id;
00531         char    name[MAX_STRING];               /*Flawfinder: ignore*/
00532         BOOL    is_for_sale;
00533         BOOL    is_auction;
00534         F32             dwell;
00535 
00536         msg->getUUID("AgentData", "AgentID", agent_id);
00537         msg->getUUID("QueryData", "QueryID", query_id );
00538 
00539         LLPanelDirBrowser* self;
00540         self = gDirBrowserInstances.getIfThere(query_id);
00541         if (!self) 
00542         {
00543                 // data from an old query
00544                 return;
00545         }
00546 
00547         self->mHaveSearchResults = TRUE;
00548 
00549         LLCtrlListInterface *list = self->childGetListInterface("results");
00550         if (!list) return;
00551 
00552         if (!list->getCanSelect())
00553         {
00554                 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
00555                 self->mResultsContents = LLSD();
00556         }
00557 
00558         S32 i;
00559         S32 count = msg->getNumberOfBlocks("QueryReplies");
00560         self->mResultsReceived += count;
00561 
00562         count = self->showNextButton(count);
00563 
00564         for (i = 0; i < count ; i++)
00565         {
00566                 msg->getUUID("QueryReplies", "ParcelID", parcel_id, i);
00567                 msg->getString("QueryReplies", "Name", MAX_STRING, name, i);
00568                 msg->getBOOL("QueryReplies", "ForSale", is_for_sale, i);
00569                 msg->getBOOL("QueryReplies", "Auction", is_auction, i);
00570                 msg->getF32("QueryReplies", "Dwell", dwell, i);
00571                 
00572                 if (parcel_id.isNull())
00573                 {
00574                         continue;
00575                 }
00576 
00577                 LLSD content;
00578                 S32 type;
00579 
00580                 LLSD row = self->createLandSale(parcel_id, is_auction, is_for_sale,  name, &type);
00581 
00582                 content["type"] = type;
00583                 content["name"] = name;
00584 
00585                 LLString buffer = llformat("%.0f", (F64)dwell);
00586                 row["columns"][3]["column"] = "dwell";
00587                 row["columns"][3]["value"] = buffer;
00588                 row["columns"][3]["font"] = "SANSSERIFSMALL";
00589 
00590                 list->addElement(row);
00591                 self->mResultsContents[parcel_id.asString()] = content;
00592         }
00593 
00594         list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending);
00595         self->updateResultCount();
00596 
00597         // Poke the result received timer
00598         self->mLastResultTimer.reset();
00599         self->mDidAutoSelect = FALSE;
00600 }
00601 
00602 
00603 void LLPanelDirBrowser::processDirEventsReply(LLMessageSystem* msg, void**)
00604 {
00605         LLUUID  agent_id;
00606         LLUUID  query_id;
00607         LLUUID  owner_id;
00608         char    name[MAX_STRING];                       /*Flawfinder: ignore*/
00609         char    date[MAX_STRING];               /*Flawfinder: ignore*/
00610         BOOL    show_mature = gSavedSettings.getBOOL("ShowMatureEvents");
00611 
00612         msg->getUUID("AgentData", "AgentID", agent_id);
00613         msg->getUUID("QueryData", "QueryID", query_id );
00614 
00615         LLPanelDirBrowser* self;
00616         self = gDirBrowserInstances.getIfThere(query_id);
00617         if (!self)
00618         {
00619                 return;
00620         }
00621 
00622         self->mHaveSearchResults = TRUE;
00623 
00624         LLCtrlListInterface *list = self->childGetListInterface("results");
00625         if (!list) return;
00626 
00627         if (!list->getCanSelect())
00628         {
00629                 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
00630                 self->mResultsContents = LLSD();
00631         }
00632 
00633         S32 rows = msg->getNumberOfBlocks("QueryReplies");
00634         self->mResultsReceived += rows;
00635 
00636         rows = self->showNextButton(rows);
00637 
00638         for (S32 i = 0; i < rows; i++)
00639         {
00640                 U32 event_id;
00641                 U32 unix_time;
00642                 U32 event_flags;
00643 
00644                 msg->getUUID("QueryReplies", "OwnerID", owner_id, i);
00645                 msg->getString("QueryReplies", "Name", MAX_STRING, name, i);
00646                 msg->getU32("QueryReplies", "EventID", event_id, i);
00647                 msg->getString("QueryReplies", "Date", MAX_STRING, date, i);
00648                 msg->getU32("QueryReplies", "UnixTime", unix_time, i);
00649                 msg->getU32("QueryReplies", "EventFlags", event_flags, i);
00650         
00651                 // Skip empty events
00652                 if (owner_id.isNull())
00653                 {
00654                         //RN: should this check event_id instead?
00655                         llwarns << "skipped event due to owner_id null, event_id " << event_id << llendl;
00656                         continue;
00657                 }
00658                 // Skip mature events if not showing
00659                 if (!show_mature
00660                         && (event_flags & EVENT_FLAG_MATURE))
00661                 {
00662                         llwarns << "Skipped due to maturity, event_id " << event_id << llendl;
00663                         continue;
00664                 }
00665 
00666                 LLSD content;
00667 
00668                 content["type"] = EVENT_CODE;
00669                 content["name"] = name;
00670                 content["event_id"] = (S32)event_id;
00671 
00672                 LLSD row;
00673                 row["id"] = llformat("%u", event_id);
00674 
00675                 // Column 0 - event icon
00676                 LLUUID image_id;
00677                 if (event_flags & EVENT_FLAG_MATURE)
00678                 {
00679                         row["columns"][0]["column"] = "icon";
00680                         row["columns"][0]["type"] = "icon";
00681                         row["columns"][0]["value"] = "icon_event_mature.tga";
00682                 }
00683                 else
00684                 {
00685                         row["columns"][0]["column"] = "icon";
00686                         row["columns"][0]["type"] = "icon";
00687                         row["columns"][0]["value"] = "icon_event.tga";
00688                 }
00689 
00690                 row["columns"][1]["column"] = "name";
00691                 row["columns"][1]["value"] = name;
00692                 row["columns"][1]["font"] = "SANSSERIF";
00693 
00694                 row["columns"][2]["column"] = "date";
00695                 row["columns"][2]["value"] = date;
00696                 row["columns"][2]["font"] = "SANSSERIFSMALL";
00697 
00698                 row["columns"][3]["column"] = "time";
00699                 row["columns"][3]["value"] = llformat("%u", unix_time);
00700                 row["columns"][3]["font"] = "SANSSERIFSMALL";
00701 
00702                 list->addElement(row, ADD_SORTED);
00703 
00704                 LLString id_str = llformat("%u", event_id);
00705                 self->mResultsContents[id_str] = content;
00706         }
00707 
00708         list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending);
00709         self->updateResultCount();
00710 
00711         // Poke the result received timer
00712         self->mLastResultTimer.reset();
00713         self->mDidAutoSelect = FALSE;
00714 }
00715 
00716 
00717 // static
00718 void LLPanelDirBrowser::processDirGroupsReply(LLMessageSystem* msg, void**)
00719 {
00720         S32             i;
00721         
00722         LLUUID  query_id;
00723         LLUUID  group_id;
00724         char    group_name[DB_GROUP_NAME_BUF_SIZE];             /*Flawfinder: ignore*/
00725         S32     members;
00726         F32     search_order;
00727 
00728         msg->getUUIDFast(_PREHASH_QueryData,_PREHASH_QueryID, query_id );
00729 
00730         LLPanelDirBrowser* self;
00731         self = gDirBrowserInstances.getIfThere(query_id);
00732         if (!self)
00733         {
00734                 return;
00735         }
00736 
00737         self->mHaveSearchResults = TRUE;
00738 
00739         LLCtrlListInterface *list = self->childGetListInterface("results");
00740         if (!list) return;
00741 
00742         if (!list->getCanSelect())
00743         {
00744                 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
00745                 self->mResultsContents = LLSD();
00746         }
00747 
00748         S32 rows = msg->getNumberOfBlocksFast(_PREHASH_QueryReplies);
00749         self->mResultsReceived += rows;
00750 
00751         rows = self->showNextButton(rows);
00752 
00753         for (i = 0; i < rows; i++)
00754         {
00755                 msg->getUUIDFast(_PREHASH_QueryReplies, _PREHASH_GroupID,               group_id, i );
00756                 msg->getStringFast(_PREHASH_QueryReplies, _PREHASH_GroupName,   DB_GROUP_NAME_BUF_SIZE,         group_name,             i);
00757                 msg->getS32Fast(_PREHASH_QueryReplies, _PREHASH_Members,                members, i );
00758                 msg->getF32Fast(_PREHASH_QueryReplies, _PREHASH_SearchOrder,    search_order, i );
00759                 
00760                 if (group_id.isNull())
00761                 {
00762                         continue;
00763                 }
00764 
00765                 LLSD content;
00766                 content["type"] = GROUP_CODE;
00767                 content["name"] = group_name;
00768 
00769                 LLSD row;
00770                 row["id"] = group_id;
00771 
00772                 LLUUID image_id;
00773                 row["columns"][0]["column"] = "icon";
00774                 row["columns"][0]["type"] = "icon";
00775                 row["columns"][0]["value"] = "icon_group.tga";
00776 
00777                 row["columns"][1]["column"] = "name";
00778                 row["columns"][1]["value"] = group_name;
00779                 row["columns"][1]["font"] = "SANSSERIF";
00780 
00781                 row["columns"][2]["column"] = "members";
00782                 row["columns"][2]["value"] = members;
00783                 row["columns"][2]["font"] = "SANSSERIFSMALL";
00784 
00785                 row["columns"][3]["column"] = "score";
00786                 row["columns"][3]["value"] = search_order;
00787 
00788                 list->addElement(row);
00789                 self->mResultsContents[group_id.asString()] = content;
00790         }
00791         list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending);
00792         self->updateResultCount();
00793 
00794         // Poke the result received timer
00795         self->mLastResultTimer.reset();
00796         self->mDidAutoSelect = FALSE;
00797 }
00798 
00799 
00800 // static
00801 void LLPanelDirBrowser::processDirClassifiedReply(LLMessageSystem* msg, void**)
00802 {
00803         S32             i;
00804         S32             num_new_rows;
00805 
00806         LLUUID  agent_id;
00807         LLUUID  query_id;
00808 
00809         msg->getUUID("AgentData", "AgentID", agent_id);
00810         if (agent_id != gAgent.getID())
00811         {
00812                 llwarns << "Message for wrong agent " << agent_id
00813                         << " in processDirClassifiedReply" << llendl;
00814                 return;
00815         }
00816 
00817         msg->getUUID("QueryData", "QueryID", query_id);
00818         LLPanelDirBrowser* self = gDirBrowserInstances.getIfThere(query_id);
00819         if (!self)
00820         {
00821                 return;
00822         }
00823 
00824         self->mHaveSearchResults = TRUE;
00825 
00826         LLCtrlListInterface *list = self->childGetListInterface("results");
00827         if (!list) return;
00828 
00829         if (!list->getCanSelect())
00830         {
00831                 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
00832                 self->mResultsContents = LLSD();
00833         }
00834 
00835         num_new_rows = msg->getNumberOfBlocksFast(_PREHASH_QueryReplies);
00836         self->mResultsReceived += num_new_rows;
00837 
00838         num_new_rows = self->showNextButton(num_new_rows);
00839         for (i = 0; i < num_new_rows; i++)
00840         {
00841                 LLUUID classified_id;
00842                 char name[DB_PARCEL_NAME_SIZE];         /*Flawfinder: ignore*/
00843                 U32 creation_date = 0;  // unix timestamp
00844                 U32 expiration_date = 0;        // future use
00845                 S32 price_for_listing = 0;
00846                 msg->getUUID("QueryReplies", "ClassifiedID", classified_id, i);
00847                 msg->getString("QueryReplies", "Name", DB_PARCEL_NAME_SIZE, name, i);
00848                 msg->getU32("QueryReplies","CreationDate",creation_date,i);
00849                 msg->getU32("QueryReplies","ExpirationDate",expiration_date,i);
00850                 msg->getS32("QueryReplies","PriceForListing",price_for_listing,i);
00851 
00852                 if ( classified_id.notNull() )
00853                 {
00854                         self->addClassified(list, classified_id, name, creation_date, price_for_listing);
00855 
00856                         LLSD content;
00857                         content["type"] = CLASSIFIED_CODE;
00858                         content["name"] = name;
00859                         self->mResultsContents[classified_id.asString()] = content;
00860                 }
00861         }
00862         // The server does the initial sort, by price paid per listing and date. JC
00863         self->updateResultCount();
00864 
00865         // Poke the result received timer
00866         self->mLastResultTimer.reset();
00867         self->mDidAutoSelect = FALSE;
00868 }
00869 
00870 void LLPanelDirBrowser::processDirLandReply(LLMessageSystem *msg, void**)
00871 {
00872         LLUUID  agent_id;
00873         LLUUID  query_id;
00874         LLUUID  parcel_id;
00875         char    name[MAX_STRING];               /*Flawfinder: ignore*/
00876         BOOL    auction;
00877         BOOL    for_sale;
00878         S32             sale_price;
00879         S32             actual_area;
00880 
00881         msg->getUUID("AgentData", "AgentID", agent_id);
00882         msg->getUUID("QueryData", "QueryID", query_id );
00883 
00884         LLPanelDirBrowser* browser;
00885         browser = gDirBrowserInstances.getIfThere(query_id);
00886         if (!browser) 
00887         {
00888                 // data from an old query
00889                 return;
00890         }
00891 
00892         // Only handled by LLPanelDirLand
00893         LLPanelDirLand* self = (LLPanelDirLand*)browser;
00894 
00895         self->mHaveSearchResults = TRUE;
00896 
00897         LLCtrlListInterface *list = self->childGetListInterface("results");
00898         if (!list) return;
00899 
00900         if (!list->getCanSelect())
00901         {
00902                 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
00903                 self->mResultsContents = LLSD();
00904         }
00905 
00906         BOOL use_price = gSavedSettings.getBOOL("FindLandPrice");
00907         S32 limit_price = self->childGetValue("priceedit").asInteger();
00908 
00909         BOOL use_area = gSavedSettings.getBOOL("FindLandArea");
00910         S32 limit_area = self->childGetValue("areaedit").asInteger();
00911 
00912         S32 i;
00913         S32 count = msg->getNumberOfBlocks("QueryReplies");
00914         self->mResultsReceived += count;
00915         
00916         S32 non_auction_count = 0;
00917         for (i = 0; i < count; i++)
00918         {
00919                 msg->getUUID(   "QueryReplies", "ParcelID", parcel_id, i);
00920                 msg->getString( "QueryReplies", "Name", MAX_STRING, name, i);
00921                 msg->getBOOL(   "QueryReplies", "Auction", auction, i);
00922                 msg->getBOOL(   "QueryReplies", "ForSale", for_sale, i);
00923                 msg->getS32(    "QueryReplies", "SalePrice", sale_price, i);
00924                 msg->getS32(    "QueryReplies", "ActualArea", actual_area, i);
00925                 
00926                 if (parcel_id.isNull()) continue;
00927 
00928                 if (use_price && (sale_price > limit_price)) continue;
00929 
00930                 if (use_area && (actual_area < limit_area)) continue;
00931 
00932                 LLSD content;
00933                 S32 type;
00934 
00935                 LLSD row = self->createLandSale(parcel_id, auction, for_sale,  name, &type);
00936 
00937                 content["type"] = type;
00938                 content["name"] = name;
00939 
00940                 LLString buffer = "Auction";
00941                 if (!auction)
00942                 {
00943                         buffer = llformat("%d", sale_price);
00944                         non_auction_count++;
00945                 }
00946                 row["columns"][3]["column"] = "price";
00947                 row["columns"][3]["value"] = buffer;
00948                 row["columns"][3]["font"] = "SANSSERIFSMALL";
00949 
00950                 buffer = llformat("%d", actual_area);
00951                 row["columns"][4]["column"] = "area";
00952                 row["columns"][4]["value"] = buffer;
00953                 row["columns"][4]["font"] = "SANSSERIFSMALL";
00954 
00955                 if (!auction)
00956                 {
00957                         F32 price_per_meter;
00958                         if (actual_area > 0)
00959                         {
00960                                 price_per_meter = (F32)sale_price / (F32)actual_area;
00961                         }
00962                         else
00963                         {
00964                                 price_per_meter = 0.f;
00965                         }
00966                         // Prices are usually L$1 - L$10 / meter
00967                         buffer = llformat("%.1f", price_per_meter);
00968                         row["columns"][5]["column"] = "per_meter";
00969                         row["columns"][5]["value"] = buffer;
00970                         row["columns"][5]["font"] = "SANSSERIFSMALL";
00971                 }
00972                 else
00973                 {
00974                         // Auctions start at L$1 per meter
00975                         row["columns"][5]["column"] = "per_meter";
00976                         row["columns"][5]["value"] = "1.0";
00977                         row["columns"][5]["font"] = "SANSSERIFSMALL";
00978                 }
00979 
00980                 list->addElement(row);
00981                 self->mResultsContents[parcel_id.asString()] = content;
00982         }
00983 
00984         // All auction results are shown on the first page
00985         // But they don't count towards the 100 / page limit
00986         // So figure out the next button here, when we know how many aren't auctions
00987         count = self->showNextButton(non_auction_count);
00988 
00989         // Empty string will sort by current sort options.
00990         list->sortByColumn("",FALSE);
00991         self->updateResultCount();
00992 
00993         // Poke the result received timer
00994         self->mLastResultTimer.reset();
00995         self->mDidAutoSelect = FALSE;
00996 }
00997 
00998 void LLPanelDirBrowser::addClassified(LLCtrlListInterface *list, const LLUUID& pick_id, const char* name, const U32 creation_date, const S32 price_for_listing)
00999 {
01000         LLString type = llformat("%d", CLASSIFIED_CODE);
01001 
01002         LLSD row;
01003         row["id"] = pick_id;
01004 
01005         row["columns"][0]["column"] = "icon";
01006         row["columns"][0]["type"] = "icon";
01007         row["columns"][0]["value"] = "icon_top_pick.tga";
01008 
01009         row["columns"][1]["column"] = "name";
01010         row["columns"][1]["value"] = name;
01011         row["columns"][1]["font"] = "SANSSERIF";
01012 
01013         row["columns"][2]["column"] = "price";
01014         row["columns"][2]["value"] = price_for_listing;
01015         row["columns"][2]["font"] = "SANSSERIFSMALL";
01016 
01017         list->addElement(row);
01018 }
01019 
01020 LLSD LLPanelDirBrowser::createLandSale(const LLUUID& parcel_id, BOOL is_auction, BOOL is_for_sale,  const LLString& name, S32 *type)
01021 {
01022         LLSD row;
01023         row["id"] = parcel_id;
01024         LLUUID image_id;
01025 
01026         // Icon and type
01027         if(is_auction)
01028         {
01029                 row["columns"][0]["column"] = "icon";
01030                 row["columns"][0]["type"] = "icon";
01031                 row["columns"][0]["value"] = "icon_auction.tga";
01032 
01033                 *type = AUCTION_CODE;
01034         }
01035         else if (is_for_sale)
01036         {
01037                 row["columns"][0]["column"] = "icon";
01038                 row["columns"][0]["type"] = "icon";
01039                 row["columns"][0]["value"] = "icon_for_sale.tga";
01040 
01041                 *type = FOR_SALE_CODE;
01042         }
01043         else
01044         {
01045                 row["columns"][0]["column"] = "icon";
01046                 row["columns"][0]["type"] = "icon";
01047                 row["columns"][0]["value"] = "icon_place.tga";
01048 
01049                 *type = PLACE_CODE;
01050         }
01051 
01052         row["columns"][2]["column"] = "name";
01053         row["columns"][2]["value"] = name;
01054         row["columns"][2]["font"] = "SANSSERIF";
01055 
01056         return row;
01057 }
01058 
01059 void LLPanelDirBrowser::newClassified()
01060 {
01061         LLCtrlListInterface *list = childGetListInterface("results");
01062         if (!list) return;
01063 
01064         if (mFloaterDirectory->mPanelClassifiedp)
01065         {
01066                 // Clear the panel on the right
01067                 mFloaterDirectory->mPanelClassifiedp->reset();
01068 
01069                 // Set up the classified with the info we've created
01070                 // and a sane default position.
01071                 mFloaterDirectory->mPanelClassifiedp->initNewClassified();
01072 
01073                 // We need the ID to select in the list.
01074                 LLUUID classified_id = mFloaterDirectory->mPanelClassifiedp->getClassifiedID();
01075 
01076                 // Put it in the list on the left
01077                 addClassified(list, classified_id, mFloaterDirectory->mPanelClassifiedp->getClassifiedName().c_str(),0,0);
01078 
01079                 // Select it.
01080                 list->setCurrentByID(classified_id);
01081 
01082                 // Make the right panel visible (should already be)
01083                 mFloaterDirectory->mPanelClassifiedp->setVisible(TRUE);
01084         }
01085 }
01086 
01087 void LLPanelDirBrowser::setupNewSearch()
01088 {
01089         LLScrollListCtrl* list = getChild<LLScrollListCtrl>("results");
01090 
01091         gDirBrowserInstances.removeData(mSearchID);
01092         // Make a new query ID
01093         mSearchID.generate();
01094 
01095         gDirBrowserInstances.addData(mSearchID, this);
01096 
01097         // ready the list for results
01098         list->operateOnAll(LLCtrlListInterface::OP_DELETE);
01099         list->addCommentText(getString("searching_text"));
01100         childDisable("results");
01101 
01102         mResultsReceived = 0;
01103         mHaveSearchResults = FALSE;
01104 
01105         // Set all panels to be invisible
01106         mFloaterDirectory->hideAllDetailPanels();
01107 
01108         updateResultCount();
01109 }
01110 
01111 
01112 // static
01113 // called from calssifieds, events, groups, land, people, and places
01114 void LLPanelDirBrowser::onClickSearchCore(void* userdata)
01115 {
01116         LLPanelDirBrowser* self = (LLPanelDirBrowser*)userdata;
01117         if (!self) return;
01118 
01119         self->resetSearchStart();
01120         self->performQuery();
01121 
01122         LLFloaterDirectory::sOldSearchCount++;
01123 }
01124 
01125 
01126 // static
01127 void LLPanelDirBrowser::sendDirFindQuery(
01128         LLMessageSystem* msg,
01129         const LLUUID& query_id,
01130         const LLString& text,
01131         U32 flags,
01132         S32 query_start)
01133 {
01134         msg->newMessage("DirFindQuery");
01135         msg->nextBlock("AgentData");
01136         msg->addUUID("AgentID", gAgent.getID());
01137         msg->addUUID("SessionID", gAgent.getSessionID());
01138         msg->nextBlock("QueryData");
01139         msg->addUUID("QueryID", query_id);
01140         msg->addString("QueryText", text);
01141         msg->addU32("QueryFlags", flags);
01142         msg->addS32("QueryStart", query_start);
01143         gAgent.sendReliableMessage();
01144 }
01145 
01146 
01147 void LLPanelDirBrowser::addHelpText(const char* text)
01148 {
01149         LLScrollListCtrl* list = getChild<LLScrollListCtrl>("results");
01150 
01151         list->addCommentText(text);
01152         childDisable("results");
01153 }
01154 
01155 
01156 void LLPanelDirBrowser::onKeystrokeName(LLLineEditor* line, void* data)
01157 {
01158         LLPanelDirBrowser *self = (LLPanelDirBrowser*)data;
01159         if (line->getLength() >= (S32)self->mMinSearchChars)
01160         {
01161                 self->setDefaultBtn( "Search" );
01162                 self->childEnable("Search");
01163         }
01164         else
01165         {
01166                 self->setDefaultBtn();
01167                 self->childDisable("Search");
01168         }
01169 }
01170 
01171 // setup results when shown
01172 void LLPanelDirBrowser::onVisibilityChange(BOOL new_visibility)
01173 {
01174         if (new_visibility)
01175         {
01176                 onCommitList(NULL, this);
01177         }
01178         LLPanel::onVisibilityChange(new_visibility);
01179 }
01180 
01181 S32 LLPanelDirBrowser::showNextButton(S32 rows)
01182 {
01183         // HACK: This hack doesn't work for llpaneldirfind (ALL) 
01184         // because other data is being returned as well.
01185         if ( getName() != "find_all_old_panel")
01186         {
01187                 // HACK: The (mResultsPerPage)+1th entry indicates there are 'more'
01188                 bool show_next = (mResultsReceived > mResultsPerPage);
01189                 childSetVisible("Next >", show_next);
01190                 if (show_next)
01191                 {
01192                         rows -= (mResultsReceived - mResultsPerPage);
01193                 }
01194         }
01195         else
01196         {
01197                 // Hide page buttons
01198                 childHide("Next >");
01199                 childHide("< Prev");
01200         }
01201         return rows;
01202 }

Generated on Fri May 16 08:33:49 2008 for SecondLife by  doxygen 1.5.5