--HG--
branch : product-engine
master
Mike Antipov 2010-01-29 13:06:36 +02:00
commit 4c2dbe9363
19 changed files with 317 additions and 124 deletions

View File

@ -35,11 +35,11 @@
#include "llsingleton.h"
#include "llinventorymodel.h"
#include "llviewerinventory.h"
#include "llcallbacklist.h"
class LLWearable;
class LLWearableHoldingPattern;
class LLInventoryCallback;
class LLAppearanceManager: public LLSingleton<LLAppearanceManager>
{

View File

@ -685,7 +685,7 @@ void LLFavoritesBarCtrl::updateButtons()
{
// an child's order and mItems should be same
if (button->getLandmarkId() != item->getUUID() // sort order has been changed
|| button->getLabelSelected() != item->getDisplayName() // favorite's name has been changed
|| button->getLabelSelected() != item->getName() // favorite's name has been changed
|| button->getRect().mRight < rightest_point) // favbar's width has been changed
{
break;
@ -780,7 +780,7 @@ LLButton* LLFavoritesBarCtrl::createButton(const LLPointer<LLViewerInventoryItem
* Empty space (or ...) is displaying instead of last symbols, even though the width of the button is enough.
* Problem will gone, if we stretch out the button. For that reason I have to put additional 20 pixels.
*/
int requred_width = mFont->getWidth(item->getDisplayName()) + 20;
int requred_width = mFont->getWidth(item->getName()) + 20;
int width = requred_width > def_button_width? def_button_width : requred_width;
LLFavoriteLandmarkButton* fav_btn = NULL;

View File

@ -43,6 +43,7 @@
#include "llviewerregion.h"
#include "lscript_rt_interface.h"
#include "llviewercontrol.h"
#include "llviewerinventory.h"
#include "llviewerobject.h"
#include "llviewerregion.h"
#include "llresmgr.h"

View File

@ -44,8 +44,6 @@
#include "llfloater.h"
#include "llscrolllistctrl.h"
#include "llviewerinventory.h"
class LLFloaterBulkPermission : public LLFloater, public LLVOInventoryListener
{
friend class LLFloaterReg;

View File

@ -40,7 +40,6 @@
#include "llinventoryfilter.h"
#include "llpanel.h"
#include "llviewercontrol.h" // gSavedSettings
#include "llviewerinventory.h"
#include "llviewerwindow.h" // Argh, only for setCursor()
// linden library includes

View File

@ -5079,7 +5079,7 @@ void LLLandmarkBridgeAction::doIt()
payload["asset_id"] = item->getAssetUUID();
LLSD args;
args["LOCATION"] = item->getDisplayName();
args["LOCATION"] = item->getName();
LLNotificationsUtil::add("TeleportFromLandmark", args, payload);
}

View File

@ -39,7 +39,6 @@
#include "llfolderviewitem.h"
#include "llinventorymodel.h" // gInventory.backgroundFetchActive()
#include "llviewercontrol.h"
#include "llviewerinventory.h"
#include "llfolderview.h"
// linden library includes

View File

@ -76,7 +76,6 @@
#include "lltabcontainer.h"
#include "lltooldraganddrop.h"
#include "lluictrlfactory.h"
#include "llviewerinventory.h"
#include "llviewermessage.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"

View File

@ -142,6 +142,105 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
return rv;
}
/*
This namespace contains a functionality to remove LM prefixes were used to store sort order of
Favorite Landmarks in landmarks' names.
Once being in Favorites folder LM inventory Item has such prefix.
Due to another solution is implemented in EXT-3985 these prefixes should be removed.
*NOTE: It will be unnecessary after the first successful session in viewer 2.0.
Can be removed before public release.
Implementation details:
At the first run with this patch it patches all cached landmarks: removes LM sort prefixes and
updates them on the viewer and server sides.
Also it calls fetching agent's inventory to process not yet loaded landmarks too.
If fetching is successfully done it will store special per-agent empty file-marker
in the user temporary folder (where cached inventory is loaded) while caching agent's inventory.
After that in will not affect the viewer until cached marker is removed.
*/
namespace LMSortPrefix
{
bool cleanup_done = false;
const std::string getMarkerPath()
{
std::string path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, gAgentID.asString()));
std::string marker_filename = llformat("%s-lm_prefix_marker", path.c_str());
return marker_filename;
}
bool wasClean()
{
static bool was_clean = false;
static bool already_init = false;
if (already_init) return was_clean;
already_init = true;
std::string path_to_marker = getMarkerPath();
was_clean = LLFile::isfile(path_to_marker);
return was_clean;
}
void setLandmarksWereCleaned()
{
if (cleanup_done)
{
std::string path_to_marker = getMarkerPath();
LLFILE* file = LLFile::fopen(path_to_marker, "w");
if(!file)
{
llwarns << "unable to save marker that LM prefixes were removed: " << path_to_marker << llendl;
return;
}
fclose(file);
}
}
void removePrefix(LLPointer<LLViewerInventoryItem> inv_item)
{
if (wasClean())
{
LL_INFOS_ONCE("") << "Inventory was cleaned for this avatar. Patch can be removed." << LL_ENDL;
return;
}
if (LLInventoryType::IT_LANDMARK != inv_item->getInventoryType()) return;
std::string old_name = inv_item->getName();
S32 sort_field = -1;
std::string display_name;
BOOL exists = LLViewerInventoryItem::extractSortFieldAndDisplayName(old_name, &sort_field, &display_name);
if (exists && sort_field != -1)
{
llinfos << "Removing Landmark sort field and separator for: " << old_name << " | " << inv_item->getUUID() << llendl;
LLUUID parent_uuid = inv_item->getParentUUID();
if (gInventory.getCategory(parent_uuid))
{
llinfos << "parent folder is: " << gInventory.getCategory(parent_uuid)->getName() << llendl;
}
// mark item completed to avoid error while copying and updating server
inv_item->setComplete(TRUE);
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item);
new_item->rename(display_name);
gInventory.updateItem(new_item);
new_item->updateServer(FALSE);
gInventory.notifyObservers();
}
}
void completeCleanup()
{
// background fetch is completed. can save marker
cleanup_done = true;
}
}
///----------------------------------------------------------------------------
/// Class LLInventoryModel
///----------------------------------------------------------------------------
@ -1736,6 +1835,8 @@ void LLInventoryModel::stopBackgroundFetch()
gIdleCallbacks.deleteFunction(&LLInventoryModel::backgroundFetch, NULL);
sBulkFetchCount=0;
sMinTimeBetweenFetches=0.0f;
LMSortPrefix::completeCleanup();
}
}
@ -1882,6 +1983,13 @@ void LLInventoryModel::cache(
const LLUUID& parent_folder_id,
const LLUUID& agent_id)
{
if (getRootFolderID() == parent_folder_id)
{
// *TODO: mantipov: can be removed before public release, EXT-3985
//save marker to avoid fetching inventory on future sessions
LMSortPrefix::setLandmarksWereCleaned();
}
lldebugs << "Caching " << parent_folder_id << " for " << agent_id
<< llendl;
LLViewerInventoryCategory* root_cat = getCategory(parent_folder_id);
@ -2692,6 +2800,28 @@ void LLInventoryModel::buildParentChildMap()
// The inv tree is built.
mIsAgentInvUsable = true;
{// *TODO: mantipov: can be removed before public release, EXT-3985
/*
*HACK: mantipov: to cleanup landmarks were marked with sort index prefix in name.
Is necessary to be called once per account after EXT-3985 is implemented.
So, let fetch agent's inventory, processing will be done in processInventoryDescendents()
Should be removed before public release.
*/
if (!LMSortPrefix::wasClean())
{
cat_array_t cats;
item_array_t items;
collectDescendents(agent_inv_root_id, cats, items, INCLUDE_TRASH);
for (item_array_t::const_iterator it= items.begin(); it != items.end(); ++it)
{
LMSortPrefix::removePrefix(*it);
}
gInventory.startBackgroundFetch(agent_inv_root_id);
}
}
llinfos << "Inventory initialized, notifying observers" << llendl;
addChangedMask(LLInventoryObserver::ALL, LLUUID::null);
notifyObservers();
@ -3457,6 +3587,10 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**)
continue;
}
gInventory.updateItem(titem);
{// *TODO: mantipov: can be removed before public release, EXT-3985
LMSortPrefix::removePrefix(titem);
}
}
// set version and descendentcount according to message.

