/** * @file llpanellandmarkinfo.cpp * @brief Displays landmark info in Side Tray. * * $LicenseInfo:firstyear=2009&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License only. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ #include "llviewerprecompiledheaders.h" #include "llpanellandmarkinfo.h" #include "llcombobox.h" #include "lliconctrl.h" #include "llinventoryfunctions.h" #include "lllineeditor.h" #include "lltextbox.h" #include "lltexteditor.h" #include "lltrans.h" #include "llagent.h" #include "llagentui.h" #include "lllandmarkactions.h" #include "llparcel.h" #include "llslurl.h" #include "llviewerinventory.h" #include "llviewerparcelmgr.h" #include "llviewerregion.h" //---------------------------------------------------------------------------- // Aux types and methods //---------------------------------------------------------------------------- typedef std::pair<LLUUID, std::string> folder_pair_t; static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right); static LLPanelInjector<LLPanelLandmarkInfo> t_landmark_info("panel_landmark_info"); // Statics for textures filenames static std::string icon_pg; static std::string icon_m; static std::string icon_r; LLPanelLandmarkInfo::LLPanelLandmarkInfo() : LLPanelPlaceInfo() {} // virtual LLPanelLandmarkInfo::~LLPanelLandmarkInfo() {} // virtual BOOL LLPanelLandmarkInfo::postBuild() { LLPanelPlaceInfo::postBuild(); mOwner = getChild<LLTextBox>("owner"); mCreator = getChild<LLTextBox>("creator"); mCreated = getChild<LLTextBox>("created"); mLandmarkTitle = getChild<LLLineEditor>("title_value"); mLandmarkTitleEditor = getChild<LLLineEditor>("title_editor"); mNotesEditor = getChild<LLTextEditor>("notes_editor"); mFolderCombo = getChild<LLComboBox>("folder_combo"); icon_pg = getString("icon_PG"); icon_m = getString("icon_M"); icon_r = getString("icon_R"); return TRUE; } // virtual void LLPanelLandmarkInfo::resetLocation() { LLPanelPlaceInfo::resetLocation(); std::string loading = LLTrans::getString("LoadingData"); mCreator->setText(loading); mOwner->setText(loading); mCreated->setText(loading); mLandmarkTitle->setText(LLStringUtil::null); mLandmarkTitleEditor->setText(LLStringUtil::null); mNotesEditor->setText(LLStringUtil::null); } // virtual void LLPanelLandmarkInfo::setInfoType(EInfoType type) { LLUUID dest_folder; setInfoType(type, dest_folder); } // Sets CREATE_LANDMARK infotype and creates landmark at desired folder void LLPanelLandmarkInfo::setInfoAndCreateLandmark(const LLUUID& folder_id) { setInfoType(CREATE_LANDMARK, folder_id); } void LLPanelLandmarkInfo::setInfoType(EInfoType type, const LLUUID &folder_id) { LLPanel* landmark_info_panel = getChild<LLPanel>("landmark_info_panel"); bool is_info_type_create_landmark = type == CREATE_LANDMARK; landmark_info_panel->setVisible(type == LANDMARK); getChild<LLTextBox>("folder_label")->setVisible(is_info_type_create_landmark); getChild<LLButton>("edit_btn")->setVisible(!is_info_type_create_landmark); mFolderCombo->setVisible(is_info_type_create_landmark); switch(type) { case CREATE_LANDMARK: { mCurrentTitle = getString("title_create_landmark"); mLandmarkTitle->setVisible(FALSE); mLandmarkTitleEditor->setVisible(TRUE); mNotesEditor->setEnabled(TRUE); LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance(); LLParcel* parcel = parcel_mgr->getAgentParcel(); std::string name = parcel->getName(); LLVector3 agent_pos = gAgent.getPositionAgent(); if (name.empty()) { S32 region_x = ll_round(agent_pos.mV[VX]); S32 region_y = ll_round(agent_pos.mV[VY]); S32 region_z = ll_round(agent_pos.mV[VZ]); std::string region_name; LLViewerRegion* region = parcel_mgr->getSelectionRegion(); if (region) { region_name = region->getName(); } else { std::string desc; LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_NORMAL, agent_pos); region_name = desc; } mLandmarkTitleEditor->setText(llformat("%s (%d, %d, %d)", region_name.c_str(), region_x, region_y, region_z)); } else { mLandmarkTitleEditor->setText(name); } LLUUID owner_id = parcel->getOwnerID(); if (owner_id.notNull()) { if (parcel->getIsGroupOwned()) { std::string owner_name = LLSLURL("group", parcel->getGroupID(), "inspect").getSLURLString(); mParcelOwner->setText(owner_name); } else { std::string owner_name = LLSLURL("agent", owner_id, "inspect").getSLURLString(); mParcelOwner->setText(owner_name); } } else { mParcelOwner->setText(getString("public")); } // Moved landmark creation here from LLPanelLandmarkInfo::processParcelInfo() // because we use only agent's current coordinates instead of waiting for // remote parcel request to complete. if (!LLLandmarkActions::landmarkAlreadyExists()) { createLandmark(folder_id); } } break; case LANDMARK: default: mCurrentTitle = getString("title_landmark"); mLandmarkTitle->setVisible(TRUE); mLandmarkTitleEditor->setVisible(FALSE); mNotesEditor->setEnabled(FALSE); break; } populateFoldersList(); // Prevent the floater from losing focus (if the sidepanel is undocked). setFocus(TRUE); LLPanelPlaceInfo::setInfoType(type); } // virtual void LLPanelLandmarkInfo::processParcelInfo(const LLParcelData& parcel_data) { LLPanelPlaceInfo::processParcelInfo(parcel_data); // HACK: Flag 0x2 == adult region, // Flag 0x1 == mature region, otherwise assume PG if (parcel_data.flags & 0x2) { mMaturityRatingIcon->setValue(icon_r); mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_ADULT)); } else if (parcel_data.flags & 0x1) { mMaturityRatingIcon->setValue(icon_m); mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_MATURE)); } else { mMaturityRatingIcon->setValue(icon_pg); mMaturityRatingText->setText(LLViewerRegion::accessToString(SIM_ACCESS_PG)); } if (parcel_data.owner_id.notNull()) { if (parcel_data.flags & 0x4) // depends onto DRTSIM-453 { std::string owner_name = LLSLURL("group", parcel_data.owner_id, "inspect").getSLURLString(); mParcelOwner->setText(owner_name); } else { std::string owner_name = LLSLURL("agent", parcel_data.owner_id, "inspect").getSLURLString(); mParcelOwner->setText(owner_name); } } else { mParcelOwner->setText(getString("public")); } LLSD info; info["update_verbs"] = true; info["global_x"] = parcel_data.global_x; info["global_y"] = parcel_data.global_y; info["global_z"] = parcel_data.global_z; notifyParent(info); } void LLPanelLandmarkInfo::displayItemInfo(const LLInventoryItem* pItem) { if (!pItem) return; if(!gCacheName) return; const LLPermissions& perm = pItem->getPermissions(); ////////////////// // CREATOR NAME // ////////////////// if (pItem->getCreatorUUID().notNull()) { // IDEVO LLUUID creator_id = pItem->getCreatorUUID(); std::string name = LLSLURL("agent", creator_id, "inspect").getSLURLString(); mCreator->setText(name); } else { mCreator->setText(getString("unknown")); } //////////////// // OWNER NAME // //////////////// if(perm.isOwned()) { std::string name; if (perm.isGroupOwned()) { LLUUID group_id = perm.getGroup(); name = LLSLURL("group", group_id, "inspect").getSLURLString(); } else { LLUUID owner_id = perm.getOwner(); name = LLSLURL("agent", owner_id, "inspect").getSLURLString(); } mOwner->setText(name); } else { std::string public_str = getString("public"); mOwner->setText(public_str); } ////////////////// // ACQUIRE DATE // ////////////////// time_t time_utc = pItem->getCreationDate(); if (0 == time_utc) { mCreated->setText(getString("unknown")); } else { std::string timeStr = getString("acquired_date"); LLSD substitution; substitution["datetime"] = (S32) time_utc; LLStringUtil::format (timeStr, substitution); mCreated->setText(timeStr); } mLandmarkTitle->setText(pItem->getName()); mLandmarkTitleEditor->setText(pItem->getName()); mNotesEditor->setText(pItem->getDescription()); } void LLPanelLandmarkInfo::toggleLandmarkEditMode(BOOL enabled) { // If switching to edit mode while creating landmark // the "Create Landmark" title remains. if (enabled && mInfoType != CREATE_LANDMARK) { mTitle->setText(getString("title_edit_landmark")); } else { mTitle->setText(mCurrentTitle); mLandmarkTitle->setText(mLandmarkTitleEditor->getText()); } if (mNotesEditor->getReadOnly() == (enabled == TRUE)) { mLandmarkTitle->setVisible(!enabled); mLandmarkTitleEditor->setVisible(enabled); mNotesEditor->setReadOnly(!enabled); mFolderCombo->setVisible(enabled); getChild<LLTextBox>("folder_label")->setVisible(enabled); getChild<LLButton>("edit_btn")->setVisible(!enabled); // HACK: To change the text color in a text editor // when it was enabled/disabled we set the text once again. mNotesEditor->setText(mNotesEditor->getText()); } // Prevent the floater from losing focus (if the sidepanel is undocked). setFocus(TRUE); } void LLPanelLandmarkInfo::setCanEdit(BOOL enabled) { getChild<LLButton>("edit_btn")->setEnabled(enabled); } const std::string& LLPanelLandmarkInfo::getLandmarkTitle() const { return mLandmarkTitleEditor->getText(); } const std::string LLPanelLandmarkInfo::getLandmarkNotes() const { return mNotesEditor->getText(); } const LLUUID LLPanelLandmarkInfo::getLandmarkFolder() const { return mFolderCombo->getValue().asUUID(); } BOOL LLPanelLandmarkInfo::setLandmarkFolder(const LLUUID& id) { return mFolderCombo->setCurrentByID(id); } void LLPanelLandmarkInfo::createLandmark(const LLUUID& folder_id) { std::string name = mLandmarkTitleEditor->getText(); std::string desc = mNotesEditor->getText(); LLStringUtil::trim(name); LLStringUtil::trim(desc); // If typed name is empty use the parcel name instead. if (name.empty()) { name = mParcelName->getText(); // If no parcel exists use the region name instead. if (name.empty()) { name = mRegionTitle; } } LLStringUtil::replaceChar(desc, '\n', ' '); // If no folder chosen use the "Landmarks" folder. LLLandmarkActions::createLandmarkHere(name, desc, folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK)); } // static std::string LLPanelLandmarkInfo::getFullFolderName(const LLViewerInventoryCategory* cat) { std::string name; LLUUID parent_id; llassert(cat); if (cat) { name = cat->getName(); parent_id = cat->getParentUUID(); bool is_under_root_category = parent_id == gInventory.getRootFolderID(); // we don't want "My Inventory" to appear in the name while ((parent_id = cat->getParentUUID()).notNull()) { cat = gInventory.getCategory(parent_id); llassert(cat); if (cat) { if (is_under_root_category || cat->getParentUUID() == gInventory.getRootFolderID()) { std::string localized_name; // Looking for translation only for protected type categories // to avoid warnings about non existent string in strings.xml. bool is_protected_type = LLFolderType::lookupIsProtectedType(cat->getPreferredType()); if (is_under_root_category) { // translate category name, if it's right below the root bool is_found = is_protected_type && LLTrans::findString(localized_name, "InvFolder " + name); name = is_found ? localized_name : name; } else { bool is_found = is_protected_type && LLTrans::findString(localized_name, "InvFolder " + cat->getName()); // add translated category name to folder's full name name = (is_found ? localized_name : cat->getName()) + "/" + name; } break; } else { name = cat->getName() + "/" + name; } } } } return name; } void LLPanelLandmarkInfo::populateFoldersList() { // Collect all folders that can contain landmarks. LLInventoryModel::cat_array_t cats; collectLandmarkFolders(cats); mFolderCombo->removeall(); // Put the "Landmarks" folder first in list. LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); const LLViewerInventoryCategory* lmcat = gInventory.getCategory(landmarks_id); if (!lmcat) { LL_WARNS() << "Cannot find the landmarks folder" << LL_ENDL; } else { std::string cat_full_name = getFullFolderName(lmcat); mFolderCombo->add(cat_full_name, lmcat->getUUID()); } typedef std::vector<folder_pair_t> folder_vec_t; folder_vec_t folders; // Sort the folders by their full name. for (S32 i = 0; i < cats.size(); i++) { const LLViewerInventoryCategory* cat = cats.at(i); std::string cat_full_name = getFullFolderName(cat); folders.push_back(folder_pair_t(cat->getUUID(), cat_full_name)); } sort(folders.begin(), folders.end(), cmp_folders); // Finally, populate the combobox. for (folder_vec_t::const_iterator it = folders.begin(); it != folders.end(); it++) mFolderCombo->add(it->second, LLSD(it->first)); } static bool cmp_folders(const folder_pair_t& left, const folder_pair_t& right) { return left.second < right.second; } void LLPanelLandmarkInfo::collectLandmarkFolders(LLInventoryModel::cat_array_t& cats) { LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); // Add descendent folders of the "Landmarks" category. LLInventoryModel::item_array_t items; // unused LLIsType is_category(LLAssetType::AT_CATEGORY); gInventory.collectDescendentsIf( landmarks_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_category); } /* virtual */ void LLUpdateLandmarkParent::fire(const LLUUID& inv_item_id) { LLInventoryModel::update_list_t update; LLInventoryModel::LLCategoryUpdate old_folder(mItem->getParentUUID(), -1); update.push_back(old_folder); LLInventoryModel::LLCategoryUpdate new_folder(mNewParentId, 1); update.push_back(new_folder); gInventory.accountForUpdate(update); mItem->setParent(mNewParentId); mItem->updateParentOnServer(FALSE); gInventory.updateItem(mItem); gInventory.notifyObservers(); }