From 1eab3247111e66a3b81153173d1624a5c1c9fb72 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Tue, 21 Mar 2023 17:47:26 +0200 Subject: SL-19379 WIP Gallery view Inventory: first pass --- indra/newview/llinventorygallery.cpp | 924 +++++++++++++++++++++++++++++++++++ 1 file changed, 924 insertions(+) create mode 100644 indra/newview/llinventorygallery.cpp (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp new file mode 100644 index 0000000000..b5fd3aaece --- /dev/null +++ b/indra/newview/llinventorygallery.cpp @@ -0,0 +1,924 @@ +/** + * @file llinventorygallery.cpp + * @brief LLInventoryGallery class implementation + * + * $LicenseInfo:firstyear=2023&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2023, 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 "llinventorygallery.h" + +#include "llaccordionctrltab.h" +#include "llcommonutils.h" +#include "lliconctrl.h" +#include "llinventorybridge.h" +#include "llinventoryfunctions.h" +#include "llinventorymodel.h" +#include "llthumbnailctrl.h" +#include "lltextbox.h" +#include "llviewerfoldertype.h" + +#include "llinventoryicon.h" + +static LLPanelInjector t_inventory_gallery("inventory_gallery"); + +const S32 GALLERY_ITEMS_PER_ROW_MIN = 2; + +LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) + : LLPanel(), + mScrollPanel(NULL), + mGalleryPanel(NULL), + mLastRowPanel(NULL), + mGalleryCreated(false), + mRowCount(0), + mItemsAddedCount(0), + mRowPanelHeight(p.row_panel_height), + mVerticalGap(p.vertical_gap), + mHorizontalGap(p.horizontal_gap), + mItemWidth(p.item_width), + mItemHeight(p.item_height), + mItemHorizontalGap(p.item_horizontal_gap), + mItemsInRow(p.items_in_row), + mRowPanWidthFactor(p.row_panel_width_factor), + mGalleryWidthFactor(p.gallery_width_factor), + mIsInitialized(false) +{ + updateGalleryWidth(); +} + +LLInventoryGallery::Params::Params() + : row_panel_height("row_panel_height", 180), + vertical_gap("vertical_gap", 10), + horizontal_gap("horizontal_gap", 10), + item_width("item_width", 150), + item_height("item_height", 175), + item_horizontal_gap("item_horizontal_gap", 16), + items_in_row("items_in_row", GALLERY_ITEMS_PER_ROW_MIN), + row_panel_width_factor("row_panel_width_factor", 166), + gallery_width_factor("gallery_width_factor", 163) +{ + addSynonym(row_panel_height, "row_height"); +} + +const LLInventoryGallery::Params& LLInventoryGallery::getDefaultParams() +{ + return LLUICtrlFactory::getDefaultParams(); +} + +BOOL LLInventoryGallery::postBuild() +{ + mScrollPanel = getChild("gallery_scroll_panel"); + LLPanel::Params params = LLPanel::getDefaultParams(); + mGalleryPanel = LLUICtrlFactory::create(params); + mMessageTextBox = getChild("empty_txt"); + + return TRUE; +} + +LLInventoryGallery::~LLInventoryGallery() +{ + while (!mUnusedRowPanels.empty()) + { + LLPanel* panelp = mUnusedRowPanels.back(); + mUnusedRowPanels.pop_back(); + panelp->die(); + } + while (!mUnusedItemPanels.empty()) + { + LLPanel* panelp = mUnusedItemPanels.back(); + mUnusedItemPanels.pop_back(); + panelp->die(); + } + + if (gInventory.containsObserver(mCategoriesObserver)) + { + gInventory.removeObserver(mCategoriesObserver); + } + delete mCategoriesObserver; +} + +void LLInventoryGallery::setRootFolder(const LLUUID cat_id) +{ + LLViewerInventoryCategory* category = gInventory.getCategory(cat_id); + if(!category || (mFolderID == cat_id)) + { + return; + } + if(mFolderID.notNull()) + { + mBackwardFolders.push_back(mFolderID); + } + mFolderID = cat_id; + updateRootFolder(); +} + +void LLInventoryGallery::updateRootFolder() +{ + if (mIsInitialized) + { + S32 count = mItemsAddedCount; + for (S32 i = count - 1; i >= 0; i--) + { + updateRemovedItem(mItems[i]->getUUID()); + } + + if (gInventory.containsObserver(mCategoriesObserver)) + { + gInventory.removeObserver(mCategoriesObserver); + } + delete mCategoriesObserver; + } + { + mRootChangedSignal(); + + mCategoriesObserver = new LLInventoryCategoriesObserver(); + gInventory.addObserver(mCategoriesObserver); + + // Start observing changes in selected category. + mCategoriesObserver->addCategory(mFolderID, + boost::bind(&LLInventoryGallery::refreshList, this, mFolderID)); + + LLViewerInventoryCategory* category = gInventory.getCategory(mFolderID); + //If not all items are fetched now + // the observer will refresh the list as soon as the new items + // arrive. + category->fetch(); + + //refreshList(cat_id); + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + + gInventory.getDirectDescendentsOf(mFolderID, cat_array, item_array); + + // Creating a vector of newly collected sub-categories UUIDs. + for (LLInventoryModel::cat_array_t::const_iterator iter = cat_array->begin(); + iter != cat_array->end(); + iter++) + { + updateAddedItem((*iter)->getUUID()); + } + + for (LLInventoryModel::item_array_t::const_iterator iter = item_array->begin(); + iter != item_array->end(); + iter++) + { + updateAddedItem((*iter)->getUUID()); + } + reArrangeRows(); + mIsInitialized = true; + + if (mScrollPanel) + { + mScrollPanel->goToTop(); + } + } + + if (!mGalleryCreated) + { + initGallery(); + } +} + +void LLInventoryGallery::initGallery() +{ + if (!mGalleryCreated) + { + uuid_vec_t cats; + getCurrentCategories(cats); + int n = cats.size(); + buildGalleryPanel(n); + mScrollPanel->addChild(mGalleryPanel); + for (int i = 0; i < n; i++) + { + addToGallery(mItemMap[cats[i]]); + } + reArrangeRows(); + mGalleryCreated = true; + } +} + +void LLInventoryGallery::draw() +{ + LLPanel::draw(); + if (mGalleryCreated) + { + updateRowsIfNeeded(); + } +} + +void LLInventoryGallery::updateRowsIfNeeded() +{ + if(((getRect().getWidth() - mRowPanelWidth) > mItemWidth) && mRowCount > 1) + { + reArrangeRows(1); + } + else if((mRowPanelWidth > (getRect().getWidth() + mItemHorizontalGap)) && mItemsInRow > GALLERY_ITEMS_PER_ROW_MIN) + { + reArrangeRows(-1); + } +} + +bool compareGalleryItem(LLInventoryGalleryItem* item1, LLInventoryGalleryItem* item2) +{ + if (item1->getSortGroup() != item2->getSortGroup()) + { + return (item1->getSortGroup() < item2->getSortGroup()); + } + if(((item1->isDefaultImage() && item2->isDefaultImage()) || (!item1->isDefaultImage() && !item2->isDefaultImage()))) + { + std::string name1 = item1->getItemName(); + std::string name2 = item2->getItemName(); + + return (LLStringUtil::compareDict(name1, name2) < 0); + } + else + { + return item2->isDefaultImage(); + } +} + +void LLInventoryGallery::reArrangeRows(S32 row_diff) +{ + std::vector buf_items = mItems; + for (std::vector::const_reverse_iterator it = buf_items.rbegin(); it != buf_items.rend(); ++it) + { + removeFromGalleryLast(*it); + } + for (std::vector::const_reverse_iterator it = mHiddenItems.rbegin(); it != mHiddenItems.rend(); ++it) + { + buf_items.push_back(*it); + } + mHiddenItems.clear(); + + mItemsInRow+= row_diff; + updateGalleryWidth(); + std::sort(buf_items.begin(), buf_items.end(), compareGalleryItem); + + for (std::vector::const_iterator it = buf_items.begin(); it != buf_items.end(); ++it) + { + (*it)->setHidden(false); + applyFilter(*it, mFilterSubString); + addToGallery(*it); + } + updateMessageVisibility(); +} + +void LLInventoryGallery::updateGalleryWidth() +{ + mRowPanelWidth = mRowPanWidthFactor * mItemsInRow - mItemHorizontalGap; + mGalleryWidth = mGalleryWidthFactor * mItemsInRow - mItemHorizontalGap; +} + +LLPanel* LLInventoryGallery::addLastRow() +{ + mRowCount++; + int row = 0; + int vgap = mVerticalGap * row; + LLPanel* result = buildRowPanel(0, row * mRowPanelHeight + vgap); + mGalleryPanel->addChild(result); + return result; +} + +void LLInventoryGallery::moveRowUp(int row) +{ + moveRow(row, mRowCount - 1 - row + 1); +} + +void LLInventoryGallery::moveRowDown(int row) +{ + moveRow(row, mRowCount - 1 - row - 1); +} + +void LLInventoryGallery::moveRow(int row, int pos) +{ + int vgap = mVerticalGap * pos; + moveRowPanel(mRowPanels[row], 0, pos * mRowPanelHeight + vgap); +} + +void LLInventoryGallery::removeLastRow() +{ + mRowCount--; + mGalleryPanel->removeChild(mLastRowPanel); + mUnusedRowPanels.push_back(mLastRowPanel); + mRowPanels.pop_back(); + if (mRowPanels.size() > 0) + { + // Just removed last row + mLastRowPanel = mRowPanels.back(); + } + else + { + mLastRowPanel = NULL; + } +} + +LLPanel* LLInventoryGallery::addToRow(LLPanel* row_stack, LLInventoryGalleryItem* item, int pos, int hgap) +{ + LLPanel* lpanel = buildItemPanel(pos * mItemWidth + hgap); + lpanel->addChild(item); + row_stack->addChild(lpanel); + mItemPanels.push_back(lpanel); + return lpanel; +} + +void LLInventoryGallery::addToGallery(LLInventoryGalleryItem* item) +{ + if(item->isHidden()) + { + mHiddenItems.push_back(item); + return; + } + mItemsAddedCount++; + mItemIndexMap[item] = mItemsAddedCount - 1; + int n = mItemsAddedCount; + int row_count = (n % mItemsInRow) == 0 ? n / mItemsInRow : n / mItemsInRow + 1; + int n_prev = n - 1; + int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1; + + bool add_row = row_count != row_count_prev; + int pos = 0; + if (add_row) + { + for (int i = 0; i < row_count_prev; i++) + { + moveRowUp(i); + } + mLastRowPanel = addLastRow(); + mRowPanels.push_back(mLastRowPanel); + } + pos = (n - 1) % mItemsInRow; + mItems.push_back(item); + addToRow(mLastRowPanel, item, pos, mHorizontalGap * pos); + reshapeGalleryPanel(row_count); +} + + +void LLInventoryGallery::removeFromGalleryLast(LLInventoryGalleryItem* item) +{ + if(item->isHidden()) + { + mHiddenItems.pop_back(); + return; + } + int n_prev = mItemsAddedCount; + int n = mItemsAddedCount - 1; + int row_count = (n % mItemsInRow) == 0 ? n / mItemsInRow : n / mItemsInRow + 1; + int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1; + mItemsAddedCount--; + + bool remove_row = row_count != row_count_prev; + removeFromLastRow(mItems[mItemsAddedCount]); + mItems.pop_back(); + if (remove_row) + { + for (int i = 0; i < row_count_prev - 1; i++) + { + moveRowDown(i); + } + removeLastRow(); + } + reshapeGalleryPanel(row_count); +} + + +void LLInventoryGallery::removeFromGalleryMiddle(LLInventoryGalleryItem* item) +{ + if(item->isHidden()) + { + mHiddenItems.erase(std::remove(mHiddenItems.begin(), mHiddenItems.end(), item), mHiddenItems.end()); + return; + } + int n = mItemIndexMap[item]; + mItemIndexMap.erase(item); + std::vector saved; + for (int i = mItemsAddedCount - 1; i > n; i--) + { + saved.push_back(mItems[i]); + removeFromGalleryLast(mItems[i]); + } + removeFromGalleryLast(mItems[n]); + int saved_count = saved.size(); + for (int i = 0; i < saved_count; i++) + { + addToGallery(saved.back()); + saved.pop_back(); + } +} + +void LLInventoryGallery::removeFromLastRow(LLInventoryGalleryItem* item) +{ + mItemPanels.back()->removeChild(item); + mLastRowPanel->removeChild(mItemPanels.back()); + mUnusedItemPanels.push_back(mItemPanels.back()); + mItemPanels.pop_back(); +} + +LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id) +{ + LLInventoryGalleryItem::Params giparams; + LLInventoryGalleryItem* gitem = LLUICtrlFactory::create(giparams); + gitem->reshape(mItemWidth, mItemHeight); + gitem->setVisible(true); + gitem->setFollowsLeft(); + gitem->setFollowsTop(); + gitem->setName(name); + gitem->setUUID(item_id); + gitem->setGallery(this); + gitem->setType(type); + gitem->setThumbnail(thumbnail_id); + return gitem; +} + +void LLInventoryGallery::buildGalleryPanel(int row_count) +{ + LLPanel::Params params; + mGalleryPanel = LLUICtrlFactory::create(params); + reshapeGalleryPanel(row_count); +} + +void LLInventoryGallery::reshapeGalleryPanel(int row_count) +{ + int bottom = 0; + int left = 0; + int height = row_count * (mRowPanelHeight + mVerticalGap); + LLRect rect = LLRect(left, bottom + height, left + mGalleryWidth, bottom); + mGalleryPanel->setRect(rect); + mGalleryPanel->reshape(mGalleryWidth, height); + mGalleryPanel->setVisible(true); + mGalleryPanel->setFollowsLeft(); + mGalleryPanel->setFollowsTop(); +} + +LLPanel* LLInventoryGallery::buildItemPanel(int left) +{ + LLPanel::Params lpparams; + int top = 0; + LLPanel* lpanel = NULL; + if(mUnusedItemPanels.empty()) + { + lpanel = LLUICtrlFactory::create(lpparams); + } + else + { + lpanel = mUnusedItemPanels.back(); + mUnusedItemPanels.pop_back(); + } + LLRect rect = LLRect(left, top + mItemHeight, left + mItemWidth + mItemHorizontalGap, top); + lpanel->setRect(rect); + lpanel->reshape(mItemWidth + mItemHorizontalGap, mItemHeight); + lpanel->setVisible(true); + lpanel->setFollowsLeft(); + lpanel->setFollowsTop(); + return lpanel; +} + +LLPanel* LLInventoryGallery::buildRowPanel(int left, int bottom) +{ + LLPanel::Params sparams; + LLPanel* stack = NULL; + if(mUnusedRowPanels.empty()) + { + stack = LLUICtrlFactory::create(sparams); + } + else + { + stack = mUnusedRowPanels.back(); + mUnusedRowPanels.pop_back(); + } + moveRowPanel(stack, left, bottom); + return stack; +} + +void LLInventoryGallery::moveRowPanel(LLPanel* stack, int left, int bottom) +{ + LLRect rect = LLRect(left, bottom + mRowPanelHeight, left + mRowPanelWidth, bottom); + stack->setRect(rect); + stack->reshape(mRowPanelWidth, mRowPanelHeight); + stack->setVisible(true); + stack->setFollowsLeft(); + stack->setFollowsTop(); +} + +void LLInventoryGallery::setFilterSubString(const std::string& string) +{ + mFilterSubString = string; + reArrangeRows(); +} + +void LLInventoryGallery::applyFilter(LLInventoryGalleryItem* item, const std::string& filter_substring) +{ + if (!item) return; + + std::string item_name = item->getItemName(); + LLStringUtil::toUpper(item_name); + + std::string cur_filter = filter_substring; + LLStringUtil::toUpper(cur_filter); + + bool hidden = (std::string::npos == item_name.find(cur_filter)); + item->setHidden(hidden); +} + +void LLInventoryGallery::getCurrentCategories(uuid_vec_t& vcur) +{ + for (gallery_item_map_t::const_iterator iter = mItemMap.begin(); + iter != mItemMap.end(); + iter++) + { + if ((*iter).second != NULL) + { + vcur.push_back((*iter).first); + } + } +} + +void LLInventoryGallery::updateAddedItem(LLUUID item_id) +{ + LLInventoryObject* obj = gInventory.getObject(item_id); + if (!obj) + { + LL_WARNS("InventoryGallery") << "Failed to find item: " << item_id << LL_ENDL; + return; + } + + LLUUID thumbnail_id = obj->getThumbnailUUID();; + + if ((LLAssetType::AT_CATEGORY == obj->getType()) && thumbnail_id.isNull()) + { + thumbnail_id = getOutfitImageID(item_id); + } + + LLInventoryGalleryItem* item = buildGalleryItem(obj->getName(), item_id, obj->getType(), thumbnail_id); + mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); + + item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::onChangeItemSelection, this, item_id)); + if (mGalleryCreated) + { + addToGallery(item); + } +} + +void LLInventoryGallery::updateRemovedItem(LLUUID item_id) +{ + gallery_item_map_t::iterator item_iter = mItemMap.find(item_id); + if (item_iter != mItemMap.end()) + { + LLInventoryGalleryItem* item = item_iter->second; + + deselectItem(item_id); + mItemMap.erase(item_iter); + removeFromGalleryMiddle(item); + + // kill removed item + if (item != NULL) + { + item->die(); + } + } + +} + +void LLInventoryGallery::updateChangedItemName(LLUUID item_id, std::string name) +{ + gallery_item_map_t::iterator iter = mItemMap.find(item_id); + if (iter != mItemMap.end()) + { + LLInventoryGalleryItem* item = iter->second; + if (item) + { + item->setName(name); + } + } +} + +void LLInventoryGallery::onChangeItemSelection(const LLUUID& category_id) +{ + if (mSelectedItemID == category_id) + return; + + if (mItemMap[mSelectedItemID]) + { + mItemMap[mSelectedItemID]->setSelected(FALSE); + } + if (mItemMap[category_id]) + { + mItemMap[category_id]->setSelected(TRUE); + } + mSelectedItemID = category_id; + signalSelectionItemID(category_id); +} + +void LLInventoryGallery::updateMessageVisibility() +{ + mMessageTextBox->setVisible(mItems.empty()); + mScrollPanel->setVisible(!mItems.empty()); +} + +void LLInventoryGallery::refreshList(const LLUUID& category_id) +{ + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + + gInventory.getDirectDescendentsOf(category_id, cat_array, item_array); + uuid_vec_t vadded; + uuid_vec_t vremoved; + + // Create added and removed items vectors. + computeDifference(*cat_array, *item_array, vadded, vremoved); + + // Handle added tabs. + for (uuid_vec_t::const_iterator iter = vadded.begin(); + iter != vadded.end(); + ++iter) + { + const LLUUID cat_id = (*iter); + updateAddedItem(cat_id); + } + + // Handle removed tabs. + for (uuid_vec_t::const_iterator iter = vremoved.begin(); iter != vremoved.end(); ++iter) + { + const LLUUID cat_id = (*iter); + updateRemovedItem(cat_id); + } + + const LLInventoryModel::changed_items_t& changed_items = gInventory.getChangedIDs(); + for (LLInventoryModel::changed_items_t::const_iterator items_iter = changed_items.begin(); + items_iter != changed_items.end(); + ++items_iter) + { + LLInventoryObject* obj = gInventory.getObject(*items_iter); + if(!obj) + { + return; + } + + updateChangedItemName(*items_iter, obj->getName()); + } + +} + +void LLInventoryGallery::computeDifference( + const LLInventoryModel::cat_array_t vcats, + const LLInventoryModel::item_array_t vitems, + uuid_vec_t& vadded, + uuid_vec_t& vremoved) +{ + uuid_vec_t vnew; + // Creating a vector of newly collected UUIDs. + for (LLInventoryModel::cat_array_t::const_iterator iter = vcats.begin(); + iter != vcats.end(); + iter++) + { + vnew.push_back((*iter)->getUUID()); + } + for (LLInventoryModel::item_array_t::const_iterator iter = vitems.begin(); + iter != vitems.end(); + iter++) + { + vnew.push_back((*iter)->getUUID()); + } + + uuid_vec_t vcur; + getCurrentCategories(vcur); + + LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved); +} + +void LLInventoryGallery::deselectItem(const LLUUID& category_id) +{ + // Reset selection if the item is selected. + if (category_id == mSelectedItemID) + { + mSelectedItemID = LLUUID::null; + signalSelectionItemID(mSelectedItemID); + } +} + +void LLInventoryGallery::signalSelectionItemID(const LLUUID& category_id) +{ + mSelectionChangeSignal(category_id); +} + +boost::signals2::connection LLInventoryGallery::setSelectionChangeCallback(selection_change_callback_t cb) +{ + return mSelectionChangeSignal.connect(cb); +} + +LLUUID LLInventoryGallery::getOutfitImageID(LLUUID outfit_id) +{ + LLUUID thumbnail_id; + LLViewerInventoryCategory* cat = gInventory.getCategory(outfit_id); + if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) + { + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + // Not LLIsOfAssetType, because we allow links + LLIsTextureType f; + gInventory.getDirectDescendentsOf(outfit_id, cats, items, f); + + // Exactly one texture found => show the texture as thumbnail + if (1 == items.size()) + { + LLViewerInventoryItem* item = items.front(); + if (item && item->getIsLinkType()) + { + item = item->getLinkedItem(); + } + if (item) + { + thumbnail_id = item->getAssetUUID(); + } + } + } + return thumbnail_id; +} + +boost::signals2::connection LLInventoryGallery::setRootChangedCallback(root_changed_callback_t cb) +{ + return mRootChangedSignal.connect(cb); +} + +void LLInventoryGallery::onForwardFolder() +{ + if(isForwardAvailable()) + { + mBackwardFolders.push_back(mFolderID); + mFolderID = mForwardFolders.back(); + mForwardFolders.pop_back(); + updateRootFolder(); + } +} + +void LLInventoryGallery::onBackwardFolder() +{ + if(isBackwardAvailable()) + { + mForwardFolders.push_back(mFolderID); + mFolderID = mBackwardFolders.back(); + mBackwardFolders.pop_back(); + updateRootFolder(); + } +} + +void LLInventoryGallery::clearNavigationHistory() +{ + mForwardFolders.clear(); + mBackwardFolders.clear(); +} + +bool LLInventoryGallery::isBackwardAvailable() +{ + return (!mBackwardFolders.empty() && (mFolderID != mBackwardFolders.back())); +} + +bool LLInventoryGallery::isForwardAvailable() +{ + return (!mForwardFolders.empty() && (mFolderID != mForwardFolders.back())); +} +//----------------------------- +// LLInventoryGalleryItem +//----------------------------- + +static LLDefaultChildRegistry::Register r("inventory_gallery_item"); + +LLInventoryGalleryItem::LLInventoryGalleryItem(const Params& p) + : LLPanel(p), + mSelected(false), + mDefaultImage(true), + mName(""), + mUUID(LLUUID()), + mIsFolder(true), + mGallery(NULL), + mType(LLAssetType::AT_NONE), + mSortGroup(SG_ITEM) +{ + buildFromFile("panel_inventory_gallery_item.xml"); +} + +LLInventoryGalleryItem::~LLInventoryGalleryItem() +{ +} + +BOOL LLInventoryGalleryItem::postBuild() +{ + mNameText = getChild("item_name"); + + mTextBgPanel = getChild("text_bg_panel"); + mHidden = false; + return TRUE; +} + +void LLInventoryGalleryItem::setType(LLAssetType::EType type) +{ + mType = type; + mIsFolder = (mType == LLAssetType::AT_CATEGORY); + + std::string icon_name = LLInventoryIcon::getIconName(mType); + if(mIsFolder) + { + mSortGroup = SG_NORMAL_FOLDER; + LLViewerInventoryCategory * cat = gInventory.getCategory(mUUID); + if (cat) + { + LLFolderType::EType preferred_type = cat->getPreferredType(); + icon_name = LLViewerFolderType::lookupIconName(preferred_type); + + if (preferred_type == LLFolderType::FT_TRASH) + { + mSortGroup = SG_TRASH_FOLDER; + } + else if(LLFolderType::lookupIsProtectedType(cat->getPreferredType())) + { + mSortGroup = SG_SYSTEM_FOLDER; + } + } + } + + getChild("item_type")->setValue(icon_name); +} + +void LLInventoryGalleryItem::setThumbnail(LLUUID id) +{ + mDefaultImage = id.isNull(); + if(mDefaultImage) + { + getChild("preview_thumbnail")->setValue("Thumbnail_Fallback"); + } + else + { + getChild("preview_thumbnail")->setValue(id); + } +} + +void LLInventoryGalleryItem::draw() +{ + LLPanel::draw(); + + // Draw border + LLUIColor border_color = LLUIColorTable::instance().getColor(mSelected ? "MenuItemHighlightBgColor" : "TextFgTentativeColor", LLColor4::white); + LLRect border = getChildView("preview_thumbnail")->getRect(); + border.mRight = border.mRight + 1; + gl_rect_2d(border, border_color.get(), FALSE); +} + +void LLInventoryGalleryItem::setName(std::string name) +{ + mNameText->setText(name); + mNameText->setToolTip(name); + mName = name; +} + +void LLInventoryGalleryItem::setSelected(bool value) +{ + mSelected = value; + mTextBgPanel->setBackgroundVisible(value); +} + +BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) +{ + setFocus(TRUE); + return LLUICtrl::handleMouseDown(x, y, mask); +} + +BOOL LLInventoryGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + setFocus(TRUE); + return LLUICtrl::handleRightMouseDown(x, y, mask); +} + +BOOL LLInventoryGalleryItem::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + if (mIsFolder && mGallery) + { + mGallery->setRootFolder(mUUID); + } + else + { + LLInvFVBridgeAction::doAction(mUUID,&gInventory); + //todo: some item types require different handling + } + + return TRUE; +} + -- cgit v1.2.3 From d6a11416ec524420b6a6ac298b7b093cb24e9ec9 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 22 Mar 2023 01:20:22 +0200 Subject: SL-19379 WIP handle updated thumbnails in Gallery mode --- indra/newview/llinventorygallery.cpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index b5fd3aaece..132f294729 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -576,6 +576,14 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) { addToGallery(item); } + + if (mCategoriesObserver == NULL) + { + mCategoriesObserver = new LLInventoryCategoriesObserver(); + gInventory.addObserver(mCategoriesObserver); + } + mCategoriesObserver->addCategory(item_id, + boost::bind(&LLInventoryGallery::updateItemThumbnail, this, item_id), true); } void LLInventoryGallery::updateRemovedItem(LLUUID item_id) @@ -583,6 +591,8 @@ void LLInventoryGallery::updateRemovedItem(LLUUID item_id) gallery_item_map_t::iterator item_iter = mItemMap.find(item_id); if (item_iter != mItemMap.end()) { + mCategoriesObserver->removeCategory(item_id); + LLInventoryGalleryItem* item = item_iter->second; deselectItem(item_id); @@ -611,6 +621,26 @@ void LLInventoryGallery::updateChangedItemName(LLUUID item_id, std::string name) } } +void LLInventoryGallery::updateItemThumbnail(LLUUID item_id) +{ + LLInventoryObject* obj = gInventory.getObject(item_id); + if (!obj) + { + return; + } + LLUUID thumbnail_id = obj->getThumbnailUUID(); + + if ((LLAssetType::AT_CATEGORY == obj->getType()) && thumbnail_id.isNull()) + { + thumbnail_id = getOutfitImageID(item_id); + } + + if (mItemMap[item_id]) + { + mItemMap[item_id]->setThumbnail(thumbnail_id); + } +} + void LLInventoryGallery::onChangeItemSelection(const LLUUID& category_id) { if (mSelectedItemID == category_id) -- cgit v1.2.3 From 24b41ee746ccc6b5dd637b8704dc7ec819434605 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 22 Mar 2023 22:15:46 +0200 Subject: SL-19379 WIP basic drag and drop handling --- indra/newview/llinventorygallery.cpp | 911 ++++++++++++++++++++++++++++++++++- 1 file changed, 908 insertions(+), 3 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 132f294729..a3a1fbcc16 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -33,17 +33,38 @@ #include "lliconctrl.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" +#include "llinventoryicon.h" #include "llinventorymodel.h" #include "llthumbnailctrl.h" #include "lltextbox.h" #include "llviewerfoldertype.h" -#include "llinventoryicon.h" +#include "llagent.h" +#include "llappearancemgr.h" +#include "llenvironment.h" +#include "llfriendcard.h" +#include "llgesturemgr.h" +#include "llmarketplacefunctions.h" +#include "lltrans.h" +#include "llviewermessage.h" +#include "llviewerobjectlist.h" +#include "llvoavatarself.h" static LLPanelInjector t_inventory_gallery("inventory_gallery"); const S32 GALLERY_ITEMS_PER_ROW_MIN = 2; +// Helper dnd functions +BOOL baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, EDragAndDropType cargo_type, + void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); +BOOL dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, BOOL drop, std::string& tooltip_msg, BOOL is_link); +BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg, BOOL user_confirm); +void dropToMyOutfits(LLInventoryCategory* inv_cat); + +//----------------------------- +// LLInventoryGallery +//----------------------------- + LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) : LLPanel(), mScrollPanel(NULL), @@ -64,6 +85,8 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mIsInitialized(false) { updateGalleryWidth(); + + mCategoriesObserver = new LLInventoryCategoriesObserver(); } LLInventoryGallery::Params::Params() @@ -147,11 +170,12 @@ void LLInventoryGallery::updateRootFolder() gInventory.removeObserver(mCategoriesObserver); } delete mCategoriesObserver; + + mCategoriesObserver = new LLInventoryCategoriesObserver(); } { mRootChangedSignal(); - mCategoriesObserver = new LLInventoryCategoriesObserver(); gInventory.addObserver(mCategoriesObserver); // Start observing changes in selected category. @@ -705,7 +729,7 @@ void LLInventoryGallery::refreshList(const LLUUID& category_id) updateChangedItemName(*items_iter, obj->getName()); } - + updateMessageVisibility(); } void LLInventoryGallery::computeDifference( @@ -826,6 +850,24 @@ bool LLInventoryGallery::isForwardAvailable() { return (!mForwardFolders.empty() && (mFolderID != mForwardFolders.back())); } + +BOOL LLInventoryGallery::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, void* cargo_data, + EAcceptance* accept, std::string& tooltip_msg) +{ + // have children handle it first + BOOL handled = LLView::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, + accept, tooltip_msg); + + // when drop is not handled by child, it should be handled by the root folder . + if (!handled || (*accept == ACCEPT_NO)) + { + handled = baseHandleDragAndDrop(mFolderID, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + + return handled; +} + //----------------------------- // LLInventoryGalleryItem //----------------------------- @@ -952,3 +994,866 @@ BOOL LLInventoryGalleryItem::handleDoubleClick(S32 x, S32 y, MASK mask) return TRUE; } +BOOL LLInventoryGalleryItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + if (!mIsFolder) + { + return FALSE; + } + return baseHandleDragAndDrop(mUUID, drop, cargo_type, cargo_data, accept, tooltip_msg); +} + +//----------------------------- +// Helper drag&drop functions +//----------------------------- + +BOOL baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; + + BOOL accepted = FALSE; + switch(cargo_type) + { + case DAD_TEXTURE: + case DAD_SOUND: + case DAD_CALLINGCARD: + case DAD_LANDMARK: + case DAD_SCRIPT: + case DAD_CLOTHING: + case DAD_OBJECT: + case DAD_NOTECARD: + case DAD_BODYPART: + case DAD_ANIMATION: + case DAD_GESTURE: + case DAD_MESH: + case DAD_SETTINGS: + accepted = dragItemIntoFolder(dest_id, inv_item, drop, tooltip_msg, true); + break; + case DAD_LINK: + // DAD_LINK type might mean one of two asset types: AT_LINK or AT_LINK_FOLDER. + // If we have an item of AT_LINK_FOLDER type we should process the linked + // category being dragged or dropped into folder. + if (inv_item && LLAssetType::AT_LINK_FOLDER == inv_item->getActualType()) + { + LLInventoryCategory* linked_category = gInventory.getCategory(inv_item->getLinkedUUID()); + if (linked_category) + { + accepted = dragCategoryIntoFolder(dest_id, (LLInventoryCategory*)linked_category, drop, tooltip_msg, TRUE); + } + } + else + { + accepted = dragItemIntoFolder(dest_id, inv_item, drop, tooltip_msg, TRUE); + } + break; + case DAD_CATEGORY: + if (LLFriendCardsManager::instance().isAnyFriendCategory(dest_id)) + { + accepted = FALSE; + } + else + { + accepted = dragCategoryIntoFolder(dest_id, (LLInventoryCategory*)cargo_data, drop, tooltip_msg, FALSE); + } + break; + case DAD_ROOT_CATEGORY: + case DAD_NONE: + break; + default: + LL_WARNS() << "Unhandled cargo type for drag&drop " << cargo_type << LL_ENDL; + break; + } + if (accepted) + { + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + return accepted; +} + +// copy of LLFolderBridge::dragItemIntoFolder +BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg, BOOL user_confirm) +{ + LLViewerInventoryCategory * cat = gInventory.getCategory(folder_id); + if (!cat) + { + return FALSE; + } + LLInventoryModel* model = &gInventory; + + if (!model || !inv_item) return FALSE; + + // cannot drag into library + if((gInventory.getRootFolderID() != folder_id) && !model->isObjectDescendentOf(folder_id, gInventory.getRootFolderID())) + { + return FALSE; + } + if (!isAgentAvatarValid()) return FALSE; + + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + + const BOOL move_is_into_current_outfit = (folder_id == current_outfit_id); + const BOOL move_is_into_favorites = (folder_id == favorites_id); + const BOOL move_is_into_my_outfits = (folder_id == my_outifts_id) || model->isObjectDescendentOf(folder_id, my_outifts_id); + const BOOL move_is_into_outfit = move_is_into_my_outfits || (cat && cat->getPreferredType()==LLFolderType::FT_OUTFIT); + const BOOL move_is_into_landmarks = (folder_id == landmarks_id) || model->isObjectDescendentOf(folder_id, landmarks_id); + const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(folder_id, marketplacelistings_id); + const BOOL move_is_from_marketplacelistings = model->isObjectDescendentOf(inv_item->getUUID(), marketplacelistings_id); + + LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); + BOOL accept = FALSE; + LLViewerObject* object = NULL; + if(LLToolDragAndDrop::SOURCE_AGENT == source) + { + const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + + const BOOL move_is_into_trash = (folder_id == trash_id) || model->isObjectDescendentOf(folder_id, trash_id); + const BOOL move_is_outof_current_outfit = LLAppearanceMgr::instance().getIsInCOF(inv_item->getUUID()); + + //-------------------------------------------------------------------------------- + // Determine if item can be moved. + // + + BOOL is_movable = TRUE; + + switch (inv_item->getActualType()) + { + case LLAssetType::AT_CATEGORY: + is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType()); + break; + default: + break; + } + // Can't explicitly drag things out of the COF. + if (move_is_outof_current_outfit) + { + is_movable = FALSE; + } + if (move_is_into_trash) + { + is_movable &= inv_item->getIsLinkType() || !get_is_item_worn(inv_item->getUUID()); + } + if (is_movable) + { + // Don't allow creating duplicates in the Calling Card/Friends + // subfolders, see bug EXT-1599. Check is item direct descendent + // of target folder and forbid item's movement if it so. + // Note: isItemDirectDescendentOfCategory checks if + // passed category is in the Calling Card/Friends folder + is_movable &= !LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(inv_item, cat); + } + + // + //-------------------------------------------------------------------------------- + + //-------------------------------------------------------------------------------- + // Determine if item can be moved & dropped + // Note: if user_confirm is false, we already went through those accept logic test and can skip them + + accept = TRUE; + + if (user_confirm && !is_movable) + { + accept = FALSE; + } + else if (user_confirm && (folder_id == inv_item->getParentUUID()) && !move_is_into_favorites) + { + accept = FALSE; + } + else if (user_confirm && (move_is_into_current_outfit || move_is_into_outfit)) + { + accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); + } + else if (user_confirm && (move_is_into_favorites || move_is_into_landmarks)) + { + accept = can_move_to_landmarks(inv_item); + } + else if (user_confirm && move_is_into_marketplacelistings) + { + //disable dropping in or out of marketplace for now + return FALSE; + + /*const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(marketplacelistings_id, folder_id); + LLViewerInventoryCategory * dest_folder = cat; + accept = can_move_item_to_marketplace(master_folder, dest_folder, inv_item, tooltip_msg, LLToolDragAndDrop::instance().getCargoCount() - LLToolDragAndDrop::instance().getCargoIndex());*/ + } + + // Check that the folder can accept this item based on folder/item type compatibility (e.g. stock folder compatibility) + if (user_confirm && accept) + { + LLViewerInventoryCategory * dest_folder = cat; + accept = dest_folder->acceptItem(inv_item); + } + + LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); + + if (accept && drop) + { + if (inv_item->getType() == LLAssetType::AT_GESTURE + && LLGestureMgr::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash) + { + LLGestureMgr::instance().deactivateGesture(inv_item->getUUID()); + } + // If an item is being dragged between windows, unselect everything in the active window + // so that we don't follow the selection to its new location (which is very annoying). + // RN: a better solution would be to deselect automatically when an item is moved + // and then select any item that is dropped only in the panel that it is dropped in + if (active_panel) + { + active_panel->unSelectAll(); + } + // Dropping in or out of marketplace needs (sometimes) confirmation + if (user_confirm && (move_is_from_marketplacelistings || move_is_into_marketplacelistings)) + { + //disable dropping in or out of marketplace for now + return FALSE; + } + + //-------------------------------------------------------------------------------- + // Destination folder logic + // + + // FAVORITES folder + // (copy the item) + else if (move_is_into_favorites) + { + copy_inventory_item( + gAgent.getID(), + inv_item->getPermissions().getOwner(), + inv_item->getUUID(), + folder_id, + std::string(), + LLPointer(NULL)); + } + // CURRENT OUTFIT or OUTFIT folder + // (link the item) + else if (move_is_into_current_outfit || move_is_into_outfit) + { + if (move_is_into_current_outfit) + { + LLAppearanceMgr::instance().wearItemOnAvatar(inv_item->getUUID(), true, true); + } + else + { + LLPointer cb = NULL; + link_inventory_object(folder_id, LLConstPointer(inv_item), cb); + } + } + // MARKETPLACE LISTINGS folder + // Move the item + else if (move_is_into_marketplacelistings) + { + //move_item_to_marketplacelistings(inv_item, mUUID); + return FALSE; + } + // NORMAL or TRASH folder + // (move the item, restamp if into trash) + else + { + // set up observer to select item once drag and drop from inbox is complete + if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX))) + { + set_dad_inbox_object(inv_item->getUUID()); + } + + gInventory.changeItemParent((LLViewerInventoryItem*)inv_item, folder_id, move_is_into_trash); + } + + if (move_is_from_marketplacelistings) + { + // If we move from an active (listed) listing, checks that it's still valid, if not, unlist + /*LLUUID version_folder_id = LLMarketplaceData::instance().getActiveFolder(from_folder_uuid); + if (version_folder_id.notNull()) + { + LLMarketplaceValidator::getInstance()->validateMarketplaceListings( + version_folder_id, + [version_folder_id](bool result) + { + if (!result) + { + LLMarketplaceData::instance().activateListing(version_folder_id, false); + } + }); + }*/ + return FALSE; + } + + // + //-------------------------------------------------------------------------------- + } + } + else if (LLToolDragAndDrop::SOURCE_WORLD == source) + { + // Make sure the object exists. If we allowed dragging from + // anonymous objects, it would be possible to bypass + // permissions. + object = gObjectList.findObject(inv_item->getParentUUID()); + if (!object) + { + LL_INFOS() << "Object not found for drop." << LL_ENDL; + return FALSE; + } + + // coming from a task. Need to figure out if the person can + // move/copy this item. + LLPermissions perm(inv_item->getPermissions()); + if ((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) + && perm.allowTransferTo(gAgent.getID()))) + // || gAgent.isGodlike()) + { + accept = TRUE; + } + else if(object->permYouOwner()) + { + // If the object cannot be copied, but the object the + // inventory is owned by the agent, then the item can be + // moved from the task to agent inventory. + accept = TRUE; + } + + // Don't allow placing an original item into Current Outfit or an outfit folder + // because they must contain only links to wearable items. + if (move_is_into_current_outfit || move_is_into_outfit) + { + accept = FALSE; + } + // Don't allow to move a single item to Favorites or Landmarks + // if it is not a landmark or a link to a landmark. + else if ((move_is_into_favorites || move_is_into_landmarks) + && !can_move_to_landmarks(inv_item)) + { + accept = FALSE; + } + else if (move_is_into_marketplacelistings) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + + if (accept && drop) + { + //todo: dnd from SOURCE_WORLD + + /*boost::shared_ptr move_inv (new LLMoveInv()); + move_inv->mObjectID = inv_item->getParentUUID(); + std::pair item_pair(folder_id, inv_item->getUUID()); + move_inv->mMoveList.push_back(item_pair); + move_inv->mCallback = NULL; + move_inv->mUserData = NULL; + if(is_move) + { + warn_move_inventory(object, move_inv); + } + else + { + // store dad inventory item to select added one later. See EXT-4347 + set_dad_inventory_item(inv_item, folder_id); + + LLNotification::Params params("MoveInventoryFromObject"); + params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); + LLNotifications::instance().forceResponse(params, 0); + }*/ + } + } + else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) + { + if (move_is_into_marketplacelistings) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + else if ((inv_item->getActualType() == LLAssetType::AT_SETTINGS) && !LLEnvironment::instance().isInventoryEnabled()) + { + tooltip_msg = LLTrans::getString("NoEnvironmentSettings"); + accept = FALSE; + } + else + { + // Don't allow placing an original item from a notecard to Current Outfit or an outfit folder + // because they must contain only links to wearable items. + accept = !(move_is_into_current_outfit || move_is_into_outfit); + } + + if (accept && drop) + { + copy_inventory_from_notecard(folder_id, // Drop to the chosen destination folder + LLToolDragAndDrop::getInstance()->getObjectID(), + LLToolDragAndDrop::getInstance()->getSourceID(), + inv_item); + } + } + else if(LLToolDragAndDrop::SOURCE_LIBRARY == source) + { + LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item; + if(item && item->isFinished()) + { + accept = TRUE; + + if (move_is_into_marketplacelistings) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + else if (move_is_into_current_outfit || move_is_into_outfit) + { + accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); + } + // Don't allow to move a single item to Favorites or Landmarks + // if it is not a landmark or a link to a landmark. + else if (move_is_into_favorites || move_is_into_landmarks) + { + accept = can_move_to_landmarks(inv_item); + } + + if (accept && drop) + { + // FAVORITES folder + // (copy the item) + if (move_is_into_favorites) + { + copy_inventory_item( + gAgent.getID(), + inv_item->getPermissions().getOwner(), + inv_item->getUUID(), + folder_id, + std::string(), + LLPointer(NULL)); + } + // CURRENT OUTFIT or OUTFIT folder + // (link the item) + else if (move_is_into_current_outfit || move_is_into_outfit) + { + if (move_is_into_current_outfit) + { + LLAppearanceMgr::instance().wearItemOnAvatar(inv_item->getUUID(), true, true); + } + else + { + LLPointer cb = NULL; + link_inventory_object(folder_id, LLConstPointer(inv_item), cb); + } + } + else + { + copy_inventory_item( + gAgent.getID(), + inv_item->getPermissions().getOwner(), + inv_item->getUUID(), + folder_id, + std::string(), + LLPointer(NULL)); + } + } + } + } + else + { + LL_WARNS() << "unhandled drag source" << LL_ENDL; + } + return accept; +} + +// copy of LLFolderBridge::dragCategoryIntoFolder +BOOL dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, + BOOL drop, std::string& tooltip_msg, BOOL is_link) +{ + BOOL user_confirm = TRUE; + LLInventoryModel* model = &gInventory; + LLViewerInventoryCategory * dest_cat = gInventory.getCategory(dest_id); + if (!dest_cat) + { + return FALSE; + } + + if (!inv_cat) return FALSE; // shouldn't happen, but in case item is incorrectly parented in which case inv_cat will be NULL + + if (!isAgentAvatarValid()) return FALSE; + // cannot drag into library + if((gInventory.getRootFolderID() != dest_id) && !model->isObjectDescendentOf(dest_id, gInventory.getRootFolderID())) + { + return FALSE; + } + + const LLUUID &cat_id = inv_cat->getUUID(); + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + //const LLUUID from_folder_uuid = inv_cat->getParentUUID(); + + const BOOL move_is_into_current_outfit = (dest_id == current_outfit_id); + const BOOL move_is_into_marketplacelistings = model->isObjectDescendentOf(dest_id, marketplacelistings_id); + const BOOL move_is_from_marketplacelistings = model->isObjectDescendentOf(cat_id, marketplacelistings_id); + + // check to make sure source is agent inventory, and is represented there. + LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); + const BOOL is_agent_inventory = (model->getCategory(cat_id) != NULL) + && (LLToolDragAndDrop::SOURCE_AGENT == source); + + BOOL accept = FALSE; + + if (is_agent_inventory) + { + const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK); + const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); + + const BOOL move_is_into_trash = (dest_id == trash_id) || model->isObjectDescendentOf(dest_id, trash_id); + const BOOL move_is_into_my_outfits = (dest_id == my_outifts_id) || model->isObjectDescendentOf(dest_id, my_outifts_id); + const BOOL move_is_into_outfit = move_is_into_my_outfits || (dest_cat && dest_cat->getPreferredType()==LLFolderType::FT_OUTFIT); + const BOOL move_is_into_current_outfit = (dest_cat && dest_cat->getPreferredType()==LLFolderType::FT_CURRENT_OUTFIT); + const BOOL move_is_into_landmarks = (dest_id == landmarks_id) || model->isObjectDescendentOf(dest_id, landmarks_id); + const BOOL move_is_into_lost_and_found = model->isObjectDescendentOf(dest_id, lost_and_found_id); + + //-------------------------------------------------------------------------------- + // Determine if folder can be moved. + // + + BOOL is_movable = TRUE; + + if (is_movable && (marketplacelistings_id == cat_id)) + { + is_movable = FALSE; + tooltip_msg = LLTrans::getString("TooltipOutboxCannotMoveRoot"); + } + if (is_movable && move_is_from_marketplacelistings) + //&& LLMarketplaceData::instance().getActivationState(cat_id)) + { + // If the incoming folder is listed and active (and is therefore either the listing or the version folder), + // then moving is *not* allowed + is_movable = FALSE; + tooltip_msg = LLTrans::getString("TooltipOutboxDragActive"); + } + if (is_movable && (dest_id == cat_id)) + { + is_movable = FALSE; + tooltip_msg = LLTrans::getString("TooltipDragOntoSelf"); + } + if (is_movable && (model->isObjectDescendentOf(dest_id, cat_id))) + { + is_movable = FALSE; + tooltip_msg = LLTrans::getString("TooltipDragOntoOwnChild"); + } + if (is_movable && LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())) + { + is_movable = FALSE; + // tooltip? + } + + U32 max_items_to_wear = gSavedSettings.getU32("WearFolderLimit"); + if (is_movable && move_is_into_outfit) + { + if (dest_id == my_outifts_id) + { + if (source != LLToolDragAndDrop::SOURCE_AGENT || move_is_from_marketplacelistings) + { + tooltip_msg = LLTrans::getString("TooltipOutfitNotInInventory"); + is_movable = false; + } + else if (can_move_to_my_outfits(model, inv_cat, max_items_to_wear)) + { + is_movable = true; + } + else + { + tooltip_msg = LLTrans::getString("TooltipCantCreateOutfit"); + is_movable = false; + } + } + else if(dest_cat && dest_cat->getPreferredType() == LLFolderType::FT_NONE) + { + is_movable = ((inv_cat->getPreferredType() == LLFolderType::FT_NONE) || (inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT)); + } + else + { + is_movable = false; + } + } + if(is_movable && move_is_into_current_outfit && is_link) + { + is_movable = FALSE; + } + if (is_movable && move_is_into_lost_and_found) + { + is_movable = FALSE; + } + if (is_movable && (dest_id == model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE))) + { + is_movable = FALSE; + // tooltip? + } + if (is_movable && (dest_cat->getPreferredType() == LLFolderType::FT_MARKETPLACE_STOCK)) + { + // One cannot move a folder into a stock folder + is_movable = FALSE; + // tooltip? + } + + LLInventoryModel::cat_array_t descendent_categories; + LLInventoryModel::item_array_t descendent_items; + if (is_movable) + { + model->collectDescendents(cat_id, descendent_categories, descendent_items, FALSE); + for (S32 i=0; i < descendent_categories.size(); ++i) + { + LLInventoryCategory* category = descendent_categories[i]; + if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) + { + // Can't move "special folders" (e.g. Textures Folder). + is_movable = FALSE; + break; + } + } + } + if (is_movable + && move_is_into_current_outfit + && descendent_items.size() > max_items_to_wear) + { + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false); + gInventory.collectDescendentsIf(cat_id, + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + not_worn); + + if (items.size() > max_items_to_wear) + { + // Can't move 'large' folders into current outfit: MAINT-4086 + is_movable = FALSE; + LLStringUtil::format_map_t args; + args["AMOUNT"] = llformat("%d", max_items_to_wear); + tooltip_msg = LLTrans::getString("TooltipTooManyWearables",args); + } + } + if (is_movable && move_is_into_trash) + { + for (S32 i=0; i < descendent_items.size(); ++i) + { + LLInventoryItem* item = descendent_items[i]; + if (get_is_item_worn(item->getUUID())) + { + is_movable = FALSE; + break; // It's generally movable, but not into the trash. + } + } + } + if (is_movable && move_is_into_landmarks) + { + for (S32 i=0; i < descendent_items.size(); ++i) + { + LLViewerInventoryItem* item = descendent_items[i]; + + // Don't move anything except landmarks and categories into Landmarks folder. + // We use getType() instead of getActua;Type() to allow links to landmarks and folders. + if (LLAssetType::AT_LANDMARK != item->getType() && LLAssetType::AT_CATEGORY != item->getType()) + { + is_movable = FALSE; + break; // It's generally movable, but not into Landmarks. + } + } + } + + if (is_movable && move_is_into_marketplacelistings) + { + const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(marketplacelistings_id, dest_id); + LLViewerInventoryCategory * dest_folder = dest_cat; + S32 bundle_size = (drop ? 1 : LLToolDragAndDrop::instance().getCargoCount()); + is_movable = can_move_folder_to_marketplace(master_folder, dest_folder, inv_cat, tooltip_msg, bundle_size); + } + + // + //-------------------------------------------------------------------------------- + + accept = is_movable; + + if (accept && drop) + { + // Dropping in or out of marketplace needs (sometimes) confirmation + if (user_confirm && (move_is_from_marketplacelistings || move_is_into_marketplacelistings)) + { + //disable dropping in or out of marketplace for now + return FALSE; + } + // Look for any gestures and deactivate them + if (move_is_into_trash) + { + for (S32 i=0; i < descendent_items.size(); i++) + { + LLInventoryItem* item = descendent_items[i]; + if (item->getType() == LLAssetType::AT_GESTURE + && LLGestureMgr::instance().isGestureActive(item->getUUID())) + { + LLGestureMgr::instance().deactivateGesture(item->getUUID()); + } + } + } + + if (dest_id == my_outifts_id) + { + // Category can contains objects, + // create a new folder and populate it with links to original objects + dropToMyOutfits(inv_cat); + } + // if target is current outfit folder we use link + else if (move_is_into_current_outfit && + (inv_cat->getPreferredType() == LLFolderType::FT_NONE || + inv_cat->getPreferredType() == LLFolderType::FT_OUTFIT)) + { + // traverse category and add all contents to currently worn. + BOOL append = true; + LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, false, append); + } + else if (move_is_into_marketplacelistings) + { + //move_folder_to_marketplacelistings(inv_cat, dest_id); + } + else + { + if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX))) + { + set_dad_inbox_object(cat_id); + } + + // Reparent the folder and restamp children if it's moving + // into trash. + gInventory.changeCategoryParent( + (LLViewerInventoryCategory*)inv_cat, + dest_id, + move_is_into_trash); + } + if (move_is_from_marketplacelistings) + { + //disable dropping in or out of marketplace for now + return FALSE; + + // If we are moving a folder at the listing folder level (i.e. its parent is the marketplace listings folder) + /*if (from_folder_uuid == marketplacelistings_id) + { + // Clear the folder from the marketplace in case it is a listing folder + if (LLMarketplaceData::instance().isListed(cat_id)) + { + LLMarketplaceData::instance().clearListing(cat_id); + } + } + else + { + // If we move from within an active (listed) listing, checks that it's still valid, if not, unlist + LLUUID version_folder_id = LLMarketplaceData::instance().getActiveFolder(from_folder_uuid); + if (version_folder_id.notNull()) + { + LLMarketplaceValidator::getInstance()->validateMarketplaceListings( + version_folder_id, + [version_folder_id](bool result) + { + if (!result) + { + LLMarketplaceData::instance().activateListing(version_folder_id, false); + } + } + ); + } + // In all cases, update the listing we moved from so suffix are updated + update_marketplace_category(from_folder_uuid); + }*/ + } + } + } + else if (LLToolDragAndDrop::SOURCE_WORLD == source) + { + if (move_is_into_marketplacelistings) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + else + { + //todo: dnd from SOURCE_WORLD + accept = FALSE; + //accept = move_inv_category_world_to_agent(cat_id, mUUID, drop, NULL, NULL, filter); + } + } + else if (LLToolDragAndDrop::SOURCE_LIBRARY == source) + { + if (move_is_into_marketplacelistings) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + else + { + // Accept folders that contain complete outfits. + accept = move_is_into_current_outfit && LLAppearanceMgr::instance().getCanMakeFolderIntoOutfit(cat_id); + } + + if (accept && drop) + { + LLAppearanceMgr::instance().wearInventoryCategory(inv_cat, true, false); + } + } + + return accept; +} + +void outfitFolderCreatedCallback(LLUUID cat_source_id, LLUUID cat_dest_id) +{ + LLInventoryModel::cat_array_t* categories; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(cat_source_id, categories, items); + + LLInventoryObject::const_object_list_t link_array; + + + LLInventoryModel::item_array_t::iterator iter = items->begin(); + LLInventoryModel::item_array_t::iterator end = items->end(); + while (iter!=end) + { + const LLViewerInventoryItem* item = (*iter); + // By this point everything is supposed to be filtered, + // but there was a delay to create folder so something could have changed + LLInventoryType::EType inv_type = item->getInventoryType(); + if ((inv_type == LLInventoryType::IT_WEARABLE) || + (inv_type == LLInventoryType::IT_GESTURE) || + (inv_type == LLInventoryType::IT_ATTACHMENT) || + (inv_type == LLInventoryType::IT_OBJECT) || + (inv_type == LLInventoryType::IT_SNAPSHOT) || + (inv_type == LLInventoryType::IT_TEXTURE)) + { + link_array.push_back(LLConstPointer(item)); + } + iter++; + } + + if (!link_array.empty()) + { + LLPointer cb = NULL; + link_inventory_array(cat_dest_id, link_array, cb); + } +} + +void dropToMyOutfits(LLInventoryCategory* inv_cat) +{ + // make a folder in the My Outfits directory. + const LLUUID dest_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + + // Note: creation will take time, so passing folder id to callback is slightly unreliable, + // but so is collecting and passing descendants' ids + inventory_func_type func = boost::bind(&outfitFolderCreatedCallback, inv_cat->getUUID(), _1); + gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func); +} + -- cgit v1.2.3 From cc98d967796e552432a59c2ad81742ad55bff983 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 24 Mar 2023 00:06:15 +0200 Subject: SL-19379 WIP add drag and drop out of Gallery --- indra/newview/llinventorygallery.cpp | 43 +++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index a3a1fbcc16..86f60b5644 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -46,6 +46,7 @@ #include "llgesturemgr.h" #include "llmarketplacefunctions.h" #include "lltrans.h" +#include "llviewerassettype.h" #include "llviewermessage.h" #include "llviewerobjectlist.h" #include "llvoavatarself.h" @@ -970,7 +971,13 @@ void LLInventoryGalleryItem::setSelected(bool value) BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) { setFocus(TRUE); - return LLUICtrl::handleMouseDown(x, y, mask); + + gFocusMgr.setMouseCapture(this); + S32 screen_x; + S32 screen_y; + localPointToScreen(x, y, &screen_x, &screen_y ); + LLToolDragAndDrop::getInstance()->setDragStart(screen_x, screen_y); + return TRUE; } BOOL LLInventoryGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) @@ -979,6 +986,40 @@ BOOL LLInventoryGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) return LLUICtrl::handleRightMouseDown(x, y, mask); } +BOOL LLInventoryGalleryItem::handleMouseUp(S32 x, S32 y, MASK mask) +{ + if(hasMouseCapture()) + { + gFocusMgr.setMouseCapture(NULL); + return TRUE; + } + return LLPanel::handleMouseUp(x, y, mask); +} + +BOOL LLInventoryGalleryItem::handleHover(S32 x, S32 y, MASK mask) +{ + if(hasMouseCapture()) + { + S32 screen_x; + S32 screen_y; + const LLInventoryItem *item = gInventory.getItem(mUUID);; + + localPointToScreen(x, y, &screen_x, &screen_y ); + if(item && LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y)) + { + EDragAndDropType type = LLViewerAssetType::lookupDragAndDropType(item->getType()); + LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_LIBRARY; + if(item->getPermissions().getOwner() == gAgent.getID()) + { + src = LLToolDragAndDrop::SOURCE_AGENT; + } + LLToolDragAndDrop::getInstance()->beginDrag(type, item->getUUID(), src); + return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask ); + } + } + return LLUICtrl::handleHover(x,y,mask); +} + BOOL LLInventoryGalleryItem::handleDoubleClick(S32 x, S32 y, MASK mask) { if (mIsFolder && mGallery) -- cgit v1.2.3 From d733ee60ea1d7cd7a9259c188b7b942a41d24460 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 24 Mar 2023 12:56:57 +0200 Subject: SL-19379 WIP add double-click attach action for objects; add icon link overlays --- indra/newview/llinventorygallery.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 86f60b5644..c2594c1b87 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -458,7 +458,7 @@ void LLInventoryGallery::removeFromLastRow(LLInventoryGalleryItem* item) mItemPanels.pop_back(); } -LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id) +LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, bool is_link) { LLInventoryGalleryItem::Params giparams; LLInventoryGalleryItem* gitem = LLUICtrlFactory::create(giparams); @@ -469,7 +469,7 @@ LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, L gitem->setName(name); gitem->setUUID(item_id); gitem->setGallery(this); - gitem->setType(type); + gitem->setType(type, is_link); gitem->setThumbnail(thumbnail_id); return gitem; } @@ -593,7 +593,7 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) thumbnail_id = getOutfitImageID(item_id); } - LLInventoryGalleryItem* item = buildGalleryItem(obj->getName(), item_id, obj->getType(), thumbnail_id); + LLInventoryGalleryItem* item = buildGalleryItem(obj->getName(), item_id, obj->getType(), thumbnail_id, obj->getIsLinkType()); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::onChangeItemSelection, this, item_id)); @@ -902,7 +902,7 @@ BOOL LLInventoryGalleryItem::postBuild() return TRUE; } -void LLInventoryGalleryItem::setType(LLAssetType::EType type) +void LLInventoryGalleryItem::setType(LLAssetType::EType type, bool is_link) { mType = type; mIsFolder = (mType == LLAssetType::AT_CATEGORY); @@ -929,6 +929,7 @@ void LLInventoryGalleryItem::setType(LLAssetType::EType type) } getChild("item_type")->setValue(icon_name); + getChild("link_overlay")->setVisible(is_link); } void LLInventoryGalleryItem::setThumbnail(LLUUID id) @@ -1002,7 +1003,7 @@ BOOL LLInventoryGalleryItem::handleHover(S32 x, S32 y, MASK mask) { S32 screen_x; S32 screen_y; - const LLInventoryItem *item = gInventory.getItem(mUUID);; + const LLInventoryItem *item = gInventory.getItem(mUUID); localPointToScreen(x, y, &screen_x, &screen_y ); if(item && LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y)) @@ -1028,8 +1029,7 @@ BOOL LLInventoryGalleryItem::handleDoubleClick(S32 x, S32 y, MASK mask) } else { - LLInvFVBridgeAction::doAction(mUUID,&gInventory); - //todo: some item types require different handling + LLInvFVBridgeAction::doAction(mUUID, &gInventory); } return TRUE; -- cgit v1.2.3 From 3605d3164d83b966c5c4a330713092d05e8e5698 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 24 Mar 2023 13:58:29 +0200 Subject: SL-19379 WIP show localized folder names in Gallery --- indra/newview/llinventorygallery.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index c2594c1b87..2624640bb4 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -586,14 +586,19 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) return; } + std::string name = obj->getName(); LLUUID thumbnail_id = obj->getThumbnailUUID();; - if ((LLAssetType::AT_CATEGORY == obj->getType()) && thumbnail_id.isNull()) + if (LLAssetType::AT_CATEGORY == obj->getType()) { - thumbnail_id = getOutfitImageID(item_id); + name = get_localized_folder_name(item_id); + if(thumbnail_id.isNull()) + { + thumbnail_id = getOutfitImageID(item_id); + } } - - LLInventoryGalleryItem* item = buildGalleryItem(obj->getName(), item_id, obj->getType(), thumbnail_id, obj->getIsLinkType()); + + LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, obj->getIsLinkType()); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::onChangeItemSelection, this, item_id)); -- cgit v1.2.3 From 11b2f138cecc123c3e6876b56ea63c5fbd734d56 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 29 Mar 2023 04:28:07 +0300 Subject: SL-19502 Copying folders should copy thumbnails --- indra/newview/llinventorygallery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 2624640bb4..08836555d4 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1900,6 +1900,6 @@ void dropToMyOutfits(LLInventoryCategory* inv_cat) // Note: creation will take time, so passing folder id to callback is slightly unreliable, // but so is collecting and passing descendants' ids inventory_func_type func = boost::bind(&outfitFolderCreatedCallback, inv_cat->getUUID(), _1); - gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func); + gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func, inv_cat->getThumbnailUUID()); } -- cgit v1.2.3 From e5b8b799cc75f3b9cd259403c323cd47b59453d8 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 29 Mar 2023 13:51:40 +0300 Subject: SL-19379 WIP add basic context menu --- indra/newview/llinventorygallery.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 08836555d4..bfca22ba8a 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -27,8 +27,8 @@ #include "llviewerprecompiledheaders.h" #include "llinventorygallery.h" +#include "llinventorygallerymenu.h" -#include "llaccordionctrltab.h" #include "llcommonutils.h" #include "lliconctrl.h" #include "llinventorybridge.h" @@ -115,12 +115,14 @@ BOOL LLInventoryGallery::postBuild() LLPanel::Params params = LLPanel::getDefaultParams(); mGalleryPanel = LLUICtrlFactory::create(params); mMessageTextBox = getChild("empty_txt"); - + mInventoryGalleryMenu = new LLInventoryGalleryContextMenu(this); return TRUE; } LLInventoryGallery::~LLInventoryGallery() { + delete mInventoryGalleryMenu; + while (!mUnusedRowPanels.empty()) { LLPanel* panelp = mUnusedRowPanels.back(); @@ -600,7 +602,7 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, obj->getIsLinkType()); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); - + item->setRightMouseDownCallback(boost::bind(&LLInventoryGallery::showContextMenu, this, _1, _2, _3, item_id)); item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::onChangeItemSelection, this, item_id)); if (mGalleryCreated) { @@ -671,6 +673,16 @@ void LLInventoryGallery::updateItemThumbnail(LLUUID item_id) } } +void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id) +{ + if (mInventoryGalleryMenu && item_id.notNull()) + { + uuid_vec_t selected_uuids; + selected_uuids.push_back(item_id); + mInventoryGalleryMenu->show(ctrl, selected_uuids, x, y); + } +} + void LLInventoryGallery::onChangeItemSelection(const LLUUID& category_id) { if (mSelectedItemID == category_id) -- cgit v1.2.3 From c10eed08189161bab67cfc296b1891a989d5748d Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 29 Mar 2023 18:02:04 +0300 Subject: SL-19379 WIP allow change search type for Gallery --- indra/newview/llinventorygallery.cpp | 39 ++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index bfca22ba8a..8516ff37c2 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -83,7 +83,8 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mItemsInRow(p.items_in_row), mRowPanWidthFactor(p.row_panel_width_factor), mGalleryWidthFactor(p.gallery_width_factor), - mIsInitialized(false) + mIsInitialized(false), + mSearchType(LLInventoryFilter::SEARCHTYPE_NAME) { updateGalleryWidth(); @@ -473,6 +474,9 @@ LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, L gitem->setGallery(this); gitem->setType(type, is_link); gitem->setThumbnail(thumbnail_id); + gitem->setCreatorName(get_searchable_creator_name(&gInventory, item_id)); + gitem->setDescription(get_searchable_description(&gInventory, item_id)); + gitem->setAssetIDStr(get_searchable_UUID(&gInventory, item_id)); return gitem; } @@ -556,16 +560,43 @@ void LLInventoryGallery::applyFilter(LLInventoryGalleryItem* item, const std::st { if (!item) return; - std::string item_name = item->getItemName(); - LLStringUtil::toUpper(item_name); + std::string desc; + + switch(mSearchType) + { + case LLInventoryFilter::SEARCHTYPE_CREATOR: + desc = item->getCreatorName(); + break; + case LLInventoryFilter::SEARCHTYPE_DESCRIPTION: + desc = item->getDescription(); + break; + case LLInventoryFilter::SEARCHTYPE_UUID: + desc = item->getAssetIDStr(); + break; + case LLInventoryFilter::SEARCHTYPE_NAME: + default: + desc = item->getItemName(); + break; + } + + LLStringUtil::toUpper(desc); std::string cur_filter = filter_substring; LLStringUtil::toUpper(cur_filter); - bool hidden = (std::string::npos == item_name.find(cur_filter)); + bool hidden = (std::string::npos == desc.find(cur_filter)); item->setHidden(hidden); } +void LLInventoryGallery::setSearchType(LLInventoryFilter::ESearchType type) +{ + if(mSearchType != type) + { + mSearchType = type; + reArrangeRows(); + } +} + void LLInventoryGallery::getCurrentCategories(uuid_vec_t& vcur) { for (gallery_item_map_t::const_iterator iter = mItemMap.begin(); -- cgit v1.2.3 From 205d6ef5d6d05f5a429f987a78f45bbb2359404d Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 29 Mar 2023 20:51:58 +0300 Subject: SL-19379 WIP show wearable type icons --- indra/newview/llinventorygallery.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 8516ff37c2..e31b6b1527 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -461,7 +461,7 @@ void LLInventoryGallery::removeFromLastRow(LLInventoryGalleryItem* item) mItemPanels.pop_back(); } -LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, bool is_link) +LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, LLInventoryType::EType inventory_type, U32 flags, bool is_link) { LLInventoryGalleryItem::Params giparams; LLInventoryGalleryItem* gitem = LLUICtrlFactory::create(giparams); @@ -472,7 +472,7 @@ LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, L gitem->setName(name); gitem->setUUID(item_id); gitem->setGallery(this); - gitem->setType(type, is_link); + gitem->setType(type, inventory_type, flags, is_link); gitem->setThumbnail(thumbnail_id); gitem->setCreatorName(get_searchable_creator_name(&gInventory, item_id)); gitem->setDescription(get_searchable_description(&gInventory, item_id)); @@ -621,7 +621,8 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) std::string name = obj->getName(); LLUUID thumbnail_id = obj->getThumbnailUUID();; - + LLInventoryType::EType inventory_type(LLInventoryType::IT_CATEGORY); + U32 misc_flags = 0; if (LLAssetType::AT_CATEGORY == obj->getType()) { name = get_localized_folder_name(item_id); @@ -630,8 +631,17 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) thumbnail_id = getOutfitImageID(item_id); } } + else + { + LLInventoryItem* inv_item = gInventory.getItem(item_id); + if (inv_item) + { + inventory_type = inv_item->getInventoryType(); + misc_flags = inv_item->getFlags(); + } + } - LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, obj->getIsLinkType()); + LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getIsLinkType()); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); item->setRightMouseDownCallback(boost::bind(&LLInventoryGallery::showContextMenu, this, _1, _2, _3, item_id)); item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::onChangeItemSelection, this, item_id)); @@ -950,12 +960,12 @@ BOOL LLInventoryGalleryItem::postBuild() return TRUE; } -void LLInventoryGalleryItem::setType(LLAssetType::EType type, bool is_link) +void LLInventoryGalleryItem::setType(LLAssetType::EType type, LLInventoryType::EType inventory_type, U32 flags, bool is_link) { mType = type; mIsFolder = (mType == LLAssetType::AT_CATEGORY); - std::string icon_name = LLInventoryIcon::getIconName(mType); + std::string icon_name = LLInventoryIcon::getIconName(mType, inventory_type, flags); if(mIsFolder) { mSortGroup = SG_NORMAL_FOLDER; -- cgit v1.2.3 From a6b71d3b8234261f4ed3674017736d04649ea992 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 29 Mar 2023 21:20:39 +0300 Subject: SL-19379 WIP allow dnd folders --- indra/newview/llinventorygallery.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index e31b6b1527..ad4124ff5b 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1061,19 +1061,30 @@ BOOL LLInventoryGalleryItem::handleHover(S32 x, S32 y, MASK mask) { S32 screen_x; S32 screen_y; - const LLInventoryItem *item = gInventory.getItem(mUUID); - localPointToScreen(x, y, &screen_x, &screen_y ); - if(item && LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y)) + + if(LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y)) { - EDragAndDropType type = LLViewerAssetType::lookupDragAndDropType(item->getType()); - LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_LIBRARY; - if(item->getPermissions().getOwner() == gAgent.getID()) + const LLInventoryItem *item = gInventory.getItem(mUUID); + if(item) + { + EDragAndDropType type = LLViewerAssetType::lookupDragAndDropType(item->getType()); + LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_LIBRARY; + if(item->getPermissions().getOwner() == gAgent.getID()) + { + src = LLToolDragAndDrop::SOURCE_AGENT; + } + LLToolDragAndDrop::getInstance()->beginDrag(type, item->getUUID(), src); + return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask ); + } + + const LLInventoryCategory *cat = gInventory.getCategory(mUUID); + if(cat && gInventory.isObjectDescendentOf(mUUID, gInventory.getRootFolderID()) + && !LLFolderType::lookupIsProtectedType((cat)->getPreferredType())) { - src = LLToolDragAndDrop::SOURCE_AGENT; + LLToolDragAndDrop::getInstance()->beginDrag(LLViewerAssetType::lookupDragAndDropType(cat->getType()), cat->getUUID(), LLToolDragAndDrop::SOURCE_AGENT); + return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask ); } - LLToolDragAndDrop::getInstance()->beginDrag(type, item->getUUID(), src); - return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask ); } } return LLUICtrl::handleHover(x,y,mask); -- cgit v1.2.3 From c15ee792a7248cf141abb3ae6a26b33a5aca1ed7 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 30 Mar 2023 15:04:49 +0300 Subject: SL-19379 WIP allow hide link items in search result --- indra/newview/llinventorygallery.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index ad4124ff5b..0fc7816f59 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -84,7 +84,8 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mRowPanWidthFactor(p.row_panel_width_factor), mGalleryWidthFactor(p.gallery_width_factor), mIsInitialized(false), - mSearchType(LLInventoryFilter::SEARCHTYPE_NAME) + mSearchType(LLInventoryFilter::SEARCHTYPE_NAME), + mSearchLinks(true) { updateGalleryWidth(); @@ -561,6 +562,11 @@ void LLInventoryGallery::applyFilter(LLInventoryGalleryItem* item, const std::st if (!item) return; std::string desc; + if(!mSearchLinks && item->isLink()) + { + item->setHidden(true); + return; + } switch(mSearchType) { @@ -593,6 +599,18 @@ void LLInventoryGallery::setSearchType(LLInventoryFilter::ESearchType type) if(mSearchType != type) { mSearchType = type; + if(!mFilterSubString.empty()) + { + reArrangeRows(); + } + } +} + +void LLInventoryGallery::toggleSearchLinks() +{ + mSearchLinks = !mSearchLinks; + if(!mFilterSubString.empty()) + { reArrangeRows(); } } @@ -940,6 +958,7 @@ LLInventoryGalleryItem::LLInventoryGalleryItem(const Params& p) mName(""), mUUID(LLUUID()), mIsFolder(true), + mIsLink(false), mGallery(NULL), mType(LLAssetType::AT_NONE), mSortGroup(SG_ITEM) @@ -964,6 +983,7 @@ void LLInventoryGalleryItem::setType(LLAssetType::EType type, LLInventoryType::E { mType = type; mIsFolder = (mType == LLAssetType::AT_CATEGORY); + mIsLink = is_link; std::string icon_name = LLInventoryIcon::getIconName(mType, inventory_type, flags); if(mIsFolder) -- cgit v1.2.3 From 81d69cf84decb84bb7d65057063a19cb6c9fa6f5 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 31 Mar 2023 13:40:59 +0300 Subject: SL-19379 WIP add worn suffix, use bold font style for worn items and italic for links --- indra/newview/llinventorygallery.cpp | 87 ++++++++++++++++++++++++++++++++++-- 1 file changed, 83 insertions(+), 4 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 0fc7816f59..8c49cd5a4b 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -243,6 +243,9 @@ void LLInventoryGallery::initGallery() } reArrangeRows(); mGalleryCreated = true; + + const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + mCategoriesObserver->addCategory(cof, boost::bind(&LLInventoryGallery::onCOFChanged, this)); } } @@ -462,7 +465,7 @@ void LLInventoryGallery::removeFromLastRow(LLInventoryGalleryItem* item) mItemPanels.pop_back(); } -LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, LLInventoryType::EType inventory_type, U32 flags, bool is_link) +LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, LLInventoryType::EType inventory_type, U32 flags, bool is_link, bool is_worn) { LLInventoryGalleryItem::Params giparams; LLInventoryGalleryItem* gitem = LLUICtrlFactory::create(giparams); @@ -475,6 +478,7 @@ LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, L gitem->setGallery(this); gitem->setType(type, inventory_type, flags, is_link); gitem->setThumbnail(thumbnail_id); + gitem->setWorn(is_worn); gitem->setCreatorName(get_searchable_creator_name(&gInventory, item_id)); gitem->setDescription(get_searchable_description(&gInventory, item_id)); gitem->setAssetIDStr(get_searchable_UUID(&gInventory, item_id)); @@ -641,6 +645,7 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) LLUUID thumbnail_id = obj->getThumbnailUUID();; LLInventoryType::EType inventory_type(LLInventoryType::IT_CATEGORY); U32 misc_flags = 0; + bool is_worn = false; if (LLAssetType::AT_CATEGORY == obj->getType()) { name = get_localized_folder_name(item_id); @@ -656,10 +661,11 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) { inventory_type = inv_item->getInventoryType(); misc_flags = inv_item->getFlags(); + is_worn = LLAppearanceMgr::instance().isLinkedInCOF(item_id); } } - - LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getIsLinkType()); + + LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getIsLinkType(), is_worn); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); item->setRightMouseDownCallback(boost::bind(&LLInventoryGallery::showContextMenu, this, _1, _2, _3, item_id)); item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::onChangeItemSelection, this, item_id)); @@ -712,6 +718,19 @@ void LLInventoryGallery::updateChangedItemName(LLUUID item_id, std::string name) } } +void LLInventoryGallery::updateWornItem(LLUUID item_id, bool is_worn) +{ + gallery_item_map_t::iterator iter = mItemMap.find(item_id); + if (iter != mItemMap.end()) + { + LLInventoryGalleryItem* item = iter->second; + if (item) + { + item->setWorn(is_worn); + } + } +} + void LLInventoryGallery::updateItemThumbnail(LLUUID item_id) { LLInventoryObject* obj = gInventory.getObject(item_id); @@ -836,6 +855,46 @@ void LLInventoryGallery::computeDifference( LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved); } +void LLInventoryGallery::onCOFChanged() +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + + gInventory.collectDescendents( + LLAppearanceMgr::instance().getCOF(), + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH); + + uuid_vec_t vnew; + uuid_vec_t vadded; + uuid_vec_t vremoved; + + for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); + iter != item_array.end(); + ++iter) + { + vnew.push_back((*iter)->getLinkedUUID()); + } + + // We need to update only items that were added or removed from COF. + LLCommonUtils::computeDifference(vnew, mCOFLinkedItems, vadded, vremoved); + + mCOFLinkedItems = vnew; + + for (uuid_vec_t::const_iterator iter = vadded.begin(); + iter != vadded.end(); + ++iter) + { + updateWornItem(*iter, true); + } + + for (uuid_vec_t::const_iterator iter = vremoved.begin(); iter != vremoved.end(); ++iter) + { + updateWornItem(*iter, false); + } +} + void LLInventoryGallery::deselectItem(const LLUUID& category_id) { // Reset selection if the item is selected. @@ -973,6 +1032,7 @@ LLInventoryGalleryItem::~LLInventoryGalleryItem() BOOL LLInventoryGalleryItem::postBuild() { mNameText = getChild("item_name"); + mSuffixText = getChild("suffix_text"); mTextBgPanel = getChild("text_bg_panel"); mHidden = false; @@ -1036,9 +1096,10 @@ void LLInventoryGalleryItem::draw() void LLInventoryGalleryItem::setName(std::string name) { + mName = name; + mNameText->setFont(getTextFont()); mNameText->setText(name); mNameText->setToolTip(name); - mName = name; } void LLInventoryGalleryItem::setSelected(bool value) @@ -1137,6 +1198,24 @@ BOOL LLInventoryGalleryItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL dro return baseHandleDragAndDrop(mUUID, drop, cargo_type, cargo_data, accept, tooltip_msg); } +void LLInventoryGalleryItem::setWorn(bool value) +{ + mWorn = value; + mSuffixText->setValue(mWorn ? getString("worn_string") : ""); + + mNameText->setFont(getTextFont()); + mNameText->setText(mName); // refresh to pick up font changes +} + +LLFontGL* LLInventoryGalleryItem::getTextFont() +{ + if(mWorn) + { + return LLFontGL::getFontSansSerifSmallBold(); + } + return mIsLink ? LLFontGL::getFontSansSerifSmallItalic() : LLFontGL::getFontSansSerifSmall(); +} + //----------------------------- // Helper drag&drop functions //----------------------------- -- cgit v1.2.3 From 126bfa4877303b47abbc99f09c09a931c20cbd3b Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 31 Mar 2023 15:23:11 +0300 Subject: SL-19379 WIP fix for displaying folder link items, added correct action for 'paste as link' --- indra/newview/llinventorygallery.cpp | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 8c49cd5a4b..499d51c431 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -222,6 +222,9 @@ void LLInventoryGallery::updateRootFolder() } } + const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + mCategoriesObserver->addCategory(cof, boost::bind(&LLInventoryGallery::onCOFChanged, this)); + if (!mGalleryCreated) { initGallery(); @@ -243,9 +246,6 @@ void LLInventoryGallery::initGallery() } reArrangeRows(); mGalleryCreated = true; - - const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - mCategoriesObserver->addCategory(cof, boost::bind(&LLInventoryGallery::onCOFChanged, this)); } } @@ -646,7 +646,14 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) LLInventoryType::EType inventory_type(LLInventoryType::IT_CATEGORY); U32 misc_flags = 0; bool is_worn = false; - if (LLAssetType::AT_CATEGORY == obj->getType()) + LLInventoryItem* inv_item = gInventory.getItem(item_id); + if (inv_item) + { + inventory_type = inv_item->getInventoryType(); + misc_flags = inv_item->getFlags(); + is_worn = LLAppearanceMgr::instance().isLinkedInCOF(item_id); + } + else if (LLAssetType::AT_CATEGORY == obj->getType()) { name = get_localized_folder_name(item_id); if(thumbnail_id.isNull()) @@ -654,16 +661,6 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) thumbnail_id = getOutfitImageID(item_id); } } - else - { - LLInventoryItem* inv_item = gInventory.getItem(item_id); - if (inv_item) - { - inventory_type = inv_item->getInventoryType(); - misc_flags = inv_item->getFlags(); - is_worn = LLAppearanceMgr::instance().isLinkedInCOF(item_id); - } - } LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getIsLinkType(), is_worn); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); @@ -1049,7 +1046,16 @@ void LLInventoryGalleryItem::setType(LLAssetType::EType type, LLInventoryType::E if(mIsFolder) { mSortGroup = SG_NORMAL_FOLDER; - LLViewerInventoryCategory * cat = gInventory.getCategory(mUUID); + LLUUID folder_id = mUUID; + if(mIsLink) + { + LLInventoryObject* obj = gInventory.getObject(mUUID); + if (obj) + { + folder_id = obj->getLinkedUUID(); + } + } + LLViewerInventoryCategory* cat = gInventory.getCategory(folder_id); if (cat) { LLFolderType::EType preferred_type = cat->getPreferredType(); -- cgit v1.2.3 From 29c5bf19f706655605bd3588e0249dbd5fd52179 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 31 Mar 2023 21:18:50 +0300 Subject: SL-19379 WIP show fallback image with original size --- indra/newview/llinventorygallery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 499d51c431..290688f179 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1081,7 +1081,7 @@ void LLInventoryGalleryItem::setThumbnail(LLUUID id) mDefaultImage = id.isNull(); if(mDefaultImage) { - getChild("preview_thumbnail")->setValue("Thumbnail_Fallback"); + getChild("preview_thumbnail")->clearTexture(); } else { -- cgit v1.2.3 From bc285ed41e86e685df07f4039c64c0402833b047 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Mon, 3 Apr 2023 21:34:37 +0300 Subject: SL-19521 Inventory filters floater should affect Inventory Gallery --- indra/newview/llinventorygallery.cpp | 154 +++++++++++++++++++++++++++++++---- 1 file changed, 136 insertions(+), 18 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 290688f179..da58aa70f9 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -84,12 +84,14 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mRowPanWidthFactor(p.row_panel_width_factor), mGalleryWidthFactor(p.gallery_width_factor), mIsInitialized(false), - mSearchType(LLInventoryFilter::SEARCHTYPE_NAME), - mSearchLinks(true) + mSearchType(LLInventoryFilter::SEARCHTYPE_NAME) { updateGalleryWidth(); - + mFilter = new LLInventoryFilter(); mCategoriesObserver = new LLInventoryCategoriesObserver(); + + mUsername = gAgentUsername; + LLStringUtil::toUpper(mUsername); } LLInventoryGallery::Params::Params() @@ -124,6 +126,7 @@ BOOL LLInventoryGallery::postBuild() LLInventoryGallery::~LLInventoryGallery() { delete mInventoryGalleryMenu; + delete mFilter; while (!mUnusedRowPanels.empty()) { @@ -254,20 +257,26 @@ void LLInventoryGallery::draw() LLPanel::draw(); if (mGalleryCreated) { - updateRowsIfNeeded(); + if(!updateRowsIfNeeded() && mFilter->isModified()) + { + reArrangeRows(); + } } } -void LLInventoryGallery::updateRowsIfNeeded() +bool LLInventoryGallery::updateRowsIfNeeded() { if(((getRect().getWidth() - mRowPanelWidth) > mItemWidth) && mRowCount > 1) { reArrangeRows(1); + return true; } else if((mRowPanelWidth > (getRect().getWidth() + mItemHorizontalGap)) && mItemsInRow > GALLERY_ITEMS_PER_ROW_MIN) { reArrangeRows(-1); + return true; } + return false; } bool compareGalleryItem(LLInventoryGalleryItem* item1, LLInventoryGalleryItem* item2) @@ -312,6 +321,7 @@ void LLInventoryGallery::reArrangeRows(S32 row_diff) applyFilter(*it, mFilterSubString); addToGallery(*it); } + mFilter->clearModified(); updateMessageVisibility(); } @@ -558,20 +568,50 @@ void LLInventoryGallery::moveRowPanel(LLPanel* stack, int left, int bottom) void LLInventoryGallery::setFilterSubString(const std::string& string) { mFilterSubString = string; - reArrangeRows(); + mFilter->setFilterSubString(string); + + //reArrangeRows(); } void LLInventoryGallery::applyFilter(LLInventoryGalleryItem* item, const std::string& filter_substring) { if (!item) return; - std::string desc; - if(!mSearchLinks && item->isLink()) + if (item->isFolder() && (mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS)) + { + item->setHidden(false); + return; + } + + if(item->isLink() && ((mFilter->getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LINKS) == 0) && !filter_substring.empty()) + { + item->setHidden(true); + return; + } + + bool hidden = false; + + if(mFilter->getFilterCreatorType() == LLInventoryFilter::FILTERCREATOR_SELF) + { + hidden = (item->getCreatorName() == mUsername) || item->isFolder(); + } + else if(mFilter->getFilterCreatorType() == LLInventoryFilter::FILTERCREATOR_OTHERS) + { + hidden = (item->getCreatorName() != mUsername) || item->isFolder(); + } + if(hidden) + { + item->setHidden(true); + return; + } + + if(!checkAgainstFilterType(item->getUUID())) { item->setHidden(true); return; } + std::string desc; switch(mSearchType) { case LLInventoryFilter::SEARCHTYPE_CREATOR: @@ -594,7 +634,7 @@ void LLInventoryGallery::applyFilter(LLInventoryGalleryItem* item, const std::st std::string cur_filter = filter_substring; LLStringUtil::toUpper(cur_filter); - bool hidden = (std::string::npos == desc.find(cur_filter)); + hidden = (std::string::npos == desc.find(cur_filter)); item->setHidden(hidden); } @@ -610,15 +650,6 @@ void LLInventoryGallery::setSearchType(LLInventoryFilter::ESearchType type) } } -void LLInventoryGallery::toggleSearchLinks() -{ - mSearchLinks = !mSearchLinks; - if(!mFilterSubString.empty()) - { - reArrangeRows(); - } -} - void LLInventoryGallery::getCurrentCategories(uuid_vec_t& vcur) { for (gallery_item_map_t::const_iterator iter = mItemMap.begin(); @@ -777,7 +808,13 @@ void LLInventoryGallery::onChangeItemSelection(const LLUUID& category_id) void LLInventoryGallery::updateMessageVisibility() { + mMessageTextBox->setVisible(mItems.empty()); + if(mItems.empty()) + { + mMessageTextBox->setText(hasDescendents(mFolderID) ? LLTrans::getString("InventorySingleFolderEmpty") : LLTrans::getString("InventorySingleFolderNoMatches")); + } + mScrollPanel->setVisible(!mItems.empty()); } @@ -1001,6 +1038,87 @@ BOOL LLInventoryGallery::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, return handled; } +bool LLInventoryGallery::hasDescendents(const LLUUID& cat_id) +{ + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(cat_id, cats, items); + + return (cats->empty() && items->empty()); +} + +bool LLInventoryGallery::checkAgainstFilterType(const LLUUID& object_id) +{ + const LLInventoryObject *object = gInventory.getObject(object_id); + if(!object) return false; + + LLInventoryType::EType object_type = LLInventoryType::IT_CATEGORY; + LLInventoryItem* inv_item = gInventory.getItem(object_id); + if (inv_item) + { + object_type = inv_item->getInventoryType(); + } + const U32 filterTypes = mFilter->getFilterTypes(); + + if ((filterTypes & LLInventoryFilter::FILTERTYPE_OBJECT) && inv_item) + { + switch (object_type) + { + case LLInventoryType::IT_NONE: + // If it has no type, pass it, unless it's a link. + if (object && object->getIsLinkType()) + { + return false; + } + break; + case LLInventoryType::IT_UNKNOWN: + { + // Unknows are only shown when we show every type. + // Unknows are 255 and won't fit in 64 bits. + if (mFilter->getFilterObjectTypes() != 0xffffffffffffffffULL) + { + return false; + } + break; + } + default: + if ((1LL << object_type & mFilter->getFilterObjectTypes()) == U64(0)) + { + return false; + } + break; + } + } + + if (filterTypes & LLInventoryFilter::FILTERTYPE_DATE) + { + const U16 HOURS_TO_SECONDS = 3600; + time_t earliest = time_corrected() - mFilter->getHoursAgo() * HOURS_TO_SECONDS; + + if (mFilter->getMinDate() > time_min() && mFilter->getMinDate() < earliest) + { + earliest = mFilter->getMinDate(); + } + else if (!mFilter->getHoursAgo()) + { + earliest = 0; + } + + if (LLInventoryFilter::FILTERDATEDIRECTION_NEWER == mFilter->getDateSearchDirection() || mFilter->isSinceLogoff()) + { + if (object->getCreationDate() < earliest || + object->getCreationDate() > mFilter->getMaxDate()) + return false; + } + else + { + if (object->getCreationDate() > earliest || + object->getCreationDate() > mFilter->getMaxDate()) + return false; + } + } + return true; +} //----------------------------- // LLInventoryGalleryItem //----------------------------- -- cgit v1.2.3 From 7ccfbd7c285cc2ab0bbf569912f8e9e2d5c1df72 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Tue, 4 Apr 2023 15:14:02 +0300 Subject: SL-19379 Don't switch focus to other Inventory floater when creating an item in Gallery --- indra/newview/llinventorygallery.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index da58aa70f9..c4da11a570 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -696,7 +696,7 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getIsLinkType(), is_worn); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); item->setRightMouseDownCallback(boost::bind(&LLInventoryGallery::showContextMenu, this, _1, _2, _3, item_id)); - item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::onChangeItemSelection, this, item_id)); + item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::changeItemSelection, this, item_id)); if (mGalleryCreated) { addToGallery(item); @@ -789,21 +789,21 @@ void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLU } } -void LLInventoryGallery::onChangeItemSelection(const LLUUID& category_id) +void LLInventoryGallery::changeItemSelection(const LLUUID& item_id) { - if (mSelectedItemID == category_id) + if ((mItemMap.count(item_id) > 0) && (mSelectedItemID == item_id)) return; if (mItemMap[mSelectedItemID]) { mItemMap[mSelectedItemID]->setSelected(FALSE); } - if (mItemMap[category_id]) + if (mItemMap[item_id]) { - mItemMap[category_id]->setSelected(TRUE); + mItemMap[item_id]->setSelected(TRUE); } - mSelectedItemID = category_id; - signalSelectionItemID(category_id); + mSelectedItemID = item_id; + signalSelectionItemID(item_id); } void LLInventoryGallery::updateMessageVisibility() -- cgit v1.2.3 From f5809ad862c0a9b1004a2c9a779df99ff4555a1f Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Tue, 4 Apr 2023 20:18:08 +0300 Subject: SL-19379 Observe thumbnail changes and update it in Gallery --- indra/newview/llinventorygallery.cpp | 76 +++++++++++++++++++++++++++++++----- 1 file changed, 67 insertions(+), 9 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index c4da11a570..8c2f4c2214 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -89,6 +89,8 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) updateGalleryWidth(); mFilter = new LLInventoryFilter(); mCategoriesObserver = new LLInventoryCategoriesObserver(); + mThumbnailsObserver = new LLThumbnailsObserver(); + gInventory.addObserver(mThumbnailsObserver); mUsername = gAgentUsername; LLStringUtil::toUpper(mUsername); @@ -146,6 +148,12 @@ LLInventoryGallery::~LLInventoryGallery() gInventory.removeObserver(mCategoriesObserver); } delete mCategoriesObserver; + + if (gInventory.containsObserver(mThumbnailsObserver)) + { + gInventory.removeObserver(mThumbnailsObserver); + } + delete mThumbnailsObserver; } void LLInventoryGallery::setRootFolder(const LLUUID cat_id) @@ -702,13 +710,8 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) addToGallery(item); } - if (mCategoriesObserver == NULL) - { - mCategoriesObserver = new LLInventoryCategoriesObserver(); - gInventory.addObserver(mCategoriesObserver); - } - mCategoriesObserver->addCategory(item_id, - boost::bind(&LLInventoryGallery::updateItemThumbnail, this, item_id), true); + mThumbnailsObserver->addItem(item_id, + boost::bind(&LLInventoryGallery::updateItemThumbnail, this, item_id)); } void LLInventoryGallery::updateRemovedItem(LLUUID item_id) @@ -716,7 +719,7 @@ void LLInventoryGallery::updateRemovedItem(LLUUID item_id) gallery_item_map_t::iterator item_iter = mItemMap.find(item_id); if (item_iter != mItemMap.end()) { - mCategoriesObserver->removeCategory(item_id); + mThumbnailsObserver->removeItem(item_id); LLInventoryGalleryItem* item = item_iter->second; @@ -978,7 +981,7 @@ LLUUID LLInventoryGallery::getOutfitImageID(LLUUID outfit_id) return thumbnail_id; } -boost::signals2::connection LLInventoryGallery::setRootChangedCallback(root_changed_callback_t cb) +boost::signals2::connection LLInventoryGallery::setRootChangedCallback(callback_t cb) { return mRootChangedSignal.connect(cb); } @@ -1340,6 +1343,61 @@ LLFontGL* LLInventoryGalleryItem::getTextFont() return mIsLink ? LLFontGL::getFontSansSerifSmallItalic() : LLFontGL::getFontSansSerifSmall(); } +//----------------------------- +// LLThumbnailsObserver +//----------------------------- + +void LLThumbnailsObserver::changed(U32 mask) +{ + if (!mItemMap.size()) + return; + std::vector deleted_ids; + + for (item_map_t::iterator iter = mItemMap.begin(); + iter != mItemMap.end(); + ++iter) + { + const LLUUID& obj_id = (*iter).first; + LLItemData& data = (*iter).second; + + LLInventoryObject* obj = gInventory.getObject(obj_id); + if (!obj) + { + deleted_ids.push_back(obj_id); + continue; + } + + const LLUUID thumbnail_id = obj->getThumbnailUUID(); + if (data.mThumbnailID != thumbnail_id) + { + data.mThumbnailID = thumbnail_id; + data.mCallback(); + } + } + + // Remove deleted items from the list + for (std::vector::iterator deleted_id = deleted_ids.begin(); deleted_id != deleted_ids.end(); ++deleted_id) + { + removeItem(*deleted_id); + } +} + +bool LLThumbnailsObserver::addItem(const LLUUID& obj_id, callback_t cb) +{ + LLInventoryObject* obj = gInventory.getObject(obj_id); + if (obj) + { + mItemMap.insert(item_map_value_t(obj_id, LLItemData(obj_id, obj->getThumbnailUUID(), cb))); + return true; + } + return false; +} + +void LLThumbnailsObserver::removeItem(const LLUUID& obj_id) +{ + mItemMap.erase(obj_id); +} + //----------------------------- // Helper drag&drop functions //----------------------------- -- cgit v1.2.3 From 7a402e352d1982e6361c966590eb07556418154b Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 5 Apr 2023 00:10:08 +0300 Subject: SL-19379 selection fix --- indra/newview/llinventorygallery.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 8c2f4c2214..b964ecff05 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -794,7 +794,7 @@ void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLU void LLInventoryGallery::changeItemSelection(const LLUUID& item_id) { - if ((mItemMap.count(item_id) > 0) && (mSelectedItemID == item_id)) + if ((mItemMap.count(item_id) == 0) || (mSelectedItemID == item_id)) return; if (mItemMap[mSelectedItemID]) @@ -1136,6 +1136,7 @@ LLInventoryGalleryItem::LLInventoryGalleryItem(const Params& p) mUUID(LLUUID()), mIsFolder(true), mIsLink(false), + mHidden(false), mGallery(NULL), mType(LLAssetType::AT_NONE), mSortGroup(SG_ITEM) @@ -1151,9 +1152,8 @@ BOOL LLInventoryGalleryItem::postBuild() { mNameText = getChild("item_name"); mSuffixText = getChild("suffix_text"); - mTextBgPanel = getChild("text_bg_panel"); - mHidden = false; + return TRUE; } -- cgit v1.2.3 From cc39c1e852b1b8ad0e6dc2bb7907b8116c716c1d Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 6 Apr 2023 19:51:08 +0300 Subject: SL-19544 preparation for Combination view --- indra/newview/llinventorygallery.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index b964ecff05..c3e06fafc5 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -613,6 +613,12 @@ void LLInventoryGallery::applyFilter(LLInventoryGalleryItem* item, const std::st return; } + if(!mFilter->checkAgainstFilterThumbnails(item->getUUID())) + { + item->setHidden(true); + return; + } + if(!checkAgainstFilterType(item->getUUID())) { item->setHidden(true); -- cgit v1.2.3 From d5a949d97a67c8b9e551fc4b22d4c901eaf1d91a Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 7 Apr 2023 15:13:47 +0300 Subject: SL-19544 WIP Combination view first pass --- indra/newview/llinventorygallery.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index c3e06fafc5..e38f2ef849 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1128,6 +1128,11 @@ bool LLInventoryGallery::checkAgainstFilterType(const LLUUID& object_id) } return true; } + +bool LLInventoryGallery::hasVisibleItems() +{ + return mItemsAddedCount > 0; +} //----------------------------- // LLInventoryGalleryItem //----------------------------- -- cgit v1.2.3 From 7df076b62682b7e9749bb402958a3ea6735be283 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 7 Apr 2023 18:02:22 +0300 Subject: SL-19544 WIP apply filter when adding an item to the Gallery --- indra/newview/llinventorygallery.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index e38f2ef849..4e4a476584 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -713,6 +713,7 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::changeItemSelection, this, item_id)); if (mGalleryCreated) { + applyFilter(item, mFilterSubString); addToGallery(item); } -- cgit v1.2.3 From 6e5b94071b62113f2bd52dd6985498990926a9f6 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Tue, 11 Apr 2023 21:39:23 +0300 Subject: SL-19544 WIP combination view filtering; hidden items should be correctly removed when root is changed --- indra/newview/llinventorygallery.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 4e4a476584..f0a1fc5751 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -180,6 +180,11 @@ void LLInventoryGallery::updateRootFolder() { updateRemovedItem(mItems[i]->getUUID()); } + S32 hidden_count = mHiddenItems.size(); + for (S32 i = hidden_count - 1; i >= 0; i--) + { + updateRemovedItem(mHiddenItems[i]->getUUID()); + } if (gInventory.containsObserver(mCategoriesObserver)) { @@ -740,7 +745,6 @@ void LLInventoryGallery::updateRemovedItem(LLUUID item_id) item->die(); } } - } void LLInventoryGallery::updateChangedItemName(LLUUID item_id, std::string name) -- cgit v1.2.3 From 842bc87941d4574fe1ce34186872e43ecef881c3 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 12 Apr 2023 12:56:56 +0300 Subject: SL-19544 WIP update combination gallery visibility after changing filter --- indra/newview/llinventorygallery.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index f0a1fc5751..9766a39e3c 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -270,9 +270,9 @@ void LLInventoryGallery::draw() LLPanel::draw(); if (mGalleryCreated) { - if(!updateRowsIfNeeded() && mFilter->isModified()) + if(!updateRowsIfNeeded()) { - reArrangeRows(); + handleModifiedFilter(); } } } @@ -1138,6 +1138,15 @@ bool LLInventoryGallery::hasVisibleItems() { return mItemsAddedCount > 0; } + +void LLInventoryGallery::handleModifiedFilter() +{ + if(mFilter->isModified()) + { + reArrangeRows(); + } +} + //----------------------------- // LLInventoryGalleryItem //----------------------------- -- cgit v1.2.3 From 107a7eb919bb0afadf6ad3f92482cf7e6d67c56e Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 13 Apr 2023 17:49:26 +0300 Subject: SL-19544 WIP add active suffix for gestures and add appropriate context menu handling --- indra/newview/llinventorygallery.cpp | 54 ++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 9766a39e3c..9344668f52 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -92,6 +92,9 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mThumbnailsObserver = new LLThumbnailsObserver(); gInventory.addObserver(mThumbnailsObserver); + mGestureObserver = new LLGalleryGestureObserver(this); + LLGestureMgr::instance().addObserver(mGestureObserver); + mUsername = gAgentUsername; LLStringUtil::toUpper(mUsername); } @@ -154,6 +157,9 @@ LLInventoryGallery::~LLInventoryGallery() gInventory.removeObserver(mThumbnailsObserver); } delete mThumbnailsObserver; + + LLGestureMgr::instance().removeObserver(mGestureObserver); + delete mGestureObserver; } void LLInventoryGallery::setRootFolder(const LLUUID cat_id) @@ -701,7 +707,14 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) { inventory_type = inv_item->getInventoryType(); misc_flags = inv_item->getFlags(); - is_worn = LLAppearanceMgr::instance().isLinkedInCOF(item_id); + if (LLAssetType::AT_GESTURE == obj->getType()) + { + is_worn = LLGestureMgr::instance().isGestureActive(item_id); + } + else + { + is_worn = LLAppearanceMgr::instance().isLinkedInCOF(item_id); + } } else if (LLAssetType::AT_CATEGORY == obj->getType()) { @@ -943,6 +956,37 @@ void LLInventoryGallery::onCOFChanged() } } +void LLInventoryGallery::onGesturesChanged() +{ + uuid_vec_t vnew; + uuid_vec_t vadded; + uuid_vec_t vremoved; + + const LLGestureMgr::item_map_t& active_gestures = LLGestureMgr::instance().getActiveGestures(); + for (LLGestureMgr::item_map_t::const_iterator iter = active_gestures.begin(); + iter != active_gestures.end(); + ++iter) + { + vnew.push_back(iter->first); + } + + LLCommonUtils::computeDifference(vnew, mActiveGestures, vadded, vremoved); + + mActiveGestures = vnew; + + for (uuid_vec_t::const_iterator iter = vadded.begin(); + iter != vadded.end(); + ++iter) + { + updateWornItem(*iter, true); + } + + for (uuid_vec_t::const_iterator iter = vremoved.begin(); iter != vremoved.end(); ++iter) + { + updateWornItem(*iter, false); + } +} + void LLInventoryGallery::deselectItem(const LLUUID& category_id) { // Reset selection if the item is selected. @@ -1353,7 +1397,13 @@ BOOL LLInventoryGalleryItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL dro void LLInventoryGalleryItem::setWorn(bool value) { mWorn = value; - mSuffixText->setValue(mWorn ? getString("worn_string") : ""); + std::string suffix(""); + + if(mWorn) + { + suffix = (mType == LLAssetType::AT_GESTURE) ? getString("active_string") : getString("worn_string"); + } + mSuffixText->setValue(suffix); mNameText->setFont(getTextFont()); mNameText->setText(mName); // refresh to pick up font changes -- cgit v1.2.3 From 94dd7b2c0c020bad25dab9472d612f673f136422 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 13 Apr 2023 19:33:20 +0300 Subject: SL-19544 WIP search by name should include suffix --- indra/newview/llinventorygallery.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 9344668f52..94996cb941 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -650,7 +650,7 @@ void LLInventoryGallery::applyFilter(LLInventoryGalleryItem* item, const std::st break; case LLInventoryFilter::SEARCHTYPE_NAME: default: - desc = item->getItemName(); + desc = item->getItemName() + item->getItemNameSuffix(); break; } @@ -1202,6 +1202,7 @@ LLInventoryGalleryItem::LLInventoryGalleryItem(const Params& p) mSelected(false), mDefaultImage(true), mName(""), + mSuffix(""), mUUID(LLUUID()), mIsFolder(true), mIsLink(false), @@ -1397,13 +1398,16 @@ BOOL LLInventoryGalleryItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL dro void LLInventoryGalleryItem::setWorn(bool value) { mWorn = value; - std::string suffix(""); if(mWorn) { - suffix = (mType == LLAssetType::AT_GESTURE) ? getString("active_string") : getString("worn_string"); + mSuffix = (mType == LLAssetType::AT_GESTURE) ? getString("active_string") : getString("worn_string"); } - mSuffixText->setValue(suffix); + else + { + mSuffix = ""; + } + mSuffixText->setValue(mSuffix); mNameText->setFont(getTextFont()); mNameText->setText(mName); // refresh to pick up font changes -- cgit v1.2.3 From 5554686b9117901cddb3d36f237622442c1d7a8d Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Mon, 17 Apr 2023 13:22:27 +0300 Subject: SL-19544 WIP show item permissions after item name --- indra/newview/llinventorygallery.cpp | 50 ++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 10 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 94996cb941..f6a1f49306 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1202,7 +1202,8 @@ LLInventoryGalleryItem::LLInventoryGalleryItem(const Params& p) mSelected(false), mDefaultImage(true), mName(""), - mSuffix(""), + mWornSuffix(""), + mPermSuffix(""), mUUID(LLUUID()), mIsFolder(true), mIsLink(false), @@ -1221,7 +1222,6 @@ LLInventoryGalleryItem::~LLInventoryGalleryItem() BOOL LLInventoryGalleryItem::postBuild() { mNameText = getChild("item_name"); - mSuffixText = getChild("suffix_text"); mTextBgPanel = getChild("text_bg_panel"); return TRUE; @@ -1262,6 +1262,32 @@ void LLInventoryGalleryItem::setType(LLAssetType::EType type, LLInventoryType::E } } } + else + { + const LLInventoryItem *item = gInventory.getItem(mUUID); + if(item && (LLAssetType::AT_CALLINGCARD != item->getType()) && !mIsLink) + { + std::string delim(" --"); + bool copy = item->getPermissions().allowCopyBy(gAgent.getID()); + if (!copy) + { + mPermSuffix += delim; + mPermSuffix += LLTrans::getString("no_copy_lbl"); + } + bool mod = item->getPermissions().allowModifyBy(gAgent.getID()); + if (!mod) + { + mPermSuffix += mPermSuffix.empty() ? delim : ","; + mPermSuffix += LLTrans::getString("no_modify_lbl"); + } + bool xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()); + if (!xfer) + { + mPermSuffix += mPermSuffix.empty() ? delim : ","; + mPermSuffix += LLTrans::getString("no_transfer_lbl"); + } + } + } getChild("item_type")->setValue(icon_name); getChild("link_overlay")->setVisible(is_link); @@ -1294,9 +1320,7 @@ void LLInventoryGalleryItem::draw() void LLInventoryGalleryItem::setName(std::string name) { mName = name; - mNameText->setFont(getTextFont()); - mNameText->setText(name); - mNameText->setToolTip(name); + updateNameText(); } void LLInventoryGalleryItem::setSelected(bool value) @@ -1401,16 +1425,14 @@ void LLInventoryGalleryItem::setWorn(bool value) if(mWorn) { - mSuffix = (mType == LLAssetType::AT_GESTURE) ? getString("active_string") : getString("worn_string"); + mWornSuffix = (mType == LLAssetType::AT_GESTURE) ? LLTrans::getString("active") : LLTrans::getString("worn"); } else { - mSuffix = ""; + mWornSuffix = ""; } - mSuffixText->setValue(mSuffix); - mNameText->setFont(getTextFont()); - mNameText->setText(mName); // refresh to pick up font changes + updateNameText(); } LLFontGL* LLInventoryGalleryItem::getTextFont() @@ -1422,6 +1444,14 @@ LLFontGL* LLInventoryGalleryItem::getTextFont() return mIsLink ? LLFontGL::getFontSansSerifSmallItalic() : LLFontGL::getFontSansSerifSmall(); } +void LLInventoryGalleryItem::updateNameText() +{ + mNameText->setFont(getTextFont()); + mNameText->setText(mName + mPermSuffix + mWornSuffix); + mNameText->setToolTip(mName + mPermSuffix + mWornSuffix); + getChild("preview_thumbnail")->setToolTip(mName + mPermSuffix + mWornSuffix); +} + //----------------------------- // LLThumbnailsObserver //----------------------------- -- cgit v1.2.3 From ce2aaab15912693d51383274dc1dfebb20c0b6a2 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Tue, 18 Apr 2023 21:27:25 +0300 Subject: SL-19604 FIXED Creating new folders and items in gallery or combination views does not highlight created item --- indra/newview/llinventorygallery.cpp | 64 ++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 10 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index f6a1f49306..b4a23f7c55 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -728,7 +728,7 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getIsLinkType(), is_worn); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); item->setRightMouseDownCallback(boost::bind(&LLInventoryGallery::showContextMenu, this, _1, _2, _3, item_id)); - item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::changeItemSelection, this, item_id)); + item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::changeItemSelection, this, item_id, false)); if (mGalleryCreated) { applyFilter(item, mFilterSubString); @@ -816,21 +816,60 @@ void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLU } } -void LLInventoryGallery::changeItemSelection(const LLUUID& item_id) +void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_to_selection) { - if ((mItemMap.count(item_id) == 0) || (mSelectedItemID == item_id)) + if ((mItemMap.count(item_id) == 0)) + { + mItemToSelect = item_id; return; - - if (mItemMap[mSelectedItemID]) + } + if (mSelectedItemID != item_id) { - mItemMap[mSelectedItemID]->setSelected(FALSE); + + if (mItemMap[mSelectedItemID]) + { + mItemMap[mSelectedItemID]->setSelected(FALSE); + } + if (mItemMap[item_id]) + { + mItemMap[item_id]->setSelected(TRUE); + } + mSelectedItemID = item_id; + signalSelectionItemID(item_id); + + mItemToSelect = LLUUID::null; + if(scroll_to_selection) + { + scrollToShowItem(mSelectedItemID); + } } - if (mItemMap[item_id]) +} + +void LLInventoryGallery::scrollToShowItem(const LLUUID& item_id) +{ + LLInventoryGalleryItem* item = mItemMap[item_id]; + if(item) { - mItemMap[item_id]->setSelected(TRUE); + const LLRect visible_content_rect = mScrollPanel->getVisibleContentRect(); + + LLRect item_rect; + item->localRectToOtherView(item->getLocalRect(), &item_rect, this); + LLRect overlap_rect(item_rect); + overlap_rect.intersectWith(visible_content_rect); + + //Scroll when the selected item is outside the visible area + if (overlap_rect.getHeight() + 5 < item->getRect().getHeight()) + { + LLRect content_rect = mScrollPanel->getContentWindowRect(); + LLRect constraint_rect; + constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); + + LLRect item_doc_rect; + item->localRectToOtherView(item->getLocalRect(), &item_doc_rect, this); + + mScrollPanel->scrollToShowRect( item_doc_rect, constraint_rect ); + } } - mSelectedItemID = item_id; - signalSelectionItemID(item_id); } void LLInventoryGallery::updateMessageVisibility() @@ -886,6 +925,11 @@ void LLInventoryGallery::refreshList(const LLUUID& category_id) updateChangedItemName(*items_iter, obj->getName()); } + + if(mItemToSelect.notNull()) + { + changeItemSelection(mItemToSelect, true); + } updateMessageVisibility(); } -- cgit v1.2.3 From a03f3cd00db95fb8dc6fd500e95054c654088bf7 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 20 Apr 2023 14:42:25 +0300 Subject: SL-19630 FIXED Adding a thumbnail to item in combination view does not update gallery view --- indra/newview/llinventorygallery.cpp | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index b4a23f7c55..a078d6c81d 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -594,18 +594,24 @@ void LLInventoryGallery::setFilterSubString(const std::string& string) void LLInventoryGallery::applyFilter(LLInventoryGalleryItem* item, const std::string& filter_substring) { - if (!item) return; + if(item) + { + item->setHidden(!checkAgainstFilters(item, filter_substring)); + } +} + +bool LLInventoryGallery::checkAgainstFilters(LLInventoryGalleryItem* item, const std::string& filter_substring) +{ + if (!item) return false; if (item->isFolder() && (mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS)) { - item->setHidden(false); - return; + return true; } if(item->isLink() && ((mFilter->getSearchVisibilityTypes() & LLInventoryFilter::VISIBILITY_LINKS) == 0) && !filter_substring.empty()) { - item->setHidden(true); - return; + return false; } bool hidden = false; @@ -620,20 +626,17 @@ void LLInventoryGallery::applyFilter(LLInventoryGalleryItem* item, const std::st } if(hidden) { - item->setHidden(true); - return; + return false; } if(!mFilter->checkAgainstFilterThumbnails(item->getUUID())) { - item->setHidden(true); - return; + return false; } if(!checkAgainstFilterType(item->getUUID())) { - item->setHidden(true); - return; + return false; } std::string desc; @@ -660,7 +663,7 @@ void LLInventoryGallery::applyFilter(LLInventoryGalleryItem* item, const std::st LLStringUtil::toUpper(cur_filter); hidden = (std::string::npos == desc.find(cur_filter)); - item->setHidden(hidden); + return !hidden; } void LLInventoryGallery::setSearchType(LLInventoryFilter::ESearchType type) @@ -803,6 +806,13 @@ void LLInventoryGallery::updateItemThumbnail(LLUUID item_id) if (mItemMap[item_id]) { mItemMap[item_id]->setThumbnail(thumbnail_id); + + bool passes_filter = checkAgainstFilters(mItemMap[item_id], mFilterSubString); + if((mItemMap[item_id]->isHidden() && passes_filter) + || (!mItemMap[item_id]->isHidden() && !passes_filter)) + { + reArrangeRows(); + } } } -- cgit v1.2.3 From 61818417d619c8d17cf861f0d72b314a14269e2f Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 5 May 2023 18:17:00 +0300 Subject: SL-19641 FIXED Gallery item is not selected after using 'Find original' --- indra/newview/llinventorygallery.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index a078d6c81d..37801c8dd5 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -882,6 +882,11 @@ void LLInventoryGallery::scrollToShowItem(const LLUUID& item_id) } } +LLInventoryGalleryItem* LLInventoryGallery::getSelectedItem() +{ + return mItemMap[mSelectedItemID]; +} + void LLInventoryGallery::updateMessageVisibility() { -- cgit v1.2.3 From 8a1cb8c00cf75ff1e09c72c2fb487728ec77c66b Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 10 May 2023 12:51:08 +0300 Subject: SL-19697 FIXED Clicking on inventory item in list view does not unselect item in gallery view --- indra/newview/llinventorygallery.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 37801c8dd5..9c7e96e97e 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1056,6 +1056,14 @@ void LLInventoryGallery::deselectItem(const LLUUID& category_id) } } +void LLInventoryGallery::clearSelection() +{ + if(mSelectedItemID != LLUUID::null) + { + changeItemSelection(LLUUID::null); + } +} + void LLInventoryGallery::signalSelectionItemID(const LLUUID& category_id) { mSelectionChangeSignal(category_id); -- cgit v1.2.3 From 784436a5b89062df69251c9ac28904f06a018011 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 17 May 2023 18:38:23 +0300 Subject: SL-19721 use LLOutfitObserver to handle cof changes --- indra/newview/llinventorygallery.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 9c7e96e97e..f97cb9dbf4 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -45,6 +45,7 @@ #include "llfriendcard.h" #include "llgesturemgr.h" #include "llmarketplacefunctions.h" +#include "lloutfitobserver.h" #include "lltrans.h" #include "llviewerassettype.h" #include "llviewermessage.h" @@ -244,8 +245,7 @@ void LLInventoryGallery::updateRootFolder() } } - const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - mCategoriesObserver->addCategory(cof, boost::bind(&LLInventoryGallery::onCOFChanged, this)); + LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLInventoryGallery::onCOFChanged, this)); if (!mGalleryCreated) { -- cgit v1.2.3 From 100ace48f1cd64a364179c06900465209aac4945 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 18 May 2023 23:22:58 +0300 Subject: SL-19686 don't build gallery items without thumbnails in combination view --- indra/newview/llinventorygallery.cpp | 65 ++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index f97cb9dbf4..18a7068b66 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -200,6 +200,14 @@ void LLInventoryGallery::updateRootFolder() delete mCategoriesObserver; mCategoriesObserver = new LLInventoryCategoriesObserver(); + + if (gInventory.containsObserver(mThumbnailsObserver)) + { + gInventory.removeObserver(mThumbnailsObserver); + } + delete mThumbnailsObserver; + mThumbnailsObserver = new LLThumbnailsObserver(); + gInventory.addObserver(mThumbnailsObserver); } { mRootChangedSignal(); @@ -699,7 +707,11 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) LL_WARNS("InventoryGallery") << "Failed to find item: " << item_id << LL_ENDL; return; } - + if(!mFilter->checkAgainstFilterThumbnails(item_id)) + { + mThumbnailsObserver->addSkippedItem(item_id, boost::bind(&LLInventoryGallery::onThumbnailAdded, this, item_id)); + return; + } std::string name = obj->getName(); LLUUID thumbnail_id = obj->getThumbnailUUID();; LLInventoryType::EType inventory_type(LLInventoryType::IT_CATEGORY); @@ -816,6 +828,15 @@ void LLInventoryGallery::updateItemThumbnail(LLUUID item_id) } } +void LLInventoryGallery::onThumbnailAdded(LLUUID item_id) +{ + if((mItemMap.count(item_id) == 0) && mFilter->checkAgainstFilterThumbnails(item_id)) + { + updateAddedItem(item_id); + reArrangeRows(); + } +} + void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id) { if (mInventoryGalleryMenu && item_id.notNull()) @@ -1525,9 +1546,33 @@ void LLInventoryGalleryItem::updateNameText() void LLThumbnailsObserver::changed(U32 mask) { - if (!mItemMap.size()) - return; std::vector deleted_ids; + for (item_map_t::iterator iter = mSkippedItems.begin(); + iter != mSkippedItems.end(); + ++iter) + { + const LLUUID& obj_id = (*iter).first; + LLItemData& data = (*iter).second; + + LLInventoryObject* obj = gInventory.getObject(obj_id); + if (!obj) + { + deleted_ids.push_back(obj_id); + continue; + } + + const LLUUID thumbnail_id = obj->getThumbnailUUID(); + if (data.mThumbnailID != thumbnail_id) + { + data.mThumbnailID = thumbnail_id; + data.mCallback(); + } + } + for (std::vector::iterator deleted_id = deleted_ids.begin(); deleted_id != deleted_ids.end(); ++deleted_id) + { + removeSkippedItem(*deleted_id); + } + deleted_ids.clear(); for (item_map_t::iterator iter = mItemMap.begin(); iter != mItemMap.end(); @@ -1569,11 +1614,25 @@ bool LLThumbnailsObserver::addItem(const LLUUID& obj_id, callback_t cb) return false; } +void LLThumbnailsObserver::addSkippedItem(const LLUUID& obj_id, callback_t cb) +{ + LLInventoryObject* obj = gInventory.getObject(obj_id); + if (obj) + { + mSkippedItems.insert(item_map_value_t(obj_id, LLItemData(obj_id, obj->getThumbnailUUID(), cb))); + } +} + void LLThumbnailsObserver::removeItem(const LLUUID& obj_id) { mItemMap.erase(obj_id); } +void LLThumbnailsObserver::removeSkippedItem(const LLUUID& obj_id) +{ + mSkippedItems.erase(obj_id); +} + //----------------------------- // Helper drag&drop functions //----------------------------- -- cgit v1.2.3 From 67e17bd822f146f333b91d353df6f55174ce4db6 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 26 May 2023 19:45:46 +0300 Subject: SL-19774 add context menu for root folder (without any selection); show paste menu when right clicking any item --- indra/newview/llinventorygallery.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 18a7068b66..c6fee42297 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -126,12 +126,15 @@ BOOL LLInventoryGallery::postBuild() mGalleryPanel = LLUICtrlFactory::create(params); mMessageTextBox = getChild("empty_txt"); mInventoryGalleryMenu = new LLInventoryGalleryContextMenu(this); + mRootGalleryMenu = new LLInventoryGalleryContextMenu(this); + mRootGalleryMenu->setRootFolder(true); return TRUE; } LLInventoryGallery::~LLInventoryGallery() { delete mInventoryGalleryMenu; + delete mRootGalleryMenu; delete mFilter; while (!mUnusedRowPanels.empty()) @@ -837,6 +840,27 @@ void LLInventoryGallery::onThumbnailAdded(LLUUID item_id) } } +BOOL LLInventoryGallery::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + if(mItemMap[mSelectedItemID]) + { + mItemMap[mSelectedItemID]->setFocus(false); + } + clearSelection(); + BOOL res = LLPanel::handleRightMouseDown(x, y, mask); + if (mSelectedItemID.isNull()) + { + if (mInventoryGalleryMenu && mFolderID.notNull()) + { + uuid_vec_t selected_uuids; + selected_uuids.push_back(mFolderID); + mRootGalleryMenu->show(this, selected_uuids, x, y); + return TRUE; + } + } + return res; +} + void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id) { if (mInventoryGalleryMenu && item_id.notNull()) -- cgit v1.2.3 From a6efb920e8e0d9add76ec86c3ed158c691685727 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 31 May 2023 01:09:57 +0300 Subject: SL-19795 Creating folders in combination mode does not scroll to new folder #2 --- indra/newview/llinventorygallery.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index c6fee42297..2f9f594790 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -183,7 +183,8 @@ void LLInventoryGallery::setRootFolder(const LLUUID cat_id) void LLInventoryGallery::updateRootFolder() { - if (mIsInitialized) + llassert(mFolderID.notNull()); + if (mIsInitialized && mFolderID.notNull()) { S32 count = mItemsAddedCount; for (S32 i = count - 1; i >= 0; i--) -- cgit v1.2.3 From 87d24252df91284eb0cd9ab2f08b376ded05554c Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 2 Jun 2023 01:58:30 +0300 Subject: SL-19795 Remove extra panels, reuse combination ones instead --- indra/newview/llinventorygallery.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 2f9f594790..efc78c5357 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -711,11 +711,7 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) LL_WARNS("InventoryGallery") << "Failed to find item: " << item_id << LL_ENDL; return; } - if(!mFilter->checkAgainstFilterThumbnails(item_id)) - { - mThumbnailsObserver->addSkippedItem(item_id, boost::bind(&LLInventoryGallery::onThumbnailAdded, this, item_id)); - return; - } + std::string name = obj->getName(); LLUUID thumbnail_id = obj->getThumbnailUUID();; LLInventoryType::EType inventory_type(LLInventoryType::IT_CATEGORY); -- cgit v1.2.3 From 8a33d65e984431d47f260b2cacbfc20ed4f8124c Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 2 Jun 2023 22:48:57 +0300 Subject: SL-19815 Suppors Page Up, Page Down, Home, End and Delete --- indra/newview/llinventorygallery.cpp | 103 +++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index efc78c5357..f4bd98a9f7 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -858,6 +858,109 @@ BOOL LLInventoryGallery::handleRightMouseDown(S32 x, S32 y, MASK mask) return res; } + +BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) +{ + BOOL handled = FALSE; + switch (key) + { + case KEY_RETURN: + // Open selected items if enter key hit on the inventory panel + if (mask == MASK_NONE && mInventoryGalleryMenu && mSelectedItemID.notNull()) + { + LLViewerInventoryCategory* category = gInventory.getCategory(mSelectedItemID); + if (category) + { + setRootFolder(mSelectedItemID); + handled = TRUE; + } + } + break; + case KEY_DELETE: +#if LL_DARWIN + case KEY_BACKSPACE: +#endif + // Delete selected items if delete or backspace key hit on the inventory panel + // Note: on Mac laptop keyboards, backspace and delete are one and the same + if (mSelectedItemID.notNull()) + { + LLViewerInventoryCategory* category = gInventory.getCategory(mSelectedItemID); + if (category) + { + if (get_is_category_removable(&gInventory, mSelectedItemID)) + { + gInventory.removeCategory(mSelectedItemID); + handled = TRUE; + } + } + else + { + if (get_is_item_removable(&gInventory, mSelectedItemID)) + { + gInventory.removeItem(mSelectedItemID); + handled = TRUE; + } + } + } + break; + + case KEY_F2: + mFilterSubString.clear(); + if (mInventoryGalleryMenu && mSelectedItemID.notNull()) + { + mInventoryGalleryMenu->doToSelected("rename", mSelectedItemID); + } + handled = TRUE; + break; + + case KEY_PAGE_UP: + mFilterSubString.clear(); + if (mScrollPanel) + { + mScrollPanel->pageUp(30); + } + handled = TRUE; + break; + + case KEY_PAGE_DOWN: + mFilterSubString.clear(); + if (mScrollPanel) + { + mScrollPanel->pageDown(30); + } + handled = TRUE; + break; + + case KEY_HOME: + mFilterSubString.clear(); + if (mScrollPanel) + { + mScrollPanel->goToTop(); + } + handled = TRUE; + break; + + case KEY_END: + mFilterSubString.clear(); + if (mScrollPanel) + { + mScrollPanel->goToBottom(); + } + handled = TRUE; + break; + + default: + break; + } + + if (handled) + { + mInventoryGalleryMenu->hide(); + } + + return handled; +} + void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id) { if (mInventoryGalleryMenu && item_id.notNull()) -- cgit v1.2.3 From ac5c62de965f3e6547cec657bb97c55ebaa40c53 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 3 Jun 2023 01:07:34 +0300 Subject: SL-19795 Fixed gallery autoscrolling --- indra/newview/llinventorygallery.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index f4bd98a9f7..f791521e3e 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1008,7 +1008,7 @@ void LLInventoryGallery::scrollToShowItem(const LLUUID& item_id) const LLRect visible_content_rect = mScrollPanel->getVisibleContentRect(); LLRect item_rect; - item->localRectToOtherView(item->getLocalRect(), &item_rect, this); + item->localRectToOtherView(item->getLocalRect(), &item_rect, mScrollPanel); LLRect overlap_rect(item_rect); overlap_rect.intersectWith(visible_content_rect); @@ -1020,7 +1020,7 @@ void LLInventoryGallery::scrollToShowItem(const LLUUID& item_id) constraint_rect.setOriginAndSize(0, 0, content_rect.getWidth(), content_rect.getHeight()); LLRect item_doc_rect; - item->localRectToOtherView(item->getLocalRect(), &item_doc_rect, this); + item->localRectToOtherView(item->getLocalRect(), &item_doc_rect, mGalleryPanel); mScrollPanel->scrollToShowRect( item_doc_rect, constraint_rect ); } -- cgit v1.2.3 From fb248ad2bc106bad827e624b4bb6b99a3f97d266 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 3 Jun 2023 02:05:17 +0300 Subject: SL-19815 Gallery support for left, right, up and down --- indra/newview/llinventorygallery.cpp | 53 +++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index f791521e3e..80bfbb8d23 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -421,8 +421,9 @@ void LLInventoryGallery::addToGallery(LLInventoryGalleryItem* item) mHiddenItems.push_back(item); return; } + mItemIndexMap[item] = mItemsAddedCount; + mIndexToItemMap[mItemsAddedCount] = item; mItemsAddedCount++; - mItemIndexMap[item] = mItemsAddedCount - 1; int n = mItemsAddedCount; int row_count = (n % mItemsInRow) == 0 ? n / mItemsInRow : n / mItemsInRow + 1; int n_prev = n - 1; @@ -458,6 +459,7 @@ void LLInventoryGallery::removeFromGalleryLast(LLInventoryGalleryItem* item) int row_count = (n % mItemsInRow) == 0 ? n / mItemsInRow : n / mItemsInRow + 1; int row_count_prev = (n_prev % mItemsInRow) == 0 ? n_prev / mItemsInRow : n_prev / mItemsInRow + 1; mItemsAddedCount--; + mIndexToItemMap.erase(mItemsAddedCount); bool remove_row = row_count != row_count_prev; removeFromLastRow(mItems[mItemsAddedCount]); @@ -483,6 +485,7 @@ void LLInventoryGallery::removeFromGalleryMiddle(LLInventoryGalleryItem* item) } int n = mItemIndexMap[item]; mItemIndexMap.erase(item); + mIndexToItemMap.erase(n); std::vector saved; for (int i = mItemsAddedCount - 1; i > n; i--) { @@ -949,6 +952,54 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) handled = TRUE; break; + case KEY_LEFT: + mFilterSubString.clear(); + + if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) + { + LLInventoryGalleryItem* item = getSelectedItem(); + if (item) + { + // Might be better to get item from panel + S32 n = mItemIndexMap[item]; + if (n == 0) + { + n = mItemsAddedCount - 1; + } + n--; + item = mIndexToItemMap[n]; + LLUUID item_id = item->getUUID(); + changeItemSelection(item_id, true); + item->setFocus(TRUE); + + } + } + handled = TRUE; + break; + + case KEY_RIGHT: + mFilterSubString.clear(); + + if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) + { + LLInventoryGalleryItem* item = getSelectedItem(); + if (item) + { + S32 n = mItemIndexMap[item]; + n++; + if (n == mItemsAddedCount) + { + n = 0; + } + item = mIndexToItemMap[n]; + LLUUID item_id = item->getUUID(); + changeItemSelection(item_id, true); + item->setFocus(TRUE); + } + } + handled = TRUE; + break; + default: break; } -- cgit v1.2.3 From 11457017a1d0f9eeb365186dc09a6a68a895c623 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 3 Jun 2023 02:10:30 +0300 Subject: SL-19815 Return key should open items in gallery view --- indra/newview/llinventorygallery.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 80bfbb8d23..a6cadea712 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -877,6 +877,14 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) setRootFolder(mSelectedItemID); handled = TRUE; } + else + { + LLViewerInventoryItem* item = gInventory.getItem(mSelectedItemID); + if (item) + { + LLInvFVBridgeAction::doAction(item->getType(), mSelectedItemID, &gInventory); + } + } } break; case KEY_DELETE: -- cgit v1.2.3 From 73afbd1a7788ba033e071fbf00b0758e6c883745 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 7 Jun 2023 22:53:50 +0300 Subject: SL-19815 Properly implement up and down keys --- indra/newview/llinventorygallery.cpp | 84 +++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index a6cadea712..1610ef7f34 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -970,11 +970,11 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) { // Might be better to get item from panel S32 n = mItemIndexMap[item]; - if (n == 0) + n--; + if (n < 0) { n = mItemsAddedCount - 1; } - n--; item = mIndexToItemMap[n]; LLUUID item_id = item->getUUID(); changeItemSelection(item_id, true); @@ -1008,6 +1008,16 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) handled = TRUE; break; + case KEY_UP: + scrollUp(); + handled = TRUE; + break; + + case KEY_DOWN: + scrollDown(); + handled = TRUE; + break; + default: break; } @@ -1020,6 +1030,50 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) return handled; } +void LLInventoryGallery::scrollUp() +{ + mFilterSubString.clear(); + + if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) + { + LLInventoryGalleryItem* item = getSelectedItem(); + if (item) + { + S32 n = mItemIndexMap[item]; + n -= mItemsInRow; + if (n >= 0) + { + item = mIndexToItemMap[n]; + LLUUID item_id = item->getUUID(); + changeItemSelection(item_id, true); + item->setFocus(TRUE); + } + } + } +} + +void LLInventoryGallery::scrollDown() +{ + mFilterSubString.clear(); + + if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) + { + LLInventoryGalleryItem* item = getSelectedItem(); + if (item) + { + S32 n = mItemIndexMap[item]; + n += mItemsInRow; + if (n < mItemsAddedCount) + { + item = mIndexToItemMap[n]; + LLUUID item_id = item->getUUID(); + changeItemSelection(item_id, true); + item->setFocus(TRUE); + } + } + } +} + void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id) { if (mInventoryGalleryMenu && item_id.notNull()) @@ -1690,6 +1744,32 @@ BOOL LLInventoryGalleryItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL dro return baseHandleDragAndDrop(mUUID, drop, cargo_type, cargo_data, accept, tooltip_msg); } +BOOL LLInventoryGalleryItem::handleKeyHere(KEY key, MASK mask) +{ + if (!mGallery) + { + return FALSE; + } + + BOOL handled = FALSE; + switch (key) + { + case KEY_UP: + mGallery->scrollUp(); + handled = true; + break; + + case KEY_DOWN: + mGallery->scrollDown(); + handled = true; + break; + + default: + break; + } + return handled; +} + void LLInventoryGalleryItem::setWorn(bool value) { mWorn = value; -- cgit v1.2.3 From 2f8227473514b864f7806af031d3c1168b3279aa Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 7 Jun 2023 23:26:29 +0300 Subject: SL-19815 Small handling rearrangement --- indra/newview/llinventorygallery.cpp | 112 +++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 46 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 1610ef7f34..63a706a9d6 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -961,60 +961,22 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) break; case KEY_LEFT: - mFilterSubString.clear(); - - if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) - { - LLInventoryGalleryItem* item = getSelectedItem(); - if (item) - { - // Might be better to get item from panel - S32 n = mItemIndexMap[item]; - n--; - if (n < 0) - { - n = mItemsAddedCount - 1; - } - item = mIndexToItemMap[n]; - LLUUID item_id = item->getUUID(); - changeItemSelection(item_id, true); - item->setFocus(TRUE); - - } - } + moveLeft(); handled = TRUE; break; case KEY_RIGHT: - mFilterSubString.clear(); - - if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) - { - LLInventoryGalleryItem* item = getSelectedItem(); - if (item) - { - S32 n = mItemIndexMap[item]; - n++; - if (n == mItemsAddedCount) - { - n = 0; - } - item = mIndexToItemMap[n]; - LLUUID item_id = item->getUUID(); - changeItemSelection(item_id, true); - item->setFocus(TRUE); - } - } + moveRight(); handled = TRUE; break; case KEY_UP: - scrollUp(); + moveUp(); handled = TRUE; break; case KEY_DOWN: - scrollDown(); + moveDown(); handled = TRUE; break; @@ -1030,7 +992,7 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) return handled; } -void LLInventoryGallery::scrollUp() +void LLInventoryGallery::moveUp() { mFilterSubString.clear(); @@ -1052,7 +1014,7 @@ void LLInventoryGallery::scrollUp() } } -void LLInventoryGallery::scrollDown() +void LLInventoryGallery::moveDown() { mFilterSubString.clear(); @@ -1074,6 +1036,53 @@ void LLInventoryGallery::scrollDown() } } +void LLInventoryGallery::moveLeft() +{ + mFilterSubString.clear(); + + if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) + { + LLInventoryGalleryItem* item = getSelectedItem(); + if (item) + { + // Might be better to get item from panel + S32 n = mItemIndexMap[item]; + n--; + if (n < 0) + { + n = mItemsAddedCount - 1; + } + item = mIndexToItemMap[n]; + LLUUID item_id = item->getUUID(); + changeItemSelection(item_id, true); + item->setFocus(TRUE); + } + } +} + +void LLInventoryGallery::moveRight() +{ + mFilterSubString.clear(); + + if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) + { + LLInventoryGalleryItem* item = getSelectedItem(); + if (item) + { + S32 n = mItemIndexMap[item]; + n++; + if (n == mItemsAddedCount) + { + n = 0; + } + item = mIndexToItemMap[n]; + LLUUID item_id = item->getUUID(); + changeItemSelection(item_id, true); + item->setFocus(TRUE); + } + } +} + void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id) { if (mInventoryGalleryMenu && item_id.notNull()) @@ -1754,13 +1763,24 @@ BOOL LLInventoryGalleryItem::handleKeyHere(KEY key, MASK mask) BOOL handled = FALSE; switch (key) { + + case KEY_LEFT: + mGallery->moveLeft(); + handled = true; + break; + + case KEY_RIGHT: + mGallery->moveRight(); + handled = true; + break; + case KEY_UP: - mGallery->scrollUp(); + mGallery->moveUp(); handled = true; break; case KEY_DOWN: - mGallery->scrollDown(); + mGallery->moveDown(); handled = true; break; -- cgit v1.2.3 From 53fc42fe032c2aef453f420645b0e46dea4c23db Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 8 Jun 2023 22:50:12 +0300 Subject: SL-19832 Inventory gallery should support CTRL+X, C and V --- indra/newview/llinventorygallery.cpp | 235 ++++++++++++++++++++++++++++++++++- 1 file changed, 234 insertions(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 63a706a9d6..eff43e33ca 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -29,6 +29,7 @@ #include "llinventorygallery.h" #include "llinventorygallerymenu.h" +#include "llclipboard.h" #include "llcommonutils.h" #include "lliconctrl.h" #include "llinventorybridge.h" @@ -133,6 +134,11 @@ BOOL LLInventoryGallery::postBuild() LLInventoryGallery::~LLInventoryGallery() { + if (gEditMenuHandler == this) + { + gEditMenuHandler = NULL; + } + delete mInventoryGalleryMenu; delete mRootGalleryMenu; delete mFilter; @@ -1009,6 +1015,7 @@ void LLInventoryGallery::moveUp() LLUUID item_id = item->getUUID(); changeItemSelection(item_id, true); item->setFocus(TRUE); + claimEditHandler(); } } } @@ -1031,6 +1038,7 @@ void LLInventoryGallery::moveDown() LLUUID item_id = item->getUUID(); changeItemSelection(item_id, true); item->setFocus(TRUE); + claimEditHandler(); } } } @@ -1056,6 +1064,7 @@ void LLInventoryGallery::moveLeft() LLUUID item_id = item->getUUID(); changeItemSelection(item_id, true); item->setFocus(TRUE); + claimEditHandler(); } } } @@ -1079,6 +1088,7 @@ void LLInventoryGallery::moveRight() LLUUID item_id = item->getUUID(); changeItemSelection(item_id, true); item->setFocus(TRUE); + claimEditHandler(); } } } @@ -1154,6 +1164,227 @@ LLInventoryGalleryItem* LLInventoryGallery::getSelectedItem() return mItemMap[mSelectedItemID]; } +void LLInventoryGallery::copy() +{ + LLClipboard::instance().reset(); + if (getVisible() && getEnabled() && mSelectedItemID.notNull()) + { + LLClipboard::instance().addToClipboard(mSelectedItemID); + } + mFilterSubString.clear(); +} + +BOOL LLInventoryGallery::canCopy() const +{ + if (!getVisible() || !getEnabled() || mSelectedItemID.isNull()) + { + return FALSE; + } + + if (!isItemCopyable(mSelectedItemID)) + { + return FALSE; + } + + return TRUE; +} + +void LLInventoryGallery::cut() +{ + // clear the inventory clipboard + LLClipboard::instance().reset(); + if (getVisible() && getEnabled() && mSelectedItemID.notNull()) + { + // todo: fade out selected item + LLClipboard::instance().setCutMode(true); + LLClipboard::instance().addToClipboard(mSelectedItemID); + } + mFilterSubString.clear(); +} + +BOOL LLInventoryGallery::canCut() const +{ + if (!getVisible() || !getEnabled() || mSelectedItemID.isNull()) + { + return FALSE; + } + + LLViewerInventoryCategory* cat = gInventory.getCategory(mSelectedItemID); + if (cat) + { + if (!get_is_category_removable(&gInventory, mSelectedItemID)) + { + return FALSE; + } + } + else if (!get_is_item_removable(&gInventory, mSelectedItemID)) + { + return FALSE; + } + + return TRUE; +} + +void LLInventoryGallery::paste() +{ + const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + if (gInventory.isObjectDescendentOf(mSelectedItemID, marketplacelistings_id)) + { + return; + } + + LLInventoryObject* obj = gInventory.getObject(mSelectedItemID); + bool is_folder = obj && (obj->getType() == LLAssetType::AT_CATEGORY); + LLUUID dest = is_folder ? mSelectedItemID : mFolderID; + bool is_cut_mode = LLClipboard::instance().isCutMode(); + + std::vector objects; + LLClipboard::instance().pasteFromClipboard(objects); + for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) + { + const LLUUID& item_id = (*iter); + if (gInventory.isObjectDescendentOf(item_id, marketplacelistings_id) && (LLMarketplaceData::instance().isInActiveFolder(item_id) || + LLMarketplaceData::instance().isListedAndActive(item_id))) + { + return; + } + LLViewerInventoryCategory* cat = gInventory.getCategory(item_id); + if (cat) + { + if (is_cut_mode) + { + gInventory.changeCategoryParent(cat, dest, false); + } + else + { + copy_inventory_category(&gInventory, cat, dest); + } + } + else + { + LLViewerInventoryItem* item = gInventory.getItem(item_id); + if (item) + { + if (is_cut_mode) + { + gInventory.changeItemParent(item, dest, false); + } + else + { + if (item->getIsLinkType()) + { + link_inventory_object(dest, item_id, + LLPointer(NULL)); + } + else + { + copy_inventory_item( + gAgent.getID(), + item->getPermissions().getOwner(), + item->getUUID(), + dest, + std::string(), + LLPointer(NULL)); + } + } + } + } + } + // todo: scroll to item on arrival + LLClipboard::instance().setCutMode(false); +} + +BOOL LLInventoryGallery::canPaste() const +{ + // Return FALSE on degenerated cases: empty clipboard, no inventory, no agent + if (!LLClipboard::instance().hasContents()) + { + return FALSE; + } + + // In cut mode, whatever is on the clipboard is always pastable + if (LLClipboard::instance().isCutMode()) + { + return TRUE; + } + + // In normal mode, we need to check each element of the clipboard to know if we can paste or not + std::vector objects; + LLClipboard::instance().pasteFromClipboard(objects); + S32 count = objects.size(); + for (S32 i = 0; i < count; i++) + { + const LLUUID& item_id = objects.at(i); + + // Each item must be copyable to be pastable + if (!isItemCopyable(item_id)) + { + return FALSE; + } + } + return TRUE; +} + +void LLInventoryGallery::claimEditHandler() +{ + gEditMenuHandler = this; +} + +bool LLInventoryGallery::isItemCopyable(const LLUUID & item_id) +{ + const LLInventoryCategory* cat = gInventory.getCategory(item_id); + if (cat) + { + // Folders are copyable if items in them are, recursively, copyable. + // Get the content of the folder + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(item_id, cat_array, item_array); + + // Check the items + LLInventoryModel::item_array_t item_array_copy = *item_array; + for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) + { + LLInventoryItem* item = *iter; + if (!isItemCopyable(item->getUUID())) + { + return false; + } + } + + // Check the folders + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLViewerInventoryCategory* category = *iter; + if (!isItemCopyable(category->getUUID())) + { + return false; + } + } + + return true; + } + + LLViewerInventoryItem* item = gInventory.getItem(item_id); + if (item) + { + // Can't copy worn objects. + // Worn objects are tied to their inworld conterparts + // Copy of modified worn object will return object with obsolete asset and inventory + if (get_is_item_worn(item_id)) + { + return false; + } + + static LLCachedControl inventory_linking(gSavedSettings, "InventoryLinking", true); + return (item->getIsLinkType() && inventory_linking) + || item->getPermissions().allowCopyBy(gAgent.getID()); + } + + return false; +} + void LLInventoryGallery::updateMessageVisibility() { @@ -1666,6 +1897,7 @@ void LLInventoryGalleryItem::setSelected(bool value) BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) { setFocus(TRUE); + mGallery->claimEditHandler(); gFocusMgr.setMouseCapture(this); S32 screen_x; @@ -1678,6 +1910,8 @@ BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLInventoryGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) { setFocus(TRUE); + mGallery->claimEditHandler(); + return LLUICtrl::handleRightMouseDown(x, y, mask); } @@ -1763,7 +1997,6 @@ BOOL LLInventoryGalleryItem::handleKeyHere(KEY key, MASK mask) BOOL handled = FALSE; switch (key) { - case KEY_LEFT: mGallery->moveLeft(); handled = true; -- cgit v1.2.3 From a358acf86ddf19aab96ad26a8f4db9cf609bdce7 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 9 Jun 2023 00:34:03 +0300 Subject: SL-19845 Show delete confirmation for 'delete' key --- indra/newview/llinventorygallery.cpp | 59 +++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 17 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index eff43e33ca..189fb33334 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -46,6 +46,7 @@ #include "llfriendcard.h" #include "llgesturemgr.h" #include "llmarketplacefunctions.h" +#include "llnotificationsutil.h" #include "lloutfitobserver.h" #include "lltrans.h" #include "llviewerassettype.h" @@ -901,23 +902,7 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) // Note: on Mac laptop keyboards, backspace and delete are one and the same if (mSelectedItemID.notNull()) { - LLViewerInventoryCategory* category = gInventory.getCategory(mSelectedItemID); - if (category) - { - if (get_is_category_removable(&gInventory, mSelectedItemID)) - { - gInventory.removeCategory(mSelectedItemID); - handled = TRUE; - } - } - else - { - if (get_is_item_removable(&gInventory, mSelectedItemID)) - { - gInventory.removeItem(mSelectedItemID); - handled = TRUE; - } - } + deleteSelection(); } break; @@ -1325,6 +1310,46 @@ BOOL LLInventoryGallery::canPaste() const return TRUE; } +void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response, const LLUUID& selected_id) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option == 0) + { + LLInventoryObject* obj = gInventory.getObject(selected_id); + if (!obj) + { + return; + } + if (obj->getType() == LLAssetType::AT_CATEGORY) + { + if (get_is_category_removable(&gInventory, selected_id)) + { + gInventory.removeCategory(selected_id); + } + } + else + { + if (get_is_item_removable(&gInventory, selected_id)) + { + gInventory.removeItem(selected_id); + } + } + } +} + +void LLInventoryGallery::deleteSelection() +{ + if (!LLInventoryAction::sDeleteConfirmationDisplayed) // ask for the confirmation at least once per session + { + LLNotifications::instance().setIgnored("DeleteItems", false); + LLInventoryAction::sDeleteConfirmationDisplayed = true; + } + + LLSD args; + args["QUESTION"] = LLTrans::getString("DeleteItem"); + LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemID)); +} + void LLInventoryGallery::claimEditHandler() { gEditMenuHandler = this; -- cgit v1.2.3 From aede902040625b145d36812a3ef29e7677cb1154 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 9 Jun 2023 20:10:46 +0300 Subject: SL-19826 WIP Pasting folders in Single folder view does not give feedback of where the folder is pasted Should resort freshly inserted or dropped folders, does not cover pasting yet --- indra/newview/llinventorygallery.cpp | 64 +++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 9 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 189fb33334..358b4e457a 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -59,8 +59,6 @@ static LLPanelInjector t_inventory_gallery("inventory_galler const S32 GALLERY_ITEMS_PER_ROW_MIN = 2; // Helper dnd functions -BOOL baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); BOOL dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, BOOL drop, std::string& tooltip_msg, BOOL is_link); BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg, BOOL user_confirm); void dropToMyOutfits(LLInventoryCategory* inv_cat); @@ -87,6 +85,7 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mRowPanWidthFactor(p.row_panel_width_factor), mGalleryWidthFactor(p.gallery_width_factor), mIsInitialized(false), + mNeedsArrange(false), mSearchType(LLInventoryFilter::SEARCHTYPE_NAME) { updateGalleryWidth(); @@ -143,6 +142,8 @@ LLInventoryGallery::~LLInventoryGallery() delete mInventoryGalleryMenu; delete mRootGalleryMenu; delete mFilter; + + gIdleCallbacks.deleteFunction(onIdle, this); while (!mUnusedRowPanels.empty()) { @@ -175,6 +176,8 @@ LLInventoryGallery::~LLInventoryGallery() void LLInventoryGallery::setRootFolder(const LLUUID cat_id) { + gIdleCallbacks.deleteFunction(onIdle, this); + LLViewerInventoryCategory* category = gInventory.getCategory(cat_id); if(!category || (mFolderID == cat_id)) { @@ -688,6 +691,33 @@ bool LLInventoryGallery::checkAgainstFilters(LLInventoryGalleryItem* item, const return !hidden; } +void LLInventoryGallery::onIdle(void* userdata) +{ + LLInventoryGallery* self = (LLInventoryGallery*)userdata; + + if (!self->mIsInitialized || !self->mGalleryCreated) + { + self->mNeedsArrange = false; + return; + } + + if (self->mNeedsArrange) + { + self->mNeedsArrange = false; + self->reArrangeRows(); + } + + if (self->mItemToSelect.notNull()) + { + self->changeItemSelection(self->mItemToSelect, true); + } + + if (self->mItemToSelect.isNull()) + { + gIdleCallbacks.deleteFunction(onIdle, (void*)self); + } +} + void LLInventoryGallery::setSearchType(LLInventoryFilter::ESearchType type) { if(mSearchType != type) @@ -1090,14 +1120,13 @@ void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLU void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_to_selection) { - if ((mItemMap.count(item_id) == 0)) + if ((mItemMap.count(item_id) == 0) || mNeedsArrange) { mItemToSelect = item_id; return; } if (mSelectedItemID != item_id) { - if (mItemMap[mSelectedItemID]) { mItemMap[mSelectedItemID]->setSelected(FALSE); @@ -1441,6 +1470,7 @@ void LLInventoryGallery::refreshList(const LLUUID& category_id) { const LLUUID cat_id = (*iter); updateAddedItem(cat_id); + mNeedsArrange = true; } // Handle removed tabs. @@ -1462,11 +1492,14 @@ void LLInventoryGallery::refreshList(const LLUUID& category_id) } updateChangedItemName(*items_iter, obj->getName()); + mNeedsArrange = true; } - if(mItemToSelect.notNull()) + if(mNeedsArrange || mItemToSelect.notNull()) { - changeItemSelection(mItemToSelect, true); + // Don't scroll to target/arrange immediately + // since more updates might be pending + gIdleCallbacks.addFunction(onIdle, (void*)this); } updateMessageVisibility(); } @@ -2009,7 +2042,7 @@ BOOL LLInventoryGalleryItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL dro { return FALSE; } - return baseHandleDragAndDrop(mUUID, drop, cargo_type, cargo_data, accept, tooltip_msg); + return mGallery->baseHandleDragAndDrop(mUUID, drop, cargo_type, cargo_data, accept, tooltip_msg); } BOOL LLInventoryGalleryItem::handleKeyHere(KEY key, MASK mask) @@ -2178,7 +2211,7 @@ void LLThumbnailsObserver::removeSkippedItem(const LLUUID& obj_id) // Helper drag&drop functions //----------------------------- -BOOL baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, +BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, EAcceptance* accept, @@ -2203,6 +2236,10 @@ BOOL baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, case DAD_MESH: case DAD_SETTINGS: accepted = dragItemIntoFolder(dest_id, inv_item, drop, tooltip_msg, true); + if (accepted && drop) + { + mItemToSelect = inv_item->getUUID(); + } break; case DAD_LINK: // DAD_LINK type might mean one of two asset types: AT_LINK or AT_LINK_FOLDER. @@ -2220,6 +2257,10 @@ BOOL baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, { accepted = dragItemIntoFolder(dest_id, inv_item, drop, tooltip_msg, TRUE); } + if (accepted && drop) + { + mItemToSelect = inv_item->getUUID(); + } break; case DAD_CATEGORY: if (LLFriendCardsManager::instance().isAnyFriendCategory(dest_id)) @@ -2228,7 +2269,12 @@ BOOL baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, } else { - accepted = dragCategoryIntoFolder(dest_id, (LLInventoryCategory*)cargo_data, drop, tooltip_msg, FALSE); + LLInventoryCategory* cat_ptr = (LLInventoryCategory*)cargo_data; + accepted = dragCategoryIntoFolder(dest_id, cat_ptr, drop, tooltip_msg, FALSE); + if (accepted && drop) + { + mItemToSelect = cat_ptr->getUUID(); + } } break; case DAD_ROOT_CATEGORY: -- cgit v1.2.3 From 5c6a2779c498e69e36276700283ccfb4bdbfd438 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 9 Jun 2023 22:04:52 +0300 Subject: SL-19826 Pasting folders in Single folder should highlight pasted folder --- indra/newview/llinventorygallery.cpp | 150 ++++++++++++++++++++++++++++------- 1 file changed, 122 insertions(+), 28 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 358b4e457a..412e9e9c0b 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -709,7 +709,9 @@ void LLInventoryGallery::onIdle(void* userdata) if (self->mItemToSelect.notNull()) { - self->changeItemSelection(self->mItemToSelect, true); + LLUUID item_to_select = self->mItemToSelect; + self->mItemToSelect = LLUUID::null; + self->changeItemSelection(item_to_select, true); } if (self->mItemToSelect.isNull()) @@ -879,12 +881,14 @@ void LLInventoryGallery::onThumbnailAdded(LLUUID item_id) BOOL LLInventoryGallery::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if(mItemMap[mSelectedItemID]) + LLUUID old_selection = mSelectedItemID; + BOOL res = LLPanel::handleRightMouseDown(x, y, mask); + if (!res) { - mItemMap[mSelectedItemID]->setFocus(false); + clearSelection(); + mItemMap[old_selection]->setFocus(false); } - clearSelection(); - BOOL res = LLPanel::handleRightMouseDown(x, y, mask); + if (mSelectedItemID.isNull()) { if (mInventoryGalleryMenu && mFolderID.notNull()) @@ -1125,24 +1129,30 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ mItemToSelect = item_id; return; } - if (mSelectedItemID != item_id) + if (mSelectedItemID == item_id) { - if (mItemMap[mSelectedItemID]) - { - mItemMap[mSelectedItemID]->setSelected(FALSE); - } - if (mItemMap[item_id]) - { - mItemMap[item_id]->setSelected(TRUE); - } - mSelectedItemID = item_id; - signalSelectionItemID(item_id); + return; + } + if (mNeedsArrange && item_id.notNull() && scroll_to_selection) + { + mItemToSelect = item_id; + return; + } - mItemToSelect = LLUUID::null; - if(scroll_to_selection) - { - scrollToShowItem(mSelectedItemID); - } + if (mItemMap[mSelectedItemID]) + { + mItemMap[mSelectedItemID]->setSelected(FALSE); + } + if (mItemMap[item_id]) + { + mItemMap[item_id]->setSelected(TRUE); + } + mSelectedItemID = item_id; + signalSelectionItemID(item_id); + + if (scroll_to_selection) + { + scrollToShowItem(mSelectedItemID); } } @@ -1241,6 +1251,11 @@ BOOL LLInventoryGallery::canCut() const void LLInventoryGallery::paste() { + if (!LLClipboard::instance().hasContents()) + { + return; + } + const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); if (gInventory.isObjectDescendentOf(mSelectedItemID, marketplacelistings_id)) { @@ -1254,6 +1269,20 @@ void LLInventoryGallery::paste() std::vector objects; LLClipboard::instance().pasteFromClipboard(objects); + + LLHandle handle = getHandle(); + std::function on_copy_callback = [handle](const LLUUID& inv_item) + { + LLInventoryGallery* panel = (LLInventoryGallery*)handle.get(); + if (panel) + { + // Scroll to pasted item and highlight it + // Should it only highlight the last one? + panel->changeItemSelection(inv_item, true); + } + }; + LLPointer cb = new LLBoostFuncInventoryCallback(on_copy_callback); + for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) { const LLUUID& item_id = (*iter); @@ -1268,10 +1297,12 @@ void LLInventoryGallery::paste() if (is_cut_mode) { gInventory.changeCategoryParent(cat, dest, false); + // Don't select immediately, wait for item to arrive + mItemToSelect = item_id; } else { - copy_inventory_category(&gInventory, cat, dest); + copy_inventory_category(&gInventory, cat, dest, LLUUID::null, false, on_copy_callback); } } else @@ -1282,13 +1313,14 @@ void LLInventoryGallery::paste() if (is_cut_mode) { gInventory.changeItemParent(item, dest, false); + // Don't select immediately, wait for item to arrive + mItemToSelect = item_id; } else { if (item->getIsLinkType()) { - link_inventory_object(dest, item_id, - LLPointer(NULL)); + link_inventory_object(dest, item_id, cb); } else { @@ -1298,13 +1330,13 @@ void LLInventoryGallery::paste() item->getUUID(), dest, std::string(), - LLPointer(NULL)); + cb); } } } } } - // todo: scroll to item on arrival + LLClipboard::instance().setCutMode(false); } @@ -1379,6 +1411,66 @@ void LLInventoryGallery::deleteSelection() LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemID)); } +void LLInventoryGallery::pasteAsLink() +{ + if (!LLClipboard::instance().hasContents()) + { + return; + } + + const LLUUID& current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID& my_outifts_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + + LLUUID dest; + LLInventoryObject* obj = gInventory.getObject(mSelectedItemID); + if (obj && obj->getType() == LLAssetType::AT_CATEGORY) + { + dest = mSelectedItemID; + } + else + { + dest = mFolderID; + } + + const BOOL move_is_into_current_outfit = (dest == current_outfit_id); + const BOOL move_is_into_my_outfits = (dest == my_outifts_id) || gInventory.isObjectDescendentOf(dest, my_outifts_id); + const BOOL move_is_into_marketplacelistings = gInventory.isObjectDescendentOf(dest, marketplacelistings_id); + + if (move_is_into_marketplacelistings || move_is_into_current_outfit || move_is_into_my_outfits) + { + return; + } + std::vector objects; + LLClipboard::instance().pasteFromClipboard(objects); + + LLHandle handle = getHandle(); + std::function on_link_callback = [handle](const LLUUID& inv_item) + { + LLInventoryGallery *panel = (LLInventoryGallery*)handle.get(); + if (panel) + { + // Scroll to pasted item and highlight it + // Should it only highlight the last one? + panel->changeItemSelection(inv_item, true); + } + }; + LLPointer cb = new LLBoostFuncInventoryCallback(on_link_callback); + + for (std::vector::const_iterator iter = objects.begin(); + iter != objects.end(); + ++iter) + { + const LLUUID& object_id = (*iter); + if (LLConstPointer link_obj = gInventory.getObject(object_id)) + { + link_inventory_object(dest, link_obj, cb); + } + } + + LLClipboard::instance().setCutMode(false); +} + void LLInventoryGallery::claimEditHandler() { gEditMenuHandler = this; @@ -1970,7 +2062,8 @@ BOOL LLInventoryGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) setFocus(TRUE); mGallery->claimEditHandler(); - return LLUICtrl::handleRightMouseDown(x, y, mask); + LLUICtrl::handleRightMouseDown(x, y, mask); + return TRUE; } BOOL LLInventoryGalleryItem::handleMouseUp(S32 x, S32 y, MASK mask) @@ -2238,6 +2331,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, accepted = dragItemIntoFolder(dest_id, inv_item, drop, tooltip_msg, true); if (accepted && drop) { + // Don't select immediately, wait for item to arrive mItemToSelect = inv_item->getUUID(); } break; @@ -2257,7 +2351,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, { accepted = dragItemIntoFolder(dest_id, inv_item, drop, tooltip_msg, TRUE); } - if (accepted && drop) + if (accepted && drop && inv_item) { mItemToSelect = inv_item->getUUID(); } -- cgit v1.2.3 From 417dbeb68ef842a8eee22ebab35c89ddee653619 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 10 Jun 2023 01:33:43 +0300 Subject: SL-19823 Edit not always active #5 --- indra/newview/llinventorygallery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 412e9e9c0b..898bcba494 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1133,7 +1133,7 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ { return; } - if (mNeedsArrange && item_id.notNull() && scroll_to_selection) + if (mNeedsArrange && item_id.notNull()) { mItemToSelect = item_id; return; -- cgit v1.2.3 From 14aa4dcdc23feafc537f06e49c48e9d693300103 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 10 Jun 2023 02:28:48 +0300 Subject: SL-19847 Delete key should not allow system folders --- indra/newview/llinventorygallery.cpp | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 898bcba494..5edcb3148c 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -934,7 +934,7 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) #endif // Delete selected items if delete or backspace key hit on the inventory panel // Note: on Mac laptop keyboards, backspace and delete are one and the same - if (mSelectedItemID.notNull()) + if (canDeleteSelection()) { deleteSelection(); } @@ -1411,6 +1411,30 @@ void LLInventoryGallery::deleteSelection() LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemID)); } +bool LLInventoryGallery::canDeleteSelection() +{ + if (mSelectedItemID.isNull()) + { + return false; + } + + LLViewerInventoryCategory* cat = gInventory.getCategory(mSelectedItemID); + if (cat) + { + if (!get_is_category_removable(&gInventory, mSelectedItemID)) + { + return false; + } + } + else if (!get_is_item_removable(&gInventory, mSelectedItemID)) + { + return false; + } + + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + return !gInventory.isObjectDescendentOf(mSelectedItemID, trash_id); +} + void LLInventoryGallery::pasteAsLink() { if (!LLClipboard::instance().hasContents()) -- cgit v1.2.3 From 143e103bcf2b9be2b249ce96e7f84a52469174c7 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 14 Jun 2023 23:59:43 +0300 Subject: SL-19686 WIP Switching single folder view for large inventories causes stalls #2 --- indra/newview/llinventorygallery.cpp | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 5edcb3148c..421949d9aa 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -85,6 +85,7 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mRowPanWidthFactor(p.row_panel_width_factor), mGalleryWidthFactor(p.gallery_width_factor), mIsInitialized(false), + mRootDirty(false), mNeedsArrange(false), mSearchType(LLInventoryFilter::SEARCHTYPE_NAME) { @@ -188,7 +189,19 @@ void LLInventoryGallery::setRootFolder(const LLUUID cat_id) mBackwardFolders.push_back(mFolderID); } mFolderID = cat_id; - updateRootFolder(); + dirtyRootFolder(); +} + +void LLInventoryGallery::dirtyRootFolder() +{ + if (getVisible()) + { + updateRootFolder(); + } + else + { + mRootDirty = true; + } } void LLInventoryGallery::updateRootFolder() @@ -260,6 +273,7 @@ void LLInventoryGallery::updateRootFolder() } reArrangeRows(); mIsInitialized = true; + mRootDirty = false; if (mScrollPanel) { @@ -305,6 +319,15 @@ void LLInventoryGallery::draw() } } +void LLInventoryGallery::onVisibilityChange(BOOL new_visibility) +{ + if (new_visibility && mRootDirty) + { + updateRootFolder(); + } + LLPanel::onVisibilityChange(new_visibility); +} + bool LLInventoryGallery::updateRowsIfNeeded() { if(((getRect().getWidth() - mRowPanelWidth) > mItemWidth) && mRowCount > 1) @@ -542,6 +565,7 @@ LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, L void LLInventoryGallery::buildGalleryPanel(int row_count) { LLPanel::Params params; + params.use_bounding_rect = false; mGalleryPanel = LLUICtrlFactory::create(params); reshapeGalleryPanel(row_count); } @@ -561,11 +585,12 @@ void LLInventoryGallery::reshapeGalleryPanel(int row_count) LLPanel* LLInventoryGallery::buildItemPanel(int left) { - LLPanel::Params lpparams; int top = 0; LLPanel* lpanel = NULL; if(mUnusedItemPanels.empty()) { + LLPanel::Params lpparams; + lpparams.use_bounding_rect = false; lpanel = LLUICtrlFactory::create(lpparams); } else @@ -585,6 +610,7 @@ LLPanel* LLInventoryGallery::buildItemPanel(int left) LLPanel* LLInventoryGallery::buildRowPanel(int left, int bottom) { LLPanel::Params sparams; + sparams.use_bounding_rect = false; LLPanel* stack = NULL; if(mUnusedRowPanels.empty()) { @@ -1787,7 +1813,7 @@ void LLInventoryGallery::onForwardFolder() mBackwardFolders.push_back(mFolderID); mFolderID = mForwardFolders.back(); mForwardFolders.pop_back(); - updateRootFolder(); + dirtyRootFolder(); } } @@ -1798,7 +1824,7 @@ void LLInventoryGallery::onBackwardFolder() mForwardFolders.push_back(mFolderID); mFolderID = mBackwardFolders.back(); mBackwardFolders.pop_back(); - updateRootFolder(); + dirtyRootFolder(); } } -- cgit v1.2.3 From 275fa896c0cc35acee24d7fc4e952ab73428b7f8 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 15 Jun 2023 00:27:11 +0300 Subject: SL-19686 WIP Switching single folder view for large inventories causes stalls #3 --- indra/newview/llinventorygallery.cpp | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 421949d9aa..fe9605daa8 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -545,12 +545,11 @@ void LLInventoryGallery::removeFromLastRow(LLInventoryGalleryItem* item) LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, LLInventoryType::EType inventory_type, U32 flags, bool is_link, bool is_worn) { LLInventoryGalleryItem::Params giparams; + giparams.visible = true; + giparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); + giparams.rect(LLRect(0,mItemHeight, mItemWidth, 0)); + giparams.name = name; LLInventoryGalleryItem* gitem = LLUICtrlFactory::create(giparams); - gitem->reshape(mItemWidth, mItemHeight); - gitem->setVisible(true); - gitem->setFollowsLeft(); - gitem->setFollowsTop(); - gitem->setName(name); gitem->setUUID(item_id); gitem->setGallery(this); gitem->setType(type, inventory_type, flags, is_link); @@ -565,6 +564,8 @@ LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, L void LLInventoryGallery::buildGalleryPanel(int row_count) { LLPanel::Params params; + params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); + params.visible = true; params.use_bounding_rect = false; mGalleryPanel = LLUICtrlFactory::create(params); reshapeGalleryPanel(row_count); @@ -578,9 +579,6 @@ void LLInventoryGallery::reshapeGalleryPanel(int row_count) LLRect rect = LLRect(left, bottom + height, left + mGalleryWidth, bottom); mGalleryPanel->setRect(rect); mGalleryPanel->reshape(mGalleryWidth, height); - mGalleryPanel->setVisible(true); - mGalleryPanel->setFollowsLeft(); - mGalleryPanel->setFollowsTop(); } LLPanel* LLInventoryGallery::buildItemPanel(int left) @@ -590,6 +588,9 @@ LLPanel* LLInventoryGallery::buildItemPanel(int left) if(mUnusedItemPanels.empty()) { LLPanel::Params lpparams; + lpparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); + lpparams.visible = true; + lpparams.rect(LLRect(left, top + mItemHeight, left + mItemWidth + mItemHorizontalGap, top)); lpparams.use_bounding_rect = false; lpanel = LLUICtrlFactory::create(lpparams); } @@ -597,23 +598,22 @@ LLPanel* LLInventoryGallery::buildItemPanel(int left) { lpanel = mUnusedItemPanels.back(); mUnusedItemPanels.pop_back(); + + LLRect rect = LLRect(left, top + mItemHeight, left + mItemWidth + mItemHorizontalGap, top); + lpanel->setShape(rect, false); } - LLRect rect = LLRect(left, top + mItemHeight, left + mItemWidth + mItemHorizontalGap, top); - lpanel->setRect(rect); - lpanel->reshape(mItemWidth + mItemHorizontalGap, mItemHeight); - lpanel->setVisible(true); - lpanel->setFollowsLeft(); - lpanel->setFollowsTop(); return lpanel; } LLPanel* LLInventoryGallery::buildRowPanel(int left, int bottom) { - LLPanel::Params sparams; - sparams.use_bounding_rect = false; LLPanel* stack = NULL; if(mUnusedRowPanels.empty()) { + LLPanel::Params sparams; + sparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); + sparams.use_bounding_rect = false; + sparams.visible = true; stack = LLUICtrlFactory::create(sparams); } else @@ -630,9 +630,6 @@ void LLInventoryGallery::moveRowPanel(LLPanel* stack, int left, int bottom) LLRect rect = LLRect(left, bottom + mRowPanelHeight, left + mRowPanelWidth, bottom); stack->setRect(rect); stack->reshape(mRowPanelWidth, mRowPanelHeight); - stack->setVisible(true); - stack->setFollowsLeft(); - stack->setFollowsTop(); } void LLInventoryGallery::setFilterSubString(const std::string& string) -- cgit v1.2.3 From 451a89d75b78ccf0313f5dadbe6f380136500fda Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 15 Jun 2023 22:23:29 +0300 Subject: SL-19686 WIP Split gallery initiation over frames --- indra/newview/llinventorygallery.cpp | 52 ++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 17 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index fe9605daa8..083dfdc65e 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -219,6 +219,7 @@ void LLInventoryGallery::updateRootFolder() { updateRemovedItem(mHiddenItems[i]->getUUID()); } + mItemBuildQuery.clear(); if (gInventory.containsObserver(mCategoriesObserver)) { @@ -262,16 +263,15 @@ void LLInventoryGallery::updateRootFolder() iter != cat_array->end(); iter++) { - updateAddedItem((*iter)->getUUID()); + mItemBuildQuery.insert((*iter)->getUUID()); } for (LLInventoryModel::item_array_t::const_iterator iter = item_array->begin(); iter != item_array->end(); iter++) { - updateAddedItem((*iter)->getUUID()); + mItemBuildQuery.insert((*iter)->getUUID()); } - reArrangeRows(); mIsInitialized = true; mRootDirty = false; @@ -287,6 +287,11 @@ void LLInventoryGallery::updateRootFolder() { initGallery(); } + + if (!mItemBuildQuery.empty()) + { + gIdleCallbacks.addFunction(onIdle, (void*)this); + } } void LLInventoryGallery::initGallery() @@ -640,12 +645,14 @@ void LLInventoryGallery::setFilterSubString(const std::string& string) //reArrangeRows(); } -void LLInventoryGallery::applyFilter(LLInventoryGalleryItem* item, const std::string& filter_substring) +bool LLInventoryGallery::applyFilter(LLInventoryGalleryItem* item, const std::string& filter_substring) { if(item) { item->setHidden(!checkAgainstFilters(item, filter_substring)); + return false; } + return true; } bool LLInventoryGallery::checkAgainstFilters(LLInventoryGalleryItem* item, const std::string& filter_substring) @@ -724,6 +731,21 @@ void LLInventoryGallery::onIdle(void* userdata) return; } + const F64 MAX_TIME_VISIBLE = 0.020f; + const F64 MAX_TIME_HIDDEN = 0.001f; // take it slow + const F64 max_time = self->getVisible() ? MAX_TIME_VISIBLE : MAX_TIME_HIDDEN; + F64 curent_time = LLTimer::getTotalSeconds(); + const F64 end_time = curent_time + max_time; + + while (!self->mItemBuildQuery.empty() && end_time > curent_time) + { + uuid_set_t::iterator iter = self->mItemBuildQuery.begin(); + LLUUID item_id = *iter; + self->mNeedsArrange |= self->updateAddedItem(item_id); + self->mItemBuildQuery.erase(iter); + curent_time = LLTimer::getTotalSeconds(); + } + if (self->mNeedsArrange) { self->mNeedsArrange = false; @@ -737,7 +759,7 @@ void LLInventoryGallery::onIdle(void* userdata) self->changeItemSelection(item_to_select, true); } - if (self->mItemToSelect.isNull()) + if (self->mItemToSelect.isNull() && self->mItemBuildQuery.empty()) { gIdleCallbacks.deleteFunction(onIdle, (void*)self); } @@ -768,13 +790,13 @@ void LLInventoryGallery::getCurrentCategories(uuid_vec_t& vcur) } } -void LLInventoryGallery::updateAddedItem(LLUUID item_id) +bool LLInventoryGallery::updateAddedItem(LLUUID item_id) { LLInventoryObject* obj = gInventory.getObject(item_id); if (!obj) { LL_WARNS("InventoryGallery") << "Failed to find item: " << item_id << LL_ENDL; - return; + return false; } std::string name = obj->getName(); @@ -805,18 +827,20 @@ void LLInventoryGallery::updateAddedItem(LLUUID item_id) } } + bool res = false; LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getIsLinkType(), is_worn); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); item->setRightMouseDownCallback(boost::bind(&LLInventoryGallery::showContextMenu, this, _1, _2, _3, item_id)); item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::changeItemSelection, this, item_id, false)); if (mGalleryCreated) { - applyFilter(item, mFilterSubString); + res = applyFilter(item, mFilterSubString); addToGallery(item); } mThumbnailsObserver->addItem(item_id, boost::bind(&LLInventoryGallery::updateItemThumbnail, this, item_id)); + return res; } void LLInventoryGallery::updateRemovedItem(LLUUID item_id) @@ -838,6 +862,8 @@ void LLInventoryGallery::updateRemovedItem(LLUUID item_id) item->die(); } } + + mItemBuildQuery.erase(item_id); } void LLInventoryGallery::updateChangedItemName(LLUUID item_id, std::string name) @@ -893,15 +919,6 @@ void LLInventoryGallery::updateItemThumbnail(LLUUID item_id) } } -void LLInventoryGallery::onThumbnailAdded(LLUUID item_id) -{ - if((mItemMap.count(item_id) == 0) && mFilter->checkAgainstFilterThumbnails(item_id)) - { - updateAddedItem(item_id); - reArrangeRows(); - } -} - BOOL LLInventoryGallery::handleRightMouseDown(S32 x, S32 y, MASK mask) { LLUUID old_selection = mSelectedItemID; @@ -1666,6 +1683,7 @@ void LLInventoryGallery::computeDifference( uuid_vec_t vcur; getCurrentCategories(vcur); + std::copy(mItemBuildQuery.begin(), mItemBuildQuery.end(), std::back_inserter(vcur)); LLCommonUtils::computeDifference(vnew, vcur, vadded, vremoved); } -- cgit v1.2.3 From d077558ed7fac01aae8d5a1670f4d0764ec6fbcb Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 15 Jun 2023 22:50:41 +0300 Subject: SL-19686 Fix memory leak --- indra/newview/llinventorygallery.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 083dfdc65e..caf93b924c 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -158,6 +158,13 @@ LLInventoryGallery::~LLInventoryGallery() mUnusedItemPanels.pop_back(); panelp->die(); } + while (!mHiddenItems.empty()) + { + LLPanel* panelp = mHiddenItems.back(); + mHiddenItems.pop_back(); + panelp->die(); + } + if (gInventory.containsObserver(mCategoriesObserver)) { @@ -490,6 +497,7 @@ void LLInventoryGallery::removeFromGalleryLast(LLInventoryGalleryItem* item) if(item->isHidden()) { mHiddenItems.pop_back(); + // Note: item still exists!!! return; } int n_prev = mItemsAddedCount; @@ -519,6 +527,7 @@ void LLInventoryGallery::removeFromGalleryMiddle(LLInventoryGalleryItem* item) if(item->isHidden()) { mHiddenItems.erase(std::remove(mHiddenItems.begin(), mHiddenItems.end(), item), mHiddenItems.end()); + // item still exists and needs to be deleted or used!!! return; } int n = mItemIndexMap[item]; @@ -859,6 +868,7 @@ void LLInventoryGallery::updateRemovedItem(LLUUID item_id) // kill removed item if (item != NULL) { + // Todo: instead of deleting, store somewhere to reuse later item->die(); } } @@ -1876,6 +1886,11 @@ BOOL LLInventoryGallery::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, return handled; } +bool LLInventoryGallery::areViewsInitialized() +{ + return mGalleryCreated && mItemBuildQuery.empty(); +} + bool LLInventoryGallery::hasDescendents(const LLUUID& cat_id) { LLInventoryModel::cat_array_t* cats; -- cgit v1.2.3 From 4de5576fb4bea538f3381f581d3caf54ee03fb05 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 15 Jun 2023 22:26:04 +0300 Subject: SL-19686 Remove gallery 'skipped' items Probably whole observer is not nessesary, instead we need a general observer to track a variety of changes. --- indra/newview/llinventorygallery.cpp | 41 ------------------------------------ 1 file changed, 41 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index caf93b924c..a7dfbb5938 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -2294,33 +2294,6 @@ void LLInventoryGalleryItem::updateNameText() void LLThumbnailsObserver::changed(U32 mask) { std::vector deleted_ids; - for (item_map_t::iterator iter = mSkippedItems.begin(); - iter != mSkippedItems.end(); - ++iter) - { - const LLUUID& obj_id = (*iter).first; - LLItemData& data = (*iter).second; - - LLInventoryObject* obj = gInventory.getObject(obj_id); - if (!obj) - { - deleted_ids.push_back(obj_id); - continue; - } - - const LLUUID thumbnail_id = obj->getThumbnailUUID(); - if (data.mThumbnailID != thumbnail_id) - { - data.mThumbnailID = thumbnail_id; - data.mCallback(); - } - } - for (std::vector::iterator deleted_id = deleted_ids.begin(); deleted_id != deleted_ids.end(); ++deleted_id) - { - removeSkippedItem(*deleted_id); - } - deleted_ids.clear(); - for (item_map_t::iterator iter = mItemMap.begin(); iter != mItemMap.end(); ++iter) @@ -2361,25 +2334,11 @@ bool LLThumbnailsObserver::addItem(const LLUUID& obj_id, callback_t cb) return false; } -void LLThumbnailsObserver::addSkippedItem(const LLUUID& obj_id, callback_t cb) -{ - LLInventoryObject* obj = gInventory.getObject(obj_id); - if (obj) - { - mSkippedItems.insert(item_map_value_t(obj_id, LLItemData(obj_id, obj->getThumbnailUUID(), cb))); - } -} - void LLThumbnailsObserver::removeItem(const LLUUID& obj_id) { mItemMap.erase(obj_id); } -void LLThumbnailsObserver::removeSkippedItem(const LLUUID& obj_id) -{ - mSkippedItems.erase(obj_id); -} - //----------------------------- // Helper drag&drop functions //----------------------------- -- cgit v1.2.3 From e99878083155b81c93b0c8b05f300a4501a2d775 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 16 Jun 2023 00:15:57 +0300 Subject: SL-19686 Don't reshape excessively --- indra/newview/llinventorygallery.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index a7dfbb5938..694881372d 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -379,7 +379,7 @@ void LLInventoryGallery::reArrangeRows(S32 row_diff) std::vector buf_items = mItems; for (std::vector::const_reverse_iterator it = buf_items.rbegin(); it != buf_items.rend(); ++it) { - removeFromGalleryLast(*it); + removeFromGalleryLast(*it, false); } for (std::vector::const_reverse_iterator it = mHiddenItems.rbegin(); it != mHiddenItems.rend(); ++it) { @@ -492,7 +492,7 @@ void LLInventoryGallery::addToGallery(LLInventoryGalleryItem* item) } -void LLInventoryGallery::removeFromGalleryLast(LLInventoryGalleryItem* item) +void LLInventoryGallery::removeFromGalleryLast(LLInventoryGalleryItem* item, bool needs_reshape) { if(item->isHidden()) { @@ -518,7 +518,10 @@ void LLInventoryGallery::removeFromGalleryLast(LLInventoryGalleryItem* item) } removeLastRow(); } - reshapeGalleryPanel(row_count); + if (needs_reshape) + { + reshapeGalleryPanel(row_count); + } } -- cgit v1.2.3 From 3561724b8c2b2e45a65d0adb85b4a082439a7eba Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 16 Jun 2023 00:39:12 +0300 Subject: SL-19686 Fix filtering returning wrong value --- indra/newview/llinventorygallery.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 694881372d..53b62c7fb7 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -661,10 +661,11 @@ bool LLInventoryGallery::applyFilter(LLInventoryGalleryItem* item, const std::st { if(item) { - item->setHidden(!checkAgainstFilters(item, filter_substring)); - return false; + bool visible = checkAgainstFilters(item, filter_substring); + item->setHidden(!visible); + return visible; } - return true; + return false; } bool LLInventoryGallery::checkAgainstFilters(LLInventoryGalleryItem* item, const std::string& filter_substring) @@ -762,6 +763,7 @@ void LLInventoryGallery::onIdle(void* userdata) { self->mNeedsArrange = false; self->reArrangeRows(); + self->updateMessageVisibility(); } if (self->mItemToSelect.notNull()) -- cgit v1.2.3 From d9a8ccc2c061bc034ebb6fb13b0950615d8bf30d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 16 Jun 2023 12:22:56 +0300 Subject: SL-19882 Fix LLInventoryGalleryItem redeclaring mName To avoid confusion and potential inheritance issues --- indra/newview/llinventorygallery.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 53b62c7fb7..c584def3eb 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -565,8 +565,8 @@ LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, L giparams.visible = true; giparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); giparams.rect(LLRect(0,mItemHeight, mItemWidth, 0)); - giparams.name = name; LLInventoryGalleryItem* gitem = LLUICtrlFactory::create(giparams); + gitem->setItemName(name); gitem->setUUID(item_id); gitem->setGallery(this); gitem->setType(type, inventory_type, flags, is_link); @@ -889,7 +889,7 @@ void LLInventoryGallery::updateChangedItemName(LLUUID item_id, std::string name) LLInventoryGalleryItem* item = iter->second; if (item) { - item->setName(name); + item->setItemName(name); } } } @@ -2001,7 +2001,7 @@ LLInventoryGalleryItem::LLInventoryGalleryItem(const Params& p) : LLPanel(p), mSelected(false), mDefaultImage(true), - mName(""), + mItemName(""), mWornSuffix(""), mPermSuffix(""), mUUID(LLUUID()), @@ -2117,9 +2117,9 @@ void LLInventoryGalleryItem::draw() gl_rect_2d(border, border_color.get(), FALSE); } -void LLInventoryGalleryItem::setName(std::string name) +void LLInventoryGalleryItem::setItemName(std::string name) { - mName = name; + mItemName = name; updateNameText(); } @@ -2287,9 +2287,9 @@ LLFontGL* LLInventoryGalleryItem::getTextFont() void LLInventoryGalleryItem::updateNameText() { mNameText->setFont(getTextFont()); - mNameText->setText(mName + mPermSuffix + mWornSuffix); - mNameText->setToolTip(mName + mPermSuffix + mWornSuffix); - getChild("preview_thumbnail")->setToolTip(mName + mPermSuffix + mWornSuffix); + mNameText->setText(mItemName + mPermSuffix + mWornSuffix); + mNameText->setToolTip(mItemName + mPermSuffix + mWornSuffix); + getChild("preview_thumbnail")->setToolTip(mItemName + mPermSuffix + mWornSuffix); } //----------------------------- -- cgit v1.2.3 From 26f64e4f0a007edc01996cdc0bc69121a16749b9 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 16 Jun 2023 13:06:37 +0300 Subject: SL-19873 Clear gallery selection when right-clicking outside of selected items --- indra/newview/llinventorygallery.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index c584def3eb..40c76a4b5f 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -936,13 +936,13 @@ void LLInventoryGallery::updateItemThumbnail(LLUUID item_id) BOOL LLInventoryGallery::handleRightMouseDown(S32 x, S32 y, MASK mask) { - LLUUID old_selection = mSelectedItemID; - BOOL res = LLPanel::handleRightMouseDown(x, y, mask); - if (!res) + if(mItemMap[mSelectedItemID]) { - clearSelection(); - mItemMap[old_selection]->setFocus(false); + mItemMap[mSelectedItemID]->setFocus(false); + setFocus(true); } + clearSelection(); + BOOL res = LLPanel::handleRightMouseDown(x, y, mask); if (mSelectedItemID.isNull()) { -- cgit v1.2.3 From 47c15e9dabf887a83186acf98213316fe5f807c5 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 16 Jun 2023 22:51:21 +0300 Subject: SL-19795 Slight gallery scroll improvement use scroll's rect instead of gallery's rect --- indra/newview/llinventorygallery.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 40c76a4b5f..200a9b2a91 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -342,12 +342,15 @@ void LLInventoryGallery::onVisibilityChange(BOOL new_visibility) bool LLInventoryGallery::updateRowsIfNeeded() { - if(((getRect().getWidth() - mRowPanelWidth) > mItemWidth) && mRowCount > 1) + S32 scroll_content_width = mScrollPanel ? mScrollPanel->getVisibleContentRect().getWidth() : getRect().getWidth(); + if(((scroll_content_width - mRowPanelWidth) > mItemWidth) + && mRowCount > 1) { reArrangeRows(1); return true; } - else if((mRowPanelWidth > (getRect().getWidth() + mItemHorizontalGap)) && mItemsInRow > GALLERY_ITEMS_PER_ROW_MIN) + else if((mRowPanelWidth > (scroll_content_width + mItemHorizontalGap)) + && mItemsInRow > GALLERY_ITEMS_PER_ROW_MIN) { reArrangeRows(-1); return true; -- cgit v1.2.3 From 7607047a95a8b1cb89e3007138fbb00986067c2b Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 16 Jun 2023 23:42:45 +0300 Subject: SL-19863 FIXED Items are not copied when attempting to paste into gallery mode --- indra/newview/llinventorygallery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 200a9b2a91..f81beefc28 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1315,7 +1315,7 @@ void LLInventoryGallery::paste() } const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); - if (gInventory.isObjectDescendentOf(mSelectedItemID, marketplacelistings_id)) + if (!mSelectedItemID.isNull() && gInventory.isObjectDescendentOf(mSelectedItemID, marketplacelistings_id)) { return; } -- cgit v1.2.3 From b5b0c174390b4158c69eeff7efd59c4f1615e491 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 17 Jun 2023 01:31:02 +0300 Subject: SL-19886 Fix onidle crash after closing inventory floater --- indra/newview/llinventorygallery.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index f81beefc28..cfaff512ff 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -143,8 +143,8 @@ LLInventoryGallery::~LLInventoryGallery() delete mInventoryGalleryMenu; delete mRootGalleryMenu; delete mFilter; - - gIdleCallbacks.deleteFunction(onIdle, this); + + gIdleCallbacks.deleteFunction(onIdle, (void*)this); while (!mUnusedRowPanels.empty()) { @@ -184,8 +184,6 @@ LLInventoryGallery::~LLInventoryGallery() void LLInventoryGallery::setRootFolder(const LLUUID cat_id) { - gIdleCallbacks.deleteFunction(onIdle, this); - LLViewerInventoryCategory* category = gInventory.getCategory(cat_id); if(!category || (mFolderID == cat_id)) { @@ -195,7 +193,13 @@ void LLInventoryGallery::setRootFolder(const LLUUID cat_id) { mBackwardFolders.push_back(mFolderID); } + + gIdleCallbacks.deleteFunction(onIdle, (void*)this); + mFolderID = cat_id; + mItemToSelect.setNull(); + mItemBuildQuery.clear(); + mNeedsArrange = false; dirtyRootFolder(); } -- cgit v1.2.3 From 30209314ac02cf5ac868b5207b684b9fadb706bb Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 19 Jun 2023 19:18:35 +0300 Subject: SL-19686 Fix gallery causing lags --- indra/newview/llinventorygallery.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index cfaff512ff..347611dfe2 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -337,9 +337,16 @@ void LLInventoryGallery::draw() void LLInventoryGallery::onVisibilityChange(BOOL new_visibility) { - if (new_visibility && mRootDirty) + if (new_visibility) { - updateRootFolder(); + if (mRootDirty) + { + updateRootFolder(); + } + else if (mNeedsArrange) + { + gIdleCallbacks.addFunction(onIdle, (void*)this); + } } LLPanel::onVisibilityChange(new_visibility); } @@ -751,9 +758,10 @@ void LLInventoryGallery::onIdle(void* userdata) return; } + bool visible = self->getVisible(); // In visible chain? const F64 MAX_TIME_VISIBLE = 0.020f; const F64 MAX_TIME_HIDDEN = 0.001f; // take it slow - const F64 max_time = self->getVisible() ? MAX_TIME_VISIBLE : MAX_TIME_HIDDEN; + const F64 max_time = visible ? MAX_TIME_VISIBLE : MAX_TIME_HIDDEN; F64 curent_time = LLTimer::getTotalSeconds(); const F64 end_time = curent_time + max_time; @@ -766,7 +774,7 @@ void LLInventoryGallery::onIdle(void* userdata) curent_time = LLTimer::getTotalSeconds(); } - if (self->mNeedsArrange) + if (self->mNeedsArrange && visible) { self->mNeedsArrange = false; self->reArrangeRows(); -- cgit v1.2.3 From 93ab02b672efc5388230629bafb5519e725a3683 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Mon, 19 Jun 2023 23:03:06 +0300 Subject: SL-19885 add sorting by date for Gallery view --- indra/newview/llinventorygallery.cpp | 48 +++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 6 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 347611dfe2..d76f0a45b2 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -87,7 +87,8 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mIsInitialized(false), mRootDirty(false), mNeedsArrange(false), - mSearchType(LLInventoryFilter::SEARCHTYPE_NAME) + mSearchType(LLInventoryFilter::SEARCHTYPE_NAME), + mSortOrder(LLInventoryFilter::SO_DATE) { updateGalleryWidth(); mFilter = new LLInventoryFilter(); @@ -369,19 +370,35 @@ bool LLInventoryGallery::updateRowsIfNeeded() return false; } -bool compareGalleryItem(LLInventoryGalleryItem* item1, LLInventoryGalleryItem* item2) +bool compareGalleryItem(LLInventoryGalleryItem* item1, LLInventoryGalleryItem* item2, bool sort_by_date, bool sort_folders_by_name) { if (item1->getSortGroup() != item2->getSortGroup()) { return (item1->getSortGroup() < item2->getSortGroup()); } - if(((item1->isDefaultImage() && item2->isDefaultImage()) || (!item1->isDefaultImage() && !item2->isDefaultImage()))) + + if(sort_folders_by_name && (item1->getSortGroup() != LLInventoryGalleryItem::SG_ITEM)) { std::string name1 = item1->getItemName(); std::string name2 = item2->getItemName(); return (LLStringUtil::compareDict(name1, name2) < 0); } + + if(((item1->isDefaultImage() && item2->isDefaultImage()) || (!item1->isDefaultImage() && !item2->isDefaultImage()))) + { + if(sort_by_date) + { + return item1->getCreationDate() > item2->getCreationDate(); + } + else + { + std::string name1 = item1->getItemName(); + std::string name2 = item2->getItemName(); + + return (LLStringUtil::compareDict(name1, name2) < 0); + } + } else { return item2->isDefaultImage(); @@ -403,7 +420,13 @@ void LLInventoryGallery::reArrangeRows(S32 row_diff) mItemsInRow+= row_diff; updateGalleryWidth(); - std::sort(buf_items.begin(), buf_items.end(), compareGalleryItem); + + bool sort_by_date = (mSortOrder & LLInventoryFilter::SO_DATE); + bool sort_folders_by_name = (mSortOrder & LLInventoryFilter::SO_FOLDERS_BY_NAME); + std::sort(buf_items.begin(), buf_items.end(), [sort_by_date, sort_folders_by_name](LLInventoryGalleryItem* item1, LLInventoryGalleryItem* item2) + { + return compareGalleryItem(item1, item2, sort_by_date, sort_folders_by_name); + }); for (std::vector::const_iterator it = buf_items.begin(); it != buf_items.end(); ++it) { @@ -573,7 +596,7 @@ void LLInventoryGallery::removeFromLastRow(LLInventoryGalleryItem* item) mItemPanels.pop_back(); } -LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, LLInventoryType::EType inventory_type, U32 flags, bool is_link, bool is_worn) +LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, LLUUID item_id, LLAssetType::EType type, LLUUID thumbnail_id, LLInventoryType::EType inventory_type, U32 flags, time_t creation_date, bool is_link, bool is_worn) { LLInventoryGalleryItem::Params giparams; giparams.visible = true; @@ -589,6 +612,7 @@ LLInventoryGalleryItem* LLInventoryGallery::buildGalleryItem(std::string name, L gitem->setCreatorName(get_searchable_creator_name(&gInventory, item_id)); gitem->setDescription(get_searchable_description(&gInventory, item_id)); gitem->setAssetIDStr(get_searchable_UUID(&gInventory, item_id)); + gitem->setCreationDate(creation_date); return gitem; } @@ -857,7 +881,8 @@ bool LLInventoryGallery::updateAddedItem(LLUUID item_id) } bool res = false; - LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getIsLinkType(), is_worn); + + LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getCreationDate(), obj->getIsLinkType(), is_worn); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); item->setRightMouseDownCallback(boost::bind(&LLInventoryGallery::showContextMenu, this, _1, _2, _3, item_id)); item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::changeItemSelection, this, item_id, false)); @@ -2006,6 +2031,17 @@ void LLInventoryGallery::handleModifiedFilter() } } +void LLInventoryGallery::setSortOrder(U32 order, bool update) +{ + bool dirty = (mSortOrder != order); + + mSortOrder = order; + if(update && dirty) + { + mNeedsArrange = true; + gIdleCallbacks.addFunction(onIdle, (void*)this); + } +} //----------------------------- // LLInventoryGalleryItem //----------------------------- -- cgit v1.2.3 From c24849f9da07f72a1dab83ccc69ec61c3448d027 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Fri, 23 Jun 2023 12:48:57 +0300 Subject: SL-19912 allow drag-n-drop items from Object's content to the Gallery --- indra/newview/llinventorygallery.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index d76f0a45b2..0cff30f1aa 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -2714,6 +2714,7 @@ BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, // coming from a task. Need to figure out if the person can // move/copy this item. LLPermissions perm(inv_item->getPermissions()); + bool is_move = false; if ((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) && perm.allowTransferTo(gAgent.getID()))) // || gAgent.isGodlike()) @@ -2725,6 +2726,7 @@ BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, // If the object cannot be copied, but the object the // inventory is owned by the agent, then the item can be // moved from the task to agent inventory. + is_move = true; accept = TRUE; } @@ -2749,9 +2751,7 @@ BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, if (accept && drop) { - //todo: dnd from SOURCE_WORLD - - /*boost::shared_ptr move_inv (new LLMoveInv()); + boost::shared_ptr move_inv (new LLMoveInv()); move_inv->mObjectID = inv_item->getParentUUID(); std::pair item_pair(folder_id, inv_item->getUUID()); move_inv->mMoveList.push_back(item_pair); @@ -2769,7 +2769,7 @@ BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, LLNotification::Params params("MoveInventoryFromObject"); params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); LLNotifications::instance().forceResponse(params, 0); - }*/ + } } } else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) @@ -3185,9 +3185,7 @@ BOOL dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, } else { - //todo: dnd from SOURCE_WORLD - accept = FALSE; - //accept = move_inv_category_world_to_agent(cat_id, mUUID, drop, NULL, NULL, filter); + accept = move_inv_category_world_to_agent(cat_id, dest_id, drop); } } else if (LLToolDragAndDrop::SOURCE_LIBRARY == source) -- cgit v1.2.3 From f30ae5c7812f5449a327a470fd4acaed7546d853 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 23 Jun 2023 21:59:55 +0300 Subject: SL-19914 Inventory gallery Tab support --- indra/newview/llinventorygallery.cpp | 80 +++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 0cff30f1aa..248f3ed649 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -63,6 +63,25 @@ BOOL dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, BOOL d BOOL dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg, BOOL user_confirm); void dropToMyOutfits(LLInventoryCategory* inv_cat); +class LLGalleryPanel: public LLPanel +{ +public: + + BOOL canFocusChildren() const override + { + // Tell Tab to not focus children + return FALSE; + } + +protected: + + LLGalleryPanel(const LLPanel::Params& params): LLPanel(params) + { + }; + + friend class LLUICtrlFactory; +}; + //----------------------------- // LLInventoryGallery //----------------------------- @@ -622,7 +641,7 @@ void LLInventoryGallery::buildGalleryPanel(int row_count) params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); params.visible = true; params.use_bounding_rect = false; - mGalleryPanel = LLUICtrlFactory::create(params); + mGalleryPanel = LLUICtrlFactory::create(params); reshapeGalleryPanel(row_count); } @@ -647,6 +666,8 @@ LLPanel* LLInventoryGallery::buildItemPanel(int left) lpparams.visible = true; lpparams.rect(LLRect(left, top + mItemHeight, left + mItemWidth + mItemHorizontalGap, top)); lpparams.use_bounding_rect = false; + lpparams.focus_root = false; + //lpparams.tab_stop = false; lpanel = LLUICtrlFactory::create(lpparams); } else @@ -669,6 +690,8 @@ LLPanel* LLInventoryGallery::buildRowPanel(int left, int bottom) sparams.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); sparams.use_bounding_rect = false; sparams.visible = true; + sparams.focus_root = false; + //sparams.tab_stop = false; stack = LLUICtrlFactory::create(sparams); } else @@ -1207,6 +1230,35 @@ void LLInventoryGallery::moveRight() } } +void LLInventoryGallery::onFocusLost() +{ + // inventory no longer handles cut/copy/paste/delete + if (gEditMenuHandler == this) + { + gEditMenuHandler = NULL; + } + + LLPanel::onFocusLost(); + + if (mSelectedItemID.notNull() && mItemMap[mSelectedItemID]) + { + mItemMap[mSelectedItemID]->setSelected(false); + } +} + +void LLInventoryGallery::onFocusReceived() +{ + // inventory now handles cut/copy/paste/delete + gEditMenuHandler = this; + + LLPanel::onFocusReceived(); + + if (mSelectedItemID.notNull() && mItemMap[mSelectedItemID]) + { + mItemMap[mSelectedItemID]->setSelected(true); + } +} + void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id) { if (mInventoryGalleryMenu && item_id.notNull()) @@ -1595,6 +1647,14 @@ void LLInventoryGallery::claimEditHandler() gEditMenuHandler = this; } +void LLInventoryGallery::resetEditHandler() +{ + if (gEditMenuHandler == this) + { + gEditMenuHandler = NULL; + } +} + bool LLInventoryGallery::isItemCopyable(const LLUUID & item_id) { const LLInventoryCategory* cat = gInventory.getCategory(item_id); @@ -2310,6 +2370,24 @@ BOOL LLInventoryGalleryItem::handleKeyHere(KEY key, MASK mask) return handled; } +void LLInventoryGalleryItem::onFocusLost() +{ + // inventory no longer handles cut/copy/paste/delete + mGallery->resetEditHandler(); + setSelected(false); + + LLPanel::onFocusLost(); +} + +void LLInventoryGalleryItem::onFocusReceived() +{ + // inventory now handles cut/copy/paste/delete + mGallery->claimEditHandler(); + setSelected(true); + + LLPanel::onFocusReceived(); +} + void LLInventoryGalleryItem::setWorn(bool value) { mWorn = value; -- cgit v1.2.3 From 7849e12c3104771a96806e8e721e3d5d92f856d2 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 27 Jun 2023 00:25:38 +0300 Subject: SL-19815 Fix missed 'handled' flags --- indra/newview/llinventorygallery.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 248f3ed649..2a71735a53 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1045,6 +1045,7 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) } } } + handled = TRUE; break; case KEY_DELETE: #if LL_DARWIN @@ -1056,6 +1057,7 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) { deleteSelection(); } + handled = TRUE; break; case KEY_F2: -- cgit v1.2.3 From 8eade6f074bf90ca914d8cb2a8f7cd58bfea7bb0 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 28 Jun 2023 12:38:43 +0300 Subject: SL-19923 FIXED Unable to drag and drop items from Library in Gallery mode --- indra/newview/llinventorygallery.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 2a71735a53..fa50261c9b 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -36,6 +36,7 @@ #include "llinventoryfunctions.h" #include "llinventoryicon.h" #include "llinventorymodel.h" +#include "llinventorymodelbackgroundfetch.h" #include "llthumbnailctrl.h" #include "lltextbox.h" #include "llviewerfoldertype.h" @@ -2240,6 +2241,15 @@ void LLInventoryGalleryItem::setSelected(bool value) { mSelected = value; mTextBgPanel->setBackgroundVisible(value); + + if(mSelected) + { + LLViewerInventoryItem* item = gInventory.getItem(mUUID); + if(item && !item->isFinished()) + { + LLInventoryModelBackgroundFetch::instance().start(mUUID, false); + } + } } BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) -- cgit v1.2.3 From bbcedf9c847f1f768e6c34e74a6a4373b0e7ae24 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 1 Jul 2023 00:20:01 +0300 Subject: SL-19914 Inventory gallery Tab support #2 --- indra/newview/llinventorygallery.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index fa50261c9b..271cc3e037 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1254,12 +1254,26 @@ void LLInventoryGallery::onFocusReceived() // inventory now handles cut/copy/paste/delete gEditMenuHandler = this; - LLPanel::onFocusReceived(); - + // Tab support, when tabbing into this view, select first item if (mSelectedItemID.notNull() && mItemMap[mSelectedItemID]) { - mItemMap[mSelectedItemID]->setSelected(true); + LLInventoryGalleryItem* focus_item = mItemMap[mSelectedItemID]; + focus_item->setSelected(true); + focus_item->setFocus(TRUE); } + else if (mIndexToItemMap.size() > 0) + { + // choose any items from visible rect + S32 vert_offset = mScrollPanel->getDocPosVertical(); + S32 panel_size = mVerticalGap + mRowPanelHeight; + S32 n = llclamp((S32)(vert_offset / panel_size) * mItemsInRow, 0, (S32)(mIndexToItemMap.size() - 1) ); + + LLInventoryGalleryItem* focus_item = mIndexToItemMap[n]; + changeItemSelection(focus_item->getUUID(), true); + focus_item->setFocus(TRUE); + } + + LLPanel::onFocusReceived(); } void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLUUID& item_id) -- cgit v1.2.3 From 35d68ce7373812d5ab028505ed035a4678da3ec9 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 1 Jul 2023 00:46:02 +0300 Subject: SL-19914 Inventory gallery Tab support #3 Don't try to select something if we are waiting for an item --- indra/newview/llinventorygallery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 271cc3e037..75df5c1043 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1261,7 +1261,7 @@ void LLInventoryGallery::onFocusReceived() focus_item->setSelected(true); focus_item->setFocus(TRUE); } - else if (mIndexToItemMap.size() > 0) + else if (mIndexToItemMap.size() > 0 && mItemToSelect.isNull()) { // choose any items from visible rect S32 vert_offset = mScrollPanel->getDocPosVertical(); -- cgit v1.2.3 From 4fb9a3f469c2cb0197d686acb68827f0fa32b451 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 20 Jul 2023 23:47:05 +0300 Subject: SL-20040 Fix selection and context menu issues --- indra/newview/llinventorygallery.cpp | 287 +++++++++++++++++++++++------------ 1 file changed, 193 insertions(+), 94 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 75df5c1043..ca1b2eb09e 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -107,6 +107,7 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mIsInitialized(false), mRootDirty(false), mNeedsArrange(false), + mNeedsSelection(false), mSearchType(LLInventoryFilter::SEARCHTYPE_NAME), mSortOrder(LLInventoryFilter::SO_DATE) { @@ -221,6 +222,7 @@ void LLInventoryGallery::setRootFolder(const LLUUID cat_id) mItemToSelect.setNull(); mItemBuildQuery.clear(); mNeedsArrange = false; + mNeedsSelection = false; dirtyRootFolder(); } @@ -829,14 +831,15 @@ void LLInventoryGallery::onIdle(void* userdata) self->updateMessageVisibility(); } - if (self->mItemToSelect.notNull()) + if (self->mNeedsSelection) { LLUUID item_to_select = self->mItemToSelect; self->mItemToSelect = LLUUID::null; + self->mNeedsSelection = false; self->changeItemSelection(item_to_select, true); } - if (self->mItemToSelect.isNull() && self->mItemBuildQuery.empty()) + if (!self->mNeedsSelection && self->mItemBuildQuery.empty()) { gIdleCallbacks.deleteFunction(onIdle, (void*)self); } @@ -908,7 +911,6 @@ bool LLInventoryGallery::updateAddedItem(LLUUID item_id) LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getCreationDate(), obj->getIsLinkType(), is_worn); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); - item->setRightMouseDownCallback(boost::bind(&LLInventoryGallery::showContextMenu, this, _1, _2, _3, item_id)); item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::changeItemSelection, this, item_id, false)); if (mGalleryCreated) { @@ -1000,15 +1002,21 @@ void LLInventoryGallery::updateItemThumbnail(LLUUID item_id) BOOL LLInventoryGallery::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if(mItemMap[mSelectedItemID]) + if (mSelectedItemIDs.size() > 0) { - mItemMap[mSelectedItemID]->setFocus(false); - setFocus(true); + selection_deque::iterator iter = mSelectedItemIDs.begin(); + if (mItemMap[*iter]) + { + mItemMap[*iter]->setFocus(false); + setFocus(true); + } } clearSelection(); + + // Scroll is going to always return true BOOL res = LLPanel::handleRightMouseDown(x, y, mask); - if (mSelectedItemID.isNull()) + if (mSelectedItemIDs.empty()) { if (mInventoryGalleryMenu && mFolderID.notNull()) { @@ -1029,20 +1037,21 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) { case KEY_RETURN: // Open selected items if enter key hit on the inventory panel - if (mask == MASK_NONE && mInventoryGalleryMenu && mSelectedItemID.notNull()) + if (mask == MASK_NONE && mInventoryGalleryMenu && mSelectedItemIDs.size() == 1) { - LLViewerInventoryCategory* category = gInventory.getCategory(mSelectedItemID); + selection_deque::iterator iter = mSelectedItemIDs.begin(); + LLViewerInventoryCategory* category = gInventory.getCategory(*iter); if (category) { - setRootFolder(mSelectedItemID); + setRootFolder(*iter); handled = TRUE; } else { - LLViewerInventoryItem* item = gInventory.getItem(mSelectedItemID); + LLViewerInventoryItem* item = gInventory.getItem(*iter); if (item) { - LLInvFVBridgeAction::doAction(item->getType(), mSelectedItemID, &gInventory); + LLInvFVBridgeAction::doAction(item->getType(), *iter, &gInventory); } } } @@ -1063,9 +1072,10 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) case KEY_F2: mFilterSubString.clear(); - if (mInventoryGalleryMenu && mSelectedItemID.notNull()) + if (mInventoryGalleryMenu && mSelectedItemIDs.size() == 1) { - mInventoryGalleryMenu->doToSelected("rename", mSelectedItemID); + selection_deque::iterator iter = mSelectedItemIDs.begin(); + mInventoryGalleryMenu->doToSelected("rename", *iter); } handled = TRUE; break; @@ -1142,9 +1152,9 @@ void LLInventoryGallery::moveUp() { mFilterSubString.clear(); - if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) + if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getSelectedItem(); + LLInventoryGalleryItem* item = getFirstSelectedItem(); if (item) { S32 n = mItemIndexMap[item]; @@ -1165,9 +1175,9 @@ void LLInventoryGallery::moveDown() { mFilterSubString.clear(); - if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) + if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getSelectedItem(); + LLInventoryGalleryItem* item = getFirstSelectedItem(); if (item) { S32 n = mItemIndexMap[item]; @@ -1188,9 +1198,9 @@ void LLInventoryGallery::moveLeft() { mFilterSubString.clear(); - if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) + if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getSelectedItem(); + LLInventoryGalleryItem* item = getFirstSelectedItem(); if (item) { // Might be better to get item from panel @@ -1213,9 +1223,9 @@ void LLInventoryGallery::moveRight() { mFilterSubString.clear(); - if (mInventoryGalleryMenu && mSelectedItemID.notNull() && mItemsAddedCount > 1) + if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getSelectedItem(); + LLInventoryGalleryItem* item = getFirstSelectedItem(); if (item) { S32 n = mItemIndexMap[item]; @@ -1243,9 +1253,12 @@ void LLInventoryGallery::onFocusLost() LLPanel::onFocusLost(); - if (mSelectedItemID.notNull() && mItemMap[mSelectedItemID]) + for (const LLUUID& id : mSelectedItemIDs) { - mItemMap[mSelectedItemID]->setSelected(false); + if (mItemMap[id]) + { + mItemMap[id]->setSelected(false); + } } } @@ -1255,13 +1268,19 @@ void LLInventoryGallery::onFocusReceived() gEditMenuHandler = this; // Tab support, when tabbing into this view, select first item - if (mSelectedItemID.notNull() && mItemMap[mSelectedItemID]) + if (mSelectedItemIDs.size() > 0) { - LLInventoryGalleryItem* focus_item = mItemMap[mSelectedItemID]; - focus_item->setSelected(true); - focus_item->setFocus(TRUE); + for (const LLUUID& id : mSelectedItemIDs) + { + if (mItemMap[id]) + { + LLInventoryGalleryItem* focus_item = mItemMap[id]; + focus_item->setSelected(true); + focus_item->setFocus(TRUE); + } + } } - else if (mIndexToItemMap.size() > 0 && mItemToSelect.isNull()) + else if (mIndexToItemMap.size() > 0 && !mNeedsSelection) { // choose any items from visible rect S32 vert_offset = mScrollPanel->getDocPosVertical(); @@ -1280,6 +1299,11 @@ void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLU { if (mInventoryGalleryMenu && item_id.notNull()) { + if (std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id) == mSelectedItemIDs.end()) + { + mSelectedItemIDs.clear(); + mSelectedItemIDs.push_back(item_id); + } uuid_vec_t selected_uuids; selected_uuids.push_back(item_id); mInventoryGalleryMenu->show(ctrl, selected_uuids, x, y); @@ -1291,32 +1315,32 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ if ((mItemMap.count(item_id) == 0) || mNeedsArrange) { mItemToSelect = item_id; + mNeedsSelection = true; return; } - if (mSelectedItemID == item_id) - { - return; - } - if (mNeedsArrange && item_id.notNull()) + if (std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id) == mSelectedItemIDs.end()) { - mItemToSelect = item_id; return; } - if (mItemMap[mSelectedItemID]) + for (const LLUUID& id : mSelectedItemIDs) { - mItemMap[mSelectedItemID]->setSelected(FALSE); + if (mItemMap[id]) + { + mItemMap[id]->setSelected(FALSE); + } } + if (mItemMap[item_id]) { mItemMap[item_id]->setSelected(TRUE); } - mSelectedItemID = item_id; + mSelectedItemIDs.push_back(item_id); signalSelectionItemID(item_id); if (scroll_to_selection) { - scrollToShowItem(mSelectedItemID); + scrollToShowItem(item_id); } } @@ -1347,31 +1371,45 @@ void LLInventoryGallery::scrollToShowItem(const LLUUID& item_id) } } -LLInventoryGalleryItem* LLInventoryGallery::getSelectedItem() +LLInventoryGalleryItem* LLInventoryGallery::getFirstSelectedItem() { - return mItemMap[mSelectedItemID]; + if (mSelectedItemIDs.size() > 0) + { + selection_deque::iterator iter = mSelectedItemIDs.begin(); + return mItemMap[*iter]; + } + return NULL; } void LLInventoryGallery::copy() { + if (!getVisible() || !getEnabled()) + { + return; + } + LLClipboard::instance().reset(); - if (getVisible() && getEnabled() && mSelectedItemID.notNull()) + + for (const LLUUID& id : mSelectedItemIDs) { - LLClipboard::instance().addToClipboard(mSelectedItemID); + LLClipboard::instance().addToClipboard(id); } mFilterSubString.clear(); } BOOL LLInventoryGallery::canCopy() const { - if (!getVisible() || !getEnabled() || mSelectedItemID.isNull()) + if (!getVisible() || !getEnabled() || mSelectedItemIDs.empty()) { return FALSE; } - if (!isItemCopyable(mSelectedItemID)) + for (const LLUUID& id : mSelectedItemIDs) { - return FALSE; + if (!isItemCopyable(id)) + { + return FALSE; + } } return TRUE; @@ -1379,36 +1417,45 @@ BOOL LLInventoryGallery::canCopy() const void LLInventoryGallery::cut() { + if (!getVisible() || !getEnabled()) + { + return; + } + // clear the inventory clipboard LLClipboard::instance().reset(); - if (getVisible() && getEnabled() && mSelectedItemID.notNull()) + LLClipboard::instance().setCutMode(true); + for (const LLUUID& id : mSelectedItemIDs) { // todo: fade out selected item - LLClipboard::instance().setCutMode(true); - LLClipboard::instance().addToClipboard(mSelectedItemID); + LLClipboard::instance().addToClipboard(id); } + mFilterSubString.clear(); } BOOL LLInventoryGallery::canCut() const { - if (!getVisible() || !getEnabled() || mSelectedItemID.isNull()) + if (!getVisible() || !getEnabled() || mSelectedItemIDs.empty()) { return FALSE; } - LLViewerInventoryCategory* cat = gInventory.getCategory(mSelectedItemID); - if (cat) + for (const LLUUID& id : mSelectedItemIDs) { - if (!get_is_category_removable(&gInventory, mSelectedItemID)) + LLViewerInventoryCategory* cat = gInventory.getCategory(id); + if (cat) + { + if (!get_is_category_removable(&gInventory, id)) + { + return FALSE; + } + } + else if (!get_is_item_removable(&gInventory, id)) { return FALSE; } } - else if (!get_is_item_removable(&gInventory, mSelectedItemID)) - { - return FALSE; - } return TRUE; } @@ -1421,14 +1468,20 @@ void LLInventoryGallery::paste() } const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); - if (!mSelectedItemID.isNull() && gInventory.isObjectDescendentOf(mSelectedItemID, marketplacelistings_id)) + if (mSelectedItemIDs.size() == 1 && gInventory.isObjectDescendentOf(*mSelectedItemIDs.begin(), marketplacelistings_id)) { return; } - LLInventoryObject* obj = gInventory.getObject(mSelectedItemID); + LLUUID first_selected_id; + if (mSelectedItemIDs.size() > 0) + { + first_selected_id = *mSelectedItemIDs.begin(); + } + + LLInventoryObject* obj = gInventory.getObject(first_selected_id); bool is_folder = obj && (obj->getType() == LLAssetType::AT_CATEGORY); - LLUUID dest = is_folder ? mSelectedItemID : mFolderID; + LLUUID dest = is_folder ? first_selected_id : mFolderID; bool is_cut_mode = LLClipboard::instance().isCutMode(); std::vector objects; @@ -1463,6 +1516,7 @@ void LLInventoryGallery::paste() gInventory.changeCategoryParent(cat, dest, false); // Don't select immediately, wait for item to arrive mItemToSelect = item_id; + mNeedsSelection = true; } else { @@ -1479,6 +1533,7 @@ void LLInventoryGallery::paste() gInventory.changeItemParent(item, dest, false); // Don't select immediately, wait for item to arrive mItemToSelect = item_id; + mNeedsSelection = true; } else { @@ -1535,28 +1590,31 @@ BOOL LLInventoryGallery::canPaste() const return TRUE; } -void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response, const LLUUID& selected_id) +void LLInventoryGallery::onDelete(const LLSD& notification, const LLSD& response, const selection_deque selected_ids) { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { - LLInventoryObject* obj = gInventory.getObject(selected_id); - if (!obj) - { - return; - } - if (obj->getType() == LLAssetType::AT_CATEGORY) + for (const LLUUID& id : selected_ids) { - if (get_is_category_removable(&gInventory, selected_id)) + LLInventoryObject* obj = gInventory.getObject(id); + if (!obj) { - gInventory.removeCategory(selected_id); + return; } - } - else - { - if (get_is_item_removable(&gInventory, selected_id)) + if (obj->getType() == LLAssetType::AT_CATEGORY) + { + if (get_is_category_removable(&gInventory, id)) + { + gInventory.removeCategory(id); + } + } + else { - gInventory.removeItem(selected_id); + if (get_is_item_removable(&gInventory, id)) + { + gInventory.removeItem(id); + } } } } @@ -1572,31 +1630,39 @@ void LLInventoryGallery::deleteSelection() LLSD args; args["QUESTION"] = LLTrans::getString("DeleteItem"); - LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemID)); + LLNotificationsUtil::add("DeleteItems", args, LLSD(), boost::bind(&LLInventoryGallery::onDelete, _1, _2, mSelectedItemIDs)); } bool LLInventoryGallery::canDeleteSelection() { - if (mSelectedItemID.isNull()) + if (mSelectedItemIDs.empty()) { return false; } - LLViewerInventoryCategory* cat = gInventory.getCategory(mSelectedItemID); - if (cat) + const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); + if (mFolderID == trash_id || gInventory.isObjectDescendentOf(mFolderID, trash_id)) + { + return false; + } + + for (const LLUUID& id : mSelectedItemIDs) { - if (!get_is_category_removable(&gInventory, mSelectedItemID)) + LLViewerInventoryCategory* cat = gInventory.getCategory(id); + if (cat) + { + if (!get_is_category_removable(&gInventory, id)) + { + return false; + } + } + else if (!get_is_item_removable(&gInventory, id)) { return false; } } - else if (!get_is_item_removable(&gInventory, mSelectedItemID)) - { - return false; - } - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - return !gInventory.isObjectDescendentOf(mSelectedItemID, trash_id); + return true; } void LLInventoryGallery::pasteAsLink() @@ -1611,12 +1677,12 @@ void LLInventoryGallery::pasteAsLink() const LLUUID& my_outifts_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); LLUUID dest; - LLInventoryObject* obj = gInventory.getObject(mSelectedItemID); - if (obj && obj->getType() == LLAssetType::AT_CATEGORY) + if (mSelectedItemIDs.size() > 0) { - dest = mSelectedItemID; + dest = *mSelectedItemIDs.begin(); } - else + LLInventoryObject* obj = gInventory.getObject(dest); + if (!obj || obj->getType() != LLAssetType::AT_CATEGORY) { dest = mFolderID; } @@ -1894,18 +1960,35 @@ void LLInventoryGallery::onGesturesChanged() void LLInventoryGallery::deselectItem(const LLUUID& category_id) { // Reset selection if the item is selected. - if (category_id == mSelectedItemID) + LLInventoryGalleryItem* item = mItemMap[category_id]; + if (item && item->isSelected()) { - mSelectedItemID = LLUUID::null; - signalSelectionItemID(mSelectedItemID); + mItemMap[category_id]->setSelected(FALSE); + setFocus(true); + // Todo: support multiselect + signalSelectionItemID(LLUUID::null); + } + + selection_deque::iterator found = std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), category_id); + if (found != mSelectedItemIDs.end()) + { + mSelectedItemIDs.erase(found); } } void LLInventoryGallery::clearSelection() { - if(mSelectedItemID != LLUUID::null) + for (const LLUUID& id: mSelectedItemIDs) + { + if (mItemMap[id]) + { + mItemMap[id]->setSelected(FALSE); + } + } + if (!mSelectedItemIDs.empty()) { - changeItemSelection(LLUUID::null); + mSelectedItemIDs.clear(); + signalSelectionItemID(LLUUID::null); } } @@ -1919,6 +2002,15 @@ boost::signals2::connection LLInventoryGallery::setSelectionChangeCallback(selec return mSelectionChangeSignal.connect(cb); } +LLUUID LLInventoryGallery::getFirstSelectedItemID() +{ + if (mSelectedItemIDs.size() > 0) + { + return *mSelectedItemIDs.begin(); + } + return LLUUID::null; +} + LLUUID LLInventoryGallery::getOutfitImageID(LLUUID outfit_id) { LLUUID thumbnail_id; @@ -2284,6 +2376,10 @@ BOOL LLInventoryGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) setFocus(TRUE); mGallery->claimEditHandler(); + //S32 gal_x, gal_y; + //localPointToOtherView(x, y, &gal_x, &gal_y, mGallery); + mGallery->showContextMenu(this, x, y, mUUID); + LLUICtrl::handleRightMouseDown(x, y, mask); return TRUE; } @@ -2532,6 +2628,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, { // Don't select immediately, wait for item to arrive mItemToSelect = inv_item->getUUID(); + mNeedsSelection = true; } break; case DAD_LINK: @@ -2553,6 +2650,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, if (accepted && drop && inv_item) { mItemToSelect = inv_item->getUUID(); + mNeedsSelection = true; } break; case DAD_CATEGORY: @@ -2567,6 +2665,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, if (accepted && drop) { mItemToSelect = cat_ptr->getUUID(); + mNeedsSelection = true; } } break; -- cgit v1.2.3 From 0941fcd5a48e9d4d95fb88750db3b964aa983486 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 21 Jul 2023 00:47:14 +0300 Subject: SL-20047 Indicate when gallery items are being cut --- indra/newview/llinventorygallery.cpp | 40 +++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index ca1b2eb09e..99bd772773 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -2230,7 +2230,9 @@ LLInventoryGalleryItem::LLInventoryGalleryItem(const Params& p) mHidden(false), mGallery(NULL), mType(LLAssetType::AT_NONE), - mSortGroup(SG_ITEM) + mSortGroup(SG_ITEM), + mCutGeneration(0), + mSelectedForCut(false) { buildFromFile("panel_inventory_gallery_item.xml"); } @@ -2328,13 +2330,24 @@ void LLInventoryGalleryItem::setThumbnail(LLUUID id) void LLInventoryGalleryItem::draw() { - LLPanel::draw(); + if (isFadeItem()) + { + // Fade out to indicate it's being cut + LLViewDrawContext context(0.5f); + LLPanel::draw(); + } + else + { + LLPanel::draw(); + + // Draw border + LLUIColor border_color = LLUIColorTable::instance().getColor(mSelected ? "MenuItemHighlightBgColor" : "TextFgTentativeColor", LLColor4::white); + LLRect border = getChildView("preview_thumbnail")->getRect(); + border.mRight = border.mRight + 1; + gl_rect_2d(border, border_color.get(), FALSE); + } + - // Draw border - LLUIColor border_color = LLUIColorTable::instance().getColor(mSelected ? "MenuItemHighlightBgColor" : "TextFgTentativeColor", LLColor4::white); - LLRect border = getChildView("preview_thumbnail")->getRect(); - border.mRight = border.mRight + 1; - gl_rect_2d(border, border_color.get(), FALSE); } void LLInventoryGalleryItem::setItemName(std::string name) @@ -2543,6 +2556,19 @@ void LLInventoryGalleryItem::updateNameText() getChild("preview_thumbnail")->setToolTip(mItemName + mPermSuffix + mWornSuffix); } +bool LLInventoryGalleryItem::isFadeItem() +{ + LLClipboard& clipboard = LLClipboard::instance(); + if (mCutGeneration == clipboard.getGeneration()) + { + return mSelectedForCut; + } + + mCutGeneration = clipboard.getGeneration(); + mSelectedForCut = clipboard.isCutMode() && clipboard.isOnClipboard(mUUID); + return mSelectedForCut; +} + //----------------------------- // LLThumbnailsObserver //----------------------------- -- cgit v1.2.3 From d237b9ee1b0bbcdb3431f8afc873af4ee9e21a4e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 21 Jul 2023 17:19:04 +0300 Subject: SL-20040 Fix selection callback --- indra/newview/llinventorygallery.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 99bd772773..87dba5f100 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1302,7 +1302,7 @@ void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLU if (std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id) == mSelectedItemIDs.end()) { mSelectedItemIDs.clear(); - mSelectedItemIDs.push_back(item_id); + changeItemSelection(item_id, false); } uuid_vec_t selected_uuids; selected_uuids.push_back(item_id); @@ -1318,8 +1318,10 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ mNeedsSelection = true; return; } - if (std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id) == mSelectedItemIDs.end()) + if (mSelectedItemIDs.size() == 1 + && std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id) != mSelectedItemIDs.end()) { + // Already selected return; } @@ -1330,6 +1332,7 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ mItemMap[id]->setSelected(FALSE); } } + mSelectedItemIDs.clear(); if (mItemMap[item_id]) { @@ -2388,9 +2391,6 @@ BOOL LLInventoryGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) { setFocus(TRUE); mGallery->claimEditHandler(); - - //S32 gal_x, gal_y; - //localPointToOtherView(x, y, &gal_x, &gal_y, mGallery); mGallery->showContextMenu(this, x, y, mUUID); LLUICtrl::handleRightMouseDown(x, y, mask); -- cgit v1.2.3 From 05b5540fe70067180be6bb664752742b31a49eb7 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 1 Aug 2023 23:53:57 +0300 Subject: SL-20107 Detaching items from COF in gallery view didn't update COF --- indra/newview/llinventorygallery.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 87dba5f100..0801b71e34 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -2376,6 +2376,9 @@ void LLInventoryGalleryItem::setSelected(bool value) BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) { + // call changeItemSelection directly, before setFocus + // to avoid autoscroll from LLInventoryGallery::onFocusReceived() + mGallery->changeItemSelection(mUUID, false); setFocus(TRUE); mGallery->claimEditHandler(); -- cgit v1.2.3 From c4c5778b263a1f9036ba6c6c18f96d1311988fcb Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 2 Aug 2023 18:00:02 +0300 Subject: SL-20098 handleDoubleClick crashes in new inventory panels --- indra/newview/llinventorygallery.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 0801b71e34..eb603f0ac3 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -2449,7 +2449,19 @@ BOOL LLInventoryGalleryItem::handleDoubleClick(S32 x, S32 y, MASK mask) { if (mIsFolder && mGallery) { - mGallery->setRootFolder(mUUID); + // setRootFolder can destroy this item. + // Delay it until handleDoubleClick processing is complete + // or make gallery handle doubleclicks. + LLHandle handle = mGallery->getHandle(); + LLUUID navigate_to = mUUID; + doOnIdleOneTime([handle, navigate_to]() + { + LLInventoryGallery* gallery = (LLInventoryGallery*)handle.get(); + if (gallery) + { + gallery->setRootFolder(navigate_to); + } + }); } else { -- cgit v1.2.3 From 03db9132db54e9366305e79e63adc4fe2f4722dc Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Thu, 10 Aug 2023 13:53:34 +0300 Subject: SL-20118 tweak the top border line --- indra/newview/llinventorygallery.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index eb603f0ac3..8170c0c63b 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -2347,6 +2347,7 @@ void LLInventoryGalleryItem::draw() LLUIColor border_color = LLUIColorTable::instance().getColor(mSelected ? "MenuItemHighlightBgColor" : "TextFgTentativeColor", LLColor4::white); LLRect border = getChildView("preview_thumbnail")->getRect(); border.mRight = border.mRight + 1; + border.mTop = border.mTop + 1; gl_rect_2d(border, border_color.get(), FALSE); } -- cgit v1.2.3 From f24f72d2f9db7490b169daea16f8ab8400ca12b4 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 6 Sep 2023 02:56:11 +0300 Subject: SL-19826 Gallery multiselect support Part#3 wip --- indra/newview/llinventorygallery.cpp | 480 ++++++++++++++++++++++++++--------- 1 file changed, 362 insertions(+), 118 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 8170c0c63b..eab15b79ad 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -107,7 +107,6 @@ LLInventoryGallery::LLInventoryGallery(const LLInventoryGallery::Params& p) mIsInitialized(false), mRootDirty(false), mNeedsArrange(false), - mNeedsSelection(false), mSearchType(LLInventoryFilter::SEARCHTYPE_NAME), mSortOrder(LLInventoryFilter::SO_DATE) { @@ -219,10 +218,10 @@ void LLInventoryGallery::setRootFolder(const LLUUID cat_id) gIdleCallbacks.deleteFunction(onIdle, (void*)this); mFolderID = cat_id; - mItemToSelect.setNull(); + mItemsToSelect.clear(); + mSelectedItemIDs.clear(); mItemBuildQuery.clear(); mNeedsArrange = false; - mNeedsSelection = false; dirtyRootFolder(); } @@ -831,15 +830,17 @@ void LLInventoryGallery::onIdle(void* userdata) self->updateMessageVisibility(); } - if (self->mNeedsSelection) + if (!self->mItemsToSelect.empty() && !self->mNeedsArrange) { - LLUUID item_to_select = self->mItemToSelect; - self->mItemToSelect = LLUUID::null; - self->mNeedsSelection = false; - self->changeItemSelection(item_to_select, true); + selection_deque selection_list(self->mItemsToSelect); + self->mItemsToSelect.clear(); + for (LLUUID & item_to_select : selection_list) + { + self->addItemSelection(item_to_select, true); + } } - if (!self->mNeedsSelection && self->mItemBuildQuery.empty()) + if (self->mItemsToSelect.empty() && self->mItemBuildQuery.empty()) { gIdleCallbacks.deleteFunction(onIdle, (void*)self); } @@ -911,7 +912,6 @@ bool LLInventoryGallery::updateAddedItem(LLUUID item_id) LLInventoryGalleryItem* item = buildGalleryItem(name, item_id, obj->getType(), thumbnail_id, inventory_type, misc_flags, obj->getCreationDate(), obj->getIsLinkType(), is_worn); mItemMap.insert(LLInventoryGallery::gallery_item_map_t::value_type(item_id, item)); - item->setFocusReceivedCallback(boost::bind(&LLInventoryGallery::changeItemSelection, this, item_id, false)); if (mGalleryCreated) { res = applyFilter(item, mFilterSubString); @@ -1074,8 +1074,7 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) mFilterSubString.clear(); if (mInventoryGalleryMenu && mSelectedItemIDs.size() == 1) { - selection_deque::iterator iter = mSelectedItemIDs.begin(); - mInventoryGalleryMenu->doToSelected("rename", *iter); + mInventoryGalleryMenu->rename(mSelectedItemIDs.front()); } handled = TRUE; break; @@ -1117,22 +1116,22 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) break; case KEY_LEFT: - moveLeft(); + moveLeft(mask); handled = TRUE; break; case KEY_RIGHT: - moveRight(); + moveRight(mask); handled = TRUE; break; case KEY_UP: - moveUp(); + moveUp(mask); handled = TRUE; break; case KEY_DOWN: - moveDown(); + moveDown(mask); handled = TRUE; break; @@ -1148,59 +1147,107 @@ BOOL LLInventoryGallery::handleKeyHere(KEY key, MASK mask) return handled; } -void LLInventoryGallery::moveUp() +void LLInventoryGallery::moveUp(MASK mask) { mFilterSubString.clear(); if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getFirstSelectedItem(); + LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID]; if (item) { - S32 n = mItemIndexMap[item]; - n -= mItemsInRow; - if (n >= 0) + if (mask == MASK_NONE || mask == MASK_CONTROL) { - item = mIndexToItemMap[n]; - LLUUID item_id = item->getUUID(); - changeItemSelection(item_id, true); - item->setFocus(TRUE); - claimEditHandler(); + S32 n = mItemIndexMap[item]; + n -= mItemsInRow; + if (n >= 0) + { + item = mIndexToItemMap[n]; + LLUUID item_id = item->getUUID(); + if (mask == MASK_CONTROL) + { + addItemSelection(item_id, true); + } + else + { + changeItemSelection(item_id, true); + } + item->setFocus(TRUE); + claimEditHandler(); + } + } + else if (mask == MASK_SHIFT) + { + S32 n = mItemIndexMap[item]; + S32 target = llmax(0, n - mItemsInRow); + toggleSelectionRange(target, n - 1); + if (target != n) + { + item = mIndexToItemMap[target]; + item->setFocus(TRUE); + claimEditHandler(); + } } } } } -void LLInventoryGallery::moveDown() +void LLInventoryGallery::moveDown(MASK mask) { mFilterSubString.clear(); if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getFirstSelectedItem(); + LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID]; if (item) { - S32 n = mItemIndexMap[item]; - n += mItemsInRow; - if (n < mItemsAddedCount) + if (mask == MASK_NONE || mask == MASK_CONTROL) { - item = mIndexToItemMap[n]; - LLUUID item_id = item->getUUID(); - changeItemSelection(item_id, true); - item->setFocus(TRUE); - claimEditHandler(); + S32 n = mItemIndexMap[item]; + n += mItemsInRow; + if (n < mItemsAddedCount) + { + item = mIndexToItemMap[n]; + LLUUID item_id = item->getUUID(); + if (mask == MASK_CONTROL) + { + addItemSelection(item_id, true); + } + else + { + changeItemSelection(item_id, true); + } + item->setFocus(TRUE); + claimEditHandler(); + } + } + else if (mask == MASK_SHIFT) + { + S32 n = mItemIndexMap[item]; + S32 target = llmin(mItemsAddedCount - 1, n + mItemsInRow); + toggleSelectionRange(n + 1, target); + if (target != n) + { + item = mIndexToItemMap[target]; + item->setFocus(TRUE); + claimEditHandler(); + } } } } } -void LLInventoryGallery::moveLeft() +void LLInventoryGallery::moveLeft(MASK mask) { mFilterSubString.clear(); if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getFirstSelectedItem(); + LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID]; + if (mask == MASK_SHIFT) + { + item = mItemMap[mLastSelectedUUID]; + } if (item) { // Might be better to get item from panel @@ -1212,20 +1259,31 @@ void LLInventoryGallery::moveLeft() } item = mIndexToItemMap[n]; LLUUID item_id = item->getUUID(); - changeItemSelection(item_id, true); + if (mask == MASK_CONTROL) + { + addItemSelection(item_id, true); + } + else if (mask == MASK_SHIFT) + { + toggleItemSelection(item_id, true); + } + else + { + changeItemSelection(item_id, true); + } item->setFocus(TRUE); claimEditHandler(); } } } -void LLInventoryGallery::moveRight() +void LLInventoryGallery::moveRight(MASK mask) { mFilterSubString.clear(); if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = getFirstSelectedItem(); + LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID]; if (item) { S32 n = mItemIndexMap[item]; @@ -1236,13 +1294,58 @@ void LLInventoryGallery::moveRight() } item = mIndexToItemMap[n]; LLUUID item_id = item->getUUID(); - changeItemSelection(item_id, true); + if (mask == MASK_CONTROL) + { + addItemSelection(item_id, true); + } + else if (mask == MASK_SHIFT) + { + toggleItemSelection(item_id, true); + } + else + { + changeItemSelection(item_id, true); + } item->setFocus(TRUE); claimEditHandler(); } } } +void LLInventoryGallery::toggleSelectionRange(S32 start_idx, S32 end_idx) +{ + LLInventoryGalleryItem* item = NULL; + for (S32 i = start_idx; i <= end_idx; i++) + { + item = mIndexToItemMap[i]; + LLUUID item_id = item->getUUID(); + toggleItemSelection(item_id, true); + } +} + +void LLInventoryGallery::toggleSelectionRangeFromLast(const LLUUID target) +{ + if (mLastSelectedUUID == target) + { + return; + } + LLInventoryGalleryItem* last_item = mItemMap[mLastSelectedUUID]; + LLInventoryGalleryItem* next_item = mItemMap[target]; + if (last_item && next_item) + { + S32 last_idx = mItemIndexMap[last_item]; + S32 next_idx = mItemIndexMap[next_item]; + if (last_idx < next_idx) + { + toggleSelectionRange(last_idx + 1, next_idx); + } + else + { + toggleSelectionRange(next_idx, last_idx - 1); + } + } +} + void LLInventoryGallery::onFocusLost() { // inventory no longer handles cut/copy/paste/delete @@ -1270,17 +1373,21 @@ void LLInventoryGallery::onFocusReceived() // Tab support, when tabbing into this view, select first item if (mSelectedItemIDs.size() > 0) { + LLInventoryGalleryItem* focus_item = NULL; for (const LLUUID& id : mSelectedItemIDs) { if (mItemMap[id]) { - LLInventoryGalleryItem* focus_item = mItemMap[id]; + focus_item = mItemMap[id]; focus_item->setSelected(true); - focus_item->setFocus(TRUE); } } + if (focus_item) + { + focus_item->setFocus(TRUE); + } } - else if (mIndexToItemMap.size() > 0 && !mNeedsSelection) + else if (mIndexToItemMap.size() > 0 && mItemsToSelect.empty()) { // choose any items from visible rect S32 vert_offset = mScrollPanel->getDocPosVertical(); @@ -1304,18 +1411,26 @@ void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLU mSelectedItemIDs.clear(); changeItemSelection(item_id, false); } - uuid_vec_t selected_uuids; - selected_uuids.push_back(item_id); + uuid_vec_t selected_uuids(mSelectedItemIDs.begin(), mSelectedItemIDs.end()); mInventoryGalleryMenu->show(ctrl, selected_uuids, x, y); } } void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_to_selection) { + for (const LLUUID& id : mSelectedItemIDs) + { + if (mItemMap[id]) + { + mItemMap[id]->setSelected(FALSE); + } + } + mSelectedItemIDs.clear(); + if ((mItemMap.count(item_id) == 0) || mNeedsArrange) { - mItemToSelect = item_id; - mNeedsSelection = true; + mItemsToSelect.clear(); + mItemsToSelect.push_back(item_id); return; } if (mSelectedItemIDs.size() == 1 @@ -1325,14 +1440,32 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ return; } - for (const LLUUID& id : mSelectedItemIDs) + if (mItemMap[item_id]) { - if (mItemMap[id]) - { - mItemMap[id]->setSelected(FALSE); - } + mItemMap[item_id]->setSelected(TRUE); + } + mSelectedItemIDs.push_back(item_id); + signalSelectionItemID(item_id); + mLastSelectedUUID = item_id; + + if (scroll_to_selection) + { + scrollToShowItem(item_id); + } +} + +void LLInventoryGallery::addItemSelection(const LLUUID& item_id, bool scroll_to_selection) +{ + if ((mItemMap.count(item_id) == 0) || mNeedsArrange) + { + mItemsToSelect.push_back(item_id); + return; + } + if (std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id) != mSelectedItemIDs.end()) + { + // Already selected + return; } - mSelectedItemIDs.clear(); if (mItemMap[item_id]) { @@ -1340,6 +1473,7 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ } mSelectedItemIDs.push_back(item_id); signalSelectionItemID(item_id); + mLastSelectedUUID = item_id; if (scroll_to_selection) { @@ -1347,6 +1481,43 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ } } +bool LLInventoryGallery::toggleItemSelection(const LLUUID& item_id, bool scroll_to_selection) +{ + bool result = false; + if ((mItemMap.count(item_id) == 0) || mNeedsArrange) + { + mItemsToSelect.push_back(item_id); + return result; + } + selection_deque::iterator found = std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id); + if (found != mSelectedItemIDs.end()) + { + if (mItemMap[item_id]) + { + mItemMap[item_id]->setSelected(FALSE); + } + mSelectedItemIDs.erase(found); + result = false; + } + else + { + if (mItemMap[item_id]) + { + mItemMap[item_id]->setSelected(TRUE); + } + mSelectedItemIDs.push_back(item_id); + signalSelectionItemID(item_id); + mLastSelectedUUID = item_id; + result = true; + } + + if (scroll_to_selection) + { + scrollToShowItem(item_id); + } + return result; +} + void LLInventoryGallery::scrollToShowItem(const LLUUID& item_id) { LLInventoryGalleryItem* item = mItemMap[item_id]; @@ -1476,32 +1647,63 @@ void LLInventoryGallery::paste() return; } - LLUUID first_selected_id; - if (mSelectedItemIDs.size() > 0) - { - first_selected_id = *mSelectedItemIDs.begin(); - } - - LLInventoryObject* obj = gInventory.getObject(first_selected_id); - bool is_folder = obj && (obj->getType() == LLAssetType::AT_CATEGORY); - LLUUID dest = is_folder ? first_selected_id : mFolderID; bool is_cut_mode = LLClipboard::instance().isCutMode(); - std::vector objects; LLClipboard::instance().pasteFromClipboard(objects); - LLHandle handle = getHandle(); - std::function on_copy_callback = [handle](const LLUUID& inv_item) + bool paste_into_root = mSelectedItemIDs.empty(); + for (LLUUID& dest : mSelectedItemIDs) { - LLInventoryGallery* panel = (LLInventoryGallery*)handle.get(); - if (panel) + LLInventoryObject* obj = gInventory.getObject(dest); + if (!obj || (obj->getType() != LLAssetType::AT_CATEGORY)) { - // Scroll to pasted item and highlight it - // Should it only highlight the last one? - panel->changeItemSelection(inv_item, true); + paste_into_root = true; + continue; } - }; - LLPointer cb = new LLBoostFuncInventoryCallback(on_copy_callback); + + paste(dest, objects, is_cut_mode, marketplacelistings_id); + is_cut_mode = false; + } + + if (paste_into_root) + { + for (const LLUUID& id : mSelectedItemIDs) + { + if (mItemMap[id]) + { + mItemMap[id]->setSelected(FALSE); + } + } + mSelectedItemIDs.clear(); + + paste(mFolderID, objects, is_cut_mode, marketplacelistings_id); + } + + LLClipboard::instance().setCutMode(false); +} + +void LLInventoryGallery::paste(const LLUUID& dest, + std::vector& objects, + bool is_cut_mode, + const LLUUID& marketplacelistings_id) +{ + LLHandle handle = getHandle(); + std::function on_copy_callback = NULL; + LLPointer cb = NULL; + if (dest == mFolderID) + { + on_copy_callback = [handle](const LLUUID& inv_item) + { + LLInventoryGallery* panel = (LLInventoryGallery*)handle.get(); + if (panel) + { + // Scroll to pasted item and highlight it + // Should it only highlight the last one? + panel->addItemSelection(inv_item, true); + } + }; + cb = new LLBoostFuncInventoryCallback(on_copy_callback); + } for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) { @@ -1517,9 +1719,11 @@ void LLInventoryGallery::paste() if (is_cut_mode) { gInventory.changeCategoryParent(cat, dest, false); - // Don't select immediately, wait for item to arrive - mItemToSelect = item_id; - mNeedsSelection = true; + if (dest == mFolderID) + { + // Don't select immediately, wait for item to arrive + mItemsToSelect.push_back(item_id); + } } else { @@ -1534,9 +1738,11 @@ void LLInventoryGallery::paste() if (is_cut_mode) { gInventory.changeItemParent(item, dest, false); - // Don't select immediately, wait for item to arrive - mItemToSelect = item_id; - mNeedsSelection = true; + if (dest == mFolderID) + { + // Don't select immediately, wait for item to arrive + mItemsToSelect.push_back(item_id); + } } else { @@ -1679,17 +1885,45 @@ void LLInventoryGallery::pasteAsLink() const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); const LLUUID& my_outifts_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - LLUUID dest; - if (mSelectedItemIDs.size() > 0) + std::vector objects; + LLClipboard::instance().pasteFromClipboard(objects); + + bool paste_into_root = mSelectedItemIDs.empty(); + for (LLUUID& dest : mSelectedItemIDs) { - dest = *mSelectedItemIDs.begin(); + LLInventoryObject* obj = gInventory.getObject(dest); + if (!obj || obj->getType() != LLAssetType::AT_CATEGORY) + { + paste_into_root = true; + continue; + } + + pasteAsLink(dest, objects, current_outfit_id, marketplacelistings_id, my_outifts_id); } - LLInventoryObject* obj = gInventory.getObject(dest); - if (!obj || obj->getType() != LLAssetType::AT_CATEGORY) + + if (paste_into_root) { - dest = mFolderID; + for (const LLUUID& id : mSelectedItemIDs) + { + if (mItemMap[id]) + { + mItemMap[id]->setSelected(FALSE); + } + } + mSelectedItemIDs.clear(); + + pasteAsLink(mFolderID, objects, current_outfit_id, marketplacelistings_id, my_outifts_id); } + LLClipboard::instance().setCutMode(false); +} + +void LLInventoryGallery::pasteAsLink(const LLUUID& dest, + std::vector& objects, + const LLUUID& current_outfit_id, + const LLUUID& marketplacelistings_id, + const LLUUID& my_outifts_id) +{ const BOOL move_is_into_current_outfit = (dest == current_outfit_id); const BOOL move_is_into_my_outfits = (dest == my_outifts_id) || gInventory.isObjectDescendentOf(dest, my_outifts_id); const BOOL move_is_into_marketplacelistings = gInventory.isObjectDescendentOf(dest, marketplacelistings_id); @@ -1698,21 +1932,23 @@ void LLInventoryGallery::pasteAsLink() { return; } - std::vector objects; - LLClipboard::instance().pasteFromClipboard(objects); - LLHandle handle = getHandle(); - std::function on_link_callback = [handle](const LLUUID& inv_item) + LLPointer cb = NULL; + if (dest == mFolderID) { - LLInventoryGallery *panel = (LLInventoryGallery*)handle.get(); - if (panel) - { - // Scroll to pasted item and highlight it - // Should it only highlight the last one? - panel->changeItemSelection(inv_item, true); - } - }; - LLPointer cb = new LLBoostFuncInventoryCallback(on_link_callback); + LLHandle handle = getHandle(); + std::function on_link_callback = [handle](const LLUUID& inv_item) + { + LLInventoryGallery* panel = (LLInventoryGallery*)handle.get(); + if (panel) + { + // Scroll to pasted item and highlight it + // Should it only highlight the last one? + panel->addItemSelection(inv_item, true); + } + }; + cb = new LLBoostFuncInventoryCallback(on_link_callback); + } for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); @@ -1724,8 +1960,6 @@ void LLInventoryGallery::pasteAsLink() link_inventory_object(dest, link_obj, cb); } } - - LLClipboard::instance().setCutMode(false); } void LLInventoryGallery::claimEditHandler() @@ -1852,7 +2086,7 @@ void LLInventoryGallery::refreshList(const LLUUID& category_id) mNeedsArrange = true; } - if(mNeedsArrange || mItemToSelect.notNull()) + if(mNeedsArrange || !mItemsToSelect.empty()) { // Don't scroll to target/arrange immediately // since more updates might be pending @@ -1969,7 +2203,7 @@ void LLInventoryGallery::deselectItem(const LLUUID& category_id) mItemMap[category_id]->setSelected(FALSE); setFocus(true); // Todo: support multiselect - signalSelectionItemID(LLUUID::null); + // signalSelectionItemID(LLUUID::null); } selection_deque::iterator found = std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), category_id); @@ -1991,6 +2225,7 @@ void LLInventoryGallery::clearSelection() if (!mSelectedItemIDs.empty()) { mSelectedItemIDs.clear(); + // BUG: wrong, item can be null signalSelectionItemID(LLUUID::null); } } @@ -2350,8 +2585,6 @@ void LLInventoryGalleryItem::draw() border.mTop = border.mTop + 1; gl_rect_2d(border, border_color.get(), FALSE); } - - } void LLInventoryGalleryItem::setItemName(std::string name) @@ -2379,7 +2612,18 @@ BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) { // call changeItemSelection directly, before setFocus // to avoid autoscroll from LLInventoryGallery::onFocusReceived() - mGallery->changeItemSelection(mUUID, false); + if (mask == MASK_CONTROL) + { + mGallery->addItemSelection(mUUID, false); + } + else if (mask == MASK_SHIFT) + { + mGallery->toggleSelectionRangeFromLast(mUUID); + } + else + { + mGallery->changeItemSelection(mUUID, false); + } setFocus(TRUE); mGallery->claimEditHandler(); @@ -2496,22 +2740,22 @@ BOOL LLInventoryGalleryItem::handleKeyHere(KEY key, MASK mask) switch (key) { case KEY_LEFT: - mGallery->moveLeft(); + mGallery->moveLeft(mask); handled = true; break; case KEY_RIGHT: - mGallery->moveRight(); + mGallery->moveRight(mask); handled = true; break; case KEY_UP: - mGallery->moveUp(); + mGallery->moveUp(mask); handled = true; break; case KEY_DOWN: - mGallery->moveDown(); + mGallery->moveDown(mask); handled = true; break; @@ -2525,7 +2769,6 @@ void LLInventoryGalleryItem::onFocusLost() { // inventory no longer handles cut/copy/paste/delete mGallery->resetEditHandler(); - setSelected(false); LLPanel::onFocusLost(); } @@ -2534,7 +2777,6 @@ void LLInventoryGalleryItem::onFocusReceived() { // inventory now handles cut/copy/paste/delete mGallery->claimEditHandler(); - setSelected(true); LLPanel::onFocusReceived(); } @@ -2649,6 +2891,11 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, { LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; + if (drop && LLToolDragAndDrop::getInstance()->getCargoIndex() == 0) + { + clearSelection(); + } + BOOL accepted = FALSE; switch(cargo_type) { @@ -2669,8 +2916,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, if (accepted && drop) { // Don't select immediately, wait for item to arrive - mItemToSelect = inv_item->getUUID(); - mNeedsSelection = true; + mItemsToSelect.push_back(inv_item->getUUID()); } break; case DAD_LINK: @@ -2691,8 +2937,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, } if (accepted && drop && inv_item) { - mItemToSelect = inv_item->getUUID(); - mNeedsSelection = true; + mItemsToSelect.push_back(inv_item->getUUID()); } break; case DAD_CATEGORY: @@ -2706,8 +2951,7 @@ BOOL LLInventoryGallery::baseHandleDragAndDrop(LLUUID dest_id, BOOL drop, accepted = dragCategoryIntoFolder(dest_id, cat_ptr, drop, tooltip_msg, FALSE); if (accepted && drop) { - mItemToSelect = cat_ptr->getUUID(); - mNeedsSelection = true; + mItemsToSelect.push_back(cat_ptr->getUUID()); } } break; -- cgit v1.2.3 From 167c5121d3a448dcbc15a9553c374c32a4f85eb9 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 6 Sep 2023 21:47:33 +0300 Subject: SL-19826 Basic 'shift' support for gallery Part#4 --- indra/newview/llinventorygallery.cpp | 159 +++++++++++++++++++++++++---------- 1 file changed, 114 insertions(+), 45 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index eab15b79ad..1ee08eb01c 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -217,6 +217,14 @@ void LLInventoryGallery::setRootFolder(const LLUUID cat_id) gIdleCallbacks.deleteFunction(onIdle, (void*)this); + for (const LLUUID& id : mSelectedItemIDs) + { + if (mItemMap[id]) + { + mItemMap[id]->setSelected(FALSE); + } + } + mFolderID = cat_id; mItemsToSelect.clear(); mSelectedItemIDs.clear(); @@ -1153,7 +1161,7 @@ void LLInventoryGallery::moveUp(MASK mask) if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID]; + LLInventoryGalleryItem* item = mItemMap[mLastInteractedUUID]; if (item) { if (mask == MASK_NONE || mask == MASK_CONTROL) @@ -1180,10 +1188,10 @@ void LLInventoryGallery::moveUp(MASK mask) { S32 n = mItemIndexMap[item]; S32 target = llmax(0, n - mItemsInRow); - toggleSelectionRange(target, n - 1); if (target != n) { item = mIndexToItemMap[target]; + toggleSelectionRangeFromLast(item->getUUID()); item->setFocus(TRUE); claimEditHandler(); } @@ -1198,7 +1206,7 @@ void LLInventoryGallery::moveDown(MASK mask) if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID]; + LLInventoryGalleryItem* item = mItemMap[mLastInteractedUUID]; if (item) { if (mask == MASK_NONE || mask == MASK_CONTROL) @@ -1225,10 +1233,10 @@ void LLInventoryGallery::moveDown(MASK mask) { S32 n = mItemIndexMap[item]; S32 target = llmin(mItemsAddedCount - 1, n + mItemsInRow); - toggleSelectionRange(n + 1, target); if (target != n) { item = mIndexToItemMap[target]; + toggleSelectionRangeFromLast(item->getUUID()); item->setFocus(TRUE); claimEditHandler(); } @@ -1243,10 +1251,10 @@ void LLInventoryGallery::moveLeft(MASK mask) if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID]; + LLInventoryGalleryItem* item = mItemMap[mLastInteractedUUID]; if (mask == MASK_SHIFT) { - item = mItemMap[mLastSelectedUUID]; + item = mItemMap[mLastInteractedUUID]; } if (item) { @@ -1265,7 +1273,15 @@ void LLInventoryGallery::moveLeft(MASK mask) } else if (mask == MASK_SHIFT) { - toggleItemSelection(item_id, true); + if (item->isSelected()) + { + toggleItemSelection(mLastInteractedUUID, true); + } + else + { + toggleItemSelection(item_id, true); + } + mLastInteractedUUID = item_id; } else { @@ -1283,7 +1299,7 @@ void LLInventoryGallery::moveRight(MASK mask) if (mInventoryGalleryMenu && mSelectedItemIDs.size() > 0 && mItemsAddedCount > 1) { - LLInventoryGalleryItem* item = mItemMap[mLastSelectedUUID]; + LLInventoryGalleryItem* item = mItemMap[mLastInteractedUUID]; if (item) { S32 n = mItemIndexMap[item]; @@ -1300,7 +1316,15 @@ void LLInventoryGallery::moveRight(MASK mask) } else if (mask == MASK_SHIFT) { - toggleItemSelection(item_id, true); + if (item->isSelected()) + { + toggleItemSelection(mLastInteractedUUID, true); + } + else + { + toggleItemSelection(item_id, true); + } + mLastInteractedUUID = item_id; } else { @@ -1315,35 +1339,62 @@ void LLInventoryGallery::moveRight(MASK mask) void LLInventoryGallery::toggleSelectionRange(S32 start_idx, S32 end_idx) { LLInventoryGalleryItem* item = NULL; - for (S32 i = start_idx; i <= end_idx; i++) + if (end_idx > start_idx) + { + for (S32 i = start_idx; i <= end_idx; i++) + { + item = mIndexToItemMap[i]; + LLUUID item_id = item->getUUID(); + toggleItemSelection(item_id, true); + } + } + else { - item = mIndexToItemMap[i]; - LLUUID item_id = item->getUUID(); - toggleItemSelection(item_id, true); + for (S32 i = start_idx; i >= end_idx; i--) + { + item = mIndexToItemMap[i]; + LLUUID item_id = item->getUUID(); + toggleItemSelection(item_id, true); + } } } void LLInventoryGallery::toggleSelectionRangeFromLast(const LLUUID target) { - if (mLastSelectedUUID == target) + if (mLastInteractedUUID == target) { return; } - LLInventoryGalleryItem* last_item = mItemMap[mLastSelectedUUID]; + LLInventoryGalleryItem* last_item = mItemMap[mLastInteractedUUID]; LLInventoryGalleryItem* next_item = mItemMap[target]; if (last_item && next_item) { S32 last_idx = mItemIndexMap[last_item]; S32 next_idx = mItemIndexMap[next_item]; - if (last_idx < next_idx) + if (next_item->isSelected()) { - toggleSelectionRange(last_idx + 1, next_idx); + if (last_idx < next_idx) + { + toggleSelectionRange(last_idx, next_idx - 1); + } + else + { + toggleSelectionRange(last_idx, next_idx + 1); + } } else { - toggleSelectionRange(next_idx, last_idx - 1); + if (last_idx < next_idx) + { + toggleSelectionRange(last_idx + 1, next_idx); + } + else + { + toggleSelectionRange(last_idx - 1, next_idx); + } } } + mLastInteractedUUID = next_item->getUUID(); } void LLInventoryGallery::onFocusLost() @@ -1408,7 +1459,6 @@ void LLInventoryGallery::showContextMenu(LLUICtrl* ctrl, S32 x, S32 y, const LLU { if (std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id) == mSelectedItemIDs.end()) { - mSelectedItemIDs.clear(); changeItemSelection(item_id, false); } uuid_vec_t selected_uuids(mSelectedItemIDs.begin(), mSelectedItemIDs.end()); @@ -1426,10 +1476,10 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ } } mSelectedItemIDs.clear(); + mItemsToSelect.clear(); if ((mItemMap.count(item_id) == 0) || mNeedsArrange) { - mItemsToSelect.clear(); mItemsToSelect.push_back(item_id); return; } @@ -1446,7 +1496,7 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ } mSelectedItemIDs.push_back(item_id); signalSelectionItemID(item_id); - mLastSelectedUUID = item_id; + mLastInteractedUUID = item_id; if (scroll_to_selection) { @@ -1473,7 +1523,7 @@ void LLInventoryGallery::addItemSelection(const LLUUID& item_id, bool scroll_to_ } mSelectedItemIDs.push_back(item_id); signalSelectionItemID(item_id); - mLastSelectedUUID = item_id; + mLastInteractedUUID = item_id; if (scroll_to_selection) { @@ -1507,9 +1557,9 @@ bool LLInventoryGallery::toggleItemSelection(const LLUUID& item_id, bool scroll_ } mSelectedItemIDs.push_back(item_id); signalSelectionItemID(item_id); - mLastSelectedUUID = item_id; result = true; } + mLastInteractedUUID = item_id; if (scroll_to_selection) { @@ -2338,6 +2388,43 @@ BOOL LLInventoryGallery::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, return handled; } +void LLInventoryGallery::startDrag() +{ + std::vector types; + uuid_vec_t ids; + LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_AGENT; + for (LLUUID& selected_id : mSelectedItemIDs) + { + const LLInventoryItem* item = gInventory.getItem(selected_id); + if (item) + { + if (item->getPermissions().getOwner() == ALEXANDRIA_LINDEN_ID) + { + src = LLToolDragAndDrop::SOURCE_LIBRARY; + } + + EDragAndDropType type = LLViewerAssetType::lookupDragAndDropType(item->getType()); + types.push_back(type); + ids.push_back(selected_id); + } + + const LLViewerInventoryCategory* cat = gInventory.getCategory(selected_id); + if (cat && gInventory.isObjectDescendentOf(selected_id, gInventory.getRootFolderID()) + && !LLFolderType::lookupIsProtectedType((cat)->getPreferredType())) + { + if (cat->getOwnerID() == ALEXANDRIA_LINDEN_ID) + { + src = LLToolDragAndDrop::SOURCE_LIBRARY; + } + + EDragAndDropType type = LLViewerAssetType::lookupDragAndDropType(cat->getType()); + types.push_back(type); + ids.push_back(selected_id); + } + } + LLToolDragAndDrop::getInstance()->beginMultiDrag(types, ids, LLToolDragAndDrop::SOURCE_AGENT); +} + bool LLInventoryGallery::areViewsInitialized() { return mGalleryCreated && mItemBuildQuery.empty(); @@ -2620,7 +2707,7 @@ BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) { mGallery->toggleSelectionRangeFromLast(mUUID); } - else + else if (!isSelected()) { mGallery->changeItemSelection(mUUID, false); } @@ -2663,28 +2750,10 @@ BOOL LLInventoryGalleryItem::handleHover(S32 x, S32 y, MASK mask) S32 screen_y; localPointToScreen(x, y, &screen_x, &screen_y ); - if(LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y)) + if(LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y) && mGallery) { - const LLInventoryItem *item = gInventory.getItem(mUUID); - if(item) - { - EDragAndDropType type = LLViewerAssetType::lookupDragAndDropType(item->getType()); - LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_LIBRARY; - if(item->getPermissions().getOwner() == gAgent.getID()) - { - src = LLToolDragAndDrop::SOURCE_AGENT; - } - LLToolDragAndDrop::getInstance()->beginDrag(type, item->getUUID(), src); - return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask ); - } - - const LLInventoryCategory *cat = gInventory.getCategory(mUUID); - if(cat && gInventory.isObjectDescendentOf(mUUID, gInventory.getRootFolderID()) - && !LLFolderType::lookupIsProtectedType((cat)->getPreferredType())) - { - LLToolDragAndDrop::getInstance()->beginDrag(LLViewerAssetType::lookupDragAndDropType(cat->getType()), cat->getUUID(), LLToolDragAndDrop::SOURCE_AGENT); - return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask ); - } + mGallery->startDrag(); + return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask); } } return LLUICtrl::handleHover(x,y,mask); -- cgit v1.2.3 From 76c6dc025d39adba54cff2c112337274efaddd10 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 14 Sep 2023 23:59:58 +0300 Subject: SL-19826 Gallery multiselect support, fix right click --- indra/newview/llinventorygallery.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'indra/newview/llinventorygallery.cpp') diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 1ee08eb01c..4838ba7a47 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1012,20 +1012,16 @@ BOOL LLInventoryGallery::handleRightMouseDown(S32 x, S32 y, MASK mask) { if (mSelectedItemIDs.size() > 0) { - selection_deque::iterator iter = mSelectedItemIDs.begin(); - if (mItemMap[*iter]) - { - mItemMap[*iter]->setFocus(false); - setFocus(true); - } + setFocus(true); } - clearSelection(); + mLastInteractedUUID = LLUUID::null; // Scroll is going to always return true BOOL res = LLPanel::handleRightMouseDown(x, y, mask); - if (mSelectedItemIDs.empty()) + if (mLastInteractedUUID.isNull()) // no child were hit { + clearSelection(); if (mInventoryGalleryMenu && mFolderID.notNull()) { uuid_vec_t selected_uuids; @@ -1487,6 +1483,7 @@ void LLInventoryGallery::changeItemSelection(const LLUUID& item_id, bool scroll_ && std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id) != mSelectedItemIDs.end()) { // Already selected + mLastInteractedUUID = item_id; return; } @@ -1514,6 +1511,7 @@ void LLInventoryGallery::addItemSelection(const LLUUID& item_id, bool scroll_to_ if (std::find(mSelectedItemIDs.begin(), mSelectedItemIDs.end(), item_id) != mSelectedItemIDs.end()) { // Already selected + mLastInteractedUUID = item_id; return; } @@ -2707,7 +2705,7 @@ BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) { mGallery->toggleSelectionRangeFromLast(mUUID); } - else if (!isSelected()) + else { mGallery->changeItemSelection(mUUID, false); } @@ -2724,6 +2722,15 @@ BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLInventoryGalleryItem::handleRightMouseDown(S32 x, S32 y, MASK mask) { + if (!isSelected()) + { + mGallery->changeItemSelection(mUUID, false); + } + else + { + // refresh last interacted + mGallery->addItemSelection(mUUID, false); + } setFocus(TRUE); mGallery->claimEditHandler(); mGallery->showContextMenu(this, x, y, mUUID); -- cgit v1.2.3