Merchant Outbox!

Enter: LLFloaterOutbox, floater_merchant_outbox, LLMarketplaceFunctions, LLPanelMarketplaceOutboxInventory, and panel_outbox_inventory

LLView now has childFromPoint() from v-d.
LLInventoryBridge{
Sync includes with v-d.
Let's ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU for ease of access and tweak it to work.
Uncomment related code.
Catch if we're moving objects into the outbox during pasteFromClipboard()
}
LLInventoryPanel: start_folder attribute for inventory_panels, this could be quite useful in the future
Sync LLToolDragAndDrop with Catznip/v-d
Add the outbox to the World menu, since that seems to involve most commerce. Perhaps we should add a menu entry to the outbox itself to open its floater?
Fix the inventory merchant menu entries, thanks Shyotl..
Merchant Outbox Strings!
This commit is contained in:
Lirusaito
2012-11-06 20:23:36 -05:00
parent d0a0aa7a65
commit 7a35a43bd4
21 changed files with 1897 additions and 67 deletions

View File

@@ -893,6 +893,39 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)
}
return NULL;
}
LLView* LLView::childFromPoint(S32 x, S32 y, bool recur)
{
if (!getVisible())
return NULL;
BOOST_FOREACH(LLView* viewp, mChildList)
{
S32 local_x = x - viewp->getRect().mLeft;
S32 local_y = y - viewp->getRect().mBottom;
if (!viewp->visibleAndContains(local_x, local_y))
{
continue;
}
// Here we've found the first (frontmost) visible child at this level
// containing the specified point. Is the caller asking us to drill
// down and return the innermost leaf child at this point, or just the
// top-level child?
if (recur)
{
LLView* leaf(viewp->childFromPoint(local_x, local_y, recur));
// Maybe viewp is already a leaf LLView, or maybe it has children
// but this particular (x, y) point falls between them. If the
// recursive call returns non-NULL, great, use that; else just use
// viewp.
return leaf? leaf : viewp;
}
return viewp;
}
return 0;
}
BOOL LLView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
{
BOOL handled = FALSE;

View File

@@ -394,11 +394,9 @@ public:
void setShape(const LLRect& new_rect, bool by_user = false);
virtual LLView* findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, LLView::ESnapType snap_type, S32 threshold, S32 padding = 0);
virtual LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding = 0);
virtual BOOL canSnapTo(const LLView* other_view);
virtual void setSnappedTo(const LLView* snap_view);
// inherited from LLFocusableElement
/* virtual */ BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent);
/* virtual */ BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent);
@@ -478,6 +476,7 @@ public:
/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect); // Display mToolTipMsg if no child handles it.
/*virtual*/ const std::string& getName() const;
/*virtual*/ void onMouseCaptureLost();
/*virtual*/ BOOL hasMouseCapture();
@@ -485,6 +484,8 @@ public:
/*virtual*/ void screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const;
/*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const;
virtual LLView* childFromPoint(S32 x, S32 y, bool recur=false);
template <class T> T* findChild(const std::string& name)
{
return getChild<T>(name,true,false);

View File

@@ -225,6 +225,7 @@ set(viewer_SOURCE_FILES
llfloaternotificationsconsole.cpp
llfloaterobjectiminfo.cpp
llfloateropenobject.cpp
llfloateroutbox.cpp
llfloaterparcel.cpp
llfloaterpermissionsmgr.cpp
llfloaterperms.cpp
@@ -305,6 +306,7 @@ set(viewer_SOURCE_FILES
llmanipscale.cpp
llmaniptranslate.cpp
llmapresponders.cpp
llmarketplacefunctions.cpp
llmarketplacenotifications.cpp
llmediactrl.cpp
llmediaremotectrl.cpp
@@ -357,6 +359,7 @@ set(viewer_SOURCE_FILES
llpanellandoptions.cpp
llpanellogin.cpp
llpanelmaininventory.cpp
llpanelmarketplaceoutboxinventory.cpp
llpanelmediahud.cpp
llpanelmorph.cpp
llpanelmsgs.cpp
@@ -727,6 +730,7 @@ set(viewer_HEADER_FILES
llfloaternotificationsconsole.h
llfloaterobjectiminfo.h
llfloateropenobject.h
llfloateroutbox.h
llfloaterparcel.h
llfloaterpermissionsmgr.h
llfloaterperms.h
@@ -807,6 +811,7 @@ set(viewer_HEADER_FILES
llmanipscale.h
llmaniptranslate.h
llmapresponders.h
llmarketplacefunctions.h
llmarketplacenotifications.h
llmediactrl.h
llmediaremotectrl.h
@@ -859,6 +864,7 @@ set(viewer_HEADER_FILES
llpanellandoptions.h
llpanellogin.h
llpanelmaininventory.h
llpanelmarketplaceoutboxinventory.h
llpanelmediahud.h
llpanelmorph.h
llpanelmsgs.h

View File

@@ -51,7 +51,7 @@
#include "llagentwearables.h"
#include "llwindow.h"
#include "llviewerstats.h"
//#include "llmarketplacefunctions.h"
#include "llmarketplacefunctions.h"
#include "llmarketplacenotifications.h"
#include "llmd5.h"
#include "llmeshrepository.h"
@@ -4090,7 +4090,7 @@ void LLAppViewer::idle()
LLViewerMediaFocus::getInstance()->update();
// Update marketplace
//LLMarketplaceInventoryImporter::update();
LLMarketplaceInventoryImporter::update();
LLMarketplaceInventoryNotifications::update();
// objects and camera should be in sync, do LOD calculations now

View File

@@ -0,0 +1,591 @@
/**
* @file llfloateroutbox.cpp
* @brief Implementation of the merchant outbox window
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llfloateroutbox.h"
#include "llfolderview.h"
#include "llinventorybridge.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llinventoryobserver.h"
#include "llinventorypanel.h"
#include "llmarketplacefunctions.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "lltextbox.h"
#include "lltexteditor.h"
//#include "lltransientfloatermgr.h"
#include "lltrans.h"
#include "llviewernetwork.h"
//#include "llwindowshade.h"
#define USE_WINDOWSHADE_DIALOGS 0
///----------------------------------------------------------------------------
/// LLOutboxNotification class
///----------------------------------------------------------------------------
class LLOutboxNotification
{
public:
bool processNotification(const LLSD& notify)
{
LLFloaterOutbox* outbox_floater = LLFloaterOutbox::getInstance();
outbox_floater->showNotification(notify);
return false;
}
};
///----------------------------------------------------------------------------
/// LLOutboxAddedObserver helper class
///----------------------------------------------------------------------------
class LLOutboxAddedObserver : public LLInventoryCategoryAddedObserver
{
public:
LLOutboxAddedObserver(LLFloaterOutbox * outboxFloater)
: LLInventoryCategoryAddedObserver()
, mOutboxFloater(outboxFloater)
{
}
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_OUTBOX)
{
mOutboxFloater->setupOutbox(added_category->getUUID());
}
}
}
private:
LLFloaterOutbox * mOutboxFloater;
};
///----------------------------------------------------------------------------
/// LLFloaterOutbox
///----------------------------------------------------------------------------
LLFloaterOutbox::LLFloaterOutbox(const LLSD& key)
: LLFloater(key)
, mCategoriesObserver(NULL)
, mCategoryAddedObserver(NULL)
, mImportBusy(false)
, mImportButton(NULL)
, mInventoryFolderCountText(NULL)
, mInventoryImportInProgress(NULL)
, mInventoryPlaceholder(NULL)
, mInventoryText(NULL)
, mInventoryTitle(NULL)
, mOutboxId(LLUUID::null)
, mOutboxInventoryPanel(NULL)
, mOutboxItemCount(0)
, mOutboxTopLevelDropZone(NULL)
// , mWindowShade(NULL)
{
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_merchant_outbox.xml");
}
LLFloaterOutbox::~LLFloaterOutbox()
{
if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver))
{
gInventory.removeObserver(mCategoriesObserver);
}
delete mCategoriesObserver;
if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver))
{
gInventory.removeObserver(mCategoryAddedObserver);
}
delete mCategoryAddedObserver;
}
BOOL LLFloaterOutbox::postBuild()
{
mInventoryFolderCountText = getChild<LLTextBox>("outbox_folder_count");
mInventoryImportInProgress = getChild<LLView>("import_progress_indicator");
mInventoryPlaceholder = getChild<LLView>("outbox_inventory_placeholder_panel");
mInventoryText = mInventoryPlaceholder->getChild<LLTextEditor>("outbox_inventory_placeholder_text");
// For some reason, adding style doesn't work unless this is true.
mInventoryText->setParseHTML(TRUE);
mInventoryTitle = mInventoryPlaceholder->getChild<LLTextBox>("outbox_inventory_placeholder_title");
mImportButton = getChild<LLButton>("outbox_import_btn");
mImportButton->setCommitCallback(boost::bind(&LLFloaterOutbox::onImportButtonClicked, this));
mOutboxTopLevelDropZone = getChild<LLPanel>("outbox_generic_drag_target");
LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterOutbox::onFocusReceived, this));
return TRUE;
}
void LLFloaterOutbox::onClose(bool app_quitting)
{
/*
if (mWindowShade)
{
delete mWindowShade;
mWindowShade = NULL;
}
*/
setVisible(FALSE);
//destroy(); //Don't because outbox should be persistent.
}
void LLFloaterOutbox::onOpen()
{
//
// Look for an outbox and set up the inventory API
//
if (mOutboxId.isNull())
{
const bool do_not_create_folder = false;
const bool do_not_find_in_library = false;
const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library);
if (outbox_id.isNull())
{
// Observe category creation to catch outbox creation
mCategoryAddedObserver = new LLOutboxAddedObserver(this);
gInventory.addObserver(mCategoryAddedObserver);
}
else
{
setupOutbox(outbox_id);
}
}
updateView();
//
// Trigger fetch of outbox contents
//
fetchOutboxContents();
}
void LLFloaterOutbox::onFocusReceived()
{
fetchOutboxContents();
}
void LLFloaterOutbox::fetchOutboxContents()
{
if (mOutboxId.notNull())
{
LLInventoryModelBackgroundFetch::instance().start(mOutboxId);
}
}
void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId)
{
llassert(outboxId.notNull());
llassert(mOutboxId.isNull());
llassert(mCategoriesObserver == NULL);
mOutboxId = outboxId;
// No longer need to observe new category creation
if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver))
{
gInventory.removeObserver(mCategoryAddedObserver);
delete mCategoryAddedObserver;
mCategoryAddedObserver = NULL;
}
// Create observer for outbox modifications
mCategoriesObserver = new LLInventoryCategoriesObserver();
gInventory.addObserver(mCategoriesObserver);
mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this));
//
// Set up the outbox inventory view
//
mOutboxInventoryPanel = getChild<LLInventoryPanel>("panel_outbox_inventory");
llassert(mOutboxInventoryPanel);
// Reshape the inventory to the proper size
LLRect inventory_placeholder_rect = mInventoryPlaceholder->getRect();
mOutboxInventoryPanel->setShape(inventory_placeholder_rect);
// Set the sort order newest to oldest
mOutboxInventoryPanel->setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME);
mOutboxInventoryPanel->getFilter()->markDefault();
fetchOutboxContents();
//
// Initialize the marketplace import API
//
LLMarketplaceInventoryImporter& importer = LLMarketplaceInventoryImporter::instance();
importer.setInitializationErrorCallback(boost::bind(&LLFloaterOutbox::initializationReportError, this, _1, _2));
importer.setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1));
importer.setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2));
importer.initialize();
}
void LLFloaterOutbox::setStatusString(const std::string& statusString)
{
llassert(mInventoryFolderCountText != NULL);
mInventoryFolderCountText->setText(statusString);
}
void LLFloaterOutbox::updateFolderCount()
{
S32 item_count = 0;
if (mOutboxId.notNull())
{
LLInventoryModel::cat_array_t * cats;
LLInventoryModel::item_array_t * items;
gInventory.getDirectDescendentsOf(mOutboxId, cats, items);
item_count = cats->count() + items->count();
}
mOutboxItemCount = item_count;
if (!mImportBusy)
{
updateFolderCountStatus();
}
}
void LLFloaterOutbox::updateFolderCountStatus()
{
if (mOutboxInventoryPanel)
{
switch (mOutboxItemCount)
{
case 0: setStatusString(getString("OutboxFolderCount0")); break;
case 1: setStatusString(getString("OutboxFolderCount1")); break;
default:
{
std::string item_count_str = llformat("%d", mOutboxItemCount);
LLStringUtil::format_map_t args;
args["[NUM]"] = item_count_str;
setStatusString(getString("OutboxFolderCountN", args));
break;
}
}
}
mImportButton->setEnabled(mOutboxItemCount > 0);
}
void LLFloaterOutbox::updateView()
{
//updateView() is called twice the first time.
updateFolderCount();
if (mOutboxItemCount > 0)
{
mOutboxInventoryPanel->setVisible(TRUE);
mInventoryPlaceholder->setVisible(FALSE);
}
else
{
if (mOutboxInventoryPanel)
{
mOutboxInventoryPanel->setVisible(FALSE);
}
mInventoryPlaceholder->setVisible(TRUE);
std::string outbox_text;
std::string outbox_title;
std::string outbox_tooltip;
const LLSD& subs = getMarketplaceStringSubstitutions();
// Text styles for marketplace hyperlinks
std::string subs_link;
std::string subs_text;
if (mOutboxId.notNull())
{
outbox_text = LLTrans::getString("InventoryOutboxNoItems");
subs_link = "[MARKETPLACE_DASHBOARD_URL]";
subs_text = " " + LLTrans::getString("InventoryOutboxNoItemsSubs");
outbox_title = LLTrans::getString("InventoryOutboxNoItemsTitle");
outbox_tooltip = LLTrans::getString("InventoryOutboxNoItemsTooltip");
}
else
{
outbox_text = LLTrans::getString("InventoryOutboxNotMerchant");
subs_link = "[MARKETPLACE_CREATE_STORE_URL]";
subs_text = " " + LLTrans::getString("InventoryOutboxNotMerchantSubs");
outbox_title = LLTrans::getString("InventoryOutboxNotMerchantTitle");
outbox_tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip");
}
mInventoryText->clear();
mInventoryText->appendColoredText(outbox_text, false, false, gColors.getColor("TextFgReadOnlyColor"));
LLStringUtil::format(subs_link, subs);
LLStyleSP subs_link_style(new LLStyle);
subs_link_style->setLinkHREF(subs_link);
subs_link_style->setColor(gSavedSettings.getColor4("HTMLLinkColor"));
mInventoryText->appendStyledText(subs_text, false, false, subs_link_style);
mInventoryTitle->setValue(outbox_title);
mInventoryPlaceholder->getParent()->setToolTip(outbox_tooltip);
}
}
bool isAccepted(EAcceptance accept)
{
return (accept >= ACCEPT_YES_COPY_SINGLE);
}
BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
EDragAndDropType cargo_type,
void* cargo_data,
EAcceptance* accept,
std::string& tooltip_msg)
{
if ((mOutboxInventoryPanel == NULL) ||
//(mWindowShade && mWindowShade->isShown()) ||
LLMarketplaceInventoryImporter::getInstance()->isImportInProgress())
{
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;
LLFolderView * root_folder = mOutboxInventoryPanel->getRootFolder();
if (mOutboxInventoryPanel->getVisible())
{
S32 inv_x, inv_y;
localPointToOtherView(x, y, &inv_x, &inv_y, mOutboxInventoryPanel);
pointInInventoryPanel = mOutboxInventoryPanel->getRect().pointInRect(inv_x, inv_y);
LLView * inventory_panel_child_at_point = mOutboxInventoryPanel->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);
}
mOutboxTopLevelDropZone->setBackgroundVisible(handled && !drop && isAccepted(*accept));
}
else
{
mOutboxTopLevelDropZone->setBackgroundVisible(!pointInInventoryPanelChild);
}
return handled;
}
BOOL LLFloaterOutbox::handleHover(S32 x, S32 y, MASK mask)
{
mOutboxTopLevelDropZone->setBackgroundVisible(FALSE);
return LLFloater::handleHover(x, y, mask);
}
/*
void LLFloaterOutbox::onMouseLeave(S32 x, S32 y, MASK mask)
{
mOutboxTopLevelDropZone->setBackgroundVisible(FALSE);
LLFloater::onMouseLeave(x, y, mask);
}
*/
void LLFloaterOutbox::onImportButtonClicked()
{
mOutboxInventoryPanel->clearSelection();
mImportBusy = LLMarketplaceInventoryImporter::instance().triggerImport();
}
void LLFloaterOutbox::onOutboxChanged()
{
llassert(!mOutboxId.isNull());
if (mOutboxInventoryPanel)
{
mOutboxInventoryPanel->requestSort();
}
fetchOutboxContents();
updateView();
}
void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content)
{
if (status == MarketplaceErrorCodes::IMPORT_DONE)
{
LLNotificationsUtil::add("OutboxImportComplete");
}
else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS)
{
const LLSD& subs = getMarketplaceStringSubstitutions();
LLNotificationsUtil::add("OutboxImportHadErrors", subs);
}
else
{
char status_string[16];
sprintf(status_string, "%d", status);
LLSD subs;
subs["[ERROR_CODE]"] = status_string;
LLNotificationsUtil::add("OutboxImportFailed", subs);
}
updateView();
}
void LLFloaterOutbox::importStatusChanged(bool inProgress)
{
if (inProgress)
{
if (mImportBusy)
{
setStatusString(getString("OutboxImporting"));
}
else
{
setStatusString(getString("OutboxInitializing"));
}
mImportBusy = true;
mImportButton->setEnabled(false);
mInventoryImportInProgress->setVisible(true);
}
else
{
mImportBusy = false;
mImportButton->setEnabled(mOutboxItemCount > 0);
mInventoryImportInProgress->setVisible(false);
}
updateView();
}
void LLFloaterOutbox::initializationReportError(U32 status, const LLSD& content)
{
if (status != MarketplaceErrorCodes::IMPORT_DONE)
{
char status_string[16];
sprintf(status_string, "%d", status);
LLSD subs;
subs["[ERROR_CODE]"] = status_string;
LLNotificationsUtil::add("OutboxInitFailed", subs);
}
updateView();
}
void LLFloaterOutbox::showNotification(const LLSD& notify)
{
LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
if (!notification)
{
llerrs << "Unable to find outbox notification!" << notify.asString() << llendl;
return;
}
#if USE_WINDOWSHADE_DIALOGS
if (mWindowShade)
{
delete mWindowShade;
}
LLRect floater_rect = getLocalRect();
floater_rect.mTop -= getHeaderHeight();
floater_rect.stretch(-5, 0);
LLWindowShade::Params params;
params.name = "notification_shade";
params.rect = floater_rect;
params.follows.flags = FOLLOWS_ALL;
params.modal = true;
params.can_close = false;
params.shade_color = LLColor4::white % 0.25f;
params.text_color = LLColor4::white;
mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params);
addChild(mWindowShade);
mWindowShade->show(notification);
#else //USE_WINDOWSHADE_DIALOGS
/*
LLNotificationsUI::LLEventHandler * handler =
LLNotificationsUI::LLNotificationManager::instance().getHandlerForNotification("alertmodal");
LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler *>(handler);
llassert(sys_handler);
sys_handler->processNotification(notify);
*/
LLNotifications::instance().add(notification);
#endif //USE_WINDOWSHADE_DIALOGS
}