View File

@ -50,7 +50,6 @@
// project includes
#include "llagent.h"
#include "llfloaterbulkpermission.h"
#include "llpanelobjectinventory.h"
#include "llpreviewscript.h"
#include "llresmgr.h"
@ -60,6 +59,7 @@
#include "lltoolmgr.h"
#include "lltrans.h"
#include "llviewerassettype.h"
#include "llviewerinventory.h"
#include "llviewerobject.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"

View File

@ -614,7 +614,7 @@ void LLPanelGroupNotices::showNotice(const std::string& subject,
mViewInventoryIcon->setVisible(TRUE);
std::stringstream ss;
ss << " " << LLViewerInventoryItem::getDisplayName(inventory_name);
ss << " " << inventory_name;
mViewInventoryName->setText(ss.str());
mBtnOpenAttachment->setEnabled(TRUE);

View File

@ -367,7 +367,6 @@ void LLPanelLandmarkInfo::createLandmark(const LLUUID& folder_id)
}
LLStringUtil::replaceChar(desc, '\n', ' ');
LLViewerInventoryItem::insertDefaultSortField(name);
// If no folder chosen use the "Landmarks" folder.
LLLandmarkActions::createLandmarkHere(name, desc,

View File

@ -46,7 +46,6 @@
#include "llnotificationsutil.h"
#include "lltextbox.h"
#include "llviewermenu.h"
#include "llviewerinventory.h"
#include "lllandmarkactions.h"
#include "llclipboard.h"

View File

@ -44,7 +44,6 @@
#include "lllineeditor.h"
#include "llradiogroup.h"
#include "llviewercontrol.h"
#include "llviewerinventory.h"
#include "llviewerobjectlist.h"

View File

@ -127,17 +127,7 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification
pAttachLink->setVisible(hasInventory);
pAttachIcon->setVisible(hasInventory);
if (hasInventory) {
std::string dis_name;
std::string inv_name = payload["inventory_name"];
if (LLViewerInventoryItem::extractSortFieldAndDisplayName(inv_name, NULL, &dis_name))
{
pAttachLink->setValue(dis_name);
}
else
{
pAttachLink->setValue(inv_name);
}
pAttachLink->setValue(payload["inventory_name"]);
mInventoryOffer = new LLOfferInfo(payload["inventory_offer"]);
childSetActionTextbox("attachment", boost::bind(

View File

@ -34,6 +34,7 @@
#include "llviewerinventory.h"
#include "llnotificationsutil.h"
#include "llsdserialize.h"
#include "message.h"
#include "indra_constants.h"
@ -1171,79 +1172,194 @@ const std::string& LLViewerInventoryItem::getName() const
return linked_category->getName();
}
return getDisplayName();
return LLInventoryItem::getName();
}
const std::string& LLViewerInventoryItem::getDisplayName() const
/**
* 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>
{
std::string result;
BOOL hasSortField = extractSortFieldAndDisplayName(0, &result);
public:
/**
* Sets sort index for specified with LLUUID favorite landmark
*/
void setSortIndex(const LLUUID& inv_item_id, S32 sort_index);
return mDisplayName = hasSortField ? result : LLInventoryItem::getName();
/**
* Gets sort index for specified with LLUUID favorite landmark
*/
S32 getSortIndex(const LLUUID& inv_item_id);
void removeSortIndex(const LLUUID& inv_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:
friend class LLSingleton<LLFavoritesOrderStorage>;
LLFavoritesOrderStorage() : mIsDirty(false) { load(); }
~LLFavoritesOrderStorage() { save(); }
/**
* Removes sort indexes for items which are not in Favorites bar for now.
*/
void cleanup();
const static std::string SORTING_DATA_FILE_NAME;
void load();
void save();
typedef std::map<LLUUID, S32> sort_index_map_t;
sort_index_map_t mSortIndexes;
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;
};
};
const std::string LLFavoritesOrderStorage::SORTING_DATA_FILE_NAME = "landmarks_sorting.xml";
const S32 LLFavoritesOrderStorage::NO_INDEX = -1;
void LLFavoritesOrderStorage::setSortIndex(const LLUUID& inv_item_id, S32 sort_index)
{
mSortIndexes[inv_item_id] = sort_index;
mIsDirty = true;
}
S32 LLFavoritesOrderStorage::getSortIndex(const LLUUID& inv_item_id)
{
sort_index_map_t::const_iterator it = mSortIndexes.find(inv_item_id);
if (it != mSortIndexes.end())
{
return it->second;
}
return NO_INDEX;
}
void LLFavoritesOrderStorage::removeSortIndex(const LLUUID& inv_item_id)
{
mSortIndexes.erase(inv_item_id);
mIsDirty = true;
}
// static
std::string LLViewerInventoryItem::getDisplayName(const std::string& name)
void LLFavoritesOrderStorage::destroyClass()
{
std::string result;
BOOL hasSortField = extractSortFieldAndDisplayName(name, 0, &result);
return hasSortField ? result : name;
LLFavoritesOrderStorage::instance().cleanup();
}
void LLFavoritesOrderStorage::load()
{
// load per-resident sorting information
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME);
LLSD settings_llsd;
llifstream file;
file.open(filename);
if (file.is_open())
{
LLSDSerialize::fromXML(settings_llsd, file);
}
for (LLSD::map_const_iterator iter = settings_llsd.beginMap();
iter != settings_llsd.endMap(); ++iter)
{
mSortIndexes.insert(std::make_pair(LLUUID(iter->first), (S32)iter->second.asInteger()));
}
}
void LLFavoritesOrderStorage::save()
{
// nothing to save if clean
if (!mIsDirty) return;
// If we quit from the login screen we will not have an SL account
// name. Don't try to save, otherwise we'll dump a file in
// C:\Program Files\SecondLife\ or similar. JC
std::string user_dir = gDirUtilp->getLindenUserDir();
if (!user_dir.empty())
{
std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, SORTING_DATA_FILE_NAME);
LLSD settings_llsd;
for(sort_index_map_t::const_iterator iter = mSortIndexes.begin(); iter != mSortIndexes.end(); ++iter)
{
settings_llsd[iter->first.asString()] = iter->second;
}
llofstream file;
file.open(filename);
LLSDSerialize::toPrettyXML(settings_llsd, file);
}
}
void LLFavoritesOrderStorage::cleanup()
{
// nothing to clean
if (!mIsDirty) return;
const LLUUID fav_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
gInventory.collectDescendents(fav_id, cats, items, LLInventoryModel::EXCLUDE_TRASH);
IsNotInFavorites is_not_in_fav(items);
sort_index_map_t aTempMap;
//copy unremoved values from mSortIndexes to aTempMap
std::remove_copy_if(mSortIndexes.begin(), mSortIndexes.end(),
inserter(aTempMap, aTempMap.begin()),
is_not_in_fav);
//Swap the contents of mSortIndexes and aTempMap
mSortIndexes.swap(aTempMap);
}
S32 LLViewerInventoryItem::getSortField() const
{
S32 result;
BOOL hasSortField = extractSortFieldAndDisplayName(&result, 0);
return hasSortField ? result : -1;
return LLFavoritesOrderStorage::instance().getSortIndex(mUUID);
}
void LLViewerInventoryItem::setSortField(S32 sortField)
{
using std::string;
std::stringstream ss;
ss << sortField;
string newSortField = ss.str();
const char separator = getSeparator();
const string::size_type separatorPos = mName.find(separator, 0);
if (separatorPos < string::npos)
{
// the name of the LLViewerInventoryItem already consists of sort field and display name.
mName = newSortField + separator + mName.substr(separatorPos + 1, string::npos);
}
else
{
// there is no sort field in the name of LLViewerInventoryItem, we should add it
mName = newSortField + separator + mName;
}
}
void LLViewerInventoryItem::rename(const std::string& n)
{
using std::string;
string new_name(n);
LLStringUtil::replaceNonstandardASCII(new_name, ' ');
LLStringUtil::replaceChar(new_name, '|', ' ');
LLStringUtil::trim(new_name);
LLStringUtil::truncate(new_name, DB_INV_ITEM_NAME_STR_LEN);
const char separator = getSeparator();
const string::size_type separatorPos = mName.find(separator, 0);
if (separatorPos < string::npos)
{
mName.replace(separatorPos + 1, string::npos, new_name);
}
else
{
mName = new_name;
}
LLFavoritesOrderStorage::instance().setSortIndex(mUUID, sortField);
}
const LLPermissions& LLViewerInventoryItem::getPermissions() const
@ -1334,6 +1450,8 @@ 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)
{
using std::string;
@ -1369,12 +1487,6 @@ BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& na
return result;
}
void LLViewerInventoryItem::insertDefaultSortField(std::string& name)
{
name.insert(0, std::string("1") + getSeparator());
}
// 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

