Favorites on the login screen

Adds some guts for the favorites bar, I'll get to that eventually
This commit is contained in:
Lirusaito
2019-02-05 04:57:49 -05:00
parent cb16e4edf0
commit a62d433262
16 changed files with 2845 additions and 45 deletions

View File

@@ -174,6 +174,7 @@ set(viewer_SOURCE_FILES
llexternaleditor.cpp
llface.cpp
llfasttimerview.cpp
llfavoritesbar.cpp
llfeaturemanager.cpp
llfirstuse.cpp
llflexibleobject.cpp
@@ -320,6 +321,7 @@ set(viewer_SOURCE_FILES
llinventoryobserver.cpp
llinventorypanel.cpp
lljoystickbutton.cpp
lllandmarkactions.cpp
lllandmarklist.cpp
lllogchat.cpp
llloginhandler.cpp
@@ -707,6 +709,7 @@ set(viewer_HEADER_FILES
llexternaleditor.h
llface.h
llfasttimerview.h
llfavoritesbar.h
llfeaturemanager.h
llfirstuse.h
llflexibleobject.h
@@ -852,6 +855,7 @@ set(viewer_HEADER_FILES
llinventoryobserver.h
llinventorypanel.h
lljoystickbutton.h
lllandmarkactions.h
lllandmarklist.h
lllightconstants.h
lllogchat.h

View File

@@ -770,6 +770,17 @@
<key>Value</key>
<string>-%Y-%m</string>
</map>
<key>ShowFavoritesOnLogin</key>
<map>
<key>Comment</key>
<string>Determines whether favorites of last logged in user will be saved on exit from viewer and shown on login screen</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>KeywordsChangeColor</key>
<map>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,276 @@
/**
* @file llfavoritesbar.h
* @brief LLFavoritesBarCtrl base class
*
* $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$
*/
#ifndef LL_LLFAVORITESBARCTRL_H
#define LL_LLFAVORITESBARCTRL_H
#include "llbutton.h"
#include "lluictrl.h"
#include "lltextbox.h"
#include "llinventoryobserver.h"
#include "llinventorymodel.h"
#include "llviewerinventory.h"
#include "llui.h" //"llinitdestroyclass.h"
#if 0
class LLMenuItemCallGL;
class LLToggleableMenu;
class LLFavoritesBarCtrl : public LLUICtrl, public LLInventoryObserver
{
public:
struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
{
Optional<LLUIImage*> image_drag_indication;
Optional<LLTextBox::Params> more_button;
Optional<LLTextBox::Params> label;
Params();
};
protected:
LLFavoritesBarCtrl(const Params&);
friend class LLUICtrlFactory;
public:
virtual ~LLFavoritesBarCtrl();
/*virtual*/ BOOL postBuild() override;
/*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg) override;
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask) override;
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask) override;
// LLInventoryObserver observer trigger
void changed(U32 mask) override;
void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE) override;
void draw() override;
void showDragMarker(BOOL show) { mShowDragMarker = show; }
void setLandingTab(LLUICtrl* tab) { mLandingTab = tab; }
protected:
void updateButtons();
LLButton* createButton(const LLPointer<LLViewerInventoryItem> item, const LLButton::Params& button_params, S32 x_offset );
const LLButton::Params& getButtonParams();
BOOL collectFavoriteItems(LLInventoryModel::item_array_t &items);
void onButtonClick(LLUUID id);
void onButtonRightClick(LLUUID id,LLView* button,S32 x,S32 y,MASK mask);
void onButtonMouseDown(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask);
void onOverflowMenuItemMouseDown(LLUUID id, LLUICtrl* item, S32 x, S32 y, MASK mask);
void onButtonMouseUp(LLUUID id, LLUICtrl* button, S32 x, S32 y, MASK mask);
void onEndDrag();
bool enableSelected(const LLSD& userdata);
void doToSelected(const LLSD& userdata);
BOOL isClipboardPasteable() const;
void pasteFromClipboard() const;
void showDropDownMenu();
LLHandle<LLView> mOverflowMenuHandle;
LLHandle<LLView> mContextMenuHandle;
LLUUID mFavoriteFolderId;
const LLFontGL *mFont;
S32 mFirstDropDownItem;
S32 mDropDownItemsCount;
bool mUpdateDropDownItems;
bool mRestoreOverflowMenu;
LLUUID mSelectedItemID;
LLUIImage* mImageDragIndication;
private:
/*
* Helper function to make code more readable. It handles all drag and drop
* operations of the existing favorites items on the favorites bar.
*/
void handleExistingFavoriteDragAndDrop(S32 x, S32 y);
/*
* Helper function to make code more readable. It handles all drag and drop
* operations of the new landmark to the favorites bar.
*/
void handleNewFavoriteDragAndDrop(LLInventoryItem *item, const LLUUID& favorites_id, S32 x, S32 y);
// finds a control under the specified LOCAL point
LLUICtrl* findChildByLocalCoords(S32 x, S32 y);
// checks if the current order of the favorites items must be saved
BOOL needToSaveItemsOrder(const LLInventoryModel::item_array_t& items);
/**
* inserts an item identified by insertedItemId BEFORE an item identified by beforeItemId.
* this function assumes that an item identified by insertedItemId doesn't exist in items array.
*/
void insertItem(LLInventoryModel::item_array_t& items, const LLUUID& dest_item_id, LLViewerInventoryItem* insertedItem, bool insert_before);
// finds an item by it's UUID in the items array
LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id);
void createOverflowMenu();
void updateMenuItems(LLToggleableMenu* menu);
// Fits menu item label width with favorites menu width
void fitLabelWidth(LLMenuItemCallGL* menu_item);
void addOpenLandmarksMenuItem(LLToggleableMenu* menu);
void positionAndShowMenu(LLToggleableMenu* menu);
BOOL mShowDragMarker;
LLUICtrl* mLandingTab;
LLUICtrl* mLastTab;
LLTextBox* mMoreTextBox;
LLTextBox* mBarLabel;
LLUUID mDragItemId;
BOOL mStartDrag;
LLInventoryModel::item_array_t mItems;
BOOL mTabsHighlightEnabled;
boost::signals2::connection mEndDragConnection;
};
#endif
/**
* Class to store sorting order of favorites landmarks in a local file. EXT-3985.
* It replaced previously implemented solution to store sort index in landmark's name as a "<N>@" prefix.
* Data are stored in user home directory.
*/
class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage>
, public LLDestroyClass<LLFavoritesOrderStorage>
{
friend class LLSingleton<LLFavoritesOrderStorage>;
LLFavoritesOrderStorage(); //LLSINGLETON(LLFavoritesOrderStorage);
~LLFavoritesOrderStorage() { save(); }
LOG_CLASS(LLFavoritesOrderStorage);
public:
/**
* Sets sort index for specified with LLUUID favorite landmark
*/
void setSortIndex(const LLViewerInventoryItem* inv_item, S32 sort_index);
/**
* Gets sort index for specified with LLUUID favorite landmark
*/
S32 getSortIndex(const LLUUID& inv_item_id);
void removeSortIndex(const LLUUID& inv_item_id);
void getSLURL(const LLUUID& asset_id);
// Saves current order of the passed items using inventory item sort field.
// Resets 'items' sort fields and saves them on server.
// Is used to save order for Favorites folder.
void saveItemsOrder(const LLInventoryModel::item_array_t& items);
void saveOrder();
void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id);
/**
* Implementation of LLDestroyClass. Calls cleanup() instance method.
*
* It is important this callback is called before gInventory is cleaned.
* For now it is called from LLAppViewer::cleanup() -> LLAppViewer::disconnectViewer(),
* Inventory is cleaned later from LLAppViewer::cleanup() after LLAppViewer::disconnectViewer() is called.
* @see cleanup()
*/
static void destroyClass();
const static S32 NO_INDEX;
private:
/**
* Removes sort indexes for items which are not in Favorites bar for now.
*/
void cleanup();
const static std::string SORTING_DATA_FILE_NAME;
std::string getSavedOrderFileName();
static std::string getStoredFavoritesFilename();
void load();
void save();
void saveFavoritesSLURLs();
// Remove record of current user's favorites from file on disk.
void removeFavoritesRecordOfUser();
void onLandmarkLoaded(const LLUUID& asset_id, class LLLandmark* landmark);
void storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl);
typedef std::map<LLUUID, S32> sort_index_map_t;
sort_index_map_t mSortIndexes;
typedef std::map<LLUUID, std::string> slurls_map_t;
slurls_map_t mSLURLs;
std::set<LLUUID> mMissingSLURLs;
bool mIsDirty;
struct IsNotInFavorites
{
IsNotInFavorites(const LLInventoryModel::item_array_t& items)
: mFavoriteItems(items)
{
}
/**
* Returns true if specified item is not found among inventory items
*/
bool operator()(const sort_index_map_t::value_type& id_index_pair) const
{
LLPointer<LLViewerInventoryItem> item = gInventory.getItem(id_index_pair.first);
if (item.isNull()) return true;
LLInventoryModel::item_array_t::const_iterator found_it =
std::find(mFavoriteItems.begin(), mFavoriteItems.end(), item);
return found_it == mFavoriteItems.end();
}
private:
LLInventoryModel::item_array_t mFavoriteItems;
};
};
inline
LLFavoritesOrderStorage::LLFavoritesOrderStorage() :
mIsDirty(false)
{ load(); }
#endif // LL_LLFAVORITESBARCTRL_H

View File

@@ -66,6 +66,7 @@
// Linden library includes
#include "lldbstrings.h"
#include "llfavoritesbar.h" // Singu TODO: Favorites bar.
#include "llfocusmgr.h"
#include "llfontgl.h"
#include "llgl.h"
@@ -2161,6 +2162,10 @@ void LLFolderView::doIdle()
{
return;
}
LLFavoritesOrderStorage::instance(); // Singu TODO: Favorites bar.
BOOL collectFavoriteItems();
collectFavoriteItems();
LL_RECORD_BLOCK_TIME(FTM_INVENTORY);

View File

@@ -42,6 +42,7 @@
#include "llattachmentsmgr.h"
#include "llavataractions.h"
#include "llcallingcard.h"
#include "llfavoritesbar.h" // management of favorites folder
#include "llfirstuse.h"
#include "llfloatercustomize.h"
#include "llfloateropenobject.h"
@@ -3957,7 +3958,7 @@ void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_c
}
else
{
LLPointer<LLInventoryCallback> cb = NULL;
LLPointer<LLInventoryCallback> cb = nullptr;
link_inventory_object(mUUID, LLConstPointer<LLInventoryObject>(inv_item), cb);
}
}
@@ -4135,7 +4136,6 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
// Destination folder logic
//
/* Singu TODO: Favorites
// REORDER
// (only reorder the item in Favorites folder)
if ((mUUID == inv_item->getParentUUID()) && move_is_into_favorites)
@@ -4145,7 +4145,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
LLUUID srcItemId = inv_item->getUUID();
LLUUID destItemId = itemp->getListener()->getUUID();
gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId);
LLFavoritesOrderStorage::instance().rearrangeFavoriteLandmarks(srcItemId, destItemId);
}
}

View File

@@ -3580,25 +3580,25 @@ void LLInventoryModel::saveItemsOrder(const LLInventoryModel::item_array_t& item
}
*/
// See also LLInventorySort where landmarks in the Favorites folder are sorted.
/*class LLViewerInventoryItemSort
class LLViewerInventoryItemSort
{
public:
bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b)
bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) const
{
return a->getSortField() < b->getSortField();
}
};*/
};
/**
* Sorts passed items by LLViewerInventoryItem sort field.
*
* @param[in, out] items - array of items, not sorted.
*/
/*static void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items)
{
static LLViewerInventoryItemSort sort_functor;
std::sort(items.begin(), items.end(), sort_functor);
}*/
//static void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items)
//{
// static LLViewerInventoryItemSort sort_functor;
// std::sort(items.begin(), items.end(), sort_functor);
//}
// * @param source_item_id - LLUUID of the source item to be moved into new position
// * @param target_item_id - LLUUID of the target item before which source item should be placed.