View File

@@ -0,0 +1,115 @@
/**
* @file llfloateroutbox.h
* @brief LLFloaterOutbox
* class definition
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* ABILITY 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_LLFLOATEROUTBOX_H
#define LL_LLFLOATEROUTBOX_H
#include "llfloater.h"
#include "llfoldertype.h"
#include "llnotificationptr.h"
class LLButton;
class LLInventoryCategoriesObserver;
class LLInventoryCategoryAddedObserver;
class LLInventoryPanel;
class LLLoadingIndicator;
class LLNotification;
class LLTextBox;
class LLTextEditor;
class LLView;
//class LLWindowShade;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFloaterOutbox
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLFloaterOutbox : public LLFloater, public LLFloaterSingleton<LLFloaterOutbox>
{
public:
LLFloaterOutbox(const LLSD& key);
~LLFloaterOutbox();
void setupOutbox(const LLUUID& outboxId);
// 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 LLSD& notify);
BOOL handleHover(S32 x, S32 y, MASK mask);
// void onMouseLeave(S32 x, S32 y, MASK mask);
protected:
void fetchOutboxContents();
void importReportResults(U32 status, const LLSD& content);
void importStatusChanged(bool inProgress);
void initializationReportError(U32 status, const LLSD& content);
void onClose(bool app_quitting);
void onOpen();
void onFocusReceived();
void onImportButtonClicked();
void onOutboxChanged();
void setStatusString(const std::string& statusString);
void updateFolderCount();
void updateFolderCountStatus();
void updateView();
private:
LLInventoryCategoriesObserver * mCategoriesObserver;
LLInventoryCategoryAddedObserver * mCategoryAddedObserver;
bool mImportBusy;
LLButton * mImportButton;
LLTextBox * mInventoryFolderCountText;
LLView * mInventoryImportInProgress;
LLView * mInventoryPlaceholder;
LLTextEditor * mInventoryText;
LLTextBox * mInventoryTitle;
LLUUID mOutboxId;
LLInventoryPanel * mOutboxInventoryPanel;
U32 mOutboxItemCount;
LLPanel * mOutboxTopLevelDropZone;
//LLWindowShade * mWindowShade;
};
#endif // LL_LLFLOATEROUTBOX_H

View File

@@ -1,4 +1,4 @@
/**
/**
* @file llinventorybridge.cpp
* @brief Implementation of the Inventory-Folder-View-Bridge classes.
*
@@ -34,49 +34,47 @@
#include <utility> // for std::pair<>
#include "llinventorypanel.h"
#include "llinventorybridge.h"
#include "llinventorydefines.h"
#include "llinventoryfunctions.h"
#include "llinventoryicon.h"
#include "llinventorymodelbackgroundfetch.h"
#include "lltrans.h"
#include "message.h"
#include "llagent.h"
#include "llagentwearables.h"
#include "llappearancemgr.h"
#include "llattachmentsmgr.h"
#include "llagentcamera.h"
#include "llcallingcard.h"
#include "llcheckboxctrl.h" // for radio buttons
#include "llradiogroup.h"
#include "llspinctrl.h"
#include "lltextbox.h"
#include "llui.h"
#include "llviewerfoldertype.h"
#include "lluictrlfactory.h"
#include "llviewercontrol.h"
#include "llagent.h"
#include "llagentcamera.h"
#include "llagentwearables.h"
#include "llappearancemgr.h"
#include "llattachmentsmgr.h"
#include "llcallingcard.h"
#include "llfirstuse.h"
#include "llfloateravatarinfo.h"
#include "llfloaterchat.h"
#include "llfloatercustomize.h"
#include "llfloaterinventory.h"
#include "llfloateropenobject.h"
#include "llfloaterproperties.h"
#include "llfloaterworldmap.h"
#include "llfocusmgr.h"
#include "llfolderview.h"
#include "llgesturemgr.h"
#include "llgiveinventory.h"
#include "lliconctrl.h"
#include "llinventorymodel.h"
#include "llimview.h"
#include "llinventoryclipboard.h"
#include "llinventorydefines.h"
#include "llinventoryfunctions.h"
#include "llinventoryicon.h"
#include "llinventorymodel.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llinventorypanel.h"
#include "lllineeditor.h"
#include "llmarketplacefunctions.h"
#include "llmenugl.h"
//#include "llmarketplacefunctions.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "llpreviewanim.h"
@@ -87,27 +85,25 @@
#include "llpreviewsound.h"
#include "llpreviewtexture.h"
#include "llresmgr.h"
#include "llselectmgr.h"
#include "llscrollcontainer.h"
#include "llimview.h"
#include "llviewerassettype.h"
#include "llfoldertype.h"
#include "lltooldraganddrop.h"
#include "llviewertexturelist.h"
#include "lltabcontainer.h"
#include "lltrans.h"
#include "llviewerassettype.h"
#include "llviewercontrol.h"
#include "llviewerfoldertype.h"
#include "llviewerinventory.h"
#include "llviewermessage.h"
#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llviewertexturelist.h"
#include "llviewerwindow.h"
#include "llvoavatar.h"
#include "llfoldertype.h"
#include "llwearable.h"
#include "llwearablelist.h"
#include "llviewermessage.h"
#include "llviewerregion.h"
#include "lltabcontainer.h"
#include "lluictrlfactory.h"
#include "llselectmgr.h"
#include "llfloateropenobject.h"
// <edit>
#include "llappviewer.h" // System Folders
#include "llfloateranimpreview.h" // for reuploads
@@ -133,7 +129,7 @@
// Marketplace outbox current disabled
#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 1
#define ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU 0
#define ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU 1
#define BLOCK_WORN_ITEMS_IN_OUTBOX 1
bool InventoryLinksEnabled()
@@ -270,7 +266,7 @@ LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory,
const std::string& LLInvFVBridge::getName() const
{
LLInventoryObject* obj = getInventoryObject();
const LLInventoryObject* obj = getInventoryObject();
if(obj)
{
return obj->getName();
@@ -354,7 +350,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc
S32 count = batch.count();
S32 i,j;
for(i = 0; i < count; ++i)
{
{
bridge = (LLInvFVBridge*)(batch.get(i));
if(!bridge || !bridge->isItemRemovable()) continue;
item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
@@ -367,7 +363,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc
}
}
for(i = 0; i < count; ++i)
{
{
bridge = (LLInvFVBridge*)(batch.get(i));
if(!bridge || !bridge->isItemRemovable()) continue;
cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
@@ -778,7 +774,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
}
}
// Don't allow items to be pasted directly into the COF.
// Don't allow items to be pasted directly into the COF or the inbox/outbox
if (!isCOFFolder() && !isInboxFolder() && !isOutboxFolder())
{
items.push_back(std::string("Paste"));
@@ -861,7 +857,7 @@ void LLInvFVBridge::addTrashContextMenuOptions(menuentry_vec_t &items,
items.push_back(std::string("Purge Item"));
if (!isItemRemovable())
{
disabled_items.push_back(std::string("Purge Item"));
disabled_items.push_back(std::string("Purge Item"));
}
items.push_back(std::string("Restore Item"));
}
@@ -945,7 +941,7 @@ BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
{
return FALSE;
}
*id = obj->getUUID();
//object_ids.put(obj->getUUID());
@@ -1148,8 +1144,8 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
new_listener = new LLItemBridge(inventory, root, uuid);
break;
case LLAssetType::AT_OBJECT:
if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT)
case LLAssetType::AT_OBJECT:
if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT)
|| inv_type == LLInventoryType::IT_TEXTURE ) //There's an abundance of objects in inv that have texture (0) as their inv type, right out of unpack.
//May have been bug either in an old client, or server version. Either way... it causes a lot of spam over something ultimately harmless.
{
@@ -1242,7 +1238,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
{
LLInventoryCategory* cat = model->getCategory(uuid);
if(cat)
if (cat)
{
model->purgeDescendentsOf(uuid);
model->notifyObservers();
@@ -1311,10 +1307,10 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const
bool can_list = true;
// Do not allow listing while import is in progress
/*if (LLMarketplaceInventoryImporter::instanceExists())
if (LLMarketplaceInventoryImporter::instanceExists())
{
can_list = !LLMarketplaceInventoryImporter::instance().isImportInProgress();
}*/
}
const LLInventoryObject* obj = getInventoryObject();
can_list &= (obj != NULL);
@@ -2861,10 +2857,11 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
{
llinfos << "Send to marketplace action!" << llendl;
LLInventoryCategory * cat = gInventory.getCategory(mUUID);
/*LLInventoryCategory * cat = gInventory.getCategory(mUUID);
if (!cat) return;
send_to_marketplace(cat);
send_to_marketplace(cat);*/
LLMarketplaceInventoryImporter::instance().triggerImport();
}
#endif // ENABLE_MERCHANT_SEND_TO_MARKETPLACE_CONTEXT_MENU
}
@@ -3028,13 +3025,55 @@ void LLFolderBridge::pasteFromClipboard()
if(model && isClipboardPasteable())
{
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, 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_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
const LLUUID parent_id(mUUID);
const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
LLDynamicArray<LLUUID> objects;
LLInventoryClipboard::instance().retrieve(objects);
if (move_is_into_outbox)
{
LLFolderViewItem * outbox_itemp = mRoot->getItemByID(mUUID);
if (outbox_itemp)
{
//LLToolDragAndDrop::instance().setCargoCount(objects.size());
BOOL can_list = TRUE;
for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin();
(iter != objects.end()) && (can_list == TRUE);
++iter)
{
const LLUUID& item_id = (*iter);
LLInventoryItem *item = model->getItem(item_id);
if (item)
{
MASK mask = 0x0;
BOOL drop = FALSE;
EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(item->getActualType());
void * cargo_data = (void *) item;
//std::string tooltip_msg;
can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data/*, tooltip_msg*/);
}
}
//LLToolDragAndDrop::instance().resetCargoCount();
if (can_list == FALSE)
{
// Notify user of failure somehow -- play error sound? modal dialog?
return;
}
}
}
const LLUUID parent_id(mUUID);
for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin();
iter != objects.end();
++iter)

