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

Generated on Thu Jul 1 06:08:56 2010 for Second Life Viewer by  doxygen 1.4.7