View File

@@ -418,15 +418,6 @@ public:
// Returns end() of the vector if not found.
static LLInventoryModel::item_array_t::iterator findItemIterByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id);
// Saves current order of the passed items using inventory item sort field.
// Resets 'items' sort fields and saves them on server.
// Is used to save order for Favorites folder.
//void saveItemsOrder(const LLInventoryModel::item_array_t& items);
// Rearranges Landmarks inside Favorites folder.
// Moves source landmark before target one.
void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id);
//--------------------------------------------------------------------
// Creation
//--------------------------------------------------------------------

View File

@@ -0,0 +1,421 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
/**
* @file lllandmarkactions.cpp
* @brief LLLandmarkActions class implementation
*
* $LicenseInfo:firstyear=2001&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 "lllandmarkactions.h"
#include "roles_constants.h"
#include "llinventory.h"
#include "llinventoryfunctions.h"
#include "lllandmark.h"
#include "llparcel.h"
#include "llregionhandle.h"
#include "llnotificationsutil.h"
#include "llagent.h"
#include "llagentui.h"
#include "llinventorymodel.h"
#include "lllandmarklist.h"
#include "llslurl.h"
#include "llstring.h"
#include "llviewerinventory.h"
#include "llviewerparcelmgr.h"
#include "llworldmapmessage.h"
#include "llviewerwindow.h"
#include "llwindow.h"
#include "llworldmap.h"
void copy_slurl_to_clipboard_callback(const std::string& slurl);
class LLFetchlLandmarkByPos : public LLInventoryCollectFunctor
{
private:
LLVector3d mPos;
public:
LLFetchlLandmarkByPos(const LLVector3d& pos) :
mPos(pos)
{}
bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) override
{
if (!item || item->getType() != LLAssetType::AT_LANDMARK)
return false;
LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID());
if (!landmark) // the landmark not been loaded yet
return false;
LLVector3d landmark_global_pos;
if (!landmark->getGlobalPos(landmark_global_pos))
return false;
//we have to round off each coordinates to compare positions properly
return ll_round(mPos.mdV[VX]) == ll_round(landmark_global_pos.mdV[VX])
&& ll_round(mPos.mdV[VY]) == ll_round(landmark_global_pos.mdV[VY])
&& ll_round(mPos.mdV[VZ]) == ll_round(landmark_global_pos.mdV[VZ]);
}
};
class LLFetchLandmarksByName : public LLInventoryCollectFunctor
{
private:
std::string name;
BOOL use_substring;
//this member will be contain copy of founded items to keep the result unique
std::set<std::string> check_duplicate;
public:
LLFetchLandmarksByName(std::string &landmark_name, BOOL if_use_substring)
:name(landmark_name),
use_substring(if_use_substring)
{
LLStringUtil::toLower(name);
}
public:
bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) override
{
if (!item || item->getType() != LLAssetType::AT_LANDMARK)
return false;
LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID());
if (!landmark) // the landmark not been loaded yet
return false;
bool acceptable = false;
std::string landmark_name = item->getName();
LLStringUtil::toLower(landmark_name);
if(use_substring)
{
acceptable = landmark_name.find( name ) != std::string::npos;
}
else
{
acceptable = landmark_name == name;
}
if(acceptable){
if(check_duplicate.find(landmark_name) != check_duplicate.end()){
// we have duplicated items in landmarks
acceptable = false;
}else{
check_duplicate.insert(landmark_name);
}
}
return acceptable;
}
};
// Returns true if the given inventory item is a landmark pointing to the current parcel.
// Used to find out if there is at least one landmark from current parcel.
class LLFirstAgentParcelLandmark : public LLInventoryCollectFunctor
{
private:
bool mFounded;// to avoid unnecessary check
public:
LLFirstAgentParcelLandmark(): mFounded(false){}
bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) override
{
if (mFounded || !item || item->getType() != LLAssetType::AT_LANDMARK)
return false;
LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID());
if (!landmark) // the landmark not been loaded yet
return false;
LLVector3d landmark_global_pos;
if (!landmark->getGlobalPos(landmark_global_pos))
return false;
mFounded = LLViewerParcelMgr::getInstance()->inAgentParcel(landmark_global_pos);
return mFounded;
}
};
static void fetch_landmarks(LLInventoryModel::cat_array_t& cats,
LLInventoryModel::item_array_t& items,
LLInventoryCollectFunctor& add)
{
// Look in "My Favorites"
const LLUUID favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
gInventory.collectDescendentsIf(favorites_folder_id,
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
add);
// Look in "Landmarks"
const LLUUID landmarks_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
gInventory.collectDescendentsIf(landmarks_folder_id,
cats,
items,
LLInventoryModel::EXCLUDE_TRASH,
add);
}
LLInventoryModel::item_array_t LLLandmarkActions::fetchLandmarksByName(std::string& name, BOOL use_substring)
{
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
LLFetchLandmarksByName by_name(name, use_substring);
fetch_landmarks(cats, items, by_name);
return items;
}
bool LLLandmarkActions::landmarkAlreadyExists()
{
// Determine whether there are landmarks pointing to the current global agent position.
return findLandmarkForAgentPos() != nullptr;
}
//static
bool LLLandmarkActions::hasParcelLandmark()
{
LLFirstAgentParcelLandmark get_first_agent_landmark;
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
fetch_landmarks(cats, items, get_first_agent_landmark);
return !items.empty();
}
// *TODO: This could be made more efficient by only fetching the FIRST
// landmark that meets the criteria
LLViewerInventoryItem* LLLandmarkActions::findLandmarkForGlobalPos(const LLVector3d &pos)
{
// Determine whether there are landmarks pointing to the current parcel.
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
LLFetchlLandmarkByPos is_current_pos_landmark(pos);
fetch_landmarks(cats, items, is_current_pos_landmark);
return (items.empty()) ? nullptr : items[0];
}
LLViewerInventoryItem* LLLandmarkActions::findLandmarkForAgentPos()
{
return findLandmarkForGlobalPos(gAgent.getPositionGlobal());
}
bool LLLandmarkActions::canCreateLandmarkHere()
{
LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
if(!agent_parcel)
{
LL_WARNS() << "No agent region" << LL_ENDL;
return false;
}
if (agent_parcel->getAllowLandmark()
|| LLViewerParcelMgr::isParcelOwnedByAgent(agent_parcel, GP_LAND_ALLOW_LANDMARK))
{
return true;
}
return false;
}
void LLLandmarkActions::createLandmarkHere(
const std::string& name,
const std::string& desc,
const LLUUID& folder_id)
{
if(!gAgent.getRegion())
{
LL_WARNS() << "No agent region" << LL_ENDL;
return;
}
LLParcel* agent_parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
if (!agent_parcel)
{
LL_WARNS() << "No agent parcel" << LL_ENDL;
return;
}
if (!canCreateLandmarkHere())
{
LLNotificationsUtil::add("CannotCreateLandmarkNotOwner");
return;
}
create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
folder_id, LLTransactionID::tnull,
name, desc,
LLAssetType::AT_LANDMARK,
LLInventoryType::IT_LANDMARK,
NOT_WEARABLE, PERM_ALL,
NULL);
}
void LLLandmarkActions::createLandmarkHere()
{
std::string landmark_name, landmark_desc;
LLAgentUI::buildLocationString(landmark_name, LLAgentUI::LOCATION_FORMAT_LANDMARK);
LLAgentUI::buildLocationString(landmark_desc, LLAgentUI::LOCATION_FORMAT_FULL);
const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
createLandmarkHere(landmark_name, landmark_desc, folder_id);
}
LLVector3d getRegionPosFromGlobalPos(const LLVector3d& global_pos, const LLSimInfo* siminfo)
{
LLVector3d local_pos;
local_pos[0] = fmod(global_pos[0], siminfo ? siminfo->getSizeX() : 256);
local_pos[1] = fmod(global_pos[1], siminfo ? siminfo->getSizeY() : 256);
return local_pos;
}
void LLLandmarkActions::getSLURLfromPosGlobal(const LLVector3d& global_pos, slurl_callback_t cb, bool escaped /* = true */)
{
const LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(global_pos);
if (siminfo)
{
std::string slurl = LLSLURL(siminfo->getName(), getRegionPosFromGlobalPos(global_pos, siminfo)).getSLURLString();
cb(slurl);
}
else
{
U64 new_region_handle = to_region_handle(global_pos);
LLWorldMapMessage::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseSLURL,
cb,
global_pos,
escaped,
_2);
LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, LLStringExplicit("unused"), false);
}
}
void LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(const LLVector3d& global_pos, region_name_and_coords_callback_t cb)
{
LLSimInfo* sim_infop = LLWorldMap::getInstance()->simInfoFromPosGlobal(global_pos);
if (sim_infop)
{
LLVector3 pos = sim_infop->getLocalPos(global_pos);
std::string name = sim_infop->getName() ;
cb(name, ll_round(pos.mV[VX]), ll_round(pos.mV[VY]),ll_round(pos.mV[VZ]));
}
else
{
U64 new_region_handle = to_region_handle(global_pos);
LLWorldMapMessage::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseNameAndCoords,
cb,
global_pos,
_1);
LLWorldMapMessage::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false);
}
}
void LLLandmarkActions::onRegionResponseSLURL(slurl_callback_t cb,
const LLVector3d& global_pos,
bool escaped,
const std::string& url)
{
std::string sim_name;
std::string slurl;
const LLSimInfo* siminfo = LLWorldMap::getInstance()->simInfoFromPosGlobal(global_pos);
if (siminfo)
{
slurl = LLSLURL(siminfo->getName(), getRegionPosFromGlobalPos(global_pos, siminfo)).getSLURLString();
}
else
{
slurl.clear();
}
cb(slurl);
}
void LLLandmarkActions::onRegionResponseNameAndCoords(region_name_and_coords_callback_t cb,
const LLVector3d& global_pos,
U64 region_handle)
{
LLSimInfo* sim_infop = LLWorldMap::getInstance()->simInfoFromHandle(region_handle);
if (sim_infop)
{
LLVector3 local_pos = sim_infop->getLocalPos(global_pos);
std::string name = sim_infop->getName() ;
cb(name, ll_round(local_pos.mV[VX]), ll_round(local_pos.mV[VY]), ll_round(local_pos.mV[VZ]));
}
}
bool LLLandmarkActions::getLandmarkGlobalPos(const LLUUID& landmarkInventoryItemID, LLVector3d& posGlobal)
{
LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID);
if (NULL == item)
return false;
const LLUUID& asset_id = item->getAssetUUID();
LLLandmark* landmark = gLandmarkList.getAsset(asset_id);
if (NULL == landmark)
return false;
return landmark->getGlobalPos(posGlobal);
}
LLLandmark* LLLandmarkActions::getLandmark(const LLUUID& landmarkInventoryItemID, LLLandmarkList::loaded_callback_t cb)
{
LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID);
if (NULL == item)
return NULL;
const LLUUID& asset_id = item->getAssetUUID();
LLLandmark* landmark = gLandmarkList.getAsset(asset_id, cb);
if (landmark)
{
return landmark;
}
return NULL;
}
void LLLandmarkActions::copySLURLtoClipboard(const LLUUID& landmarkInventoryItemID)
{
LLLandmark* landmark = LLLandmarkActions::getLandmark(landmarkInventoryItemID);
if(landmark)
{
LLVector3d global_pos;
landmark->getGlobalPos(global_pos);
LLLandmarkActions::getSLURLfromPosGlobal(global_pos,&copy_slurl_to_clipboard_callback,true);
}
}
void copy_slurl_to_clipboard_callback(const std::string& slurl)
{
gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(slurl));
LLSD args;
args["SLURL"] = slurl;
LLNotificationsUtil::add("CopySLURL", args);
}

