diff options
38 files changed, 1923 insertions, 2070 deletions
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index fbf23bc3f0..784e20ad46 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -275,6 +275,18 @@ void LLInventoryObject::correctInventoryName(std::string& name) LLStringUtil::truncate(name, DB_INV_ITEM_NAME_STR_LEN); } +time_t LLInventoryObject::getCreationDate() const +{ + return mCreationDate; +} + +void LLInventoryObject::setCreationDate(time_t creation_date_utc) +{ + mCreationDate = creation_date_utc; +} + + + ///---------------------------------------------------------------------------- /// Class LLInventoryItem @@ -297,9 +309,10 @@ LLInventoryItem::LLInventoryItem(const LLUUID& uuid, mDescription(desc), mSaleInfo(sale_info), mInventoryType(inv_type), - mFlags(flags), - mCreationDate(creation_date_utc) + mFlags(flags) { + mCreationDate = creation_date_utc; + LLStringUtil::replaceNonstandardASCII(mDescription, ' '); LLStringUtil::replaceChar(mDescription, '|', ' '); mPermissions.initMasks(inv_type); @@ -312,9 +325,9 @@ LLInventoryItem::LLInventoryItem() : mDescription(), mSaleInfo(), mInventoryType(LLInventoryType::IT_NONE), - mFlags(0), - mCreationDate(0) + mFlags(0) { + mCreationDate = 0; } LLInventoryItem::LLInventoryItem(const LLInventoryItem* other) : @@ -379,11 +392,6 @@ const std::string& LLInventoryItem::getDescription() const return mDescription; } -time_t LLInventoryItem::getCreationDate() const -{ - return mCreationDate; -} - U32 LLInventoryItem::getCRC32() const { // *FIX: Not a real crc - more of a checksum. @@ -440,11 +448,6 @@ void LLInventoryItem::setFlags(U32 flags) mFlags = flags; } -void LLInventoryItem::setCreationDate(time_t creation_date_utc) -{ - mCreationDate = creation_date_utc; -} - // Currently only used in the Viewer to handle calling cards // where the creator is actually used to store the target. void LLInventoryItem::setCreator(const LLUUID& creator) diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index a5cfe59bda..dc9a09e9d6 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -75,6 +75,7 @@ public: virtual LLAssetType::EType getType() const; LLAssetType::EType getActualType() const; // bypasses indirection for linked items BOOL getIsLinkType() const; + virtual time_t getCreationDate() const; //-------------------------------------------------------------------- // Mutators @@ -85,6 +86,7 @@ public: virtual void rename(const std::string& new_name); void setParent(const LLUUID& new_parent); void setType(LLAssetType::EType type); + virtual void setCreationDate(time_t creation_date_utc); // only stored for items private: // in place correction for inventory name string @@ -113,6 +115,7 @@ protected: LLUUID mParentUUID; // Parent category. Root categories have LLUUID::NULL. LLAssetType::EType mType; std::string mName; + time_t mCreationDate; // seconds from 1/1/1970, UTC }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -178,7 +181,6 @@ public: void setPermissions(const LLPermissions& perm); void setInventoryType(LLInventoryType::EType inv_type); void setFlags(U32 flags); - void setCreationDate(time_t creation_date_utc); void setCreator(const LLUUID& creator); // only used for calling cards // Check for changes in permissions masks and sale info @@ -224,7 +226,6 @@ protected: LLSaleInfo mSaleInfo; LLInventoryType::EType mInventoryType; U32 mFlags; - time_t mCreationDate; // seconds from 1/1/1970, UTC }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index ce59401e87..d44ccac6e4 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -212,7 +212,7 @@ namespace LLInitParam {} ParamValue(const default_value_t& other) - : T(other), + : T(other), mValidated(false) {} @@ -632,38 +632,38 @@ namespace LLInitParam class BaseBlock* mCurrentBlockPtr; // pointer to block currently being constructed }; - //TODO: implement in terms of owned_ptr - template<typename T> + //TODO: implement in terms of owned_ptr + template<typename T> class LazyValue - { + { public: LazyValue() - : mPtr(NULL) - {} + : mPtr(NULL) + {} ~LazyValue() - { - delete mPtr; - } + { + delete mPtr; + } LazyValue(const T& value) - { + { mPtr = new T(value); } LazyValue(const LazyValue& other) : mPtr(NULL) - { + { *this = other; - } + } LazyValue& operator = (const LazyValue& other) { if (!other.mPtr) - { + { delete mPtr; - mPtr = NULL; - } + mPtr = NULL; + } else { if (!mPtr) @@ -674,9 +674,9 @@ namespace LLInitParam { *mPtr = *(other.mPtr); } - } - return *this; } + return *this; + } bool operator==(const LazyValue& other) const { @@ -684,13 +684,13 @@ namespace LLInitParam return *mPtr == *other.mPtr; } - bool empty() const - { - return mPtr == NULL; - } + bool empty() const + { + return mPtr == NULL; + } - void set(const T& other) - { + void set(const T& other) + { if (!mPtr) { mPtr = new T(other); @@ -701,36 +701,36 @@ namespace LLInitParam } } - const T& get() const - { + const T& get() const + { return *ensureInstance(); - } + } - T& get() - { + T& get() + { return *ensureInstance(); } operator const T&() const { return get(); - } + } - private: - // lazily allocate an instance of T - T* ensureInstance() const + private: + // lazily allocate an instance of T + T* ensureInstance() const + { + if (mPtr == NULL) { - if (mPtr == NULL) - { - mPtr = new T(); - } - return mPtr; - } + mPtr = new T(); + } + return mPtr; + } - private: + private: - mutable T* mPtr; - }; + mutable T* mPtr; + }; // root class of all parameter blocks @@ -2492,10 +2492,10 @@ namespace LLInitParam } EValueAge; typedef ParamValue<T> derived_t; - typedef CustomParamValue<T> self_t; - typedef Block<derived_t> block_t; + typedef CustomParamValue<T> self_t; + typedef Block<derived_t> block_t; typedef T default_value_t; - typedef T value_t; + typedef T value_t; typedef void baseblock_base_class_t; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 785bf4b868..4f447fd35b 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -808,7 +808,7 @@ set(viewer_HEADER_FILES llfloaterwindowsize.h llfloaterworldmap.h llfolderview.h - llfoldervieweventlistener.h + llfolderviewmodel.h llfolderviewitem.h llfollowcam.h llfriendcard.h diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index c9031dd26a..68dc7681cc 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -711,23 +711,30 @@ namespace action_give_inventory //static std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs() { - std::set<LLUUID> inventory_selected_uuids; + std::set<LLFolderViewItem*> inventory_selected; LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel(); if (active_panel) { - inventory_selected_uuids = active_panel->getRootFolder()->getSelectionList(); + inventory_selected= active_panel->getRootFolder()->getSelectionList(); } - if (inventory_selected_uuids.empty()) + if (inventory_selected.empty()) { LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); if (sidepanel_inventory) { - inventory_selected_uuids = sidepanel_inventory->getInboxSelectionList(); + inventory_selected= sidepanel_inventory->getInboxSelectionList(); } } + std::set<LLUUID> inventory_selected_uuids; + for (std::set<LLFolderViewItem*>::iterator it = inventory_selected.begin(), end_it = inventory_selected.end(); + it != end_it; + ++it) + { + inventory_selected_uuids.insert((*it)->getListener()->getUUID()); + } return inventory_selected_uuids; } @@ -763,15 +770,15 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL // check selection in the panel LLFolderView* root_folder = inv_panel->getRootFolder(); - const std::set<LLUUID> inventory_selected_uuids = root_folder->getSelectionList(); - if (inventory_selected_uuids.empty()) return false; // nothing selected + const std::set<LLFolderViewItem*> inventory_selected = root_folder->getSelectionList(); + if (inventory_selected.empty()) return false; // nothing selected bool can_share = true; - std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); - const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end(); + std::set<LLFolderViewItem*>::const_iterator it = inventory_selected.begin(); + const std::set<LLFolderViewItem*>::const_iterator it_end = inventory_selected.end(); for (; it != it_end; ++it) { - LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); + LLViewerInventoryCategory* inv_cat = gInventory.getCategory((*it)->getItemViewModel()->getUUID()); // any category can be offered. if (inv_cat) { @@ -779,9 +786,9 @@ bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NUL } // check if inventory item can be given - LLFolderViewItem* item = root_folder->getItemByID(*it); + LLFolderViewItem* item = *it; if (!item) return false; - LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getListener()); + LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getViewModelItem()); if (bridge && bridge->canShare()) { continue; diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index c55970ad69..04a55b261c 100644 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -250,7 +250,8 @@ void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId) mOutboxInventoryPanel->setShape(inventory_placeholder_rect); // Set the sort order newest to oldest - mOutboxInventoryPanel->setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME); + + mOutboxInventoryPanel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME); mOutboxInventoryPanel->getFilter()->markDefault(); fetchOutboxContents(); @@ -386,7 +387,7 @@ BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, // Determine if the mouse is inside the inventory panel itself or just within the floater bool pointInInventoryPanel = false; bool pointInInventoryPanelChild = false; - LLFolderView * root_folder = mOutboxInventoryPanel->getRootFolder(); + LLFolderView* root_folder = mOutboxInventoryPanel->getRootFolder(); if (mOutboxInventoryPanel->getVisible()) { S32 inv_x, inv_y; @@ -443,10 +444,10 @@ void LLFloaterOutbox::onOutboxChanged() { llassert(!mOutboxId.isNull()); - if (mOutboxInventoryPanel) - { - mOutboxInventoryPanel->requestSort(); - } + //if (mOutboxInventoryPanel) + //{ + // mOutboxInventoryPanel->requestSort(); + //} fetchOutboxContents(); diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 57fc3f7efd..f0edbb638a 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -27,16 +27,13 @@ #include "llviewerprecompiledheaders.h" #include "llfolderview.h" +#include "llfolderview.h" #include "llcallbacklist.h" #include "llinventorybridge.h" #include "llclipboard.h" // *TODO: remove this once hack below gone. -#include "llinventoryfilter.h" -#include "llinventoryfunctions.h" -#include "llinventorymodelbackgroundfetch.h" #include "llinventorypanel.h" #include "llfoldertype.h" -#include "llfloaterinventory.h"// hacked in for the bonus context menu items. #include "llkeyboard.h" #include "lllineeditor.h" #include "llmenugl.h" @@ -64,7 +61,6 @@ #include "llfontgl.h" #include "llgl.h" #include "llrender.h" -#include "llinventory.h" // Third-party library includes #include <algorithm> @@ -94,42 +90,6 @@ enum { F32 LLFolderView::sAutoOpenTime = 1.f; -void delete_selected_item(void* user_data); -void copy_selected_item(void* user_data); -void open_selected_items(void* user_data); -void properties_selected_items(void* user_data); -void paste_items(void* user_data); - - -//--------------------------------------------------------------------------- - -// Tells all folders in a folderview to sort their items -// (and only their items, not folders) by a certain function. -class LLSetItemSortFunction : public LLFolderViewFunctor -{ -public: - LLSetItemSortFunction(U32 ordering) - : mSortOrder(ordering) {} - virtual ~LLSetItemSortFunction() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); - - U32 mSortOrder; -}; - - -// Set the sort order. -void LLSetItemSortFunction::doFolder(LLFolderViewFolder* folder) -{ - folder->setItemSortOrder(mSortOrder); -} - -// Do nothing. -void LLSetItemSortFunction::doItem(LLFolderViewItem* item) -{ - return; -} - //--------------------------------------------------------------------------- // Tells all folders in a folderview to close themselves @@ -154,7 +114,6 @@ public: }; -// Set the sort order. void LLCloseAllFoldersFunctor::doFolder(LLFolderViewFolder* folder) { folder->setOpenArrangeRecursively(mOpen); @@ -177,7 +136,7 @@ const LLRect LLFolderViewScrollContainer::getScrolledViewRect() const LLFolderView* folder_view = dynamic_cast<LLFolderView*>(mScrolledView); if (folder_view) { - S32 height = folder_view->mRunningHeight; + S32 height = folder_view->getRect().getHeight(); rect = mScrolledView->getRect(); rect.setLeftTopAndSize(rect.mLeft, rect.mTop, rect.getWidth(), height); @@ -200,7 +159,6 @@ LLFolderView::Params::Params() use_label_suffix("use_label_suffix"), allow_multiselect("allow_multiselect", true), show_empty_message("show_empty_message", true), - show_load_status("show_load_status", true), use_ellipses("use_ellipses", false) { folder_indentation = -4; @@ -210,7 +168,6 @@ LLFolderView::Params::Params() // Default constructor LLFolderView::LLFolderView(const Params& p) : LLFolderViewFolder(p), - mRunningHeight(0), mScrollContainer( NULL ), mPopupMenuHandle(), mAllowMultiSelect(p.allow_multiselect), @@ -226,7 +183,7 @@ LLFolderView::LLFolderView(const Params& p) mNeedsAutoRename(FALSE), mDebugFilters(FALSE), mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME), // This gets overridden by a pref immediately - mFilter( new LLInventoryFilter(p.title) ), + mFilter(), mShowSelectionContext(FALSE), mShowSingleSelection(FALSE), mArrangeGeneration(0), @@ -237,17 +194,15 @@ LLFolderView::LLFolderView(const Params& p) mParentPanel(p.parent_panel), mUseEllipses(p.use_ellipses), mDraggingOverItem(NULL), - mStatusTextBox(NULL) + mStatusTextBox(NULL), + mViewModel(p.view_model) { mRoot = this; - mShowLoadStatus = p.show_load_status(); - LLRect rect = p.rect; LLRect new_rect(rect.mLeft, rect.mBottom + getRect().getHeight(), rect.mLeft + getRect().getWidth(), rect.mBottom); setRect( rect ); reshape(rect.getWidth(), rect.getHeight()); - mIsOpen = TRUE; // this view is always open. mAutoOpenItems.setDepth(AUTO_OPEN_STACK_DEPTH); mAutoOpenCandidate = NULL; mAutoOpenTimer.stop(); @@ -332,8 +287,6 @@ LLFolderView::~LLFolderView( void ) mItems.clear(); mFolders.clear(); - mItemMap.clear(); - delete mFilter; mFilter = NULL; } @@ -343,31 +296,10 @@ BOOL LLFolderView::canFocusChildren() const return FALSE; } -static LLFastTimer::DeclareTimer FTM_SORT("Sort Inventory"); - -void LLFolderView::setSortOrder(U32 order) -{ - if (order != mSortOrder) - { - LLFastTimer t(FTM_SORT); - - mSortOrder = order; - - sortBy(order); - arrangeAll(); - } -} - - -U32 LLFolderView::getSortOrder() const -{ - return mSortOrder; -} - BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { // enforce sort order of My Inventory followed by Library - if (folder->getListener()->getUUID() == gInventory.getLibraryRootFolderID()) + if (((LLFolderViewModelItemInventory*)folder->getViewModelItem())->getUUID() == gInventory.getLibraryRootFolderID()) { mFolders.push_back(folder); } @@ -375,7 +307,6 @@ BOOL LLFolderView::addFolder( LLFolderViewFolder* folder) { mFolders.insert(mFolders.begin(), folder); } - folder->setShowLoadStatus(mShowLoadStatus); folder->setOrigin(0, 0); folder->reshape(getRect().getWidth(), 0); folder->setVisible(FALSE); @@ -402,131 +333,35 @@ void LLFolderView::openTopLevelFolders() } } -void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) -{ - // call base class to do proper recursion - LLFolderViewFolder::setOpenArrangeRecursively(openitem, recurse); - // make sure root folder is always open - mIsOpen = TRUE; -} - -static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); - // This view grows and shrinks to enclose all of its children items and folders. +// mItemHeight = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0; +// *width should be 0 +// conform show folder state works S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation ) { - if (getListener()->getUUID().notNull()) - { - if (mNeedsSort) - { - mFolders.sort(mSortFunction); - mItems.sort(mSortFunction); - mNeedsSort = false; - } - } - - LLFastTimer t2(FTM_ARRANGE); - - filter_generation = mFilter->getMinRequiredGeneration(); mMinWidth = 0; + S32 target_height; - mHasVisibleChildren = hasFilteredDescendants(filter_generation); - // arrange always finishes, so optimistically set the arrange generation to the most current - mLastArrangeGeneration = getRoot()->getArrangeGeneration(); - - LLInventoryFilter::EFolderShow show_folder_state = - getRoot()->getFilter()->getShowFolderState(); + LLFolderViewFolder::arrange(&mMinWidth, &target_height, mFilter->getFirstSuccessGeneration()); - S32 total_width = LEFT_PAD; - S32 running_height = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0; - S32 target_height = running_height; - S32 parent_item_height = getRect().getHeight(); - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - LLFolderViewFolder* folderp = (*fit); - if (getDebugFilters()) - { - folderp->setVisible(TRUE); - } - else - { - folderp->setVisible((show_folder_state == LLInventoryFilter::SHOW_ALL_FOLDERS || // always show folders? - (folderp->getFiltered(filter_generation) || folderp->hasFilteredDescendants(filter_generation)))); - } - - if (folderp->getVisible()) - { - S32 child_height = 0; - S32 child_width = 0; - S32 child_top = parent_item_height - running_height; - - target_height += folderp->arrange( &child_width, &child_height, filter_generation ); - - mMinWidth = llmax(mMinWidth, child_width); - total_width = llmax( total_width, child_width ); - running_height += child_height; - folderp->setOrigin( ICON_PAD, child_top - (*fit)->getRect().getHeight() ); - } - } - - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - LLFolderViewItem* itemp = (*iit); - itemp->setVisible(itemp->getFiltered(filter_generation)); - - if (itemp->getVisible()) - { - S32 child_width = 0; - S32 child_height = 0; - S32 child_top = parent_item_height - running_height; - - target_height += itemp->arrange( &child_width, &child_height, filter_generation ); - itemp->reshape(itemp->getRect().getWidth(), child_height); - - mMinWidth = llmax(mMinWidth, child_width); - total_width = llmax( total_width, child_width ); - running_height += child_height; - itemp->setOrigin( ICON_PAD, child_top - itemp->getRect().getHeight() ); - } - } - - if(!mHasVisibleChildren)// is there any filtered items ? - { - //Nope. We need to display status textbox, let's reserve some place for it - running_height = mStatusTextBox->getTextPixelHeight(); - target_height = running_height; - } - - mRunningHeight = running_height; LLRect scroll_rect = mScrollContainer->getContentWindowRect(); - reshape( llmax(scroll_rect.getWidth(), total_width), running_height ); + reshape( llmax(scroll_rect.getWidth(), mMinWidth), mCurHeight ); LLRect new_scroll_rect = mScrollContainer->getContentWindowRect(); if (new_scroll_rect.getWidth() != scroll_rect.getWidth()) { - reshape( llmax(scroll_rect.getWidth(), total_width), running_height ); + reshape( llmax(scroll_rect.getWidth(), mMinWidth), mCurHeight ); } // move item renamer text field to item's new position updateRenamerPosition(); - mTargetHeight = (F32)target_height; return llround(mTargetHeight); } -const std::string LLFolderView::getFilterSubString(BOOL trim) -{ - return mFilter->getFilterSubString(trim); -} - -static LLFastTimer::DeclareTimer FTM_FILTER("Filter Inventory"); +static LLFastTimer::DeclareTimer FTM_FILTER("Filter Folder View"); -void LLFolderView::filter( LLInventoryFilter& filter ) +void LLFolderView::filter( LLFolderViewFilter& filter ) { LLFastTimer t2(FTM_FILTER); filter.setFilterCount(llclamp(gSavedSettings.getS32("FilterItemsPerFrame"), 1, 5000)); @@ -552,7 +387,7 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent) scroll_rect = mScrollContainer->getContentWindowRect(); } width = llmax(mMinWidth, scroll_rect.getWidth()); - height = llmax(mRunningHeight, scroll_rect.getHeight()); + height = llmax(llround(mCurHeight), scroll_rect.getHeight()); // Restrict width within scroll container's width if (mUseEllipses && mScrollContainer) @@ -651,30 +486,6 @@ BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL openitem, return rv; } -void LLFolderView::setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus) -{ - LLFolderViewItem* itemp = getItemByID(obj_id); - if(itemp && itemp->getListener()) - { - itemp->arrangeAndSet(TRUE, take_keyboard_focus); - mSelectThisID.setNull(); - return; - } - else - { - // save the desired item to be selected later (if/when ready) - mSelectThisID = obj_id; - } -} - -void LLFolderView::updateSelection() -{ - if (mSelectThisID.notNull()) - { - setSelectionByID(mSelectThisID, false); - } -} - BOOL LLFolderView::changeSelection(LLFolderViewItem* selection, BOOL selected) { BOOL rv = FALSE; @@ -725,9 +536,6 @@ void LLFolderView::sanitizeSelection() // and we want to preserve context LLFolderViewItem* original_selected_item = getCurSelectedItem(); - // Cache "Show all folders" filter setting - BOOL show_all_folders = (getRoot()->getFilter()->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS); - std::vector<LLFolderViewItem*> items_to_remove; selected_items_t::iterator item_iter; for (item_iter = mSelectedItems.begin(); item_iter != mSelectedItems.end(); ++item_iter) @@ -738,21 +546,12 @@ void LLFolderView::sanitizeSelection() BOOL visible = item->potentiallyVisible(); // initialize from filter state for this item // modify with parent open and filters states LLFolderViewFolder* parent_folder = item->getParentFolder(); - if ( parent_folder ) - { - if ( show_all_folders ) - { // "Show all folders" is on, so this folder is visible - visible = TRUE; - } - else - { // Move up through parent folders and see what's visible + // Move up through parent folders and see what's visible while(parent_folder) { visible = visible && parent_folder->isOpen() && parent_folder->potentiallyVisible(); parent_folder = parent_folder->getParentFolder(); } - } - } // deselect item if any ancestor is closed or didn't pass filter requirements. if (!visible) @@ -841,18 +640,12 @@ void LLFolderView::clearSelection() } mSelectedItems.clear(); - mSelectThisID.setNull(); } -std::set<LLUUID> LLFolderView::getSelectionList() const -{ - std::set<LLUUID> selection; - for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); - item_it != mSelectedItems.end(); - ++item_it) +std::set<LLFolderViewItem*> LLFolderView::getSelectionList() const { - selection.insert((*item_it)->getListener()->getUUID()); - } + std::set<LLFolderViewItem*> selection; + std::copy(mSelectedItems.begin(), mSelectedItems.end(), std::inserter(selection, selection.begin())); return selection; } @@ -868,7 +661,7 @@ BOOL LLFolderView::startDrag(LLToolDragAndDrop::ESource source) { EDragAndDropType type = DAD_NONE; LLUUID id = LLUUID::null; - can_drag = can_drag && (*item_it)->getListener()->startDrag(&type, &id); + can_drag = can_drag && (*item_it)->getViewModelItem()->startDrag(&type, &id); types.push_back(type); cargo_ids.push_back(id); @@ -890,7 +683,7 @@ void LLFolderView::draw() if (mDebugFilters) { std::string current_filter_string = llformat("Current Filter: %d, Least Filter: %d, Auto-accept Filter: %d", - mFilter->getCurrentGeneration(), mFilter->getMinRequiredGeneration(), mFilter->getMustPassGeneration()); + mFilter->getCurrentGeneration(), mFilter->getFirstSuccessGeneration(), mFilter->getFirstRequiredGeneration()); LLFontGL::getFontMonospace()->renderUTF8(current_filter_string, 0, 2, getRect().getHeight() - LLFontGL::getFontMonospace()->getLineHeight(), LLColor4(0.5f, 0.5f, 0.8f, 1.f), LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); @@ -929,25 +722,23 @@ void LLFolderView::draw() mSearchString.clear(); } - if (hasVisibleChildren() - || mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) + if (hasVisibleChildren()) { mStatusText.clear(); mStatusTextBox->setVisible( FALSE ); } else if (mShowEmptyMessage) { - if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration()) + if (!mViewModel->contentsReady() || mCompletedFilterGeneration < mFilter->getFirstSuccessGeneration()) { + // TODO RN: Get this from filter mStatusText = LLTrans::getString("Searching"); } else { if (getFilter()) { - LLStringUtil::format_map_t args; - args["[SEARCH_TERM]"] = LLURI::escape(getFilter()->getFilterSubStringOrig()); - mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage(), args); + mStatusText = getFilter()->getEmptyLookupMessage(); } } mStatusTextBox->setValue(mStatusText); @@ -994,7 +785,7 @@ void LLFolderView::finishRenamingItem( void ) closeRenamer(); - // List is re-sorted alphabeticly, so scroll to make sure the selected item is visible. + // List is re-sorted alphabetically, so scroll to make sure the selected item is visible. scrollToShowSelection(); } @@ -1123,8 +914,8 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL } else if (count > 1) { - LLDynamicArray<LLFolderViewEventListener*> listeners; - LLFolderViewEventListener* listener; + LLDynamicArray<LLFolderViewModelItem*> listeners; + LLFolderViewModelItem* listener; LLFolderViewItem* last_item = items[count - 1]; LLFolderViewItem* new_selection = last_item->getNextOpenNode(FALSE); while(new_selection && new_selection->isSelected()) @@ -1150,13 +941,13 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL for(S32 i = 0; i < count; ++i) { - listener = items[i]->getListener(); - if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewEventListener*>::FAIL)) + listener = items[i]->getViewModelItem(); + if(listener && (listeners.find(listener) == LLDynamicArray<LLFolderViewModelItem*>::FAIL)) { listeners.put(listener); } } - listener = listeners.get(0); + listener = static_cast<LLFolderViewModelItem*>(listeners.get(0)); if(listener) { listener->removeBatch(listeners); @@ -1172,36 +963,37 @@ void LLFolderView::openSelectedItems( void ) { if(getVisible() && getEnabled()) { - if (mSelectedItems.size() == 1) - { - mSelectedItems.front()->openItem(); - } - else - { - LLMultiPreview* multi_previewp = new LLMultiPreview(); - LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - // IT_{OBJECT,ATTACHMENT} creates LLProperties - // floaters; others create LLPreviews. Put - // each one in the right type of container. - LLFolderViewEventListener* listener = (*item_it)->getListener(); - bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); - if (is_prop) - LLFloater::setFloaterHost(multi_propertiesp); - else - LLFloater::setFloaterHost(multi_previewp); - (*item_it)->openItem(); - } - - LLFloater::setFloaterHost(NULL); - // *NOTE: LLMulti* will safely auto-delete when open'd - // without any children. - multi_previewp->openFloater(LLSD()); - multi_propertiesp->openFloater(LLSD()); - } + // TODO RN: move to LLFolderViewModelInventory + //if (mSelectedItems.size() == 1) + //{ + // mSelectedItems.front()->openItem(); + //} + //else + //{ + // LLMultiPreview* multi_previewp = new LLMultiPreview(); + // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + + // selected_items_t::iterator item_it; + // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + // { + // // IT_{OBJECT,ATTACHMENT} creates LLProperties + // // floaters; others create LLPreviews. Put + // // each one in the right type of container. + // LLFolderViewModelItemInventory* listener = (*item_it)->getViewModelItem(); + // bool is_prop = listener && (listener->getInventoryType() == LLInventoryType::IT_OBJECT || listener->getInventoryType() == LLInventoryType::IT_ATTACHMENT); + // if (is_prop) + // LLFloater::setFloaterHost(multi_propertiesp); + // else + // LLFloater::setFloaterHost(multi_previewp); + // (*item_it)->openItem(); + // } + + // LLFloater::setFloaterHost(NULL); + // // *NOTE: LLMulti* will safely auto-delete when open'd + // // without any children. + // multi_previewp->openFloater(LLSD()); + // multi_propertiesp->openFloater(LLSD()); + //} } } @@ -1209,27 +1001,28 @@ void LLFolderView::propertiesSelectedItems( void ) { if(getVisible() && getEnabled()) { - if (mSelectedItems.size() == 1) - { - LLFolderViewItem* folder_item = mSelectedItems.front(); - if(!folder_item) return; - folder_item->getListener()->showProperties(); - } - else - { - LLMultiProperties* multi_propertiesp = new LLMultiProperties(); + // TODO RN: move to LLFolderViewModelInventory + //if (mSelectedItems.size() == 1) + //{ + // LLFolderViewItem* folder_item = mSelectedItems.front(); + // if(!folder_item) return; + // folder_item->getViewModelItem()->showProperties(); + //} + //else + //{ + // LLMultiProperties* multi_propertiesp = new LLMultiProperties(); - LLFloater::setFloaterHost(multi_propertiesp); + // LLFloater::setFloaterHost(multi_propertiesp); - selected_items_t::iterator item_it; - for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) - { - (*item_it)->getListener()->showProperties(); - } + // selected_items_t::iterator item_it; + // for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) + // { + // (*item_it)->getViewModelItem()->showProperties(); + // } - LLFloater::setFloaterHost(NULL); - multi_propertiesp->openFloater(LLSD()); - } + // LLFloater::setFloaterHost(NULL); + // multi_propertiesp->openFloater(LLSD()); + //} } } @@ -1327,7 +1120,7 @@ BOOL LLFolderView::canCopy() const for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) { const LLFolderViewItem* item = *selected_it; - if (!item->getListener()->isItemCopyable()) + if (!item->getViewModelItem()->isItemCopyable()) { return FALSE; } @@ -1343,11 +1136,11 @@ void LLFolderView::copy() S32 count = mSelectedItems.size(); if(getVisible() && getEnabled() && (count > 0)) { - LLFolderViewEventListener* listener = NULL; + LLFolderViewModelItem* listener = NULL; selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - listener = (*item_it)->getListener(); + listener = (*item_it)->getViewModelItem(); if(listener) { listener->copyToClipboard(); @@ -1367,7 +1160,7 @@ BOOL LLFolderView::canCut() const for (selected_items_t::const_iterator selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) { const LLFolderViewItem* item = *selected_it; - const LLFolderViewEventListener* listener = item->getListener(); + const LLFolderViewModelItem* listener = item->getViewModelItem(); if (!listener || !listener->isItemRemovable()) { @@ -1384,11 +1177,11 @@ void LLFolderView::cut() S32 count = mSelectedItems.size(); if(getVisible() && getEnabled() && (count > 0)) { - LLFolderViewEventListener* listener = NULL; + LLFolderViewModelItem* listener = NULL; selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - listener = (*item_it)->getListener(); + listener = (*item_it)->getViewModelItem(); if(listener) { listener->cutToClipboard(); @@ -1413,11 +1206,11 @@ BOOL LLFolderView::canPaste() const { // *TODO: only check folders and parent folders of items const LLFolderViewItem* item = (*item_it); - const LLFolderViewEventListener* listener = item->getListener(); + const LLFolderViewModelItem* listener = item->getViewModelItem(); if(!listener || !listener->isClipboardPasteable()) { const LLFolderViewFolder* folderp = item->getParentFolder(); - listener = folderp->getListener(); + listener = folderp->getViewModelItem(); if (!listener || !listener->isClipboardPasteable()) { return FALSE; @@ -1435,24 +1228,24 @@ void LLFolderView::paste() if(getVisible() && getEnabled()) { // find set of unique folders to paste into - std::set<LLFolderViewItem*> folder_set; + std::set<LLFolderViewFolder*> folder_set; selected_items_t::iterator selected_it; for (selected_it = mSelectedItems.begin(); selected_it != mSelectedItems.end(); ++selected_it) { LLFolderViewItem* item = *selected_it; - LLFolderViewEventListener* listener = item->getListener(); - if (listener->getInventoryType() != LLInventoryType::IT_CATEGORY) + LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(item); + if (folder == NULL) { item = item->getParentFolder(); } - folder_set.insert(item); + folder_set.insert(folder); } - std::set<LLFolderViewItem*>::iterator set_iter; + std::set<LLFolderViewFolder*>::iterator set_iter; for(set_iter = folder_set.begin(); set_iter != folder_set.end(); ++set_iter) { - LLFolderViewEventListener* listener = (*set_iter)->getListener(); + LLFolderViewModelItem* listener = (*set_iter)->getViewModelItem(); if(listener && listener->isClipboardPasteable()) { listener->pasteFromClipboard(); @@ -1474,8 +1267,8 @@ void LLFolderView::startRenamingSelectedItem( void ) { item = mSelectedItems.front(); } - if(getVisible() && getEnabled() && (count == 1) && item && item->getListener() && - item->getListener()->isItemRenameable()) + if(getVisible() && getEnabled() && (count == 1) && item && item->getViewModelItem() && + item->getViewModelItem()->isItemRenameable()) { mRenameItem = item; @@ -1784,7 +1577,7 @@ BOOL LLFolderView::canDoDelete() const for (selected_items_t::const_iterator item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - if (!(*item_it)->getListener()->isItemRemovable()) + if (!(*item_it)->getViewModelItem()->isItemRemovable()) { return FALSE; } @@ -1895,7 +1688,7 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) S32 count = mSelectedItems.size(); LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); if ( handled - && ( count > 0 && (hasVisibleChildren() || mFilter->getShowFolderState() == LLInventoryFilter::SHOW_ALL_FOLDERS) ) // show menu only if selected items are visible + && ( count > 0 && (hasVisibleChildren()) ) // show menu only if selected items are visible && menu ) { if (mCallbackRegistrar) @@ -1968,15 +1761,9 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, // when drop is not handled by child, it should be handled // by the folder which is the hierarchy root. - if (!handled - && getListener()->getUUID().notNull()) - { - handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - } - - if (handled) + if (!handled) { - lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderView" << llendl; + handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); } return handled; @@ -2076,55 +1863,6 @@ void LLFolderView::setShowSingleSelection(BOOL show) } } -void LLFolderView::addItemID(const LLUUID& id, LLFolderViewItem* itemp) -{ - mItemMap[id] = itemp; -} - -void LLFolderView::removeItemID(const LLUUID& id) -{ - mItemMap.erase(id); -} - -LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); -LLFolderViewItem* LLFolderView::getItemByID(const LLUUID& id) -{ - LLFastTimer _(FTM_GET_ITEM_BY_ID); - if (id == getListener()->getUUID()) - { - return this; - } - - std::map<LLUUID, LLFolderViewItem*>::iterator map_it; - map_it = mItemMap.find(id); - if (map_it != mItemMap.end()) - { - return map_it->second; - } - - return NULL; -} - -LLFolderViewFolder* LLFolderView::getFolderByID(const LLUUID& id) -{ - if (id == getListener()->getUUID()) - { - return this; - } - - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end(); - ++iter) - { - LLFolderViewFolder *folder = (*iter); - if (folder->getListener()->getUUID() == id) - { - return folder; - } - } - return NULL; -} - bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) { std::string action = userdata.asString(); @@ -2140,7 +1878,7 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) return true; } if (("copy" == action) || ("cut" == action)) - { + { // Clear the clipboard before we start adding things on it LLClipboard::instance().reset(); } @@ -2155,7 +1893,7 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) } - std::set<LLUUID> selected_items = getSelectionList(); + std::set<LLFolderViewItem*> selected_items = getSelectionList(); LLMultiPreview* multi_previewp = NULL; LLMultiProperties* multi_propertiesp = NULL; @@ -2176,13 +1914,13 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata) LLFloater::setFloaterHost(multi_propertiesp); } - std::set<LLUUID>::iterator set_iter; + std::set<LLFolderViewItem*>::iterator set_iter; for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) { - LLFolderViewItem* folder_item = getItemByID(*set_iter); + LLFolderViewItem* folder_item = *set_iter; if(!folder_item) continue; - LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); + LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem(); if(!bridge) continue; bridge->performAction(model, action); } @@ -2248,7 +1986,7 @@ void LLFolderView::doIdle() // Open filtered folders for folder views with mAutoSelectOverride=TRUE. // Used by LLPlacesFolderView. - if (mAutoSelectOverride && !mFilter->getFilterSubString().empty()) + if (mAutoSelectOverride && mFilter->showAllResults()) { // these are named variables to get around gcc not binding non-const references to rvalues // and functor application is inherently non-const to allow for stateful functors @@ -2260,7 +1998,7 @@ void LLFolderView::doIdle() } BOOL filter_finished = mCompletedFilterGeneration >= mFilter->getCurrentGeneration() - && !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); + && mViewModel->contentsReady(); if (filter_finished || gFocusMgr.childHasKeyboardFocus(inventory_panel) || gFocusMgr.childHasMouseCapture(inventory_panel)) @@ -2540,72 +2278,18 @@ void LLFolderView::onRenamerLost() } } -LLInventoryFilter* LLFolderView::getFilter() +LLFolderViewFilter* LLFolderView::getFilter() { return mFilter; } -void LLFolderView::setFilterPermMask( PermissionMask filter_perm_mask ) -{ - mFilter->setFilterPermissions(filter_perm_mask); -} - -U32 LLFolderView::getFilterObjectTypes() const -{ - return mFilter->getFilterObjectTypes(); -} - -PermissionMask LLFolderView::getFilterPermissions() const -{ - return mFilter->getFilterPermissions(); -} - -BOOL LLFolderView::isFilterModified() -{ - return mFilter->isNotDefault(); -} - -void delete_selected_item(void* user_data) -{ - if(user_data) - { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->removeSelectedItems(); - } -} - -void copy_selected_item(void* user_data) -{ - if(user_data) - { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->copy(); - } -} - -void paste_items(void* user_data) -{ - if(user_data) - { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->paste(); - } -} - -void open_selected_items(void* user_data) -{ - if(user_data) - { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->openSelectedItems(); - } -} - -void properties_selected_items(void* user_data) +S32 LLFolderView::getItemHeight() { - if(user_data) + S32 debug_height = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0; + if(!hasVisibleChildren()) { - LLFolderView* fv = reinterpret_cast<LLFolderView*>(user_data); - fv->propertiesSelectedItems(); + //We need to display status textbox, let's reserve some place for it + return llmax(debug_height, mStatusTextBox->getTextPixelHeight()); } + return debug_height; } diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h index dc3d02eac6..813b4d130f 100644 --- a/indra/newview/llfolderview.h +++ b/indra/newview/llfolderview.h @@ -48,9 +48,10 @@ #include "lltooldraganddrop.h" #include "llviewertexture.h" -class LLFolderViewEventListener; +class LLFolderViewModelInterface; class LLFolderViewFolder; class LLFolderViewItem; +class LLFolderViewFilter; class LLInventoryModel; class LLPanel; class LLLineEditor; @@ -95,8 +96,8 @@ public: Optional<bool> use_label_suffix, allow_multiselect, show_empty_message, - show_load_status, use_ellipses; + Mandatory<LLFolderViewModelInterface*> view_model; Params(); }; @@ -110,9 +111,8 @@ public: virtual LLFolderView* getRoot() { return this; } - // FolderViews default to sort by name. This will change that, - // and resort the items if necessary. - void setSortOrder(U32 order); + LLFolderViewModelInterface* getFolderViewModel() { return mViewModel; } + void setFilterPermMask(PermissionMask filter_perm_mask); typedef boost::signals2::signal<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)> signal_t; @@ -120,14 +120,7 @@ public: void setReshapeCallback(const signal_t::slot_type& cb) { mReshapeSignal.connect(cb); } // filter is never null - LLInventoryFilter* getFilter(); - const std::string getFilterSubString(BOOL trim = FALSE); - U32 getFilterObjectTypes() const; - PermissionMask getFilterPermissions() const; - // *NOTE: use getFilter()->getShowFolderState(); - //LLInventoryFilter::EFolderShow getShowFolderState(); - U32 getSortOrder() const; - BOOL isFilterModified(); + LLFolderViewFilter* getFilter(); bool getAllowMultiSelect() { return mAllowMultiSelect; } @@ -135,19 +128,18 @@ public: void closeAllFolders(); void openTopLevelFolders(); - virtual void toggleOpen() {}; - virtual void setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse); virtual BOOL addFolder( LLFolderViewFolder* folder); // Find width and height of this object and its children. Also // makes sure that this view and its children are the right size. virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); + virtual S32 getItemHeight(); void arrangeAll() { mArrangeGeneration++; } S32 getArrangeGeneration() { return mArrangeGeneration; } - // Apply filters to control visibility of inventory items - virtual void filter( LLInventoryFilter& filter); + // applies filters to control visibility of items + virtual void filter( LLFolderViewFilter& filter); // Get the last selected item virtual LLFolderViewItem* getCurSelectedItem( void ); @@ -156,21 +148,15 @@ public: virtual BOOL setSelection(LLFolderViewItem* selection, BOOL openitem, BOOL take_keyboard_focus); - // Used by menu callbacks - void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); - - // Called once a frame to update the selection if mSelectThisID has been set - void updateSelection(); - - // This method is used to toggle the selection of an item. - // Walks children and keeps track of selected objects. + // This method is used to toggle the selection of an item. Walks + // children, and keeps track of selected objects. virtual BOOL changeSelection(LLFolderViewItem* selection, BOOL selected); - virtual std::set<LLUUID> getSelectionList() const; + virtual std::set<LLFolderViewItem*> getSelectionList() const; // Make sure if ancestor is selected, descendents are not void sanitizeSelection(); - void clearSelection(); + virtual void clearSelection(); void addToSelectionList(LLFolderViewItem* item); void removeFromSelectionList(LLFolderViewItem* item); @@ -193,6 +179,7 @@ public: void autoOpenItem(LLFolderViewFolder* item); void closeAutoOpenedFolders(); BOOL autoOpenTest(LLFolderViewFolder* item); + BOOL isOpen() const { return TRUE; } // root folder always open // Copy & paste virtual void copy(); @@ -241,11 +228,6 @@ public: F32 getSelectionFadeElapsedTime() { return mMultiSelectionFadeTimer.getElapsedTimeF32(); } bool getUseEllipses() { return mUseEllipses; } - void addItemID(const LLUUID& id, LLFolderViewItem* itemp); - void removeItemID(const LLUUID& id); - LLFolderViewItem* getItemByID(const LLUUID& id); - LLFolderViewFolder* getFolderByID(const LLUUID& id); - bool doToSelected(LLInventoryModel* model, const LLSD& userdata); void doIdle(); // Real idle routine @@ -320,7 +302,7 @@ protected: LLFrameTimer mAutoOpenTimer; LLFrameTimer mSearchTimer; std::string mSearchString; - LLInventoryFilter* mFilter; + LLFolderViewFilter* mFilter; BOOL mShowSelectionContext; BOOL mShowSingleSelection; LLFrameTimer mMultiSelectionFadeTimer; @@ -330,13 +312,11 @@ protected: signal_t mReshapeSignal; S32 mSignalSelectCallback; S32 mMinWidth; - S32 mRunningHeight; - std::map<LLUUID, LLFolderViewItem*> mItemMap; BOOL mDragAndDropThisFrame; - LLUUID mSelectThisID; // if non null, select this item - LLPanel* mParentPanel; + + LLFolderViewModelInterface* mViewModel; /** * Is used to determine if we need to cut text In LLFolderViewItem to avoid horizontal scroll. @@ -357,8 +337,66 @@ public: }; -bool sort_item_name(LLFolderViewItem* a, LLFolderViewItem* b); -bool sort_item_date(LLFolderViewItem* a, LLFolderViewItem* b); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFolderViewFunctor +// +// Simple abstract base class for applying a functor to folders and +// items in a folder view hierarchy. This is suboptimal for algorithms +// that only work folders or only work on items, but I'll worry about +// that later when it's determined to be too slow. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLFolderViewFunctor +{ +public: + virtual ~LLFolderViewFunctor() {} + virtual void doFolder(LLFolderViewFolder* folder) = 0; + virtual void doItem(LLFolderViewItem* item) = 0; +}; + +class LLSelectFirstFilteredItem : public LLFolderViewFunctor +{ +public: + LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} + virtual ~LLSelectFirstFilteredItem() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); + BOOL wasItemSelected() { return mItemSelected; } +protected: + BOOL mItemSelected; +}; + +class LLOpenFilteredFolders : public LLFolderViewFunctor +{ +public: + LLOpenFilteredFolders() {} + virtual ~LLOpenFilteredFolders() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; + +class LLSaveFolderState : public LLFolderViewFunctor +{ +public: + LLSaveFolderState() : mApply(FALSE) {} + virtual ~LLSaveFolderState() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item) {} + void setApply(BOOL apply); + void clearOpenFolders() { mOpenFolders.clear(); } +protected: + std::set<LLUUID> mOpenFolders; + BOOL mApply; +}; + +class LLOpenFoldersWithSelection : public LLFolderViewFunctor +{ +public: + LLOpenFoldersWithSelection() {} + virtual ~LLOpenFoldersWithSelection() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; // Flags for buildContextMenu() const U32 SUPPRESS_OPEN_ITEM = 0x1; diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h deleted file mode 100644 index 06682dcbf1..0000000000 --- a/indra/newview/llfoldervieweventlistener.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @file llfoldervieweventlistener.h - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ -#ifndef LLFOLDERVIEWEVENTLISTENER_H -#define LLFOLDERVIEWEVENTLISTENER_H - -#include "lldarray.h" // *TODO: convert to std::vector -#include "llfoldertype.h" -#include "llfontgl.h" // just for StyleFlags enum -#include "llinventorytype.h" -#include "llpermissionsflags.h" -#include "llpointer.h" -#include "llwearabletype.h" - - -class LLFolderViewItem; -class LLFolderView; -class LLFontGL; -class LLInventoryModel; -class LLMenuGL; -class LLScrollContainer; -class LLUIImage; -class LLUUID; - -// This is an abstract base class that users of the folderview classes -// would use to catch the useful events emitted from the folder -// views. -class LLFolderViewEventListener -{ -public: - virtual ~LLFolderViewEventListener( void ) {} - virtual const std::string& getName() const = 0; - virtual const std::string& getDisplayName() const = 0; - virtual const LLUUID& getUUID() const = 0; - virtual time_t getCreationDate() const = 0; // UTC seconds - virtual PermissionMask getPermissionMask() const = 0; - virtual LLFolderType::EType getPreferredType() const = 0; - virtual LLPointer<LLUIImage> getIcon() const = 0; - virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } - virtual LLFontGL::StyleFlags getLabelStyle() const = 0; - virtual std::string getLabelSuffix() const = 0; - virtual void openItem( void ) = 0; - virtual void closeItem( void ) = 0; - virtual void previewItem( void ) = 0; - virtual void selectItem(void) = 0; - virtual void showProperties(void) = 0; - virtual BOOL isItemRenameable() const = 0; - virtual BOOL renameItem(const std::string& new_name) = 0; - virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder - virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed - virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. - virtual BOOL removeItem() = 0; - virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) = 0; - virtual void move( LLFolderViewEventListener* parent_listener ) = 0; - virtual BOOL isItemCopyable() const = 0; - virtual BOOL copyToClipboard() const = 0; - virtual BOOL cutToClipboard() const = 0; - virtual BOOL isClipboardPasteable() const = 0; - virtual void pasteFromClipboard() = 0; - virtual void pasteLinkFromClipboard() = 0; - virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; - virtual BOOL isUpToDate() const = 0; - virtual BOOL hasChildren() const = 0; - virtual LLInventoryType::EType getInventoryType() const = 0; - virtual void performAction(LLInventoryModel* model, std::string action) = 0; - virtual LLWearableType::EType getWearableType() const = 0; - - // This method should be called when a drag begins. returns TRUE - // if the drag can begin, otherwise FALSE. - virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; - - // This method will be called to determine if a drop can be - // performed, and will set drop to TRUE if a drop is - // requested. Returns TRUE if a drop is possible/happened, - // otherwise FALSE. - virtual BOOL dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - std::string& tooltip_msg) = 0; -}; - -#endif diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index f40f051537..6e60ec5e1a 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -29,10 +29,10 @@ // viewer includes #include "llfolderview.h" // Items depend extensively on LLFolderViews -#include "llfoldervieweventlistener.h" +#include "llfolderview.h" +#include "llfolderviewmodel.h" #include "llviewerfoldertype.h" #include "llinventorybridge.h" // for LLItemBridge in LLInventorySort::operator() -#include "llinventoryfilter.h" #include "llinventoryfunctions.h" #include "llinventorymodelbackgroundfetch.h" #include "llpanel.h" @@ -119,18 +119,16 @@ LLFolderViewItem::LLFolderViewItem(const LLFolderViewItem::Params& p) mItemHeight(p.item_height), mPassedFilter(FALSE), mLastFilterGeneration(-1), - mStringMatchOffset(std::string::npos), + //TODO RN: create interface for string highlighting + //mStringMatchOffset(std::string::npos), mControlLabelRotation(0.f), mDragAndDropTarget(FALSE), - mIsLoading(FALSE), mLabel(p.name), mRoot(p.root), - mCreationDate(p.creation_date), mIcon(p.icon), mIconOpen(p.icon_open), mIconOverlay(p.icon_overlay), mListener(p.listener), - mShowLoadStatus(false), mIsMouseOverTitle(false) { } @@ -219,19 +217,13 @@ LLFolderViewItem* LLFolderViewItem::getPreviousOpenNode(BOOL include_children) // until we find out otherwise BOOL LLFolderViewItem::potentiallyVisible() { - // we haven't been checked against min required filter - // or we have and we passed - return potentiallyFiltered(); -} - -BOOL LLFolderViewItem::potentiallyFiltered() -{ - return getLastFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration() || getFiltered(); + return getFiltered() // we've passed the filter + || getLastFilterGeneration() < getRoot()->getFilter()->getFirstSuccessGeneration(); // or we don't know yet } BOOL LLFolderViewItem::getFiltered() { - return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration(); + return mPassedFilter && mLastFilterGeneration >= getRoot()->getFilter()->getFirstSuccessGeneration(); } BOOL LLFolderViewItem::getFiltered(S32 filter_generation) @@ -250,60 +242,19 @@ void LLFolderViewItem::setIcon(LLUIImagePtr icon) mIcon = icon; } -// refresh information from the listener -void LLFolderViewItem::refreshFromListener() +void LLFolderViewItem::refresh() { - if(mListener) - { - mLabel = mListener->getDisplayName(); - LLFolderType::EType preferred_type = mListener->getPreferredType(); - - // *TODO: to be removed when database supports multi language. This is a - // temporary attempt to display the inventory folder in the user locale. - // mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID - // it uses the same way to find localized string + if(!getViewModelItem()) return; - // HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder) - // Translation of Accessories folder in Library inventory folder - bool accessories = false; - if(mLabel == std::string("Accessories")) - { - //To ensure that Accessories folder is in Library we have to check its parent folder. - //Due to parent LLFolderViewFloder is not set to this item yet we have to check its parent via Inventory Model - LLInventoryCategory* cat = gInventory.getCategory(mListener->getUUID()); - if(cat) - { - const LLUUID& parent_folder_id = cat->getParentUUID(); - accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); - } - } - - //"Accessories" inventory category has folder type FT_NONE. So, this folder - //can not be detected as protected with LLFolderType::lookupIsProtectedType - if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) - { - LLTrans::findString(mLabel, "InvFolder " + mLabel); - }; + mLabel = getViewModelItem()->getDisplayName(); - setToolTip(mLabel); - setIcon(mListener->getIcon()); - time_t creation_date = mListener->getCreationDate(); - if ((creation_date > 0) && (mCreationDate != creation_date)) - { - setCreationDate(creation_date); - dirtyFilter(); - } - if (mRoot->useLabelSuffix()) - { - mLabelStyle = mListener->getLabelStyle(); - mLabelSuffix = mListener->getLabelSuffix(); - } + setToolTip(mLabel); + setIcon(getViewModelItem()->getIcon()); + if (mRoot->useLabelSuffix()) + { + mLabelStyle = getViewModelItem()->getLabelStyle(); + mLabelSuffix = getViewModelItem()->getLabelSuffix(); } -} - -void LLFolderViewItem::refresh() -{ - refreshFromListener(); std::string searchable_label(mLabel); searchable_label.append(mLabelSuffix); @@ -322,11 +273,7 @@ void LLFolderViewItem::refresh() } mLabelWidthDirty = true; -} - -void LLFolderViewItem::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor) -{ - functor(mListener); + dirtyFilter(); } // This function is called when items are added or view filters change. It's @@ -392,26 +339,20 @@ void LLFolderViewItem::changeSelectionFromRoot(LLFolderViewItem* selection, BOOL getRoot()->changeSelection(selection, selected); } -std::set<LLUUID> LLFolderViewItem::getSelectionList() const +std::set<LLFolderViewItem*> LLFolderViewItem::getSelectionList() const { - std::set<LLUUID> selection; + std::set<LLFolderViewItem*> selection; return selection; } -EInventorySortGroup LLFolderViewItem::getSortGroup() const -{ - return SG_ITEM; -} - // addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder) { if (!folder) { return FALSE; } mParentFolder = folder; - root->addItemID(getListener()->getUUID(), this); return folder->addItem(this); } @@ -450,7 +391,7 @@ S32 LLFolderViewItem::getItemHeight() return mItemHeight; } -void LLFolderViewItem::filter( LLInventoryFilter& filter) +void LLFolderViewItem::filter( LLFolderViewFilter& filter) { const BOOL previous_passed_filter = mPassedFilter; const BOOL passed_filter = filter.check(this); @@ -465,7 +406,8 @@ void LLFolderViewItem::filter( LLInventoryFilter& filter) } setFiltered(passed_filter, filter.getCurrentGeneration()); - mStringMatchOffset = filter.getStringMatchOffset(); + //TODO RN: create interface for string highlighting + //mStringMatchOffset = filter.getStringMatchOffset(this); filter.decrementFilterCount(); if (getRoot()->getDebugFilters()) @@ -528,9 +470,9 @@ void LLFolderViewItem::selectItem(void) { if (mIsSelected == FALSE) { - if (mListener) + if (getViewModelItem()) { - mListener->selectItem(); + getViewModelItem()->selectItem(); } mIsSelected = TRUE; } @@ -538,9 +480,9 @@ void LLFolderViewItem::selectItem(void) BOOL LLFolderViewItem::isMovable() { - if( mListener ) + if( getViewModelItem() ) { - return mListener->isItemMovable(); + return getViewModelItem()->isItemMovable(); } else { @@ -550,9 +492,9 @@ BOOL LLFolderViewItem::isMovable() BOOL LLFolderViewItem::isRemovable() { - if( mListener ) + if( getViewModelItem() ) { - return mListener->isItemRemovable(); + return getViewModelItem()->isItemRemovable(); } else { @@ -578,9 +520,9 @@ BOOL LLFolderViewItem::remove() { return FALSE; } - if(mListener) + if(getViewModelItem()) { - return mListener->removeItem(); + return getViewModelItem()->removeItem(); } return TRUE; } @@ -588,25 +530,17 @@ BOOL LLFolderViewItem::remove() // Build an appropriate context menu for the item. void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) { - if(mListener) + if(getViewModelItem()) { - mListener->buildContextMenu(menu, flags); + getViewModelItem()->buildContextMenu(menu, flags); } } void LLFolderViewItem::openItem( void ) { - if( mListener ) - { - mListener->openItem(); - } -} - -void LLFolderViewItem::preview( void ) -{ - if (mListener) + if( getViewModelItem() ) { - mListener->previewItem(); + getViewModelItem()->openItem(); } } @@ -614,9 +548,9 @@ void LLFolderViewItem::rename(const std::string& new_name) { if( !new_name.empty() ) { - if( mListener ) + if( getViewModelItem() ) { - mListener->renameItem(new_name); + getViewModelItem()->renameItem(new_name); if(mParentFolder) { @@ -631,19 +565,13 @@ const std::string& LLFolderViewItem::getSearchableLabel() const return mSearchableLabel; } -LLViewerInventoryItem * LLFolderViewItem::getInventoryItem(void) -{ - if (!getListener()) return NULL; - return gInventory.getItem(getListener()->getUUID()); -} - const std::string& LLFolderViewItem::getName( void ) const { - if(mListener) + if(getViewModelItem()) { - return mListener->getName(); + return getViewModelItem()->getName(); } - return mLabel; + return LLStringUtil::null; } // LLView functionality @@ -719,21 +647,19 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) // *TODO: push this into listener and remove // dependency on llagent - if (mListener - && gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getRootFolderID())) + if (getViewModelItem()) { - src = LLToolDragAndDrop::SOURCE_AGENT; + src = getViewModelItem()->getDragSource(); } - else if (mListener - && gInventory.isObjectDescendentOf(mListener->getUUID(), gInventory.getLibraryRootFolderID())) + else { - src = LLToolDragAndDrop::SOURCE_LIBRARY; + src = LLToolDragAndDrop::SOURCE_VIEWER; } can_drag = root->startDrag(src); if (can_drag) { - // if (mListener) mListener->startDrag(); + // if (getViewModelItem()) getViewModelItem()->startDrag(); // RN: when starting drag and drop, clear out last auto-open root->autoOpenTest(NULL); root->setShowSelectionContext(TRUE); @@ -770,7 +696,10 @@ BOOL LLFolderViewItem::handleHover( S32 x, S32 y, MASK mask ) BOOL LLFolderViewItem::handleDoubleClick( S32 x, S32 y, MASK mask ) { - preview(); + if (getViewModelItem()) + { + getViewModelItem()->openItem(); + } return TRUE; } @@ -822,9 +751,9 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, { BOOL accepted = FALSE; BOOL handled = FALSE; - if(mListener) + if(getViewModelItem()) { - accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); + accepted = getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); handled = accepted; if (accepted) { @@ -870,16 +799,12 @@ void LLFolderViewItem::draw() const S32 FOCUS_LEFT = 1; const LLFontGL* font = getLabelFontForStyle(mLabelStyle); - const BOOL in_inventory = getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getRootFolderID()); - const BOOL in_library = getListener() && gInventory.isObjectDescendentOf(getListener()->getUUID(), gInventory.getLibraryRootFolderID()); + getViewModelItem()->update(); //--------------------------------------------------------------------------------// // Draw open folder arrow // - const bool up_to_date = mListener && mListener->isUpToDate(); - const bool possibly_has_children = ((up_to_date && hasVisibleChildren()) // we fetched our children and some of them have passed the filter... - || (!up_to_date && mListener && mListener->hasChildren())); // ...or we know we have children but haven't fetched them (doesn't obey filter) - if (possibly_has_children) + if (hasVisibleChildren() || getViewModelItem()->hasChildren()) { LLUIImage* arrow_image = default_params.folder_arrow_image; gl_draw_scaled_rotated_image( @@ -976,25 +901,27 @@ void LLFolderViewItem::draw() mDragAndDropTarget = FALSE; } - const LLViewerInventoryItem *item = getInventoryItem(); - const BOOL highlight_link = mIconOverlay && item && item->getIsLinkType(); - //--------------------------------------------------------------------------------// - // Draw open icon - // - const S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; - if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders - { - mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); - } - else if (mIcon) - { - mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - } - - if (highlight_link) - { - mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); - } + //TODO RN: implement this in terms of getIcon() and getIconOverlay() + + //const LLViewerInventoryItem *item = getInventoryItem(); + //const BOOL highlight_link = mIconOverlay && item && item->getIsLinkType(); + ////--------------------------------------------------------------------------------// + //// Draw open icon + //// + //const S32 icon_x = mIndentation + ARROW_SIZE + TEXT_PAD; + //if (!mIconOpen.isNull() && (llabs(mControlLabelRotation) > 80)) // For open folders + // { + // mIconOpen->draw(icon_x, getRect().getHeight() - mIconOpen->getHeight() - TOP_PAD + 1); + //} + //else if (mIcon) + //{ + // mIcon->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + // } + + //if (highlight_link) + //{ + // mIconOverlay->draw(icon_x, getRect().getHeight() - mIcon->getHeight() - TOP_PAD + 1); + //} //--------------------------------------------------------------------------------// // Exit if no label to draw @@ -1005,9 +932,10 @@ void LLFolderViewItem::draw() } LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor; - if (highlight_link) color = sLinkColor; - if (in_library) color = sLibraryColor; - + //TODO RN: implement this in terms of getColor() + //if (highlight_link) color = sLinkColor; + //if (getViewModelItem() && gInventory.isObjectDescendentOf(getViewModelItem()->getUUID(), gInventory.getLibraryRootFolderID())) color = sLibraryColor; + F32 right_x = 0; F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation); @@ -1017,7 +945,7 @@ void LLFolderViewItem::draw() // if (getRoot()->getDebugFilters()) { - if (!getFiltered() && !possibly_has_children) + if (!getFiltered() && !getViewModelItem()->hasChildren()) { color.mV[VALPHA] *= 0.5f; } @@ -1037,30 +965,6 @@ void LLFolderViewItem::draw() S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE); //--------------------------------------------------------------------------------// - // Draw "Loading..." text - // - bool root_is_loading = false; - if (in_inventory) - { - root_is_loading = LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress(); - } - if (in_library) - { - root_is_loading = LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress(); - } - if ((mIsLoading - && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) - || (LLInventoryModelBackgroundFetch::instance().folderFetchActive() - && root_is_loading - && mShowLoadStatus)) - { - std::string load_string = " ( " + LLTrans::getString("LoadingData") + " ) "; - font->renderUTF8(load_string, 0, right_x, y, sSearchStatusColor, - LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - S32_MAX, S32_MAX, &right_x, FALSE); - } - - //--------------------------------------------------------------------------------// // Draw label suffix // if (!mLabelSuffix.empty()) @@ -1073,28 +977,29 @@ void LLFolderViewItem::draw() //--------------------------------------------------------------------------------// // Highlight string match // - if (mStringMatchOffset != std::string::npos) - { - // don't draw backgrounds for zero-length strings - S32 filter_string_length = getRoot()->getFilterSubString().size(); - if (filter_string_length > 0) - { - std::string combined_string = mLabel + mLabelSuffix; - S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; - S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; - S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); - S32 top = getRect().getHeight() - TOP_PAD; - - LLUIImage* box_image = default_params.selection_image; - LLRect box_rect(left, top, right, bottom); - box_image->draw(box_rect, sFilterBGColor); - F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); - F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; - font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, - sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, - filter_string_length, S32_MAX, &right_x, FALSE ); - } - } + //TODO RN: expose interface for highlighting + //if (mStringMatchOffset != std::string::npos) + //{ + // // don't draw backgrounds for zero-length strings + // S32 filter_string_length = getRoot()->getFilterSubString().size(); + // if (filter_string_length > 0) + // { + // std::string combined_string = mLabel + mLabelSuffix; + // S32 left = llround(text_left) + font->getWidth(combined_string, 0, mStringMatchOffset) - 1; + // S32 right = left + font->getWidth(combined_string, mStringMatchOffset, filter_string_length) + 2; + // S32 bottom = llfloor(getRect().getHeight() - font->getLineHeight() - 3 - TOP_PAD); + // S32 top = getRect().getHeight() - TOP_PAD; + // + // LLUIImage* box_image = default_params.selection_image; + // LLRect box_rect(left, top, right, bottom); + // box_image->draw(box_rect, sFilterBGColor); + // F32 match_string_left = text_left + font->getWidthF32(combined_string, 0, mStringMatchOffset); + // F32 yy = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD; + // font->renderUTF8( combined_string, mStringMatchOffset, match_string_left, yy, + // sFilterTextColor, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, + // filter_string_length, S32_MAX, &right_x, FALSE ); + // } + //} } @@ -1103,19 +1008,16 @@ void LLFolderViewItem::draw() ///---------------------------------------------------------------------------- LLFolderViewFolder::LLFolderViewFolder( const LLFolderViewItem::Params& p ): - LLFolderViewItem( p ), // 0 = no create time + LLFolderViewItem( p ), mIsOpen(FALSE), mExpanderHighlighted(FALSE), mCurHeight(0.f), mTargetHeight(0.f), mAutoOpenCountdown(0.f), - mSubtreeCreationDate(0), - mAmTrash(LLFolderViewFolder::UNKNOWN), mLastArrangeGeneration( -1 ), mLastCalculatedWidth(0), mCompletedFilterGeneration(-1), mMostFilteredDescendantGeneration(-1), - mNeedsSort(false), mPassedFolderFilter(FALSE) { } @@ -1136,32 +1038,30 @@ void LLFolderViewFolder::setFilteredFolder(bool filtered, S32 filter_generation) bool LLFolderViewFolder::getFilteredFolder(S32 filter_generation) { - return mPassedFolderFilter && mLastFilterGeneration >= getRoot()->getFilter()->getMinRequiredGeneration(); + return mPassedFolderFilter && mLastFilterGeneration >= getRoot()->getFilter()->getFirstSuccessGeneration(); } // addToFolder() returns TRUE if it succeeds. FALSE otherwise -BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +BOOL LLFolderViewFolder::addToFolder(LLFolderViewFolder* folder) { if (!folder) { return FALSE; } mParentFolder = folder; - root->addItemID(getListener()->getUUID(), this); return folder->addFolder(this); } +static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); + // Finds width and height of this object and its children. Also // makes sure that this view and its children are the right size. S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) { // sort before laying out contents - if (mNeedsSort) - { - mFolders.sort(mSortFunction); - mItems.sort(mSortFunction); - mNeedsSort = false; - } + getRoot()->getFolderViewModel()->sort(this); + + LLFastTimer t2(FTM_ARRANGE); // evaluate mHasVisibleChildren mHasVisibleChildren = false; @@ -1183,8 +1083,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit) { LLFolderViewFolder* folderp = (*fit); - found = ( folderp->getListener() - && (folderp->getFiltered(filter_generation) + found = ( (folderp->getFiltered(filter_generation) || (folderp->getFilteredFolder(filter_generation) && folderp->hasFilteredDescendants(filter_generation)))); if (found) @@ -1202,7 +1101,6 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) mCurHeight = llmax((F32)*height, mCurHeight); // initialize running height value as height of single item in case we have no children - *height = getItemHeight(); F32 running_height = (F32)*height; F32 target_height = (F32)*height; @@ -1212,7 +1110,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) // set last arrange generation first, in case children are animating // and need to be arranged again mLastArrangeGeneration = getRoot()->getArrangeGeneration(); - if (mIsOpen) + if (isOpen()) { // Add sizes of children S32 parent_item_height = getRect().getHeight(); @@ -1226,10 +1124,9 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) } else { - folderp->setVisible( folderp->getListener() - && (folderp->getFiltered(filter_generation) + folderp->setVisible( folderp->getFiltered(filter_generation) || (folderp->getFilteredFolder(filter_generation) - && folderp->hasFilteredDescendants(filter_generation)))); // passed filter or has descendants that passed filter + && folderp->hasFilteredDescendants(filter_generation))); // passed filter or has descendants that passed filter } if (folderp->getVisible()) @@ -1288,7 +1185,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation) // animate current height towards target height if (llabs(mCurHeight - mTargetHeight) > 1.f) { - mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(mIsOpen ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); + mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(isOpen() ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); requestArrange(); @@ -1339,9 +1236,7 @@ BOOL LLFolderViewFolder::needsArrange() void LLFolderViewFolder::requestSort() { - mNeedsSort = true; - // whenever item order changes, we need to lay things out again - requestArrange(); + getRoot()->getFolderViewModel()->requestSort(this); } void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recurse_up) @@ -1357,15 +1252,15 @@ void LLFolderViewFolder::setCompletedFilterGeneration(S32 generation, BOOL recur } } -void LLFolderViewFolder::filter( LLInventoryFilter& filter) +void LLFolderViewFolder::filter( LLFolderViewFilter& filter) { S32 filter_generation = filter.getCurrentGeneration(); // if failed to pass filter newer than must_pass_generation // you will automatically fail this time, so we only // check against items that have passed the filter - S32 must_pass_generation = filter.getMustPassGeneration(); + S32 must_pass_generation = filter.getFirstRequiredGeneration(); - bool autoopen_folders = (filter.hasFilterString()); + bool autoopen_folders = filter.showAllResults(); // if we have already been filtered against this generation, skip out if (getCompletedFilterGeneration() >= filter_generation) @@ -1380,8 +1275,9 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) && !mPassedFilter) // and did not pass the filter { // go ahead and flag this folder as done - mLastFilterGeneration = filter_generation; - mStringMatchOffset = std::string::npos; + mLastFilterGeneration = filter_generation; + //TODO RN: create interface for string highlighting + //mStringMatchOffset = std::string::npos; } else // filter self only on first pass through { @@ -1415,15 +1311,6 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) return; } - // when applying a filter, matching folders get their contents downloaded first - if (filter.isNotDefault() - && getFiltered(filter.getMinRequiredGeneration()) - && (mListener - && !gInventory.isCategoryComplete(mListener->getUUID()))) - { - LLInventoryModelBackgroundFetch::instance().start(mListener->getUUID()); - } - // now query children for (folders_t::iterator iter = mFolders.begin(); iter != mFolders.end(); @@ -1442,7 +1329,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) if (folder->getCompletedFilterGeneration() >= filter_generation) { // track latest generation to pass any child items - if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getMinRequiredGeneration())) + if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getFirstSuccessGeneration())) { mMostFilteredDescendantGeneration = filter_generation; requestArrange(); @@ -1496,7 +1383,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) item->filter( filter ); - if (item->getFiltered(filter.getMinRequiredGeneration())) + if (item->getFiltered(filter.getFirstSuccessGeneration())) { mMostFilteredDescendantGeneration = filter_generation; requestArrange(); @@ -1513,7 +1400,7 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) } } -void LLFolderViewFolder::filterFolder(LLInventoryFilter& filter) +void LLFolderViewFolder::filterFolder(LLFolderViewFilter& filter) { const BOOL previous_passed_filter = mPassedFolderFilter; const BOOL passed_filter = filter.checkFolder(this); @@ -1561,7 +1448,7 @@ void LLFolderViewFolder::dirtyFilter() BOOL LLFolderViewFolder::getFiltered() { - return getFilteredFolder(getRoot()->getFilter()->getMinRequiredGeneration()) + return getFilteredFolder(getRoot()->getFilter()->getFirstSuccessGeneration()) && LLFolderViewItem::getFiltered(); } @@ -1578,7 +1465,7 @@ BOOL LLFolderViewFolder::hasFilteredDescendants(S32 filter_generation) BOOL LLFolderViewFolder::hasFilteredDescendants() { - return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getCurrentGeneration(); + return mMostFilteredDescendantGeneration >= getRoot()->getFilter()->getFirstSuccessGeneration(); } // Passes selection information on to children and record selection @@ -1933,14 +1820,6 @@ void LLFolderViewFolder::extendSelectionTo(LLFolderViewItem* new_selection) void LLFolderViewFolder::destroyView() { - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - LLFolderViewItem* item = (*iit); - getRoot()->removeItemID(item->getListener()->getUUID()); - } - std::for_each(mItems.begin(), mItems.end(), DeletePointer()); mItems.clear(); @@ -1950,8 +1829,6 @@ void LLFolderViewFolder::destroyView() folderp->destroyView(); // removes entry from mFolders } - //deleteAllChildren(); - if (mParentFolder) { mParentFolder->removeView(this); @@ -2013,103 +1890,14 @@ void LLFolderViewFolder::extractItem( LLFolderViewItem* item ) dirtyFilter(); //because an item is going away regardless of filter status, force rearrange requestArrange(); - getRoot()->removeItemID(item->getListener()->getUUID()); removeChild(item); } -bool LLFolderViewFolder::isTrash() const -{ - if (mAmTrash == LLFolderViewFolder::UNKNOWN) - { - mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH; - } - return mAmTrash == LLFolderViewFolder::TRASH; -} - -void LLFolderViewFolder::sortBy(U32 order) -{ - if (!mSortFunction.updateSort(order)) - { - // No changes. - return; - } - - // Propagate this change to sub folders - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->sortBy(order); - } - - // Don't sort the topmost folders (My Inventory and Library) - if (mListener->getUUID().notNull()) - { - mFolders.sort(mSortFunction); - mItems.sort(mSortFunction); - } - - if (order & LLInventoryFilter::SO_DATE) - { - time_t latest = 0; - - if (!mItems.empty()) - { - LLFolderViewItem* item = *(mItems.begin()); - latest = item->getCreationDate(); - } - - if (!mFolders.empty()) - { - LLFolderViewFolder* folder = *(mFolders.begin()); - if (folder->getCreationDate() > latest) - { - latest = folder->getCreationDate(); - } - } - mSubtreeCreationDate = latest; - } -} - -void LLFolderViewFolder::setItemSortOrder(U32 ordering) -{ - if (mSortFunction.updateSort(ordering)) - { - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->setItemSortOrder(ordering); - } - - mFolders.sort(mSortFunction); - mItems.sort(mSortFunction); - } -} - -EInventorySortGroup LLFolderViewFolder::getSortGroup() const -{ - if (isTrash()) - { - return SG_TRASH_FOLDER; - } - - if( mListener ) - { - if(LLFolderType::lookupIsProtectedType(mListener->getPreferredType())) - { - return SG_SYSTEM_FOLDER; - } - } - - return SG_NORMAL_FOLDER; -} - BOOL LLFolderViewFolder::isMovable() { - if( mListener ) + if( getViewModelItem() ) { - if( !(mListener->isItemMovable()) ) + if( !(getViewModelItem()->isItemMovable()) ) { return FALSE; } @@ -2140,9 +1928,9 @@ BOOL LLFolderViewFolder::isMovable() BOOL LLFolderViewFolder::isRemovable() { - if( mListener ) + if( getViewModelItem() ) { - if( !(mListener->isItemRemovable()) ) + if( !(getViewModelItem()->isItemRemovable()) ) { return FALSE; } @@ -2182,37 +1970,23 @@ BOOL LLFolderViewFolder::addItem(LLFolderViewItem* item) item->dirtyFilter(); - // Update the folder creation date if the folder has no creation date - bool setting_date = false; - const time_t item_creation_date = item->getCreationDate(); - if ((item_creation_date > 0) && (mCreationDate == 0)) - { - setCreationDate(item_creation_date); - setting_date = true; - } - // Handle sorting requestArrange(); requestSort(); - // Traverse parent folders and update creation date and resort, if necessary - LLFolderViewFolder* parentp = getParentFolder(); - while (parentp) - { - // Update the parent folder creation date - if (setting_date && (parentp->mCreationDate == 0)) - { - parentp->setCreationDate(item_creation_date); - } + //TODO RN - make sort bubble up as long as parent Folder doesn't have anything matching sort criteria + //// Traverse parent folders and update creation date and resort, if necessary + //LLFolderViewFolder* parentp = this; + //while (parentp) + //{ + // if (parentp->mSortFunction.isByDate()) + // { + // // parent folder doesn't have a time stamp yet, so get it from us + // parentp->requestSort(); + // } - if (parentp->mSortFunction.isByDate()) - { - // parent folder doesn't have a time stamp yet, so get it from us - parentp->requestSort(); - } - - parentp = parentp->getParentFolder(); - } + // parentp = parentp->getParentFolder(); + //} return TRUE; } @@ -2229,13 +2003,7 @@ BOOL LLFolderViewFolder::addFolder(LLFolderViewFolder* folder) // rearrange all descendants too, as our indentation level might have changed folder->requestArrange(TRUE); requestSort(); - LLFolderViewFolder* parentp = getParentFolder(); - while (parentp && !parentp->mSortFunction.isByDate()) - { - // parent folder doesn't have a time stamp yet, so get it from us - parentp->requestSort(); - parentp = parentp->getParentFolder(); - } + return TRUE; } @@ -2261,7 +2029,7 @@ void LLFolderViewFolder::requestArrange(BOOL include_descendants) void LLFolderViewFolder::toggleOpen() { - setOpen(!mIsOpen); + setOpen(!isOpen()); } // Force a folder open or closed @@ -2272,17 +2040,17 @@ void LLFolderViewFolder::setOpen(BOOL openitem) void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse) { - BOOL was_open = mIsOpen; + BOOL was_open = isOpen(); mIsOpen = openitem; - if (mListener) + if (getViewModelItem()) { if(!was_open && openitem) { - mListener->openItem(); + getViewModelItem()->openItem(); } else if(was_open && !openitem) { - mListener->closeItem(); + getViewModelItem()->closeItem(); } } @@ -2302,7 +2070,7 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL openitem, ERecurseType r mParentFolder->setOpenArrangeRecursively(openitem, RECURSE_UP); } - if (was_open != mIsOpen) + if (was_open != isOpen()) { requestArrange(); } @@ -2371,23 +2139,6 @@ void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor) } } -void LLFolderViewFolder::applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor) -{ - functor(mListener); - for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) - { - folders_t::iterator fit = iter++; - (*fit)->applyListenerFunctorRecursively(functor); - } - for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) - { - items_t::iterator iit = iter++; - (*iit)->applyListenerFunctorRecursively(functor); - } -} - // LLView functionality BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, @@ -2398,7 +2149,7 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, { BOOL handled = FALSE; - if (mIsOpen) + if (isOpen()) { handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL); } @@ -2420,7 +2171,7 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - BOOL accepted = mListener && mListener->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); + BOOL accepted = getViewModelItem() && getViewModelItem()->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); if (accepted) { @@ -2444,11 +2195,8 @@ BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) { BOOL handled = FALSE; - // fetch contents of this folder, as context menu can depend on contents - // still, user would have to open context menu again to see the changes - gInventory.fetchDescendentsOf(mListener->getUUID()); - if( mIsOpen ) + if( isOpen() ) { handled = childrenHandleRightMouseDown( x, y, mask ) != NULL; } @@ -2478,7 +2226,7 @@ BOOL LLFolderViewFolder::handleHover(S32 x, S32 y, MASK mask) BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) { BOOL handled = FALSE; - if( mIsOpen ) + if( isOpen() ) { handled = childrenHandleMouseDown(x,y,mask) != NULL; } @@ -2502,17 +2250,17 @@ BOOL LLFolderViewFolder::handleMouseDown( S32 x, S32 y, MASK mask ) BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask ) { /* Disable outfit double click to wear - const LLUUID &cat_uuid = getListener()->getUUID(); + const LLUUID &cat_uuid = getViewModelItem()->getUUID(); const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid); if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT) { - getListener()->performAction(NULL, NULL,"replaceoutfit"); + getViewModelItem()->performAction(NULL, NULL,"replaceoutfit"); return TRUE; } */ BOOL handled = FALSE; - if( mIsOpen ) + if( isOpen() ) { handled = childrenHandleDoubleClick( x, y, mask ) != NULL; } @@ -2540,7 +2288,7 @@ void LLFolderViewFolder::draw() { mControlLabelRotation = mAutoOpenCountdown * -90.f; } - else if (mIsOpen) + else if (isOpen()) { mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); } @@ -2549,31 +2297,10 @@ void LLFolderViewFolder::draw() mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); } - bool possibly_has_children = false; - bool up_to_date = mListener && mListener->isUpToDate(); - if(!up_to_date - && mListener->hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter) - { - possibly_has_children = true; - } - - - BOOL loading = (mIsOpen - && possibly_has_children - && !up_to_date ); - - if ( loading && !mIsLoading ) - { - // Measure how long we've been in the loading state - mTimeSinceRequestStart.reset(); - } - - mIsLoading = loading; - LLFolderViewItem::draw(); // draw children if root folder, or any other folder that is open or animating to closed state - if( getRoot() == this || (mIsOpen || mCurHeight != mTargetHeight )) + if( getRoot() == this || (isOpen() || mCurHeight != mTargetHeight )) { LLView::draw(); } @@ -2581,20 +2308,14 @@ void LLFolderViewFolder::draw() mExpanderHighlighted = FALSE; } -time_t LLFolderViewFolder::getCreationDate() const -{ - return llmax<time_t>(mCreationDate, mSubtreeCreationDate); -} - - BOOL LLFolderViewFolder::potentiallyVisible() { // folder should be visible by it's own filter status return LLFolderViewItem::potentiallyVisible() // or one or more of its descendants have passed the minimum filter requirement - || hasFilteredDescendants(getRoot()->getFilter()->getMinRequiredGeneration()) + || hasFilteredDescendants() // or not all of its descendants have been checked against minimum filter requirement - || getCompletedFilterGeneration() < getRoot()->getFilter()->getMinRequiredGeneration(); + || getCompletedFilterGeneration() < getRoot()->getFilter()->getFirstSuccessGeneration(); } // this does prefix traversal, as folders are listed above their contents @@ -2808,48 +2529,35 @@ LLFolderViewItem* LLFolderViewFolder::getPreviousFromChild( LLFolderViewItem* it return result; } - -bool LLInventorySort::updateSort(U32 order) -{ - if (order != mSortOrder) - { - mSortOrder = order; - mByDate = (order & LLInventoryFilter::SO_DATE); - mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); - mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); - return true; - } - return false; -} - -bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b) +bool LLInventorySort::operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const { // ignore sort order for landmarks in the Favorites folder. // they should be always sorted as in Favorites bar. See EXT-719 - if (a->getSortGroup() == SG_ITEM - && b->getSortGroup() == SG_ITEM - && a->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK - && b->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) - { - - static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - - LLUUID a_uuid = a->getParentFolder()->getListener()->getUUID(); - LLUUID b_uuid = b->getParentFolder()->getListener()->getUUID(); - - if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) - { - // *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem - // or to LLInvFVBridge - LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a->getListener()))->getItem(); - LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b->getListener()))->getItem(); - if (!aitem || !bitem) - return false; - S32 a_sort = aitem->getSortField(); - S32 b_sort = bitem->getSortField(); - return a_sort < b_sort; - } - } + //TODO RN: fix sorting in favorites folder + //if (a->getSortGroup() == SG_ITEM + // && b->getSortGroup() == SG_ITEM + // && a->getInventoryType() == LLInventoryType::IT_LANDMARK + // && b->getInventoryType() == LLInventoryType::IT_LANDMARK) + //{ + + // static const LLUUID& favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + + // LLUUID a_uuid = a->getParentFolder()->getUUID(); + // LLUUID b_uuid = b->getParentFolder()->getUUID(); + + // if ((a_uuid == favorites_folder_id && b_uuid == favorites_folder_id)) + // { + // // *TODO: mantipov: probably it is better to add an appropriate method to LLFolderViewItem + // // or to LLInvFVBridge + // LLViewerInventoryItem* aitem = (static_cast<const LLItemBridge*>(a))->getItem(); + // LLViewerInventoryItem* bitem = (static_cast<const LLItemBridge*>(b))->getItem(); + // if (!aitem || !bitem) + // return false; + // S32 a_sort = aitem->getSortField(); + // S32 b_sort = bitem->getSortField(); + // return a_sort < b_sort; + // } + //} // We sort by name if we aren't sorting by date // OR if these are folders and we are sorting folders by name. @@ -2877,7 +2585,7 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde if (by_name) { - S32 compare = LLStringUtil::compareDict(a->getLabel(), b->getLabel()); + S32 compare = LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()); if (0 == compare) { return (a->getCreationDate() > b->getCreationDate()); @@ -2889,13 +2597,11 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde } else { - // BUG: This is very very slow. The getCreationDate() is log n in number - // of inventory items. time_t first_create = a->getCreationDate(); time_t second_create = b->getCreationDate(); if (first_create == second_create) { - return (LLStringUtil::compareDict(a->getLabel(), b->getLabel()) < 0); + return (LLStringUtil::compareDict(a->getDisplayName(), b->getDisplayName()) < 0); } else { @@ -2903,3 +2609,4 @@ bool LLInventorySort::operator()(const LLFolderViewItem* const& a, const LLFolde } } } + diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 3c7592046a..9e024d7eea 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -30,51 +30,11 @@ #include "lldarray.h" // *TODO: Eliminate, forward declare #include "lluiimage.h" -class LLFontGL; class LLFolderView; -class LLFolderViewEventListener; +class LLFolderViewModelItem; class LLFolderViewFolder; class LLFolderViewFunctor; -class LLFolderViewItem; -class LLFolderViewListenerFunctor; -class LLInventoryFilter; -class LLMenuGL; -class LLUIImage; -class LLViewerInventoryItem; - -// These are grouping of inventory types. -// Order matters when sorting system folders to the top. -enum EInventorySortGroup -{ - SG_SYSTEM_FOLDER, - SG_TRASH_FOLDER, - SG_NORMAL_FOLDER, - SG_ITEM -}; - -// *TODO: do we really need one sort object per folder? -// can we just have one of these per LLFolderView ? -class LLInventorySort -{ -public: - LLInventorySort() - : mSortOrder(0), - mByDate(false), - mSystemToTop(false), - mFoldersByName(false) { } - - // Returns true if order has changed - bool updateSort(U32 order); - U32 getSort() { return mSortOrder; } - bool isByDate() { return mByDate; } - - bool operator()(const LLFolderViewItem* const& a, const LLFolderViewItem* const& b); -private: - U32 mSortOrder; - bool mByDate; - bool mSystemToTop; - bool mFoldersByName; -}; +class LLFolderViewFilter; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderViewItem @@ -91,19 +51,19 @@ public: struct Params : public LLInitParam::Block<Params, LLView::Params> { - Optional<LLUIImage*> icon; - Optional<LLUIImage*> icon_open; // used for folders - Optional<LLUIImage*> icon_overlay; // for links - Optional<LLFolderView*> root; - Mandatory<LLFolderViewEventListener*> listener; + Optional<LLUIImage*> icon, + icon_open, // used for folders + icon_overlay, // for links + folder_arrow_image, + selection_image; + Optional<LLFolderView*> root; + Mandatory<LLFolderViewModelItem*> listener; - Optional<LLUIImage*> folder_arrow_image; - Optional<S32> folder_indentation; // pixels - Optional<LLUIImage*> selection_image; - Optional<S32> item_height; // pixels - Optional<S32> item_top_pad; // pixels + Optional<S32> folder_indentation, // pixels + item_height, + item_top_pad; - Optional<S32> creation_date; //UTC seconds + Optional<time_t> creation_date; Params(); }; @@ -121,17 +81,14 @@ public: static const F32 FOLDER_CLOSE_TIME_CONSTANT; static const F32 FOLDER_OPEN_TIME_CONSTANT; - // Mostly for debugging printout purposes. const std::string& getSearchableLabel() { return mSearchableLabel; } - BOOL isLoading() const { return mIsLoading; } - private: BOOL mIsSelected; protected: friend class LLUICtrlFactory; - friend class LLFolderViewEventListener; + friend class LLFolderViewModelItem; LLFolderViewItem(const Params& p); @@ -139,9 +96,8 @@ protected: std::string mSearchableLabel; S32 mLabelWidth; bool mLabelWidthDirty; - time_t mCreationDate; LLFolderViewFolder* mParentFolder; - LLFolderViewEventListener* mListener; + LLFolderViewModelItem* mListener; BOOL mIsCurSelection; BOOL mSelectPending; LLFontGL::StyleFlags mLabelStyle; @@ -155,13 +111,11 @@ protected: S32 mItemHeight; BOOL mPassedFilter; S32 mLastFilterGeneration; - std::string::size_type mStringMatchOffset; + //TODO RN: create interface for string highlighting + //std::string::size_type mStringMatchOffset; F32 mControlLabelRotation; LLFolderView* mRoot; BOOL mDragAndDropTarget; - BOOL mIsLoading; - LLTimer mTimeSinceRequestStart; - bool mShowLoadStatus; bool mIsMouseOverTitle; // helper function to change the selection from the root. @@ -174,11 +128,11 @@ protected: static LLFontGL* getLabelFontForStyle(U8 style); - virtual void setCreationDate(time_t creation_date_utc) { mCreationDate = creation_date_utc; } - public: BOOL postBuild(); + virtual void openItem( void ); + // This function clears the currently selected item, and records // the specified selected item appropriately for display and use // in the UI. If open is TRUE, then folders are opened up along @@ -198,17 +152,15 @@ public: // addToFolder() returns TRUE if it succeeds. FALSE otherwise enum { ARRANGE = TRUE, DO_NOT_ARRANGE = FALSE }; - virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); - - virtual EInventorySortGroup getSortGroup() const; + virtual BOOL addToFolder(LLFolderViewFolder* folder); // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); virtual S32 getItemHeight(); - // applies filters to control visibility of inventory items - virtual void filter( LLInventoryFilter& filter); + // applies filters to control visibility of items + virtual void filter( LLFolderViewFilter& filter); // updates filter serial number and optionally propagated value up to root S32 getLastFilterGeneration() { return mLastFilterGeneration; } @@ -231,7 +183,7 @@ public: virtual void selectItem(); // gets multiple-element selection - virtual std::set<LLUUID> getSelectionList() const; + virtual std::set<LLFolderViewItem*> getSelectionList() const; // Returns true is this object and all of its children can be removed (deleted by user) virtual BOOL isRemovable(); @@ -252,15 +204,13 @@ public: BOOL hasVisibleChildren() { return mHasVisibleChildren; } - void setShowLoadStatus(bool status) { mShowLoadStatus = status; } - // Call through to the viewed object and return true if it can be // removed. Returns true if it's removed. //virtual BOOL removeRecursively(BOOL single_item); BOOL remove(); // Build an appropriate context menu for the item. Flags unused. - void buildContextMenu(LLMenuGL& menu, U32 flags); + void buildContextMenu(class LLMenuGL& menu, U32 flags); // This method returns the actual name of the thing being // viewed. This method will ask the viewed object itself. @@ -273,8 +223,6 @@ public: // contents possible before the entire view has been constructed. const std::string& getLabel() const { return mLabel; } - // Used for sorting, like getLabel() above. - virtual time_t getCreationDate() const { return mCreationDate; } LLFolderViewFolder* getParentFolder( void ) { return mParentFolder; } const LLFolderViewFolder* getParentFolder( void ) const { return mParentFolder; } @@ -282,22 +230,15 @@ public: LLFolderViewItem* getNextOpenNode( BOOL include_children = TRUE ); LLFolderViewItem* getPreviousOpenNode( BOOL include_children = TRUE ); - const LLFolderViewEventListener* getListener( void ) const { return mListener; } - LLFolderViewEventListener* getListener( void ) { return mListener; } - - // Gets the inventory item if it exists (null otherwise) - LLViewerInventoryItem * getInventoryItem(void); + const LLFolderViewModelItem* getViewModelItem( void ) const { return mListener; } + LLFolderViewModelItem* getViewModelItem( void ) { return mListener; } // just rename the object. void rename(const std::string& new_name); - // open - virtual void openItem( void ); - virtual void preview(void); // Show children (unfortunate that this is called "open") virtual void setOpen(BOOL open = TRUE) {}; - virtual BOOL isOpen() const { return FALSE; } virtual LLFolderView* getRoot(); @@ -315,11 +256,8 @@ public: void setIcon(LLUIImagePtr icon); // refresh information from the object being viewed. - void refreshFromListener(); virtual void refresh(); - virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor); - // LLView functionality virtual BOOL handleRightMouseDown( S32 x, S32 y, MASK mask ); virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); @@ -343,11 +281,6 @@ private: static std::map<U8, LLFontGL*> sFonts; // map of styles to fonts }; - -// function used for sorting. -typedef bool (*sort_order_f)(LLFolderViewItem* a, LLFolderViewItem* b); - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFolderViewFolder // @@ -363,10 +296,6 @@ protected: friend class LLUICtrlFactory; public: - typedef enum e_trash - { - UNKNOWN, TRASH, NOT_TRASH - } ETrash; typedef std::list<LLFolderViewItem*> items_t; typedef std::list<LLFolderViewFolder*> folders_t; @@ -374,15 +303,12 @@ public: protected: items_t mItems; folders_t mFolders; - LLInventorySort mSortFunction; BOOL mIsOpen; BOOL mExpanderHighlighted; F32 mCurHeight; F32 mTargetHeight; F32 mAutoOpenCountdown; - time_t mSubtreeCreationDate; - mutable ETrash mAmTrash; S32 mLastArrangeGeneration; S32 mLastCalculatedWidth; S32 mCompletedFilterGeneration; @@ -408,17 +334,13 @@ public: LLFolderViewItem* getPreviousFromChild( LLFolderViewItem*, BOOL include_children = TRUE ); // addToFolder() returns TRUE if it succeeds. FALSE otherwise - virtual BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); + virtual BOOL addToFolder(LLFolderViewFolder* folder); // Finds width and height of this object and it's children. Also // makes sure that this view and it's children are the right size. virtual S32 arrange( S32* width, S32* height, S32 filter_generation ); BOOL needsArrange(); - void requestSort(); - - // Returns the sort group (system, trash, folder) for this folder. - virtual EInventorySortGroup getSortGroup() const; virtual void setCompletedFilterGeneration(S32 generation, BOOL recurse_up); virtual S32 getCompletedFilterGeneration() { return mCompletedFilterGeneration; } @@ -426,8 +348,8 @@ public: BOOL hasFilteredDescendants(S32 filter_generation); BOOL hasFilteredDescendants(); - // applies filters to control visibility of inventory items - virtual void filter( LLInventoryFilter& filter); + // applies filters to control visibility of items + virtual void filter( LLFolderViewFilter& filter); virtual void setFiltered(BOOL filtered, S32 filter_generation); virtual BOOL getFiltered(); virtual BOOL getFiltered(S32 filter_generation); @@ -435,7 +357,7 @@ public: virtual void dirtyFilter(); // folder-specific filtering (filter status propagates top down instead of bottom up) - void filterFolder(LLInventoryFilter& filter); + void filterFolder(LLFolderViewFilter& filter); void setFilteredFolder(bool filtered, S32 filter_generation); bool getFilteredFolder(S32 filter_generation); @@ -479,15 +401,11 @@ public: // extractItem() removes the specified item from the folder, but // doesn't delete it. - void extractItem( LLFolderViewItem* item ); + virtual void extractItem( LLFolderViewItem* item ); // This function is called by a child that needs to be resorted. void resort(LLFolderViewItem* item); - void setItemSortOrder(U32 ordering); - void sortBy(U32); - //BOOL (*func)(LLFolderViewItem* a, LLFolderViewItem* b)); - void setAutoOpenCountdown(F32 countdown) { mAutoOpenCountdown = countdown; } // folders can be opened. This will usually be called by internal @@ -501,6 +419,8 @@ public: // don't rearrange child folder contents unless explicitly requested virtual void requestArrange(BOOL include_descendants = FALSE); + virtual void requestSort(); + // internal method which doesn't update the entire view. This // method was written because the list iterators destroy the state // of other iterations, thus, we can't arrange while iterating @@ -519,7 +439,6 @@ public: std::string& tooltip_msg); void applyFunctorRecursively(LLFolderViewFunctor& functor); - virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor); // Just apply this functor to the folder's immediate children. void applyFunctorToChildren(LLFolderViewFunctor& functor); @@ -545,32 +464,23 @@ public: std::string& tooltip_msg); virtual void draw(); - time_t getCreationDate() const; - bool isTrash() const; - folders_t::const_iterator getFoldersBegin() const { return mFolders.begin(); } - folders_t::const_iterator getFoldersEnd() const { return mFolders.end(); } + folders_t::iterator getFoldersBegin() { return mFolders.begin(); } + folders_t::iterator getFoldersEnd() { return mFolders.end(); } folders_t::size_type getFoldersCount() const { return mFolders.size(); } items_t::const_iterator getItemsBegin() const { return mItems.begin(); } items_t::const_iterator getItemsEnd() const { return mItems.end(); } items_t::size_type getItemsCount() const { return mItems.size(); } + LLFolderViewFolder* getCommonAncestor(LLFolderViewItem* item_a, LLFolderViewItem* item_b, bool& reverse); void gatherChildRangeExclusive(LLFolderViewItem* start, LLFolderViewItem* end, bool reverse, std::vector<LLFolderViewItem*>& items); -}; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewListenerFunctor -// -// This simple abstract base class can be used to applied to all -// listeners in a hierarchy. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -class LLFolderViewListenerFunctor -{ public: - virtual ~LLFolderViewListenerFunctor() {} - virtual void operator()(LLFolderViewEventListener* listener) = 0; + //WARNING: do not call directly...use the appropriate LLFolderViewModel-derived class instead + template<typename SORT_FUNC> void sortFolders(SORT_FUNC& func) { mFolders.sort(func); } + template<typename SORT_FUNC> void sortItems(SORT_FUNC& func) { mItems.sort(func); } }; + #endif // LLFOLDERVIEWITEM_H diff --git a/indra/newview/llfolderviewmodel.h b/indra/newview/llfolderviewmodel.h new file mode 100644 index 0000000000..9bbd7f48cf --- /dev/null +++ b/indra/newview/llfolderviewmodel.h @@ -0,0 +1,316 @@ +/** + * @file llfolderviewmodel.h + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#ifndef LLFOLDERVIEWEVENTLISTENER_H +#define LLFOLDERVIEWEVENTLISTENER_H + +#include "lldarray.h" // *TODO: convert to std::vector +#include "llfoldertype.h" +#include "llfontgl.h" // just for StyleFlags enum +#include "llfolderviewitem.h" +#include "llinventorytype.h" +#include "llpermissionsflags.h" +#include "llpointer.h" +#include "llwearabletype.h" +#include "lltooldraganddrop.h" + +// These are grouping of inventory types. +// Order matters when sorting system folders to the top. +enum EInventorySortGroup +{ + SG_SYSTEM_FOLDER, + SG_TRASH_FOLDER, + SG_NORMAL_FOLDER, + SG_ITEM +}; + +class LLFontGL; +class LLInventoryModel; +class LLMenuGL; +class LLUIImage; +class LLUUID; +class LLFolderViewItem; +class LLFolderViewFolder; + +class LLFolderViewFilter +{ +public: + enum EFilterModified + { + FILTER_NONE, // nothing to do, already filtered + FILTER_RESTART, // restart filtering from scratch + FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter + FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one + }; + +public: + + LLFolderViewFilter() {} + virtual ~LLFolderViewFilter() {} + + // +-------------------------------------------------------------------+ + // + Execution And Results + // +-------------------------------------------------------------------+ + virtual bool check(const LLFolderViewItem* item) = 0; + virtual bool check(const LLInventoryItem* item) = 0; + virtual bool checkFolder(const LLFolderViewFolder* folder) const = 0; + virtual bool checkFolder(const LLUUID& folder_id) const = 0; + + virtual void setEmptyLookupMessage(const std::string& message) = 0; + virtual std::string getEmptyLookupMessage() const = 0; + + virtual bool showAllResults() const = 0; + + // +-------------------------------------------------------------------+ + // + Status + // +-------------------------------------------------------------------+ + virtual bool isActive() const = 0; + virtual bool isModified() const = 0; + virtual void clearModified() = 0; + virtual const std::string& getName() const = 0; + virtual const std::string& getFilterText() = 0; + //RN: this is public to allow system to externally force a global refilter + virtual void setModified(EFilterModified behavior = FILTER_RESTART) = 0; + + // +-------------------------------------------------------------------+ + // + Count + // +-------------------------------------------------------------------+ + virtual void setFilterCount(S32 count) = 0; + virtual S32 getFilterCount() const = 0; + virtual void decrementFilterCount() = 0; + + // +-------------------------------------------------------------------+ + // + Default + // +-------------------------------------------------------------------+ + virtual bool isDefault() const = 0; + virtual bool isNotDefault() const = 0; + virtual void markDefault() = 0; + virtual void resetDefault() = 0; + + // +-------------------------------------------------------------------+ + // + Generation + // +-------------------------------------------------------------------+ + virtual S32 getCurrentGeneration() const = 0; + virtual S32 getFirstSuccessGeneration() const = 0; + virtual S32 getFirstRequiredGeneration() const = 0; +}; + +class LLFolderViewModelInterface +{ +public: + virtual void requestSortAll() = 0; + virtual void requestSort(class LLFolderViewFolder*) = 0; + + virtual void sort(class LLFolderViewFolder*) = 0; + virtual void filter(class LLFolderViewFolder*) = 0; + + virtual bool contentsReady() = 0; +}; + +struct LLFolderViewModelCommon : public LLFolderViewModelInterface +{ + LLFolderViewModelCommon() + : mTargetSortVersion(0) + {} + + virtual void requestSortAll() + { + // sort everything + mTargetSortVersion++; + } + + virtual void requestSort(class LLFolderViewFolder* folder) + { + folder->requestSort(); + } + +protected: + bool needsSort(class LLFolderViewModelItem* item); + + S32 mTargetSortVersion; +}; + +// This is am abstract base class that users of the folderview classes +// would use to bridge the folder view with the underlying data +class LLFolderViewModelItem +{ +public: + virtual ~LLFolderViewModelItem( void ) {}; + + virtual void update() {} //called when drawing + virtual const std::string& getName() const = 0; + virtual const std::string& getDisplayName() const = 0; + + virtual LLPointer<LLUIImage> getIcon() const = 0; + virtual LLPointer<LLUIImage> getOpenIcon() const { return getIcon(); } + + virtual LLFontGL::StyleFlags getLabelStyle() const = 0; + virtual std::string getLabelSuffix() const = 0; + + virtual void openItem( void ) = 0; + virtual void closeItem( void ) = 0; + virtual void selectItem(void) = 0; + + virtual BOOL isItemRenameable() const = 0; + virtual BOOL renameItem(const std::string& new_name) = 0; + + virtual BOOL isItemMovable( void ) const = 0; // Can be moved to another folder + virtual void move( LLFolderViewModelItem* parent_listener ) = 0; + + virtual BOOL isItemRemovable( void ) const = 0; // Can be destroyed + virtual BOOL removeItem() = 0; + virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch) = 0; + + virtual BOOL isItemCopyable() const = 0; + virtual BOOL copyToClipboard() const = 0; + virtual BOOL cutToClipboard() const = 0; + + virtual BOOL isClipboardPasteable() const = 0; + virtual void pasteFromClipboard() = 0; + virtual void pasteLinkFromClipboard() = 0; + + virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; + + // This method should be called when a drag begins. returns TRUE + // if the drag can begin, otherwise FALSE. + virtual LLToolDragAndDrop::ESource getDragSource() const = 0; + virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const = 0; + + virtual bool hasChildren() const = 0; + + // This method will be called to determine if a drop can be + // performed, and will set drop to TRUE if a drop is + // requested. Returns TRUE if a drop is possible/happened, + // otherwise FALSE. + virtual BOOL dragOrDrop(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + std::string& tooltip_msg) = 0; + + virtual void requestSort() = 0; + virtual S32 getSortVersion() = 0; + virtual void setSortVersion(S32 version) = 0; +}; + +class LLFolderViewModelItemCommon : public LLFolderViewModelItem +{ +public: + LLFolderViewModelItemCommon() + : mSortVersion(-1) + {} + + void requestSort() { mSortVersion = -1; } + S32 getSortVersion() { return mSortVersion; } + void setSortVersion(S32 version) { mSortVersion = version;} + +protected: + S32 mSortVersion; +}; + +template <typename SORT_TYPE, typename ITEM_TYPE, typename FOLDER_TYPE, typename FILTER_TYPE> +class LLFolderViewModel : public LLFolderViewModelCommon +{ +public: + LLFolderViewModel() {} + virtual ~LLFolderViewModel() {} + + typedef SORT_TYPE SortType; + typedef ITEM_TYPE ItemType; + typedef FOLDER_TYPE FolderType; + typedef FILTER_TYPE FilterType; + + virtual SortType& getSorter() { return mSorter; } + virtual const SortType& getSorter() const { return mSorter; } + virtual void setSorter(const SortType& sorter) { mSorter = sorter; requestSortAll(); } + virtual FilterType& getFilter() { return mFilter; } + virtual const FilterType& getFilter() const { return mFilter; } + virtual void setFilter(const FilterType& filter) { mFilter = filter; } + + virtual bool contentsReady() { return true; } + + struct ViewModelCompare + { + ViewModelCompare(const SortType& sorter) + : mSorter(sorter) + {} + + bool operator () (const LLFolderViewItem* a, const LLFolderViewItem* b) + { + return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); + } + + bool operator () (const LLFolderViewFolder* a, const LLFolderViewFolder* b) + { + return mSorter(static_cast<const ItemType*>(a->getViewModelItem()), static_cast<const ItemType*>(b->getViewModelItem())); + } + + const SortType& mSorter; + }; + + void sort(LLFolderViewFolder* folder) + { + if (needsSort(folder->getViewModelItem())) + { + folder->sortFolders(ViewModelCompare(getSorter())); + folder->sortItems(ViewModelCompare(getSorter())); + folder->getViewModelItem()->setSortVersion(mTargetSortVersion); + folder->requestArrange(); + } + } + + //TODO RN: fix this + void filter(LLFolderViewFolder* folder) + { + /*FilterType& filter = getFilter(); + for (std::list<LLFolderViewItem*>::const_iterator it = folder->getItemsBegin(), end_it = folder->getItemsEnd(); + it != end_it; + ++it) + { + LLFolderViewItem* child_item = *it; + child_item->setFiltered(filter.checkFolder(static_cast<ItemType*>(child_item->getViewModelItem())), filter.getCurrentGeneration()); + } + + for (std::list<LLFolderViewFolder*>::const_iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); + it != end_it; + ++it) + { + LLFolderViewItem* child_folder = *it; + child_folder->setFiltered(filter.check(static_cast<ItemType*>(child_folder->getViewModelItem())), filter.getCurrentGeneration()); + }*/ + } + +protected: + SortType mSorter; + FilterType mFilter; +}; + + +bool LLFolderViewModelCommon::needsSort(class LLFolderViewModelItem* item) +{ + return item->getSortVersion() < mTargetSortVersion; +} + + + +#endif diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index 11401d6c68..a64ddd185d 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -47,13 +47,13 @@ static const std::string INVENTORY_STRING_FRIENDS_ALL_SUBFOLDER = "All"; // helper functions // NOTE: For now Friends & All folders are created as protected folders of the LLFolderType::FT_CALLINGCARD type. -// So, their names will be processed in the LLFolderViewItem::refreshFromListener() to be localized +// So, their names will be processed in the LLFolderViewItem::refresh() to be localized // using "InvFolder LABEL_NAME" as LLTrans::findString argument. // We must use in this file their hard-coded names to ensure found them on different locales. EXT-5829. // These hard-coded names will be stored in InventoryItems but shown localized in FolderViewItems -// If hack in the LLFolderViewItem::refreshFromListener() to localize protected folder is removed +// If hack in the LLFolderViewItem::refresh() to localize protected folder is removed // or these folders are not protected these names should be localized in another place/way. inline const std::string get_friend_folder_name() { diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index b86c453d61..312b7314a1 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -115,10 +115,10 @@ void teleport_via_landmark(const LLUUID& asset_id); static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); static bool check_category(LLInventoryModel* model, const LLUUID& cat_id, - LLFolderView* active_folder_view, + LLInventoryPanel* active_panel, LLInventoryFilter* filter); static bool check_item(const LLUUID& item_id, - LLFolderView* active_folder_view, + LLInventoryPanel* active_panel, LLInventoryFilter* filter); // Helper functions @@ -208,7 +208,11 @@ const std::string& LLInvFVBridge::getName() const const std::string& LLInvFVBridge::getDisplayName() const { - return getName(); + if(mDisplayName.empty()) + { + buildDisplayName(); + } + return mDisplayName; } // Folders have full perms @@ -227,9 +231,24 @@ LLFolderType::EType LLInvFVBridge::getPreferredType() const // Folders don't have creation dates. time_t LLInvFVBridge::getCreationDate() const { - return 0; + LLInventoryObject* objectp = getInventoryObject(); + if (objectp) + { + return objectp->getCreationDate(); + } + return (time_t)0; } +void LLInvFVBridge::setCreationDate(time_t creation_date_utc) +{ + LLInventoryObject* objectp = getInventoryObject(); + if (objectp) + { + objectp->setCreationDate(creation_date_utc); + } +} + + // Can be destroyed (or moved to trash) BOOL LLInvFVBridge::isItemRemovable() const { @@ -283,7 +302,7 @@ void LLInvFVBridge::showProperties() */ } -void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) +void LLInvFVBridge::removeBatch(std::vector<LLFolderViewModelItem*>& batch) { // Deactivate gestures when moving them into Trash LLInvFVBridge* bridge; @@ -292,11 +311,11 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc LLViewerInventoryCategory* cat = NULL; LLInventoryModel::cat_array_t descendent_categories; LLInventoryModel::item_array_t descendent_items; - S32 count = batch.count(); + S32 count = batch.size(); S32 i,j; for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.get(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); if (item) @@ -309,7 +328,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc } for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.get(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); if (cat) @@ -327,7 +346,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc removeBatchNoCheck(batch); } -void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch) +void LLInvFVBridge::removeBatchNoCheck(std::vector<LLFolderViewModelItem*>& batch) { // this method moves a bunch of items and folders to the trash. As // per design guidelines for the inventory model, the message is @@ -343,14 +362,14 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener* uuid_vec_t move_ids; LLInventoryModel::update_map_t update; bool start_new_message = true; - S32 count = batch.count(); + S32 count = batch.size(); S32 i; // first, hide any 'preview' floaters that correspond to the items // being deleted. for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.get(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); if(item) @@ -363,7 +382,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener* for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.get(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); if(item) @@ -404,7 +423,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener* for(i = 0; i < count; ++i) { - bridge = (LLInvFVBridge*)(batch.get(i)); + bridge = (LLInvFVBridge*)(batch[i]); if(!bridge || !bridge->isItemRemovable()) continue; LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); if(cat) @@ -876,6 +895,12 @@ LLInventoryModel* LLInvFVBridge::getInventoryModel() const return panel ? panel->getModel() : NULL; } +LLInventoryFilter* getInventoryFilter() const +{ + LLInventoryPanel* panel = mInventoryPanel.get(); + return panel ? panel->getFilter() : NULL; +} + BOOL LLInvFVBridge::isItemInTrash() const { LLInventoryModel* model = getInventoryModel(); @@ -1250,7 +1275,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const if (can_list) { - LLFolderViewFolder * object_folderp = mRoot->getFolderByID(object_id); + LLFolderViewFolder * object_folderp = mInventoryPanel.get() ? mInventoryPanel.get()->getFolderByID(object_id) : NULL; if (object_folderp) { can_list = !object_folderp->isLoading(); @@ -1261,7 +1286,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const { // Get outbox id const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); - LLFolderViewItem * outbox_itemp = mRoot->getItemByID(outbox_id); + LLFolderViewItem * outbox_itemp = mInventoryPanel.get() ? mInventoryPanel.get()->getItemByID(outbox_id) : NULL; if (outbox_itemp) { @@ -1271,7 +1296,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const void * cargo_data = (void *) obj; std::string tooltip_msg; - can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); + can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); } } } @@ -1283,6 +1308,21 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const #endif } +LLToolDragAndDrop::ESource LLInvFVBridge::getDragSource() const +{ + if (gInventory.isObjectDescendentOf(getUUID(), gInventory.getRootFolderID())) + { + return LLToolDragAndDrop::SOURCE_AGENT; + } + else if (gInventory.isObjectDescendentOf(getUUID(), gInventory.getLibraryRootFolderID())) + { + return LLToolDragAndDrop::SOURCE_LIBRARY; + } + + return SOURCE_VIEWER; +} + + // +=================================================+ // | InventoryFVBridgeBuilder | @@ -1368,10 +1408,10 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) LLInventoryItem* itemp = model->getItem(mUUID); if (!itemp) return; - LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); + LLFolderViewItem* folder_view_itemp = mInventoryPanel.get()->getItemByID(itemp->getParentUUID()); if (!folder_view_itemp) return; - folder_view_itemp->getListener()->pasteFromClipboard(); + folder_view_itemp->getViewModelItem()->pasteFromClipboard(); return; } else if ("paste_link" == action) @@ -1380,10 +1420,10 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) LLInventoryItem* itemp = model->getItem(mUUID); if (!itemp) return; - LLFolderViewItem* folder_view_itemp = mRoot->getItemByID(itemp->getParentUUID()); + LLFolderViewItem* folder_view_itemp = mInventoryPanel.get()->getItemByID(itemp->getParentUUID()); if (!folder_view_itemp) return; - folder_view_itemp->getListener()->pasteLinkFromClipboard(); + folder_view_itemp->getViewModelItem()->pasteLinkFromClipboard(); return; } else if (isMarketplaceCopyAction(action)) @@ -1494,24 +1534,15 @@ PermissionMask LLItemBridge::getPermissionMask() const return perm_mask; } -const std::string& LLItemBridge::getDisplayName() const -{ - if(mDisplayName.empty()) - { - buildDisplayName(getItem(), mDisplayName); - } - return mDisplayName; -} - -void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) +void LLItemBridge::buildDisplayName() { - if(item) + if(getItem()) { - name.assign(item->getName()); + mDisplayName.assign(getItem()->getName()); } else { - name.assign(LLStringUtil::null); + mDisplayName.assign(LLStringUtil::null); } } @@ -1629,11 +1660,11 @@ BOOL LLItemBridge::renameItem(const std::string& new_name) { LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); new_item->rename(new_name); - buildDisplayName(new_item, mDisplayName); new_item->updateServer(FALSE); model->updateItem(new_item); model->notifyObservers(); + buildDisplayName(); } // return FALSE because we either notified observers (& therefore // rebuilt) or we didn't update. @@ -1786,6 +1817,88 @@ void LLFolderBridge::selectItem() LLInventoryModelBackgroundFetch::instance().start(getUUID(), true); } +void LLFolderBridge::buildDisplayName() +{ + LLFolderType::EType preferred_type = getPreferredType(); + + // *TODO: to be removed when database supports multi language. This is a + // temporary attempt to display the inventory folder in the user locale. + // mantipov: *NOTE: be sure this code is synchronized with LLFriendCardsManager::findChildFolderUUID + // it uses the same way to find localized string + + // HACK: EXT - 6028 ([HARD CODED]? Inventory > Library > "Accessories" folder) + // Translation of Accessories folder in Library inventory folder + bool accessories = false; + if(getName() == "Accessories") + { + //To ensure that Accessories folder is in Library we have to check its parent folder. + //Due to parent LLFolderViewFloder is not set to this item yet we have to check its parent via Inventory Model + LLInventoryCategory* cat = gInventory.getCategory(getUUID()); + if(cat) + { + const LLUUID& parent_folder_id = cat->getParentUUID(); + accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); + } + } + + //"Accessories" inventory category has folder type FT_NONE. So, this folder + //can not be detected as protected with LLFolderType::lookupIsProtectedType + if (accessories || LLFolderType::lookupIsProtectedType(preferred_type)) + { + LLTrans::findString(mDisplayName, "InvFolder " + getName()); + }; +} + + +void LLFolderBridge::update() +{ + bool possibly_has_children = false; + bool up_to_date = isUpToDate(); + if(!up_to_date && hasChildren()) // we know we have children but haven't fetched them (doesn't obey filter) + { + possibly_has_children = true; + } + + BOOL loading = (possibly_has_children + && !up_to_date ); + + if (loading != mIsLoading) + { + if ( loading && !mIsLoading ) + { + // Measure how long we've been in the loading state + mTimeSinceRequestStart.reset(); + } + + const BOOL in_inventory = gInventory.isObjectDescendentOf(getUUID(), gInventory.getRootFolderID()); + const BOOL in_library = gInventory.isObjectDescendentOf(getUUID(), gInventory.getLibraryRootFolderID()); + + bool root_is_loading = false; + if (in_inventory) + { + root_is_loading = LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress(); + } + if (in_library) + { + root_is_loading = LLInventoryModelBackgroundFetch::instance().libraryFetchInProgress(); + } + if ((mIsLoading + && mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) + || (LLInventoryModelBackgroundFetch::instance().folderFetchActive() + && root_is_loading)) + { + mDisplayName = LLInvFVBridge::getDisplayName() + " ( " + LLTrans::getString("LoadingData") + " ) "; + mIsLoading = true; + } + else + { + mDisplayName = LLInvFVBridge::getDisplayName(); + mIsLoading = false; + } + } +} + + // Iterate through a folder's children to determine if // all the children are removable. class LLIsItemRemovable : public LLFolderViewFunctor @@ -1794,11 +1907,11 @@ public: LLIsItemRemovable() : mPassed(TRUE) {} virtual void doFolder(LLFolderViewFolder* folder) { - mPassed &= folder->getListener()->isItemRemovable(); + mPassed &= folder->getViewModelItem()->isItemRemovable(); } virtual void doItem(LLFolderViewItem* item) { - mPassed &= item->getListener()->isItemRemovable(); + mPassed &= item->getViewModelItem()->isItemRemovable(); } BOOL mPassed; }; @@ -1812,7 +1925,7 @@ BOOL LLFolderBridge::isItemRemovable() const } LLInventoryPanel* panel = mInventoryPanel.get(); - LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL); + LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getItemByID(mUUID) : NULL); if (folderp) { LLIsItemRemovable folder_test; @@ -2051,7 +2164,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, LLInventoryPanel* destination_panel = mInventoryPanel.get(); if (!destination_panel) return false; - LLInventoryFilter* filter = destination_panel->getFilter(); + LLInventoryFilter* filter = getInventoryFilter(); if (!filter) return false; const LLUUID &cat_id = inv_cat->getUUID(); @@ -2270,7 +2383,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, { // Check whether the folder being dragged from active inventory panel // passes the filter of the destination panel. - is_movable = check_category(model, cat_id, active_folder_view, filter); + is_movable = check_category(model, cat_id, active_panel, filter); } } } @@ -2696,7 +2809,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) { if ("open" == action) { - LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder *>(mRoot->getItemByID(mUUID)); + LLFolderViewFolder *f = dynamic_cast<LLFolderViewFolder *>(mInventoryPanel.get()->getItemByID(mUUID)); if (f) { f->setOpen(TRUE); @@ -2971,7 +3084,7 @@ void LLFolderBridge::pasteFromClipboard() if (move_is_into_outbox) { - LLFolderViewItem * outbox_itemp = mRoot->getItemByID(mUUID); + LLFolderViewItem * outbox_itemp = mInventoryPanel.get()->getItemByID(mUUID); if (outbox_itemp) { @@ -2994,7 +3107,7 @@ void LLFolderBridge::pasteFromClipboard() void * cargo_data = (void *) item; std::string tooltip_msg; - can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); + can_list = outbox_itemp->getViewModelItem()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); } } @@ -3166,7 +3279,7 @@ BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInv return ((item_array.count() > 0) ? TRUE : FALSE ); } -void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) +void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items) { LLInventoryModel* model = getInventoryModel(); llassert(model != NULL); @@ -3177,30 +3290,30 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) if (lost_and_found_id == mUUID) { // This is the lost+found folder. - mItems.push_back(std::string("Empty Lost And Found")); + items.push_back(std::string("Empty Lost And Found")); - mDisabledItems.push_back(std::string("New Folder")); - mDisabledItems.push_back(std::string("New Script")); - mDisabledItems.push_back(std::string("New Note")); - mDisabledItems.push_back(std::string("New Gesture")); - mDisabledItems.push_back(std::string("New Clothes")); - mDisabledItems.push_back(std::string("New Body Parts")); + disabled_items.push_back(std::string("New Folder")); + disabled_items.push_back(std::string("New Script")); + disabled_items.push_back(std::string("New Note")); + disabled_items.push_back(std::string("New Gesture")); + disabled_items.push_back(std::string("New Clothes")); + disabled_items.push_back(std::string("New Body Parts")); } if(trash_id == mUUID) { // This is the trash. - mItems.push_back(std::string("Empty Trash")); + items.push_back(std::string("Empty Trash")); } else if(isItemInTrash()) { // This is a folder in the trash. - mItems.clear(); // clear any items that used to exist - addTrashContextMenuOptions(mItems, mDisabledItems); + items.clear(); // clear any items that used to exist + addTrashContextMenuOptions(items, disabled_items); } else if(isOutboxFolder()) { - addOutboxContextMenuOptions(flags, mItems, mDisabledItems); + addOutboxContextMenuOptions(flags, items, disabled_items); } else if(isAgentInventory()) // do not allow creating in library { @@ -3214,40 +3327,40 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) { - mItems.push_back(std::string("New Folder")); + items.push_back(std::string("New Folder")); } - mItems.push_back(std::string("New Script")); - mItems.push_back(std::string("New Note")); - mItems.push_back(std::string("New Gesture")); - mItems.push_back(std::string("New Clothes")); - mItems.push_back(std::string("New Body Parts")); + items.push_back(std::string("New Script")); + items.push_back(std::string("New Note")); + items.push_back(std::string("New Gesture")); + items.push_back(std::string("New Clothes")); + items.push_back(std::string("New Body Parts")); } #if SUPPORT_ENSEMBLES // Changing folder types is an unfinished unsupported feature // and can lead to unexpected behavior if enabled. - mItems.push_back(std::string("Change Type")); + items.push_back(std::string("Change Type")); const LLViewerInventoryCategory *cat = getCategory(); if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) { - mDisabledItems.push_back(std::string("Change Type")); + disabled_items.push_back(std::string("Change Type")); } #endif - getClipboardEntries(false, mItems, mDisabledItems, flags); + getClipboardEntries(false, items, disabled_items, flags); } else { // Want some but not all of the items from getClipboardEntries for outfits. if (cat && (cat->getPreferredType() == LLFolderType::FT_OUTFIT)) { - mItems.push_back(std::string("Rename")); + items.push_back(std::string("Rename")); - addDeleteContextMenuOptions(mItems, mDisabledItems); + addDeleteContextMenuOptions(items, disabled_items); // EXT-4030: disallow deletion of currently worn outfit const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory())) { - mDisabledItems.push_back(std::string("Delete")); + disabled_items.push_back(std::string("Delete")); } } } @@ -3276,20 +3389,44 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags) // Preemptively disable system folder removal if more than one item selected. if ((flags & FIRST_SELECTED_ITEM) == 0) { - mDisabledItems.push_back(std::string("Delete System Folder")); + disabled_items.push_back(std::string("Delete System Folder")); } if (!isOutboxFolder()) { - mItems.push_back(std::string("Share")); + items.push_back(std::string("Share")); if (!canShare()) { - mDisabledItems.push_back(std::string("Share")); + disabled_items.push_back(std::string("Share")); + } + } + // Add menu items that are dependent on the contents of the folder. + LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID); + if (category) + { + uuid_vec_t folders; + folders.push_back(category->getUUID()); + + sSelf = getHandle(); + LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders); + fetch->startFetch(); + if (fetch->isFinished()) + { + // Do not call execute() or done() here as if the folder is here, there's likely no point drilling down + // This saves lots of time as buildContextMenu() is called a lot + delete fetch; + buildContextMenuFolderOptions(flags); + } + else + { + // it's all on its way - add an observer, and the inventory will call done for us when everything is here. + inc_busy_count(); + gInventory.addObserver(fetch); } } } -void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) +void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items) { // Build folder specific options back up LLInventoryModel* model = getInventoryModel(); @@ -3316,21 +3453,21 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) { - mItems.push_back(std::string("Calling Card Separator")); - mItems.push_back(std::string("Conference Chat Folder")); - mItems.push_back(std::string("IM All Contacts In Folder")); + items.push_back(std::string("Calling Card Separator")); + items.push_back(std::string("Conference Chat Folder")); + items.push_back(std::string("IM All Contacts In Folder")); } } if (!isItemRemovable()) { - mDisabledItems.push_back(std::string("Delete")); + disabled_items.push_back(std::string("Delete")); } #ifndef LL_RELEASE_FOR_DOWNLOAD if (LLFolderType::lookupIsProtectedType(type)) { - mItems.push_back(std::string("Delete System Folder")); + items.push_back(std::string("Delete System Folder")); } #endif @@ -3345,7 +3482,7 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) checkFolderForContentsOfType(model, is_object) || checkFolderForContentsOfType(model, is_gesture) ) { - mItems.push_back(std::string("Folder Wearables Separator")); + items.push_back(std::string("Folder Wearables Separator")); // Only enable add/replace outfit for non-system folders. if (!is_system_folder) @@ -3353,25 +3490,25 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) // Adding an outfit onto another (versus replacing) doesn't make sense. if (type != LLFolderType::FT_OUTFIT) { - mItems.push_back(std::string("Add To Outfit")); + items.push_back(std::string("Add To Outfit")); } - mItems.push_back(std::string("Replace Outfit")); + items.push_back(std::string("Replace Outfit")); } if (is_ensemble) { - mItems.push_back(std::string("Wear As Ensemble")); + items.push_back(std::string("Wear As Ensemble")); } - mItems.push_back(std::string("Remove From Outfit")); + items.push_back(std::string("Remove From Outfit")); if (!LLAppearanceMgr::getCanRemoveFromCOF(mUUID)) { - mDisabledItems.push_back(std::string("Remove From Outfit")); + disabled_items.push_back(std::string("Remove From Outfit")); } if (!LLAppearanceMgr::instance().getCanReplaceCOF(mUUID)) { - mDisabledItems.push_back(std::string("Replace Outfit")); + disabled_items.push_back(std::string("Replace Outfit")); } - mItems.push_back(std::string("Outfit Separator")); + items.push_back(std::string("Outfit Separator")); } } @@ -3380,49 +3517,28 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { sSelf.markDead(); - mItems.clear(); - mDisabledItems.clear(); + // fetch contents of this folder, as context menu can depend on contents + // still, user would have to open context menu again to see the changes + gInventory.fetchDescendentsOf(getUUID()); + + + menuentry_vec_t items; + menuentry_vec_t disabled_items; lldebugs << "LLFolderBridge::buildContextMenu()" << llendl; LLInventoryModel* model = getInventoryModel(); if(!model) return; - buildContextMenuBaseOptions(flags); - - // Add menu items that are dependent on the contents of the folder. - LLViewerInventoryCategory* category = (LLViewerInventoryCategory *) model->getCategory(mUUID); - if (category) - { - uuid_vec_t folders; - folders.push_back(category->getUUID()); - - sSelf = getHandle(); - LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(folders); - fetch->startFetch(); - if (fetch->isFinished()) - { - // Do not call execute() or done() here as if the folder is here, there's likely no point drilling down - // This saves lots of time as buildContextMenu() is called a lot - delete fetch; - buildContextMenuFolderOptions(flags); - } - else - { - // it's all on its way - add an observer, and the inventory will call done for us when everything is here. - inc_busy_count(); - gInventory.addObserver(fetch); - } - } - - hide_context_entries(menu, mItems, mDisabledItems); + buildContextMenuOptions(flags, items, disabled_items); + hide_context_entries(menu, items, disabled_items); // Reposition the menu, in case we're adding items to an existing menu. menu.needsArrange(); menu.arrangeAndClear(); } -BOOL LLFolderBridge::hasChildren() const +bool LLFolderBridge::hasChildren() const { LLInventoryModel* model = getInventoryModel(); if(!model) return FALSE; @@ -3516,9 +3632,7 @@ void LLFolderBridge::createNewCategory(void* user_data) { LLFolderBridge* bridge = (LLFolderBridge*)user_data; if(!bridge) return; - LLInventoryPanel* panel = bridge->mInventoryPanel.get(); - if (!panel) return; - LLInventoryModel* model = panel->getModel(); + LLInventoryModel* model = bridge->getInventoryModel(); if(!model) return; LLUUID id; id = model->createNewCategory(bridge->getUUID(), @@ -3596,6 +3710,24 @@ void LLFolderBridge::createNewEyes(void* user_data) LLFolderBridge::createWearable((LLFolderBridge*)user_data, LLWearableType::WT_EYES); } +EInventorySortGroup LLFolderBridge::getSortGroup() const +{ + LLFolderType::EType preferred_type = getPreferredType(); + + if (preferred_type == LLFolderType::FT_TRASH) + { + return SG_TRASH_FOLDER; + } + + if(LLFolderType::lookupIsProtectedType(preferred_type)) + { + return SG_SYSTEM_FOLDER; + } + + return SG_NORMAL_FOLDER; +} + + // static void LLFolderBridge::createWearable(LLFolderBridge* bridge, LLWearableType::EType type) { @@ -3698,9 +3830,9 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item) LLPointer<AddFavoriteLandmarkCallback> cb = new AddFavoriteLandmarkCallback(); LLInventoryPanel* panel = mInventoryPanel.get(); LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; - if (drag_over_item && drag_over_item->getListener()) + if (drag_over_item && drag_over_item->getViewModelItem()) { - cb.get()->setTargetLandmarkId(drag_over_item->getListener()->getUUID()); + cb.get()->setTargetLandmarkId(drag_over_item->getViewModelItem()->getUUID()); } copy_inventory_item( @@ -3749,7 +3881,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLInventoryPanel* destination_panel = mInventoryPanel.get(); if (!destination_panel) return false; - LLInventoryFilter* filter = destination_panel->getFilter(); + LLInventoryFilter* filter = getInventoryFilter(); if (!filter) return false; const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); @@ -3866,10 +3998,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // passes the filter of the destination panel. if (accept && active_panel) { - LLFolderView* active_folder_view = active_panel->getRootFolder(); - if (!active_folder_view) return false; - - LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID()); + LLFolderViewItem* fv_item = active_panel->getItemByID(inv_item->getUUID()); if (!fv_item) return false; accept = filter->check(fv_item); @@ -3884,6 +4013,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, } // 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 && (destination_panel != active_panel)) { active_panel->unSelectAll(); @@ -3901,7 +4032,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, if (itemp) { LLUUID srcItemId = inv_item->getUUID(); - LLUUID destItemId = itemp->getListener()->getUUID(); + LLUUID destItemId = itemp->getViewModelItem()->getUUID(); gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); } } @@ -4089,10 +4220,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // passes the filter of the destination panel. if (accept && active_panel) { - LLFolderView* active_folder_view = active_panel->getRootFolder(); - if (!active_folder_view) return false; - - LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID()); + LLFolderViewItem* fv_item = active_panel->getItemByID(inv_item->getUUID()); if (!fv_item) return false; accept = filter->check(fv_item); @@ -4135,10 +4263,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // static bool check_category(LLInventoryModel* model, const LLUUID& cat_id, - LLFolderView* active_folder_view, + LLInventoryPanel* active_panel, LLInventoryFilter* filter) { - if (!model || !active_folder_view || !filter) + if (!model || !active_panel || !filter) return false; if (!filter->checkFolder(cat_id)) @@ -4158,13 +4286,13 @@ bool check_category(LLInventoryModel* model, // Empty folder should be checked as any other folder view item. // If we are filtering by date the folder should not pass because // it doesn't have its own creation date. See LLInvFVBridge::getCreationDate(). - return check_item(cat_id, active_folder_view, filter); + return check_item(cat_id, active_panel, filter); } for (S32 i = 0; i < num_descendent_categories; ++i) { LLInventoryCategory* category = descendent_categories[i]; - if(!check_category(model, category->getUUID(), active_folder_view, filter)) + if(!check_category(model, category->getUUID(), active_panel, filter)) { return false; } @@ -4173,7 +4301,7 @@ bool check_category(LLInventoryModel* model, for (S32 i = 0; i < num_descendent_items; ++i) { LLViewerInventoryItem* item = descendent_items[i]; - if(!check_item(item->getUUID(), active_folder_view, filter)) + if(!check_item(item->getUUID(), active_panel, filter)) { return false; } @@ -4184,12 +4312,12 @@ bool check_category(LLInventoryModel* model, // static bool check_item(const LLUUID& item_id, - LLFolderView* active_folder_view, + LLInventoryPanel* active_panel, LLInventoryFilter* filter) { - if (!active_folder_view || !filter) return false; + if (!active_panel || !filter) return false; - LLFolderViewItem* fv_item = active_folder_view->getItemByID(item_id); + LLFolderViewItem* fv_item = active_panel->getItemByID(item_id); if (!fv_item) return false; return filter->check(fv_item); @@ -4294,15 +4422,6 @@ void LLSoundBridge::openItem() } } -void LLSoundBridge::previewItem() -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - send_sound_trigger(item->getAssetUUID(), 1.0); - } -} - void LLSoundBridge::openSoundPreview(void* which) { LLSoundBridge *me = (LLSoundBridge *)which; @@ -4518,7 +4637,7 @@ LLCallingCardBridge::~LLCallingCardBridge() void LLCallingCardBridge::refreshFolderViewItem() { LLInventoryPanel* panel = mInventoryPanel.get(); - LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL; + LLFolderViewItem* itemp = panel ? panel->getItemByID(mUUID) : NULL; if (itemp) { itemp->refresh(); @@ -5309,11 +5428,10 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name) { LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); new_item->rename(new_name); - buildDisplayName(new_item, mDisplayName); new_item->updateServer(FALSE); model->updateItem(new_item); - model->notifyObservers(); + buildDisplayName(); if (isAgentAvatarValid()) { @@ -5913,16 +6031,6 @@ void LLMeshBridge::openItem() } } -void LLMeshBridge::previewItem() -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - // preview mesh - } -} - - void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { lldebugs << "LLMeshBridge::buildContextMenu()" << llendl; @@ -6011,7 +6119,8 @@ void LLLinkFolderBridge::gotoItem() const LLUUID &cat_uuid = getFolderID(); if (!cat_uuid.isNull()) { - if (LLFolderViewItem *base_folder = mRoot->getItemByID(cat_uuid)) + LLFolderViewItem *base_folder = mInventoryPanel.get()->getItemByID(cat_uuid) + if (base_folder) { if (LLInventoryModel* model = getInventoryModel()) { @@ -6349,9 +6458,8 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_ /************************************************************************/ void LLRecentItemsFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { - LLFolderBridge::buildContextMenu(menu, flags); - - menuentry_vec_t disabled_items, items = getMenuItems(); + menuentry_vec_t disabled_items, items; + buildContextMenuOptions(flags, items, disabled_items); items.erase(std::remove(items.begin(), items.end(), std::string("New Folder")), items.end()); @@ -6400,5 +6508,4 @@ LLInvFVBridge* LLRecentInventoryBridgeBuilder::createBridge( } - // EOF diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index dc9e88d54d..bc5ac24c70 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -29,9 +29,10 @@ #include "llcallingcard.h" #include "llfloaterproperties.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" #include "llinventorymodel.h" #include "llinventoryobserver.h" +#include "llinventorypanel.h" #include "llviewercontrol.h" #include "llwearable.h" @@ -41,7 +42,7 @@ class LLInventoryModel; class LLMenuGL; class LLCallingCardObserver; class LLViewerJointAttachment; - +class LLFolderView; typedef std::vector<std::string> menuentry_vec_t; @@ -56,7 +57,7 @@ typedef std::vector<std::string> menuentry_vec_t; // functionality a bit. (except for folders, you can create those // manually...) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInvFVBridge : public LLFolderViewEventListener +class LLInvFVBridge : public LLFolderViewModelItemInventory { public: // This method is a convenience function which creates the correct @@ -83,18 +84,18 @@ public: virtual void restoreToWorld() {} //-------------------------------------------------------------------- - // Inherited LLFolderViewEventListener functions + // Inherited LLFolderViewModelItemInventory functions //-------------------------------------------------------------------- virtual const std::string& getName() const; virtual const std::string& getDisplayName() const; virtual PermissionMask getPermissionMask() const; virtual LLFolderType::EType getPreferredType() const; virtual time_t getCreationDate() const; + virtual void setCreationDate(time_t creation_date_utc); virtual LLFontGL::StyleFlags getLabelStyle() const { return LLFontGL::NORMAL; } virtual std::string getLabelSuffix() const { return LLStringUtil::null; } virtual void openItem() {} virtual void closeItem() {} - virtual void previewItem() {openItem();} virtual void showProperties(); virtual BOOL isItemRenameable() const { return TRUE; } //virtual BOOL renameItem(const std::string& new_name) {} @@ -103,8 +104,8 @@ public: virtual BOOL isItemInTrash() const; virtual BOOL isLink() const; //virtual BOOL removeItem() = 0; - virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch); - virtual void move(LLFolderViewEventListener* new_parent_bridge) {} + virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch); + virtual void move(LLFolderViewModelItem* new_parent_bridge) {} virtual BOOL isItemCopyable() const { return FALSE; } virtual BOOL copyToClipboard() const; virtual BOOL cutToClipboard() const; @@ -115,6 +116,7 @@ public: void getClipboardEntries(bool show_asset_id, menuentry_vec_t &items, menuentry_vec_t &disabled_items, U32 flags); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); + virtual LLToolDragAndDrop::ESource getDragSource() const; virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, @@ -122,6 +124,9 @@ public: std::string& tooltip_msg) { return FALSE; } virtual LLInventoryType::EType getInventoryType() const { return mInvType; } virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } + EInventorySortGroup getSortGroup() const { return SG_ITEM; } + virtual LLInventoryObject* getInventoryObject() const; + //-------------------------------------------------------------------- // Convenience functions for adding various common menu options. @@ -138,16 +143,16 @@ protected: protected: LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid); - LLInventoryObject* getInventoryObject() const; LLInventoryModel* getInventoryModel() const; + LLInventoryFilter* getInventoryFilter() const; BOOL isLinkedObjectInTrash() const; // Is this obj or its baseobj in the trash? BOOL isLinkedObjectMissing() const; // Is this a linked obj whose baseobj is not in inventory? BOOL isAgentInventory() const; // false if lost or in the inventory library - BOOL isCOFFolder() const; // true if COF or descendent of - BOOL isInboxFolder() const; // true if COF or descendent of marketplace inbox - BOOL isOutboxFolder() const; // true if COF or descendent of marketplace outbox + BOOL isCOFFolder() const; // true if COF or descendant of + BOOL isInboxFolder() const; // true if COF or descendant of marketplace inbox + BOOL isOutboxFolder() const; // true if COF or descendant of marketplace outbox BOOL isOutboxFolderDirectParent() const; const LLUUID getOutboxFolder() const; @@ -160,14 +165,18 @@ protected: LLViewerInventoryCategory* item, const LLUUID& new_parent, BOOL restamp); - void removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch); + void removeBatchNoCheck(std::vector<LLFolderViewModelItem*>& batch); protected: - LLHandle<LLInventoryPanel> mInventoryPanel; - LLFolderView* mRoot; - const LLUUID mUUID; // item id - LLInventoryType::EType mInvType; - BOOL mIsLink; + LLHandle<LLInventoryPanel> mInventoryPanel; + LLFolderView* mRoot; + const LLUUID mUUID; // item id + LLInventoryType::EType mInvType; + bool mIsLink; + LLTimer mTimeSinceRequestStart; + mutable std::string mDisplayName; + void purgeItem(LLInventoryModel *model, const LLUUID &uuid); + virtual void buildDisplayName(); }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -203,7 +212,6 @@ public: virtual void restoreToWorld(); virtual void gotoItem(); virtual LLUIImagePtr getIcon() const; - virtual const std::string& getDisplayName() const; virtual std::string getLabelSuffix() const; virtual LLFontGL::StyleFlags getLabelStyle() const; virtual PermissionMask getPermissionMask() const; @@ -212,7 +220,7 @@ public: virtual BOOL renameItem(const std::string& new_name); virtual BOOL removeItem(); virtual BOOL isItemCopyable() const; - virtual BOOL hasChildren() const { return FALSE; } + virtual bool hasChildren() const { return FALSE; } virtual BOOL isUpToDate() const { return TRUE; } /*virtual*/ void clearDisplayName() { mDisplayName.clear(); } @@ -222,9 +230,8 @@ public: protected: BOOL confirmRemoveItem(const LLSD& notification, const LLSD& response); virtual BOOL isItemPermissive() const; - static void buildDisplayName(LLInventoryItem* item, std::string& name); + virtual void buildDisplayName(); - mutable std::string mDisplayName; }; class LLFolderBridge : public LLInvFVBridge @@ -232,15 +239,18 @@ class LLFolderBridge : public LLInvFVBridge public: LLFolderBridge(LLInventoryPanel* inventory, LLFolderView* root, - const LLUUID& uuid) : - LLInvFVBridge(inventory, root, uuid), + const LLUUID& uuid) + : LLInvFVBridge(inventory, root, uuid), mCallingCards(FALSE), - mWearables(FALSE) + mWearables(FALSE), + mIsLoading(false) {} BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg); BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg); + virtual void buildDisplayName(); + virtual void performAction(LLInventoryModel* model, std::string action); virtual void openItem(); virtual void closeItem(); @@ -262,7 +272,7 @@ public: virtual void pasteFromClipboard(); virtual void pasteLinkFromClipboard(); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); - virtual BOOL hasChildren() const; + virtual bool hasChildren() const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, @@ -275,14 +285,17 @@ public: virtual BOOL isClipboardPasteable() const; virtual BOOL isClipboardPasteableAsLink() const; + EInventorySortGroup getSortGroup() const; + virtual void update(); + static void createWearable(LLFolderBridge* bridge, LLWearableType::EType type); LLViewerInventoryCategory* getCategory() const; LLHandle<LLFolderBridge> getHandle() { mHandle.bind(this); return mHandle; } protected: - void buildContextMenuBaseOptions(U32 flags); - void buildContextMenuFolderOptions(U32 flags); + void buildContextMenuOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items); + void buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items); //-------------------------------------------------------------------- // Menu callbacks @@ -308,8 +321,6 @@ protected: void modifyOutfit(BOOL append); void determineFolderType(); - menuentry_vec_t getMenuItems() { return mItems; } // returns a copy of current menu items - void dropToFavorites(LLInventoryItem* inv_item); void dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); @@ -321,10 +332,12 @@ public: static void staticFolderOptionsMenu(); private: - BOOL mCallingCards; - BOOL mWearables; - menuentry_vec_t mItems; - menuentry_vec_t mDisabledItems; + + bool mCallingCards; + bool mWearables; + bool mIsLoading; + LLTimer mTimeSinceRequestStart; + std::string mDisplayName; LLRootHandle<LLFolderBridge> mHandle; }; @@ -354,7 +367,6 @@ public: const LLUUID& uuid) : LLItemBridge(inventory, root, uuid) {} virtual void openItem(); - virtual void previewItem(); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); static void openSoundPreview(void*); }; @@ -544,7 +556,6 @@ class LLMeshBridge : public LLItemBridge public: virtual LLUIImagePtr getIcon() const; virtual void openItem(); - virtual void previewItem(); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); protected: diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 4d0af94f9f..9c9b04d03d 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -29,7 +29,7 @@ #include "llinventoryfilter.h" // viewer includes -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" #include "llfolderviewitem.h" #include "llinventorymodel.h" #include "llinventorymodelbackgroundfetch.h" @@ -42,57 +42,49 @@ #include "llclipboard.h" #include "lltrans.h" +//TODO RN: fix use of static cast as much as possible + LLFastTimer::DeclareTimer FT_FILTER_CLIPBOARD("Filter Clipboard"); -LLInventoryFilter::FilterOps::FilterOps() : - mFilterObjectTypes(0xffffffffffffffffULL), - mFilterCategoryTypes(0xffffffffffffffffULL), - mFilterWearableTypes(0xffffffffffffffffULL), - mMinDate(time_min()), - mMaxDate(time_max()), - mHoursAgo(0), - mShowFolderState(SHOW_NON_EMPTY_FOLDERS), - mPermissions(PERM_NONE), - mFilterTypes(FILTERTYPE_OBJECT), - mFilterUUID(LLUUID::null), - mFilterLinks(FILTERLINK_INCLUDE_LINKS) +LLInventoryFilter::FilterOps::FilterOps(const Params& p) +: mFilterObjectTypes(p.object_types), + mFilterCategoryTypes(p.category_types), + mFilterWearableTypes(p.wearable_types), + mMinDate(p.date_range.min_date), + mMaxDate(p.date_range.max_date), + mHoursAgo(p.hours_ago), + mShowFolderState(p.show_folder_state), + mPermissions(p.permissions), + mFilterTypes(p.types), + mFilterUUID(p.uuid), + mFilterLinks(p.links) { } ///---------------------------------------------------------------------------- /// Class LLInventoryFilter ///---------------------------------------------------------------------------- -LLInventoryFilter::LLInventoryFilter(const std::string& name) -: mName(name), - mModified(FALSE), - mNeedTextRebuild(TRUE), - mEmptyLookupMessage("InventoryNoMatchingItems") +LLInventoryFilter::LLInventoryFilter(const Params& p) +: mFilterModified(FILTER_NONE), + mEmptyLookupMessage("InventoryNoMatchingItems"), + mFilterOps(p.filter_ops), + mOrder(p.sort_order), + mFilterSubString(p.substring), + mLastSuccessGeneration(0), + mLastFailGeneration(S32_MAX), + mFirstSuccessGeneration(0), + mFilterCount(0) { - mOrder = SO_FOLDERS_BY_NAME; // This gets overridden by a pref immediately - - mSubStringMatchOffset = 0; - mFilterSubString.clear(); - mFilterGeneration = 0; - mMustPassGeneration = S32_MAX; - mMinRequiredGeneration = 0; - mFilterCount = 0; - mNextFilterGeneration = mFilterGeneration + 1; - - mLastLogoff = gSavedPerAccountSettings.getU32("LastLogoff"); - mFilterBehavior = FILTER_NONE; + mNextFilterGeneration = mLastSuccessGeneration + 1; // copy mFilterOps into mDefaultFilterOps markDefault(); } -LLInventoryFilter::~LLInventoryFilter() -{ -} - -BOOL LLInventoryFilter::check(const LLFolderViewItem* item) +bool LLInventoryFilter::check(const LLFolderViewItem* item) { // Clipboard cut items are *always* filtered so we need this value upfront - const LLFolderViewEventListener* listener = item->getListener(); + const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE); // If it's a folder and we're showing all folders, return automatically. @@ -102,7 +94,7 @@ BOOL LLInventoryFilter::check(const LLFolderViewItem* item) return passed_clipboard; } - mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; + std::string::size_type string_offset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos; const BOOL passed_filtertype = checkAgainstFilterType(item); const BOOL passed_permissions = checkAgainstPermissions(item); @@ -111,22 +103,22 @@ BOOL LLInventoryFilter::check(const LLFolderViewItem* item) passed_permissions && passed_filterlink && passed_clipboard && - (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); + (mFilterSubString.size() == 0 || string_offset != std::string::npos)); return passed; } bool LLInventoryFilter::check(const LLInventoryItem* item) { - mSubStringMatchOffset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; + std::string::size_type string_offset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; const bool passed_filtertype = checkAgainstFilterType(item); const bool passed_permissions = checkAgainstPermissions(item); const BOOL passed_clipboard = checkAgainstClipboard(item->getUUID()); - const bool passed = (passed_filtertype && - passed_permissions && - passed_clipboard && - (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); + const bool passed = (passed_filtertype + && passed_permissions + && passed_clipboard + && (mFilterSubString.size() == 0 || string_offset != std::string::npos)); return passed; } @@ -140,7 +132,7 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const return false; } - const LLFolderViewEventListener* listener = folder->getListener(); + const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(folder->getViewModelItem()); if (!listener) { llwarns << "Folder view event listener not found." << llendl; @@ -155,6 +147,13 @@ bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const { + // when applying a filter, matching folders get their contents downloaded first + if (isNotDefault() + && !gInventory.isCategoryComplete(folder_id)) + { + LLInventoryModelBackgroundFetch::instance().start(folder_id); + } + // Always check against the clipboard const BOOL passed_clipboard = checkAgainstClipboard(folder_id); @@ -163,7 +162,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const { return passed_clipboard; } - + if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY) { // Can only filter categories for items in your inventory @@ -179,9 +178,9 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const return passed_clipboard; } -BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const { - const LLFolderViewEventListener* listener = item->getListener(); + const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); if (!listener) return FALSE; LLInventoryType::EType object_type = listener->getInventoryType(); @@ -268,7 +267,7 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con } } } - + return TRUE; } @@ -347,13 +346,13 @@ bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const return true; } -BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const { - const LLFolderViewEventListener* listener = item->getListener(); + const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); if (!listener) return FALSE; PermissionMask perm = listener->getPermissionMask(); - const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(item->getListener()); + const LLInvFVBridge *bridge = dynamic_cast<const LLInvFVBridge *>(item->getViewModelItem()); if (bridge && bridge->isLink()) { const LLUUID& linked_uuid = gInventory.getLinkedItemID(bridge->getUUID()); @@ -375,9 +374,9 @@ bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) con return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions; } -BOOL LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const +bool LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const { - const LLFolderViewEventListener* listener = item->getListener(); + const LLFolderViewModelItemInventory* listener = static_cast<const LLFolderViewModelItemInventory*>(item->getViewModelItem()); if (!listener) return TRUE; const LLUUID object_id = listener->getUUID(); @@ -397,20 +396,20 @@ const std::string& LLInventoryFilter::getFilterSubString(BOOL trim) const return mFilterSubString; } -std::string::size_type LLInventoryFilter::getStringMatchOffset() const +std::string::size_type LLInventoryFilter::getStringMatchOffset(LLFolderViewItem* item) const { - return mSubStringMatchOffset; + return mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; } -BOOL LLInventoryFilter::isDefault() const +bool LLInventoryFilter::isDefault() const { return !isNotDefault(); } // has user modified default filter params? -BOOL LLInventoryFilter::isNotDefault() const +bool LLInventoryFilter::isNotDefault() const { - BOOL not_default = FALSE; + S32 not_default = 0; not_default |= (mFilterOps.mFilterObjectTypes != mDefaultFilterOps.mFilterObjectTypes); not_default |= (mFilterOps.mFilterCategoryTypes != mDefaultFilterOps.mFilterCategoryTypes); @@ -422,11 +421,11 @@ BOOL LLInventoryFilter::isNotDefault() const not_default |= (mFilterOps.mMinDate != mDefaultFilterOps.mMinDate); not_default |= (mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate); not_default |= (mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo); - - return not_default; + + return not_default != 0; } -BOOL LLInventoryFilter::isActive() const +bool LLInventoryFilter::isActive() const { return mFilterOps.mFilterObjectTypes != 0xffffffffffffffffULL || mFilterOps.mFilterCategoryTypes != 0xffffffffffffffffULL @@ -440,16 +439,9 @@ BOOL LLInventoryFilter::isActive() const || mFilterOps.mHoursAgo != 0; } -BOOL LLInventoryFilter::isModified() const +bool LLInventoryFilter::isModified() const { - return mModified; -} - -BOOL LLInventoryFilter::isModifiedAndClear() -{ - BOOL ret = mModified; - mModified = FALSE; - return ret; + return mFilterModified != FILTER_NONE; } void LLInventoryFilter::updateFilterTypes(U64 types, U64& current_types) @@ -613,9 +605,10 @@ void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date) void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl) { + static LLCachedControl<U32> s_last_logoff(gSavedSettings, "LastLogoff", 0); if (sl && !isSinceLogoff()) { - setDateRange(mLastLogoff, time_max()); + setDateRange(s_last_logoff(), time_max()); setModified(); } if (!sl && isSinceLogoff()) @@ -634,17 +627,18 @@ void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl) } } -BOOL LLInventoryFilter::isSinceLogoff() const +bool LLInventoryFilter::isSinceLogoff() const { - return (mFilterOps.mMinDate == (time_t)mLastLogoff) && + static LLCachedControl<U32> s_last_logoff(gSavedSettings, "LastLogoff", 0); + + return (mFilterOps.mMinDate == (time_t)s_last_logoff()) && (mFilterOps.mMaxDate == time_max()) && (mFilterOps.mFilterTypes & FILTERTYPE_DATE); } void LLInventoryFilter::clearModified() { - mModified = FALSE; - mFilterBehavior = FILTER_NONE; + mFilterModified = FILTER_NONE; } void LLInventoryFilter::setHoursAgo(U32 hours) @@ -742,40 +736,39 @@ void LLInventoryFilter::resetDefault() setModified(); } -void LLInventoryFilter::setModified(EFilterBehavior behavior) +void LLInventoryFilter::setModified(EFilterModified behavior) { - mModified = TRUE; - mNeedTextRebuild = TRUE; - mFilterGeneration = mNextFilterGeneration++; + mFilterText.clear(); + mLastSuccessGeneration = mNextFilterGeneration++; - if (mFilterBehavior == FILTER_NONE) + if (mFilterModified == FILTER_NONE) { - mFilterBehavior = behavior; + mFilterModified = behavior; } - else if (mFilterBehavior != behavior) + else if (mFilterModified != behavior) { // trying to do both less restrictive and more restrictive filter // basically means restart from scratch - mFilterBehavior = FILTER_RESTART; + mFilterModified = FILTER_RESTART; } if (isNotDefault()) { // if not keeping current filter results, update last valid as well - switch(mFilterBehavior) + switch(mFilterModified) { case FILTER_RESTART: - mMustPassGeneration = mFilterGeneration; - mMinRequiredGeneration = mFilterGeneration; + mLastFailGeneration = mLastSuccessGeneration; + mFirstSuccessGeneration = mLastSuccessGeneration; break; case FILTER_LESS_RESTRICTIVE: - mMustPassGeneration = mFilterGeneration; + mLastFailGeneration = mLastSuccessGeneration; break; case FILTER_MORE_RESTRICTIVE: - mMinRequiredGeneration = mFilterGeneration; + mFirstSuccessGeneration = mLastSuccessGeneration; // must have passed either current filter generation (meaningless, as it hasn't been run yet) // or some older generation, so keep the value - mMustPassGeneration = llmin(mMustPassGeneration, mFilterGeneration); + mLastFailGeneration = llmin(mLastFailGeneration, mLastSuccessGeneration); break; default: llerrs << "Bad filter behavior specified" << llendl; @@ -784,29 +777,29 @@ void LLInventoryFilter::setModified(EFilterBehavior behavior) else { // shortcut disabled filters to show everything immediately - mMinRequiredGeneration = 0; - mMustPassGeneration = S32_MAX; + mLastFailGeneration = 0; + mFirstSuccessGeneration = S32_MAX; } } -BOOL LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const +bool LLInventoryFilter::isFilterObjectTypesWith(LLInventoryType::EType t) const { return mFilterOps.mFilterObjectTypes & (1LL << t); } const std::string& LLInventoryFilter::getFilterText() { - if (!mNeedTextRebuild) + if (!mFilterText.empty()) { return mFilterText; } - mNeedTextRebuild = FALSE; std::string filtered_types; std::string not_filtered_types; BOOL filtered_by_type = FALSE; BOOL filtered_by_all_types = TRUE; S32 num_filter_types = 0; + mFilterText.clear(); if (isFilterObjectTypesWith(LLInventoryType::IT_ANIMATION)) @@ -991,60 +984,53 @@ const std::string& LLInventoryFilter::getFilterText() return mFilterText; } -void LLInventoryFilter::toLLSD(LLSD& data) const -{ - data["filter_types"] = (LLSD::Integer)getFilterObjectTypes(); - data["min_date"] = (LLSD::Integer)getMinDate(); - data["max_date"] = (LLSD::Integer)getMaxDate(); - data["hours_ago"] = (LLSD::Integer)getHoursAgo(); - data["show_folder_state"] = (LLSD::Integer)getShowFolderState(); - data["permissions"] = (LLSD::Integer)getFilterPermissions(); - data["substring"] = (LLSD::String)getFilterSubString(); - data["sort_order"] = (LLSD::Integer)getSortOrder(); - data["since_logoff"] = (LLSD::Boolean)isSinceLogoff(); -} - -void LLInventoryFilter::fromLLSD(LLSD& data) -{ - if(data.has("filter_types")) - { - setFilterObjectTypes((U64)data["filter_types"].asInteger()); - } - - if(data.has("min_date") && data.has("max_date")) - { - setDateRange(data["min_date"].asInteger(), data["max_date"].asInteger()); - } - - if(data.has("hours_ago")) - { - setHoursAgo((U32)data["hours_ago"].asInteger()); - } - if(data.has("show_folder_state")) - { - setShowFolderState((EFolderShow)data["show_folder_state"].asInteger()); - } +LLInventoryFilter& LLInventoryFilter::operator=( const LLInventoryFilter& other ) +{ + setFilterObjectTypes(other.getFilterObjectTypes()); + setDateRange(other.getMinDate(), other.getMaxDate()); + setHoursAgo(other.getHoursAgo()); + setShowFolderState(other.getShowFolderState()); + setFilterPermissions(other.getFilterPermissions()); + setFilterSubString(other.getFilterSubString()); + setSortOrder(other.getSortOrder()); + setDateRangeLastLogoff(other.isSinceLogoff()); + return *this; +} - if(data.has("permissions")) - { - setFilterPermissions((PermissionMask)data["permissions"].asInteger()); - } - if(data.has("substring")) - { - setFilterSubString(std::string(data["substring"].asString())); - } +void LLInventoryFilter::toParams(Params& params) const +{ + params.filter_ops.types = getFilterObjectTypes(); + params.filter_ops.category_types = getFilterCategoryTypes(); + params.filter_ops.wearable_types = getFilterWearableTypes(); + params.filter_ops.date_range.min_date = getMinDate(); + params.filter_ops.date_range.max_date = getMaxDate(); + params.filter_ops.hours_ago = getHoursAgo(); + params.filter_ops.show_folder_state = getShowFolderState(); + params.filter_ops.permissions = getFilterPermissions(); + params.substring = getFilterSubString(); + params.sort_order = getSortOrder(); + params.since_logoff = isSinceLogoff(); +} - if(data.has("sort_order")) +void LLInventoryFilter::fromParams(const Params& params) +{ + if (!params.validateBlock()) { - setSortOrder((U32)data["sort_order"].asInteger()); + return; } - if(data.has("since_logoff")) - { - setDateRangeLastLogoff((bool)data["since_logoff"].asBoolean()); - } + setFilterObjectTypes(params.filter_ops.types); + setFilterCategoryTypes(params.filter_ops.category_types); + setFilterWearableTypes(params.filter_ops.wearable_types); + setDateRange(params.filter_ops.date_range.min_date, params.filter_ops.date_range.max_date); + setHoursAgo(params.filter_ops.hours_ago); + setShowFolderState(params.filter_ops.show_folder_state); + setFilterPermissions(params.filter_ops.permissions); + setFilterSubString(params.substring); + setSortOrder(params.sort_order); + setDateRangeLastLogoff(params.since_logoff); } U64 LLInventoryFilter::getFilterObjectTypes() const @@ -1057,7 +1043,12 @@ U64 LLInventoryFilter::getFilterCategoryTypes() const return mFilterOps.mFilterCategoryTypes; } -BOOL LLInventoryFilter::hasFilterString() const +U64 LLInventoryFilter::getFilterWearableTypes() const +{ + return mFilterOps.mFilterWearableTypes; +} + +bool LLInventoryFilter::hasFilterString() const { return mFilterSubString.size() > 0; } @@ -1092,10 +1083,6 @@ U32 LLInventoryFilter::getSortOrder() const { return mOrder; } -const std::string& LLInventoryFilter::getName() const -{ - return mName; -} void LLInventoryFilter::setFilterCount(S32 count) { @@ -1113,15 +1100,15 @@ void LLInventoryFilter::decrementFilterCount() S32 LLInventoryFilter::getCurrentGeneration() const { - return mFilterGeneration; + return mLastSuccessGeneration; } -S32 LLInventoryFilter::getMinRequiredGeneration() const +S32 LLInventoryFilter::getFirstSuccessGeneration() const { - return mMinRequiredGeneration; + return mFirstSuccessGeneration; } -S32 LLInventoryFilter::getMustPassGeneration() const +S32 LLInventoryFilter::getFirstRequiredGeneration() const { - return mMustPassGeneration; + return mLastFailGeneration; } void LLInventoryFilter::setEmptyLookupMessage(const std::string& message) @@ -1129,9 +1116,13 @@ void LLInventoryFilter::setEmptyLookupMessage(const std::string& message) mEmptyLookupMessage = message; } -const std::string& LLInventoryFilter::getEmptyLookupMessage() const +// TODO RN: turn this into a param and move to llfolderviewmodelinterface +std::string LLInventoryFilter::getEmptyLookupMessage() const { - return mEmptyLookupMessage; + LLStringUtil::format_map_t args; + args["[SEARCH_TERM]"] = LLURI::escape(getFilterSubStringOrig()); + + return LLTrans::getString(mEmptyLookupMessage, args); } @@ -1141,3 +1132,27 @@ bool LLInventoryFilter::areDateLimitsSet() || mFilterOps.mMaxDate != time_max() || mFilterOps.mHoursAgo != 0; } + +bool LLInventoryFilter::showAllResults() const +{ + return hasFilterString(); +} + + + +bool LLInventoryFilter::FilterOps::DateRange::validateBlock( bool emit_errors /*= true*/ ) const +{ + bool valid = LLInitParam::Block<DateRange>::validateBlock(emit_errors); + if (valid) + { + if (max_date() < min_date()) + { + if (emit_errors) + { + llwarns << "max_date should be greater or equal to min_date" << llendl; + } + valid = false; + } + } + return valid; +} diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index 9e600c036f..e0c3d7141b 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -29,12 +29,13 @@ #include "llinventorytype.h" #include "llpermissionsflags.h" +#include "llfolderviewmodel.h" class LLFolderViewItem; class LLFolderViewFolder; class LLInventoryItem; -class LLInventoryFilter +class LLInventoryFilter : public LLFolderViewFilter { public: enum EFolderShow @@ -44,14 +45,6 @@ public: SHOW_NO_FOLDERS }; - enum EFilterBehavior - { - FILTER_NONE, // nothing to do, already filtered - FILTER_RESTART, // restart filtering from scratch - FILTER_LESS_RESTRICTIVE, // existing filtered items will certainly pass this filter - FILTER_MORE_RESTRICTIVE // if you didn't pass the previous filter, you definitely won't pass this one - }; - enum EFilterType { FILTERTYPE_NONE = 0, FILTERTYPE_OBJECT = 0x1 << 0, // normal default search-by-object-type @@ -59,7 +52,7 @@ public: FILTERTYPE_UUID = 0x1 << 2, // find the object with UUID and any links to it FILTERTYPE_DATE = 0x1 << 3, // search by date range FILTERTYPE_WEARABLE = 0x1 << 4, // search by wearable type - FILTERTYPE_EMPTYFOLDERS = 0x1 << 5 // pass if folder is not a system folder to be hidden if empty + FILTERTYPE_EMPTYFOLDERS = 0x1 << 5 // pass if folder is not a system folder to be hidden if }; enum EFilterLink @@ -77,16 +70,92 @@ public: SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2 // Force system folders to be on top }; - LLInventoryFilter(const std::string& name); - virtual ~LLInventoryFilter(); + struct FilterOps + { + struct DateRange : public LLInitParam::Block<DateRange> + { + Optional<time_t> min_date; + Optional<time_t> max_date; + + DateRange() + : min_date("min_date", time_min()), + max_date("max_date", time_max()) + {} + + bool validateBlock(bool emit_errors = true) const; + }; + + struct Params : public LLInitParam::Block<Params> + { + Optional<U32> types; + Optional<U64> object_types, + wearable_types, + category_types; + Optional<EFilterLink> links; + Optional<LLUUID> uuid; + Optional<DateRange> date_range; + Optional<S32> hours_ago; + Optional<EFolderShow> show_folder_state; + Optional<PermissionMask> permissions; + + Params() + : types("filter_types", FILTERTYPE_OBJECT), + object_types("object_types", 0xffffFFFFffffFFFFULL), + wearable_types("wearable_types", 0xffffFFFFffffFFFFULL), + category_types("category_types", 0xffffFFFFffffFFFFULL), + links("links", FILTERLINK_INCLUDE_LINKS), + uuid("uuid"), + date_range("date_range"), + hours_ago("hours_ago", 0), + show_folder_state("show_folder_state", SHOW_NON_EMPTY_FOLDERS), + permissions("permissions", PERM_NONE) + {} + }; + + FilterOps(const Params& = Params()); + + U32 mFilterTypes; + + U64 mFilterObjectTypes; // For _OBJECT + U64 mFilterWearableTypes; + U64 mFilterCategoryTypes; // For _CATEGORY + LLUUID mFilterUUID; // for UUID + + time_t mMinDate; + time_t mMaxDate; + U32 mHoursAgo; + EFolderShow mShowFolderState; + PermissionMask mPermissions; + U64 mFilterLinks; + }; + + struct Params : public LLInitParam::Block<Params> + { + Optional<FilterOps::Params> filter_ops; + Optional<std::string> substring; + Optional<U32> sort_order; + Optional<bool> since_logoff; + + Params() + : filter_ops(""), + substring("substring"), + sort_order("sort_order"), + since_logoff("since_logoff") + {} + }; + + LLInventoryFilter(const Params& p = Params()); + LLInventoryFilter(const LLInventoryFilter& other) { *this = other; } + virtual ~LLInventoryFilter() {} // +-------------------------------------------------------------------+ // + Parameters // +-------------------------------------------------------------------+ - void setFilterObjectTypes(U64 types); U64 getFilterObjectTypes() const; U64 getFilterCategoryTypes() const; - BOOL isFilterObjectTypesWith(LLInventoryType::EType t) const; + U64 getFilterWearableTypes() const; + bool isFilterObjectTypesWith(LLInventoryType::EType t) const; + void setFilterObjectTypes(U64 types); void setFilterCategoryTypes(U64 types); void setFilterUUID(const LLUUID &object_id); void setFilterWearableTypes(U64 types); @@ -96,7 +165,7 @@ public: void setFilterSubString(const std::string& string); const std::string& getFilterSubString(BOOL trim = FALSE) const; const std::string& getFilterSubStringOrig() const { return mFilterSubStringOrig; } - BOOL hasFilterString() const; + bool hasFilterString() const; void setFilterPermissions(PermissionMask perms); PermissionMask getFilterPermissions() const; @@ -115,19 +184,23 @@ public: // +-------------------------------------------------------------------+ // + Execution And Results // +-------------------------------------------------------------------+ - BOOL check(const LLFolderViewItem* item); + bool check(const LLFolderViewItem* item); bool check(const LLInventoryItem* item); bool checkFolder(const LLFolderViewFolder* folder) const; bool checkFolder(const LLUUID& folder_id) const; - BOOL checkAgainstFilterType(const LLFolderViewItem* item) const; + bool checkAgainstFilterType(const LLFolderViewItem* item) const; bool checkAgainstFilterType(const LLInventoryItem* item) const; - BOOL checkAgainstPermissions(const LLFolderViewItem* item) const; + bool checkAgainstPermissions(const LLFolderViewItem* item) const; bool checkAgainstPermissions(const LLInventoryItem* item) const; - BOOL checkAgainstFilterLinks(const LLFolderViewItem* item) const; + bool checkAgainstFilterLinks(const LLFolderViewItem* item) const; bool checkAgainstClipboard(const LLUUID& object_id) const; + bool showAllResults() const; + + std::string::size_type getStringMatchOffset() const; + std::string::size_type getStringMatchOffset(LLFolderViewItem* item) const; // +-------------------------------------------------------------------+ // + Presentation // +-------------------------------------------------------------------+ @@ -138,20 +211,19 @@ public: U32 getSortOrder() const; void setEmptyLookupMessage(const std::string& message); - const std::string& getEmptyLookupMessage() const; + std::string getEmptyLookupMessage() const; // +-------------------------------------------------------------------+ // + Status // +-------------------------------------------------------------------+ - BOOL isActive() const; - BOOL isModified() const; - BOOL isModifiedAndClear(); - BOOL isSinceLogoff() const; + bool isActive() const; + bool isModified() const; + bool isSinceLogoff() const; void clearModified(); const std::string& getName() const; const std::string& getFilterText(); //RN: this is public to allow system to externally force a global refilter - void setModified(EFilterBehavior behavior = FILTER_RESTART); + void setModified(EFilterModified behavior = FILTER_RESTART); // +-------------------------------------------------------------------+ // + Count @@ -163,8 +235,8 @@ public: // +-------------------------------------------------------------------+ // + Default // +-------------------------------------------------------------------+ - BOOL isDefault() const; - BOOL isNotDefault() const; + bool isDefault() const; + bool isNotDefault() const; void markDefault(); void resetDefault(); @@ -172,57 +244,37 @@ public: // + Generation // +-------------------------------------------------------------------+ S32 getCurrentGeneration() const; - S32 getMinRequiredGeneration() const; - S32 getMustPassGeneration() const; + S32 getFirstSuccessGeneration() const; + S32 getFirstRequiredGeneration() const; + // +-------------------------------------------------------------------+ // + Conversion // +-------------------------------------------------------------------+ - void toLLSD(LLSD& data) const; - void fromLLSD(LLSD& data); + void toParams(Params& params) const; + void fromParams(const Params& p); + + LLInventoryFilter& operator =(const LLInventoryFilter& other); private: bool areDateLimitsSet(); - struct FilterOps - { - FilterOps(); - U32 mFilterTypes; - - U64 mFilterObjectTypes; // For _OBJECT - U64 mFilterWearableTypes; - U64 mFilterCategoryTypes; // For _CATEGORY - LLUUID mFilterUUID; // for UUID - - time_t mMinDate; - time_t mMaxDate; - U32 mHoursAgo; - EFolderShow mShowFolderState; - PermissionMask mPermissions; - U64 mFilterLinks; - }; - U32 mOrder; - U32 mLastLogoff; FilterOps mFilterOps; FilterOps mDefaultFilterOps; - std::string::size_type mSubStringMatchOffset; std::string mFilterSubString; std::string mFilterSubStringOrig; - const std::string mName; - S32 mFilterGeneration; - S32 mMustPassGeneration; - S32 mMinRequiredGeneration; + S32 mLastSuccessGeneration; + S32 mLastFailGeneration; + S32 mFirstSuccessGeneration; S32 mNextFilterGeneration; S32 mFilterCount; - EFilterBehavior mFilterBehavior; + EFilterModified mFilterModified; - BOOL mModified; - BOOL mNeedTextRebuild; std::string mFilterText; std::string mEmptyLookupMessage; }; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index ab5b082915..1e494c3ef1 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -948,7 +948,7 @@ void LLSaveFolderState::setApply(BOOL apply) void LLSaveFolderState::doFolder(LLFolderViewFolder* folder) { LLMemType mt(LLMemType::MTYPE_INVENTORY_DO_FOLDER); - LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener(); + LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getViewModelItem(); if(!bridge) return; if(mApply) diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 5cf9c528b0..c6b1da0417 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -418,21 +418,6 @@ public: class LLFolderViewItem; class LLFolderViewFolder; -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLFolderViewFunctor -// -// Simple abstract base class for applying a functor to folders and -// items in a folder view hierarchy. This is suboptimal for algorithms -// that only work folders or only work on items, but I'll worry about -// that later when it's determined to be too slow. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLFolderViewFunctor -{ -public: - virtual ~LLFolderViewFunctor() {} - virtual void doFolder(LLFolderViewFolder* folder) = 0; - virtual void doItem(LLFolderViewItem* item) = 0; -}; class LLInventoryState { @@ -442,49 +427,6 @@ public: static LLUUID sWearNewClothingTransactionID; // wear all clothing in this transaction }; -class LLSelectFirstFilteredItem : public LLFolderViewFunctor -{ -public: - LLSelectFirstFilteredItem() : mItemSelected(FALSE) {} - virtual ~LLSelectFirstFilteredItem() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); - BOOL wasItemSelected() { return mItemSelected; } -protected: - BOOL mItemSelected; -}; - -class LLOpenFilteredFolders : public LLFolderViewFunctor -{ -public: - LLOpenFilteredFolders() {} - virtual ~LLOpenFilteredFolders() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); -}; - -class LLSaveFolderState : public LLFolderViewFunctor -{ -public: - LLSaveFolderState() : mApply(FALSE) {} - virtual ~LLSaveFolderState() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item) {} - void setApply(BOOL apply); - void clearOpenFolders() { mOpenFolders.clear(); } -protected: - std::set<LLUUID> mOpenFolders; - BOOL mApply; -}; - -class LLOpenFoldersWithSelection : public LLFolderViewFunctor -{ -public: - LLOpenFoldersWithSelection() {} - virtual ~LLOpenFoldersWithSelection() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); -}; #endif // LL_LLINVENTORYFUNCTIONS_H diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 71dd963f28..e739694fe0 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -38,6 +38,7 @@ #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" #include "llfolderview.h" +#include "llfolderviewitem.h" #include "llimfloater.h" #include "llimview.h" #include "llinventorybridge.h" @@ -55,6 +56,68 @@ const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("Recent const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string(""); static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER; +// +// class LLFolderViewModelInventory +// +void LLFolderViewModelInventory::requestSort(class LLFolderViewFolder* folder) +{ + base_t::requestSort(folder); + if (getSorter().isByDate()) + { + // sort by date potentially affects parent folders which use a date + // derived from newest item in them + requestSort(folder->getParentFolder()); + } +} + +static LLFastTimer::DeclareTimer FTM_INVENTORY_SORT("Sort"); + +void LLFolderViewModelInventory::sort( LLFolderViewFolder* folder ) +{ + LLFastTimer _(FTM_INVENTORY_SORT); + + if (!needsSort(folder->getViewModelItem())) return; + + LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(folder->getViewModelItem()); + if (modelp->getUUID().isNull()) return; + + for (std::list<LLFolderViewFolder*>::iterator it = folder->getFoldersBegin(), end_it = folder->getFoldersEnd(); + it != end_it; + ++it) + { + LLFolderViewFolder* child_folderp = *it; + sort(child_folderp); + + if (child_folderp->getFoldersCount() > 0) + { + time_t most_recent_folder_time = + static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getFoldersBegin())->getViewModelItem())->getCreationDate(); + LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); + if (most_recent_folder_time > modelp->getCreationDate()) + { + modelp->setCreationDate(most_recent_folder_time); + } + } + if (child_folderp->getItemsCount() > 0) + { + time_t most_recent_item_time = + static_cast<LLFolderViewModelItemInventory*>((*child_folderp->getItemsBegin())->getViewModelItem())->getCreationDate(); + + LLFolderViewModelItemInventory* modelp = static_cast<LLFolderViewModelItemInventory*>(child_folderp->getViewModelItem()); + if (most_recent_item_time > modelp->getCreationDate()) + { + modelp->setCreationDate(most_recent_item_time); + } + } + } + base_t::sort(folder); +} + +bool LLFolderViewModelInventory::contentsReady() +{ + return !LLInventoryModelBackgroundFetch::instance().folderFetchActive(); +} + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryPanelObserver @@ -134,7 +197,6 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : mAllowMultiSelect(p.allow_multi_select), mShowItemLinkOverlays(p.show_item_link_overlays), mShowEmptyMessage(p.show_empty_message), - mShowLoadStatus(p.show_load_status), mViewsInitialized(false), mInvFVBridgeBuilder(NULL) { @@ -187,6 +249,7 @@ void LLInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) root_id); mFolderRoot = createFolderView(new_listener, params.use_label_suffix()); + addItemID(root_id, mFolderRoot); } void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) @@ -258,13 +321,10 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) LLInventoryPanel::~LLInventoryPanel() { - if (mFolderRoot) + U32 sort_order = getFolderViewModel()->getSorter().getSortOrder(); + if (mSortOrderSetting != INHERIT_SORT_ORDER) { - U32 sort_order = mFolderRoot->getSortOrder(); - if (mSortOrderSetting != INHERIT_SORT_ORDER) - { - gSavedSettings.setU32(mSortOrderSetting, sort_order); - } + gSavedSettings.setU32(mSortOrderSetting, sort_order); } gIdleCallbacks.deleteFunction(onIdle, this); @@ -281,7 +341,7 @@ LLInventoryPanel::~LLInventoryPanel() void LLInventoryPanel::draw() { // Select the desired item (in case it wasn't loaded when the selection was requested) - mFolderRoot->updateSelection(); + updateSelection(); // Nudge the filter if the clipboard state changed if (mClipboardState != LLClipboard::instance().getGeneration()) @@ -293,22 +353,9 @@ void LLInventoryPanel::draw() LLPanel::draw(); } -LLInventoryFilter* LLInventoryPanel::getFilter() -{ - if (mFolderRoot) - { - return mFolderRoot->getFilter(); - } - return NULL; -} - const LLInventoryFilter* LLInventoryPanel::getFilter() const { - if (mFolderRoot) - { - return mFolderRoot->getFilter(); - } - return NULL; + return &getFolderViewModel()->getFilter(); } void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType filter_type) @@ -321,12 +368,12 @@ void LLInventoryPanel::setFilterTypes(U64 types, LLInventoryFilter::EFilterType U32 LLInventoryPanel::getFilterObjectTypes() const { - return mFolderRoot->getFilterObjectTypes(); + return getFilter()->getFilterObjectTypes(); } U32 LLInventoryPanel::getFilterPermMask() const { - return mFolderRoot->getFilterPermissions(); + return getFilter()->getFilterPermissions(); } @@ -347,16 +394,17 @@ void LLInventoryPanel::setFilterSubString(const std::string& string) const std::string LLInventoryPanel::getFilterSubString() { - return mFolderRoot->getFilterSubString(); + return getFilter()->getFilterSubString(); } void LLInventoryPanel::setSortOrder(U32 order) { + LLInventorySort sorter(order); getFilter()->setSortOrder(order); - if (getFilter()->isModified()) + if (order != getFolderViewModel()->getSorter().getSortOrder()) { - mFolderRoot->setSortOrder(order); + getFolderViewModel()->setSorter(LLInventorySort(order)); // try to keep selection onscreen, even if it wasn't to start with mFolderRoot->scrollToShowSelection(); } @@ -364,12 +412,7 @@ void LLInventoryPanel::setSortOrder(U32 order) U32 LLInventoryPanel::getSortOrder() const { - return mFolderRoot->getSortOrder(); -} - -void LLInventoryPanel::requestSort() -{ - mFolderRoot->requestSort(); + return getFolderViewModel()->getSorter().getSortOrder(); } void LLInventoryPanel::setSinceLogoff(BOOL sl) @@ -418,7 +461,9 @@ void LLInventoryPanel::modelChanged(U32 mask) { const LLUUID& item_id = (*items_iter); const LLInventoryObject* model_item = model->getObject(item_id); - LLFolderViewItem* view_item = mFolderRoot->getItemByID(item_id); + LLFolderViewItem* view_item = getItemByID(item_id); + LLFolderViewModelItemInventory* viewmodel_item = + static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL); // LLFolderViewFolder is derived from LLFolderViewItem so dynamic_cast from item // to folder is the fast way to get a folder without searching through folders tree. @@ -433,7 +478,7 @@ void LLInventoryPanel::modelChanged(U32 mask) if (view_item) { // Request refresh on this item (also flags for filtering) - LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getListener(); + LLInvFVBridge* bridge = (LLInvFVBridge*)view_item->getViewModelItem(); if(bridge) { // Clear the display name first, so it gets properly re-built during refresh() bridge->clearDisplayName(); @@ -452,8 +497,11 @@ void LLInventoryPanel::modelChanged(U32 mask) if (model_item && view_item) { view_item->destroyView(); + removeItemID(viewmodel_item->getUUID()); } view_item = buildNewViews(item_id); + viewmodel_item = + static_cast<LLFolderViewModelItemInventory*>(view_item ? view_item->getViewModelItem() : NULL); view_folder = dynamic_cast<LLFolderViewFolder *>(view_item); } @@ -510,9 +558,9 @@ void LLInventoryPanel::modelChanged(U32 mask) else if (model_item && view_item) { // Don't process the item if it is the root - if (view_item->getRoot() != view_item) + if (view_item->getParentFolder()) { - LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolderRoot->getItemByID(model_item->getParentUUID()); + LLFolderViewFolder* new_parent = (LLFolderViewFolder*)getItemByID(model_item->getParentUUID()); // Item has been moved. if (view_item->getParentFolder() != new_parent) { @@ -520,13 +568,15 @@ void LLInventoryPanel::modelChanged(U32 mask) { // Item is to be moved and we found its new parent in the panel's directory, so move the item's UI. view_item->getParentFolder()->extractItem(view_item); - view_item->addToFolder(new_parent, mFolderRoot); + view_item->addToFolder(new_parent); + addItemID(viewmodel_item->getUUID(), view_item); } else { // Item is to be moved outside the panel's directory (e.g. moved to trash for a panel that // doesn't include trash). Just remove the item's UI. view_item->destroyView(); + removeItemID(viewmodel_item->getUUID()); } } } @@ -539,6 +589,7 @@ void LLInventoryPanel::modelChanged(U32 mask) { // Remove the item's UI. view_item->destroyView(); + removeItemID(viewmodel_item->getUUID()); } } } @@ -568,16 +619,11 @@ void LLInventoryPanel::onIdle(void *userdata) } } -const LLUUID& LLInventoryPanel::getRootFolderID() const -{ - return mFolderRoot->getListener()->getUUID(); -} - void LLInventoryPanel::initializeViews() { if (!gInventory.isInventoryUsable()) return; - rebuildViewsFor(getRootFolderID()); + rebuildViewsFor(gInventory.getRootFolderID()); mViewsInitialized = true; @@ -587,14 +633,14 @@ void LLInventoryPanel::initializeViews() if (gAgent.isFirstLogin()) { // Auto open the user's library - LLFolderViewFolder* lib_folder = mFolderRoot->getFolderByID(gInventory.getLibraryRootFolderID()); + LLFolderViewFolder* lib_folder = getFolderByID(gInventory.getLibraryRootFolderID()); if (lib_folder) { lib_folder->setOpen(TRUE); } // Auto close the user's my inventory folder - LLFolderViewFolder* my_inv_folder = mFolderRoot->getFolderByID(gInventory.getRootFolderID()); + LLFolderViewFolder* my_inv_folder = getFolderByID(gInventory.getRootFolderID()); if (my_inv_folder) { my_inv_folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN); @@ -605,10 +651,11 @@ void LLInventoryPanel::initializeViews() LLFolderViewItem* LLInventoryPanel::rebuildViewsFor(const LLUUID& id) { // Destroy the old view for this ID so we can rebuild it. - LLFolderViewItem* old_view = mFolderRoot->getItemByID(id); + LLFolderViewItem* old_view = getItemByID(id); if (old_view) { old_view->destroyView(); + removeItemID(static_cast<LLFolderViewModelItemInventory*>(old_view->getViewModelItem())->getUUID()); } return buildNewViews(id); @@ -632,7 +679,6 @@ LLFolderView * LLInventoryPanel::createFolderView(LLInvFVBridge * bridge, bool u p.use_label_suffix = useLabelSuffix; p.allow_multiselect = mAllowMultiSelect; p.show_empty_message = mShowEmptyMessage; - p.show_load_status = mShowLoadStatus; return LLUICtrlFactory::create<LLFolderView>(p); } @@ -682,79 +728,65 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) { LLInventoryObject const* objectp = gInventory.getObject(id); - LLUUID root_id = mFolderRoot->getListener()->getUUID(); - LLFolderViewFolder* parent_folder = NULL; - LLFolderViewItem* itemp = NULL; - if (id == root_id) - { - parent_folder = mFolderRoot; - } - else if (objectp) - { - const LLUUID &parent_id = objectp->getParentUUID(); - parent_folder = (LLFolderViewFolder*)mFolderRoot->getItemByID(parent_id); - - if (parent_folder) + if (!objectp) return NULL; + + LLFolderViewItem* folder_view_item = getItemByID(id); + LLFolderViewFolder* parent_folder = folder_view_item->getParentFolder(); + + if (!folder_view_item && parent_folder) + { + if (objectp->getType() <= LLAssetType::AT_NONE || + objectp->getType() >= LLAssetType::AT_COUNT) { - if (objectp->getType() <= LLAssetType::AT_NONE || - objectp->getType() >= LLAssetType::AT_COUNT) - { - llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " - << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() - << llendl; - return NULL; - } + llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " + << ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() + << llendl; + return NULL; + } - if ((objectp->getType() == LLAssetType::AT_CATEGORY) && - (objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)) + if ((objectp->getType() == LLAssetType::AT_CATEGORY) && + (objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)) + { + LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(), + objectp->getType(), + LLInventoryType::IT_CATEGORY, + this, + mFolderRoot, + objectp->getUUID()); + if (new_listener) { - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(), - objectp->getType(), - LLInventoryType::IT_CATEGORY, - this, - mFolderRoot, - objectp->getUUID()); - if (new_listener) - { - LLFolderViewFolder* folderp = createFolderViewFolder(new_listener); - if (folderp) - { - folderp->setItemSortOrder(mFolderRoot->getSortOrder()); - } - itemp = folderp; - } + folder_view_item = createFolderViewFolder(new_listener); } - else - { - // Build new view for item. - LLInventoryItem* item = (LLInventoryItem*)objectp; - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(), - item->getActualType(), - item->getInventoryType(), - this, - mFolderRoot, - item->getUUID(), - item->getFlags()); + } + else + { + // Build new view for item. + LLInventoryItem* item = (LLInventoryItem*)objectp; + LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(), + item->getActualType(), + item->getInventoryType(), + this, + mFolderRoot, + item->getUUID(), + item->getFlags()); - if (new_listener) - { - itemp = createFolderViewItem(new_listener); - } + if (new_listener) + { + folder_view_item = createFolderViewItem(new_listener); } + } - if (itemp) - { - itemp->addToFolder(parent_folder, mFolderRoot); - } - } + if (folder_view_item) + { + folder_view_item->addToFolder(parent_folder); + addItemID(id, folder_view_item); + } } // If this is a folder, add the children of the folder and recursively add any // child folders. - if (id.isNull() - || (objectp - && objectp->getType() == LLAssetType::AT_CATEGORY)) + if (folder_view_item && objectp->getType() == LLAssetType::AT_CATEGORY) { LLViewerInventoryCategory::cat_array_t* categories; LLViewerInventoryItem::item_array_t* items; @@ -771,7 +803,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) } } - if(items && parent_folder) + if(items) { for (LLViewerInventoryItem::item_array_t::const_iterator item_iter = items->begin(); item_iter != items->end(); @@ -784,7 +816,7 @@ LLFolderViewItem* LLInventoryPanel::buildNewViews(const LLUUID& id) mInventory->unlockDirectDescendentArrays(id); } - return itemp; + return folder_view_item; } // bit of a hack to make sure the inventory is open. @@ -795,8 +827,8 @@ void LLInventoryPanel::openStartFolderOrMyInventory() { LLFolderViewFolder *fchild = dynamic_cast<LLFolderViewFolder*>(child); if (fchild - && fchild->getListener() - && fchild->getListener()->getUUID() == gInventory.getRootFolderID()) + && fchild->getViewModelItem() + && fchild->getViewModelItem()->getName() == "My Inventory") { fchild->setOpen(TRUE); break; @@ -813,7 +845,7 @@ void LLInventoryPanel::openSelected() { LLFolderViewItem* folder_item = mFolderRoot->getCurSelectedItem(); if(!folder_item) return; - LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); + LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getViewModelItem(); if(!bridge) return; bridge->openItem(); } @@ -917,7 +949,7 @@ void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_foc { return; } - mFolderRoot->setSelectionByID(obj_id, take_keyboard_focus); + setSelectionByID(obj_id, take_keyboard_focus); } void LLInventoryPanel::setSelectCallback(const boost::function<void (const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb) @@ -930,7 +962,7 @@ void LLInventoryPanel::setSelectCallback(const boost::function<void (const std:: void LLInventoryPanel::clearSelection() { - mFolderRoot->clearSelection(); + mSelectThisID.setNull(); } void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action) @@ -939,7 +971,7 @@ void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& it mCompletionObserver->reset(); for (std::deque<LLFolderViewItem*>::const_iterator it = items.begin(); it != items.end(); ++it) { - LLUUID id = (*it)->getListener()->getUUID(); + LLUUID id = static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID(); LLViewerInventoryItem* inv_item = mInventory->getItem(id); if (inv_item && !inv_item->isFinished()) @@ -966,12 +998,12 @@ void LLInventoryPanel::doToSelected(const LLSD& userdata) void LLInventoryPanel::doCreate(const LLSD& userdata) { - menu_create_inventory_item(mFolderRoot, LLFolderBridge::sSelf.get(), userdata); + menu_create_inventory_item(this, LLFolderBridge::sSelf.get(), userdata); } bool LLInventoryPanel::beginIMSession() { - std::set<LLUUID> selected_items = mFolderRoot->getSelectionList(); + std::set<LLFolderViewItem*> selected_items = mFolderRoot->getSelectionList(); std::string name; static int session_num = 1; @@ -979,20 +1011,19 @@ bool LLInventoryPanel::beginIMSession() LLDynamicArray<LLUUID> members; EInstantMessage type = IM_SESSION_CONFERENCE_START; - std::set<LLUUID>::const_iterator iter; + std::set<LLFolderViewItem*>::const_iterator iter; for (iter = selected_items.begin(); iter != selected_items.end(); iter++) { - LLUUID item = *iter; - LLFolderViewItem* folder_item = mFolderRoot->getItemByID(item); + LLFolderViewItem* folder_item = (*iter); if(folder_item) { - LLFolderViewEventListener* fve_listener = folder_item->getListener(); + LLFolderViewModelItemInventory* fve_listener = static_cast<LLFolderViewModelItemInventory*>(folder_item->getViewModelItem()); if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY)) { - LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener(); + LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getViewModelItem(); if(!bridge) return true; LLViewerInventoryCategory* cat = bridge->getCategory(); if(!cat) return true; @@ -1026,9 +1057,7 @@ bool LLInventoryPanel::beginIMSession() } else { - LLFolderViewItem* folder_item = mFolderRoot->getItemByID(item); - if(!folder_item) return true; - LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener(); + LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getViewModelItem(); if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD) { @@ -1069,13 +1098,13 @@ bool LLInventoryPanel::beginIMSession() bool LLInventoryPanel::attachObject(const LLSD& userdata) { // Copy selected item UUIDs to a vector. - std::set<LLUUID> selected_items = mFolderRoot->getSelectionList(); + std::set<LLFolderViewItem*> selected_items = mFolderRoot->getSelectionList(); uuid_vec_t items; - for (std::set<LLUUID>::const_iterator set_iter = selected_items.begin(); + for (std::set<LLFolderViewItem*>::const_iterator set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter) { - items.push_back(*set_iter); + items.push_back(static_cast<LLFolderViewModelItemInventory*>((*set_iter)->getViewModelItem())->getUUID()); } // Attach selected items. @@ -1222,6 +1251,80 @@ BOOL LLInventoryPanel::getIsHiddenFolderType(LLFolderType::EType folder_type) co return !(getFilter()->getFilterCategoryTypes() & (1ULL << folder_type)); } +void LLInventoryPanel::addItemID( const LLUUID& id, LLFolderViewItem* itemp ) +{ + mItemMap[id] = itemp; +} + +void LLInventoryPanel::removeItemID(const LLUUID& id) +{ + LLInventoryModel::cat_array_t categories; + LLInventoryModel::item_array_t items; + gInventory.collectDescendents(id, categories, items, TRUE); + + mItemMap.erase(id); + + for (LLInventoryModel::cat_array_t::iterator it = categories.begin(), end_it = categories.end(); + it != end_it; + ++it) + { + mItemMap.erase((*it)->getUUID()); + } + + for (LLInventoryModel::item_array_t::iterator it = items.begin(), end_it = items.end(); + it != end_it; + ++it) + { + mItemMap.erase((*it)->getUUID()); + } +} + +LLFastTimer::DeclareTimer FTM_GET_ITEM_BY_ID("Get FolderViewItem by ID"); +LLFolderViewItem* LLInventoryPanel::getItemByID(const LLUUID& id) +{ + LLFastTimer _(FTM_GET_ITEM_BY_ID); + + std::map<LLUUID, LLFolderViewItem*>::iterator map_it; + map_it = mItemMap.find(id); + if (map_it != mItemMap.end()) + { + return map_it->second; + } + + return NULL; +} + +LLFolderViewFolder* LLInventoryPanel::getFolderByID(const LLUUID& id) +{ + LLFolderViewItem* item = getItemByID(id); + return dynamic_cast<LLFolderViewFolder*>(item); +} + + +void LLInventoryPanel::setSelectionByID( const LLUUID& obj_id, BOOL take_keyboard_focus ) +{ + LLFolderViewItem* itemp = getItemByID(obj_id); + if(itemp && itemp->getViewModelItem()) + { + itemp->arrangeAndSet(TRUE, take_keyboard_focus); + mSelectThisID.setNull(); + return; + } + else + { + // save the desired item to be selected later (if/when ready) + mSelectThisID = obj_id; + } +} + +void LLInventoryPanel::updateSelection() +{ + if (mSelectThisID.notNull()) + { + setSelectionByID(mSelectThisID, false); + } +} + /************************************************************************/ /* Recent Inventory Panel related class */ diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 6db59afb9b..cd32b18779 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -30,6 +30,7 @@ #include "llassetstorage.h" #include "lldarray.h" +#include "llfolderviewitem.h" #include "llfloater.h" #include "llinventory.h" #include "llinventoryfilter.h" @@ -38,23 +39,71 @@ #include "lluictrlfactory.h" #include <set> -class LLFolderView; -class LLFolderViewFolder; -class LLFolderViewItem; -class LLInventoryFilter; -class LLInventoryModel; class LLInvFVBridge; class LLInventoryFVBridgeBuilder; -class LLMenuBarGL; -class LLCheckBoxCtrl; -class LLSpinCtrl; -class LLTextBox; -class LLIconCtrl; -class LLSaveFolderState; -class LLFilterEditor; -class LLTabContainer; class LLInvPanelComplObserver; +class LLFolderViewModelItemInventory + : public LLFolderViewModelItemCommon +{ +public: + virtual const LLUUID& getUUID() const = 0; + virtual time_t getCreationDate() const = 0; // UTC seconds + virtual void setCreationDate(time_t creation_date_utc) = 0; + virtual PermissionMask getPermissionMask() const = 0; + virtual LLFolderType::EType getPreferredType() const = 0; + virtual void showProperties(void) = 0; + virtual BOOL isItemInTrash( void) const { return FALSE; } // TODO: make into pure virtual. + virtual BOOL isUpToDate() const = 0; + virtual bool hasChildren() const = 0; + virtual LLInventoryType::EType getInventoryType() const = 0; + virtual void performAction(LLInventoryModel* model, std::string action) = 0; + virtual LLWearableType::EType getWearableType() const = 0; + virtual EInventorySortGroup getSortGroup() const = 0; + virtual LLInventoryObject* getInventoryObject() const = 0; +}; + +class LLInventorySort +{ +public: + LLInventorySort(U32 order = 0) + : mSortOrder(order), + mByDate(false), + mSystemToTop(false), + mFoldersByName(false) + { + mByDate = (order & LLInventoryFilter::SO_DATE); + mSystemToTop = (order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP); + mFoldersByName = (order & LLInventoryFilter::SO_FOLDERS_BY_NAME); + } + + bool isByDate() const { return mByDate; } + U32 getSortOrder() const { return mSortOrder; } + + bool operator()(const LLFolderViewModelItemInventory* const& a, const LLFolderViewModelItemInventory* const& b) const; +private: + U32 mSortOrder; + bool mByDate; + bool mSystemToTop; + bool mFoldersByName; +}; + +class LLFolderViewModelInventory + : public LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> +{ +public: + typedef LLFolderViewModel<LLInventorySort, LLFolderViewModelItemInventory, LLFolderViewModelItemInventory, LLInventoryFilter> base_t; + + virtual ~LLFolderViewModelInventory() {} + + void sort(LLFolderViewFolder* folder); + void requestSort(LLFolderViewFolder* folder); + + bool contentsReady(); + +}; + + class LLInventoryPanel : public LLPanel { //-------------------------------------------------------------------- @@ -85,7 +134,6 @@ public: Optional<std::string> start_folder; Optional<bool> use_label_suffix; Optional<bool> show_empty_message; - Optional<bool> show_load_status; Optional<LLScrollContainer::Params> scroll; Optional<bool> accepts_drag_and_drop; @@ -98,7 +146,6 @@ public: start_folder("start_folder"), use_label_suffix("use_label_suffix", true), show_empty_message("show_empty_message", true), - show_load_status("show_load_status"), scroll("scroll"), accepts_drag_and_drop("accepts_drag_and_drop") {} @@ -182,10 +229,21 @@ public: static void openInventoryPanelAndSetSelection(BOOL auto_open, const LLUUID& obj_id); + void addItemID(const LLUUID& id, LLFolderViewItem* itemp); + void removeItemID(const LLUUID& id); + LLFolderViewItem* getItemByID(const LLUUID& id); + LLFolderViewFolder* getFolderByID(const LLUUID& id); + void setSelectionByID(const LLUUID& obj_id, BOOL take_keyboard_focus); + void updateSelection(); + + LLFolderViewModelInventory* getFolderViewModel() { return &mViewModel; } + const LLFolderViewModelInventory* getFolderViewModel() const { return &mViewModel; } + protected: void openStartFolderOrMyInventory(); // open the first level of inventory void onItemsCompletion(); // called when selected items are complete + LLUUID mSelectThisID; LLInventoryModel* mInventory; LLInventoryObserver* mInventoryObserver; LLInvPanelComplObserver* mCompletionObserver; @@ -193,11 +251,13 @@ protected: BOOL mAllowMultiSelect; BOOL mShowItemLinkOverlays; // Shows link graphic over inventory item icons BOOL mShowEmptyMessage; - BOOL mShowLoadStatus; LLFolderView* mFolderRoot; LLScrollContainer* mScroller; + LLFolderViewModelInventory mViewModel; + + std::map<LLUUID, LLFolderViewItem*> mItemMap; /** * Pointer to LLInventoryFVBridgeBuilder. * @@ -218,7 +278,6 @@ public: void setSortOrder(U32 order); U32 getSortOrder() const; - void requestSort(); private: std::string mSortOrderSetting; @@ -231,8 +290,7 @@ public: void addHideFolderType(LLFolderType::EType folder_type); public: - BOOL getIsViewsInitialized() const { return mViewsInitialized; } - const LLUUID& getRootFolderID() const; + BOOL getIsViewsInitialized() const { return mViewsInitialized; } protected: // Builds the UI. Call this once the inventory is usable. void initializeViews(); diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 68a3b6d1cd..54ad2bcb76 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -102,7 +102,7 @@ void LLCheckFolderState::doFolder(LLFolderViewFolder* folder) // Counting only folders that pass the filter. // The listener check allow us to avoid counting the folder view // object itself because it has no listener assigned. - if (folder->hasFilteredDescendants() && folder->getListener()) + if (folder->hasFilteredDescendants() && folder->getViewModelItem()) { if (folder->isOpen()) { @@ -138,7 +138,7 @@ private: // virtual void LLOpenFolderByID::doFolder(LLFolderViewFolder* folder) { - if (folder->getListener() && folder->getListener()->getUUID() == mFolderID) + if (folder->getViewModelItem() && folder->getViewModelItem()->getUUID() == mFolderID) { if (!folder->isOpen()) { @@ -286,7 +286,7 @@ void LLLandmarksPanel::onShowProfile() if(!cur_item) return; - cur_item->getListener()->performAction(mCurrentSelectedList->getModel(),"about"); + cur_item->getViewModelItem()->performAction(mCurrentSelectedList->getModel(),"about"); } // virtual @@ -299,7 +299,7 @@ void LLLandmarksPanel::onTeleport() return; } - LLFolderViewEventListener* listenerp = current_item->getListener(); + LLFolderViewModelItem* listenerp = current_item->getViewModelItem(); if (listenerp && listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) { listenerp->openItem(); @@ -360,7 +360,7 @@ void LLLandmarksPanel::onSelectorButtonClicked() LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem(); if (!cur_item) return; - LLFolderViewEventListener* listenerp = cur_item->getListener(); + LLFolderViewModelItem* listenerp = cur_item->getViewModelItem(); if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK) { LLSD key; @@ -376,7 +376,7 @@ void LLLandmarksPanel::updateShowFolderState() if (!mLandmarksInventoryPanel->getFilter()) return; - bool show_all_folders = mLandmarksInventoryPanel->getRootFolder()->getFilterSubString().empty(); + bool show_all_folders = mLandmarksInventoryPanel->getFilterSubString().empty(); if (show_all_folders) { show_all_folders = category_has_descendents(mLandmarksInventoryPanel); @@ -418,7 +418,7 @@ void LLLandmarksPanel::setItemSelected(const LLUUID& obj_id, BOOL take_keyboard_ bool LLLandmarksPanel::isLandmarkSelected() const { LLFolderViewItem* current_item = getCurSelectedItem(); - if(current_item && current_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) + if(current_item && current_item->getViewModelItem()->getInventoryType() == LLInventoryType::IT_LANDMARK) { return true; } @@ -441,9 +441,9 @@ bool LLLandmarksPanel::isReceivedFolderSelected() const void LLLandmarksPanel::doActionOnCurSelectedLandmark(LLLandmarkList::loaded_callback_t cb) { LLFolderViewItem* cur_item = getCurSelectedItem(); - if(cur_item && cur_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) + if(cur_item && cur_item->getViewModelItem()->getInventoryType() == LLInventoryType::IT_LANDMARK) { - LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID(), cb); + LLLandmark* landmark = LLLandmarkActions::getLandmark(cur_item->getViewModelItem()->getUUID(), cb); if (landmark) { cb(landmark); @@ -466,7 +466,7 @@ LLFolderViewItem* LLLandmarksPanel::selectItemInAccordionTab(LLPlacesInventoryPa LLFolderView* root = inventory_list->getRootFolder(); - LLFolderViewItem* item = root->getItemByID(obj_id); + LLFolderViewItem* item = inventory_list->getItemByID(obj_id); if (!item) return NULL; @@ -510,7 +510,7 @@ void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data) { LLFolderViewItem* cur_item = getCurSelectedItem(); if (!cur_item) return; - LLUUID id = cur_item->getListener()->getUUID(); + LLUUID id = cur_item->getViewModelItem()->getUUID(); LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id); doActionOnCurSelectedLandmark(boost::bind( &LLLandmarksPanel::doProcessParcelInfo, this, _1, cur_item, inv_item, parcel_data)); @@ -665,20 +665,20 @@ void LLLandmarksPanel::deselectOtherThan(const LLPlacesInventoryPanel* inventory { if (inventory_list != mFavoritesInventoryPanel) { - mFavoritesInventoryPanel->getRootFolder()->clearSelection(); + mFavoritesInventoryPanel->clearSelection(); } if (inventory_list != mLandmarksInventoryPanel) { - mLandmarksInventoryPanel->getRootFolder()->clearSelection(); + mLandmarksInventoryPanel->clearSelection(); } if (inventory_list != mMyInventoryPanel) { - mMyInventoryPanel->getRootFolder()->clearSelection(); + mMyInventoryPanel->clearSelection(); } if (inventory_list != mLibraryInventoryPanel) { - mLibraryInventoryPanel->getRootFolder()->clearSelection(); + mLibraryInventoryPanel->clearSelection(); } } @@ -738,7 +738,7 @@ void LLLandmarksPanel::onActionsButtonClick() if(!cur_item) return; - LLFolderViewEventListener* listenerp = cur_item->getListener(); + LLFolderViewModelItem* listenerp = cur_item->getViewModelItem(); if(!listenerp) return; @@ -794,21 +794,21 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const LLFolderViewItem* item = getCurSelectedItem(); if (item && mCurrentSelectedList == mLandmarksInventoryPanel) { - LLFolderViewEventListener* folder_bridge = NULL; - if (item-> getListener()->getInventoryType() + LLFolderViewModelItem* folder_bridge = NULL; + if (item-> getViewModelItem()->getInventoryType() == LLInventoryType::IT_LANDMARK) { // for a landmark get parent folder bridge - folder_bridge = item->getParentFolder()->getListener(); + folder_bridge = item->getParentFolder()->getViewModelItem(); } - else if (item-> getListener()->getInventoryType() + else if (item-> getViewModelItem()->getInventoryType() == LLInventoryType::IT_CATEGORY) { // for a folder get its own bridge - folder_bridge = item->getListener(); + folder_bridge = item->getViewModelItem(); } - menu_create_inventory_item(mCurrentSelectedList->getRootFolder(), + menu_create_inventory_item(mCurrentSelectedList, dynamic_cast<LLFolderBridge*> (folder_bridge), LLSD( "category"), gInventory.findCategoryUUIDForType( LLFolderType::FT_LANDMARK)); @@ -816,7 +816,7 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const else { //in case My Landmarks tab is completely empty (thus cannot be determined as being selected) - menu_create_inventory_item(mLandmarksInventoryPanel->getRootFolder(), NULL, LLSD("category"), + menu_create_inventory_item(mLandmarksInventoryPanel, NULL, LLSD("category"), gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK)); if (mMyLandmarksAccordionTab) @@ -836,7 +836,7 @@ void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const { LLFolderViewItem* cur_item = getCurSelectedItem(); if(cur_item) - LLLandmarkActions::copySLURLtoClipboard(cur_item->getListener()->getUUID()); + LLLandmarkActions::copySLURLtoClipboard(cur_item->getViewModelItem()->getUUID()); } else if ( "paste" == command_name) { @@ -977,12 +977,12 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const { if (!root_folder_view) return false; - std::set<LLUUID> selected_uuids = root_folder_view->getSelectionList(); + std::set<LLFolderViewItem*> selected_uuids = root_folder_view->getSelectionList(); // Allow to execute the command only if it can be applied to all selected items. - for (std::set<LLUUID>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) + for (std::set<LLFolderViewItem*>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) { - LLFolderViewItem* item = root_folder_view->getItemByID(*iter); + LLFolderViewItem* item = *iter; // If no item is found it might be a folder id. if (!item) @@ -1015,7 +1015,7 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const LLFolderViewItem* cur_item = root_folder_view->getCurSelectedItem(); if (!cur_item) return false; - LLViewerInventoryItem* inv_item = cur_item->getInventoryItem(); + LLViewerInventoryItem* inv_item = static_cast<LLViewerInventoryItem*>(static_cast<LLFolderViewModelItemInventory*>(cur_item->getViewModelItem())->getInventoryObject()); if (!inv_item) return false; LLUUID asset_uuid = inv_item->getAssetUUID(); @@ -1049,7 +1049,7 @@ bool LLLandmarksPanel::isActionEnabled(const LLSD& userdata) const { if (mCurrentSelectedList) { - std::set<LLUUID> selection = mCurrentSelectedList->getRootFolder()->getSelectionList(); + std::set<LLFolderViewItem*> selection = mCurrentSelectedList->getRootFolder()->getSelectionList(); if (!selection.empty()) { return ( 1 == selection.size() && !LLAgentPicksInfo::getInstance()->isPickLimitReached() ); @@ -1105,27 +1105,23 @@ void LLLandmarksPanel::onMenuVisibilityChange(LLUICtrl* ctrl, const LLSD& param) { const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - std::set<LLUUID> selected_uuids = root_folder_view->getSelectionList(); + std::set<LLFolderViewItem*> selected_uuids = root_folder_view->getSelectionList(); // Iterate through selected items to find out if any of these items are in Trash // or all the items are in Trash category. - for (std::set<LLUUID>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) + for (std::set<LLFolderViewItem*>::const_iterator iter = selected_uuids.begin(); iter != selected_uuids.end(); ++iter) { - LLFolderViewItem* item = root_folder_view->getItemByID(*iter); + LLFolderViewItem* item = *iter; // If no item is found it might be a folder id. - if (!item) - { - item = root_folder_view->getFolderByID(*iter); - } if (!item) continue; - LLFolderViewEventListener* listenerp = item->getListener(); + LLFolderViewModelItem* listenerp = item->getViewModelItem(); if(!listenerp) continue; // Trash category itself should not be included because it can't be // actually restored from trash. - are_all_items_in_trash &= listenerp->isItemInTrash() && *iter != trash_id; + are_all_items_in_trash &= listenerp->isItemInTrash() && (*iter)->getItemViewModel()->getUUID() != trash_id; // If there are any selected items in Trash including the Trash category itself // we show "Restore Item" in context menu and hide other irrelevant items. @@ -1164,7 +1160,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold bool can_be_modified = false; // landmarks can be modified in any other accordion... - if (item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK) + if (item->getViewModelItem()->getInventoryType() == LLInventoryType::IT_LANDMARK) { can_be_modified = true; @@ -1202,7 +1198,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold if (can_be_modified) { - LLFolderViewEventListener* listenerp = item->getListener(); + LLFolderViewModelItemInventory* listenerp = item->getViewModelItem(); if ("cut" == command_name) { @@ -1262,8 +1258,9 @@ bool LLLandmarksPanel::handleDragAndDropToTrash(BOOL drop, EDragAndDropType carg LLInventoryItem* item = static_cast<LLInventoryItem*>(cargo_data); if (item) { - LLFolderViewItem* fv_item = (mCurrentSelectedList && mCurrentSelectedList->getRootFolder()) ? - mCurrentSelectedList->getRootFolder()->getItemByID(item->getUUID()) : NULL; + LLFolderViewItem* fv_item = mCurrentSelectedList + ? mCurrentSelectedList->getItemByID(item->getUUID()) + : NULL; if (fv_item) { @@ -1391,7 +1388,7 @@ void LLLandmarksPanel::doCreatePick(LLLandmark* landmark) static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::string& string) { // When search is cleared, restore the old folder state. - if (!inventory_list->getRootFolder()->getFilterSubString().empty() && string == "") + if (!inventory_list->getFilterSubString().empty() && string == "") { inventory_list->setFilterSubString(LLStringUtil::null); // Re-open folders that were open before @@ -1405,7 +1402,7 @@ static void filter_list(LLPlacesInventoryPanel* inventory_list, const std::strin } // save current folder open state if no filter currently applied - if (inventory_list->getRootFolder()->getFilterSubString().empty()) + if (inventory_list->getFilterSubString().empty()) { inventory_list->saveFolderState(); } diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index c11597f532..fbdbce61bd 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -53,6 +53,7 @@ #include "llviewermenu.h" #include "llviewertexturelist.h" #include "llsidepanelinventory.h" +#include "llfolderview.h" const std::string FILTERS_FILENAME("filters.xml"); @@ -171,7 +172,10 @@ BOOL LLPanelMainInventory::postBuild() { LLSD recent_items = savedFilterState.get( recent_items_panel->getFilter()->getName()); - recent_items_panel->getFilter()->fromLLSD(recent_items); + LLInventoryFilter::Params p; + LLParamSDParser parser; + parser.readSD(recent_items, p); + recent_items_panel->getFilter()->fromParams(p); } } @@ -212,22 +216,23 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) if (filter) { LLSD filterState; - filter->toLLSD(filterState); + LLInventoryFilter::Params p; + filter->toParams(p); + if (p.validateBlock(false)) + { + LLParamSDParser().writeSD(filterState, p); filterRoot[filter->getName()] = filterState; } } + } - LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items"); - if (recent_items_panel) - { - LLInventoryFilter* filter = recent_items_panel->getFilter(); + LLInventoryFilter* filter = getChild<LLInventoryPanel>("Recent Items")->getFilter(); if (filter) { LLSD filterState; filter->toLLSD(filterState); filterRoot[filter->getName()] = filterState; } - } std::ostringstream filterSaveName; filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME); @@ -306,7 +311,7 @@ void LLPanelMainInventory::newWindow() void LLPanelMainInventory::doCreate(const LLSD& userdata) { - menu_create_inventory_item(getPanel()->getRootFolder(), NULL, userdata); + menu_create_inventory_item(getPanel(), NULL, userdata); } void LLPanelMainInventory::resetFilters() @@ -417,7 +422,7 @@ void LLPanelMainInventory::onFilterEdit(const std::string& search_string ) } // save current folder open state if no filter currently applied - if (!mActivePanel->getRootFolder()->isFilterModified()) + if (!mActivePanel->getFilter()->isNotDefault()) { mSavedFolderState->setApply(FALSE); mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -972,7 +977,7 @@ void LLPanelMainInventory::saveTexture(const LLSD& userdata) return; } - const LLUUID& item_id = current_item->getListener()->getUUID(); + const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item_id), TAKE_FOCUS_YES); if (preview_texture) { @@ -1045,7 +1050,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { return; } - const LLUUID item_id = current_item->getListener()->getUUID(); + const LLUUID item_id = current_item->getViewModelItem()->getUUID(); LLViewerInventoryItem *item = gInventory.getItem(item_id); if (item) { @@ -1060,7 +1065,7 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { return; } - current_item->getListener()->performAction(getActivePanel()->getModel(), "goto"); + current_item->getViewModelItem()->performAction(getActivePanel()->getModel(), "goto"); } if (command_name == "find_links") @@ -1070,8 +1075,8 @@ void LLPanelMainInventory::onCustomAction(const LLSD& userdata) { return; } - const LLUUID& item_id = current_item->getListener()->getUUID(); - const std::string &item_name = current_item->getListener()->getName(); + const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); + const std::string &item_name = current_item->getViewModelItem()->getName(); mFilterSubString = item_name; LLInventoryFilter *filter = mActivePanel->getFilter(); filter->setFilterSubString(item_name); @@ -1089,11 +1094,11 @@ bool LLPanelMainInventory::isSaveTextureEnabled(const LLSD& userdata) LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (current_item) { - LLViewerInventoryItem *inv_item = current_item->getInventoryItem(); + LLViewerInventoryItem *inv_item = dynamic_cast<LLViewerInventoryItem*>(static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getInventoryObject()); if(inv_item) { bool can_save = inv_item->checkPermissionsSet(PERM_ITEM_UNRESTRICTED); - LLInventoryType::EType curr_type = current_item->getListener()->getInventoryType(); + LLInventoryType::EType curr_type = static_cast<LLFolderViewModelItemInventory*>(current_item->getViewModelItem())->getInventoryType(); return can_save && (curr_type == LLInventoryType::IT_TEXTURE || curr_type == LLInventoryType::IT_SNAPSHOT); } } @@ -1110,15 +1115,15 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) if (root) { can_delete = TRUE; - std::set<LLUUID> selection_set = root->getSelectionList(); + std::set<LLFolderViewItem*> selection_set = root->getSelectionList(); if (selection_set.empty()) return FALSE; - for (std::set<LLUUID>::iterator iter = selection_set.begin(); + for (std::set<LLFolderViewItem*>::iterator iter = selection_set.begin(); iter != selection_set.end(); ++iter) { const LLUUID &item_id = (*iter); - LLFolderViewItem *item = root->getItemByID(item_id); - const LLFolderViewEventListener *listener = item->getListener(); + LLFolderViewItem *item = *iter; + const LLFolderViewModelItemInventory *listener = item->getViewModelItem(); llassert(listener); if (!listener) return FALSE; can_delete &= listener->isItemRemovable(); @@ -1136,7 +1141,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) return FALSE; - const LLUUID& item_id = current_item->getListener()->getUUID(); + const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); const LLViewerInventoryItem *item = gInventory.getItem(item_id); if (item && item->getIsLinkType() && !item->getIsBrokenLink()) { @@ -1148,11 +1153,11 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) if (command_name == "find_links") { LLFolderView* root = getActivePanel()->getRootFolder(); - std::set<LLUUID> selection_set = root->getSelectionList(); + std::set<LLFolderViewItem*> selection_set = root->getSelectionList(); if (selection_set.size() != 1) return FALSE; LLFolderViewItem* current_item = root->getCurSelectedItem(); if (!current_item) return FALSE; - const LLUUID& item_id = current_item->getListener()->getUUID(); + const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); const LLInventoryObject *obj = gInventory.getObject(item_id); if (obj && !obj->getIsLinkType() && LLAssetType::lookupCanLink(obj->getType())) { @@ -1165,7 +1170,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata) { LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem(); if (!current_item) return FALSE; - const LLUUID& item_id = current_item->getListener()->getUUID(); + const LLUUID& item_id = current_item->getViewModelItem()->getUUID(); const LLViewerInventoryItem *item = gInventory.getItem(item_id); if (item && item->getIsBrokenLink()) { diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp index 66c9c323cb..8a07d6d516 100644 --- a/indra/newview/llpanelmarketplaceinbox.cpp +++ b/indra/newview/llpanelmarketplaceinbox.cpp @@ -94,7 +94,7 @@ LLInventoryPanel * LLPanelMarketplaceInbox::setupInventoryPanel() mInventoryPanel->setShape(inventory_placeholder_rect); // Set the sort order newest to oldest - mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE); + mInventoryPanel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_DATE); mInventoryPanel->getFilter()->markDefault(); // Set selection callback for proper update of inventory status buttons @@ -139,12 +139,12 @@ U32 LLPanelMarketplaceInbox::getFreshItemCount() const if (mInventoryPanel) { - const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder(); + LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder(); if (inbox_folder) { - LLFolderViewFolder::folders_t::const_iterator folders_it = inbox_folder->getFoldersBegin(); - LLFolderViewFolder::folders_t::const_iterator folders_end = inbox_folder->getFoldersEnd(); + LLFolderViewFolder::folders_t::iterator folders_it = inbox_folder->getFoldersBegin(); + LLFolderViewFolder::folders_t::iterator folders_end = inbox_folder->getFoldersEnd(); for (; folders_it != folders_end; ++folders_it) { @@ -157,8 +157,8 @@ U32 LLPanelMarketplaceInbox::getFreshItemCount() const } } - LLFolderViewFolder::items_t::const_iterator items_it = inbox_folder->getItemsBegin(); - LLFolderViewFolder::items_t::const_iterator items_end = inbox_folder->getItemsEnd(); + LLFolderViewFolder::items_t::iterator items_it = inbox_folder->getItemsBegin(); + LLFolderViewFolder::items_t::iterator items_end = inbox_folder->getItemsEnd(); for (; items_it != items_end; ++items_it) { diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index 678e4f2843..1d079adfd3 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -29,6 +29,7 @@ #include "llpanelmarketplaceinboxinventory.h" #include "llfolderview.h" +#include "llfolderviewitem.h" #include "llfoldervieweventlistener.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" @@ -253,9 +254,9 @@ LLInboxFolderViewItem::LLInboxFolderViewItem(const Params& p) #endif } -BOOL LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* root) +BOOL LLInboxFolderViewItem::addToFolder(LLFolderViewFolder* folder) { - BOOL retval = LLFolderViewItem::addToFolder(folder, root); + BOOL retval = LLFolderViewItem::addToFolder(folder); #if SUPPORTING_FRESH_ITEM_COUNT // Compute freshness if our parent is the root folder for the inbox diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h index d6b827ee3e..209f3a4098 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.h +++ b/indra/newview/llpanelmarketplaceinboxinventory.h @@ -81,8 +81,6 @@ public: bool isFresh() const { return mFresh; } protected: - void setCreationDate(time_t creation_date_utc); - bool mFresh; }; @@ -102,7 +100,7 @@ public: LLInboxFolderViewItem(const Params& p); - BOOL addToFolder(LLFolderViewFolder* folder, LLFolderView* root); + BOOL addToFolder(LLFolderViewFolder* folder); BOOL handleDoubleClick(S32 x, S32 y, MASK mask); void draw(); diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp index ff62cb23db..7db01d9059 100644 --- a/indra/newview/llpanelmarketplaceoutboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceoutboxinventory.cpp @@ -28,8 +28,8 @@ #include "llpanelmarketplaceoutboxinventory.h" -#include "llfolderview.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewitem.h" +#include "llfolderviewmodel.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llpanellandmarks.h" diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index f84d6e5cc1..ae68b5ce95 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -71,7 +71,7 @@ /// Class LLTaskInvFVBridge ///---------------------------------------------------------------------------- -class LLTaskInvFVBridge : public LLFolderViewEventListener +class LLTaskInvFVBridge : public LLFolderViewModelItemInventory { protected: LLUUID mUUID; @@ -102,7 +102,7 @@ public: S32 getPrice(); static bool commitBuyItem(const LLSD& notification, const LLSD& response); - // LLFolderViewEventListener functionality + // LLFolderViewModelItemInventory functionality virtual const std::string& getName() const; virtual const std::string& getDisplayName() const; virtual PermissionMask getPermissionMask() const { return PERM_NONE; } @@ -113,15 +113,14 @@ public: virtual void openItem(); virtual BOOL canOpenItem() const { return FALSE; } virtual void closeItem() {} - virtual void previewItem(); virtual void selectItem() {} virtual BOOL isItemRenameable() const; virtual BOOL renameItem(const std::string& new_name); virtual BOOL isItemMovable() const; virtual BOOL isItemRemovable() const; virtual BOOL removeItem(); - virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch); - virtual void move(LLFolderViewEventListener* parent_listener); + virtual void removeBatch(std::vector<LLFolderViewModelItem*>& batch); + virtual void move(LLFolderViewModelItem* parent_listener); virtual BOOL isItemCopyable() const; virtual BOOL copyToClipboard() const; virtual BOOL cutToClipboard() const; @@ -352,11 +351,6 @@ void LLTaskInvFVBridge::openItem() lldebugs << "LLTaskInvFVBridge::openItem()" << llendl; } -void LLTaskInvFVBridge::previewItem() -{ - openItem(); -} - BOOL LLTaskInvFVBridge::isItemRenameable() const { if(gAgent.isGodlike()) return TRUE; @@ -467,7 +461,7 @@ BOOL LLTaskInvFVBridge::removeItem() return FALSE; } -void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) +void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewModelItem*>& batch) { if (!mPanel) { @@ -507,7 +501,7 @@ void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& } } -void LLTaskInvFVBridge::move(LLFolderViewEventListener* parent_listener) +void LLTaskInvFVBridge::move(LLFolderViewModelItem* parent_listener) { } @@ -1548,7 +1542,8 @@ void LLPanelObjectInventory::reset() p.folder_indentation = -14; // subtract space normally reserved for folder expanders mFolders = LLUICtrlFactory::create<LLFolderView>(p); // this ensures that we never say "searching..." or "no items found" - mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); + //TODO RN: make this happen by manipulating filter object directly + //mFolders->getFilter()->setShowFolderState(LLInventoryFilter::SHOW_ALL_FOLDERS); mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); if (hasFocus()) @@ -1608,7 +1603,7 @@ void LLPanelObjectInventory::updateInventory() // << " panel UUID: " << panel->mTaskUUID << "\n" // << " task UUID: " << object->mID << llendl; // We're still interested in this task's inventory. - std::set<LLUUID> selected_items; + std::set<LLFolderViewItem*> selected_items; BOOL inventory_has_focus = FALSE; if (mHaveInventory) { @@ -1646,11 +1641,11 @@ void LLPanelObjectInventory::updateInventory() } // restore previous selection - std::set<LLUUID>::iterator selection_it; + std::set<LLFolderViewItem*>::iterator selection_it; BOOL first_item = TRUE; for (selection_it = selected_items.begin(); selection_it != selected_items.end(); ++selection_it) { - LLFolderViewItem* selected_item = mFolders->getItemByID(*selection_it); + LLFolderViewItem* selected_item = (*selection_it); if (selected_item) { //HACK: "set" first item then "change" each other one to get keyboard focus right @@ -1752,7 +1747,8 @@ void LLPanelObjectInventory::createViewsForCategory(LLInventoryObject::object_li params.tool_tip = params.name; view = LLUICtrlFactory::create<LLFolderViewItem> (params); } - view->addToFolder(folder, mFolders); + view->addToFolder(folder); + addItemID(view->getViewModelItem()->getUUID(), view); } } diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index 35e2e96bab..a95d27f992 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -270,7 +270,7 @@ private: if (inventory_panel->getVisible()) { - inventory_panel->setSortOrder(sort_order); + inventory_panel->getFolderViewModel()->setSorter(sort_order); } else { @@ -738,7 +738,7 @@ void LLPanelOutfitEdit::onSearchEdit(const std::string& string) } // save current folder open state if no filter currently applied - if (mInventoryItemsPanel->getRootFolder()->getFilterSubString().empty()) + if (mInventoryItemsPanel->getFilterSubString().empty()) { mSavedFolderState->setApply(FALSE); mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -885,13 +885,13 @@ LLPanelOutfitEdit::selection_info_t LLPanelOutfitEdit::getAddMorePanelSelectionT { if (mInventoryItemsPanel != NULL && mInventoryItemsPanel->getVisible()) { - std::set<LLUUID> selected_uuids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); + std::set<LLFolderViewItem*> selected_items = mInventoryItemsPanel->getRootFolder()->getSelectionList(); - result.second = selected_uuids.size(); + result.second = selected_items.size(); if (result.second == 1) { - result.first = getWearableTypeByItemUUID(*(selected_uuids.begin())); + result.first = getWearableTypeByItemUUID((*selected_items.begin())->getListener()->getUUID()); } } else if (mWearableItemsList != NULL && mWearableItemsList->getVisible()) @@ -1310,7 +1310,7 @@ void LLPanelOutfitEdit::getCurrentItemUUID(LLUUID& selected_id) LLFolderViewItem* curr_item = mInventoryItemsPanel->getRootFolder()->getCurSelectedItem(); if (!curr_item) return; - LLFolderViewEventListener* listenerp = curr_item->getListener(); + LLFolderViewModelItemInventory* listenerp = curr_item->getViewModelItem(); if (!listenerp) return; selected_id = listenerp->getUUID(); @@ -1327,9 +1327,13 @@ void LLPanelOutfitEdit::getSelectedItemsUUID(uuid_vec_t& uuid_list) void (uuid_vec_t::* tmp)(LLUUID const &) = &uuid_vec_t::push_back; if (mInventoryItemsPanel->getVisible()) { - std::set<LLUUID> item_set = mInventoryItemsPanel->getRootFolder()->getSelectionList(); - - std::for_each(item_set.begin(), item_set.end(), boost::bind( tmp, &uuid_list, _1)); + std::set<LLFolderViewItem*> item_set = mInventoryItemsPanel->getRootFolder()->getSelectionList(); + for (std::set<LLFolderViewItem*>::iterator it = item_set.begin(), end_it = item_set.end(); + it != end_it; + ++it) + { + uuid_list.push_back((*it)->getItemViewModel()->getUUID()); + } } else if (mWearablesListViewPanel->getVisible()) { @@ -1374,13 +1378,13 @@ void LLPanelOutfitEdit::saveListSelection() { if(mWearablesListViewPanel->getVisible()) { - std::set<LLUUID> selected_ids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); + std::set<LLFolderViewItem*> selected_ids = mInventoryItemsPanel->getRootFolder()->getSelectionList(); if(!selected_ids.size()) return; - for (std::set<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) + for (std::set<LLFolderViewItem*>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) { - mWearableItemsList->selectItemByUUID(*item_id, true); + mWearableItemsList->selectItemByUUID((*item_id)->getItemViewModel()->getUUID(), true); } mWearableItemsList->scrollToShowFirstSelectedItem(); } @@ -1398,7 +1402,7 @@ void LLPanelOutfitEdit::saveListSelection() for(std::vector<LLUUID>::const_iterator item_id = selected_ids.begin(); item_id != selected_ids.end(); ++item_id) { - LLFolderViewItem* item = root->getItemByID(*item_id); + LLFolderViewItem* item = mInventoryItemsPanel->getItemByID(*item_id); if (!item) continue; LLFolderViewFolder* parent = item->getParentFolder(); diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index fe4cc0f55f..97c5d531d2 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -85,34 +85,33 @@ void LLPlacesLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) void LLPlacesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { + std::vector<std::string> items; + std::vector<std::string> disabled_items; + + LLInventoryPanel* inv_panel = mInventoryPanel.get(); + bool is_open = false; + if (inv_panel) { - std::vector<std::string> items; - std::vector<std::string> disabled_items; + LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getItemByID(mUUID)); + is_open = (NULL != folder) && folder->isOpen(); + } - LLInventoryPanel* inv_panel = mInventoryPanel.get(); - bool is_open = false; - if (inv_panel) - { - LLFolderViewFolder* folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID)); - is_open = (NULL != folder) && folder->isOpen(); - } + // collect all items' names + fill_items_with_menu_items(items, menu); - // collect all items' names - fill_items_with_menu_items(items, menu); + // remove expand or collapse menu item depend on folder state + std::string collapse_expand_item_to_hide(is_open ? "expand" : "collapse"); + std::vector<std::string>::iterator it = std::find(items.begin(), items.end(), collapse_expand_item_to_hide); + if (it != items.end()) items.erase(it); - // remove expand or collapse menu item depend on folder state - std::string collapse_expand_item_to_hide(is_open ? "expand" : "collapse"); - std::vector<std::string>::iterator it = std::find(items.begin(), items.end(), collapse_expand_item_to_hide); - if (it != items.end()) items.erase(it); - // Disabled items are processed via LLLandmarksPanel::isActionEnabled() - // they should be synchronized with Places/My Landmarks/Gear menu. See EXT-1601 + // Disabled items are processed via LLLandmarksPanel::isActionEnabled() + // they should be synchronized with Places/My Landmarks/Gear menu. See EXT-1601 - // repeat parent functionality - sSelf = getHandle(); // necessary for "New Folder" functionality + // repeat parent functionality + sSelf = getHandle(); // necessary for "New Folder" functionality - hide_context_entries(menu, items, disabled_items); - } + hide_context_entries(menu, items, disabled_items); } //virtual @@ -140,7 +139,7 @@ LLFolderViewFolder* LLPlacesFolderBridge::getFolder() LLInventoryPanel* inv_panel = mInventoryPanel.get(); if (inv_panel) { - folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID)); + folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getItemByID(mUUID)); } return folder; diff --git a/indra/newview/llplacesinventorypanel.cpp b/indra/newview/llplacesinventorypanel.cpp index f7823f4fe8..da5ce7d4b7 100644 --- a/indra/newview/llplacesinventorypanel.cpp +++ b/indra/newview/llplacesinventorypanel.cpp @@ -30,7 +30,8 @@ #include "llplacesinventorypanel.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" +#include "llfolderview.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llpanellandmarks.h" @@ -91,7 +92,7 @@ void LLPlacesInventoryPanel::buildFolderView(const LLInventoryPanel::Params& par p.parent_panel = this; p.allow_multiselect = mAllowMultiSelect; p.use_ellipses = true; // truncate inventory item text so remove horizontal scroller - mFolderRoot = (LLFolderView*)LLUICtrlFactory::create<LLPlacesFolderView>(p); + mFolderRoot = LLUICtrlFactory::create<LLPlacesFolderView>(p); } @@ -161,7 +162,7 @@ BOOL LLPlacesFolderView::handleRightMouseDown(S32 x, S32 y, MASK mask) // then determine its type and set necessary menu handle if (getCurSelectedItem()) { - LLInventoryType::EType inventory_type = getCurSelectedItem()->getListener()->getInventoryType(); + LLInventoryType::EType inventory_type = getCurSelectedItem()->getViewModelItem()->getInventoryType(); inventory_type_menu_handle_t::iterator it_handle = mMenuHandlesByInventoryType.find(inventory_type); if (it_handle != mMenuHandlesByInventoryType.end()) diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 853656905c..194aa7f71b 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -38,7 +38,7 @@ #include "llfiltereditor.h" #include "llfloaterreg.h" #include "llfloaterworldmap.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" #include "lloutfitobserver.h" #include "llpaneleditwearable.h" #include "llpaneloutfitsinventory.h" @@ -267,7 +267,7 @@ void LLSidepanelAppearance::onOpenOutfitButtonClicked() if (inventory_panel) { LLFolderView* root = inventory_panel->getRootFolder(); - LLFolderViewItem *outfit_folder = root->getItemByID(outfit_link->getLinkedUUID()); + LLFolderViewItem *outfit_folder = inventory_panel->getItemByID(outfit_link->getLinkedUUID()); if (outfit_folder) { outfit_folder->setOpen(!outfit_folder->isOpen()); diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 4f9ab318a5..f3d32e7a67 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -36,6 +36,7 @@ #include "llfirstuse.h" #include "llfloatersidepanelcontainer.h" #include "llfoldertype.h" +#include "llfolderview.h" #include "llhttpclient.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" @@ -383,10 +384,10 @@ void LLSidepanelInventory::onToggleInboxBtn() { inboxPanel->setTargetDim(gSavedPerAccountSettings.getS32("InventoryInboxHeight")); if (inboxPanel->isInVisibleChain()) - { - gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); - } + { + gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); } +} else { gSavedPerAccountSettings.setS32("InventoryInboxHeight", inboxPanel->getTargetDim()); @@ -472,7 +473,7 @@ void LLSidepanelInventory::performActionOnSelection(const std::string &action) } } - current_item->getListener()->performAction(mPanelMainInventory->getActivePanel()->getModel(), action); + current_item->getViewModelItem()->performAction(mPanelMainInventory->getActivePanel()->getModel(), action); } void LLSidepanelInventory::onWearButtonClicked() @@ -662,7 +663,7 @@ LLInventoryItem *LLSidepanelInventory::getSelectedItem() return NULL; } } - const LLUUID &item_id = current_item->getListener()->getUUID(); + const LLUUID &item_id = current_item->getViewModelItem()->getUUID(); LLInventoryItem *item = gInventory.getItem(item_id); return item; } @@ -671,7 +672,7 @@ U32 LLSidepanelInventory::getSelectedCount() { int count = 0; - std::set<LLUUID> selection_list = mPanelMainInventory->getActivePanel()->getRootFolder()->getSelectionList(); + std::set<LLFolderViewItem*> selection_list = mPanelMainInventory->getActivePanel()->getRootFolder()->getSelectionList(); count += selection_list.size(); if ((count == 0) && mInboxEnabled && (mInventoryPanelInbox != NULL)) @@ -722,9 +723,9 @@ void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox) updateVerbs(); } -std::set<LLUUID> LLSidepanelInventory::getInboxSelectionList() +std::set<LLFolderViewItem*> LLSidepanelInventory::getInboxSelectionList() { - std::set<LLUUID> inventory_selected_uuids; + std::set<LLFolderViewItem*> inventory_selected_uuids; if (mInboxEnabled && (mInventoryPanelInbox != NULL)) { diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h index a33607f50d..e8b2808d4f 100644 --- a/indra/newview/llsidepanelinventory.h +++ b/indra/newview/llsidepanelinventory.h @@ -63,7 +63,7 @@ public: BOOL isMainInventoryPanelActive() const; void clearSelections(bool clearMain, bool clearInbox); - std::set<LLUUID> getInboxSelectionList(); + std::set<LLFolderViewItem*> getInboxSelectionList(); void showItemInfoPanel(); void showTaskInfoPanel(); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index ed9faa0706..a995f07df7 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -39,7 +39,7 @@ #include "llfocusmgr.h" #include "llviewertexture.h" #include "llfolderview.h" -#include "llfoldervieweventlistener.h" +#include "llfolderviewmodel.h" #include "llinventory.h" #include "llinventoryfunctions.h" #include "llinventorymodelbackgroundfetch.h" @@ -181,7 +181,7 @@ protected: F32 mContextConeOpacity; LLSaveFolderState mSavedFolderState; BOOL mSelectedItemPinned; - + LLRadioGroup* mModeSelector; LLScrollListCtrl* mLocalScrollCtrl; }; @@ -358,7 +358,7 @@ BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask) { if (!root_folder->getCurSelectedItem()) { - LLFolderViewItem* itemp = root_folder->getItemByID(gInventory.getRootFolderID()); + LLFolderViewItem* itemp = mInventoryPanel->getItemByID(gInventory.getRootFolderID()); if (itemp) { root_folder->setSelection(itemp, FALSE, FALSE); @@ -800,7 +800,7 @@ void LLFloaterTexturePicker::onSelectionChange(const std::deque<LLFolderViewItem if (items.size()) { LLFolderViewItem* first_item = items.front(); - LLInventoryItem* itemp = gInventory.getItem(first_item->getListener()->getUUID()); + LLInventoryItem* itemp = gInventory.getItem(first_item->getViewModelItem()->getUUID()); mNoCopyTextureSelected = FALSE; if (itemp) { @@ -982,7 +982,7 @@ void LLFloaterTexturePicker::onFilterEdit(const std::string& search_string ) else if (mInventoryPanel->getFilterSubString().empty()) { // first letter in search term, save existing folder open state - if (!mInventoryPanel->getRootFolder()->isFilterModified()) + if (!mInventoryPanel->getFilter()->isNotDefault()) { mSavedFolderState.setApply(FALSE); mInventoryPanel->getRootFolder()->applyFunctorRecursively(mSavedFolderState); @@ -1280,7 +1280,7 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id) // (i.e. op == TEXTURE_SELECT) or texture changes via DnD. else if (mCommitOnSelection || op == TEXTURE_SELECT) mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? - + if(floaterp->isDirty() || id.notNull()) // mModelView->setDirty does not work. { setTentative( FALSE ); @@ -1292,10 +1292,10 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id) } else { - mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE); - lldebugs << "mImageItemID: " << mImageItemID << llendl; - mImageAssetID = floaterp->getAssetID(); - lldebugs << "mImageAssetID: " << mImageAssetID << llendl; + mImageItemID = floaterp->findItemID(floaterp->getAssetID(), FALSE); + lldebugs << "mImageItemID: " << mImageItemID << llendl; + mImageAssetID = floaterp->getAssetID(); + lldebugs << "mImageAssetID: " << mImageAssetID << llendl; } if (op == TEXTURE_SELECT && mOnSelectCallback) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 45ca23cdfe..d827b2b8aa 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1308,7 +1308,7 @@ const std::string NEW_NOTECARD_NAME = "New Note"; // *TODO:Translate? (probably const std::string NEW_GESTURE_NAME = "New Gesture"; // *TODO:Translate? (probably not) // ! REFACTOR ! Really need to refactor this so that it's not a bunch of if-then statements... -void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid) +void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, const LLSD& userdata, const LLUUID& default_parent_uuid) { std::string type_name = userdata.asString(); @@ -1332,7 +1332,7 @@ void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, cons LLUUID category = gInventory.createNewCategory(parent_id, preferred_type, LLStringUtil::null); gInventory.notifyObservers(); - root->setSelectionByID(category, TRUE); + panel->setSelectionByID(category, TRUE); } else if ("lsl" == type_name) { @@ -1375,7 +1375,7 @@ void menu_create_inventory_item(LLFolderView* root, LLFolderBridge *bridge, cons llwarns << "Can't create unrecognized type " << type_name << llendl; } } - root->setNeedsAutoRename(TRUE); + panel->getRoot()->->setNeedsAutoRename(TRUE); } LLAssetType::EType LLViewerInventoryItem::getType() const @@ -1785,12 +1785,6 @@ void LLViewerInventoryItem::getSLURL() LLFavoritesOrderStorage::instance().getSLURL(mAssetUUID); } -const LLPermissions& LLViewerInventoryItem::getPermissions() const -{ - // Use the actual permissions of the symlink, not its parent. - return LLInventoryItem::getPermissions(); -} - const LLUUID& LLViewerInventoryItem::getCreatorUUID() const { if (const LLViewerInventoryItem *linked_item = getLinkedItem()) @@ -1861,17 +1855,6 @@ LLWearableType::EType LLViewerInventoryItem::getWearableType() const return LLWearableType::EType(getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK); } - -time_t LLViewerInventoryItem::getCreationDate() const -{ - return LLInventoryItem::getCreationDate(); -} - -U32 LLViewerInventoryItem::getCRC32() const -{ - return LLInventoryItem::getCRC32(); -} - // *TODO: mantipov: should be removed with LMSortPrefix patch in llinventorymodel.cpp, EXT-3985 static char getSeparator() { return '@'; } BOOL LLViewerInventoryItem::extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName) diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 7822ef4da6..d66362d544 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -34,7 +34,7 @@ #include <boost/signals2.hpp> // boost::signals2::trackable -class LLFolderView; +class LLInventoryPanel; class LLFolderBridge; class LLViewerInventoryCategory; @@ -63,7 +63,6 @@ public: virtual S32 getSortField() const; virtual void setSortField(S32 sortField); virtual void getSLURL(); //Caches SLURL for landmark. //*TODO: Find a better way to do it and remove this method from here. - virtual const LLPermissions& getPermissions() const; virtual const bool getIsFullPerm() const; // 'fullperm' in the popular sense: modify-ok & copy-ok & transfer-ok, no special god rules applied virtual const LLUUID& getCreatorUUID() const; virtual const std::string& getDescription() const; @@ -72,8 +71,11 @@ public: virtual bool isWearableType() const; virtual LLWearableType::EType getWearableType() const; virtual U32 getFlags() const; - virtual time_t getCreationDate() const; - virtual U32 getCRC32() const; // really more of a checksum. + + using LLInventoryItem::getPermissions; + using LLInventoryItem::getCreationDate; + using LLInventoryItem::setCreationDate; + using LLInventoryItem::getCRC32; static BOOL extractSortFieldAndDisplayName(const std::string& name, S32* sortField, std::string* displayName); @@ -372,7 +374,7 @@ void copy_inventory_from_notecard(const LLUUID& destination_id, U32 callback_id = 0); -void menu_create_inventory_item(LLFolderView* root, +void menu_create_inventory_item(LLInventoryPanel* root, LLFolderBridge* bridge, const LLSD& userdata, const LLUUID& default_parent_uuid = LLUUID::null); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index dd78bbd491..90d144b458 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -728,7 +728,7 @@ static void highlight_inventory_objects_in_panel(const std::vector<LLUUID>& item LLFolderView* fv = inventory_panel->getRootFolder(); if (fv) { - LLFolderViewItem* fv_item = fv->getItemByID(item_id); + LLFolderViewItem* fv_item = inventory_panel->getItemByID(item_id); if (fv_item) { LLFolderViewItem* fv_folder = fv_item->getParentFolder(); @@ -816,7 +816,13 @@ private: mSelectedItems.clear(); if (LLInventoryPanel::getActiveInventoryPanel()) { - mSelectedItems = LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); + std::set<LLFolderViewItem*> selection = LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); + for (std::set<LLFolderViewItem*>::iterator it = selection.begin(), end_it = selection.end(); + it != end_it; + ++it) + { + mSelectedItems.insert((*it)->getListener()->getUUID()); + } } mSelectedItems.erase(mMoveIntoFolderID); } @@ -851,7 +857,15 @@ private: } // get selected items (without destination folder) - selected_items_t selected_items = active_panel->getRootFolder()->getSelectionList(); + selected_items_t selected_items; + + std::set<LLFolderViewItem*> selection = LLInventoryPanel::getActiveInventoryPanel()->getRootFolder()->getSelectionList(); + for (std::set<LLFolderViewItem*>::iterator it = selection.begin(), end_it = selection.end(); + it != end_it; + ++it) + { + selected_items.insert((*it)->getListener()->getUUID()); + } selected_items.erase(mMoveIntoFolderID); // compare stored & current sets of selected items |