887 lines
26 KiB
C++
887 lines
26 KiB
C++
/**
|
|
* @file llpanellandmarks.cpp
|
|
* @brief Landmarks tab for Side Bar "Places" panel
|
|
*
|
|
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
|
*
|
|
* Copyright (c) 2001-2009, Linden Research, Inc.
|
|
*
|
|
* Second Life Viewer Source Code
|
|
* The source code in this file ("Source Code") is provided by Linden Lab
|
|
* to you under the terms of the GNU General Public License, version 2.0
|
|
* ("GPL"), unless you have obtained a separate licensing agreement
|
|
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
|
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
|
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
|
*
|
|
* There are special exceptions to the terms and conditions of the GPL as
|
|
* it is applied to this Source Code. View the full text of the exception
|
|
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
|
* online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
|
*
|
|
* By copying, modifying or distributing this software, you acknowledge
|
|
* that you have read and understood your obligations described above,
|
|
* and agree to abide by those obligations.
|
|
*
|
|
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
|
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
|
* COMPLETENESS OR PERFORMANCE.
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "llviewerprecompiledheaders.h"
|
|
|
|
#include "llpanellandmarks.h"
|
|
|
|
#include "llbutton.h"
|
|
#include "llfloaterreg.h"
|
|
#include "llsdutil.h"
|
|
|
|
#include "llaccordionctrltab.h"
|
|
#include "llagent.h"
|
|
#include "llagentpicksinfo.h"
|
|
#include "llagentui.h"
|
|
#include "lldndbutton.h"
|
|
#include "llfloaterworldmap.h"
|
|
#include "llfolderviewitem.h"
|
|
#include "llinventorysubtreepanel.h"
|
|
#include "lllandmarkactions.h"
|
|
#include "llplacesinventorybridge.h"
|
|
#include "llsidetray.h"
|
|
#include "llviewermenu.h"
|
|
#include "llviewerregion.h"
|
|
|
|
// Not yet implemented; need to remove buildPanel() from constructor when we switch
|
|
//static LLRegisterPanelClassWrapper<LLLandmarksPanel> t_landmarks("panel_landmarks");
|
|
|
|
static const std::string OPTIONS_BUTTON_NAME = "options_gear_btn";
|
|
static const std::string ADD_LANDMARK_BUTTON_NAME = "add_landmark_btn";
|
|
static const std::string ADD_FOLDER_BUTTON_NAME = "add_folder_btn";
|
|
static const std::string TRASH_BUTTON_NAME = "trash_btn";
|
|
|
|
|
|
// helper functions
|
|
static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string);
|
|
|
|
|
|
LLLandmarksPanel::LLLandmarksPanel()
|
|
: LLPanelPlacesTab()
|
|
, mFavoritesInventoryPanel(NULL)
|
|
, mLandmarksInventoryPanel(NULL)
|
|
, mMyInventoryPanel(NULL)
|
|
, mLibraryInventoryPanel(NULL)
|
|
, mCurrentSelectedList(NULL)
|
|
, mListCommands(NULL)
|
|
, mGearFolderMenu(NULL)
|
|
, mGearLandmarkMenu(NULL)
|
|
{
|
|
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_landmarks.xml");
|
|
}
|
|
|
|
LLLandmarksPanel::~LLLandmarksPanel()
|
|
{
|
|
}
|
|
|
|
BOOL LLLandmarksPanel::postBuild()
|
|
{
|
|
if (!gInventory.isInventoryUsable())
|
|
return FALSE;
|
|
|
|
// mast be called before any other initXXX methods to init Gear menu
|
|
initListCommandsHandlers();
|
|
|
|
U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER);
|
|
mSortByDate = sort_order & LLInventoryFilter::SO_DATE;
|
|
initFavoritesInventroyPanel();
|
|
initLandmarksInventroyPanel();
|
|
initMyInventroyPanel();
|
|
initLibraryInventroyPanel();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// virtual
|
|
void LLLandmarksPanel::onSearchEdit(const std::string& string)
|
|
{
|
|
filter_list(mFavoritesInventoryPanel, string);
|
|
filter_list(mLandmarksInventoryPanel, string);
|
|
filter_list(mMyInventoryPanel, string);
|
|
filter_list(mLibraryInventoryPanel, string);
|
|
}
|
|
|
|
// virtual
|
|
void LLLandmarksPanel::onShowOnMap()
|
|
{
|
|
if (NULL == mCurrentSelectedList)
|
|
{
|
|
llwarns << "There are no selected list. No actions are performed." << llendl;
|
|
return;
|
|
}
|
|
LLLandmark* landmark = getCurSelectedLandmark();
|
|
if (!landmark)
|
|
return;
|
|
|
|
LLVector3d landmark_global_pos;
|
|
if (!landmark->getGlobalPos(landmark_global_pos))
|
|
return;
|
|
|
|
LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
|
|
if (!landmark_global_pos.isExactlyZero() && worldmap_instance)
|
|
{
|
|
worldmap_instance->trackLocation(landmark_global_pos);
|
|
LLFloaterReg::showInstance("world_map", "center");
|
|
}
|
|
}
|
|
|
|
// virtual
|
|
void LLLandmarksPanel::onTeleport()
|
|
{
|
|
LLFolderViewItem* current_item = getCurSelectedItem();
|
|
if (!current_item)
|
|
{
|
|
llwarns << "There are no selected list. No actions are performed." << llendl;
|
|
return;
|
|
}
|
|
|
|
LLFolderViewEventListener* listenerp = current_item->getListener();
|
|
if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
|
|
{
|
|
listenerp->openItem();
|
|
}
|
|
}
|
|
|
|
// virtual
|
|
void LLLandmarksPanel::updateVerbs()
|
|
{
|
|
if (!isTabVisible())
|
|
return;
|
|
|
|
BOOL enabled = isLandmarkSelected();
|
|
mTeleportBtn->setEnabled(enabled);
|
|
mShowOnMapBtn->setEnabled(enabled);
|
|
|
|
// TODO: mantipov: Uncomment when mShareBtn is supported
|
|
// Share button should be enabled when neither a folder nor a landmark is selected
|
|
//mShareBtn->setEnabled(NULL != current_item);
|
|
|
|
updateListCommands();
|
|
}
|
|
|
|
void LLLandmarksPanel::onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
|
|
{
|
|
if (user_action && (items.size() > 0))
|
|
{
|
|
deselectOtherThan(inventory_list);
|
|
mCurrentSelectedList = inventory_list;
|
|
}
|
|
|
|
LLFolderViewItem* current_item = inventory_list->getRootFolder()->getCurSelectedItem();
|
|
if (!current_item)
|
|
return;
|
|
|
|
updateVerbs();
|
|
}
|
|
|
|
void LLLandmarksPanel::onSelectorButtonClicked()
|
|
{
|
|
// TODO: mantipov: update getting of selected item
|
|
// TODO: bind to "i" button
|
|
LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem();
|
|
|
|
LLFolderViewEventListener* listenerp = cur_item->getListener();
|
|
if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
|
|
{
|
|
LLSD key;
|
|
key["type"] = "landmark";
|
|
key["id"] = listenerp->getUUID();
|
|
|
|
LLSideTray::getInstance()->showPanel("panel_places", key);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// PROTECTED METHODS
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
bool LLLandmarksPanel::isLandmarkSelected() const
|
|
{
|
|
LLFolderViewItem* current_item = getCurSelectedItem();
|
|
if(current_item && current_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool LLLandmarksPanel::isReceivedFolderSelected() const
|
|
{
|
|
// Received Folder can be only in Landmarks accordion
|
|
if (mCurrentSelectedList != mLandmarksInventoryPanel) return false;
|
|
|
|
// *TODO: it should be filled with logic when EXT-976 is done.
|
|
|
|
llwarns << "Not implemented yet until EXT-976 is done." << llendl;
|
|
|
|
return false;
|
|
}
|
|
LLLandmark* LLLandmarksPanel::getCurSelectedLandmark() const
|
|
{
|
|
|
|
LLFolderViewItem* cur_item = getCurSelectedItem();
|
|
if(cur_item && cur_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
|
|
{
|
|
return LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID());
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem () const
|
|
{
|
|
return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL;
|
|
}
|
|
|
|
void LLLandmarksPanel::updateSortOrder(LLInventoryPanel* panel, bool byDate)
|
|
{
|
|
if(!panel) return;
|
|
|
|
U32 order = panel->getSortOrder();
|
|
if (byDate)
|
|
{
|
|
panel->setSortOrder( order | LLInventoryFilter::SO_DATE );
|
|
}
|
|
else
|
|
{
|
|
panel->setSortOrder( order & ~LLInventoryFilter::SO_DATE );
|
|
}
|
|
}
|
|
|
|
// virtual
|
|
void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)
|
|
{
|
|
//this function will be called after user will try to create a pick for selected landmark.
|
|
// We have to make request to sever to get parcel_id and snaption_id.
|
|
if(isLandmarkSelected())
|
|
{
|
|
LLLandmark* landmark = getCurSelectedLandmark();
|
|
LLFolderViewItem* cur_item = getCurSelectedItem();
|
|
LLUUID id = cur_item->getListener()->getUUID();
|
|
LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id);
|
|
if(landmark)
|
|
{
|
|
LLPanelPickEdit* panel_pick = LLPanelPickEdit::create();
|
|
LLVector3d landmark_global_pos;
|
|
landmark->getGlobalPos(landmark_global_pos);
|
|
|
|
// let's toggle pick panel into panel places
|
|
LLPanel* panel_places = LLSideTray::getInstance()->getChild<LLPanel>("panel_places");//-> sidebar_places
|
|
panel_places->addChild(panel_pick);
|
|
LLRect paren_rect(panel_places->getRect());
|
|
panel_pick->reshape(paren_rect.getWidth(),paren_rect.getHeight(), TRUE);
|
|
panel_pick->setRect(paren_rect);
|
|
panel_pick->onOpen(LLSD());
|
|
|
|
LLPickData data;
|
|
data.pos_global = landmark_global_pos;
|
|
data.name = cur_item->getName();
|
|
data.desc = inv_item->getDescription();
|
|
data.snapshot_id = parcel_data.snapshot_id;
|
|
data.parcel_id = parcel_data.parcel_id;
|
|
panel_pick->setPickData(&data);
|
|
|
|
LLSD params;
|
|
params["parcel_id"] =parcel_data.parcel_id;
|
|
/* set exit callback to get back onto panel places
|
|
in callback we will make cleaning up( delete pick_panel instance,
|
|
remove landmark panel from observer list
|
|
*/
|
|
panel_pick->setExitCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
|
|
panel_pick, panel_places,params));
|
|
panel_pick->setSaveCallback(boost::bind(&LLLandmarksPanel::onPickPanelExit,this,
|
|
panel_pick, panel_places,params));
|
|
}
|
|
}
|
|
}
|
|
|
|
// virtual
|
|
void LLLandmarksPanel::setParcelID(const LLUUID& parcel_id)
|
|
{
|
|
if (!parcel_id.isNull())
|
|
{
|
|
LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
|
|
LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
|
|
}
|
|
}
|
|
|
|
// virtual
|
|
void LLLandmarksPanel::setErrorStatus(U32 status, const std::string& reason)
|
|
{
|
|
llerrs<< "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// PRIVATE METHODS
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void LLLandmarksPanel::initFavoritesInventroyPanel()
|
|
{
|
|
mFavoritesInventoryPanel = getChild<LLInventorySubTreePanel>("favorites_list");
|
|
|
|
initLandmarksPanel(mFavoritesInventoryPanel);
|
|
|
|
initAccordion("tab_favorites", mFavoritesInventoryPanel);
|
|
}
|
|
|
|
void LLLandmarksPanel::initLandmarksInventroyPanel()
|
|
{
|
|
mLandmarksInventoryPanel = getChild<LLInventorySubTreePanel>("landmarks_list");
|
|
|
|
initLandmarksPanel(mLandmarksInventoryPanel);
|
|
|
|
mLandmarksInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS);
|
|
|
|
// subscribe to have auto-rename functionality while creating New Folder
|
|
mLandmarksInventoryPanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mLandmarksInventoryPanel, _1, _2));
|
|
|
|
initAccordion("tab_landmarks", mLandmarksInventoryPanel);
|
|
}
|
|
|
|
void LLLandmarksPanel::initMyInventroyPanel()
|
|
{
|
|
mMyInventoryPanel= getChild<LLInventorySubTreePanel>("my_inventory_list");
|
|
|
|
initLandmarksPanel(mMyInventoryPanel);
|
|
|
|
initAccordion("tab_inventory", mMyInventoryPanel);
|
|
}
|
|
|
|
void LLLandmarksPanel::initLibraryInventroyPanel()
|
|
{
|
|
mLibraryInventoryPanel = getChild<LLInventorySubTreePanel>("library_list");
|
|
|
|
initLandmarksPanel(mLibraryInventoryPanel);
|
|
|
|
initAccordion("tab_library", mLibraryInventoryPanel);
|
|
}
|
|
|
|
void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_list)
|
|
{
|
|
inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK);
|
|
inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2));
|
|
|
|
inventory_list->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
|
|
updateSortOrder(inventory_list, mSortByDate);
|
|
|
|
LLPlacesFolderView* root_folder = dynamic_cast<LLPlacesFolderView*>(inventory_list->getRootFolder());
|
|
if (root_folder)
|
|
{
|
|
root_folder->setupMenuHandle(LLInventoryType::IT_CATEGORY, mGearFolderMenu->getHandle());
|
|
root_folder->setupMenuHandle(LLInventoryType::IT_LANDMARK, mGearLandmarkMenu->getHandle());
|
|
}
|
|
|
|
// save initial folder state to avoid incorrect work while switching between Landmarks & Teleport History tabs
|
|
// See EXT-1609.
|
|
inventory_list->saveFolderState();
|
|
}
|
|
|
|
void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list)
|
|
{
|
|
LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>(accordion_tab_name);
|
|
accordion_tab->setDropDownStateChangedCallback(
|
|
boost::bind(&LLLandmarksPanel::onAccordionExpandedCollapsed, this, _2, inventory_list));
|
|
}
|
|
|
|
void LLLandmarksPanel::onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list)
|
|
{
|
|
bool expanded = param.asBoolean();
|
|
|
|
if(!expanded && (mCurrentSelectedList == inventory_list))
|
|
{
|
|
inventory_list->getRootFolder()->clearSelection();
|
|
|
|
mCurrentSelectedList = NULL;
|
|
updateVerbs();
|
|
}
|
|
}
|
|
|
|
void LLLandmarksPanel::deselectOtherThan(const LLInventorySubTreePanel* inventory_list)
|
|
{
|
|
if (inventory_list != mFavoritesInventoryPanel)
|
|
{
|
|
mFavoritesInventoryPanel->getRootFolder()->clearSelection();
|
|
}
|
|
|
|
if (inventory_list != mLandmarksInventoryPanel)
|
|
{
|
|
mLandmarksInventoryPanel->getRootFolder()->clearSelection();
|
|
}
|
|
if (inventory_list != mMyInventoryPanel)
|
|
{
|
|
mMyInventoryPanel->getRootFolder()->clearSelection();
|
|
}
|
|
if (inventory_list != mLibraryInventoryPanel)
|
|
{
|
|
mLibraryInventoryPanel->getRootFolder()->clearSelection();
|
|
}
|
|
}
|
|
|
|
// List Commands Handlers
|
|
void LLLandmarksPanel::initListCommandsHandlers()
|
|
{
|
|
mListCommands = getChild<LLPanel>("bottom_panel");
|
|
|
|
mListCommands->childSetAction(OPTIONS_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onActionsButtonClick, this));
|
|
mListCommands->childSetAction(ADD_LANDMARK_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddLandmarkButtonClick, this));
|
|
mListCommands->childSetAction(ADD_FOLDER_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onAddFolderButtonClick, this));
|
|
mListCommands->childSetAction(TRASH_BUTTON_NAME, boost::bind(&LLLandmarksPanel::onTrashButtonClick, this));
|
|
|
|
|
|
LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>(TRASH_BUTTON_NAME);
|
|
trash_btn->setDragAndDropHandler(boost::bind(&LLLandmarksPanel::handleDragAndDropToTrash, this
|
|
, _4 // BOOL drop
|
|
, _5 // EDragAndDropType cargo_type
|
|
, _7 // EAcceptance* accept
|
|
));
|
|
|
|
mCommitCallbackRegistrar.add("Places.LandmarksGear.Add.Action", boost::bind(&LLLandmarksPanel::onAddAction, this, _2));
|
|
mCommitCallbackRegistrar.add("Places.LandmarksGear.CopyPaste.Action", boost::bind(&LLLandmarksPanel::onClipboardAction, this, _2));
|
|
mCommitCallbackRegistrar.add("Places.LandmarksGear.Custom.Action", boost::bind(&LLLandmarksPanel::onCustomAction, this, _2));
|
|
mCommitCallbackRegistrar.add("Places.LandmarksGear.Folding.Action", boost::bind(&LLLandmarksPanel::onFoldingAction, this, _2));
|
|
mEnableCallbackRegistrar.add("Places.LandmarksGear.Check", boost::bind(&LLLandmarksPanel::isActionChecked, this, _2));
|
|
mEnableCallbackRegistrar.add("Places.LandmarksGear.Enable", boost::bind(&LLLandmarksPanel::isActionEnabled, this, _2));
|
|
mGearLandmarkMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_landmark.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
|
|
mGearFolderMenu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_places_gear_folder.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
|
|
}
|
|
|
|
|
|
void LLLandmarksPanel::updateListCommands()
|
|
{
|
|
bool add_folder_enabled = isActionEnabled("category");
|
|
bool trash_enabled = isActionEnabled("delete");
|
|
|
|
// keep Options & Add Landmark buttons always enabled
|
|
mListCommands->childSetEnabled(ADD_FOLDER_BUTTON_NAME, add_folder_enabled);
|
|
mListCommands->childSetEnabled(TRASH_BUTTON_NAME, trash_enabled);
|
|
}
|
|
|
|
void LLLandmarksPanel::onActionsButtonClick()
|
|
{
|
|
LLFolderViewItem* cur_item = NULL;
|
|
if(mCurrentSelectedList)
|
|
cur_item = mCurrentSelectedList->getRootFolder()->getCurSelectedItem();
|
|
|
|
if(!cur_item)
|
|
return;
|
|
|
|
LLFolderViewEventListener* listenerp = cur_item->getListener();
|
|
|
|
LLMenuGL* menu =NULL;
|
|
if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
|
|
{
|
|
menu = mGearLandmarkMenu;
|
|
}
|
|
else if (listenerp->getInventoryType() == LLInventoryType::IT_CATEGORY)
|
|
{
|
|
mGearFolderMenu->getChild<LLMenuItemCallGL>("expand")->setVisible(!cur_item->isOpen());
|
|
mGearFolderMenu->getChild<LLMenuItemCallGL>("collapse")->setVisible(cur_item->isOpen());
|
|
menu = mGearFolderMenu;
|
|
}
|
|
if(menu)
|
|
{
|
|
menu->buildDrawLabels();
|
|
menu->updateParent(LLMenuGL::sMenuContainer);
|
|
LLView* actions_btn = getChild<LLView>(OPTIONS_BUTTON_NAME);
|
|
S32 menu_x, menu_y;
|
|
actions_btn->localPointToOtherView(0,actions_btn->getRect().getHeight(),&menu_x,&menu_y, this);
|
|
menu_y += menu->getRect().getHeight();
|
|
LLMenuGL::showPopup(this, menu, menu_x,menu_y);
|
|
}
|
|
}
|
|
|
|
void LLLandmarksPanel::onAddLandmarkButtonClick() const
|
|
{
|
|
if(LLLandmarkActions::landmarkAlreadyExists())
|
|
{
|
|
std::string location;
|
|
LLAgentUI::buildLocationString(location, LLAgentUI::LOCATION_FORMAT_FULL);
|
|
llwarns<<" Landmark already exists at location: "<< location<<llendl;
|
|
return;
|
|
}
|
|
LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark"));
|
|
}
|
|
|
|
void LLLandmarksPanel::onAddFolderButtonClick() const
|
|
{
|
|
LLFolderViewItem* item = getCurSelectedItem();
|
|
if(item && mCurrentSelectedList == mLandmarksInventoryPanel)
|
|
{
|
|
LLFolderViewEventListener* folder_bridge = NULL;
|
|
if(item-> getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
|
|
{
|
|
// for a landmark get parent folder bridge
|
|
folder_bridge = item->getParentFolder()->getListener();
|
|
}
|
|
else if (item-> getListener()->getInventoryType() == LLInventoryType::IT_CATEGORY)
|
|
{
|
|
// for a folder get its own bridge
|
|
folder_bridge = item->getListener();
|
|
}
|
|
|
|
menu_create_inventory_item(mCurrentSelectedList->getRootFolder()
|
|
, dynamic_cast<LLFolderBridge*>(folder_bridge)
|
|
, LLSD("category")
|
|
, gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK)
|
|
);
|
|
}
|
|
}
|
|
|
|
void LLLandmarksPanel::onTrashButtonClick() const
|
|
{
|
|
onClipboardAction("delete");
|
|
}
|
|
|
|
void LLLandmarksPanel::onAddAction(const LLSD& userdata) const
|
|
{
|
|
std::string command_name = userdata.asString();
|
|
if("add_landmark" == command_name)
|
|
{
|
|
onAddLandmarkButtonClick();
|
|
}
|
|
else if ("category" == command_name)
|
|
{
|
|
onAddFolderButtonClick();
|
|
}
|
|
}
|
|
|
|
void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const
|
|
{
|
|
if(!mCurrentSelectedList)
|
|
return;
|
|
std::string command_name = userdata.asString();
|
|
if("copy_slurl" == command_name)
|
|
{
|
|
LLFolderViewItem* cur_item = getCurSelectedItem();
|
|
if(cur_item)
|
|
LLLandmarkActions::copySLURLtoClipboard(cur_item->getListener()->getUUID());
|
|
}
|
|
else if ( "paste" == command_name)
|
|
{
|
|
mCurrentSelectedList->getRootFolder()->paste();
|
|
}
|
|
else if ( "cut" == command_name)
|
|
{
|
|
mCurrentSelectedList->getRootFolder()->cut();
|
|
}
|
|
else
|
|
{
|
|
mCurrentSelectedList->getRootFolder()->doToSelected(mCurrentSelectedList->getModel(),command_name);
|
|
}
|
|
}
|
|
|
|
void LLLandmarksPanel::onFoldingAction(const LLSD& userdata)
|
|
{
|
|
if(!mCurrentSelectedList) return;
|
|
|
|
LLFolderView* root_folder = mCurrentSelectedList->getRootFolder();
|
|
std::string command_name = userdata.asString();
|
|
|
|
if ("expand_all" == command_name)
|
|
{
|
|
root_folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN);
|
|
root_folder->arrangeAll();
|
|
}
|
|
else if ("collapse_all" == command_name)
|
|
{
|
|
root_folder->closeAllFolders();
|
|
}
|
|
else if ( "sort_by_date" == command_name)
|
|
{
|
|
mSortByDate = !mSortByDate;
|
|
updateSortOrder(mLandmarksInventoryPanel, mSortByDate);
|
|
updateSortOrder(mMyInventoryPanel, mSortByDate);
|
|
updateSortOrder(mLibraryInventoryPanel, mSortByDate);
|
|
}
|
|
else
|
|
{
|
|
root_folder->doToSelected(&gInventory, userdata);
|
|
}
|
|
}
|
|
|
|
bool LLLandmarksPanel::isActionChecked(const LLSD& userdata) const
|
|
{
|
|
const std::string command_name = userdata.asString();
|
|
|
|
if ( "sort_by_date" == command_name)
|
|
{
|
|
return mSortByDate;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const
|
|
{
|
|
std::string command_name = userdata.asString();
|
|
|
|
|
|
LLPlacesFolderView* rootFolderView = mCurrentSelectedList ?
|
|
static_cast<LLPlacesFolderView*>(mCurrentSelectedList->getRootFolder()) : NULL;
|
|
|
|
if (NULL == rootFolderView) return false;
|
|
|
|
// disable some commands for multi-selection. EXT-1757
|
|
if (rootFolderView->getSelectedCount() > 1)
|
|
{
|
|
if ( "teleport" == command_name
|
|
|| "more_info" == command_name
|
|
|| "rename" == command_name
|
|
|| "show_on_map" == command_name
|
|
|| "copy_slurl" == command_name
|
|
)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
}
|
|
|
|
// disable some commands for Favorites accordion. EXT-1758
|
|
if (mCurrentSelectedList == mFavoritesInventoryPanel)
|
|
{
|
|
if ( "expand_all" == command_name
|
|
|| "collapse_all" == command_name
|
|
|| "sort_by_date" == command_name
|
|
)
|
|
return false;
|
|
}
|
|
|
|
|
|
if("category" == command_name)
|
|
{
|
|
// we can add folder only in Landmarks Accordion
|
|
if (mCurrentSelectedList == mLandmarksInventoryPanel)
|
|
{
|
|
// ... but except Received folder
|
|
return !isReceivedFolderSelected();
|
|
}
|
|
else return false;
|
|
}
|
|
else if("paste" == command_name || "rename" == command_name || "cut" == command_name || "delete" == command_name)
|
|
{
|
|
return canSelectedBeModified(command_name);
|
|
}
|
|
else if ( "sort_by_date" == command_name)
|
|
{
|
|
return mSortByDate;
|
|
}
|
|
else if("create_pick" == command_name)
|
|
{
|
|
return !LLAgentPicksInfo::getInstance()->isPickLimitReached();
|
|
}
|
|
else
|
|
{
|
|
llwarns << "Unprocessed command has come: " << command_name << llendl;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void LLLandmarksPanel::onCustomAction(const LLSD& userdata)
|
|
{
|
|
LLFolderViewItem* cur_item = getCurSelectedItem();
|
|
if(!cur_item)
|
|
return ;
|
|
std::string command_name = userdata.asString();
|
|
if("more_info" == command_name)
|
|
{
|
|
cur_item->getListener()->performAction(mCurrentSelectedList->getRootFolder(),mCurrentSelectedList->getModel(),"about");
|
|
}
|
|
else if ("teleport" == command_name)
|
|
{
|
|
onTeleport();
|
|
}
|
|
else if ("show_on_map" == command_name)
|
|
{
|
|
onShowOnMap();
|
|
}
|
|
else if ("create_pick" == command_name)
|
|
{
|
|
LLLandmark* landmark = getCurSelectedLandmark();
|
|
if(!landmark) return;
|
|
|
|
LLViewerRegion* region = gAgent.getRegion();
|
|
if (!region) return;
|
|
|
|
LLGlobalVec pos_global;
|
|
LLUUID region_id;
|
|
landmark->getGlobalPos(pos_global);
|
|
landmark->getRegionID(region_id);
|
|
LLVector3 region_pos((F32)fmod(pos_global.mdV[VX], (F64)REGION_WIDTH_METERS),
|
|
(F32)fmod(pos_global.mdV[VY], (F64)REGION_WIDTH_METERS),
|
|
(F32)pos_global.mdV[VZ]);
|
|
|
|
LLSD body;
|
|
std::string url = region->getCapability("RemoteParcelRequest");
|
|
if (!url.empty())
|
|
{
|
|
body["location"] = ll_sd_from_vector3(region_pos);
|
|
if (!region_id.isNull())
|
|
{
|
|
body["region_id"] = region_id;
|
|
}
|
|
if (!pos_global.isExactlyZero())
|
|
{
|
|
U64 region_handle = to_region_handle(pos_global);
|
|
body["region_handle"] = ll_sd_from_U64(region_handle);
|
|
}
|
|
LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle()));
|
|
}
|
|
else
|
|
{
|
|
llwarns << "Can't create pick for landmark for region" << region_id
|
|
<< ". Region: " << region->getName()
|
|
<< " does not support RemoteParcelRequest" << llendl;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
Processes such actions: cut/rename/delete/paste actions
|
|
|
|
Rules:
|
|
1. We can't perform any action in Library
|
|
2. For Landmarks we can:
|
|
- cut/rename/delete in any other accordions
|
|
- paste - only in Favorites, Landmarks accordions
|
|
3. For Folders we can: perform any action in Landmarks accordion, except Received folder
|
|
4. We can not paste folders from Clipboard (processed by LLFolderView::canPaste())
|
|
5. Check LLFolderView/Inventory Bridges rules
|
|
*/
|
|
bool LLLandmarksPanel::canSelectedBeModified(const std::string& command_name) const
|
|
{
|
|
// validate own rules first
|
|
|
|
// nothing can be modified in Library
|
|
if (mLibraryInventoryPanel == mCurrentSelectedList) return false;
|
|
|
|
bool can_be_modified = false;
|
|
|
|
// landmarks can be modified in any other accordion...
|
|
if (isLandmarkSelected())
|
|
{
|
|
can_be_modified = true;
|
|
|
|
// we can modify landmarks anywhere except paste to My Inventory
|
|
if ("paste" == command_name)
|
|
{
|
|
can_be_modified = (mCurrentSelectedList != mMyInventoryPanel);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ...folders only in the Landmarks accordion...
|
|
can_be_modified = mLandmarksInventoryPanel == mCurrentSelectedList;
|
|
|
|
// ...except "Received" folder
|
|
can_be_modified &= !isReceivedFolderSelected();
|
|
}
|
|
|
|
// then ask LLFolderView permissions
|
|
if (can_be_modified)
|
|
{
|
|
if ("cut" == command_name)
|
|
{
|
|
can_be_modified = mCurrentSelectedList->getRootFolder()->canCut();
|
|
}
|
|
else if ("rename" == command_name)
|
|
{
|
|
can_be_modified = getCurSelectedItem()->getListener()->isItemRenameable();
|
|
}
|
|
else if ("delete" == command_name)
|
|
{
|
|
can_be_modified = getCurSelectedItem()->getListener()->isItemRemovable();
|
|
}
|
|
else if("paste" == command_name)
|
|
{
|
|
return mCurrentSelectedList->getRootFolder()->canPaste();
|
|
}
|
|
else
|
|
{
|
|
llwarns << "Unprocessed command has come: " << command_name << llendl;
|
|
}
|
|
}
|
|
|
|
return can_be_modified;
|
|
}
|
|
|
|
void LLLandmarksPanel::onPickPanelExit( LLPanelPickEdit* pick_panel, LLView* owner, const LLSD& params)
|
|
{
|
|
pick_panel->setVisible(FALSE);
|
|
owner->removeChild(pick_panel);
|
|
//we need remove observer to avoid processParcelInfo in the future.
|
|
LLRemoteParcelInfoProcessor::getInstance()->removeObserver(params["parcel_id"].asUUID(), this);
|
|
|
|
delete pick_panel;
|
|
pick_panel = NULL;
|
|
}
|
|
|
|
bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept)
|
|
{
|
|
*accept = ACCEPT_NO;
|
|
|
|
switch (cargo_type)
|
|
{
|
|
|
|
case DAD_LANDMARK:
|
|
case DAD_CATEGORY:
|
|
{
|
|
bool is_enabled = isActionEnabled("delete");
|
|
|
|
if (is_enabled) *accept = ACCEPT_YES_MULTI;
|
|
|
|
if (is_enabled && drop)
|
|
{
|
|
onClipboardAction("delete");
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// HELPER FUNCTIONS
|
|
//////////////////////////////////////////////////////////////////////////
|
|
static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string)
|
|
{
|
|
if (string == "")
|
|
{
|
|
inventory_list->setFilterSubString(LLStringUtil::null);
|
|
|
|
// re-open folders that were initially open
|
|
inventory_list->restoreFolderState();
|
|
}
|
|
|
|
gInventory.startBackgroundFetch();
|
|
|
|
if (inventory_list->getFilterSubString().empty() && string.empty())
|
|
{
|
|
// current filter and new filter empty, do nothing
|
|
return;
|
|
}
|
|
|
|
// save current folder open state if no filter currently applied
|
|
if (inventory_list->getRootFolder()->getFilterSubString().empty())
|
|
{
|
|
inventory_list->saveFolderState();
|
|
}
|
|
|
|
// set new filter string
|
|
inventory_list->setFilterSubString(string);
|
|
}
|
|
// EOF
|