View File

@@ -45,6 +45,7 @@
#include "llappviewer.h"
//#include "llfirstuse.h"
#include "llfloaterinventory.h"
#include "llfloateroutbox.h"
#include "llfocusmgr.h"
#include "llfolderview.h"
#include "llgesturemgr.h"
@@ -430,7 +431,7 @@ void show_item_profile(const LLUUID& item_uuid)
void open_outbox()
{
//LLFloaterReg::showInstance("outbox");
LLFloaterOutbox::showInstance();
}
LLUUID create_folder_in_outbox_for_item(LLInventoryItem* item, const LLUUID& destFolderId, S32 operation_id)

View File

@@ -44,6 +44,7 @@
#include "llscrollcontainer.h"
#include "llviewerassettype.h"
#include "llpanelmaininventory.h"
#include "llpanelmarketplaceoutboxinventory.h"
#include "llsdserialize.h"
@@ -130,6 +131,7 @@ void LLInvPanelComplObserver::done()
LLInventoryPanel::LLInventoryPanel(const std::string& name,
const std::string& sort_order_setting,
const std::string& start_folder,
const LLRect& rect,
LLInventoryModel* inventory,
BOOL allow_multi_select,
@@ -140,6 +142,7 @@ LLInventoryPanel::LLInventoryPanel(const std::string& name,
mFolderRoot(NULL),
mScroller(NULL),
mSortOrderSetting(sort_order_setting),
mStartFolder(start_folder),
mInventory(inventory),
mAllowMultiSelect(allow_multi_select),
mViewsInitialized(false),
@@ -154,12 +157,38 @@ LLInventoryPanel::LLInventoryPanel(const std::string& name,
void LLInventoryPanel::buildFolderView()
{
// Determine the root folder in case specified, and
// build the views starting with that folder.
//std::string start_folder_name(params.start_folder());
const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolder);
LLUUID root_id;
if ("LIBRARY" == mStartFolder)
{
root_id = gInventory.getLibraryRootFolderID();
}
else
{
root_id = (preferred_type != LLFolderType::FT_NONE)
? gInventory.findCategoryUUIDForType(preferred_type, false, false)
: LLUUID::null;
}
if ((root_id == LLUUID::null) && !mStartFolder.empty())
{
llwarns << "No category found that matches start_folder: " << mStartFolder << llendl;
root_id = LLUUID::generateNewID();
}
LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(LLAssetType::AT_CATEGORY,
LLAssetType::AT_CATEGORY,
LLInventoryType::IT_CATEGORY,
this,
NULL,
LLUUID::null);
root_id);
mFolderRoot = createFolderView(new_listener, true/*params.use_label_suffix()*/);
}
@@ -247,6 +276,7 @@ class LLInventoryRecentItemsPanel : public LLInventoryPanel
public:
LLInventoryRecentItemsPanel(const std::string& name,
const std::string& sort_order_setting,
const std::string& start_folder,
const LLRect& rect,
LLInventoryModel* inventory,
BOOL allow_multi_select,
@@ -270,12 +300,19 @@ LLView* LLInventoryPanel::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
std::string sort_order(INHERIT_SORT_ORDER);
node->getAttributeString("sort_order", sort_order);
if(name != "Recent Items")
panel = new LLInventoryPanel(name, sort_order,
std::string start_folder;
node->getAttributeString("start_folder", start_folder);
if(name == "Recent Items")
panel = new LLInventoryRecentItemsPanel(name, sort_order, start_folder,
rect, &gInventory,
allow_multi_select, parent);
else if(name == "panel_outbox_inventory")
panel = new LLOutboxInventoryPanel(name, sort_order, start_folder,
rect, &gInventory,
allow_multi_select, parent);
else
panel = new LLInventoryRecentItemsPanel(name, sort_order,
panel = new LLInventoryPanel(name, sort_order, start_folder,
rect, &gInventory,
allow_multi_select, parent);
@@ -1058,11 +1095,12 @@ static const LLRecentInventoryBridgeBuilder RECENT_ITEMS_BUILDER;
LLInventoryRecentItemsPanel:: LLInventoryRecentItemsPanel(const std::string& name,
const std::string& sort_order_setting,
const std::string& start_folder,
const LLRect& rect,
LLInventoryModel* inventory,
BOOL allow_multi_select,
LLView *parent_view) :
LLInventoryPanel(name, sort_order_setting,rect,inventory,allow_multi_select,parent_view)
LLView *parent_view) :
LLInventoryPanel(name, sort_order_setting, start_folder,rect,inventory,allow_multi_select,parent_view)
{
mInvFVBridgeBuilder = &RECENT_ITEMS_BUILDER;
}

View File

@@ -69,6 +69,7 @@ class LLInventoryPanel : public LLPanel
protected:
LLInventoryPanel(const std::string& name,
const std::string& sort_order_setting,
const std::string& start_folder,
const LLRect& rect,
LLInventoryModel* inventory,
BOOL allow_multi_select,
@@ -188,6 +189,7 @@ public:
void requestSort();
private:
const std::string mStartFolder;
const std::string mSortOrderSetting;
//--------------------------------------------------------------------

View File

@@ -0,0 +1,484 @@
/**
* @file llmarketplacefunctions.cpp
* @brief Implementation of assorted functions related to the marketplace
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llmarketplacefunctions.h"
#include "llagent.h"
#include "llhttpclient.h"
#include "lltimer.h"
#include "lltrans.h"
#include "llviewercontrol.h"
#include "llviewermedia.h"
#include "llviewernetwork.h"
#include "hippogridmanager.h"
//
// Helpers
//
static std::string getMarketplaceDomain()
{
std::string domain = "secondlife.com";
if (gHippoGridManager->getCurrentGrid()->isSecondLife())
{
if (!LLViewerLogin::getInstance()->isInProductionGrid())
{
domain = "secondlife.aditi.lindenlab.com";
}
}
else
{
// TODO: Find out if OpenSim, and Avination adopted any outbox stuffs, if so code HippoGridManager for this
// Aurora grid has not.
// For now, reset domain on other grids, so we don't harass LL web services.
domain = ""; //gHippoGridManager->getCurrentGrid()->getMarketPlaceDomain();
}
return domain;
}
static std::string getMarketplaceURL(const std::string& urlStringName)
{
LLStringUtil::format_map_t domain_arg;
domain_arg["[MARKETPLACE_DOMAIN_NAME]"] = getMarketplaceDomain();
std::string marketplace_url = LLTrans::getString(urlStringName, domain_arg);
return marketplace_url;
}
LLSD getMarketplaceStringSubstitutions()
{
std::string marketplace_url = getMarketplaceURL("MarketplaceURL");
std::string marketplace_url_create = getMarketplaceURL("MarketplaceURL_CreateStore");
std::string marketplace_url_dashboard = getMarketplaceURL("MarketplaceURL_Dashboard");
std::string marketplace_url_imports = getMarketplaceURL("MarketplaceURL_Imports");
std::string marketplace_url_info = getMarketplaceURL("MarketplaceURL_LearnMore");
LLSD marketplace_sub_map;
marketplace_sub_map["[MARKETPLACE_URL]"] = marketplace_url;
marketplace_sub_map["[MARKETPLACE_CREATE_STORE_URL]"] = marketplace_url_create;
marketplace_sub_map["[MARKETPLACE_LEARN_MORE_URL]"] = marketplace_url_info;
marketplace_sub_map["[MARKETPLACE_DASHBOARD_URL]"] = marketplace_url_dashboard;
marketplace_sub_map["[MARKETPLACE_IMPORTS_URL]"] = marketplace_url_imports;
return marketplace_sub_map;
}
namespace LLMarketplaceImport
{
// Basic interface for this namespace
bool hasSessionCookie();
bool inProgress();
bool resultPending();
U32 getResultStatus();
const LLSD& getResults();
bool establishMarketplaceSessionCookie();
bool pollStatus();
bool triggerImport();
// Internal state variables
static std::string sMarketplaceCookie = "";
static LLSD sImportId = LLSD::emptyMap();
static bool sImportInProgress = false;
static bool sImportPostPending = false;
static bool sImportGetPending = false;
static U32 sImportResultStatus = 0;
static LLSD sImportResults = LLSD::emptyMap();
static LLTimer slmGetTimer;
static LLTimer slmPostTimer;
// Responders
class LLImportPostResponder : public LLHTTPClient::Responder
{
public:
LLImportPostResponder() : LLCurl::Responder() {}
void completed(U32 status, const std::string& reason, const LLSD& content)
{
slmPostTimer.stop();
if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
{
llinfos << " SLM POST status: " << status << llendl;
llinfos << " SLM POST reason: " << reason << llendl;
llinfos << " SLM POST content: " << content.asString() << llendl;
llinfos << " SLM POST timer: " << slmPostTimer.getElapsedTimeF32() << llendl;
}
if ((status == MarketplaceErrorCodes::IMPORT_REDIRECT) ||
(status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) ||
(status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT))
{
if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
{
llinfos << " SLM POST clearing marketplace cookie due to authentication failure or timeout" << llendl;
}
sMarketplaceCookie.clear();
}
sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE);
sImportPostPending = false;
sImportResultStatus = status;
sImportId = content;
}
};
class LLImportGetResponder : public LLHTTPClient::Responder
{
public:
LLImportGetResponder() : LLCurl::Responder() {}
void completedHeader(U32 status, const std::string& reason, const LLSD& content)
{
const std::string& set_cookie_string = content["set-cookie"].asString();
if (!set_cookie_string.empty())
{
sMarketplaceCookie = set_cookie_string;
}
}
void completed(U32 status, const std::string& reason, const LLSD& content)
{
slmGetTimer.stop();
if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
{
llinfos << " SLM GET status: " << status << llendl;
llinfos << " SLM GET reason: " << reason << llendl;
llinfos << " SLM GET content: " << content.asString() << llendl;
llinfos << " SLM GET timer: " << slmGetTimer.getElapsedTimeF32() << llendl;
}
if ((status == MarketplaceErrorCodes::IMPORT_AUTHENTICATION_ERROR) ||
(status == MarketplaceErrorCodes::IMPORT_JOB_TIMEOUT))
{
if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
{
llinfos << " SLM GET clearing marketplace cookie due to authentication failure or timeout" << llendl;
}
sMarketplaceCookie.clear();
}
sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING);
sImportGetPending = false;
sImportResultStatus = status;
sImportResults = content;
}
};
// Basic API
bool hasSessionCookie()
{
return !sMarketplaceCookie.empty();
}
bool inProgress()
{
return sImportInProgress;
}
bool resultPending()
{
return (sImportPostPending || sImportGetPending);
}
U32 getResultStatus()
{
return sImportResultStatus;
}
const LLSD& getResults()
{
return sImportResults;
}
static std::string getInventoryImportURL()
{
std::string url = getMarketplaceURL("MarketplaceURL");
url += "api/1/";
url += gAgent.getID().getString();
url += "/inventory/import/";
return url;
}
bool establishMarketplaceSessionCookie()
{
if (hasSessionCookie())
{
return false;
}
sImportInProgress = true;
sImportGetPending = true;
std::string url = getInventoryImportURL();
if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
{
llinfos << " SLM GET: " << url << llendl;
}
slmGetTimer.start();
LLHTTPClient::get(url, new LLImportGetResponder(), LLViewerMedia::getHeaders());
return true;
}
bool pollStatus()
{
if (!hasSessionCookie())
{
return false;
}
sImportGetPending = true;
std::string url = getInventoryImportURL();
url += sImportId.asString();
// Make the headers for the post
LLSD headers = LLSD::emptyMap();
headers["Accept"] = "*/*";
headers["Cookie"] = sMarketplaceCookie;
headers["Content-Type"] = "application/llsd+xml";
headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent();
if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
{
llinfos << " SLM GET: " << url << llendl;
}
slmGetTimer.start();
LLHTTPClient::get(url, new LLImportGetResponder(), headers);
return true;
}
bool triggerImport()
{
if (!hasSessionCookie())
{
return false;
}
sImportId = LLSD::emptyMap();
sImportInProgress = true;
sImportPostPending = true;
sImportResultStatus = MarketplaceErrorCodes::IMPORT_PROCESSING;
sImportResults = LLSD::emptyMap();
std::string url = getInventoryImportURL();
// Make the headers for the post
LLSD headers = LLSD::emptyMap();
headers["Accept"] = "*/*";
headers["Connection"] = "Keep-Alive";
headers["Cookie"] = sMarketplaceCookie;
headers["Content-Type"] = "application/xml";
headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent();
if (gSavedSettings.getBOOL("InventoryOutboxLogging"))
{
llinfos << " SLM POST: " << url << llendl;
}
slmPostTimer.start();
LLHTTPClient::post(url, LLSD(), new LLImportPostResponder(), headers);
return true;
}
}
//
// Interface class
//
static const F32 MARKET_IMPORTER_UPDATE_FREQUENCY = 300.0f; //1.0f;
//static
void LLMarketplaceInventoryImporter::update()
{
if (instanceExists())
{
static LLTimer update_timer;
if (update_timer.hasExpired())
{
LLMarketplaceInventoryImporter::instance().updateImport();
update_timer.setTimerExpirySec(MARKET_IMPORTER_UPDATE_FREQUENCY);
}
}
}
LLMarketplaceInventoryImporter::LLMarketplaceInventoryImporter()
: mAutoTriggerImport(false)
, mImportInProgress(false)
, mInitialized(false)
, mErrorInitSignal(NULL)
, mStatusChangedSignal(NULL)
, mStatusReportSignal(NULL)
{
}
boost::signals2::connection LLMarketplaceInventoryImporter::setInitializationErrorCallback(const status_report_signal_t::slot_type& cb)
{
if (mErrorInitSignal == NULL)
{
mErrorInitSignal = new status_report_signal_t();
}
return mErrorInitSignal->connect(cb);
}
boost::signals2::connection LLMarketplaceInventoryImporter::setStatusChangedCallback(const status_changed_signal_t::slot_type& cb)
{
if (mStatusChangedSignal == NULL)
{
mStatusChangedSignal = new status_changed_signal_t();
}
return mStatusChangedSignal->connect(cb);
}
boost::signals2::connection LLMarketplaceInventoryImporter::setStatusReportCallback(const status_report_signal_t::slot_type& cb)
{
if (mStatusReportSignal == NULL)
{
mStatusReportSignal = new status_report_signal_t();
}
return mStatusReportSignal->connect(cb);
}
void LLMarketplaceInventoryImporter::initialize()
{
llassert(!mInitialized);
if (!LLMarketplaceImport::hasSessionCookie())
{
LLMarketplaceImport::establishMarketplaceSessionCookie();
}
}
void LLMarketplaceInventoryImporter::reinitializeAndTriggerImport()
{
mInitialized = false;
initialize();
mAutoTriggerImport = true;
}
bool LLMarketplaceInventoryImporter::triggerImport()
{
const bool import_triggered = LLMarketplaceImport::triggerImport();
if (!import_triggered)
{
reinitializeAndTriggerImport();
}
return import_triggered;
}
void LLMarketplaceInventoryImporter::updateImport()
{
const bool in_progress = LLMarketplaceImport::inProgress();
if (in_progress && !LLMarketplaceImport::resultPending())
{
const bool polling_status = LLMarketplaceImport::pollStatus();
if (!polling_status)
{
reinitializeAndTriggerImport();
}
}
if (mImportInProgress != in_progress)
{
mImportInProgress = in_progress;
// If we are no longer in progress
if (!mImportInProgress)
{
if (mInitialized)
{
// Report results
if (mStatusReportSignal)
{
(*mStatusReportSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults());
}
}
else
{
// Look for results success
mInitialized = LLMarketplaceImport::hasSessionCookie();
if (mInitialized)
{
// Follow up with auto trigger of import
if (mAutoTriggerImport)
{
mAutoTriggerImport = false;
mImportInProgress = triggerImport();
}
}
else if (mErrorInitSignal)
{
(*mErrorInitSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults());
}
}
}
// Make sure we trigger the status change with the final state (in case of auto trigger after initialize)
if (mStatusChangedSignal)
{
(*mStatusChangedSignal)(mImportInProgress);
}
}
}

View File

@@ -0,0 +1,94 @@
/**
* @file llmarketplacefunctions.h
* @brief Miscellaneous marketplace-related functions and classes
* class definition
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2011, 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_LLMARKETPLACEFUNCTIONS_H
#define LL_LLMARKETPLACEFUNCTIONS_H
#include <llsd.h>
#include <boost/function.hpp>
#include <boost/signals2.hpp>
#include "llsingleton.h"
#include "llstring.h"
LLSD getMarketplaceStringSubstitutions();
namespace MarketplaceErrorCodes
{
enum eCode
{
IMPORT_DONE = 200,
IMPORT_PROCESSING = 202,
IMPORT_REDIRECT = 302,
IMPORT_AUTHENTICATION_ERROR = 401,
IMPORT_DONE_WITH_ERRORS = 409,
IMPORT_JOB_FAILED = 410,
IMPORT_JOB_TIMEOUT = 499,
};
}
class LLMarketplaceInventoryImporter
: public LLSingleton<LLMarketplaceInventoryImporter>
{
public:
static void update();
LLMarketplaceInventoryImporter();
typedef boost::signals2::signal<void (bool)> status_changed_signal_t;
typedef boost::signals2::signal<void (U32, const LLSD&)> status_report_signal_t;
boost::signals2::connection setInitializationErrorCallback(const status_report_signal_t::slot_type& cb);
boost::signals2::connection setStatusChangedCallback(const status_changed_signal_t::slot_type& cb);
boost::signals2::connection setStatusReportCallback(const status_report_signal_t::slot_type& cb);
void initialize();
bool triggerImport();
bool isImportInProgress() const { return mImportInProgress; }
protected:
void reinitializeAndTriggerImport();
void updateImport();
private:
bool mAutoTriggerImport;
bool mImportInProgress;
bool mInitialized;
status_report_signal_t * mErrorInitSignal;
status_changed_signal_t * mStatusChangedSignal;
status_report_signal_t * mStatusReportSignal;
};
#endif // LL_LLMARKETPLACEFUNCTIONS_H

View File

@@ -0,0 +1,149 @@
/**
* @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 "lltrans.h"
//#include "llviewerfoldertype.h"
//
// statics
//
static LLRegisterWidget<LLOutboxInventoryPanel> r1("outbox_inventory_panel");
//static LLRegisterWidget<LLOutboxFolderViewFolder> r2("outbox_folder_view_folder");
//
// LLOutboxInventoryPanel Implementation
//
LLOutboxInventoryPanel::LLOutboxInventoryPanel(const std::string& name,
const std::string& sort_order_setting,
const std::string& start_folder,
const LLRect& rect,
LLInventoryModel* inventory,
BOOL allow_multi_select,
LLView* parent_view)
: LLInventoryPanel(name, sort_order_setting, start_folder, rect, inventory, allow_multi_select, parent_view)
{
}
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);
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, true/*params.use_label_suffix()*/);
}
LLFolderViewFolder * LLOutboxInventoryPanel::createFolderViewFolder(LLInvFVBridge * bridge)
{
return new LLOutboxFolderViewFolder(
bridge->getDisplayName(),
bridge->getIcon(),
bridge->getOpenIcon(),
LLUI::getUIImage("inv_link_overlay.tga"),
mFolderRoot,
bridge);
}
LLFolderViewItem * LLOutboxInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge)
{
return new LLOutboxFolderViewItem(
bridge->getDisplayName(),
bridge->getIcon(),
bridge->getOpenIcon(),
LLUI::getUIImage("inv_link_overlay.tga"),
bridge->getCreationDate(),
mFolderRoot,
bridge);
}
//
// LLOutboxFolderViewFolder Implementation
//
LLOutboxFolderViewFolder::LLOutboxFolderViewFolder(const std::string& name, LLUIImagePtr icon,
LLUIImagePtr icon_open,
LLUIImagePtr icon_link,
LLFolderView* root,
LLFolderViewEventListener* listener)
: LLFolderViewFolder(name, icon, icon_open, icon_link, root, listener)
{
}
//
// LLOutboxFolderViewItem Implementation
//
LLOutboxFolderViewItem::LLOutboxFolderViewItem(const std::string& name, LLUIImagePtr icon,
LLUIImagePtr icon_open,
LLUIImagePtr icon_overlay,
S32 creation_date,
LLFolderView* root,
LLFolderViewEventListener* listener)
: LLFolderViewItem(name, icon, icon_open, icon_overlay, creation_date, root, listener)
{
}
BOOL LLOutboxFolderViewItem::handleDoubleClick(S32 x, S32 y, MASK mask)
{
return TRUE;
}
void LLOutboxFolderViewItem::openItem()
{
// Intentionally do nothing to block attaching items from the outbox
}
// eof