View File

@@ -0,0 +1,138 @@
/**
* @file lllandmarkactions.h
* @brief LLLandmark class declaration
*
* $LicenseInfo:firstyear=2000&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$
*/
#ifndef LL_LLLANDMARKACTIONS_H
#define LL_LLLANDMARKACTIONS_H
#include "llinventorymodel.h"
#include "lllandmarklist.h"
class LLLandmark;
/**
* @brief Provides helper functions to manage landmarks
*/
class LLLandmarkActions
{
public:
typedef std::function<void(std::string& slurl)> slurl_callback_t;
typedef std::function<void(std::string& slurl, S32 x, S32 y, S32 z)> region_name_and_coords_callback_t;
/**
* @brief Fetches landmark LLViewerInventoryItems for the given landmark name.
*/
static LLInventoryModel::item_array_t fetchLandmarksByName(std::string& name, BOOL if_use_substring);
/**
* @brief Checks whether landmark exists for current agent position.
*/
static bool landmarkAlreadyExists();
/**
* @brief Checks whether landmark exists for current agent parcel.
*/
static bool hasParcelLandmark();
/**
* @brief Searches landmark for global position.
* @return Returns landmark or NULL.
*
* *TODO: dzaporozhan: There can be many landmarks for single parcel.
*/
static LLViewerInventoryItem* findLandmarkForGlobalPos(const LLVector3d &pos);
/**
* @brief Searches landmark for agent global position.
* @return Returns landmark or NULL.
*
* *TODO: dzaporozhan: There can be many landmarks for single parcel.
*/
static LLViewerInventoryItem* findLandmarkForAgentPos();
/**
* @brief Checks whether agent has rights to create landmark for current parcel.
*/
static bool canCreateLandmarkHere();
/**
* @brief Creates landmark for current parcel.
*/
static void createLandmarkHere();
/**
* @brief Creates landmark for current parcel.
*/
static void createLandmarkHere(
const std::string& name,
const std::string& desc,
const LLUUID& folder_id);
/**
* @brief Creates SLURL for given global position.
*/
static void getSLURLfromPosGlobal(const LLVector3d& global_pos, slurl_callback_t cb, bool escaped = true);
static void getRegionNameAndCoordsFromPosGlobal(const LLVector3d& global_pos, region_name_and_coords_callback_t cb);
/**
* @brief Gets landmark global position specified by inventory LLUUID.
* Found position is placed into "posGlobal" variable.
*.
* @return - true if specified item exists in Inventory and an appropriate landmark found.
* and its position is known, false otherwise.
*/
// *TODO: mantipov: profide callback for cases, when Landmark is not loaded yet.
static bool getLandmarkGlobalPos(const LLUUID& landmarkInventoryItemID, LLVector3d& posGlobal);
/**
* @brief Retrieve a landmark from gLandmarkList by inventory item's id
* If a landmark is not currently in the gLandmarkList a callback "cb" is called when it is loaded.
*
* @return pointer to loaded landmark from gLandmarkList or NULL if landmark does not exist or wasn't loaded.
*/
static LLLandmark* getLandmark(const LLUUID& landmarkInventoryItemID, LLLandmarkList::loaded_callback_t cb = nullptr);
/**
* @brief Performs standard action of copying of SLURL from landmark to user's clipboard.
* This action requires additional server request. The user will be notified by info message,
* when URL is copied .
*/
static void copySLURLtoClipboard(const LLUUID& landmarkInventoryItemID);
private:
LLLandmarkActions() = delete;
LLLandmarkActions(const LLLandmarkActions&) = delete;
static void onRegionResponseSLURL(slurl_callback_t cb,
const LLVector3d& global_pos,
bool escaped,
const std::string& url);
static void onRegionResponseNameAndCoords(region_name_and_coords_callback_t cb,
const LLVector3d& global_pos,
U64 region_handle);
};
#endif //LL_LLLANDMARKACTIONS_H

