llpanelplace.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  1. /**
  2. * @file llpanelplace.cpp
  3. * @brief Display of a place in the Find directory.
  4. *
  5. * $LicenseInfo:firstyear=2004&license=viewergpl$
  6. *
  7. * Copyright (c) 2004-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llpanelplace.h"
  34. #include "llbutton.h"
  35. #include "llcachename.h"
  36. #include "llfloater.h"
  37. #include "llqueryflags.h"
  38. #include "llregionhandle.h"
  39. #include "llsdutil.h"
  40. #include "llsdutil_math.h"
  41. #include "llsdserialize.h"
  42. #include "lltextbox.h"
  43. #include "lltexteditor.h"
  44. #include "lluictrlfactory.h"
  45. #include "llagent.h"
  46. #include "llfloateravatarinfo.h"
  47. #include "llfloatergroupinfo.h"
  48. #include "llfloaterworldmap.h"
  49. #include "llgridmanager.h"
  50. #include "lltexturectrl.h"
  51. #include "llviewercontrol.h"
  52. #if CREATE_LANDMARK
  53. # include "llviewermenu.h" // For create_landmark()
  54. #endif
  55. #include "llviewerparcelmgr.h"
  56. #include "llviewerregion.h"
  57. #include "llweb.h"
  58. #include "llworldmap.h"
  59. //static
  60. std::set<LLPanelPlace*> LLPanelPlace::sInstances;
  61. // LLPanelPlace class proper
  62. LLPanelPlace::LLPanelPlace(bool can_close_parent)
  63. : LLPanel(std::string("Places Panel")),
  64. mCanCloseParent(can_close_parent),
  65. mTeleportRequested(false),
  66. mOwnerIsGroup(false),
  67. mAuctionID(0)
  68. {
  69. sInstances.insert(this);
  70. }
  71. LLPanelPlace::~LLPanelPlace()
  72. {
  73. sInstances.erase(this);
  74. mTeleportArrivingConnection.disconnect();
  75. mTeleportFailedConnection.disconnect();
  76. gViewerParcelMgr.removeInfoObserver(mParcelID, this);
  77. }
  78. bool LLPanelPlace::postBuild()
  79. {
  80. // Since this is only used in the directory browser, always
  81. // disable the snapshot control. Otherwise clicking on it will
  82. // open a texture picker.
  83. mSnapshotCtrl = getChild<LLTextureCtrl>("snapshot_ctrl");
  84. mSnapshotCtrl->setEnabled(false);
  85. mParcelNameText = getChild<LLTextBox>("name_editor");
  86. // Text boxes appear to have a " " in them by default. This breaks the
  87. // emptiness test for filling in data from the network. Slam to empty.
  88. mParcelNameText->setText(LLStringUtil::null);
  89. mDescEditor = getChild<LLTextEditor>("desc_editor");
  90. mParcelInfoText = getChild<LLTextBox>("info_editor");
  91. // This item exists only in panel_place_small.xml
  92. mLandTypeText = getChild<LLTextBox>("land_type_display", true, false);
  93. // These items exists only in panel_place.xml
  94. mOwnerLabel = getChild<LLTextBox>("owner_label", true, false);
  95. mOwnerText = getChild<LLTextBox>("owner_name", true, false);
  96. if (mOwnerText)
  97. {
  98. mOwnerText->setClickedCallback(onClickOwnerName, this);
  99. mOwnerText->setColor(LLTextEditor::getLinksColor());
  100. }
  101. mLocationText = getChild<LLTextBox>("location_editor");
  102. mTeleportBtn = getChild<LLButton>( "teleport_btn");
  103. mTeleportBtn->setClickedCallback(onClickTeleport);
  104. mTeleportBtn->setCallbackUserData(this);
  105. mMapBtn = getChild<LLButton>("map_btn");
  106. mMapBtn->setClickedCallback(onClickMap);
  107. mMapBtn->setCallbackUserData(this);
  108. #if CREATE_LANDMARK
  109. mLandmarkBtn = getChild<LLButton>( "landmark_btn");
  110. mLandmarkBtn->setClickedCallback(onClickLandmark);
  111. mLandmarkBtn->setCallbackUserData(this);
  112. #endif
  113. mAuctionBtn = getChild<LLButton>("auction_btn");
  114. mAuctionBtn->setClickedCallback(onClickAuction);
  115. mAuctionBtn->setCallbackUserData(this);
  116. // Default to no auction button. We will show it if we get an auction Id.
  117. mAuctionBtn->setVisible(false);
  118. mTeleportArrivingConnection =
  119. gViewerParcelMgr.setTPArrivingCallback(boost::bind(&LLPanelPlace::onTeleportArriving,
  120. this));
  121. mTeleportFailedConnection =
  122. gViewerParcelMgr.setTPFailedCallback(boost::bind(&LLPanelPlace::onTeleportFailed,
  123. this));
  124. return true;
  125. }
  126. void LLPanelPlace::displayItemInfo(const LLInventoryItem* pItem)
  127. {
  128. mParcelNameText->setText(pItem->getName());
  129. mDescEditor->setText(pItem->getDescription());
  130. }
  131. // Use this for search directory clicks, because we are totally recycling the
  132. // panel and don't need to use what's there.
  133. // For SLURL clicks, don't call this, because we need to cache the location
  134. // info from the user.
  135. void LLPanelPlace::resetLocation()
  136. {
  137. mTeleportArrivingConnection.disconnect();
  138. mTeleportFailedConnection.disconnect();
  139. gViewerParcelMgr.removeInfoObserver(mParcelID, this);
  140. mParcelID.setNull();
  141. mRequestedID.setNull();
  142. mRegionID.setNull();
  143. mLandmarkAssetID.setNull();
  144. mPosGlobal.clear();
  145. mPosRegion.clear();
  146. mAuctionID = 0;
  147. mParcelNameText->setText(LLStringUtil::null);
  148. mDescEditor->setText(LLStringUtil::null);
  149. mParcelInfoText->setText(LLStringUtil::null);
  150. if (mLandTypeText)
  151. {
  152. mLandTypeText->setText(LLStringUtil::null);
  153. }
  154. if (mOwnerLabel)
  155. {
  156. mOwnerLabel->setVisible(false);
  157. }
  158. if (mOwnerText)
  159. {
  160. mOwnerText->setVisible(false);
  161. mOwnerText->setText(LLStringUtil::null);
  162. }
  163. mLocationText->setText(LLStringUtil::null);
  164. }
  165. // Set the name and clear other bits of info. Used for SLURL clicks
  166. void LLPanelPlace::resetName(const std::string& name)
  167. {
  168. setName(name);
  169. mDescEditor->setText(LLStringUtil::null);
  170. llinfos << "Clearing place name" << llendl;
  171. mParcelNameText->setText(LLStringUtil::null);
  172. mParcelInfoText->setText(LLStringUtil::null);
  173. if (mLandTypeText)
  174. {
  175. mLandTypeText->setText(LLStringUtil::null);
  176. }
  177. if (mOwnerLabel)
  178. {
  179. mOwnerLabel->setVisible(false);
  180. }
  181. if (mOwnerText)
  182. {
  183. mOwnerText->setVisible(false);
  184. mOwnerText->setText(LLStringUtil::null);
  185. }
  186. }
  187. //virtual
  188. void LLPanelPlace::setParcelID(const LLUUID& parcel_id)
  189. {
  190. mParcelID = parcel_id;
  191. sendParcelInfoRequest();
  192. }
  193. void LLPanelPlace::setSnapshot(const LLUUID& snapshot_id)
  194. {
  195. mSnapshotCtrl->setImageAssetID(snapshot_id);
  196. }
  197. void LLPanelPlace::setLocationString(const std::string& location)
  198. {
  199. mLocationText->setText(location);
  200. }
  201. void LLPanelPlace::setLandTypeString(const std::string& land_type)
  202. {
  203. if (mLandTypeText)
  204. {
  205. mLandTypeText->setText(land_type);
  206. }
  207. }
  208. void LLPanelPlace::sendParcelInfoRequest()
  209. {
  210. if (mParcelID != mRequestedID)
  211. {
  212. gViewerParcelMgr.addInfoObserver(mParcelID, this);
  213. gViewerParcelMgr.sendParcelInfoRequest(mParcelID);
  214. mRequestedID = mParcelID;
  215. }
  216. }
  217. //virtual
  218. void LLPanelPlace::setErrorStatus(S32 status, const std::string& reason)
  219. {
  220. // Remove the observer
  221. gViewerParcelMgr.removeInfoObserver(mParcelID, this);
  222. // We only really handle 404 and 499 errors
  223. std::string error_text;
  224. if (status == HTTP_NOT_FOUND)
  225. {
  226. error_text = getString("server_error_text");
  227. }
  228. else if (status == HTTP_INTERNAL_ERROR)
  229. {
  230. error_text = getString("server_forbidden_text");
  231. }
  232. mDescEditor->setText(error_text);
  233. }
  234. //virtual
  235. void LLPanelPlace::processParcelInfo(const LLParcelData& parcel_data)
  236. {
  237. mAuctionID = parcel_data.mAuctionId;
  238. if (parcel_data.mSnapshotId.notNull())
  239. {
  240. mSnapshotCtrl->setImageAssetID(parcel_data.mSnapshotId);
  241. }
  242. // Only assign the name and description if they are not empty and there
  243. // is not a value present (e.g. passed in from a landmark)
  244. if (mParcelNameText->getText().empty() && !parcel_data.mName.empty())
  245. {
  246. mParcelNameText->setText(parcel_data.mName);
  247. }
  248. if (mDescEditor->getText().empty() && !parcel_data.mDesc.empty())
  249. {
  250. mDescEditor->setText(parcel_data.mDesc);
  251. }
  252. U8 flags = parcel_data.mFlags;
  253. LLUIString traffic = getString("traffic_text");
  254. traffic.setArg("[TRAFFIC]", llformat("%d", (int)parcel_data.mDwell));
  255. std::string info_text = traffic;
  256. info_text += ' ';
  257. LLUIString area = getString("area_text");
  258. area.setArg("[AREA]", llformat("%d", parcel_data.mActualArea));
  259. info_text += area;
  260. bool for_sale = flags & DFQ_FOR_SALE;
  261. if (for_sale)
  262. {
  263. info_text += ' ';
  264. LLUIString forsale = getString("forsale_text");
  265. forsale.setArg("[PRICE]", llformat("%d", parcel_data.mSalePrice));
  266. info_text += forsale;
  267. }
  268. if (mAuctionID)
  269. {
  270. for_sale = true;
  271. info_text += ' ';
  272. LLUIString auction = getString("auction_text");
  273. auction.setArg("[ID]", llformat("%010d ", mAuctionID));
  274. info_text += auction;
  275. }
  276. mAuctionBtn->setVisible(mAuctionID > 0);
  277. mParcelInfoText->setText(info_text);
  278. mOwnerID = parcel_data.mOwnerId;
  279. if (!for_sale && mOwnerText && mOwnerID.notNull() && gCacheNamep)
  280. {
  281. std::string name;
  282. bool got_name;
  283. mOwnerIsGroup = flags & 0x4; // Depends onto DRTSIM-453
  284. if (mOwnerIsGroup)
  285. {
  286. got_name = gCacheNamep->getGroupName(mOwnerID, name);
  287. }
  288. else
  289. {
  290. got_name = gCacheNamep->getFullName(mOwnerID, name);
  291. }
  292. if (got_name)
  293. {
  294. if (mOwnerLabel)
  295. {
  296. mOwnerLabel->setVisible(true);
  297. }
  298. mOwnerText->setVisible(true);
  299. mOwnerText->setText(name);
  300. }
  301. else
  302. {
  303. gCacheNamep->get(mOwnerID, mOwnerIsGroup,
  304. boost::bind(&LLPanelPlace::nameCallback,
  305. _1, _2, _3, this));
  306. }
  307. }
  308. // *HACK: Flag 0x2 == adult region, Flag 0x1 == mature region, otherwise
  309. // assume PG.
  310. std::string rating;
  311. if (flags & 0x2)
  312. {
  313. rating = LLViewerRegion::accessToString(SIM_ACCESS_ADULT);
  314. }
  315. else if (flags & 0x1)
  316. {
  317. rating = LLViewerRegion::accessToString(SIM_ACCESS_MATURE);
  318. }
  319. else
  320. {
  321. rating = LLViewerRegion::accessToString(SIM_ACCESS_PG);
  322. }
  323. if (mPosGlobal.isExactlyZero())
  324. {
  325. mPosGlobal.set(parcel_data.mGlobalX, parcel_data.mGlobalY,
  326. parcel_data.mGlobalZ);
  327. }
  328. S32 region_x, region_y, region_z;
  329. // If the region position is zero, grab position from the global
  330. if (mPosRegion.isExactlyZero())
  331. {
  332. region_x = ll_round(parcel_data.mGlobalX) % REGION_WIDTH_UNITS;
  333. region_y = ll_round(parcel_data.mGlobalY) % REGION_WIDTH_UNITS;
  334. region_z = ll_round(parcel_data.mGlobalZ);
  335. }
  336. else
  337. {
  338. // Just use given region position for display
  339. region_x = ll_round(mPosRegion.mV[0]);
  340. region_y = ll_round(mPosRegion.mV[1]);
  341. region_z = ll_round(mPosRegion.mV[2]);
  342. }
  343. std::string location = llformat("%s %d, %d, %d (%s)",
  344. parcel_data.mSimName.c_str(),
  345. region_x, region_y, region_z,
  346. rating.c_str());
  347. mLocationText->setText(location);
  348. }
  349. void LLPanelPlace::displayParcelInfo(const LLVector3& pos_region,
  350. const LLUUID& landmark_asset_id,
  351. // item_id so to send map correct id
  352. const LLUUID& landmark_item_id,
  353. const LLUUID& region_id,
  354. const LLVector3d& pos_global)
  355. {
  356. mRegionID = region_id;
  357. mPosRegion = pos_region;
  358. mPosGlobal = pos_global;
  359. mLandmarkAssetID = landmark_asset_id;
  360. mLandmarkItemID = landmark_item_id;
  361. const std::string& url = gAgent.getRegionCapability("RemoteParcelRequest");
  362. if (url.empty())
  363. {
  364. mDescEditor->setText(getString("server_update_text"));
  365. }
  366. else
  367. {
  368. gViewerParcelMgr.requestRegionParcelInfo(url, mRegionID, mPosRegion,
  369. mPosGlobal, getObserverHandle());
  370. }
  371. mSnapshotCtrl->setImageAssetID(LLUUID::null);
  372. mSnapshotCtrl->setFallbackImageName("default_land_picture.j2c");
  373. }
  374. //static
  375. void LLPanelPlace::onTeleportArriving(LLPanelPlace* self)
  376. {
  377. if (sInstances.count(self) && self->mTeleportRequested)
  378. {
  379. self->mTeleportRequested = false;
  380. if (gSavedSettings.getBool("HideFloatersOnTPSuccess"))
  381. {
  382. LLView* parent_viewp = self->getParent();
  383. if (!parent_viewp) return;
  384. LLFloater* parent_floaterp = parent_viewp->asFloater();
  385. if (parent_floaterp && parent_floaterp->getVisible() &&
  386. !parent_floaterp->isMinimized())
  387. {
  388. if (self->canCloseParent())
  389. {
  390. parent_floaterp->close();
  391. }
  392. else
  393. {
  394. parent_floaterp->setVisible(false);
  395. }
  396. }
  397. }
  398. }
  399. }
  400. //static
  401. void LLPanelPlace::onTeleportFailed(LLPanelPlace* self)
  402. {
  403. if (sInstances.count(self) && self->mTeleportRequested)
  404. {
  405. self->mTeleportRequested = false;
  406. }
  407. }
  408. //static
  409. void LLPanelPlace::onClickTeleport(void* data)
  410. {
  411. LLPanelPlace* self = (LLPanelPlace*)data;
  412. if (!self) return;
  413. self->mTeleportRequested = true;
  414. if (self->mLandmarkAssetID.notNull())
  415. {
  416. gAgent.teleportViaLandmark(self->mLandmarkAssetID);
  417. if (gFloaterWorldMapp)
  418. {
  419. // remember this must be an inventory item id, not an asset UUID
  420. gFloaterWorldMapp->trackLandmark(self->mLandmarkItemID);
  421. }
  422. }
  423. else if (!self->mPosGlobal.isExactlyZero())
  424. {
  425. gAgent.teleportViaLocation(self->mPosGlobal);
  426. if (gFloaterWorldMapp)
  427. {
  428. gFloaterWorldMapp->trackLocation(self->mPosGlobal);
  429. }
  430. }
  431. }
  432. //static
  433. void LLPanelPlace::onClickMap(void* data)
  434. {
  435. LLPanelPlace* self = (LLPanelPlace*)data;
  436. if (self && !self->mPosGlobal.isExactlyZero() && gFloaterWorldMapp)
  437. {
  438. // It's likely we're going to TP and don't care any more about this
  439. // panel, so let's flag it like if a TP was requested to allow
  440. // auto-close on next TP success:
  441. self->mTeleportRequested = true;
  442. gFloaterWorldMapp->trackLocation(self->mPosGlobal);
  443. LLFloaterWorldMap::show(NULL, true);
  444. }
  445. }
  446. #if CREATE_LANDMARK
  447. //static
  448. void LLPanelPlace::onClickLandmark(void* data)
  449. {
  450. LLPanelPlace* self = (LLPanelPlace*)data;
  451. create_landmark(self->mParcelNameText->getText(), "", self->mPosGlobal);
  452. }
  453. #endif
  454. //static
  455. void LLPanelPlace::onClickAuction(void* data)
  456. {
  457. LLPanelPlace* self = (LLPanelPlace*)data;
  458. if (!self) return;
  459. LLSD payload;
  460. payload["auction_id"] = self->mAuctionID;
  461. gNotifications.add("GoToAuctionPage", LLSD(), payload,
  462. callbackAuctionWebPage);
  463. }
  464. //static
  465. bool LLPanelPlace::callbackAuctionWebPage(const LLSD& notification,
  466. const LLSD& response)
  467. {
  468. if (LLNotification::getSelectedOption(notification, response) == 0)
  469. {
  470. std::string url;
  471. S32 auction_id = notification["payload"]["auction_id"].asInteger();
  472. url = AUCTION_URL + llformat("%010d", auction_id );
  473. llinfos << "Loading auction page " << url << llendl;
  474. LLWeb::loadURL(url);
  475. }
  476. return false;
  477. }
  478. //static
  479. void LLPanelPlace::onClickOwnerName(void* data)
  480. {
  481. LLPanelPlace* self = (LLPanelPlace*)data;
  482. if (self && self->mOwnerID.notNull())
  483. {
  484. if (self->mOwnerIsGroup)
  485. {
  486. LLFloaterGroupInfo::showFromUUID(self->mOwnerID);
  487. }
  488. else
  489. {
  490. LLFloaterAvatarInfo::show(self->mOwnerID);
  491. }
  492. }
  493. }
  494. //static
  495. void LLPanelPlace::nameCallback(const LLUUID& id, const std::string& name,
  496. bool is_group, LLPanelPlace* self)
  497. {
  498. if (self && sInstances.count(self) && self->mOwnerText &&
  499. id == self->mOwnerID)
  500. {
  501. if (self->mOwnerLabel)
  502. {
  503. self->mOwnerLabel->setVisible(true);
  504. }
  505. self->mOwnerText->setVisible(true);
  506. self->mOwnerText->setText(name);
  507. }
  508. }