View File

@@ -0,0 +1,74 @@
/**
* @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 "llinventorypanel.h"
#include "llfolderviewitem.h"
class LLOutboxInventoryPanel : public LLInventoryPanel
{
public:
LLOutboxInventoryPanel(const std::string& name,
const std::string& sort_order_setting,
const std::string& start_folder,
const LLRect& rect,
LLInventoryModel* inventory,
BOOL allow_multi_select,
LLView *parent_view = NULL);
~LLOutboxInventoryPanel();
// virtual
void buildFolderView(/*const LLInventoryPanel::Params& params*/);
// virtual
LLFolderViewFolder * createFolderViewFolder(LLInvFVBridge * bridge);
LLFolderViewItem * createFolderViewItem(LLInvFVBridge * bridge);
};
class LLOutboxFolderViewFolder : public LLFolderViewFolder
{
public:
LLOutboxFolderViewFolder(const std::string& name, LLUIImagePtr icon, LLUIImagePtr icon_open, LLUIImagePtr icon_link, LLFolderView* root, LLFolderViewEventListener* listener);
};
class LLOutboxFolderViewItem : public LLFolderViewItem
{
public:
LLOutboxFolderViewItem(const std::string& name, LLUIImagePtr icon, LLUIImagePtr icon_open, LLUIImagePtr icon_overlay, S32 creation_date, LLFolderView* root, LLFolderViewEventListener* listener);
// virtual
BOOL handleDoubleClick(S32 x, S32 y, MASK mask);
void openItem();
};
#endif //LL_OUTBOXINVENTORYPANEL_H