View File

@@ -1,3 +1,5 @@
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
/**
* @file lllandmarklist.cpp
* @brief Landmark asset list class
@@ -35,7 +37,6 @@
#include "llagent.h"
#include "llvfile.h"
#include "llviewerstats.h"
#include "llnotificationsutil.h"
// Globals
LLLandmarkList gLandmarkList;
@@ -47,6 +48,7 @@ LLLandmarkList gLandmarkList;
LLLandmarkList::~LLLandmarkList()
{
std::for_each(mList.begin(), mList.end(), DeletePairedPointer());
mList.clear();
}
LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t cb)
@@ -67,7 +69,7 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t
{
if ( mBadList.find(asset_uuid) != mBadList.end() )
{
return NULL;
return nullptr;
}
landmark_requested_list_t::iterator iter = mRequestedList.find(asset_uuid);
@@ -76,7 +78,7 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t
const F32 rerequest_time = 30.f; // 30 seconds between requests
if (gFrameTimeSeconds - iter->second < rerequest_time)
{
return NULL;
return nullptr;
}
}
@@ -89,10 +91,10 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t
gAssetStorage->getAssetData(asset_uuid,
LLAssetType::AT_LANDMARK,
LLLandmarkList::processGetAssetReply,
NULL);
nullptr);
mRequestedList[asset_uuid] = gFrameTimeSeconds;
}
return NULL;
return nullptr;
}
// static
@@ -143,14 +145,16 @@ void LLLandmarkList::processGetAssetReply(
else
{
LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED );
// SJB: No use case for a notification here. Use LL_DEBUGS() instead
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status )
{
LLNotificationsUtil::add("LandmarkMissing");
LL_WARNS("Landmarks") << "Missing Landmark" << LL_ENDL;
//LLNotificationsUtil::add("LandmarkMissing");
}
else
{
LLNotificationsUtil::add("UnableToLoadLandmark");
LL_WARNS("Landmarks") << "Unable to load Landmark" << LL_ENDL;
//LLNotificationsUtil::add("UnableToLoadLandmark");
}
gLandmarkList.mBadList.insert(uuid);

View File

@@ -27,11 +27,6 @@
#ifndef LL_LLLANDMARKLIST_H
#define LL_LLLANDMARKLIST_H
#ifndef BOOST_FUNCTION_HPP_INCLUDED
#include <boost/function.hpp>
#define BOOST_FUNCTION_HPP_INCLUDED
#endif
#include <map>
#include "lllandmark.h"
#include "lluuid.h"
#include "llassetstorage.h"
@@ -43,7 +38,7 @@ class LLInventoryItem;
class LLLandmarkList
{
public:
typedef boost::function<void(LLLandmark*)> loaded_callback_t;
typedef std::function<void(LLLandmark*)> loaded_callback_t;
LLLandmarkList() {}
~LLLandmarkList();
@@ -53,7 +48,7 @@ public:
//const LLLandmark* getNext() { return mList.getNextData(); }
BOOL assetExists(const LLUUID& asset_uuid);
LLLandmark* getAsset(const LLUUID& asset_uuid, loaded_callback_t cb = NULL);
LLLandmark* getAsset(const LLUUID& asset_uuid, loaded_callback_t cb = nullptr);
static void processGetAssetReply(
LLVFS *vfs,
const LLUUID& uuid,

View File

@@ -86,6 +86,8 @@
#include <boost/lexical_cast.hpp>
// </edit>
#include <boost/algorithm/string.hpp>
#include "llsdserialize.h"
#include "llstring.h"
#include <cctype>
@@ -354,6 +356,67 @@ LLPanelLogin::LLPanelLogin(const LLRect& rect)
{
setFields(*saved_login_entries.rbegin());
}
addFavoritesToStartLocation();
}
void LLPanelLogin::addFavoritesToStartLocation()
{
// Clear the combo.
auto combo = getChild<LLComboBox>("start_location_combo");
if (!combo) return;
S32 num_items = combo->getItemCount();
for (S32 i = num_items - 1; i > 2; i--)
{
combo->remove(i);
}
// Load favorites into the combo.
const auto grid = gHippoGridManager->getCurrentGrid();
std::string first, last;
getFields(first, last, std::string());
auto user_defined_name(first + ' ' + last);
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites_" + grid->getGridName() + ".xml");
std::string old_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");
LLSD fav_llsd;
llifstream file;
file.open(filename);
if (!file.is_open())
{
file.open(old_filename);
if (!file.is_open()) return;
}
LLSDSerialize::fromXML(fav_llsd, file);
for (LLSD::map_const_iterator iter = fav_llsd.beginMap();
iter != fav_llsd.endMap(); ++iter)
{
// The account name in stored_favorites.xml has Resident last name even if user has
// a single word account name, so it can be compared case-insensitive with the
// user defined "firstname lastname".
S32 res = LLStringUtil::compareInsensitive(user_defined_name, iter->first);
if (res != 0)
{
LL_DEBUGS() << "Skipping favorites for " << iter->first << LL_ENDL;
continue;
}
combo->addSeparator();
LL_DEBUGS() << "Loading favorites for " << iter->first << LL_ENDL;
auto user_llsd = iter->second;
for (LLSD::array_const_iterator iter1 = user_llsd.beginArray();
iter1 != user_llsd.endArray(); ++iter1)
{
std::string label = (*iter1)["name"].asString();
std::string value = (*iter1)["slurl"].asString();
if (!label.empty() && !value.empty())
{
combo->add(label, value);
}
}
break;
}
}
void LLPanelLogin::setSiteIsAlive(bool alive)
@@ -1048,6 +1111,42 @@ void LLPanelLogin::onSelectGrid(LLUICtrl *ctrl)
}
gHippoGridManager->setCurrentGrid(grid);
ctrl->setValue(grid);
sInstance->addFavoritesToStartLocation();
/*
* Determine whether or not the value in the start_location_combo makes sense
* with the new grid value.
*
* Note that some forms that could be in the location combo are grid-agnostic,
* such as "MyRegion/128/128/0". There could be regions with that name on any
* number of grids, so leave them alone. Other forms, such as
* https://grid.example.com/region/Party%20Town/20/30/5 specify a particular
* grid; in those cases we want to clear the location.
*/
auto location_combo = sInstance->getChild<LLComboBox>("start_location_combo");
S32 index = location_combo->getCurrentIndex();
switch (index)
{
case 0: // last location
case 1: // home location
// do nothing - these are grid-agnostic locations
break;
default:
{
std::string location = location_combo->getValue().asString();
LLSLURL slurl(location); // generata a slurl from the location combo contents
if ( slurl.getType() == LLSLURL::LOCATION
&& slurl.getGrid() != gHippoGridManager->getCurrentGridNick()
)
{
// the grid specified by the location is not this one, so clear the combo
location_combo->setCurrentByIndex(0); // last location on the new grid
location_combo->setTextEntry(LLStringUtil::null);
}
}
break;
}
}
void LLPanelLogin::onLocationSLURL()
@@ -1067,6 +1166,8 @@ void LLPanelLogin::onSelectLoginEntry(const LLSD& selected_entry)
setFields(LLSavedLoginEntry(selected_entry));
// This stops the automatic matching of the first name to a selected grid.
LLViewerLogin::getInstance()->setNameEditted(true);
sInstance->addFavoritesToStartLocation();
}
void LLPanelLogin::onLoginComboLostFocus(LLComboBox* combo_box)

