Commit abdb9ad8 authored by Kitty Barnett's avatar Kitty Barnett

Merged with .Catznip tip

--HG--
branch : Catznip
parents e2a5878d 215cafaf
......@@ -45,6 +45,10 @@
#include "llscrolllistctrl.h"
#include "llviewerobject.h"
#include "lluictrlfactory.h"
// [SL:KB] - Patch: Inventory-OfferToast | Checked: Catznip-5.2
#include "llpanelinventoryoffer.h"
#include "llviewercontrol.h"
// [/SL:KB]
#include "llviewerwindow.h"
#include "lltrans.h"
......@@ -182,6 +186,10 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info)
floater->getChild<LLUICtrl>("buy_text")->setTextArg("[AMOUNT]", llformat("%d", sale_info.getSalePrice()));
floater->getChild<LLUICtrl>("buy_name_text")->setTextArg("[NAME]", owner_name);
// [SL:KB] - Patch: Inventory-OfferToast | Checked: Catznip-5.2
floater->getChild<LLUICtrl>("buy_btn")->setEnabled(true);
// [/SL:KB]
// Must do this after the floater is created, because
// sometimes the inventory is already there and
// the callback is called immediately.
......@@ -288,18 +296,52 @@ void LLFloaterBuy::inventoryChanged(LLViewerObject* obj,
void LLFloaterBuy::onClickBuy()
{
// Put the items where we put new folders.
LLUUID category_id;
category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
// [SL:KB] - Patch: Inventory-OfferToast | Checked: Catznip-5.2
if (gSavedPerAccountSettings.getBOOL("InventoryOfferAcceptIn"))
{
const LLUUID idDestFolder(gSavedPerAccountSettings.getString("InventoryOfferAcceptInFolder"));
if ( (idDestFolder.notNull()) && (gInventory.getCategory(idDestFolder)) )
{
// Prevent the user from clicking buy a second time while we wait for the folder to be created
getChild<LLUICtrl>("buy_btn")->setEnabled(false);
// *NOTE: doesn't work for multiple object buy, which UI does not
// currently support sale info is used for verification only, if
// it doesn't match region info then sale is canceled.
LLSelectMgr::getInstance()->sendBuy(gAgent.getID(), category_id, mSaleInfo );
// Create the destination folder (note: might fire instantly if the folder already exists)
new LLCreateAcceptInFolder(idDestFolder, boost::bind(&LLFloaterBuy::onClickBuyCb, getHandle(), _1));
closeFloater();
return;
}
}
// Put the items where we put new folders.
LLUUID category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
onClickBuyCb(getHandle(), category_id);
// [/SL:KB]
// // Put the items where we put new folders.
// LLUUID category_id;
// category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT);
//
// // *NOTE: doesn't work for multiple object buy, which UI does not
// // currently support sale info is used for verification only, if
// // it doesn't match region info then sale is canceled.
// LLSelectMgr::getInstance()->sendBuy(gAgent.getID(), category_id, mSaleInfo );
//
// closeFloater();
}
// [SL:KB] - Patch: Inventory-OfferToast | Checked: Catznip-5.2
void LLFloaterBuy::onClickBuyCb(LLHandle<LLFloater> handle, const LLUUID& idDestFolder)
{
LLFloaterBuy* pInstance = dynamic_cast<LLFloaterBuy*>(handle.get());
if ( (pInstance) && (!pInstance->isDead()) && (pInstance->isInVisibleChain()) )
{
// *NOTE: doesn't work for multiple object buy, which UI does not
// currently support sale info is used for verification only, if
// it doesn't match region info then sale is canceled.
LLSelectMgr::getInstance()->sendBuy(gAgent.getID(), idDestFolder, pInstance->mSaleInfo);
pInstance->closeFloater();
}
}
// [/SL:KB]
void LLFloaterBuy::onClickCancel()
{
......
......@@ -64,6 +64,10 @@ class LLFloaterBuy
void* data);
void onClickBuy();
// [SL:KB] - Patch: Inventory-OfferToast | Checked: Catznip-5.2
static void onClickBuyCb(LLHandle<LLFloater> handle, const LLUUID& idDestFolder);
// [/SL:KB]
void onClickCancel();
private:
......
......@@ -47,6 +47,10 @@
#include "llnotificationsutil.h"
#include "llselectmgr.h"
#include "llscrolllistctrl.h"
// [SL:KB] - Patch: Inventory-OfferToast | Checked: Catznip-5.2
#include "llpanelinventoryoffer.h"
#include "llviewercontrol.h"
// [/SL:KB]
#include "llviewerobject.h"
#include "llviewerregion.h"
#include "lluictrlfactory.h"
......@@ -279,10 +283,20 @@ void LLFloaterBuyContents::onClickBuy()
return;
}
// We may want to wear this item
if (getChild<LLUICtrl>("wear_check")->getValue())
// [SL:KB] - Patch: Inventory-OfferToast | Checked: Catznip-5.2
if (gSavedPerAccountSettings.getBOOL("InventoryOfferAcceptIn"))
{
LLInventoryState::sWearNewClothing = TRUE;
const LLUUID idDestFolder(gSavedPerAccountSettings.getString("InventoryOfferAcceptInFolder"));
if ( (idDestFolder.notNull()) && (gInventory.getCategory(idDestFolder)) )
{
// Prevent the user from clicking buy a second time while we wait for the folder to be created
getChild<LLUICtrl>("buy_btn")->setEnabled(false);
// Create the destination folder (note: might fire instantly if the folder already exists)
new LLCreateAcceptInFolder(idDestFolder, boost::bind(&LLFloaterBuyContents::onClickBuyCb, getHandle(), _1));
return;
}
}
// [SL:KB] - Patch: Inventory-ShowNewInventory | Checked: 2014-03-15 (Catznip-3.6)
......@@ -293,21 +307,57 @@ void LLFloaterBuyContents::onClickBuy()
// [/SL:KB]
// Put the items where we put new folders.
LLUUID category_id;
category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_ROOT_INVENTORY);
// *NOTE: doesn't work for multiple object buy, which UI does not
// currently support sale info is used for verification only, if
// it doesn't match region info then sale is canceled.
LLSelectMgr::getInstance()->sendBuy(gAgent.getID(), category_id, mSaleInfo);
// NOTE: do this here instead of on receipt of object, since contents are transfered
// via a generic BulkUpdateInventory message with no way of distinguishing it from
// other inventory operations
LLFirstUse::newInventory();
closeFloater();
LLUUID category_id = category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_ROOT_INVENTORY);
onClickBuyCb(getHandle(), category_id);
// [/SL:KB]
// // We may want to wear this item
// if (getChild<LLUICtrl>("wear_check")->getValue())
// {
// LLInventoryState::sWearNewClothing = TRUE;
// }
//
// // Put the items where we put new folders.
// LLUUID category_id;
// category_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_ROOT_INVENTORY);
//
// // *NOTE: doesn't work for multiple object buy, which UI does not
// // currently support sale info is used for verification only, if
// // it doesn't match region info then sale is canceled.
// LLSelectMgr::getInstance()->sendBuy(gAgent.getID(), category_id, mSaleInfo);
//
// // NOTE: do this here instead of on receipt of object, since contents are transfered
// // via a generic BulkUpdateInventory message with no way of distinguishing it from
// // other inventory operations
// LLFirstUse::newInventory();
// closeFloater();
}
// [SL:KB] - Patch: Inventory-OfferToast | Checked: Catznip-5.2
void LLFloaterBuyContents::onClickBuyCb(LLHandle<LLFloater> handle, const LLUUID& idDestFolder)
{
LLFloaterBuyContents* pInstance = dynamic_cast<LLFloaterBuyContents*>(handle.get());
if ( (pInstance) && (!pInstance->isDead()) && (pInstance->isInVisibleChain()) )
{
// We may want to wear this item
if (pInstance->getChild<LLUICtrl>("wear_check")->getValue())
{
LLInventoryState::sWearNewClothing = TRUE;
}
// *NOTE: doesn't work for multiple object buy, which UI does not
// currently support sale info is used for verification only, if
// it doesn't match region info then sale is canceled.
LLSelectMgr::getInstance()->sendBuy(gAgent.getID(), idDestFolder, pInstance->mSaleInfo);
// NOTE: do this here instead of on receipt of object, since contents are transfered
// via a generic BulkUpdateInventory message with no way of distinguishing it from
// other inventory operations
LLFirstUse::newInventory();
pInstance->closeFloater();
}
}
// [/SL:KB]
void LLFloaterBuyContents::onClickCancel()
{
closeFloater();
......
......@@ -58,6 +58,9 @@ class LLFloaterBuyContents
void* data);
void onClickBuy();
// [SL:KB] - Patch: Inventory-OfferToast | Checked: Catznip-5.2
static void onClickBuyCb(LLHandle<LLFloater> handle, const LLUUID& idDestFolder);
// [/SL:KB]
void onClickCancel();
protected:
......
......@@ -27,8 +27,8 @@
// LLFloaterInventoryOfferFolderBrowse class
//
LLFloaterInventoryOfferFolderBrowse::LLFloaterInventoryOfferFolderBrowse(const LLUUID& idFolder)
: LLFloater(LLSD().with("uuid", idFolder))
LLFloaterInventoryOfferFolderBrowse::LLFloaterInventoryOfferFolderBrowse()
: LLFloater(LLSD())
{
buildFromFile("floater_offer_invfolder_browse.xml");
}
......@@ -52,6 +52,7 @@ BOOL LLFloaterInventoryOfferFolderBrowse::postBuild()
U32 maskFilterTypes = 0x1 << LLInventoryType::IT_CATEGORY;
m_pInvPanel->setFilterTypes(maskFilterTypes);
m_pInvPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
m_pInvPanel->getFilter().setFilterCategoryTypes(m_pInvPanel->getFilter().getFilterCategoryTypes() | (1ULL << LLFolderType::FT_INBOX));
m_pInvPanel->getFilter().markDefault();
m_pSavedFolderState = new LLSaveFolderState();
......@@ -79,7 +80,7 @@ void LLFloaterInventoryOfferFolderBrowse::onCommit()
// virtual
void LLFloaterInventoryOfferFolderBrowse::onOpen(const LLSD& sdKey)
{
const LLUUID idInvObject = sdKey["uuid"].asUUID();
const LLUUID idInvObject = sdKey["folder_id"].asUUID();
if (idInvObject.notNull())
{
m_pInvPanel->setSelection(idInvObject, TAKE_FOCUS_NO);
......
......@@ -34,7 +34,7 @@ class LLFloaterInventoryOfferFolderBrowse : public LLFloater
{
LOG_CLASS(LLFloaterInventoryOfferFolderBrowse);
public:
LLFloaterInventoryOfferFolderBrowse(const LLUUID& idFolder = LLUUID::null);
LLFloaterInventoryOfferFolderBrowse();
~LLFloaterInventoryOfferFolderBrowse() override;
/*
......
......@@ -24,6 +24,7 @@
#include "llfloaterofferinvfolderbrowse.h"
#include "llfloaterofferinvfolderconfig.h"
#include "llinventoryfunctions.h"
#include "llnotifications.h"
#include "llnotificationsutil.h"
#include "llviewercontrol.h"
......@@ -73,10 +74,23 @@ BOOL LLFloaterInventoryOfferFolderConfig::postBuild()
return TRUE;
}
// virtual
void LLFloaterInventoryOfferFolderConfig::closeFloater(bool app_quitting /*=false*/)
{
if ( ((m_fFolderItemsDirty) || (isDirty())) && (!app_quitting) )
{
LLNotificationsUtil::add("InventoryOfferFolderConfigSaveChanges", LLSD(), LLSD(), boost::bind(&LLFloaterInventoryOfferFolderConfig::onSaveChangesCb, this, _1, _2));
return;
}
LLFloater::closeFloater(app_quitting);
}
// virtual
void LLFloaterInventoryOfferFolderConfig::onCommit()
{
gSavedPerAccountSettings.setLLSD("InventoryOfferAcceptInOptions", m_sdFolderItems);
m_fFolderItemsDirty = false;
LLFloater::onCommit();
}
......@@ -176,6 +190,7 @@ void LLFloaterInventoryOfferFolderConfig::onRemoveFolder()
if (m_sdFolderItems[idxFolder]["uuid"].asUUID() == sdSelValue.asUUID())
{
m_sdFolderItems.erase(idxFolder);
m_fFolderItemsDirty = true;
break;
}
}
......@@ -186,9 +201,47 @@ void LLFloaterInventoryOfferFolderConfig::onRemoveFolder()
}
void LLFloaterInventoryOfferFolderConfig::onSelectFolder()
{
LLNotification::Params::Functor f;
f.function = boost::bind(&LLFloaterInventoryOfferFolderConfig::onSelectFolderCb, this, _1, _2);
if (isDirty())
{
LLNotifications::instance().add(LLNotification::Params().name("InventoryOfferFolderConfigSaveChangesFolder")
.substitutions(LLSD().with("NAME", m_pEditFolderName->getText()))
.payload(LLSD())
.functor(f));
}
else
{
LLNotifications::instance().forceResponse(LLNotification::Params("InventoryOfferFolderConfigSaveChangesFolder").payload(LLSD())
.functor(f), 1 /*NO*/);
}
}
void LLFloaterInventoryOfferFolderConfig::onSelectFolderCb(const LLSD& sdNotification, const LLSD& sdResponse)
{
const LLSD sdSelValue = m_pFolderList->getSelectedValue();
//
// Handle the notification response
//
S32 idxOption = LLNotificationsUtil::getSelectedOption(sdNotification, sdResponse);
switch (idxOption)
{
case 0: // Yes (Save)
onSaveFolder();
m_pFolderList->selectByValue(sdSelValue);
break;
case 1: // No (Don't Save)
break;
case 2: // Cancel
return;
}
//
// Handle the selection
//
m_pEditFolderItem = nullptr;
for (LLSD::array_iterator itFolder = m_sdFolderItems.beginArray(), endFolder = m_sdFolderItems.endArray(); itFolder != endFolder; ++itFolder)
{
......@@ -223,7 +276,7 @@ void LLFloaterInventoryOfferFolderConfig::onBrowseFolder()
if (LLFloater* pBrowseFloater = new LLFloaterInventoryOfferFolderBrowse())
{
pBrowseFloater->setCommitCallback(boost::bind(&LLFloaterInventoryOfferFolderConfig::onBrowseFolderCb, this, _2));
pBrowseFloater->openFloater();
pBrowseFloater->openFloater(LLSD().with("folder_id", m_idEditFolder));
m_BrowseFloaterHandle = pBrowseFloater->getHandle();
}
......@@ -247,11 +300,13 @@ void LLFloaterInventoryOfferFolderConfig::onSaveFolder()
if ( (m_pEditFolderItem) && (m_pEditFolderItem->isUndefined()) )
{
m_sdFolderItems.append(folderInfo.toLLSD());
m_fFolderItemsDirty = true;
m_pEditFolderItem = &m_sdFolderItems[m_sdFolderItems.size() - 1];
}
else if (m_pEditFolderItem)
{
m_pEditFolderItem->assign(folderInfo.toLLSD());
m_fFolderItemsDirty = true;
}
m_pEditFolderName->resetDirty();
......@@ -264,14 +319,21 @@ void LLFloaterInventoryOfferFolderConfig::onSaveFolder()
void LLFloaterInventoryOfferFolderConfig::onOk()
{
LLNotification::Params::Functor f;
f.function = boost::bind(&LLFloaterInventoryOfferFolderConfig::onOkCb, this, _1, _2);
if (isDirty())
{
LLNotificationsUtil::add("InventoryOfferFolderConfigSaveChanges", LLSD().with("NAME", m_pEditFolderName->getText()), LLSD(), boost::bind(&LLFloaterInventoryOfferFolderConfig::onOkCb, this, _1, _2));
return;
LLNotifications::instance().add(LLNotification::Params().name("InventoryOfferFolderConfigSaveChangesFolder")
.substitutions(LLSD().with("NAME", m_pEditFolderName->getText()))
.payload(LLSD())
.functor(f));
}
else
{
LLNotifications::instance().forceResponse(LLNotification::Params("InventoryOfferFolderConfigSaveChangesFolder").payload(LLSD())
.functor(f), 1 /*NO*/);
}
onCommit();
closeFloater();
}
void LLFloaterInventoryOfferFolderConfig::onOkCb(const LLSD& sdNotification, const LLSD& sdResponse)
......@@ -282,6 +344,8 @@ void LLFloaterInventoryOfferFolderConfig::onOkCb(const LLSD& sdNotification, con
case 0: // Save
onSaveFolder();
break;
case 1: // Don't save
break;
case 2: // Cancel
return;
}
......@@ -292,9 +356,32 @@ void LLFloaterInventoryOfferFolderConfig::onOkCb(const LLSD& sdNotification, con
void LLFloaterInventoryOfferFolderConfig::onCancel()
{
m_fFolderItemsDirty = false;
clearControls();
closeFloater();
}
void LLFloaterInventoryOfferFolderConfig::onSaveChangesCb(const LLSD& sdNotification, const LLSD& sdResponse)
{
S32 idxOption = LLNotificationsUtil::getSelectedOption(sdNotification, sdResponse);
switch (idxOption)
{
case 0: // Persist the current entry changes and then update the setting
onSaveFolder();
onCommit();
break;
case 1: // Don't save anything
m_fFolderItemsDirty = false;
clearControls();
break;
case 2: // Cancel
return;
}
closeFloater();
}
// ============================================================================
// LLAcceptInFolder - helper data structure
//
......
......@@ -64,6 +64,7 @@ class LLFloaterInventoryOfferFolderConfig : public LLFloater
* LLFloater overrides
*/
public:
void closeFloater(bool app_quitting = false) override;
LLSD getValue() const { return m_sdFolderItems; }
BOOL isDirty() const override;
void onCommit() override;
......@@ -77,8 +78,10 @@ class LLFloaterInventoryOfferFolderConfig : public LLFloater
void onAddFolder();
void onRemoveFolder();
void onSelectFolder();
void onSelectFolderCb(const LLSD& sdNotification, const LLSD& sdResponse);
void onBrowseFolder();
void onBrowseFolderCb(const LLSD& sdData);
void onSaveChangesCb(const LLSD& sdNotification, const LLSD& sdResponse);
void onSaveFolder();
void onOk();
void onOkCb(const LLSD& sdNotification, const LLSD& sdResponse);
......@@ -93,6 +96,7 @@ class LLFloaterInventoryOfferFolderConfig : public LLFloater
* Member variables
*/
protected:
bool m_fFolderItemsDirty = false;
LLSD m_sdFolderItems;
LLScrollListCtrl* m_pFolderList = nullptr;
......
......@@ -137,7 +137,7 @@ void LLPanelInventoryOfferFolder::onBrowseFolder()
if (LLFloater* pBrowseFloater = new LLFloaterInventoryOfferFolderBrowse())
{
pBrowseFloater->setCommitCallback(boost::bind(&LLPanelInventoryOfferFolder::onBrowseFolderCb, this, _2));
pBrowseFloater->openFloater();
pBrowseFloater->openFloater(LLSD().with("folder_id", m_pAcceptInList->getSelectedValue().asUUID()));
m_BrowseFloaterHandle = pBrowseFloater->getHandle();
}
......@@ -248,7 +248,7 @@ bool LLAcceptInFolderOfferBase::createDestinationFolder()
// Split the path up in individual folders
//
if (std::string::npos != strSubfolderPath.find("/"))
boost::split(m_DestPath, strSubfolderPath, boost::is_any_of(std::string("/")));
boost::split(m_DestPath, strSubfolderPath, boost::is_any_of(std::string("/")), boost::algorithm::token_compress_on);
//
// Kick off creating the destination folder (if it doesn't already exist)
......@@ -272,9 +272,10 @@ void LLAcceptInFolderOfferBase::onCategoryCreateCallback(LLUUID idFolder, LLAcce
return;
}
while (pInstance->m_DestPath.size() > 1)
while (!pInstance->m_DestPath.empty())
{
std::string strFolder = pInstance->m_DestPath.front();
LLInventoryObject::correctInventoryName(strFolder);
pInstance->m_DestPath.pop_front();
LLInventoryModel::cat_array_t* folders;
......@@ -294,7 +295,6 @@ void LLAcceptInFolderOfferBase::onCategoryCreateCallback(LLUUID idFolder, LLAcce
}
else
{
LLInventoryObject::correctInventoryName(strFolder);
inventory_func_type f = boost::bind(LLAcceptInFolderOfferBase::onCategoryCreateCallback, _1, pInstance);
const LLUUID idTemp = gInventory.createNewCategory(idFolder, LLFolderType::FT_NONE, strFolder, f);
if (idTemp.notNull())
......@@ -455,3 +455,23 @@ void LLAcceptInFolderAgentOffer::onDestinationCreated(const LLUUID& idFolder)
}
// ============================================================================
// LLCreateAcceptInFolder class
//
LLCreateAcceptInFolder::LLCreateAcceptInFolder(const LLUUID& idBaseFolder, const folder_created_signal_t::slot_type& cb)
: LLAcceptInFolderOfferBase(idBaseFolder)
{
m_FolderCreatedSignal.connect(cb);
if (!createDestinationFolder())
delete this;
}
//virtual
void LLCreateAcceptInFolder::onDestinationCreated(const LLUUID& idFolder)
{
m_FolderCreatedSignal(idFolder);
delete this;
}
// ============================================================================
......@@ -147,3 +147,27 @@ class LLAcceptInFolderAgentOffer : public LLAcceptInFolderOfferBase, public LLIn
};
// ============================================================================
// LLCreateAcceptInFolder - create the destination floater and then callback
//
class LLCreateAcceptInFolder : public LLAcceptInFolderOfferBase
{
LOG_CLASS(LLCreateAcceptInFolder);
public:
typedef boost::signals2::signal<void (const LLUUID& idDestFolder)> folder_created_signal_t;
LLCreateAcceptInFolder(const LLUUID& idBaseFolder, const folder_created_signal_t::slot_type& cb);
/*
* Member functions (+ base class overrides)
*/
protected:
void onDestinationCreated(const LLUUID& idFolder) override;
/*
* Member variables
*/
protected:
folder_created_signal_t m_FolderCreatedSignal;
};
// ============================================================================
......@@ -2,7 +2,7 @@
<floater
legacy_header_height="18"
can_resize="true"
height="290"
height="315"
layout="topleft"
min_height="290"
min_width="280"
......@@ -52,11 +52,21 @@
name="text"
relative_width="1" />
</scroll_list>
<panel
class="panel_offer_invfolder"
height="23"
filename="panel_offer_invfolder.xml"
follows="bottom|left|right"
layout="topleft"
left="10"
name="panel_offer_invfolder"
right="-5"
top_pad="5" />
<text
type="string"
length="1"
follows="left|right|bottom"
height="16"
height="15"
layout="topleft"
left="10"
name="buy_text"
......
......@@ -2,7 +2,7 @@
<floater
legacy_header_height="18"
can_resize="true"
height="290"
height="315"
layout="topleft"
min_height="290"
min_width="280"
......@@ -78,6 +78,16 @@
name="text"
relative_width="1" />
</scroll_list>
<panel
class="panel_offer_invfolder"
height="23"
filename="panel_offer_invfolder.xml"
follows="bottom|left|right"
layout="topleft"
left="10"
name="panel_offer_invfolder"
right="-5"
top_pad="4" />
<text
type="string"
length="1"
......@@ -88,7 +98,7 @@
line_spacing.pixels="7"
name="buy_text"
text_color="White"
top_pad="5"
top_pad="6"
use_ellipses="true"
width="260"
word_wrap="true">
......