summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llui/llfolderview.h2
-rw-r--r--indra/newview/app_settings/settings_per_account.xml11
-rw-r--r--indra/newview/llinventorybridge.cpp52
-rw-r--r--indra/newview/llinventorymodel.cpp5
-rw-r--r--indra/newview/llinventorypanel.cpp96
-rw-r--r--indra/newview/llinventorypanel.h21
-rw-r--r--indra/newview/llpanelmaininventory.cpp12
-rw-r--r--indra/newview/llpanelmaininventory.h2
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory.xml7
-rw-r--r--indra/newview/skins/default/xui/en/panel_main_inventory.xml40
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml1
11 files changed, 225 insertions, 24 deletions
diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h
index 6bb5e6c02e..c175034d75 100644
--- a/indra/llui/llfolderview.h
+++ b/indra/llui/llfolderview.h
@@ -241,6 +241,8 @@ public:
void dumpSelectionInformation();
virtual S32 notify(const LLSD& info) ;
+
+ void setShowEmptyMessage(bool show_msg) { mShowEmptyMessage = show_msg; }
bool useLabelSuffix() { return mUseLabelSuffix; }
virtual void updateMenu();
diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml
index 8f4ca6c633..5eecf1b9f5 100644
--- a/indra/newview/app_settings/settings_per_account.xml
+++ b/indra/newview/app_settings/settings_per_account.xml
@@ -392,6 +392,17 @@
<key>Value</key>
<string></string>
</map>
+ <key>FavoritesFolder</key>
+ <map>
+ <key>Comment</key>
+ <string>User's chosen folder which will be shown in the Favorites tab (UUID)</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string></string>
+ </map>
<key>SnapshotBaseDir</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 657c65c68d..03123689c5 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -138,6 +138,35 @@ bool isMarketplaceSendAction(const std::string& action)
return ("send_to_marketplace" == action);
}
+bool isPanelActive(const std::string& panel_name)
+{
+ LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
+ return (active_panel && (active_panel->getName() == panel_name));
+}
+
+bool isParentSystemFolder(const LLInventoryModel* model, const LLUUID& folder_id)
+{
+ if (!model || folder_id.isNull()) return false;
+
+ LLViewerInventoryCategory* cat = model->getCategory(folder_id);
+ if (cat)
+ {
+ if (cat->getPreferredType() == LLFolderType::FT_ROOT_INVENTORY)
+ {
+ return false;
+ }
+ if (LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
+ {
+ return true;
+ }
+ else
+ {
+ return isParentSystemFolder(model, cat->getParentUUID());
+ }
+ }
+ return false;
+}
+
// Used by LLFolderBridge as callback for directory fetching recursion
class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
{
@@ -888,8 +917,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
disabled_items.push_back(std::string("Properties"));
}
- LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
- if (active_panel && (active_panel->getName() != "All Items"))
+ if (!isPanelActive("All Items"))
{
items.push_back(std::string("Show in Main Panel"));
}
@@ -980,7 +1008,7 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items,
items.push_back(std::string("Delete"));
- if (!isItemRemovable())
+ if (!isItemRemovable() || isPanelActive("Favorite Items"))
{
disabled_items.push_back(std::string("Delete"));
}
@@ -4010,6 +4038,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
disabled_items.push_back(std::string("New Clothes"));
disabled_items.push_back(std::string("New Body Parts"));
disabled_items.push_back(std::string("upload_def"));
+ disabled_items.push_back(std::string("Set Favorites folder"));
}
if (favorites == mUUID)
{
@@ -4037,6 +4066,7 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
disabled_items.push_back(std::string("New Clothes"));
disabled_items.push_back(std::string("New Body Parts"));
disabled_items.push_back(std::string("upload_def"));
+ disabled_items.push_back(std::string("Set Favorites folder"));
}
if (marketplace_listings_id == mUUID)
{
@@ -4045,14 +4075,14 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
disabled_items.push_back(std::string("Cut"));
disabled_items.push_back(std::string("Delete"));
}
+
+ if (isPanelActive("Favorite Items"))
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
if(trash_id == mUUID)
{
- bool is_recent_panel = false;
- LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
- if (active_panel && (active_panel->getName() == "Recent Items"))
- {
- is_recent_panel = true;
- }
+ bool is_recent_panel = isPanelActive("Recent Items");
// This is the trash.
items.push_back(std::string("Empty Trash"));
@@ -4102,6 +4132,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items
items.push_back(std::string("New Settings"));
items.push_back(std::string("upload_def"));
+ if (!LLFolderType::lookupIsProtectedType(getPreferredType()) && !isParentSystemFolder(model, mUUID))
+ {
+ items.push_back(std::string("Set Favorites folder"));
+ }
if (!LLEnvironment::instance().isInventoryEnabled())
{
disabled_items.push_back("New Settings");
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 17e80dca89..a44a54632c 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -542,6 +542,11 @@ const LLUUID LLInventoryModel::findUserDefinedCategoryUUIDForType(LLFolderType::
cat_id = LLUUID(gSavedPerAccountSettings.getString("AnimationUploadFolder"));
break;
}
+ case LLFolderType::FT_FAVORITE:
+ {
+ cat_id = LLUUID(gSavedPerAccountSettings.getString("FavoritesFolder"));
+ break;
+ }
default:
break;
}
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index c6075b4066..8e814916ad 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -179,6 +179,7 @@ LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this));
mCommitCallbackRegistrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, this));
mCommitCallbackRegistrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryPanel::fileUploadLocation, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.SetFavoritesFolder", boost::bind(&LLInventoryPanel::setFavoritesFolder, this, _2));
}
LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id )
@@ -1374,6 +1375,11 @@ void LLInventoryPanel::fileUploadLocation(const LLSD& userdata)
}
}
+void LLInventoryPanel::setFavoritesFolder(const LLSD& userdata)
+{
+ gSavedPerAccountSettings.setString("FavoritesFolder", LLFolderBridge::sSelf.get()->getUUID().asString());
+}
+
void LLInventoryPanel::purgeSelectedItems()
{
if (!mFolderRoot.get()) return;
@@ -1753,6 +1759,96 @@ LLInventoryRecentItemsPanel::LLInventoryRecentItemsPanel( const Params& params)
mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER;
}
+static LLDefaultChildRegistry::Register<LLInventoryFavoriteItemsPanel> t_favorites_inventory_panel("favorites_inventory_panel");
+
+LLInventoryFavoriteItemsPanel::LLInventoryFavoriteItemsPanel(const Params& params)
+ : LLInventoryPanel(params)
+{
+ std::string ctrl_name = "FavoritesFolder";
+ if (gSavedPerAccountSettings.controlExists(ctrl_name))
+ {
+ LLPointer<LLControlVariable> cntrl_ptr = gSavedPerAccountSettings.getControl(ctrl_name);
+ if (cntrl_ptr.notNull())
+ {
+ mFolderChangedSignal = cntrl_ptr->getCommitSignal()->connect(boost::bind(&LLInventoryFavoriteItemsPanel::updateFavoritesRootFolder, this));
+ }
+ }
+}
+
+void LLInventoryFavoriteItemsPanel::setSelectCallback(const boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb)
+{
+ if (mFolderRoot.get())
+ {
+ mFolderRoot.get()->setSelectCallback(cb);
+ mSelectionCallback = cb;
+ }
+}
+
+void LLInventoryFavoriteItemsPanel::initFromParams(const Params& p)
+{
+ Params fav_params(p);
+ fav_params.start_folder.id = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+ LLInventoryPanel::initFromParams(fav_params);
+ updateFavoritesRootFolder();
+}
+
+void LLInventoryFavoriteItemsPanel::updateFavoritesRootFolder()
+{
+ const LLUUID& folder_id = gInventory.findUserDefinedCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+
+ bool is_favorites_set = (folder_id != gInventory.findCategoryUUIDForTypeInRoot(LLFolderType::FT_FAVORITE, true, gInventory.getRootFolderID()));
+
+ if (!is_favorites_set || folder_id != getRootFolderID())
+ {
+ LLUUID root_id = folder_id;
+ if (mFolderRoot.get())
+ {
+ removeItemID(getRootFolderID());
+ mFolderRoot.get()->destroyView();
+ }
+
+ mCommitCallbackRegistrar.pushScope();
+ {
+ LLFolderView* folder_view = createFolderRoot(root_id);
+ mFolderRoot = folder_view->getHandle();
+
+ addItemID(root_id, mFolderRoot.get());
+
+
+ LLRect scroller_view_rect = getRect();
+ scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
+ LLScrollContainer::Params scroller_params(mParams.scroll());
+ scroller_params.rect(scroller_view_rect);
+
+ if (mScroller)
+ {
+ removeChild(mScroller);
+ delete mScroller;
+ mScroller = NULL;
+ }
+ mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params);
+ addChild(mScroller);
+ mScroller->addChild(mFolderRoot.get());
+ mFolderRoot.get()->setScrollContainer(mScroller);
+ mFolderRoot.get()->setFollowsAll();
+ mFolderRoot.get()->addChild(mFolderRoot.get()->mStatusTextBox);
+
+ if (!mSelectionCallback.empty())
+ {
+ mFolderRoot.get()->setSelectCallback(mSelectionCallback);
+ }
+ }
+ mCommitCallbackRegistrar.popScope();
+ mFolderRoot.get()->setCallbackRegistrar(&mCommitCallbackRegistrar);
+
+ if (is_favorites_set)
+ {
+ buildNewViews(folder_id);
+ }
+ mFolderRoot.get()->setShowEmptyMessage(!is_favorites_set);
+ }
+}
+
/************************************************************************/
/* Asset Pre-Filtered Inventory Panel related class */
/* Exchanges filter's flexibility for speed of generation and */
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index b55eb2b828..d1c0b35e21 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -214,6 +214,7 @@ public:
void doCreate(const LLSD& userdata);
bool beginIMSession();
void fileUploadLocation(const LLSD& userdata);
+ void setFavoritesFolder(const LLSD& userdata);
void purgeSelectedItems();
bool attachObject(const LLSD& userdata);
static void idle(void* user_data);
@@ -338,4 +339,24 @@ private:
bool mViewsInitialized; // Views have been generated
};
+
+class LLInventoryFavoriteItemsPanel : public LLInventoryPanel
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params>
+ {};
+
+ void initFromParams(const Params& p);
+ bool isSelectionRemovable() { return false; }
+ void setSelectCallback(const boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)>& cb);
+
+protected:
+ LLInventoryFavoriteItemsPanel::LLInventoryFavoriteItemsPanel(const Params& params);
+ ~LLInventoryFavoriteItemsPanel() { mFolderChangedSignal.disconnect(); }
+ void updateFavoritesRootFolder();
+
+ boost::signals2::connection mFolderChangedSignal;
+ boost::function<void(const std::deque<LLFolderViewItem*>& items, BOOL user_action)> mSelectionCallback;
+ friend class LLUICtrlFactory;
+};
#endif // LL_LLINVENTORYPANEL_H
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 02cd22c307..89682d9576 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -188,6 +188,16 @@ BOOL LLPanelMainInventory::postBuild()
worn_filter.markDefault();
mWornItemsPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mWornItemsPanel, _1, _2));
}
+
+ mFavoriteItemsPanel = getChild<LLInventoryFavoriteItemsPanel>("Favorite Items");
+ if (mFavoriteItemsPanel)
+ {
+ LLInventoryFilter& recent_filter = mFavoriteItemsPanel->getFilter();
+ recent_filter.setEmptyLookupMessage("InventoryFavoritItemsNotSelected");
+ recent_filter.markDefault();
+ mFavoriteItemsPanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mFavoriteItemsPanel, _1, _2));
+ }
+
mSearchTypeCombo = getChild<LLComboBox>("search_type");
if(mSearchTypeCombo)
{
@@ -1403,7 +1413,7 @@ BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
}
if (command_name == "delete")
{
- return getActivePanel()->isSelectionRemovable();
+ return getActivePanel()->isSelectionRemovable() && (getActivePanel() != mFavoriteItemsPanel);
}
if (command_name == "save_texture")
{
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index a6bdee233d..c0b4a7b6fc 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -37,6 +37,7 @@
class LLComboBox;
class LLFolderViewItem;
class LLInventoryPanel;
+class LLInventoryFavoriteItemsPanel;
class LLSaveFolderState;
class LLFilterEditor;
class LLTabContainer;
@@ -136,6 +137,7 @@ private:
LLHandle<LLFloater> mFinderHandle;
LLInventoryPanel* mActivePanel;
LLInventoryPanel* mWornItemsPanel;
+ LLInventoryFavoriteItemsPanel* mFavoriteItemsPanel;
bool mResortActivePanel;
LLSaveFolderState* mSavedFolderState;
std::string mFilterText;
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 9aa84c1bac..adefa261aa 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -393,6 +393,13 @@
parameter="model" />
</menu_item_call>
</menu>
+ <menu_item_call
+ label="Use as Favorites folder"
+ layout="topleft"
+ name="Set Favorites folder">
+ <menu_item_call.on_click
+ function="Inventory.SetFavoritesFolder"/>
+ </menu_item_call>
<menu
label="Change Type"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
index d77fbdec0a..2745b9d302 100644
--- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
@@ -117,20 +117,32 @@
name="Recent Items"
show_item_link_overlays="true"
width="290" />
- <inventory_panel
- name="Worn Items"
- label="WORN"
- show_empty_message="false"
- follows="all"
- layout="topleft"
- width="290"
- bg_opaque_color="DkGray2"
- bg_alpha_color="DkGray2"
- background_visible="true"
- border="false"
- bevel_style="none"
- scroll.reserve_scroll_corner="false">
- </inventory_panel>
+ <inventory_panel
+ name="Worn Items"
+ label="WORN"
+ show_empty_message="false"
+ follows="all"
+ layout="topleft"
+ width="290"
+ bg_opaque_color="DkGray2"
+ bg_alpha_color="DkGray2"
+ background_visible="true"
+ border="false"
+ bevel_style="none"
+ scroll.reserve_scroll_corner="false"/>
+ <favorites_inventory_panel
+ name="Favorite Items"
+ label="FAVORITES"
+ show_empty_message="false"
+ follows="all"
+ layout="topleft"
+ width="290"
+ bg_opaque_color="DkGray2"
+ bg_alpha_color="DkGray2"
+ background_visible="true"
+ border="false"
+ bevel_style="none"
+ scroll.reserve_scroll_corner="false"/>
</tab_container>
<layout_stack
animate="false"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 1bfac6aeb7..b26ae0ebf8 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2295,6 +2295,7 @@ For AI Character: Get the closest navigable point to the point provided.
<!-- inventory -->
<string name="InventoryNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search].</string>
<string name="InventoryNoMatchingRecentItems">Didn't find what you're looking for? Try [secondlife:///app/inventory/filters Show filters].</string>
+ <string name="InventoryFavoritItemsNotSelected">Click "Use as Favorites folder" on a folder of your choice. You can choose a different folder at any time. System folders cannot be used for Favorites.</string>
<string name="PlacesNoMatchingItems">Didn't find what you're looking for? Try [secondlife:///app/search/places/[SEARCH_TERM] Search].</string>
<string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string>
<string name="MarketplaceNoMatchingItems">No items found. Check the spelling of your search string and try again.</string>