diff options
Diffstat (limited to 'indra')
20 files changed, 1216 insertions, 7 deletions
diff --git a/indra/llcommon/llfoldertype.cpp b/indra/llcommon/llfoldertype.cpp index 9c38349cf7..5b80189d2a 100755 --- a/indra/llcommon/llfoldertype.cpp +++ b/indra/llcommon/llfoldertype.cpp @@ -96,6 +96,8 @@ LLFolderDictionary::LLFolderDictionary() addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", FALSE)); addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE)); + + addEntry(LLFolderType::FT_MARKETPLACE_LISTINGS, new FolderEntry("merchant", FALSE)); addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE)); }; diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h index a0c847914f..91dc1da543 100644 --- a/indra/llcommon/llfoldertype.h +++ b/indra/llcommon/llfoldertype.h @@ -87,6 +87,8 @@ public: FT_BASIC_ROOT = 52, + FT_MARKETPLACE_LISTINGS = 53, + FT_COUNT, FT_NONE = -1 diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp index de96f75602..9ea83e9621 100755 --- a/indra/newview/llfloateroutbox.cpp +++ b/indra/newview/llfloateroutbox.cpp @@ -1,6 +1,8 @@ /** * @file llfloateroutbox.cpp - * @brief Implementation of the merchant outbox window + * @brief Implementation of the merchant outbox window and of the marketplace listings window + * + * *TODO : Eventually, take out all the merchant outbox stuff and rename that file to llfloatermarketplacelistings * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -105,6 +107,39 @@ private: }; ///---------------------------------------------------------------------------- +/// LLMarketplaceListingsAddedObserver helper class +///---------------------------------------------------------------------------- + +class LLMarketplaceListingsAddedObserver : public LLInventoryCategoryAddedObserver +{ +public: + LLMarketplaceListingsAddedObserver(LLFloaterMarketplaceListings * marketplace_listings_floater) + : LLInventoryCategoryAddedObserver() + , mMarketplaceListingsFloater(marketplace_listings_floater) + { + } + + void done() + { + for (cat_vec_t::iterator it = mAddedCategories.begin(); it != mAddedCategories.end(); ++it) + { + LLViewerInventoryCategory* added_category = *it; + + LLFolderType::EType added_category_type = added_category->getPreferredType(); + + if (added_category_type == LLFolderType::FT_MARKETPLACE_LISTINGS) + { + mMarketplaceListingsFloater->initializeMarketPlace(); + } + } + } + +private: + LLFloaterMarketplaceListings * mMarketplaceListingsFloater; +}; + + +///---------------------------------------------------------------------------- /// LLFloaterOutbox ///---------------------------------------------------------------------------- @@ -617,3 +652,490 @@ void LLFloaterOutbox::showNotification(const LLNotificationPtr& notification) notification_handler->processNotification(notification); } +///---------------------------------------------------------------------------- +/// LLFloaterMarketplaceListings +///---------------------------------------------------------------------------- + +LLFloaterMarketplaceListings::LLFloaterMarketplaceListings(const LLSD& key) +: LLFloater(key) +, mCategoriesObserver(NULL) +, mCategoryAddedObserver(NULL) +, mRootFolderId(LLUUID::null) +, mInventoryStatus(NULL) +, mInventoryInitializationInProgress(NULL) +, mInventoryPlaceholder(NULL) +, mInventoryText(NULL) +, mInventoryTitle(NULL) +, mSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME) +, mFilterType(LLInventoryFilter::FILTERTYPE_NONE) +{ + mCommitCallbackRegistrar.add("Marketplace.ViewSort.Action", boost::bind(&LLFloaterMarketplaceListings::onViewSortMenuItemClicked, this, _2)); + mEnableCallbackRegistrar.add("Marketplace.ViewSort.CheckItem", boost::bind(&LLFloaterMarketplaceListings::onViewSortMenuItemCheck, this, _2)); +} + +LLFloaterMarketplaceListings::~LLFloaterMarketplaceListings() +{ + if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver)) + { + gInventory.removeObserver(mCategoriesObserver); + } + delete mCategoriesObserver; + + if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) + { + gInventory.removeObserver(mCategoryAddedObserver); + } + delete mCategoryAddedObserver; +} + +BOOL LLFloaterMarketplaceListings::postBuild() +{ + mInventoryStatus = getChild<LLTextBox>("marketplace_status"); + mInventoryInitializationInProgress = getChild<LLView>("initialization_progress_indicator"); + mInventoryPlaceholder = getChild<LLView>("marketplace_listings_inventory_placeholder_panel"); + mInventoryText = mInventoryPlaceholder->getChild<LLTextBox>("marketplace_listings_inventory_placeholder_text"); + mInventoryTitle = mInventoryPlaceholder->getChild<LLTextBox>("marketplace_listings_inventory_placeholder_title"); + + LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterMarketplaceListings::onFocusReceived, this)); + + // Observe category creation to catch marketplace listings creation (moot if already existing) + mCategoryAddedObserver = new LLMarketplaceListingsAddedObserver(this); + gInventory.addObserver(mCategoryAddedObserver); + + // Merov : Debug : fetch aggressively so we can create test data right onOpen() + llinfos << "Merov : postBuild, do fetchContent() ahead of time" << llendl; + fetchContents(); + + return TRUE; +} + +void LLFloaterMarketplaceListings::clean() +{ + // Note: we cannot delete the mOutboxInventoryPanel as that point + // as this is called through callback observers of the panel itself. + // Doing so would crash rapidly. + + // Invalidate the outbox data + mRootFolderId.setNull(); +} + +void LLFloaterMarketplaceListings::onClose(bool app_quitting) +{ +} + +void LLFloaterMarketplaceListings::onOpen(const LLSD& key) +{ + // + // Initialize the Market Place or go update the outbox + // + if (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_NOT_INITIALIZED) + { + initializeMarketPlace(); + } + else + { + setup(); + } + + // Merov : Debug : Create fake Marketplace data if none is present + if (LLMarketplaceData::instance().isEmpty() && (getFolderCount() > 0)) + { + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(mRootFolderId, cats, items); + + int index = 0; + for (LLInventoryModel::cat_array_t::iterator iter = cats->begin(); iter != cats->end(); iter++, index++) + { + LLViewerInventoryCategory* category = *iter; + if (index%3) + { + LLMarketplaceData::instance().addTestItem(category->getUUID()); + if (index%3 == 1) + { + LLMarketplaceData::instance().setListingID(category->getUUID(),"TestingID1234"); + } + LLMarketplaceData::instance().setActivation(category->getUUID(),(index%2)); + } + } + } + + // + // Update the floater view + // + updateView(); + + // + // Trigger fetch of the contents + // + fetchContents(); +} + +void LLFloaterMarketplaceListings::onFocusReceived() +{ + fetchContents(); +} + + +void LLFloaterMarketplaceListings::onViewSortMenuItemClicked(const LLSD& userdata) +{ + std::string chosen_item = userdata.asString(); + + LLInventoryPanel* panel = mInventoryPanel.get(); + + llinfos << "Merov : MenuItemClicked, item = " << chosen_item << ", panel on = " << panel->hasFocus() << llendl; + + // Sort options + if (chosen_item == "sort_by_stock_amount") + { + mSortOrder = (mSortOrder == LLInventoryFilter::SO_FOLDERS_BY_NAME ? LLInventoryFilter::SO_FOLDERS_BY_WEIGHT : LLInventoryFilter::SO_FOLDERS_BY_NAME); + panel->getFolderViewModel()->setSorter(mSortOrder); + } + // View/filter options + else if (chosen_item == "show_all") + { + mFilterType = LLInventoryFilter::FILTERTYPE_NONE; + panel->getFilter().resetDefault(); + } + else if (chosen_item == "show_non_associated_listings") + { + mFilterType = LLInventoryFilter::FILTERTYPE_MARKETPLACE_UNASSOCIATED; + panel->getFilter().setFilterMarketplaceUnassociatedFolders(); + } + else if (chosen_item == "show_active") + { + mFilterType = LLInventoryFilter::FILTERTYPE_MARKETPLACE_ACTIVE; + panel->getFilter().setFilterMarketplaceActiveFolders(); + } + else if (chosen_item == "show_inactive_listings") + { + mFilterType = LLInventoryFilter::FILTERTYPE_MARKETPLACE_INACTIVE; + panel->getFilter().setFilterMarketplaceInactiveFolders(); + } +} + +bool LLFloaterMarketplaceListings::onViewSortMenuItemCheck(const LLSD& userdata) +{ + std::string chosen_item = userdata.asString(); + + LLInventoryPanel* panel = mInventoryPanel.get(); + + llinfos << "Merov : MenuItemCheck, item = " << chosen_item << ", panel on = " << panel->hasFocus() << llendl; + + if (!panel->hasFocus()) + { + return false; + } + + if (chosen_item == "sort_by_stock_amount") + return mSortOrder == LLInventoryFilter::SO_FOLDERS_BY_WEIGHT; + if (chosen_item == "show_all") + return mFilterType == LLInventoryFilter::FILTERTYPE_NONE; + if (chosen_item == "show_non_associated_listings") + return mFilterType == LLInventoryFilter::FILTERTYPE_MARKETPLACE_UNASSOCIATED; + if (chosen_item == "show_active") + return mFilterType == LLInventoryFilter::FILTERTYPE_MARKETPLACE_ACTIVE; + if (chosen_item == "show_inactive_listings") + return mFilterType == LLInventoryFilter::FILTERTYPE_MARKETPLACE_INACTIVE; + return false; +} + + +void LLFloaterMarketplaceListings::fetchContents() +{ + if (mRootFolderId.notNull()) + { + LLInventoryModelBackgroundFetch::instance().start(mRootFolderId); + } +} + +void LLFloaterMarketplaceListings::setup() +{ + if (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() != MarketplaceStatusCodes::MARKET_PLACE_MERCHANT) + { + // If we are *not* a merchant or we have no market place connection established yet, do nothing + return; + } + + // We are a merchant. Get the Marketplace listings folder, create it if needs be. + LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, true); + if (outbox_id.isNull()) + { + // We should never get there unless the inventory fails badly + llinfos << "Merov : Inventory problem: failure to create the marketplace listings folder for a merchant!" << llendl; + llerrs << "Inventory problem: failure to create the marketplace listings folder for a merchant!" << llendl; + return; + } + + // Consolidate Marketplace listings + // We shouldn't have to do that but with a client/server system relying on a "well known folder" convention, things get messy and conventions get broken down eventually + gInventory.consolidateForType(outbox_id, LLFolderType::FT_MARKETPLACE_LISTINGS); + + if (outbox_id == mRootFolderId) + { + llinfos << "Merov : Inventory warning: Marketplace listings folder already set" << llendl; + llwarns << "Inventory warning: Marketplace listings folder already set" << llendl; + return; + } + mRootFolderId = outbox_id; + + // No longer need to observe new category creation + if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) + { + gInventory.removeObserver(mCategoryAddedObserver); + delete mCategoryAddedObserver; + mCategoryAddedObserver = NULL; + } + llassert(!mCategoryAddedObserver); + + // Create observer for marketplace listings modifications : clear the old one and create a new one + if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver)) + { + gInventory.removeObserver(mCategoriesObserver); + delete mCategoriesObserver; + } + mCategoriesObserver = new LLInventoryCategoriesObserver(); + gInventory.addObserver(mCategoriesObserver); + mCategoriesObserver->addCategory(mRootFolderId, boost::bind(&LLFloaterMarketplaceListings::onChanged, this)); + llassert(mCategoriesObserver); + + // Set up the marketplace listings inventory view + LLPanel* inventory_panel = LLUICtrlFactory::createFromFile<LLPanel>("panel_marketplace_listings.xml", mInventoryPlaceholder->getParent(), LLInventoryPanel::child_registry_t::instance()); + LLInventoryPanel* items_panel = inventory_panel->getChild<LLInventoryPanel>("All Items"); + mInventoryPanel = items_panel->getInventoryPanelHandle(); + llassert(mInventoryPanel.get() != NULL); + + // Reshape the inventory to the proper size + LLRect inventory_placeholder_rect = mInventoryPlaceholder->getRect(); + inventory_panel->setShape(inventory_placeholder_rect); + + // Set the sort order newest to oldest + items_panel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME); + items_panel->getFilter().markDefault(); + + // Set filters on the 3 prefiltered panels + items_panel = inventory_panel->getChild<LLInventoryPanel>("Active Items"); + items_panel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME); + items_panel->getFilter().setFilterMarketplaceActiveFolders(); + items_panel->getFilter().markDefault(); + items_panel = inventory_panel->getChild<LLInventoryPanel>("Inactive Items"); + items_panel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME); + items_panel->getFilter().setFilterMarketplaceInactiveFolders(); + items_panel->getFilter().markDefault(); + items_panel = inventory_panel->getChild<LLInventoryPanel>("Unassociated Items"); + items_panel->getFolderViewModel()->setSorter(LLInventoryFilter::SO_FOLDERS_BY_NAME); + items_panel->getFilter().setFilterMarketplaceUnassociatedFolders(); + items_panel->getFilter().markDefault(); + + // Get the content of the marketplace listings folder + fetchContents(); +} + +void LLFloaterMarketplaceListings::initializeMarketPlace() +{ + // + // Initialize the marketplace import API + // + LLMarketplaceInventoryImporter& importer = LLMarketplaceInventoryImporter::instance(); + + if (!importer.isInitialized()) + { + importer.setInitializationErrorCallback(boost::bind(&LLFloaterMarketplaceListings::initializationReportError, this, _1, _2)); + importer.setStatusChangedCallback(boost::bind(&LLFloaterMarketplaceListings::importStatusChanged, this, _1)); + importer.setStatusReportCallback(boost::bind(&LLFloaterMarketplaceListings::importReportResults, this, _1, _2)); + importer.initialize(); + } +} + +S32 LLFloaterMarketplaceListings::getFolderCount() +{ + if (mInventoryPanel.get() && mRootFolderId.notNull()) + { + LLInventoryModel::cat_array_t * cats; + LLInventoryModel::item_array_t * items; + gInventory.getDirectDescendentsOf(mRootFolderId, cats, items); + + return (cats->count() + items->count()); + } + else + { + return 0; + } +} + +void LLFloaterMarketplaceListings::setStatusString(const std::string& statusString) +{ + mInventoryStatus->setText(statusString); +} + +void LLFloaterMarketplaceListings::updateView() +{ + LLInventoryPanel* panel = mInventoryPanel.get(); + + if (getFolderCount() > 0) + { + panel->setVisible(TRUE); + mInventoryPlaceholder->setVisible(FALSE); + } + else + { + if (panel) + { + panel->setVisible(FALSE); + } + + std::string text; + std::string title; + std::string tooltip; + + const LLSD& subs = getMarketplaceStringSubstitutions(); + U32 mkt_status = LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus(); + + // *TODO : check those messages and create better appropriate ones in strings.xml + if (mRootFolderId.notNull()) + { + // Does the outbox needs recreation? + if ((panel == NULL) || !gInventory.getCategory(mRootFolderId)) + { + setup(); + } + // "Marketplace listings is empty!" message strings + text = LLTrans::getString("InventoryMarketplaceListingsNoItems", subs); + title = LLTrans::getString("InventoryMarketplaceListingsNoItemsTitle"); + tooltip = LLTrans::getString("InventoryMarketplaceListingsNoItemsTooltip"); + } + else if (mkt_status <= MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING) + { + // "Initializing!" message strings + text = LLTrans::getString("InventoryOutboxInitializing", subs); + title = LLTrans::getString("InventoryOutboxInitializingTitle"); + tooltip = LLTrans::getString("InventoryOutboxInitializingTooltip"); + } + else if (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_NOT_MERCHANT) + { + // "Not a merchant!" message strings + text = LLTrans::getString("InventoryOutboxNotMerchant", subs); + title = LLTrans::getString("InventoryOutboxNotMerchantTitle"); + tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip"); + } + else + { + // "Errors!" message strings + text = LLTrans::getString("InventoryOutboxError", subs); + title = LLTrans::getString("InventoryOutboxErrorTitle"); + tooltip = LLTrans::getString("InventoryOutboxErrorTooltip"); + } + + mInventoryText->setValue(text); + mInventoryTitle->setValue(title); + mInventoryPlaceholder->getParent()->setToolTip(tooltip); + } +} + +bool LLFloaterMarketplaceListings::isAccepted(EAcceptance accept) +{ + // *TODO : Need a bit more test on what we accept: depends of what and where... + return (accept >= ACCEPT_YES_COPY_SINGLE); +} + + +BOOL LLFloaterMarketplaceListings::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + if ((mInventoryPanel.get() == NULL) || mRootFolderId.isNull()) + { + return FALSE; + } + + LLView * handled_view = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + BOOL handled = (handled_view != NULL); + + // Determine if the mouse is inside the inventory panel itself or just within the floater + bool pointInInventoryPanel = false; + bool pointInInventoryPanelChild = false; + LLInventoryPanel* panel = mInventoryPanel.get(); + LLFolderView* root_folder = panel->getRootFolder(); + if (panel->getVisible()) + { + S32 inv_x, inv_y; + localPointToOtherView(x, y, &inv_x, &inv_y, panel); + + pointInInventoryPanel = panel->getRect().pointInRect(inv_x, inv_y); + + LLView * inventory_panel_child_at_point = panel->childFromPoint(inv_x, inv_y, true); + pointInInventoryPanelChild = (inventory_panel_child_at_point != root_folder); + } + + // Pass all drag and drop for this floater to the outbox inventory control + if (!handled || !isAccepted(*accept)) + { + // Handle the drag and drop directly to the root of the outbox if we're not in the inventory panel + // (otherwise the inventory panel itself will handle the drag and drop operation, without any override) + if (!pointInInventoryPanel) + { + handled = root_folder->handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + } + + return handled; +} + +BOOL LLFloaterMarketplaceListings::handleHover(S32 x, S32 y, MASK mask) +{ + return LLFloater::handleHover(x, y, mask); +} + +void LLFloaterMarketplaceListings::onMouseLeave(S32 x, S32 y, MASK mask) +{ + LLFloater::onMouseLeave(x, y, mask); +} + +void LLFloaterMarketplaceListings::onChanged() +{ + LLViewerInventoryCategory* category = gInventory.getCategory(mRootFolderId); + if (mRootFolderId.notNull() && category) + { + fetchContents(); + updateView(); + } + else + { + clean(); + } +} + +void LLFloaterMarketplaceListings::initializationReportError(U32 status, const LLSD& content) +{ + updateView(); +} + +void LLFloaterMarketplaceListings::importStatusChanged(bool inProgress) +{ + if (mRootFolderId.isNull() && (LLMarketplaceInventoryImporter::getInstance()->getMarketPlaceStatus() == MarketplaceStatusCodes::MARKET_PLACE_MERCHANT)) + { + setup(); + } + + if (inProgress) + { + setStatusString(getString("MarketplaceListingsInitializing")); + mInventoryInitializationInProgress->setVisible(true); + } + else + { + setStatusString(""); + mInventoryInitializationInProgress->setVisible(false); + } + + updateView(); +} + +void LLFloaterMarketplaceListings::importReportResults(U32 status, const LLSD& content) +{ + updateView(); +} + + diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h index 40519c8fd2..4908e4342b 100755 --- a/indra/newview/llfloateroutbox.h +++ b/indra/newview/llfloateroutbox.h @@ -1,7 +1,8 @@ /** * @file llfloateroutbox.h - * @brief LLFloaterOutbox - * class definition + * @brief Implementation of the merchant outbox window and of the marketplace listings window + * + * *TODO : Eventually, take out all the merchant outbox stuff and rename that file to llfloatermarketplacelistings * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -30,6 +31,7 @@ #include "llfloater.h" #include "llfoldertype.h" +#include "llinventoryfilter.h" #include "llnotificationptr.h" @@ -113,4 +115,69 @@ private: LLWindowShade * mWindowShade; }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFloaterMarketplaceListings +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFloaterMarketplaceListings : public LLFloater +{ +public: + LLFloaterMarketplaceListings(const LLSD& key); + ~LLFloaterMarketplaceListings(); + + void initializeMarketPlace(); + + // virtuals + BOOL postBuild(); + BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + + void showNotification(const LLNotificationPtr& notification); + + BOOL handleHover(S32 x, S32 y, MASK mask); + void onMouseLeave(S32 x, S32 y, MASK mask); + +protected: + void setup(); + void clean(); + void fetchContents(); + + void importReportResults(U32 status, const LLSD& content); + void importStatusChanged(bool inProgress); + void initializationReportError(U32 status, const LLSD& content); + void setStatusString(const std::string& statusString); + + void onClose(bool app_quitting); + void onOpen(const LLSD& key); + void onFocusReceived(); + void onChanged(); + + bool isAccepted(EAcceptance accept); + + void updateView(); + +private: + S32 getFolderCount(); + // UI callbacks + void onViewSortMenuItemClicked(const LLSD& userdata); + bool onViewSortMenuItemCheck(const LLSD& userdata); + + LLInventoryCategoriesObserver * mCategoriesObserver; + LLInventoryCategoryAddedObserver * mCategoryAddedObserver; + + LLTextBox * mInventoryStatus; + LLView * mInventoryInitializationInProgress; + LLView * mInventoryPlaceholder; + LLTextBox * mInventoryText; + LLTextBox * mInventoryTitle; + + LLUUID mRootFolderId; + LLHandle<LLInventoryPanel> mInventoryPanel; + LLInventoryFilter::ESortOrderType mSortOrder; + LLInventoryFilter::EFilterType mFilterType; +}; + #endif // LL_LLFLOATEROUTBOX_H diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 44943d8722..3d418105e3 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -959,6 +959,18 @@ BOOL LLInvFVBridge::isInboxFolder() const return gInventory.isObjectDescendentOf(mUUID, inbox_id); } +BOOL LLInvFVBridge::isMarketplaceListingsFolder() const +{ + const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + + if (folder_id.isNull()) + { + return FALSE; + } + + return gInventory.isObjectDescendentOf(mUUID, folder_id); +} + BOOL LLInvFVBridge::isOutboxFolder() const { const LLUUID outbox_id = getOutboxFolder(); @@ -1931,6 +1943,58 @@ void LLFolderBridge::buildDisplayName() const } } +std::string LLFolderBridge::getLabelSuffix() const +{ + // *TODO : We need to display some suffix also for the version folder! + /* + LLInventoryCategory* cat = gInventory.getCategory(getUUID()); + if(cat) + { + const LLUUID& parent_folder_id = cat->getParentUUID(); + accessories = (parent_folder_id == gInventory.getLibraryRootFolderID()); + } + */ + if (isMarketplaceListingsFolder()) + { + if (LLMarketplaceData::instance().isListed(getUUID())) + { + llinfos << "Merov : in merchant folder and listed : id = " << getUUID() << llendl; + std::string suffix = LLMarketplaceData::instance().getListingID(getUUID()); + if (suffix.empty()) + { + suffix = LLTrans::getString("MarketplaceNoID"); + } + suffix = " (" + suffix + ")"; + if (LLMarketplaceData::instance().getActivationState(getUUID())) + { + suffix += " (" + LLTrans::getString("MarketplaceActive") + ")"; + } + return LLInvFVBridge::getLabelSuffix() + suffix; + } + else + { + llinfos << "Merov : in merchant folder but not listed : id = " << getUUID() << llendl; + return LLInvFVBridge::getLabelSuffix(); + } + } + else + { + return LLInvFVBridge::getLabelSuffix(); + } +} + +LLFontGL::StyleFlags LLFolderBridge::getLabelStyle() const +{ + if (isMarketplaceListingsFolder() && LLMarketplaceData::instance().getActivationState(getUUID())) + { + return LLFontGL::BOLD; + } + else + { + return LLFontGL::NORMAL; + } +} + void LLFolderBridge::update() { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index bc875e8f37..26c48fdc57 100755 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -160,6 +160,7 @@ protected: BOOL isInboxFolder() const; // true if COF or descendant of marketplace inbox BOOL isOutboxFolder() const; // true if COF or descendant of marketplace outbox BOOL isOutboxFolderDirectParent() const; + BOOL isMarketplaceListingsFolder() const; // true if descendant of Marketplace listings folder const LLUUID getOutboxFolder() const; virtual BOOL isItemPermissive() const; @@ -274,7 +275,8 @@ public: virtual LLUIImagePtr getIcon() const; virtual LLUIImagePtr getIconOpen() const; virtual LLUIImagePtr getIconOverlay() const; - + virtual std::string getLabelSuffix() const; + virtual LLFontGL::StyleFlags getLabelStyle() const; static LLUIImagePtr getIcon(LLFolderType::EType preferred_type); virtual BOOL renameItem(const std::string& new_name); diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 15463e0d33..6a800cf5ba 100755 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -33,6 +33,7 @@ #include "llfolderviewitem.h" #include "llinventorymodel.h" #include "llinventorymodelbackgroundfetch.h" +#include "llmarketplacefunctions.h" #include "llviewercontrol.h" #include "llfolderview.h" #include "llinventorybridge.h" @@ -131,6 +132,30 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const LLInventoryModelBackgroundFetch::instance().start(folder_id); } + // Marketplace folder filtering + const U32 filterTypes = mFilterOps.mFilterTypes; + if (filterTypes & FILTERTYPE_MARKETPLACE_ACTIVE) + { + if (!LLMarketplaceData::instance().getActivationState(folder_id)) + { + return false; + } + } + if (filterTypes & FILTERTYPE_MARKETPLACE_INACTIVE) + { + if (LLMarketplaceData::instance().getActivationState(folder_id)) + { + return false; + } + } + if (filterTypes & FILTERTYPE_MARKETPLACE_UNASSOCIATED) + { + if (!LLMarketplaceData::instance().getListingID(folder_id).empty()) + { + return false; + } + } + // Always check against the clipboard const BOOL passed_clipboard = checkAgainstClipboard(folder_id); @@ -250,7 +275,7 @@ bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInvent } } } - + return TRUE; } @@ -475,6 +500,21 @@ void LLInventoryFilter::setFilterEmptySystemFolders() mFilterOps.mFilterTypes |= FILTERTYPE_EMPTYFOLDERS; } +void LLInventoryFilter::setFilterMarketplaceActiveFolders() +{ + mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_ACTIVE; +} + +void LLInventoryFilter::setFilterMarketplaceInactiveFolders() +{ + mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_INACTIVE; +} + +void LLInventoryFilter::setFilterMarketplaceUnassociatedFolders() +{ + mFilterOps.mFilterTypes |= FILTERTYPE_MARKETPLACE_UNASSOCIATED; +} + void LLInventoryFilter::setFilterUUID(const LLUUID& object_id) { if (mFilterOps.mFilterUUID == LLUUID::null) diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index ce516af0b9..113596b0eb 100755 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -52,7 +52,10 @@ public: FILTERTYPE_UUID = 0x1 << 2, // find the object with UUID and any links to it FILTERTYPE_DATE = 0x1 << 3, // search by date range FILTERTYPE_WEARABLE = 0x1 << 4, // search by wearable type - FILTERTYPE_EMPTYFOLDERS = 0x1 << 5 // pass if folder is not a system folder to be hidden if + FILTERTYPE_EMPTYFOLDERS = 0x1 << 5, // pass if folder is not a system folder to be hidden if empty + FILTERTYPE_MARKETPLACE_ACTIVE = 0x1 << 6, // pass if folder is a marketplace active folder + FILTERTYPE_MARKETPLACE_INACTIVE = 0x1 << 7, // pass if folder is a marketplace inactive folder + FILTERTYPE_MARKETPLACE_UNASSOCIATED = 0x1 << 8 // pass if folder is a marketplace non associated (no market ID) folder }; enum EFilterLink @@ -67,7 +70,8 @@ public: SO_NAME = 0, // Sort inventory by name SO_DATE = 0x1, // Sort inventory by date SO_FOLDERS_BY_NAME = 0x1 << 1, // Force folder sort by name - SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2 // Force system folders to be on top + SO_SYSTEM_FOLDERS_TO_TOP = 0x1 << 2,// Force system folders to be on top + SO_FOLDERS_BY_WEIGHT = 0x1 << 3, // Force folder sort by weight, usually, amount of some elements in their descendents }; struct FilterOps @@ -160,6 +164,9 @@ public: void setFilterUUID(const LLUUID &object_id); void setFilterWearableTypes(U64 types); void setFilterEmptySystemFolders(); + void setFilterMarketplaceActiveFolders(); + void setFilterMarketplaceInactiveFolders(); + void setFilterMarketplaceUnassociatedFolders(); void updateFilterTypes(U64 types, U64& current_types); void setFilterSubString(const std::string& string); diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index f1a4889f5a..203eb4ec4e 100755 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -111,6 +111,16 @@ void append_path(const LLUUID& id, std::string& path) path.append(temp); } +void update_marketplace_category(const LLUUID& cat_id) +{ + // When changing the marketplace status of a folder, the only thing that needs to happen is + // for all observers of the folder to, possibly, change the display label of said folder. + // At least that's the status for the moment so, even if that function seems small, we + // prefer to encapsulate that behavior here. + gInventory.addChangedMask(LLInventoryObserver::LABEL, cat_id); + gInventory.notifyObservers(); +} + void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name) { LLViewerInventoryCategory* cat; diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index f1066a4dc9..1443c186cf 100755 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -58,6 +58,9 @@ void show_task_item_profile(const LLUUID& item_uuid, const LLUUID& object_id); void show_item_original(const LLUUID& item_uuid); void reset_inventory_filter(); +// Just nudge the category in the global inventory to signal that its marketplace status changed +void update_marketplace_category(const LLUUID& cat_id); + void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name); void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id = LLUUID::null); diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 81ee7ac07e..bf8f7819ef 100755 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -288,6 +288,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) { getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_INBOX)); getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_OUTBOX)); + getFilter().setFilterCategoryTypes(getFilter().getFilterCategoryTypes() & ~(1ULL << LLFolderType::FT_MARKETPLACE_LISTINGS)); } // set the filter for the empty folder if the debug setting is on @@ -1489,5 +1490,6 @@ namespace LLInitParam declare(LLFolderType::lookup(LLFolderType::FT_INBOX) , LLFolderType::FT_INBOX); declare(LLFolderType::lookup(LLFolderType::FT_OUTBOX) , LLFolderType::FT_OUTBOX); declare(LLFolderType::lookup(LLFolderType::FT_BASIC_ROOT) , LLFolderType::FT_BASIC_ROOT); + declare(LLFolderType::lookup(LLFolderType::FT_MARKETPLACE_LISTINGS) , LLFolderType::FT_MARKETPLACE_LISTINGS); } } diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 05c9d76810..6f35cc217d 100755 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -30,6 +30,7 @@ #include "llagent.h" #include "llhttpclient.h" +#include "llinventoryfunctions.h" #include "llsdserialize.h" #include "lltimer.h" #include "lltrans.h" @@ -528,3 +529,121 @@ void LLMarketplaceInventoryImporter::updateImport() } } +// +// Direct Delivery : Marketplace tuples and data +// + +// Tuple == Item +LLMarketplaceTuple::LLMarketplaceTuple() : + mFolderListingId(), + mListingId(""), + mActiveVersionFolderId(), + mIsActive(false) +{ +} + +LLMarketplaceTuple::LLMarketplaceTuple(const LLUUID& folder_id) : + mFolderListingId(folder_id), + mListingId(""), + mActiveVersionFolderId(), + mIsActive(false) +{ +} + +LLMarketplaceTuple::LLMarketplaceTuple(const LLUUID& folder_id, std::string listing_id, const LLUUID& version_id, bool is_listed) : + mFolderListingId(folder_id), + mListingId(listing_id), + mActiveVersionFolderId(version_id), + mIsActive(is_listed) +{ +} + + +// Data map +LLMarketplaceData::LLMarketplaceData() +{ +} + +// Accessors +bool LLMarketplaceData::getActivationState(const LLUUID& folder_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + return (it == mMarketplaceItems.end() ? false : (it->second).mIsActive); +} +std::string LLMarketplaceData::getListingID(const LLUUID& folder_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + return (it == mMarketplaceItems.end() ? "" : (it->second).mListingId); +} +LLUUID LLMarketplaceData::getVersionFolderID(const LLUUID& folder_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + return (it == mMarketplaceItems.end() ? LLUUID::null : (it->second).mActiveVersionFolderId); +} +bool LLMarketplaceData::isListed(const LLUUID& folder_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + return (it != mMarketplaceItems.end()); +} + +// Modifiers +bool LLMarketplaceData::setListingID(const LLUUID& folder_id, std::string listing_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it == mMarketplaceItems.end()) + { + return false; + } + else + { + (it->second).mListingId = listing_id; + update_marketplace_category(folder_id); + return true; + } +} +bool LLMarketplaceData::setVersionFolderID(const LLUUID& folder_id, const LLUUID& version_id) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it == mMarketplaceItems.end()) + { + return false; + } + else + { + (it->second).mActiveVersionFolderId = version_id; + update_marketplace_category(folder_id); + return true; + } +} +bool LLMarketplaceData::setActivation(const LLUUID& folder_id, bool activate) +{ + marketplace_items_list_t::iterator it = mMarketplaceItems.find(folder_id); + if (it == mMarketplaceItems.end()) + { + return false; + } + else + { + (it->second).mIsActive = activate; + update_marketplace_category(folder_id); + return true; + } +} + +// Test methods +void LLMarketplaceData::addTestItem(const LLUUID& folder_id) +{ + llinfos << "Merov : addTestItem, id = " << folder_id << llendl; + mMarketplaceItems[folder_id] = LLMarketplaceTuple(folder_id); + update_marketplace_category(folder_id); +} +void LLMarketplaceData::addTestItem(const LLUUID& folder_id, const LLUUID& version_id) +{ + llinfos << "Merov : addTestItem, id = " << folder_id << ", version = " << version_id << llendl; + mMarketplaceItems[folder_id] = LLMarketplaceTuple(folder_id); + setVersionFolderID(folder_id, version_id); + update_marketplace_category(folder_id); + update_marketplace_category(version_id); +} + + diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h index abe60890a3..00840c6e23 100755 --- a/indra/newview/llmarketplacefunctions.h +++ b/indra/newview/llmarketplacefunctions.h @@ -109,6 +109,63 @@ private: }; +// Classes handling the data coming from and going to the Marketplace DB: +// * implement the Marketplace API (TBD) +// * cache the current Marketplace data (tuples) +// * provide methods to get Marketplace data on any inventory item +// * signal marketplace updates to inventory +class LLMarketplaceData; + +// A Marketplace item is known by its tuple +class LLMarketplaceTuple +{ +public: + friend class LLMarketplaceData; + + LLMarketplaceTuple(); + LLMarketplaceTuple(const LLUUID& folder_id); + LLMarketplaceTuple(const LLUUID& folder_id, std::string listing_id, const LLUUID& version_id, bool is_listed = false); + +private: + // Representation of a marketplace item in the Marketplace DB (well, what we know of it...) + LLUUID mFolderListingId; + std::string mListingId; + LLUUID mActiveVersionFolderId; + bool mIsActive; +}; +// Note: the folder UUID is used as a key to this map. It could therefore be taken off the object themselves +typedef std::map<LLUUID, LLMarketplaceTuple> marketplace_items_list_t; + +// There's one and only one possible set of Marketplace data per agent and per session +class LLMarketplaceData + : public LLSingleton<LLMarketplaceData> +{ +public: + LLMarketplaceData(); + + bool isEmpty() { return (mMarketplaceItems.size() == 0); } + + // Access Marketplace Data : each method returns a default value if the folder_id can't be found + bool getActivationState(const LLUUID& folder_id); + std::string getListingID(const LLUUID& folder_id); + LLUUID getVersionFolderID(const LLUUID& folder_id); + + bool isListed(const LLUUID& folder_id); // returns true if folder_id is in the items map + + // Modify Marketplace Data : each method returns true if the function succeeds, false if error + bool setListingID(const LLUUID& folder_id, std::string listing_id); + bool setVersionFolderID(const LLUUID& folder_id, const LLUUID& version_id); + bool setActivation(const LLUUID& folder_id, bool activate); + + // Merov : DD Development : methods to populate the items list with something usefull using + // inventory IDs and some pseudo random code so we can play with the UI... + void addTestItem(const LLUUID& folder_id); + void addTestItem(const LLUUID& folder_id, const LLUUID& version_id); + +private: + marketplace_items_list_t mMarketplaceItems; +}; + #endif // LL_LLMARKETPLACEFUNCTIONS_H diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index a8eeddb798..853d98693b 100755 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -243,6 +243,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("tex_fetch_debugger", "floater_texture_fetch_debugger.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTextureFetchDebugger>); } LLFloaterReg::add("media_settings", "floater_media_settings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMediaSettings>); + LLFloaterReg::add("marketplace_listings", "floater_marketplace_listings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMarketplaceListings>); LLFloaterReg::add("message_critical", "floater_critical.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>); LLFloaterReg::add("message_tos", "floater_tos.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterTOS>); LLFloaterReg::add("moveview", "floater_moveview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMove>); diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index 991f6b40e6..ee8f85782f 100644 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp @@ -140,6 +140,8 @@ LLViewerFolderDictionary::LLViewerFolderDictionary() addEntry(LLFolderType::FT_OUTBOX, new ViewerFolderEntry("Merchant Outbox", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible)); addEntry(LLFolderType::FT_BASIC_ROOT, new ViewerFolderEntry("Basic Root", "Inv_SysOpen", "Inv_SysClosed", FALSE, true)); + + addEntry(LLFolderType::FT_MARKETPLACE_LISTINGS, new ViewerFolderEntry("Marketplace listings", "Inv_SysOpen", "Inv_SysClosed", FALSE, boxes_invisible)); addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "Inv_FolderOpen", "Inv_FolderClosed", FALSE, false, "default")); diff --git a/indra/newview/skins/default/xui/en/floater_marketplace_listings.xml b/indra/newview/skins/default/xui/en/floater_marketplace_listings.xml new file mode 100755 index 0000000000..80d6187e1e --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_marketplace_listings.xml @@ -0,0 +1,107 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<floater + title="MARKETPLACE LISTINGS" + name="floater_marketplace_listings" + help_topic="floater_marketplace_listings" + positioning="cascading" + width="333" + height="445" + min_width="200" + min_height="300" + can_close="true" + can_resize="true" + save_rect="true" + save_visibility="false" + reuse_instance="true"> + <string name="MarketplaceListingsInitializing">Initializing...</string> + <panel + follows="all" + layout="topleft" + left="0" + top="0" + label="" + height="440" + width="333"> + <panel + follows="all" + left="10" + height="420" + width="313" + top="0" + bg_opaque_color="InventoryBackgroundColor"> + <panel + name="marketplace_listings_inventory_placeholder_panel" + follows="all" + layout="topleft" + top="0" + left="0" + width="313" + height="420" + bg_opaque_color="InventoryBackgroundColor"> + <text + name="marketplace_listings_inventory_placeholder_title" + type="string" + follows="top|left|right" + layout="topleft" + top="10" + left="0" + width="313" + height="25" + wrap="true" + halign="center" + font="SansSerifBold"> + Loading... + </text> + <text + name="marketplace_listings_inventory_placeholder_text" + type="string" + follows="top|left|right" + layout="topleft" + top="35" + left="0" + width="313" + height="130" + wrap="true" + halign="left" /> + </panel> + </panel> + <panel + follows="bottom|left|right" + layout="topleft" + left="10" + width="313" + height="20"> + <text + name="marketplace_status" + type="string" + follows="bottom|left|right" + layout="topleft" + top="0" + left="5" + width="150" + height="20" + wrap="true" + halign="left" + valign="center" + font="SansSerif"/> + </panel> + <layout_stack name="initialization_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false"> + <layout_panel /> + <layout_panel height="24" auto_resize="false"> + <layout_stack orientation="horizontal" left="0" height="24" top="0" width="333" follows="all"> + <layout_panel width="0" /> + <layout_panel width="24" auto_resize="false"> + <loading_indicator + height="24" + layout="topleft" + left="0" + top="0" + width="24" /> + </layout_panel> + <layout_panel width="0" /> + </layout_stack> + </layout_panel> + <layout_panel /> + </layout_stack> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/en/menu_marketplace_view.xml b/indra/newview/skins/default/xui/en/menu_marketplace_view.xml new file mode 100755 index 0000000000..9ed93e2f11 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_marketplace_view.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<toggleable_menu + name="menu_marketplace_sort" + left="0" bottom="0" visible="false" + mouse_opaque="false"> + <menu_item_check + label="Sort by stock amount (low to high)" + name="sort_by_stock_amount"> + <menu_item_check.on_click + function="Marketplace.ViewSort.Action" + parameter="sort_by_stock_amount"/> + <menu_item_check.on_check + function="Marketplace.ViewSort.CheckItem" + parameter="sort_by_stock_amount"/> + </menu_item_check> + <menu_item_separator layout="topleft" /> + <menu_item_check name="show_all" label="Show All"> + <menu_item_check.on_click + function="Marketplace.ViewSort.Action" + parameter="show_all" /> + <menu_item_check.on_check + function="Marketplace.ViewSort.CheckItem" + parameter="show_all" /> + </menu_item_check> + <menu_item_check name="show_associated_listings" label="Show Associated Listings Only"> + <menu_item_check.on_click + function="Marketplace.ViewSort.Action" + parameter="show_associated_listings" /> + <menu_item_check.on_check + function="Marketplace.ViewSort.CheckItem" + parameter="show_associated_listings" /> + </menu_item_check> + <menu_item_check name="show_active" label="Show Active Listings and Folders Only"> + <menu_item_check.on_click + function="Marketplace.ViewSort.Action" + parameter="show_active" /> + <menu_item_check.on_check + function="Marketplace.ViewSort.CheckItem" + parameter="show_active" /> + </menu_item_check> + <menu_item_check name="show_inactive_listings" label="Show Inactive Listings Only"> + <menu_item_check.on_click + function="Marketplace.ViewSort.Action" + parameter="show_inactive_listings" /> + <menu_item_check.on_check + function="Marketplace.ViewSort.CheckItem" + parameter="show_inactive_listings" /> + </menu_item_check> +</toggleable_menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 7e8d2aaf9a..2c432c2c8c 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -181,6 +181,13 @@ function="Floater.ToggleOrBringToFront" parameter="outbox" /> </menu_item_call> + <menu_item_call + label="Marketplace listings..." + name="MarketplaceListings"> + <menu_item_call.on_click + function="Floater.ToggleOrBringToFront" + parameter="marketplace_listings" /> + </menu_item_call> <menu_item_call label="Account dashboard..." name="Manage My Account"> diff --git a/indra/newview/skins/default/xui/en/panel_marketplace_listings.xml b/indra/newview/skins/default/xui/en/panel_marketplace_listings.xml new file mode 100755 index 0000000000..54fc3a0c0f --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_marketplace_listings.xml @@ -0,0 +1,138 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + label="Marketplace" + name="main marketplace panel" + follows="all" + layout="topleft" + width="308" + height="375"> + <panel + label="tool_panel" + name="nearby_buttons_panel" + follows="left|top|right" + layout="topleft" + height="30" + width="308" + top="0" + left="0"> + <menu_button + name="sort_btn" + tool_tip="View/sort options" + layout="topleft" + follows="top|left" + width="31" + height="25" + left="2" + menu_filename="menu_marketplace_view.xml" + image_hover_unselected="Toolbar_Middle_Over" + image_overlay="Conv_toolbar_sort" + image_selected="Toolbar_Middle_Selected" + image_unselected="Toolbar_Middle_Off" + menu_position="bottomleft"/> + </panel> + <panel + follows="all" + layout="topleft" + default_tab_group="1" + width="308" + height="340"> + <tab_container + name="marketplace filter tabs" + follows="all" + layout="topleft" + top="0" + left="0" + top_pad="0" + width="308" + height="340" + halign="center" + tab_height="30" + tab_group="1" + tab_position="top" + tab_min_width="50"> + <inventory_panel + label="ALL" + name="All Items" + help_topic="marketplace_tab" + layout="topleft" + follows="all" + width="308" + height="310" + top="16" + left="0" + start_folder.name="Marketplace listings" + show_empty_message="false" + show_load_status="false" + start_folder.type="merchant" + tool_tip="Drag and drop items here to sell them" + bg_opaque_color="DkGray2" + bg_alpha_color="DkGray2" + background_visible="true" + border="false" + bevel_style="none" + sort_order_setting="InventorySortOrder" + show_item_link_overlays="true"> + </inventory_panel> + <inventory_panel + label="ACTIVE" + name="Active Items" + help_topic="marketplace_tab" + layout="topleft" + follows="all" + width="308" + height="310" + left_delta="0" + start_folder.name="Marketplace listings" + show_empty_message="false" + show_load_status="false" + start_folder.type="merchant" + bg_opaque_color="DkGray2" + bg_alpha_color="DkGray2" + background_visible="true" + border="false" + bevel_style="none" + show_item_link_overlays="true"> + </inventory_panel> + <inventory_panel + label="INACTIVE" + name="Inactive Items" + help_topic="marketplace_tab" + layout="topleft" + follows="all" + width="308" + height="310" + left_delta="0" + start_folder.name="Marketplace listings" + show_empty_message="false" + show_load_status="false" + start_folder.type="merchant" + bg_opaque_color="DkGray2" + bg_alpha_color="DkGray2" + background_visible="true" + border="false" + bevel_style="none" + show_item_link_overlays="true"> + </inventory_panel> + <inventory_panel + label="UNASSOCIATED" + name="Unassociated Items" + help_topic="marketplace_tab" + layout="topleft" + follows="all" + width="308" + height="310" + left_delta="0" + start_folder.name="Marketplace listings" + show_empty_message="false" + show_load_status="false" + start_folder.type="merchant" + bg_opaque_color="DkGray2" + bg_alpha_color="DkGray2" + background_visible="true" + border="false" + bevel_style="none" + show_item_link_overlays="true"> + </inventory_panel> + </tab_container> + </panel> +</panel>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 3252ed2b62..80b520622a 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2255,6 +2255,11 @@ We are accessing your account on the [[MARKETPLACE_CREATE_STORE_URL] Marketplace <string name="InventoryOutboxError"> The [[MARKETPLACE_CREATE_STORE_URL] Marketplace store] is returning errors. </string> + <string name="InventoryMarketplaceListingsNoItemsTitle">Your Marketplace Listings folder is empty.</string> + <string name="InventoryMarketplaceListingsNoItemsTooltip"></string> + <string name="InventoryMarketplaceListingsNoItems"> + Drag folders to this area to list them for sale on the [[MARKETPLACE_DASHBOARD_URL] Marketplace]. + </string> <string name="Marketplace Error None">No errors</string> <string name="Marketplace Error Not Merchant">Error: Before sending items to the Marketplace you will need to set yourself up as a merchant (free of charge).</string> @@ -2266,6 +2271,9 @@ The [[MARKETPLACE_CREATE_STORE_URL] Marketplace store] is returning errors. <string name="Marketplace Error Unsellable Item">Error: This item can not be sold on the marketplace.</string> <string name="Marketplace Error Internal Import">Error: There was a problem with this item. Try again later.</string> + <string name="MarketplaceNoID">no Mkt ID</string> + <string name="MarketplaceActive">live</string> + <string name="Open landmarks">Open landmarks</string> <!-- use value="" because they have preceding spaces --> |