@ -64,12 +64,8 @@ public:
virtual LLAssetType::EType getType() const;
virtual const LLUUID& getAssetUUID() const;
virtual const std::string& getName() const;
virtual const std::string& getDisplayName() const;
static std::string getDisplayName(const std::string& name);
static char getSeparator() { return '@'; }
virtual S32 getSortField() const;
virtual void setSortField(S32 sortField);
virtual void rename(const std::string& new_name);
virtual const LLPermissions& getPermissions() const;
virtual const LLUUID& getCreatorUUID() const;
virtual const std::string& getDescription() const;
@ -82,7 +78,6 @@ public:
virtual U32 getCRC32() const; // really more of a checksum.
static BOOL extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName);
static void insertDefaultSortField(std::string& name);
// construct a complete viewer inventory item
LLViewerInventoryItem(const LLUUID& uuid, const LLUUID& parent_uuid,

View File

@ -1435,31 +1435,6 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const
return false;
}
std::string get_display_name(const std::string& name)
{
// We receive landmark name as \'<n>@name\' where <n> is a number
// LLViewerInventoryItem::getDisplayName will remove \'<n>@ though we need the \'
// Lets save all chars preceding @ and insert them back after <n>@ was removed
std::string saved;
if(std::string::npos != name.find(LLViewerInventoryItem::getSeparator()))
{
int n = 0;
while(!isdigit(name[n]) && LLViewerInventoryItem::getSeparator() != name[n])
{
++n;
}
saved = name.substr(0, n);
}
std::string d_name = LLViewerInventoryItem::getDisplayName(name);
d_name.insert(0, saved);
LLStringUtil::trim(d_name);
return d_name;
}
void inventory_offer_handler(LLOfferInfo* info)
{
//Until throttling is implmented, busy mode should reject inventory instead of silently
@ -1497,11 +1472,6 @@ void inventory_offer_handler(LLOfferInfo* info)
LLStringUtil::truncate(msg, indx);
}
if(LLAssetType::AT_LANDMARK == info->mType)
{
msg = get_display_name(msg);
}
LLSD args;
args["[OBJECTNAME]"] = msg;

View File

@ -38,7 +38,6 @@
#include "llassetstorage.h"
#include "llagent.h"
#include "llvoavatar.h"
#include "llviewerinventory.h"
#include "llviewerstats.h"
#include "llnotificationsutil.h"
#include "llinventorymodel.h"