View File

@@ -107,6 +107,7 @@ public:
private:
void reshapeBrowser();
void addFavoritesToStartLocation();
void onLocationSLURL();
void onClickConnect();

View File

@@ -50,8 +50,8 @@
#include "llinventorypanel.h"
#include "llfloaterinventory.h"
#include "llfloaterperms.h"
#include "lllandmarkactions.h"
#include "lllandmark.h"
#include "llviewerassettype.h"
#include "llviewerregion.h"
#include "llviewerobjectlist.h"
@@ -62,6 +62,7 @@
#include "llcommandhandler.h"
#include "llviewermessage.h"
#include "llavatarnamecache.h"
#include "llfavoritesbar.h"
#include "llsdutil.h"
@@ -1090,13 +1091,6 @@ void create_notecard_cb(const LLUUID& inv_item)
}
}
void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id)
{
if (mTargetLandmarkId.isNull()) return;
//gInventory.rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId); // MULTI-WEARABLES TODO
}
LLInventoryCallbackManager gInventoryCallbacks;
void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id,
@@ -2136,17 +2130,21 @@ const std::string& LLViewerInventoryItem::getName() const
return LLInventoryItem::getName();
}
#if 0
S32 LLViewerInventoryItem::getSortField() const
{
return LLFavoritesOrderStorage::instance().getSortIndex(mUUID);
}
//void LLViewerInventoryItem::setSortField(S32 sortField)
//{
// LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField);
// getSLURL();
//}
void LLViewerInventoryItem::getSLURL()
{
LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID);
}
#endif
const LLPermissions& LLViewerInventoryItem::getPermissions() const
{
@@ -2244,6 +2242,33 @@ U32 LLViewerInventoryItem::getCRC32() const
return LLInventoryItem::getCRC32();
}
// *TODO: mantipov: should be removed with LMSortPrefix patch in llinventorymodel.cpp, EXT-3985
static char getSeparator() { return '@'; }
BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName)
{
const char separator = getSeparator();
const std::string::size_type separatorPos = name.find(separator, 0);
BOOL result = FALSE;
if (separatorPos < std::string::npos)
{
if (sortField)
{
*sortField = std::stoi(name.substr(0, separatorPos));
}
if (displayName)
{
*displayName = name.substr(separatorPos + 1, std::string::npos);
}
result = TRUE;
}
return result;
}
// This returns true if the item that this item points to
// doesn't exist in memory (i.e. LLInventoryModel). The baseitem
// might still be in the database but just not loaded yet.

View File

@@ -63,6 +63,9 @@ public:
virtual const LLUUID& getAssetUUID() const;
virtual const LLUUID& getProtectedAssetUUID() const; // returns LLUUID::null if current agent does not have permission to expose this asset's UUID to the user
virtual const std::string& getName() const;
virtual S32 getSortField() const;
//virtual void setSortField(S32 sortField);
virtual void getSLURL(); //Caches SLURL for landmark. //*TODO: Find a better way to do it and remove this method from here.
virtual const LLPermissions& getPermissions() const;
virtual const bool getIsFullPerm() const; // 'fullperm' in the popular sense: modify-ok & copy-ok & transfer-ok, no special god rules applied
virtual const LLUUID& getCreatorUUID() const;
@@ -75,6 +78,8 @@ public:
virtual time_t getCreationDate() const;
virtual U32 getCRC32() const; // really more of a checksum.
static BOOL extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName);
// construct a complete viewer inventory item
LLViewerInventoryItem(const LLUUID& uuid, const LLUUID& parent_uuid,
const LLPermissions& permissions,