View File

@@ -358,7 +358,7 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary()
addEntry(DAD_NOTECARD, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_CATEGORY, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearCategory, &LLToolDragAndDrop::dad3dGiveInventoryCategory, &LLToolDragAndDrop::dad3dUpdateInventoryCategory, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_ROOT_CATEGORY, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_BODYPART, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearItem, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_BODYPART, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dWearItem, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_ANIMATION, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_GESTURE, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dActivateGesture, &LLToolDragAndDrop::dad3dGiveInventory, &LLToolDragAndDrop::dad3dUpdateInventory, &LLToolDragAndDrop::dad3dNULL));
addEntry(DAD_LINK, new DragAndDropEntry(&LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL, &LLToolDragAndDrop::dad3dNULL));
@@ -1710,6 +1710,12 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv(
//}
// </edit>
const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
if(gInventory.isObjectDescendentOf(item->getUUID(), outbox_id))
{
return ACCEPT_NO;
}
// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.2.1f
if ( (rlv_handler_t::isEnabled()) && (gRlvAttachmentLocks.hasLockedAttachmentPoint(RLV_LOCK_ANY)) )
{
@@ -1739,7 +1745,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv(
else
{
// rez_attachment(item, 0);
// [SL:KB] - Patch: Appearance-Misc | Checked: 2010-09-08 (Catznip-2.2.0a) | Added: Catznip-2.2.0a
// [SL:KB] - Patch: Appearance-DnDWear | Checked: 2010-09-28 (Catznip-3.0.0a) | Added: Catznip-2.2.0a
// Make this behave consistent with dad3dWearItem
rez_attachment(item, 0, !(mask & MASK_CONTROL));
// [/SL:KB]
@@ -2068,7 +2074,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearItem(
if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY)
{
// it's in the agent inventory
LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) )
{
return ACCEPT_NO;
@@ -2118,7 +2124,7 @@ EAcceptance LLToolDragAndDrop::dad3dActivateGesture(
if(mSource == SOURCE_AGENT || mSource == SOURCE_LIBRARY)
{
// it's in the agent inventory
LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
if( gInventory.isObjectDescendentOf( item->getUUID(), trash_id ) )
{
return ACCEPT_NO;
@@ -2191,7 +2197,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory(
if(drop)
{
BOOL append = ( (mask & MASK_SHIFT) ? TRUE : FALSE );
BOOL append = ( (mask & MASK_SHIFT) ? TRUE : FALSE );
LLAppearanceMgr::instance().wearInventoryCategory(category, false, append);
}
return ACCEPT_YES_MULTI;

View File

@@ -139,6 +139,7 @@
#include "llfloatermute.h"
#include "llfloateropenobject.h"
#include "llfloateroutbox.h"
#include "llfloaterpermissionsmgr.h"
#include "llfloaterperms.h"
#include "llfloaterpostprocess.h"
@@ -6537,6 +6538,10 @@ class LLShowFloater : public view_listener_t
{
LLFloaterPerms::toggleInstance(LLSD());
}
else if (floater_name == "outbox")
{
LLFloaterOutbox::toggleInstance(LLSD());
}
return true;
}
};
@@ -6611,6 +6616,10 @@ class LLFloaterVisible : public view_listener_t
if (!instn) new_value = false;
else new_value = instn->getVisible();
}
else if (floater_name == "outbox")
{
new_value = LLFloaterOutbox::instanceVisible(LLSD());
}
gMenuHolder->findControl(control_name)->setValue(new_value);
return true;
}

View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<floater
positioning="cascading"
can_close="true"
can_resize="true"
height="440"
help_topic="floater_merchant_outbox"
min_width="300"
min_height="200"
name="floater_merchant_outbox"
save_rect="true"
save_visibility="false"
reuse_instance="true"
title="Merchant Outbox"
width="333">
<string name="OutboxFolderCount0">No folders</string>
<string name="OutboxFolderCount1">1 folder</string>
<string name="OutboxFolderCountN">[NUM] folders</string>
<string name="OutboxImporting">Sending folders...</string>
<string name="OutboxInitializing">Initializing...</string>
<!--panel
name="panel_1 this panel killed xui names, for some reason"
follows="all"
layout="topleft"
left="0"
top="0"
label=""
height="440"
width="333"-->
<panel
name="outbox_inventory_placeholder_panel"
mouse_opaque="false"
follows="all"
layout="topleft"
bottom="70"
left="10"
width="308"
height="352"
bg_opaque_color="InventoryBackgroundColor">
<text
name="outbox_inventory_placeholder_title"
type="string"
follows="top|left|right"
layout="topleft"
top="355"
left="0"
width="308"
height="25"
wrap="true"
halign="center"
font="SansSerifBold">
Loading...
</text>
<text_editor
name="outbox_inventory_placeholder_text"
type="string"
follows="top|left|right"
layout="topleft"
top="337"
left="0"
width="308"
bottom="130"
wrap="true"
enabled="false"
font="SansSerifSmall"
hide_scrollbar="true"
hide_border="true"
bg_readonly_color="0 0 0 0"
halign="left" />
</panel>
<inventory_panel
name="panel_outbox_inventory"
mouse_opaque="false"
filename="panel_outbox_inventory.xml"
follows="all"
layout="topleft"
bottom="70"
left="10"
width="308"
height="352"
bg_opaque_color="InventoryBackgroundColor"/>
<panel
name="panel_2"
mouse_opaque="false"
follows="bottom|left|right"
left="10"
bottom="5"
width="313"
top="70">
<panel
name="outbox_generic_drag_target"
mouse_opaque="false"
follows="left|right"
bottom="33"
left="0"
width="308"
height="25"
background_visible="false"
bg_alpha_color="0.950 0.412 0.173 0.35"
border="true"
bevel_style="in"
visible="true">
<text
name="text_1"
type="string"
follows="all"
layout="topleft"
height="20"
left="5"
width="293"
halign="center"
font="SansSerifMedium"
font_shadow="hard"
valign="top">
Drag items here to create folders
</text>
</panel>
<text
name="outbox_folder_count"
type="string"
follows="all"
layout="topleft"
bottom_delta="-27"
left="0"
width="150"
height="20"
wrap="true"
halign="left"
valign="center"
font="SansSerif"/>
<button
label="Send to Marketplace"
tool_tip="Push to my Marketplace Storefront"
name="outbox_import_btn"
follows="bottom|right"
tab_stop="false"
halign="center"
bottom_delta="-3"
left="160"
height="25"
width="150"
enabled="false" />
</panel>
<text name="import_progress_indicator" left="160" height="440" top="438" width="333" follows="all" visible="false">Import in progress</text>
<!--/panel-->
</floater>

View File

@@ -311,11 +311,13 @@
</menu_item_call>
<menu_item_separator name="Marketplace Separator" />
<menu_item_call bottom_delta="-18" height="18" label="Copy to Merchant Outbox" left="0" mouse_opaque="true"
name="Merchant Copy" width="128"/>
name="Merchant Copy" width="128">
<on_click filter="" function="Inventory.DoToSelected" userdata="copy_to_outbox" />
</menu_item_call>
<menu_item_call bottom_delta="-18" height="18" label="Send to Marketplace" left="0" mouse_opaque="true"
name="Marketplace Send" width="128"/>
name="Marketplace Send" width="128">
<on_click filter="" function="Inventory.DoToSelected" userdata="send_to_marketplace" />
</menu_item_call>
<menu_item_call bottom_delta="-18" height="18" label="--no options--" left="0"
mouse_opaque="true" name="--no options--" width="128" />
<!--menu_item_separator name="Wearable Separator" -->

View File

@@ -547,6 +547,12 @@
<on_click function="PromptShowURL" name="ManageMyAccount_url"
userdata="WebLaunchJoinNow,http://secondlife.com/account/" />
</menu_item_call>
<menu_item_check
label="Merchant Outbox..."
name="MerchantOutbox">
<on_click function="ShowFloater" userdata="outbox" />
<on_check function="FloaterVisible" userdata="outbox" />
</menu_item_check>
<menu_item_call bottom="-286" enabled="true" height="19" label="Buy [CURRENCY]..." left="0"
mouse_opaque="true" name="Buy and Sell L$..." width="166">
<on_click function="ShowFloater" userdata="buy currency" />

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<outbox_inventory_panel
name="inventory_outbox"
start_folder="Outbox"
follows="all" layout="topleft"
top="0" left="0" height="165" width="308"
top_pad="0"
bg_opaque_color="0.169 0.169 0.169 1"
bg_alpha_color="0.169 0.169 0.169 1"
background_visible="true"
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" />
</outbox_inventory_panel>

View File

@@ -2853,6 +2853,23 @@ Where tag = tag string to match. Removes bot's matching the tag.
<!-- inventory -->
<string name="InventoryNoMatchingItems">No matching items found in inventory.</string>
<string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/</string>
<string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4</string>
<string name="MarketplaceURL_Dashboard">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard</string>
<string name="MarketplaceURL_Imports">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/imports</string>
<string name="MarketplaceURL_LearnMore">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more</string>
<string name="InventoryOutboxNotMerchantTitle">Anyone can sell items on the Marketplace.</string>
<string name="InventoryOutboxNotMerchantTooltip"></string>
<string name="InventoryOutboxNotMerchant">
If you'd like to become a merchant, you'll need to
</string>
<string name="InventoryOutboxNotMerchantSubs">create a Marketplace store.</string>
<string name="InventoryOutboxNoItemsTitle">Your outbox is empty.</string>
<string name="InventoryOutboxNoItemsTooltip"></string>
<string name="InventoryOutboxNoItems">
Drag folders to this area and click "Send to Marketplace" to list them for sale on the
</string>
<string name="InventoryOutboxNoItemsSubs">Marketplace.</string>
<!-- use value="" because they have preceding spaces -->
<string name="no_transfer" value=" (no transfer)" />