diff options
52 files changed, 1556 insertions, 448 deletions
diff --git a/BuildParams b/BuildParams index 10d16ff7d7..10d16ff7d7 100755..100644 --- a/BuildParams +++ b/BuildParams diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index fa2b3bff36..fa2b3bff36 100755..100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 2893e746e9..2893e746e9 100755..100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 998016f8f6..998016f8f6 100755..100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h diff --git a/indra/llui/llbadge.cpp b/indra/llui/llbadge.cpp index fde3c53a65..ceeeb4d1f6 100644 --- a/indra/llui/llbadge.cpp +++ b/indra/llui/llbadge.cpp @@ -27,11 +27,14 @@ #define LLBADGE_CPP #include "llbadge.h" +#include "llscrollcontainer.h" #include "lluictrlfactory.h" static LLDefaultChildRegistry::Register<LLBadge> r("badge"); +static const S32 BADGE_OFFSET_NOT_SPECIFIED = 0x7FFFFFFF; + // Compiler optimization, generate extern template template class LLBadge* LLView::getChild<class LLBadge>(const std::string& name, BOOL recurse) const; @@ -46,6 +49,8 @@ LLBadge::Params::Params() , label_offset_horiz("label_offset_horiz") , label_offset_vert("label_offset_vert") , location("location", LLRelPos::TOP_LEFT) + , location_offset_hcenter("location_offset_hcenter") + , location_offset_vcenter("location_offset_vcenter") , location_percent_hcenter("location_percent_hcenter") , location_percent_vcenter("location_percent_vcenter") , padding_horiz("padding_horiz") @@ -70,6 +75,8 @@ bool LLBadge::Params::equals(const Params& a) const comp &= (label_offset_horiz() == a.label_offset_horiz()); comp &= (label_offset_vert() == a.label_offset_vert()); comp &= (location() == a.location()); + comp &= (location_offset_hcenter() == a.location_offset_hcenter()); + comp &= (location_offset_vcenter() == a.location_offset_vcenter()); comp &= (location_percent_hcenter() == a.location_percent_hcenter()); comp &= (location_percent_vcenter() == a.location_percent_vcenter()); comp &= (padding_horiz() == a.padding_horiz()); @@ -91,16 +98,29 @@ LLBadge::LLBadge(const LLBadge::Params& p) , mLabelOffsetHoriz(p.label_offset_horiz) , mLabelOffsetVert(p.label_offset_vert) , mLocation(p.location) + , mLocationOffsetHCenter(BADGE_OFFSET_NOT_SPECIFIED) + , mLocationOffsetVCenter(BADGE_OFFSET_NOT_SPECIFIED) , mLocationPercentHCenter(0.5f) , mLocationPercentVCenter(0.5f) , mPaddingHoriz(p.padding_horiz) , mPaddingVert(p.padding_vert) + , mParentScroller(NULL) { if (mImage.isNull()) { llwarns << "Badge: " << getName() << " with no image!" << llendl; } + if (p.location_offset_hcenter.isProvided()) + { + mLocationOffsetHCenter = p.location_offset_hcenter(); + } + + if (p.location_offset_vcenter.isProvided()) + { + mLocationOffsetVCenter = p.location_offset_vcenter(); + } + // // The following logic is to set the mLocationPercentHCenter and mLocationPercentVCenter // based on the Location enum and our horizontal and vertical location percentages. The @@ -144,6 +164,15 @@ bool LLBadge::addToView(LLView * view) if (child_added) { setShape(view->getLocalRect()); + + // Find a parent scroll container, if there is one in case we need it for positioning + + LLView * parent = mOwner.get(); + + while ((parent != NULL) && ((mParentScroller = dynamic_cast<LLScrollContainer *>(parent)) == NULL)) + { + parent = parent->getParent(); + } } return child_added; @@ -201,21 +230,11 @@ void LLBadge::draw() if (owner_view) { // - // Calculate badge position based on owner - // - - LLRect owner_rect; - owner_view->localRectToOtherView(owner_view->getLocalRect(), & owner_rect, this); - - F32 badge_center_x = owner_rect.mLeft + owner_rect.getWidth() * mLocationPercentHCenter; - F32 badge_center_y = owner_rect.mBottom + owner_rect.getHeight() * mLocationPercentVCenter; - - // // Calculate badge size based on label text // LLWString badge_label_wstring = mLabel; - + S32 badge_label_begin_offset = 0; S32 badge_char_length = S32_MAX; S32 badge_pixel_length = S32_MAX; @@ -228,6 +247,77 @@ void LLBadge::draw() F32 badge_height = (2.0f * mPaddingVert) + mGLFont->getLineHeight(); // + // Calculate badge position based on owner + // + + LLRect owner_rect; + owner_view->localRectToOtherView(owner_view->getLocalRect(), & owner_rect, this); + + S32 location_offset_horiz = mLocationOffsetHCenter; + S32 location_offset_vert = mLocationOffsetVCenter; + + // If we're in a scroll container, do some math to keep us in the same place on screen if applicable + if (mParentScroller != NULL) + { + LLRect visibleRect = mParentScroller->getVisibleContentRect(); + + if (mLocationOffsetHCenter != BADGE_OFFSET_NOT_SPECIFIED) + { + if (LLRelPos::IsRight(mLocation)) + { + location_offset_horiz += visibleRect.mRight; + } + else if (LLRelPos::IsLeft(mLocation)) + { + location_offset_horiz += visibleRect.mLeft; + } + else // center + { + location_offset_horiz += (visibleRect.mLeft + visibleRect.mRight) / 2; + } + } + + if (mLocationOffsetVCenter != BADGE_OFFSET_NOT_SPECIFIED) + { + if (LLRelPos::IsTop(mLocation)) + { + location_offset_vert += visibleRect.mTop; + } + else if (LLRelPos::IsBottom(mLocation)) + { + location_offset_vert += visibleRect.mBottom; + } + else // center + { + location_offset_vert += (visibleRect.mBottom + visibleRect.mTop) / 2; + } + } + } + + F32 badge_center_x; + F32 badge_center_y; + + // Compute x position + if (mLocationOffsetHCenter == BADGE_OFFSET_NOT_SPECIFIED) + { + badge_center_x = owner_rect.mLeft + owner_rect.getWidth() * mLocationPercentHCenter; + } + else + { + badge_center_x = location_offset_horiz; + } + + // Compute y position + if (mLocationOffsetVCenter == BADGE_OFFSET_NOT_SPECIFIED) + { + badge_center_y = owner_rect.mBottom + owner_rect.getHeight() * mLocationPercentVCenter; + } + else + { + badge_center_y = location_offset_vert; + } + + // // Draw button image, if available. // Otherwise draw basic rectangular button. // diff --git a/indra/llui/llbadge.h b/indra/llui/llbadge.h index f81ccdf0cd..4b21a71aaa 100644 --- a/indra/llui/llbadge.h +++ b/indra/llui/llbadge.h @@ -39,8 +39,9 @@ // Declarations // -class LLUICtrlFactory; class LLFontGL; +class LLScrollContainer; +class LLUICtrlFactory; // // Relative Position Alignment @@ -108,6 +109,8 @@ public: Optional< S32 > label_offset_vert; Optional< LLRelPos::Location > location; + Optional< S32 > location_offset_hcenter; + Optional< S32 > location_offset_vcenter; Optional< U32 > location_percent_hcenter; Optional< U32 > location_percent_vcenter; @@ -150,6 +153,8 @@ private: S32 mLabelOffsetVert; LLRelPos::Location mLocation; + S32 mLocationOffsetHCenter; + S32 mLocationOffsetVCenter; F32 mLocationPercentHCenter; F32 mLocationPercentVCenter; @@ -157,6 +162,8 @@ private: F32 mPaddingHoriz; F32 mPaddingVert; + + LLScrollContainer* mParentScroller; }; // Build time optimization, generate once in .cpp file diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0e36b787a2..6fc7e51ca2 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -368,6 +368,7 @@ set(viewer_SOURCE_FILES llpanelmarketplaceinbox.cpp llpanelmarketplaceinboxinventory.cpp llpanelmarketplaceoutbox.cpp + llpanelmarketplaceoutboxinventory.cpp llpanelmediasettingsgeneral.cpp llpanelmediasettingspermissions.cpp llpanelmediasettingssecurity.cpp @@ -924,6 +925,7 @@ set(viewer_HEADER_FILES llpanelmarketplaceinbox.h llpanelmarketplaceinboxinventory.h llpanelmarketplaceoutbox.h + llpanelmarketplaceoutboxinventory.h llpanelmediasettingsgeneral.h llpanelmediasettingspermissions.h llpanelmediasettingssecurity.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 33541b559b..781431d4de 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4226,6 +4226,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>InventoryMarketplaceUserStatus</key> + <map> + <key>Comment</key> + <string>Marketplace user status.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>String</string> + <key>Value</key> + <string /> + </map> <key>InventorySortOrder</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index 1142f01232..9064d6894d 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -33,10 +33,10 @@ <key>Value</key> <string /> </map> - <key>LastInventoryInboxExpand</key> + <key>LastInventoryInboxCollapse</key> <map> <key>Comment</key> - <string>The last time the received items inbox was expanded.</string> + <string>The last time the received items inbox was collapsed.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 966f5b941e..966f5b941e 100755..100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index ef846ec42e..ef846ec42e 100755..100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 6461a5525e..0751378428 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -1914,7 +1914,7 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, // by the folder which is the hierarchy root. if (!handled && getListener()->getUUID().notNull()) { - LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); } if (handled) diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h index 3bfbf36110..aee31ca033 100644 --- a/indra/newview/llfoldervieweventlistener.h +++ b/indra/newview/llfoldervieweventlistener.h @@ -96,7 +96,8 @@ public: // otherwise FALSE. virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data) = 0; + void* cargo_data, + std::string& tooltip_msg) = 0; }; #endif diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index e2b7c45eab..2f07e084ab 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -840,7 +840,7 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, BOOL handled = FALSE; if(mListener) { - accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data); + accepted = mListener->dragOrDrop(mask,drop,cargo_type,cargo_data, tooltip_msg); handled = accepted; if (accepted) { @@ -2162,7 +2162,7 @@ BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data); + BOOL accepted = mListener && mListener->dragOrDrop(mask,drop,c_type,cargo_data, tooltip_msg); if (accepted) { mDragAndDropTarget = TRUE; @@ -2254,7 +2254,7 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, if (!handled) { - BOOL accepted = mListener && mListener->dragOrDrop(mask, drop,cargo_type,cargo_data); + BOOL accepted = mListener && mListener->dragOrDrop(mask, drop,cargo_type,cargo_data, tooltip_msg); if (accepted) { diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index ff328fd071..0959a08359 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -573,7 +573,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } // Don't allow items to be pasted directly into the COF or the inbox - if (!isCOFFolder() && !isInboxFolder()) + if (!isCOFFolder() && !isInboxFolder() && !isOutboxFolder()) { items.push_back(std::string("Paste")); } @@ -610,6 +610,10 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); + } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); } else { @@ -794,6 +798,20 @@ BOOL LLInvFVBridge::isInboxFolder() const return gInventory.isObjectDescendentOf(mUUID, inbox_id); } + +BOOL LLInvFVBridge::isOutboxFolder() const +{ + const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); + + if (outbox_id.isNull()) + { + return FALSE; + } + + return gInventory.isObjectDescendentOf(mUUID, outbox_id); +} + + BOOL LLInvFVBridge::isItemPermissive() const { return FALSE; @@ -1648,8 +1666,77 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const } +static BOOL can_move_to_outbox(LLInventoryItem* inv_item, std::string& tooltip_msg) +{ + bool worn = get_is_item_worn(inv_item->getUUID()); + bool allow_transfer = inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()); + + if (!allow_transfer) + { + tooltip_msg = LLTrans::getString("TooltipOutboxNoTransfer"); + } + else if(worn) + { + tooltip_msg = LLTrans::getString("TooltipOutboxWorn"); + } + + return !worn && allow_transfer; +} + + + +void LLFolderBridge::dropFolderToOutbox(LLInventoryCategory* inv_cat) +{ + copy_folder_to_outbox(inv_cat, getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false), inv_cat->getUUID()); +} + + + +int get_folder_levels(LLInventoryCategory* inv_cat) +{ + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items); + + int max_child_levels = 0; + + for (S32 i=0; i < cats->count(); ++i) + { + LLInventoryCategory* category = cats->get(i); + max_child_levels = llmax(max_child_levels, get_folder_levels(category)); + } + + return 1 + max_child_levels; +} + +int get_folder_path_length(const LLUUID& ancestor_id, const LLUUID& descendant_id) +{ + int depth = 0; + + if (ancestor_id == descendant_id) return depth; + + const LLInventoryCategory* category = gInventory.getCategory(descendant_id); + + while(category) + { + LLUUID parent_id = category->getParentUUID(); + + if (parent_id.isNull()) break; + + depth++; + + if (parent_id == ancestor_id) return depth; + + category = gInventory.getCategory(parent_id); + } + + llwarns << "get_folder_path_length() couldn't trace a path from the descendant to the ancestor" << llendl; + return -1; +} + BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, - BOOL drop) + BOOL drop, + std::string& tooltip_msg) { LLInventoryModel* model = getInventoryModel(); @@ -1674,10 +1761,13 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, const LLUUID &cat_id = inv_cat->getUUID(); const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); - + const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); const BOOL move_is_into_outfit = getCategory() && (getCategory()->getPreferredType() == LLFolderType::FT_OUTFIT); const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); + const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); + const BOOL move_is_from_outbox = model->isObjectDescendentOf(inv_cat->getUUID(), outbox_id); //-------------------------------------------------------------------------------- // Determine if folder can be moved. @@ -1730,6 +1820,27 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } } } + if (move_is_into_outbox) + { + for (S32 i=0; i < descendent_items.count(); ++i) + { + LLInventoryItem* item = descendent_items[i]; + if (!can_move_to_outbox(item, tooltip_msg)) + { + is_movable = FALSE; + break; + } + } + + int nested_folder_levels = get_folder_path_length(outbox_id, mUUID) + get_folder_levels(inv_cat); + + if (nested_folder_levels > 4) + { + tooltip_msg = LLTrans::getString("TooltipOutboxFolderLevels"); + is_movable = FALSE; + } + + } // //-------------------------------------------------------------------------------- @@ -1797,6 +1908,10 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, #endif } } + if (move_is_into_outbox && !move_is_from_outbox) + { + dropFolderToOutbox(inv_cat); + } else { if (gInventory.isObjectDescendentOf(inv_cat->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false))) @@ -2493,6 +2608,7 @@ void LLFolderBridge::folderOptionsMenu() if (trash_id == mUUID) return; if (isItemInTrash()) return; if (!isAgentInventory()) return; + if (isOutboxFolder()) return; LLFolderType::EType type = category->getPreferredType(); const bool is_system_folder = LLFolderType::lookupIsProtectedType(type); @@ -2628,6 +2744,10 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) mItems.clear(); // clear any items that used to exist addTrashContextMenuOptions(mItems, mDisabledItems); } + else if(isOutboxFolder()) + { + mItems.push_back(std::string("Delete")); + } else if(isAgentInventory()) // do not allow creating in library { LLViewerInventoryCategory *cat = getCategory(); @@ -2635,7 +2755,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) // Not sure what the right thing is to do here. if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT)) { - if (!isInboxFolder()) // don't allow creation in inbox + if (!isInboxFolder() && !isOutboxFolder()) // don't allow creation in inbox { // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) @@ -2702,10 +2822,13 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) mDisabledItems.push_back(std::string("Delete System Folder")); } - mItems.push_back(std::string("Share")); - if (!canShare()) + if (!isOutboxFolder()) { - mDisabledItems.push_back(std::string("Share")); + mItems.push_back(std::string("Share")); + if (!canShare()) + { + mDisabledItems.push_back(std::string("Share")); + } } hide_context_entries(menu, mItems, mDisabledItems); @@ -2746,7 +2869,8 @@ BOOL LLFolderBridge::hasChildren() const BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data) + void* cargo_data, + std::string& tooltip_msg) { LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; @@ -2766,7 +2890,7 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, case DAD_ANIMATION: case DAD_GESTURE: case DAD_MESH: - accept = dragItemIntoFolder(inv_item, drop); + accept = dragItemIntoFolder(inv_item, drop, tooltip_msg); break; case DAD_LINK: // DAD_LINK type might mean one of two asset types: AT_LINK or AT_LINK_FOLDER. @@ -2777,12 +2901,12 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, LLInventoryCategory* linked_category = gInventory.getCategory(inv_item->getLinkedUUID()); if (linked_category) { - accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop); + accept = dragCategoryIntoFolder((LLInventoryCategory*)linked_category, drop, tooltip_msg); } } else { - accept = dragItemIntoFolder(inv_item, drop); + accept = dragItemIntoFolder(inv_item, drop, tooltip_msg); } break; case DAD_CATEGORY: @@ -2792,7 +2916,7 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, } else { - accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop); + accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop, tooltip_msg); } break; case DAD_ROOT_CATEGORY: @@ -3049,7 +3173,8 @@ void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_c // into the folder, as well as performing the actual drop, depending // if drop == TRUE. BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, - BOOL drop) + BOOL drop, + std::string& tooltip_msg) { LLInventoryModel* model = getInventoryModel(); @@ -3060,11 +3185,14 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false); const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); + const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); const BOOL move_is_into_favorites = (mUUID == favorites_id); const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); + const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); //(mUUID == outbox_id); + const BOOL move_is_from_outbox = model->isObjectDescendentOf(inv_item->getUUID(), outbox_id); LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); BOOL accept = FALSE; @@ -3130,6 +3258,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { accept = can_move_to_landmarks(inv_item); } + else if (move_is_into_outbox) + { + accept = can_move_to_outbox(inv_item, tooltip_msg); + } if(accept && drop) { @@ -3180,6 +3312,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { dropToOutfit(inv_item, move_is_into_current_outfit); } + else if (move_is_into_outbox && !move_is_from_outbox) + { + copy_item_to_outbox(inv_item, outbox_id, LLUUID::null); + } // NORMAL or TRASH folder // (move the item, restamp if into trash) else @@ -3380,6 +3516,10 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); + } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); } else { @@ -3456,6 +3596,10 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); + } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); } else { @@ -3470,8 +3614,11 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) getClipboardEntries(true, items, disabled_items, flags); } - items.push_back(std::string("Sound Separator")); - items.push_back(std::string("Sound Play")); + if (!isOutboxFolder()) + { + items.push_back(std::string("Sound Separator")); + items.push_back(std::string("Sound Play")); + } hide_context_entries(menu, items, disabled_items); } @@ -3507,6 +3654,10 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); + } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); } else { @@ -3521,8 +3672,11 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) getClipboardEntries(true, items, disabled_items, flags); } - items.push_back(std::string("Landmark Separator")); - items.push_back(std::string("About Landmark")); + if (!isOutboxFolder()) + { + items.push_back(std::string("Landmark Separator")); + items.push_back(std::string("About Landmark")); + } // Disable "About Landmark" menu item for // multiple landmarks selected. Only one landmark @@ -3736,6 +3890,10 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); + } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); } else { @@ -3778,7 +3936,8 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data) + void* cargo_data, + std::string& tooltip_msg) { LLViewerInventoryItem* item = getItem(); BOOL rv = FALSE; @@ -3993,6 +4152,10 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { addTrashContextMenuOptions(items, disabled_items); } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); + } else { items.push_back(std::string("Share")); @@ -4046,6 +4209,10 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); + } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); } else { @@ -4060,9 +4227,12 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) getClipboardEntries(true, items, disabled_items, flags); } - items.push_back(std::string("Animation Separator")); - items.push_back(std::string("Animation Play")); - items.push_back(std::string("Animation Audition")); + if (!isOutboxFolder()) + { + items.push_back(std::string("Animation Separator")); + items.push_back(std::string("Animation Play")); + items.push_back(std::string("Animation Audition")); + } hide_context_entries(menu, items, disabled_items); @@ -4319,6 +4489,10 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if(isItemInTrash()) { addTrashContextMenuOptions(items, disabled_items); + } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); } else { @@ -4652,6 +4826,10 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { addTrashContextMenuOptions(items, disabled_items); } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); + } else { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere BOOL can_open = ((flags & SUPPRESS_OPEN_ITEM) != SUPPRESS_OPEN_ITEM); @@ -5049,6 +5227,10 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) items.push_back(std::string("Restore Item")); } + else if(isOutboxFolder()) + { + items.push_back(std::string("Delete")); + } else { items.push_back(std::string("Properties")); diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 15629c0c75..4a64df1371 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -115,7 +115,8 @@ public: virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data) { return FALSE; } + void* cargo_data, + std::string& tooltip_msg) { return FALSE; } virtual LLInventoryType::EType getInventoryType() const { return mInvType; } virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } @@ -140,6 +141,7 @@ protected: 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 inbox virtual BOOL isItemPermissive() const; static void changeItemParent(LLInventoryModel* model, LLViewerInventoryItem* item, @@ -228,8 +230,9 @@ public: mCallingCards(FALSE), mWearables(FALSE) {} - BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop); - BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop); + + BOOL dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop, std::string& tooltip_msg); + BOOL dragCategoryIntoFolder(LLInventoryCategory* inv_category, BOOL drop, std::string& tooltip_msg); virtual void performAction(LLInventoryModel* model, std::string action); virtual void openItem(); @@ -255,7 +258,8 @@ public: virtual BOOL hasChildren() const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data); + void* cargo_data, + std::string& tooltip_msg); virtual BOOL isItemRemovable() const; virtual BOOL isItemMovable() const ; @@ -299,6 +303,8 @@ protected: void dropToFavorites(LLInventoryItem* inv_item); void dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); + void dropToOutbox(LLInventoryItem* inv_item); + void dropFolderToOutbox(LLInventoryCategory* inv_cat); //-------------------------------------------------------------------- // Messy hacks for handling folder options @@ -378,7 +384,8 @@ public: virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data); + void* cargo_data, + std::string& tooltip_msg); void refreshFolderViewItem(); protected: LLCallingCardObserver* mObserver; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index db3b968730..8632e40c54 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -58,6 +58,7 @@ #include "llinventorypanel.h" #include "lllineeditor.h" #include "llmenugl.h" +#include "llnotificationsutil.h" #include "llpanelmaininventory.h" #include "llpreviewanim.h" #include "llpreviewgesture.h" @@ -471,6 +472,133 @@ void show_item_original(const LLUUID& item_uuid) } } +void move_to_outbox_cb(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if (option != 0) return; // canceled + + LLViewerInventoryItem * viitem = gInventory.getItem(notification["payload"]["item_id"].asUUID()); + LLUUID dest_folder_id = notification["payload"]["dest_folder_id"].asUUID(); + + if (viitem) + { + // when moving item directly into outbox create folder with that name + if (dest_folder_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + { + dest_folder_id = gInventory.createNewCategory(dest_folder_id, LLFolderType::FT_NONE, viitem->getName()); + gInventory.notifyObservers(); + } + + LLUUID parent = viitem->getParentUUID(); + + change_item_parent( + &gInventory, + viitem, + dest_folder_id, + false); + + LLUUID top_level_folder = notification["payload"]["top_level_folder"].asUUID(); + + if (top_level_folder != LLUUID::null) + { + LLViewerInventoryCategory* category; + + while (parent.notNull()) + { + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(parent,cat_array,item_array); + + LLUUID next_parent; + + category = gInventory.getCategory(parent); + + if (!category) break; + + next_parent = category->getParentUUID(); + + if (cat_array->empty() && item_array->empty()) + { + remove_category(&gInventory, parent); + } + + if (parent == top_level_folder) + { + break; + } + + parent = next_parent; + } + } + + } +} + + +void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder) +{ + if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + // when moving item directly into outbox create folder with that name + if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + { + dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_item->getName()); + gInventory.notifyObservers(); + } + + copy_inventory_item( + gAgent.getID(), + inv_item->getPermissions().getOwner(), + inv_item->getUUID(), + dest_folder, + inv_item->getName(), + LLPointer<LLInventoryCallback>(NULL)); + } + else + { + LLSD args; + args["ITEM_NAME"] = inv_item->getName(); + LLSD payload; + payload["item_id"] = inv_item->getUUID(); + payload["dest_folder_id"] = dest_folder; + payload["top_level_folder"] = top_level_folder; + LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&move_to_outbox_cb, _1, _2)); + } +} + +void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder) +{ + LLUUID new_folder_id = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_cat->getName()); + gInventory.notifyObservers(); + + LLInventoryModel::cat_array_t* cat_array; + LLInventoryModel::item_array_t* item_array; + gInventory.getDirectDescendentsOf(inv_cat->getUUID(),cat_array,item_array); + + // copy the vector because otherwise the iterator won't be happy if we delete from it + LLInventoryModel::item_array_t item_array_copy = *item_array; + + for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++) + { + LLInventoryItem* item = *iter; + copy_item_to_outbox(item, new_folder_id, top_level_folder); + } + + LLInventoryModel::cat_array_t cat_array_copy = *cat_array; + + for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) + { + LLViewerInventoryCategory* category = *iter; + copy_folder_to_outbox(category, new_folder_id, top_level_folder); + } + + // delete the folder if we have emptied it + //if (cat_array->empty() && item_array->empty()) + //{ + // remove_category(inventory_model, inv_cat->getUUID()); + //} +} + ///---------------------------------------------------------------------------- /// LLInventoryCollectFunctor implementations ///---------------------------------------------------------------------------- diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 2016b92666..3e80fe322c 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -71,6 +71,10 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s // Generates a string containing the path to the item specified by item_id. void append_path(const LLUUID& id, std::string& path); +void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder); + +void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder); + /** Miscellaneous global functions ** ** *******************************************************************************/ diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 1aa402802e..5f033cf517 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -163,49 +163,6 @@ void LLInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) { root_id = gInventory.getLibraryRootFolderID(); } - // leslie -- temporary HACK to work around sim not creating inbox and outbox with proper system folder type - else if (preferred_type == LLFolderType::FT_INBOX) - { - LLInventoryModel::cat_array_t* cats; - LLInventoryModel::item_array_t* items; - - gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items); - - if (cats) - { - for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it) - { - LLInventoryCategory* cat = *cat_it; - - if (cat->getName() == "Received Items") - { - root_id = cat->getUUID(); - } - } - } - } - // leslie -- temporary HACK to work around sim not creating inbox and outbox with proper system folder type - else if (preferred_type == LLFolderType::FT_OUTBOX) - { - LLInventoryModel::cat_array_t* cats; - LLInventoryModel::item_array_t* items; - - gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items); - - if (cats) - { - for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it) - { - LLInventoryCategory* cat = *cat_it; - - if (cat->getName() == "Merchant Outbox") - { - root_id = cat->getUUID(); - } - } - } - } - // leslie -- end temporary HACK else { root_id = (preferred_type != LLFolderType::FT_NONE) @@ -281,6 +238,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) // hide inbox getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX)); + getFilter()->setFilterCategoryTypes(getFilter()->getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX)); // Initialize base class params. LLPanel::initFromParams(params); diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index afed306a28..afed306a28 100755..100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 35a7314cd5..35a7314cd5 100755..100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp index f17f36a977..3fc10eb176 100644 --- a/indra/newview/llpanelmarketplaceinbox.cpp +++ b/indra/newview/llpanelmarketplaceinbox.cpp @@ -1,236 +1,238 @@ -/** - * @file llpanelmarketplaceinbox.cpp - * @brief Panel for marketplace inbox - * -* $LicenseInfo:firstyear=2011&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelmarketplaceinbox.h" -#include "llpanelmarketplaceinboxinventory.h" - -#include "llappviewer.h" -#include "llbutton.h" -#include "llinventorypanel.h" -#include "llfolderview.h" -#include "llsidepanelinventory.h" -#include "llviewercontrol.h" - - -static LLRegisterPanelClassWrapper<LLPanelMarketplaceInbox> t_panel_marketplace_inbox("panel_marketplace_inbox"); - -const LLPanelMarketplaceInbox::Params& LLPanelMarketplaceInbox::getDefaultParams() -{ - return LLUICtrlFactory::getDefaultParams<LLPanelMarketplaceInbox>(); -} - -// protected -LLPanelMarketplaceInbox::LLPanelMarketplaceInbox(const Params& p) - : LLPanel(p) - , mInventoryPanel(NULL) -{ -} - -LLPanelMarketplaceInbox::~LLPanelMarketplaceInbox() -{ - if (getChild<LLButton>("inbox_btn")->getToggleState()) - { - gSavedPerAccountSettings.setString("LastInventoryInboxExpand", LLDate::now().asString()); - } -} - -// virtual -BOOL LLPanelMarketplaceInbox::postBuild() -{ - LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLPanelMarketplaceInbox::handleLoginComplete, this)); - - LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMarketplaceInbox::onFocusReceived, this)); - - return TRUE; -} - -void LLPanelMarketplaceInbox::onSelectionChange() -{ - LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory")); - - sidepanel_inventory->updateVerbs(); -} - - -void LLPanelMarketplaceInbox::handleLoginComplete() -{ - // Set us up as the class to drive the badge value for the sidebar_inventory button - LLSideTray::getInstance()->setTabButtonBadgeDriver("sidebar_inventory", this); -} - -LLInventoryPanel * LLPanelMarketplaceInbox::setupInventoryPanel() -{ - LLView * inbox_inventory_placeholder = getChild<LLView>("inbox_inventory_placeholder"); - LLView * inbox_inventory_parent = inbox_inventory_placeholder->getParent(); - - mInventoryPanel = - LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_inbox_inventory.xml", - inbox_inventory_parent, - LLInventoryPanel::child_registry_t::instance()); - - // Reshape the inventory to the proper size - LLRect inventory_placeholder_rect = inbox_inventory_placeholder->getRect(); - mInventoryPanel->setShape(inventory_placeholder_rect); - - // Set the sort order newest to oldest, and a selection change callback - mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE); - mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceInbox::onSelectionChange, this)); - - // Set up the note to display when the inbox is empty - mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryInboxNoItems"); - - // Hide the placeholder text - inbox_inventory_placeholder->setVisible(FALSE); - - return mInventoryPanel; -} - -void LLPanelMarketplaceInbox::onFocusReceived() -{ - LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory"); - - sidepanel_inventory->clearSelections(true, false, true); -} - -BOOL LLPanelMarketplaceInbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg) -{ - *accept = ACCEPT_NO; - return TRUE; -} - -U32 LLPanelMarketplaceInbox::getFreshItemCount() const -{ -#if SUPPORTING_FRESH_ITEM_COUNT - - // - // NOTE: When turning this on, be sure to test the no inbox/outbox case because this code probably - // will return "2" for the Inventory and LIBRARY top-levels when that happens. - // - - U32 fresh_item_count = 0; - - if (mInventoryPanel) - { - const 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(); - - for (; folders_it != folders_end; ++folders_it) - { - const LLFolderViewFolder * folder_view = *folders_it; - const LLInboxFolderViewFolder * inbox_folder_view = dynamic_cast<const LLInboxFolderViewFolder*>(folder_view); - - if (inbox_folder_view && inbox_folder_view->isFresh()) - { - fresh_item_count++; - } - } - } - } - - return fresh_item_count; -#else - return getTotalItemCount(); -#endif -} - -U32 LLPanelMarketplaceInbox::getTotalItemCount() const -{ - U32 item_count = 0; - - if (mInventoryPanel) - { - const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder(); - - if (inbox_folder) - { - item_count += inbox_folder->getFoldersCount(); - } - } - - return item_count; -} - -std::string LLPanelMarketplaceInbox::getBadgeString() const -{ - std::string item_count_str(""); - - // If the inbox is visible, and the side panel is collapsed or expanded and not the inventory panel - if (getParent()->getVisible() && - (LLSideTray::getInstance()->getCollapsed() || !LLSideTray::getInstance()->isPanelActive("sidepanel_inventory"))) - { - U32 item_count = getFreshItemCount(); - - if (item_count) - { - item_count_str = llformat("%d", item_count); - } - } - - return item_count_str; -} - -void LLPanelMarketplaceInbox::draw() -{ - U32 item_count = getTotalItemCount(); - - LLView * fresh_new_count_view = getChildView("inbox_fresh_new_count"); - - if (item_count > 0) - { - std::string item_count_str = llformat("%d", item_count); - - LLStringUtil::format_map_t args; - args["[NUM]"] = item_count_str; - getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelWithArg", args)); - -#if SUPPORTING_FRESH_ITEM_COUNT - // set green text to fresh item count - U32 fresh_item_count = getFreshItemCount(); - fresh_new_count_view->setVisible((fresh_item_count > 0)); - - if (fresh_item_count > 0) - { - getChild<LLUICtrl>("inbox_fresh_new_count")->setTextArg("[NUM]", llformat("%d", fresh_item_count)); - } -#else - fresh_new_count_view->setVisible(FALSE); -#endif - } - else - { - getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelNoArg")); - - fresh_new_count_view->setVisible(FALSE); - } - - LLPanel::draw(); -} +/**
+ * @file llpanelmarketplaceinbox.cpp
+ * @brief Panel for marketplace inbox
+ *
+* $LicenseInfo:firstyear=2011&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llpanelmarketplaceinbox.h"
+#include "llpanelmarketplaceinboxinventory.h"
+
+#include "llappviewer.h"
+#include "llbutton.h"
+#include "llinventorypanel.h"
+#include "llfolderview.h"
+#include "llsidepanelinventory.h"
+#include "llviewercontrol.h"
+
+
+static LLRegisterPanelClassWrapper<LLPanelMarketplaceInbox> t_panel_marketplace_inbox("panel_marketplace_inbox");
+
+const LLPanelMarketplaceInbox::Params& LLPanelMarketplaceInbox::getDefaultParams()
+{
+ return LLUICtrlFactory::getDefaultParams<LLPanelMarketplaceInbox>();
+}
+
+// protected
+LLPanelMarketplaceInbox::LLPanelMarketplaceInbox(const Params& p)
+ : LLPanel(p)
+ , mInventoryPanel(NULL)
+{
+}
+
+LLPanelMarketplaceInbox::~LLPanelMarketplaceInbox()
+{
+ if (getChild<LLButton>("inbox_btn")->getToggleState())
+ {
+ gSavedPerAccountSettings.setString("LastInventoryInboxCollapse", LLDate::now().asString());
+ }
+}
+
+// virtual
+BOOL LLPanelMarketplaceInbox::postBuild()
+{
+ LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLPanelMarketplaceInbox::handleLoginComplete, this));
+
+ LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLPanelMarketplaceInbox::onFocusReceived, this));
+
+ return TRUE;
+}
+
+void LLPanelMarketplaceInbox::onSelectionChange()
+{
+ LLSidepanelInventory* sidepanel_inventory = dynamic_cast<LLSidepanelInventory*>(LLSideTray::getInstance()->getPanel("sidepanel_inventory"));
+
+ sidepanel_inventory->updateVerbs();
+}
+
+
+void LLPanelMarketplaceInbox::handleLoginComplete()
+{
+ // Set us up as the class to drive the badge value for the sidebar_inventory button
+ LLSideTray::getInstance()->setTabButtonBadgeDriver("sidebar_inventory", this);
+}
+
+LLInventoryPanel * LLPanelMarketplaceInbox::setupInventoryPanel()
+{
+ LLView * inbox_inventory_placeholder = getChild<LLView>("inbox_inventory_placeholder");
+ LLView * inbox_inventory_parent = inbox_inventory_placeholder->getParent();
+
+ mInventoryPanel =
+ LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_inbox_inventory.xml",
+ inbox_inventory_parent,
+ LLInventoryPanel::child_registry_t::instance());
+
+ llassert(mInventoryPanel);
+
+ // Reshape the inventory to the proper size
+ LLRect inventory_placeholder_rect = inbox_inventory_placeholder->getRect();
+ mInventoryPanel->setShape(inventory_placeholder_rect);
+
+ // Set the sort order newest to oldest, and a selection change callback
+ mInventoryPanel->setSortOrder(LLInventoryFilter::SO_DATE);
+ mInventoryPanel->setSelectCallback(boost::bind(&LLPanelMarketplaceInbox::onSelectionChange, this));
+
+ // Set up the note to display when the inbox is empty
+ mInventoryPanel->getFilter()->setEmptyLookupMessage("InventoryInboxNoItems");
+
+ // Hide the placeholder text
+ inbox_inventory_placeholder->setVisible(FALSE);
+
+ return mInventoryPanel;
+}
+
+void LLPanelMarketplaceInbox::onFocusReceived()
+{
+ LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory");
+
+ sidepanel_inventory->clearSelections(true, false, true);
+}
+
+BOOL LLPanelMarketplaceInbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void *cargo_data, EAcceptance *accept, std::string& tooltip_msg)
+{
+ *accept = ACCEPT_NO;
+ return TRUE;
+}
+
+U32 LLPanelMarketplaceInbox::getFreshItemCount() const
+{
+#if SUPPORTING_FRESH_ITEM_COUNT
+
+ //
+ // NOTE: When turning this on, be sure to test the no inbox/outbox case because this code probably
+ // will return "2" for the Inventory and LIBRARY top-levels when that happens.
+ //
+
+ U32 fresh_item_count = 0;
+
+ if (mInventoryPanel)
+ {
+ const 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();
+
+ for (; folders_it != folders_end; ++folders_it)
+ {
+ const LLFolderViewFolder * folder_view = *folders_it;
+ const LLInboxFolderViewFolder * inbox_folder_view = dynamic_cast<const LLInboxFolderViewFolder*>(folder_view);
+
+ if (inbox_folder_view && inbox_folder_view->isFresh())
+ {
+ fresh_item_count++;
+ }
+ }
+ }
+ }
+
+ return fresh_item_count;
+#else
+ return getTotalItemCount();
+#endif
+}
+
+U32 LLPanelMarketplaceInbox::getTotalItemCount() const
+{
+ U32 item_count = 0;
+
+ if (mInventoryPanel)
+ {
+ const LLFolderViewFolder * inbox_folder = mInventoryPanel->getRootFolder();
+
+ if (inbox_folder)
+ {
+ item_count += inbox_folder->getFoldersCount();
+ }
+ }
+
+ return item_count;
+}
+
+std::string LLPanelMarketplaceInbox::getBadgeString() const
+{
+ std::string item_count_str("");
+
+ // If the inbox is visible, and the side panel is collapsed or expanded and not the inventory panel
+ if (getParent()->getVisible() &&
+ (LLSideTray::getInstance()->getCollapsed() || !LLSideTray::getInstance()->isPanelActive("sidepanel_inventory")))
+ {
+ U32 item_count = getFreshItemCount();
+
+ if (item_count)
+ {
+ item_count_str = llformat("%d", item_count);
+ }
+ }
+
+ return item_count_str;
+}
+
+void LLPanelMarketplaceInbox::draw()
+{
+ U32 item_count = getTotalItemCount();
+
+ LLView * fresh_new_count_view = getChildView("inbox_fresh_new_count");
+
+ if (item_count > 0)
+ {
+ std::string item_count_str = llformat("%d", item_count);
+
+ LLStringUtil::format_map_t args;
+ args["[NUM]"] = item_count_str;
+ getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelWithArg", args));
+
+#if SUPPORTING_FRESH_ITEM_COUNT
+ // set green text to fresh item count
+ U32 fresh_item_count = getFreshItemCount();
+ fresh_new_count_view->setVisible((fresh_item_count > 0));
+
+ if (fresh_item_count > 0)
+ {
+ getChild<LLUICtrl>("inbox_fresh_new_count")->setTextArg("[NUM]", llformat("%d", fresh_item_count));
+ }
+#else
+ fresh_new_count_view->setVisible(FALSE);
+#endif
+ }
+ else
+ {
+ getChild<LLButton>("inbox_btn")->setLabel(getString("InboxLabelNoArg"));
+
+ fresh_new_count_view->setVisible(FALSE);
+ }
+
+ LLPanel::draw();
+}
diff --git a/indra/newview/llpanelmarketplaceinboxinventory.cpp b/indra/newview/llpanelmarketplaceinboxinventory.cpp index 2c97d539a1..de4e4414c4 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.cpp +++ b/indra/newview/llpanelmarketplaceinboxinventory.cpp @@ -66,7 +66,7 @@ void LLInboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& para LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false); - // leslie -- temporary HACK to work around sim not creating inbox and outbox with proper system folder type + // leslie -- temporary HACK to work around sim not creating inbox with proper system folder type if (root_id.isNull()) { std::string start_folder_name(params.start_folder()); @@ -182,7 +182,7 @@ void LLInboxFolderViewFolder::draw() void LLInboxFolderViewFolder::updateFlag() const { - LLDate saved_freshness_date = LLDate(gSavedPerAccountSettings.getString("LastInventoryInboxExpand")); + LLDate saved_freshness_date = LLDate(gSavedPerAccountSettings.getString("LastInventoryInboxCollapse")); mFresh = (mCreationDate > saved_freshness_date.secondsSinceEpoch()); } diff --git a/indra/newview/llpanelmarketplaceinboxinventory.h b/indra/newview/llpanelmarketplaceinboxinventory.h index 8946b9dc98..d2d42e11f4 100644 --- a/indra/newview/llpanelmarketplaceinboxinventory.h +++ b/indra/newview/llpanelmarketplaceinboxinventory.h @@ -33,7 +33,7 @@ #include "llfolderviewitem.h" -#define SUPPORTING_FRESH_ITEM_COUNT 0 +#define SUPPORTING_FRESH_ITEM_COUNT 1 diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp index d51a0d78fe..221420985a 100644 --- a/indra/newview/llpanelmarketplaceoutbox.cpp +++ b/indra/newview/llpanelmarketplaceoutbox.cpp @@ -34,11 +34,16 @@ #include "lleventcoro.h" #include "llinventorypanel.h" #include "llloadingindicator.h" +#include "llnotificationsutil.h" #include "llpanelmarketplaceinbox.h" #include "llsidepanelinventory.h" #include "llsidetray.h" #include "lltimer.h" - +#include "llviewernetwork.h" +#include "llagent.h" +#include "llviewermedia.h" +#include "llfolderview.h" +#include "llinventoryfunctions.h" static LLRegisterPanelClassWrapper<LLPanelMarketplaceOutbox> t_panel_marketplace_outbox("panel_marketplace_outbox"); @@ -83,7 +88,7 @@ void LLPanelMarketplaceOutbox::handleLoginComplete() void LLPanelMarketplaceOutbox::onFocusReceived() { LLSidepanelInventory * sidepanel_inventory = LLSideTray::getInstance()->getPanel<LLSidepanelInventory>("sidepanel_inventory"); - + sidepanel_inventory->clearSelections(true, true, false); } @@ -96,7 +101,7 @@ void LLPanelMarketplaceOutbox::onSelectionChange() LLInventoryPanel * LLPanelMarketplaceOutbox::setupInventoryPanel() { - LLView * outbox_inventory_placeholder = getChild<LLView>("outbox_inventory_placeholder"); + LLView * outbox_inventory_placeholder = getChild<LLView>("outbox_inventory_placeholder_panel"); LLView * outbox_inventory_parent = outbox_inventory_placeholder->getParent(); mInventoryPanel = @@ -104,6 +109,8 @@ LLInventoryPanel * LLPanelMarketplaceOutbox::setupInventoryPanel() outbox_inventory_parent, LLInventoryPanel::child_registry_t::instance()); + llassert(mInventoryPanel); + // Reshape the inventory to the proper size LLRect inventory_placeholder_rect = outbox_inventory_placeholder->getRect(); mInventoryPanel->setShape(inventory_placeholder_rect); @@ -121,11 +128,30 @@ LLInventoryPanel * LLPanelMarketplaceOutbox::setupInventoryPanel() return mInventoryPanel; } -bool LLPanelMarketplaceOutbox::isOutboxEmpty() const +BOOL LLPanelMarketplaceOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) { - // TODO: Check for contents of outbox + BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + + if (!handled && mInventoryPanel && mInventoryPanel->getRootFolder()) + { + handled = mInventoryPanel->getRootFolder()->handleDragAndDropFromChild(mask,drop,cargo_type,cargo_data,accept,tooltip_msg); - return false; + if (handled) + { + mInventoryPanel->getRootFolder()->setDragAndDropThisFrame(); + } + } + + return handled; +} + +bool LLPanelMarketplaceOutbox::isOutboxEmpty() const +{ + return (getTotalItemCount() == 0); } bool LLPanelMarketplaceOutbox::isSyncInProgress() const @@ -149,28 +175,91 @@ void timeDelay(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel) waitForEventOn(self, "mainloop"); } - outboxPanel->onSyncComplete(); + outboxPanel->onSyncComplete(true, LLSD::emptyMap()); gTimeDelayDebugFunc = ""; } -void LLPanelMarketplaceOutbox::onSyncButtonClicked() + +class LLInventorySyncResponder : public LLHTTPClient::Responder { - // TODO: Actually trigger sync to marketplace +public: + LLInventorySyncResponder(LLPanelMarketplaceOutbox * outboxPanel) + : LLCurl::Responder() + , mOutboxPanel(outboxPanel) + { + } + + void completed(U32 status, const std::string& reason, const LLSD& content) + { + llinfos << "inventory_import complete status: " << status << ", reason: " << reason << llendl; + + if (isGoodStatus(status)) + { + // Complete success + llinfos << "success" << llendl; + LLSD imported_list = content["imported"]; + LLSD::array_const_iterator it = imported_list.beginArray(); + for ( ; it != imported_list.endArray(); ++it) + { + LLUUID imported_folder = (*it).asUUID(); + remove_category(&gInventory, imported_folder); + } + } + else + { + llwarns << "failed" << llendl; + } + + mOutboxPanel->onSyncComplete(isGoodStatus(status), content); + } + +private: + LLPanelMarketplaceOutbox * mOutboxPanel; +}; +void LLPanelMarketplaceOutbox::onSyncButtonClicked() +{ + // Get the sync animation going mSyncInProgress = true; updateSyncButtonStatus(); - // Set a timer (for testing only) + // Make the url for the inventory import request + std::string url = "https://marketplace.secondlife.com/"; + + if (!LLGridManager::getInstance()->isInProductionGrid()) + { + std::string gridLabel = LLGridManager::getInstance()->getGridLabel(); + url = llformat("https://marketplace.%s.lindenlab.com/", utf8str_tolower(gridLabel).c_str()); + + // TEMP for Jim's pdp + //url = "http://pdp24.lindenlab.com:3000/"; + } + + url += "api/1/users/"; + url += gAgent.getID().getString(); + url += "/inventory_import"; + + llinfos << "http get: " << url << llendl; + LLHTTPClient::get(url, new LLInventorySyncResponder(this), LLViewerMedia::getHeaders()); - gTimeDelayDebugFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox timeDelay", boost::bind(&timeDelay, _1, this)); + // Set a timer (for testing only) + //gTimeDelayDebugFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox timeDelay", boost::bind(&timeDelay, _1, this)); } -void LLPanelMarketplaceOutbox::onSyncComplete() +void LLPanelMarketplaceOutbox::onSyncComplete(bool goodStatus, const LLSD& content) { mSyncInProgress = false; - updateSyncButtonStatus(); + + if (goodStatus) + { + LLNotificationsUtil::add("OutboxUploadComplete", LLSD::emptyMap(), LLSD::emptyMap()); + } + else + { + LLNotificationsUtil::add("OutboxUploadHadErrors", LLSD::emptyMap(), LLSD::emptyMap()); + } } void LLPanelMarketplaceOutbox::updateSyncButtonStatus() @@ -192,3 +281,46 @@ void LLPanelMarketplaceOutbox::updateSyncButtonStatus() mSyncButton->setEnabled(!isOutboxEmpty()); } } + +U32 LLPanelMarketplaceOutbox::getTotalItemCount() const +{ + U32 item_count = 0; + + if (mInventoryPanel) + { + const LLFolderViewFolder * outbox_folder = mInventoryPanel->getRootFolder(); + + if (outbox_folder) + { + item_count += outbox_folder->getFoldersCount(); + } + } + + return item_count; +} + +void LLPanelMarketplaceOutbox::draw() +{ + const U32 item_count = getTotalItemCount(); + const bool not_empty = (item_count > 0); + + if (not_empty) + { + std::string item_count_str = llformat("%d", item_count); + + LLStringUtil::format_map_t args; + args["[NUM]"] = item_count_str; + getChild<LLButton>("outbox_btn")->setLabel(getString("OutboxLabelWithArg", args)); + } + else + { + getChild<LLButton>("outbox_btn")->setLabel(getString("OutboxLabelNoArg")); + } + + if (!isSyncInProgress()) + { + mSyncButton->setEnabled(not_empty); + } + + LLPanel::draw(); +} diff --git a/indra/newview/llpanelmarketplaceoutbox.h b/indra/newview/llpanelmarketplaceoutbox.h index 8e2c35914d..2cf5b77569 100644 --- a/indra/newview/llpanelmarketplaceoutbox.h +++ b/indra/newview/llpanelmarketplaceoutbox.h @@ -54,12 +54,22 @@ public: /*virtual*/ BOOL postBuild(); + /*virtual*/ void draw(); + LLInventoryPanel * setupInventoryPanel(); + U32 getTotalItemCount() const; + bool isOutboxEmpty() const; bool isSyncInProgress() const; - void onSyncComplete(); + void onSyncComplete(bool goodStatus, const LLSD& content); + + /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); protected: void onSyncButtonClicked(); diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.cpp b/indra/newview/llpanelmarketplaceoutboxinventory.cpp new file mode 100644 index 0000000000..638d3c5150 --- /dev/null +++ b/indra/newview/llpanelmarketplaceoutboxinventory.cpp @@ -0,0 +1,172 @@ +/** + * @file llpanelmarketplaceoutboxinventory.cpp + * @brief LLOutboxInventoryPanel class definition + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelmarketplaceoutboxinventory.h" + +#include "llfolderview.h" +#include "llfoldervieweventlistener.h" +#include "llinventorybridge.h" +#include "llinventoryfunctions.h" +#include "llpanellandmarks.h" +#include "llplacesinventorybridge.h" +#include "llviewerfoldertype.h" + + +// +// statics +// + +static LLDefaultChildRegistry::Register<LLOutboxInventoryPanel> r1("outbox_inventory_panel"); +static LLDefaultChildRegistry::Register<LLOutboxFolderViewFolder> r2("outbox_folder_view_folder"); + + +// +// LLOutboxInventoryPanel Implementation +// + +LLOutboxInventoryPanel::LLOutboxInventoryPanel(const LLOutboxInventoryPanel::Params& p) + : LLInventoryPanel(p) +{ +} + +LLOutboxInventoryPanel::~LLOutboxInventoryPanel() +{ +} + +// virtual +void LLOutboxInventoryPanel::buildFolderView(const LLInventoryPanel::Params& params) +{ + // Determine the root folder in case specified, and + // build the views starting with that folder. + + LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false); + + // leslie -- temporary HACK to work around sim not creating outbox with proper system folder type + if (root_id.isNull()) + { + std::string start_folder_name(params.start_folder()); + + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + + gInventory.getDirectDescendentsOf(gInventory.getRootFolderID(), cats, items); + + if (cats) + { + for (LLInventoryModel::cat_array_t::const_iterator cat_it = cats->begin(); cat_it != cats->end(); ++cat_it) + { + LLInventoryCategory* cat = *cat_it; + + if (cat->getName() == start_folder_name) + { + root_id = cat->getUUID(); + break; + } + } + } + + if (root_id == LLUUID::null) + { + llwarns << "No category found that matches outbox inventory panel start_folder: " << start_folder_name << llendl; + } + } + // leslie -- end temporary HACK + + if (root_id == LLUUID::null) + { + llwarns << "Outbox inventory panel has no root folder!" << llendl; + root_id = LLUUID::generateNewID(); + } + + LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY, + LLAssetType::AT_CATEGORY, + LLInventoryType::IT_CATEGORY, + this, + NULL, + root_id); + + mFolderRoot = createFolderView(new_listener, params.use_label_suffix()); +} + +LLFolderViewFolder * LLOutboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge) +{ + LLOutboxFolderViewFolder::Params params; + + params.name = bridge->getDisplayName(); + params.icon = bridge->getIcon(); + params.icon_open = bridge->getOpenIcon(); + + if (mShowItemLinkOverlays) // if false, then links show up just like normal items + { + params.icon_overlay = LLUI::getUIImage("Inv_Link"); + } + + params.root = mFolderRoot; + params.listener = bridge; + params.tool_tip = params.name; + + return LLUICtrlFactory::create<LLOutboxFolderViewFolder>(params); +} + + +// +// LLOutboxFolderViewFolder Implementation +// + +LLOutboxFolderViewFolder::LLOutboxFolderViewFolder(const Params& p) + : LLFolderViewFolder(p) + , LLBadgeOwner(getHandle()) + , mError(false) +{ + initBadgeParams(p.error_badge()); +} + +LLOutboxFolderViewFolder::~LLOutboxFolderViewFolder() +{ +} + +// virtual +void LLOutboxFolderViewFolder::draw() +{ + if (!badgeHasParent()) + { + addBadgeToParentPanel(); + } + + setBadgeVisibility(mError); + + LLFolderViewFolder::draw(); +} + +void LLOutboxFolderViewFolder::setCreationDate(time_t creation_date_utc) const +{ + mCreationDate = creation_date_utc; +} + + +// eof diff --git a/indra/newview/llpanelmarketplaceoutboxinventory.h b/indra/newview/llpanelmarketplaceoutboxinventory.h new file mode 100644 index 0000000000..ba68654ad7 --- /dev/null +++ b/indra/newview/llpanelmarketplaceoutboxinventory.h @@ -0,0 +1,82 @@ +/** + * @file llpanelmarketplaceoutboxinventory.h + * @brief LLOutboxInventoryPanel class declaration + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_OUTBOXINVENTORYPANEL_H +#define LL_OUTBOXINVENTORYPANEL_H + + +#include "llbadgeowner.h" +#include "llinventorypanel.h" +#include "llfolderviewitem.h" + + +class LLOutboxInventoryPanel : public LLInventoryPanel +{ +public: + struct Params : public LLInitParam::Block<Params, LLInventoryPanel::Params> + { + Params() {} + }; + + LLOutboxInventoryPanel(const Params& p); + ~LLOutboxInventoryPanel(); + + // virtual + void buildFolderView(const LLInventoryPanel::Params& params); + + // virtual + class LLFolderViewFolder* createFolderViewFolder(LLInvFVBridge * bridge); +}; + + +class LLOutboxFolderViewFolder : public LLFolderViewFolder, public LLBadgeOwner +{ +public: + struct Params : public LLInitParam::Block<Params, LLFolderViewFolder::Params> + { + Optional<LLBadge::Params> error_badge; + + Params() + : error_badge("error_badge") + { + } + }; + + LLOutboxFolderViewFolder(const Params& p); + ~LLOutboxFolderViewFolder(); + + void draw(); + + bool hasError() const { return mError; } + +protected: + void setCreationDate(time_t creation_date_utc) const; + + bool mError; +}; + + +#endif //LL_OUTBOXINVENTORYPANEL_H diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 83ba8afbfc..44364b5831 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -140,7 +140,8 @@ public: virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data); + void* cargo_data, + std::string& tooltip_msg); }; LLTaskInvFVBridge::LLTaskInvFVBridge( @@ -581,7 +582,8 @@ BOOL LLTaskInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const BOOL LLTaskInvFVBridge::dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data) + void* cargo_data, + std::string& tooltip_msg) { //llinfos << "LLTaskInvFVBridge::dragOrDrop()" << llendl; return FALSE; @@ -711,7 +713,8 @@ public: virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; virtual BOOL dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data); + void* cargo_data, + std::string& tooltip_msg); virtual BOOL canOpenItem() const { return TRUE; } virtual void openItem(); }; @@ -805,7 +808,8 @@ BOOL LLTaskCategoryBridge::startDrag(EDragAndDropType* type, LLUUID* id) const BOOL LLTaskCategoryBridge::dragOrDrop(MASK mask, BOOL drop, EDragAndDropType cargo_type, - void* cargo_data) + void* cargo_data, + std::string& tooltip_msg) { //llinfos << "LLTaskCategoryBridge::dragOrDrop()" << llendl; BOOL accept = FALSE; diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index a800611aac..5ae3a30fd5 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -52,7 +52,10 @@ #include "llsidepaneltaskinfo.h" #include "llstring.h" #include "lltabcontainer.h" +#include "lltextbox.h" +#include "lltrans.h" #include "llviewermedia.h" +#include "llviewernetwork.h" #include "llweb.h" static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_inventory"); @@ -66,11 +69,14 @@ static const char * const OUTBOX_BUTTON_NAME = "outbox_btn"; static const char * const INBOX_LAYOUT_PANEL_NAME = "inbox_layout_panel"; static const char * const OUTBOX_LAYOUT_PANEL_NAME = "outbox_layout_panel"; + +static const char * const INBOX_OUTBOX_LAYOUT_PANEL_NAME = "inbox_outbox_layout_panel"; static const char * const MAIN_INVENTORY_LAYOUT_PANEL_NAME = "main_inventory_layout_panel"; static const char * const INBOX_INVENTORY_PANEL = "inventory_inbox"; static const char * const OUTBOX_INVENTORY_PANEL = "inventory_outbox"; +static const char * const INBOX_OUTBOX_LAYOUT_STACK_NAME = "inbox_outbox_layout_stack"; static const char * const INVENTORY_LAYOUT_STACK_NAME = "inventory_layout_stack"; static const char * const MARKETPLACE_INBOX_PANEL = "marketplace_inbox"; @@ -235,16 +241,20 @@ BOOL LLSidepanelInventory::postBuild() // Marketplace inbox/outbox setup { - LLLayoutStack* stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME); + LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME); // Disable user_resize on main inventory panel by default - stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, false); - stack->setPanelUserResize(INBOX_LAYOUT_PANEL_NAME, false); - stack->setPanelUserResize(OUTBOX_LAYOUT_PANEL_NAME, false); + inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, false); + inv_stack->setPanelUserResize(INBOX_OUTBOX_LAYOUT_PANEL_NAME, false); + + // Collapse marketplace panel by default + inv_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME), true); + + LLLayoutStack* inout_stack = getChild<LLLayoutStack>(INBOX_OUTBOX_LAYOUT_STACK_NAME); // Collapse both inbox and outbox panels - stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true); - stack->collapsePanel(getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME), true); + inout_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true); + inout_stack->collapsePanel(getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME), true); // Set up button states and callbacks LLButton * inbox_button = getChild<LLButton>(INBOX_BUTTON_NAME); @@ -303,8 +313,7 @@ void LLSidepanelInventory::handleLoginComplete() observeOutboxModifications(outbox_id); // Enable the display of the outbox if it exists - //enableOutbox(true); - // leslie NOTE: Disabling outbox until we support it officially. + enableOutbox(true); } } @@ -388,23 +397,67 @@ void LLSidepanelInventory::observeOutboxModifications(const LLUUID& outboxID) void LLSidepanelInventory::enableInbox(bool enabled) { mInboxEnabled = enabled; - getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME)->setVisible(enabled); + + LLLayoutPanel * inbox_layout_panel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME); + inbox_layout_panel->setVisible(enabled); + + if (mInboxEnabled) + { + LLLayoutPanel * inout_layout_panel = getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME); + + inout_layout_panel->setVisible(TRUE); + + if (mOutboxEnabled) + { + S32 inbox_min_dim = inbox_layout_panel->getMinDim(); + S32 outbox_min_dim = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME)->getMinDim(); + + inout_layout_panel->setMinDim(inbox_min_dim + outbox_min_dim); + } + } } void LLSidepanelInventory::enableOutbox(bool enabled) { mOutboxEnabled = enabled; - getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME)->setVisible(enabled); + + LLLayoutPanel * outbox_layout_panel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME); + outbox_layout_panel->setVisible(enabled); + + if (mOutboxEnabled) + { + LLLayoutPanel * inout_layout_panel = getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME); + + inout_layout_panel->setVisible(TRUE); + + if (mInboxEnabled) + { + S32 inbox_min_dim = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME)->getMinDim(); + S32 outbox_min_dim = outbox_layout_panel->getMinDim(); + + inout_layout_panel->setMinDim(inbox_min_dim + outbox_min_dim); + } + + updateOutboxUserStatus(); + } } void LLSidepanelInventory::onInboxChanged(const LLUUID& inbox_id) { // Trigger a load of the entire inbox so we always know the contents and their creation dates for sorting LLInventoryModelBackgroundFetch::instance().start(inbox_id); + + // If the outbox is expanded, don't auto-expand the inbox + if (mOutboxEnabled) + { + if (getChild<LLButton>(OUTBOX_BUTTON_NAME)->getToggleState()) + { + return; + } + } - // Expand the inbox since we have fresh items - LLPanelMarketplaceInbox * inbox = findChild<LLPanelMarketplaceInbox>(MARKETPLACE_INBOX_PANEL); - if (inbox) + // Expand the inbox since we have fresh items and the outbox is not expanded + if (mInboxEnabled) { getChild<LLButton>(INBOX_BUTTON_NAME)->setToggleState(true); onToggleInboxBtn(); @@ -413,65 +466,87 @@ void LLSidepanelInventory::onInboxChanged(const LLUUID& inbox_id) void LLSidepanelInventory::onOutboxChanged(const LLUUID& outbox_id) { - // Perhaps use this to track outbox changes? + // Expand the outbox since we have new items in it + if (mOutboxEnabled) + { + getChild<LLButton>(OUTBOX_BUTTON_NAME)->setToggleState(true); + onToggleOutboxBtn(); + } } -bool manageInboxOutboxPanels(LLLayoutStack * stack, - LLButton * pressedButton, LLLayoutPanel * pressedPanel, +bool LLSidepanelInventory::manageInboxOutboxPanels(LLButton * pressedButton, LLLayoutPanel * pressedPanel, LLButton * otherButton, LLLayoutPanel * otherPanel) { bool expand = pressedButton->getToggleState(); bool otherExpanded = otherButton->getToggleState(); - // - // NOTE: Ideally we could have two panel sizes stored for a collapsed and expanded minimum size. - // For now, leave this code disabled because it creates some bad artifacts when expanding - // and collapsing the inbox/outbox. - // - //S32 smallMinSize = (expand ? pressedPanel->getMinDim() : otherPanel->getMinDim()); - //S32 pressedMinSize = (expand ? 2 * smallMinSize : smallMinSize); - //otherPanel->setMinDim(smallMinSize); - //pressedPanel->setMinDim(pressedMinSize); + LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME); + LLLayoutStack* inout_stack = getChild<LLLayoutStack>(INBOX_OUTBOX_LAYOUT_STACK_NAME); + LLLayoutPanel* inout_panel = getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME); + + // Enable user_resize on main inventory panel only when a marketplace box is expanded + inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, expand); + inv_stack->collapsePanel(inout_panel, !expand); + // Collapse other marketplace panel if it is expanded if (expand && otherExpanded) { // Reshape pressedPanel to the otherPanel's height so we preserve the marketplace panel size pressedPanel->reshape(pressedPanel->getRect().getWidth(), otherPanel->getRect().getHeight()); - stack->collapsePanel(otherPanel, true); + inout_stack->collapsePanel(otherPanel, true); otherButton->setToggleState(false); } + else + { + // NOTE: This is an attempt to reshape the inventory panel to the proper size but it doesn't seem to propagate + // propery to the child panels. - stack->collapsePanel(pressedPanel, !expand); + S32 new_height = inout_panel->getRect().getHeight(); - // Enable user_resize on main inventory panel only when a marketplace box is expanded - stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, expand); + if (otherPanel->getVisible()) + { + new_height -= otherPanel->getMinDim(); + } + + pressedPanel->reshape(pressedPanel->getRect().getWidth(), new_height); + } + + // Expand/collapse the indicated panel + inout_stack->collapsePanel(pressedPanel, !expand); return expand; } void LLSidepanelInventory::onToggleInboxBtn() { - LLLayoutStack* stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME); LLButton* pressedButton = getChild<LLButton>(INBOX_BUTTON_NAME); LLLayoutPanel* pressedPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME); LLButton* otherButton = getChild<LLButton>(OUTBOX_BUTTON_NAME); LLLayoutPanel* otherPanel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME); - manageInboxOutboxPanels(stack, pressedButton, pressedPanel, otherButton, otherPanel); + bool inbox_expanded = manageInboxOutboxPanels(pressedButton, pressedPanel, otherButton, otherPanel); - gSavedPerAccountSettings.setString("LastInventoryInboxExpand", LLDate::now().asString()); + if (!inbox_expanded) + { + gSavedPerAccountSettings.setString("LastInventoryInboxCollapse", LLDate::now().asString()); + } } void LLSidepanelInventory::onToggleOutboxBtn() { - LLLayoutStack* stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME); LLButton* pressedButton = getChild<LLButton>(OUTBOX_BUTTON_NAME); LLLayoutPanel* pressedPanel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME); LLButton* otherButton = getChild<LLButton>(INBOX_BUTTON_NAME); LLLayoutPanel* otherPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME); - manageInboxOutboxPanels(stack, pressedButton, pressedPanel, otherButton, otherPanel); + bool inbox_was_expanded = otherButton->getToggleState(); + manageInboxOutboxPanels(pressedButton, pressedPanel, otherButton, otherPanel); + + if (inbox_was_expanded) + { + gSavedPerAccountSettings.setString("LastInventoryInboxCollapse", LLDate::now().asString()); + } } void LLSidepanelInventory::onOpen(const LLSD& key) @@ -636,6 +711,77 @@ void LLSidepanelInventory::showInventoryPanel() updateVerbs(); } +void LLSidepanelInventory::updateOutboxUserStatus() +{ + const bool isMerchant = (gSavedSettings.getString("InventoryMarketplaceUserStatus") == "merchant"); + const bool hasOutbox = !gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false).isNull(); + + LLView * outbox_placeholder = getChild<LLView>("outbox_inventory_placeholder_panel"); + LLView * outbox_placeholder_parent = outbox_placeholder->getParent(); + + LLTextBox * outbox_title_box = outbox_placeholder->getChild<LLTextBox>("outbox_inventory_placeholder_title"); + LLTextBox * outbox_text_box = outbox_placeholder->getChild<LLTextBox>("outbox_inventory_placeholder_text"); + + std::string outbox_text; + std::string outbox_title; + std::string outbox_tooltip; + + if (isMerchant) + { + if (hasOutbox) + { + outbox_text = LLTrans::getString("InventoryOutboxNoItems"); + outbox_title = LLTrans::getString("InventoryOutboxNoItemsTitle"); + outbox_tooltip = LLTrans::getString("InventoryOutboxNoItemsTooltip"); + } + else + { + outbox_text = LLTrans::getString("InventoryOutboxCreationError"); + outbox_title = LLTrans::getString("InventoryOutboxCreationErrorTitle"); + outbox_tooltip = LLTrans::getString("InventoryOutboxCreationErrorTooltip"); + } + } + else + { + // + // The string to become a merchant contains 3 URL's which need the domain name patched in. + // + + std::string domain = "secondlife.com"; + + if (!LLGridManager::getInstance()->isInProductionGrid()) + { + std::string gridLabel = LLGridManager::getInstance()->getGridLabel(); + domain = llformat("%s.lindenlab.com", utf8str_tolower(gridLabel).c_str()); + } + + LLStringUtil::format_map_t domain_arg; + domain_arg["[DOMAIN_NAME]"] = domain; + + std::string marketplace_url = LLTrans::getString("MarketplaceURL", domain_arg); + std::string marketplace_url_create = LLTrans::getString("MarketplaceURL_CreateStore", domain_arg); + std::string marketplace_url_info = LLTrans::getString("MarketplaceURL_LearnMore", domain_arg); + + LLStringUtil::format_map_t args1, args2, args3; + args1["[MARKETPLACE_URL]"] = marketplace_url; + args2["[LEARN_MORE_URL]"] = marketplace_url_info; + args3["[CREATE_STORE_URL]"] = marketplace_url_create; + + // NOTE: This is dumb, ridiculous and very finicky. The order of these is very important + // to have these three string substitutions work properly. + outbox_text = LLTrans::getString("InventoryOutboxNotMerchant", args1); + LLStringUtil::format(outbox_text, args2); + LLStringUtil::format(outbox_text, args3); + + outbox_title = LLTrans::getString("InventoryOutboxNotMerchantTitle"); + outbox_tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip"); + } + + outbox_text_box->setValue(outbox_text); + outbox_title_box->setValue(outbox_title); + outbox_placeholder_parent->setToolTip(outbox_tooltip); +} + void LLSidepanelInventory::updateVerbs() { mInfoBtn->setEnabled(FALSE); diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h index f80a3a9dd3..b7d11f7f9b 100644 --- a/indra/newview/llsidepanelinventory.h +++ b/indra/newview/llsidepanelinventory.h @@ -29,11 +29,13 @@ #include "llpanel.h" +class LLButton; class LLFolderViewItem; class LLInboxOutboxAddedObserver; class LLInventoryCategoriesObserver; class LLInventoryItem; class LLInventoryPanel; +class LLLayoutPanel; class LLPanelMainInventory; class LLSidepanelItemInfo; class LLSidepanelTaskInfo; @@ -58,7 +60,7 @@ public: LLInventoryPanel* getActivePanel(); // Returns an active inventory panel, if any. LLPanelMainInventory* getMainInventoryPanel() const { return mPanelMainInventory; } BOOL isMainInventoryPanelActive() const; - + void clearSelections(bool clearMain, bool clearInbox, bool clearOutbox); std::set<LLUUID> getInboxOrOutboxSelectionList(); @@ -74,10 +76,11 @@ public: void enableInbox(bool enabled); void enableOutbox(bool enabled); - + bool isInboxEnabled() const { return mInboxEnabled; } bool isOutboxEnabled() const { return mOutboxEnabled; } + void updateOutboxUserStatus(); void updateVerbs(); protected: @@ -93,6 +96,8 @@ protected: void onInboxChanged(const LLUUID& inbox_id); void onOutboxChanged(const LLUUID& outbox_id); + bool manageInboxOutboxPanels(LLButton * pressedButton, LLLayoutPanel * pressedPanel, LLButton * otherButton, LLLayoutPanel * otherPanel); + // // UI Elements // diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 14f17e8917..a06cb838cf 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1652,6 +1652,13 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv( return ACCEPT_NO; } + const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + if(gInventory.isObjectDescendentOf(item->getUUID(), outbox_id)) + { + return ACCEPT_NO; + } + + if( drop ) { if(mSource == SOURCE_LIBRARY) diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 384f7cd61d..e403034eaf 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1378,8 +1378,15 @@ public: { if (isGoodStatus(status)) { + std::string merchantStatus = content[gAgent.getID().getString()].asString(); + llinfos << "Marketplace merchant status: " << merchantStatus << llendl; + + // Save the merchant status before turning on the display + gSavedSettings.setString("InventoryMarketplaceUserStatus", merchantStatus); + // Complete success gSavedSettings.setBOOL("InventoryDisplayInbox", true); + gSavedSettings.setBOOL("InventoryDisplayOutbox", true); } else if (status == 401) { @@ -1394,6 +1401,39 @@ public: } }; + +void doOnetimeEarlyHTTPRequests() +{ + std::string url = "https://marketplace.secondlife.com/"; + + if (!LLGridManager::getInstance()->isInProductionGrid()) + { + std::string gridLabel = LLGridManager::getInstance()->getGridLabel(); + url = llformat("https://marketplace.%s.lindenlab.com/", utf8str_tolower(gridLabel).c_str()); + + // TEMP for Jim's pdp + //url = "http://pdp24.lindenlab.com:3000/"; + } + + url += "api/1/users/"; + url += gAgent.getID().getString(); + url += "/user_status"; + + llinfos << "http get: " << url << llendl; + LLHTTPClient::get(url, new LLInventoryUserStatusResponder(), LLViewerMedia::getHeaders()); +} + + +LLSD LLViewerMedia::getHeaders() +{ + LLSD headers = LLSD::emptyMap(); + headers["Accept"] = "*/*"; + headers["Cookie"] = sOpenIDCookie; + headers["User-Agent"] = getCurrentUserAgent(); + + return headers; +} + ///////////////////////////////////////////////////////////////////////////////////////// // static void LLViewerMedia::setOpenIDCookie() @@ -1441,24 +1481,7 @@ void LLViewerMedia::setOpenIDCookie() new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()), headers); - std::string url = "https://marketplace.secondlife.com/"; - - if (!LLGridManager::getInstance()->isInProductionGrid()) - { - std::string gridLabel = LLGridManager::getInstance()->getGridLabel(); - url = llformat("https://marketplace.%s.lindenlab.com/", utf8str_tolower(gridLabel).c_str()); - } - - url += "api/1/users/"; - url += gAgent.getID().getString(); - url += "/user_status"; - - headers = LLSD::emptyMap(); - headers["Accept"] = "*/*"; - headers["Cookie"] = sOpenIDCookie; - headers["User-Agent"] = getCurrentUserAgent(); - - LLHTTPClient::get(url, new LLInventoryUserStatusResponder(), headers); + doOnetimeEarlyHTTPRequests(); } } diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index aeac6ba29a..0b69b8f0c1 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -162,6 +162,8 @@ public: static LLPluginClassMedia* getSpareBrowserMediaSource(); static void setOnlyAudibleMediaTextureID(const LLUUID& texture_id); + + static LLSD getHeaders(); private: static void setOpenIDCookie(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 30216f02db..30216f02db 100755..100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 31b6fc77f5..6144c761b7 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -33,6 +33,9 @@ name="LtGray_50" value="0.75 0.75 0.75 0.50" /> <color + name="Gray" + value="0.5 0.5 0.5 1" /> + <color name="DkGray" value="0.125 0.125 0.125 1" /> <color @@ -197,7 +200,7 @@ reference="Black" /> <color name="ColorPaletteEntry02" - value="0.5 0.5 0.5 1" /> + reference="Gray" /> <color name="ColorPaletteEntry03" value="0.5 0 0 1" /> diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 799cd907dc..4d83ec2902 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -72,6 +72,10 @@ with the same filename but different name <texture name="BackButton_Over" file_name="icons/back_arrow_over.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" /> <texture name="BackButton_Press" file_name="icons/back_arrow_press.png" preload="false" scale.left="22" scale.top="12" scale.right="25" scale.bottom="12" /> + <texture name="Error_Tag_Background" file_name="widgets/Error_Tag_Background.png" preload="true" scale.left="12" scale.top="2" scale.right="36" scale.bottom="2" /> + <texture name="New_Tag_Background" file_name="widgets/New_Tag_Background.png" preload="true" scale.left="12" scale.top="2" scale.right="36" scale.bottom="2" /> + <texture name="New_Tag_Border" file_name="widgets/New_Tag_Border.png" preload="true" scale.left="12" scale.top="2" scale.right="36" scale.bottom="2" /> + <texture name="Badge_Background" file_name="widgets/Badge_Background.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" /> <texture name="Badge_Border" file_name="widgets/Badge_Border.png" preload="true" scale.left="9" scale.top="12" scale.right="248" scale.bottom="12" /> diff --git a/indra/newview/skins/default/textures/widgets/Badge_Background_New.png b/indra/newview/skins/default/textures/widgets/Badge_Background_New.png Binary files differdeleted file mode 100644 index 9f114f2e4a..0000000000 --- a/indra/newview/skins/default/textures/widgets/Badge_Background_New.png +++ /dev/null diff --git a/indra/newview/skins/default/textures/widgets/Error_Tag_Background.png b/indra/newview/skins/default/textures/widgets/Error_Tag_Background.png Binary files differnew file mode 100644 index 0000000000..c8dbc8e87a --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/Error_Tag_Background.png diff --git a/indra/newview/skins/default/textures/widgets/New_Tag_Background.png b/indra/newview/skins/default/textures/widgets/New_Tag_Background.png Binary files differnew file mode 100644 index 0000000000..cd639dd80f --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/New_Tag_Background.png diff --git a/indra/newview/skins/default/textures/widgets/New_Tag_Border.png b/indra/newview/skins/default/textures/widgets/New_Tag_Border.png Binary files differnew file mode 100644 index 0000000000..56df0d0127 --- /dev/null +++ b/indra/newview/skins/default/textures/widgets/New_Tag_Border.png diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml index 1d4a1d4827..1d4a1d4827 100755..100644 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 310616d57e..1dda0b3235 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -201,6 +201,40 @@ Save changes to current clothing/body part? <notification icon="alertmodal.tga" + name="ConfirmNoCopyToOutbox" + type="alertmodal"> + You don't have permission to copy this item to the Marketplace Outbox. Are you sure you want to move the following item? + [ITEM_NAME] + <usetemplate + name="okcancelbuttons" + notext="No" + yestext="Yes"/> + </notification> + + <notification + icon="alertmodal.tga" + name="OutboxUploadComplete" + type="alertmodal"> +Marketplace upload complete. + <usetemplate + name="okbutton" + yestext="Hooray!"/> + </notification> + + <notification + icon="alertmodal.tga" + name="OutboxUploadHadErrors" + type="alertmodal"> +Marketplace upload completed with errors! Please correct the problems in your outbox and retry. Thanks. + <usetemplate + name="okbutton" + yestext="Boo!"/> + </notification> + + + + <notification + icon="alertmodal.tga" name="CompileQueueSaveText" type="alertmodal"> There was a problem uploading the text for a script due to the following reason: [REASON]. Please try again later. @@ -5089,7 +5123,7 @@ Topic: [SUBJECT], Message: [MESSAGE] name="FriendOnline" type="notifytip"> <tag>friendship</tag> -<nolink>[NAME]</nolink> is Online +[NAME] is Online </notification> <notification @@ -5097,7 +5131,7 @@ Topic: [SUBJECT], Message: [MESSAGE] name="FriendOffline" type="notifytip"> <tag>friendship</tag> -<nolink>[NAME]</nolink> is Offline +[NAME] is Offline </notification> <notification @@ -6810,7 +6844,7 @@ Select residents to share with. See the log file for details. </notification> - <notification + <notification name="MeshUploadPermError" icon="alert.tga" type="alert"> @@ -6834,7 +6868,7 @@ Are you sure you want to share the following items: With the following Residents: -<nolink>[RESIDENTS]</nolink> +[RESIDENTS] <tag>confirm</tag> <usetemplate name="okcancelbuttons" diff --git a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml index d06190ec54..383e637ace 100644 --- a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml @@ -4,7 +4,7 @@ start_folder="Received Items" follows="all" layout="topleft" top="0" left="0" height="165" width="308" - top_pad="0" + top_pad="0" bg_opaque_color="DkGray2" bg_alpha_color="DkGray2" background_visible="true" 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 0df9aa2868..888230a00e 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -6,7 +6,7 @@ height="423" label="Things" layout="topleft" - min_height="350" + min_height="300" min_width="240" name="main inventory panel" width="330"> diff --git a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml index af32056428..66117615e4 100644 --- a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<inventory_panel +<outbox_inventory_panel name="inventory_outbox" start_folder="Outbox" follows="all" layout="topleft" top="0" left="0" height="165" width="308" - top_pad="0" + top_pad="0" bg_opaque_color="DkGray2" bg_alpha_color="DkGray2" background_visible="true" @@ -12,6 +12,7 @@ border="false" bevel_style="none" show_item_link_overlays="true" + tool_tip="Drag and drop items here to prepare them for sale on your storefront" > <scroll reserve_scroll_corner="false" /> -</inventory_panel> +</outbox_inventory_panel> diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml index 79a0ec7c72..7a176ff367 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml @@ -30,11 +30,12 @@ width="330"> <layout_panel name="main_inventory_layout_panel" + layout="topleft" min_dim="150" width="330" follows="bottom|left|right" user_resize="false" - height="480"> + height="300"> <panel class="panel_main_inventory" filename="panel_main_inventory.xml" @@ -44,14 +45,36 @@ name="panel_main_inventory" top="0" label="" - height="480" + height="300" width="330" /> </layout_panel> - <layout_panel + <layout_panel width="330" + layout="topleft" auto_resize="true" user_resize="false" follows="bottom|left|right" + name="inbox_outbox_layout_panel" + visible="false" + min_dim="35" + max_dim="235" + expanded_min_dim="125" + height="235"> + <layout_stack + follows="left|right|top|bottom" + layout="topleft" + left="0" + top="0" + orientation="vertical" + name="inbox_outbox_layout_stack" + height="235" + width="330"> + <layout_panel + width="330" + layout="topleft" + auto_resize="true" + user_resize="false" + follows="left|right|top" name="inbox_layout_panel" visible="false" min_dim="35" @@ -72,6 +95,7 @@ <string name="InboxLabelNoArg">Received Items</string> <button label="Received Items" + font="SansSerifMedium" name="inbox_btn" height="35" width="308" @@ -96,7 +120,6 @@ name="inbox_fresh_new_count" font="SansSerifMedium" halign="right" - text_color="EmphasisColor" top_pad="0" width="300"> [NUM] New @@ -129,41 +152,45 @@ </panel> </layout_panel> <layout_panel - width="330" - auto_resize="true" - user_resize="false" - follows="bottom|left|right" - name="outbox_layout_panel" - visible="false" - min_dim="35" - max_dim="200" - expanded_min_dim="90" - height="200"> + width="330" + layout="topleft" + auto_resize="true" + user_resize="false" + follows="all" + name="outbox_layout_panel" + visible="false" + min_dim="35" + max_dim="200" + expanded_min_dim="90" + height="200"> <panel follows="all" layout="topleft" - left="10" + left="0" name="marketplace_outbox" class="panel_marketplace_outbox" top="0" label="" height="200" - width="310"> + width="330"> + <string name="OutboxLabelWithArg">Merchant Outbox ([NUM])</string> + <string name="OutboxLabelNoArg">Merchant Outbox</string> <button label="Merchant Outbox" - is_toggle="true" - handle_right_mouse="false" + font="SansSerifMedium" name="outbox_btn" - follows="top|left|right" - image_unselected="MarketplaceBtn_Off" - image_selected="MarketplaceBtn_Selected" height="35" - tab_stop="false" width="308" + image_unselected="MarketplaceBtn_Off" + image_selected="MarketplaceBtn_Selected" halign="left" + handle_right_mouse="false" + follows="top|left|right" + is_toggle="true" + tab_stop="false" pad_left="35" top="0" - left="0" /> + left="10" /> <button image_unselected="OutboxPush_Off" image_selected="OutboxPush_Selected" @@ -213,24 +240,50 @@ bg_opaque_color="InventoryBackgroundColor" background_visible="true" background_opaque="true" - tool_tip="Drag and drop items here to prepare them for sale on your storefront" > - <text - name="outbox_inventory_placeholder" - type="string" + <panel + name="outbox_inventory_placeholder_panel" follows="all" layout="topleft" top="0" left="0" width="308" height="165" - wrap="true" - halign="center"> - Set up your merchant account to use this feature. - </text> + bg_opaque_color="InventoryBackgroundColor" + background_visible="true" + background_opaque="true" + > + <text + name="outbox_inventory_placeholder_title" + type="string" + follows="all" + layout="topleft" + top="10" + left="0" + width="308" + height="25" + wrap="true" + halign="center" + font="SansSerifBold"> + Loading... + </text> + <text + name="outbox_inventory_placeholder_text" + type="string" + follows="all" + layout="topleft" + top="35" + left="0" + width="308" + height="130" + wrap="true" + halign="left" /> + </panel> </panel> </panel> </layout_panel> + </layout_stack> + </layout_panel> </layout_stack> <panel follows="bottom|left|right" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index f049f857f0..2eff3f2290 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -164,12 +164,16 @@ Please try logging in again in a minute.</string> <string name="TooltipLand">Land:</string> <string name="TooltipMustSingleDrop">Only a single item can be dragged here</string> <string name="TooltipPrice" value="L$[AMOUNT]: "/> - + <string name="TooltipOutboxNoTransfer">One or more of these objects cannot be sold or transferred to another user.</string> + <string name="TooltipOutboxWorn">ou are wearing one or more of these objects. Remove them from your avatar and try moving them again.</string> + <string name="TooltipOutboxFolderLevels">This folder has too many levels of subfolders. Rearrange the interior folders to a maximum of 4 levels deep (Root Folder contains A contains B contains C).</string> + <string name="TooltipOutboxTooManyObjects">This folder contains more than 200 objects. Box some of the items to reduce the object count.</string> + <!-- tooltips for Urls --> <string name="TooltipHttpUrl">Click to view this web page</string> <string name="TooltipSLURL">Click to view this location's information</string> <string name="TooltipAgentUrl">Click to view this Resident's profile</string> - <string name="TooltipAgentInspect">Learn more about this Resident</string> + <string name="TooltipAgentInspect">Learn more about this Resident</string> <string name="TooltipAgentMute">Click to mute this Resident</string> <string name="TooltipAgentUnmute">Click to unmute this Resident</string> <string name="TooltipAgentIM">Click to IM this Resident</string> @@ -2025,7 +2029,18 @@ Returns a string with the requested data about the region <string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string> <string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string> <string name="InventoryInboxNoItems">Items purchased through the marketplace will be delivered here.</string> - <string name="InventoryOutboxNoItems">Drag items here in preparation for listing on your marketplace storefront.</string> + <string name="MarketplaceURL">http://marketplace.[DOMAIN_NAME]</string> + <string name="MarketplaceURL_CreateStore">http://marketplace.[DOMAIN_NAME]/create_store</string> + <string name="MarketplaceURL_LearnMore">http://marketplace.[DOMAIN_NAME]/learn_more</string> + <string name="InventoryOutboxCreationErrorTitle">Your Merchant Outbox is not properly configured</string> + <string name="InventoryOutboxCreationErrorTooltip">Merchant Outbox configuration error</string> + <string name="InventoryOutboxCreationError">Please contact Customer Service to correct the problem.</string> + <string name="InventoryOutboxNotMerchantTitle">Anyone can sell items on the Marketplace</string> + <string name="InventoryOutboxNotMerchantTooltip">Become a merchant!</string> + <string name="InventoryOutboxNotMerchant">[[MARKETPLACE_URL] The Second Life Marketplace] offers more than one million virtual products for sale, all of them created by Residents. You, too, can sell items you create, as well as some of the items you have purchased. It’s easy and setup is free. [[LEARN_MORE_URL] Learn more] or [[CREATE_STORE_URL] create a store] on the Marketplace to get started.</string> + <string name="InventoryOutboxNoItemsTitle">A new way to send items to the Marketplace</string> + <string name="InventoryOutboxNoItemsTooltip">Drag and drop items here to prepare them for sale on the Marketplace</string> + <string name="InventoryOutboxNoItems">Drag items or folders that you wish to sell into this area. A copy of the item will appear, leaving your inventory unchanged, unless you have dragged a no-copy item. When you are ready to send the items to the Marketplace, click the Upload button. Once your items have been moved to your Marketplace Inventory, they will disappear from this folder.</string> <!-- use value="" because they have preceding spaces --> <string name="no_transfer" value=" (no transfer)" /> <string name="no_modify" value=" (no modify)" /> diff --git a/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml b/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml index 95f5cf2ecd..77d8024cb2 100644 --- a/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml +++ b/indra/newview/skins/default/xui/en/widgets/inbox_folder_view_folder.xml @@ -10,10 +10,12 @@ label="New" label_offset_horiz="-1" location="right" - padding_horiz="4" - padding_vert="1" - location_percent_hcenter="70" - border_image="" - image="Badge_Background_New" + padding_horiz="12.5" + padding_vert="2" + location_offset_hcenter="-23" + border_image="New_Tag_Border" + border_color="DkGray2" + image="New_Tag_Background" + image_color="Black" /> </inbox_folder_view_folder> diff --git a/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml b/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml new file mode 100644 index 0000000000..0792996107 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/outbox_folder_view_folder.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<outbox_folder_view_folder + folder_arrow_image="Folder_Arrow" + folder_indentation="8" + item_height="20" + item_top_pad="4" + selection_image="Rounded_Square" + > + <error_badge + label=" " + label_offset_horiz="-1" + location="right" + padding_horiz="12.5" + padding_vert="2" + location_offset_hcenter="-23" + image="Error_Tag_Background" + image_color="Black" + /> +</outbox_folder_view_folder> diff --git a/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml b/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml new file mode 100644 index 0000000000..e3f2072819 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/outbox_inventory_panel.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<outbox_inventory_panel show_load_status="false" /> diff --git a/scripts/gpu_table_tester b/scripts/gpu_table_tester index 52b1c8f31d..52b1c8f31d 100644..100755 --- a/scripts/gpu_table_tester +++ b/scripts/gpu_table_tester |