diff options
Diffstat (limited to 'indra/newview')
96 files changed, 12825 insertions, 8196 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f10db9330c..649d86aaa6 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -369,7 +369,9 @@ set(viewer_SOURCE_FILES llsearchhistory.cpp llselectmgr.cpp llsidepanelinventory.cpp - llsidepanelobjectinfo.cpp + llsidepanelinventorysubpanel.cpp + llsidepaneliteminfo.cpp + llsidepaneltaskinfo.cpp llsidetray.cpp llsidetraypanelcontainer.cpp llsky.cpp @@ -861,7 +863,9 @@ set(viewer_HEADER_FILES llsearchhistory.h llselectmgr.h llsidepanelinventory.h - llsidepanelobjectinfo.h + llsidepanelinventorysubpanel.h + llsidepaneliteminfo.h + llsidepaneltaskinfo.h llsidetray.h llsidetraypanelcontainer.h llsky.h @@ -1027,7 +1031,6 @@ set(viewer_HEADER_FILES macmain.h noise.h pipeline.h - randgauss.h VertexCache.h VorbisFramework.h ) diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings index dceaba9a43..879408d6e4 100644 --- a/indra/newview/English.lproj/InfoPlist.strings +++ b/indra/newview/English.lproj/InfoPlist.strings @@ -2,6 +2,6 @@ CFBundleName = "Second Life"; -CFBundleShortVersionString = "Second Life version 2.0.0.3256"; -CFBundleGetInfoString = "Second Life version 2.0.0.3256, Copyright 2004-2009 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version 2.0.0.200030"; +CFBundleGetInfoString = "Second Life version 2.0.0.200030, Copyright 2004-2009 Linden Research, Inc."; diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist index 7aec8a343d..38ebb22b84 100644 --- a/indra/newview/Info-SecondLife.plist +++ b/indra/newview/Info-SecondLife.plist @@ -32,7 +32,7 @@ </dict> </array> <key>CFBundleVersion</key> - <string>2.0.0.3256</string> + <string>2.0.0.200030</string> <key>CSResourcesFileMapped</key> <true/> </dict> diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 67ffe54b7e..3fc37aa3d5 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -178,7 +178,10 @@ void LLAvatarActions::startIM(const LLUUID& id) std::string name; gCacheName->getFullName(id, name); LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id); - LLIMFloater::show(session_id); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } make_ui_sound("UISndStartIM"); } @@ -191,7 +194,11 @@ void LLAvatarActions::startConference(const std::vector<LLUUID>& ids) { id_array.push_back(*it); } - gIMMgr->addSession("Friends Conference", IM_SESSION_CONFERENCE_START, ids[0], id_array); + LLUUID session_id = gIMMgr->addSession("Friends Conference", IM_SESSION_CONFERENCE_START, ids[0], id_array); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } make_ui_sound("UISndStartIM"); } diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index b56e8d1ec2..0ee3e78409 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -44,6 +44,7 @@ #include "llcachename.h" #include "llagentdata.h" +#include "llimfloater.h" #define MENU_ITEM_VIEW_PROFILE 0 #define MENU_ITEM_SEND_IM 1 @@ -354,7 +355,11 @@ void LLAvatarIconCtrl::onAvatarIconContextMenuItemClicked(const LLSD& userdata) name.append(" "); name.append(getLastName()); - gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id); + LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } } else if (level == "add") { diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index a17ba79078..e5cc2fce88 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -50,7 +50,6 @@ LLBottomTray::LLBottomTray(const LLSD&) mSpeakBtn(NULL), mNearbyChatBar(NULL), mToolbarStack(NULL) - { mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL); diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp index c4bfd71999..319cbf8209 100644 --- a/indra/newview/llcurrencyuimanager.cpp +++ b/indra/newview/llcurrencyuimanager.cpp @@ -76,8 +76,15 @@ public: bool mUserEnteredCurrencyBuy; // from website - bool mSiteCurrencyEstimated; - S32 mSiteCurrencyEstimatedCost; + + // pre-viewer 2.0, the server returned estimates as an + // integer US cents value, e.g., "1000" for $10.00 + // post-viewer 2.0, the server may also return estimates + // as a string with currency embedded, e.g., "10.00 Euros" + bool mUSDCurrencyEstimated; + S32 mUSDCurrencyEstimatedCost; + bool mLocalCurrencyEstimated; + std::string mLocalCurrencyEstimatedCost; std::string mSiteConfirm; bool mBought; @@ -101,6 +108,10 @@ public: void startCurrencyBuy(const std::string& password); void finishCurrencyBuy(); + + void clearEstimate(); + bool hasEstimate() const; + std::string getLocalEstimate() const; void startTransaction(TransactionType type, const char* method, LLXMLRPCValue params); @@ -126,12 +137,11 @@ LLCurrencyUIManager::Impl::Impl(LLPanel& dialog) mError(false), mUserCurrencyBuy(2000), // note, this is a default, real value set in llfloaterbuycurrency.cpp mUserEnteredCurrencyBuy(false), - mSiteCurrencyEstimated(false), - mSiteCurrencyEstimatedCost(0), mBought(false), mTransactionType(TransactionNone), mTransaction(0), mCurrencyChanged(false) { + clearEstimate(); } LLCurrencyUIManager::Impl::~Impl() @@ -141,14 +151,13 @@ LLCurrencyUIManager::Impl::~Impl() void LLCurrencyUIManager::Impl::updateCurrencyInfo() { - mSiteCurrencyEstimated = false; - mSiteCurrencyEstimatedCost = 0; + clearEstimate(); mBought = false; mCurrencyChanged = false; if (mUserCurrencyBuy == 0) { - mSiteCurrencyEstimated = true; + mLocalCurrencyEstimated = true; return; } @@ -185,9 +194,21 @@ void LLCurrencyUIManager::Impl::finishCurrencyInfo() } LLXMLRPCValue currency = result["currency"]; - mSiteCurrencyEstimated = true; - mSiteCurrencyEstimatedCost = currency["estimatedCost"].asInt(); - + + // old XML-RPC server: estimatedCost = value in US cents + mUSDCurrencyEstimated = currency["estimatedCost"].isValid(); + if (mUSDCurrencyEstimated) + { + mUSDCurrencyEstimatedCost = currency["estimatedCost"].asInt(); + } + + // newer XML-RPC server: estimatedLocalCost = local currency string + mLocalCurrencyEstimated = currency["estimatedLocalCost"].isValid(); + if (mLocalCurrencyEstimated) + { + mLocalCurrencyEstimatedCost = currency["estimatedLocalCost"].asString(); + } + S32 newCurrencyBuy = currency["currencyBuy"].asInt(); if (newCurrencyBuy != mUserCurrencyBuy) { @@ -200,17 +221,20 @@ void LLCurrencyUIManager::Impl::finishCurrencyInfo() void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password) { - mSiteCurrencyEstimated = false; - mSiteCurrencyEstimatedCost = 0; - mCurrencyChanged = false; - LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct(); keywordArgs.appendString("agentId", gAgent.getID().asString()); keywordArgs.appendString( "secureSessionId", gAgent.getSecureSessionID().asString()); keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy); - keywordArgs.appendInt("estimatedCost", mSiteCurrencyEstimatedCost); + if (mUSDCurrencyEstimated) + { + keywordArgs.appendInt("estimatedCost", mUSDCurrencyEstimatedCost); + } + if (mLocalCurrencyEstimated) + { + keywordArgs.appendString("estimatedLocalCost", mLocalCurrencyEstimatedCost); + } keywordArgs.appendString("confirm", mSiteConfirm); if (!password.empty()) { @@ -226,6 +250,9 @@ void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password) params.append(keywordArgs); startTransaction(TransactionBuy, "buyCurrency", params); + + clearEstimate(); + mCurrencyChanged = false; } void LLCurrencyUIManager::Impl::finishCurrencyBuy() @@ -270,6 +297,34 @@ void LLCurrencyUIManager::Impl::startTransaction(TransactionType type, clearError(); } +void LLCurrencyUIManager::Impl::clearEstimate() +{ + mUSDCurrencyEstimated = false; + mUSDCurrencyEstimatedCost = 0; + mLocalCurrencyEstimated = false; + mLocalCurrencyEstimatedCost = "0"; +} + +bool LLCurrencyUIManager::Impl::hasEstimate() const +{ + return (mUSDCurrencyEstimated || mLocalCurrencyEstimated); +} + +std::string LLCurrencyUIManager::Impl::getLocalEstimate() const +{ + if (mLocalCurrencyEstimated) + { + // we have the new-style local currency string + return mLocalCurrencyEstimatedCost; + } + if (mUSDCurrencyEstimated) + { + // we have the old-style USD-specific value + return "US$ " + llformat("%#.2f", mUSDCurrencyEstimatedCost / 100.0); + } + return ""; +} + bool LLCurrencyUIManager::Impl::checkTransaction() { if (!mTransaction) @@ -342,8 +397,8 @@ void LLCurrencyUIManager::Impl::currencyKey(S32 value) mUserCurrencyBuy = value; - if (mSiteCurrencyEstimated) { - mSiteCurrencyEstimated = false; + if (hasEstimate()) { + clearEstimate(); //cannot just simply refresh the whole UI, as the edit field will // get reset and the cursor will change... @@ -406,8 +461,8 @@ void LLCurrencyUIManager::Impl::updateUI() } } - mPanel.childSetTextArg("currency_est", "[LOCALAMOUNT]", "US$ " + llformat("%#.2f", mSiteCurrencyEstimatedCost / 100.0)); - mPanel.childSetVisible("currency_est", mSiteCurrencyEstimated && mUserCurrencyBuy > 0); + mPanel.childSetTextArg("currency_est", "[LOCALAMOUNT]", getLocalEstimate()); + mPanel.childSetVisible("currency_est", hasEstimate() && mUserCurrencyBuy > 0); if (mPanel.childIsEnabled("buy_btn") ||mPanel.childIsVisible("currency_est") @@ -448,18 +503,32 @@ void LLCurrencyUIManager::setZeroMessage(const std::string& message) impl.mZeroMessage = message; } -void LLCurrencyUIManager::setEstimate(int amount) +void LLCurrencyUIManager::setUSDEstimate(int amount) +{ + impl.mUSDCurrencyEstimatedCost = amount; + impl.mUSDCurrencyEstimated = true; + impl.updateUI(); + + impl.mCurrencyChanged = false; +} + +int LLCurrencyUIManager::getUSDEstimate() +{ + return impl.mUSDCurrencyEstimated ? impl.mUSDCurrencyEstimatedCost : 0; +} + +void LLCurrencyUIManager::setLocalEstimate(const std::string &amount) { - impl.mSiteCurrencyEstimatedCost = amount; - impl.mSiteCurrencyEstimated = true; + impl.mLocalCurrencyEstimatedCost = amount; + impl.mLocalCurrencyEstimated = true; impl.updateUI(); impl.mCurrencyChanged = false; } -int LLCurrencyUIManager::getEstimate() +std::string LLCurrencyUIManager::getLocalEstimate() const { - return impl.mSiteCurrencyEstimated ? impl.mSiteCurrencyEstimatedCost : 0; + return impl.getLocalEstimate(); } void LLCurrencyUIManager::prepare() @@ -490,7 +559,7 @@ void LLCurrencyUIManager::buy(const std::string& buy_msg) LLUIString msg = buy_msg; msg.setArg("[LINDENS]", llformat("%d", impl.mUserCurrencyBuy)); - msg.setArg("[LOCALAMOUNT]", "US$ " + llformat("%#.2f", impl.mSiteCurrencyEstimatedCost / 100.0)); + msg.setArg("[LOCALAMOUNT]", getLocalEstimate()); LLConfirmationManager::confirm(impl.mSiteConfirm, msg, impl, @@ -511,7 +580,7 @@ bool LLCurrencyUIManager::canCancel() bool LLCurrencyUIManager::canBuy() { return impl.mTransactionType == Impl::TransactionNone - && impl.mSiteCurrencyEstimated + && impl.hasEstimate() && impl.mUserCurrencyBuy > 0; } diff --git a/indra/newview/llcurrencyuimanager.h b/indra/newview/llcurrencyuimanager.h index 93427aed7f..dfe027098d 100644 --- a/indra/newview/llcurrencyuimanager.h +++ b/indra/newview/llcurrencyuimanager.h @@ -57,11 +57,16 @@ public: void setZeroMessage(const std::string& message); // sets the gray message to show when zero - void setEstimate(int); - int getEstimate(); + void setUSDEstimate(int); // deprecated in 2.0 + int getUSDEstimate(); // deprecated in 2.0 // the amount in US$ * 100 (in otherwords, in cents) // use set when you get this information from elsewhere + void setLocalEstimate(const std::string &local_est); + std::string getLocalEstimate() const; + // the estimated cost in the user's local currency + // for example, "US$ 10.00" or "10.00 Euros" + void prepare(); // call once after dialog is built, from postBuild() void updateUI(bool show = true); diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 36f0315790..467796b4a3 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -685,7 +685,14 @@ void LLFloaterBuyLandUI::finishWebSiteInfo() mSiteLandUseAction = landUse["action"].asString(); LLXMLRPCValue currency = result["currency"]; - mCurrency.setEstimate(currency["estimatedCost"].asInt()); + if (currency["estimatedCost"].isValid()) + { + mCurrency.setUSDEstimate(currency["estimatedCost"].asInt()); + } + if (currency["estimatedLocalCost"].isValid()) + { + mCurrency.setLocalEstimate(currency["estimatedLocalCost"].asString()); + } mSiteConfirm = result["confirm"].asString(); } @@ -733,7 +740,8 @@ void LLFloaterBuyLandUI::runWebSitePrep(const std::string& password) keywordArgs.appendInt("billableArea", mIsForGroup ? 0 : mParcelBillableArea); keywordArgs.appendInt("currencyBuy", mCurrency.getAmount()); - keywordArgs.appendInt("estimatedCost", mCurrency.getEstimate()); + keywordArgs.appendInt("estimatedCost", mCurrency.getUSDEstimate()); + keywordArgs.appendString("estimatedLocalCost", mCurrency.getLocalEstimate()); keywordArgs.appendString("confirm", mSiteConfirm); if (!password.empty()) { @@ -1217,7 +1225,7 @@ void LLFloaterBuyLandUI::refreshUI() childSetText("currency_reason", getString("not_enough_lindens", string_args)); - childSetTextArg("currency_est", "[AMOUNT2]", llformat("%#.2f", mCurrency.getEstimate() / 100.0)); + childSetTextArg("currency_est", "[LOCAL_AMOUNT]", mCurrency.getLocalEstimate()); } if (willHaveEnough) @@ -1297,7 +1305,7 @@ void LLFloaterBuyLandUI::startBuyPreConfirm() { LLStringUtil::format_map_t string_args; string_args["[AMOUNT]"] = llformat("%d", mCurrency.getAmount()); - string_args["[AMOUNT2]"] = llformat("%#.2f", mCurrency.getEstimate() / 100.0); + string_args["[LOCAL_AMOUNT]"] = mCurrency.getLocalEstimate(); action += getString("buy_for_US", string_args); } diff --git a/indra/newview/llfloaterinspect.cpp b/indra/newview/llfloaterinspect.cpp index e26937e93f..13ca7638c5 100644 --- a/indra/newview/llfloaterinspect.cpp +++ b/indra/newview/llfloaterinspect.cpp @@ -88,32 +88,7 @@ LLFloaterInspect::~LLFloaterInspect(void) } //sInstance = NULL; } -/* -BOOL LLFloaterInspect::isVisible() -{ - return (!!sInstance); -}*/ -/* -void LLFloaterInspect::show(void* ignored) -{ - // setForceSelection ensures that the pie menu does not deselect things when it - // looses the focus (this can happen with "select own objects only" enabled - // VWR-1471 - BOOL forcesel = LLSelectMgr::getInstance()->setForceSelection(TRUE); - - if (!sInstance) // first use - { - sInstance = new LLFloaterInspect; - } - sInstance->openFloater(); - LLToolMgr::getInstance()->setTransientTool(LLToolCompInspect::getInstance()); - LLSelectMgr::getInstance()->setForceSelection(forcesel); // restore previouis value - - sInstance->mObjectSelection = LLSelectMgr::getInstance()->getSelection(); - sInstance->refresh(); -} -*/ void LLFloaterInspect::onOpen(const LLSD& key) { BOOL forcesel = LLSelectMgr::getInstance()->setForceSelection(TRUE); diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp index 2fe21f28de..663bd232f7 100644 --- a/indra/newview/llfloateruipreview.cpp +++ b/indra/newview/llfloateruipreview.cpp @@ -670,6 +670,15 @@ void LLFloaterUIPreview::refreshList() } } + found = TRUE; + while(found) // for every sidepanel file that matches the pattern + { + if((found = gDirUtilp->getNextFileInDir(getLocalizedDirectory(), "sidepanel_*.xml", name, FALSE))) // get next file matching pattern + { + addFloaterEntry(name.c_str()); // and add it to the list (file name only; localization code takes care of rest of path) + } + } + if(!mFileList->isEmpty()) // if there were any matching files, just select the first one (so we don't have to worry about disabling buttons when no entry is selected) { mFileList->selectFirstItem(); diff --git a/indra/newview/llfloatervoicedevicesettings.cpp b/indra/newview/llfloatervoicedevicesettings.cpp index bbeb287171..43024a4bd0 100644 --- a/indra/newview/llfloatervoicedevicesettings.cpp +++ b/indra/newview/llfloatervoicedevicesettings.cpp @@ -95,6 +95,9 @@ void LLPanelVoiceDeviceSettings::handleVisibilityChange ( BOOL new_visibility ) else { cleanup(); + // when closing this window, turn of visiblity control so that + // next time preferences is opened we don't suspend voice + gSavedSettings.setBOOL("ShowDeviceSettings", FALSE); } } void LLPanelVoiceDeviceSettings::draw() diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index c46eedbef2..e60bde9fd8 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -43,6 +43,7 @@ #include "llimview.h" // for gIMMgr #include "llsidetray.h" #include "llstatusbar.h" // can_afford_transaction() +#include "llimfloater.h" // // Globals @@ -279,10 +280,14 @@ void LLGroupActions::startChat(const LLUUID& group_id) LLGroupData group_data; if (gAgent.getGroupData(group_id, group_data)) { - gIMMgr->addSession( + LLUUID session_id = gIMMgr->addSession( group_data.mName, IM_SESSION_GROUP_START, group_id); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } make_ui_sound("UISndStartIM"); } else diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index 2e2b2d5101..010ed23918 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -183,6 +183,11 @@ void LLGroupList::addNewItem(const LLUUID& id, const std::string& name, const LL item->childSetVisible("info_btn", false); item->setGroupIconVisible(mShowIcons); + if (id.isNull()) + { + item->childSetVisible("profile_btn", false); + } + addItem(item, id, pos); // setCommentVisible(false); diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 85863ed85b..a634a1b0fd 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -115,7 +115,7 @@ void LLIMFloater::onClose(bool app_quitting) /* static */ void LLIMFloater::newIMCallback(const LLSD& data){ - if (data["num_unread"].asInteger() > 0) + if (data["num_unread"].asInteger() > 0 || data["from_id"].asUUID().isNull()) { LLUUID session_id = data["session_id"].asUUID(); @@ -235,7 +235,7 @@ BOOL LLIMFloater::postBuild() std::string session_name(LLIMModel::instance().getName(mSessionID)); - mInputEditor->setLabel(mInputEditor->getLabel() + " " + session_name); + mInputEditor->setLabel(LLTrans::getString("IM_to_label") + " " + session_name); LLStringUtil::toUpper(session_name); setTitle(session_name); @@ -498,7 +498,8 @@ void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void* // Allow enabling the LLIMFloater input editor only if session can accept text LLIMModel::LLIMSession* im_session = LLIMModel::instance().findIMSession(self->mSessionID); - if( im_session && im_session->mTextIMPossible ) + //TODO: While disabled lllineeditor can receive focus we need to check if it is enabled (EK) + if( im_session && im_session->mTextIMPossible && !self->mInputEditor->getEnabled()) { //in disconnected state IM input editor should be disabled self->mInputEditor->setEnabled(!gDisconnected); @@ -588,6 +589,32 @@ void LLIMFloater::processIMTyping(const LLIMInfo* im_info, BOOL typing) } } +void LLIMFloater::processAgentListUpdates(const LLSD& body) +{ + if ( !body.isMap() ) return; + + if ( body.has("agent_updates") && body["agent_updates"].isMap() ) + { + LLSD agent_data = body["agent_updates"].get(gAgentID.asString()); + if (agent_data.isMap() && agent_data.has("info")) + { + LLSD agent_info = agent_data["info"]; + + if (agent_info.has("mutes")) + { + BOOL moderator_muted_text = agent_info["mutes"]["text"].asBoolean(); + mInputEditor->setEnabled(!moderator_muted_text); + std::string label; + if (moderator_muted_text) + label = LLTrans::getString("IM_muted_text_label"); + else + label = LLTrans::getString("IM_to_label") + " " + LLIMModel::instance().getName(mSessionID); + mInputEditor->setLabel(label); + } + } + } +} + void LLIMFloater::processSessionUpdate(const LLSD& session_update) { // *TODO : verify following code when moderated mode will be implemented diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h index f5edb3188a..065441b188 100644 --- a/indra/newview/llimfloater.h +++ b/indra/newview/llimfloater.h @@ -90,6 +90,7 @@ public: void onVisibilityChange(const LLSD& new_visibility); void processIMTyping(const LLIMInfo* im_info, BOOL typing); + void processAgentListUpdates(const LLSD& body); void processSessionUpdate(const LLSD& session_update); BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 7399f1e1b3..0b8b5935f8 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -321,6 +321,9 @@ void LLFloaterIMPanel::draw() // hide/show start call and end call buttons LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionUUID); + if (!voice_channel) + return; + childSetVisible("end_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() >= LLVoiceChannel::STATE_CALL_STARTED); childSetVisible("start_call_btn", LLVoiceClient::voiceEnabled() && voice_channel->getState() < LLVoiceChannel::STATE_CALL_STARTED); childSetEnabled("start_call_btn", enable_connect); @@ -770,10 +773,13 @@ void LLFloaterIMPanel::onVisibilityChange(const LLSD& new_visibility) } LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(mSessionUUID); - if (new_visibility.asBoolean() && voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED) - LLFloaterReg::showInstance("voice_call", mSessionUUID); - else - LLFloaterReg::hideInstance("voice_call", mSessionUUID); + if (voice_channel && voice_channel->getState() == LLVoiceChannel::STATE_CONNECTED) + { + if (new_visibility.asBoolean()) + LLFloaterReg::showInstance("voice_call", mSessionUUID); + else + LLFloaterReg::hideInstance("voice_call", mSessionUUID); + } } void LLFloaterIMPanel::sendMsg() diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 7e8701bf21..fdf119fbee 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -134,7 +134,6 @@ void LLIMModel::setActiveSessionID(const LLUUID& session_id) LLIMModel::LLIMModel() { addNewMsgCallback(LLIMFloater::newIMCallback); - addNoUnreadMsgsCallback(LLIMFloater::newIMCallback); addNewMsgCallback(toast_callback); } @@ -440,7 +439,8 @@ bool LLIMModel::addMessage(const LLUUID& session_id, const std::string& from, co addToHistory(session_id, from, from_id, utf8_text); if (log2file) logToFile(session_id, from, from_id, utf8_text); - session->mNumUnread++; + //we do not count system messages + if (from_id.notNull()) session->mNumUnread++; // notify listeners LLSD arg; @@ -1192,10 +1192,14 @@ void LLIncomingCallDialog::processCallResponse(S32 response) } else { - gIMMgr->addSession( + LLUUID session_id = gIMMgr->addSession( mPayload["session_name"].asString(), type, session_id); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } std::string url = gAgent.getRegion()->getCapability( "ChatSessionRequest"); @@ -1279,10 +1283,14 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response) } else { - gIMMgr->addSession( + LLUUID session_id = gIMMgr->addSession( payload["session_name"].asString(), type, session_id); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } std::string url = gAgent.getRegion()->getCapability( "ChatSessionRequest"); @@ -1350,13 +1358,6 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response) LLIMMgr::LLIMMgr() : mIMReceived(FALSE) { - static bool registered_dialog = false; - if (!registered_dialog) - { - LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>); - registered_dialog = true; - } - mPendingInvitations = LLSD::emptyMap(); mPendingAgentListUpdates = LLSD::emptyMap(); } @@ -1555,6 +1556,10 @@ LLUUID LLIMMgr::addP2PSession(const std::string& name, const std::string& caller_uri) { LLUUID session_id = addSession(name, IM_NOTHING_SPECIAL, other_participant_id); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); if (speaker_mgr) @@ -1848,6 +1853,29 @@ void LLIMMgr::clearPendingInvitation(const LLUUID& session_id) } } +void LLIMMgr::processAgentListUpdates(const LLUUID& session_id, const LLSD& body) +{ + LLIMFloater* im_floater = LLIMFloater::findInstance(session_id); + if ( im_floater ) + { + im_floater->processAgentListUpdates(body); + } + LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); + if (speaker_mgr) + { + speaker_mgr->updateSpeakers(body); + } + else + { + //we don't have a speaker manager yet..something went wrong + //we are probably receiving an update here before + //a start or an acceptance of an invitation. Race condition. + gIMMgr->addPendingAgentListUpdates( + session_id, + body); + } +} + LLSD LLIMMgr::getPendingAgentListUpdates(const LLUUID& session_id) { if ( mPendingAgentListUpdates.has(session_id.asString()) ) @@ -2232,20 +2260,7 @@ public: const LLSD& input) const { const LLUUID& session_id = input["body"]["session_id"].asUUID(); - LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id); - if (speaker_mgr) - { - speaker_mgr->updateSpeakers(input["body"]); - } - else - { - //we don't have a speaker manager yet..something went wrong - //we are probably receiving an update here before - //a start or an acceptance of an invitation. Race condition. - gIMMgr->addPendingAgentListUpdates( - input["body"]["session_id"].asUUID(), - input["body"]); - } + gIMMgr->processAgentListUpdates(session_id, input["body"]); } }; diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index f986d9dcdb..bd55bd2c30 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -66,7 +66,10 @@ public: EInstantMessage mType; LLUUID mOtherParticipantID; std::vector<LLUUID> mInitialTargetIDs; + + //does NOT include system messages S32 mNumUnread; + std::list<LLSD> mMsgs; LLVoiceChannel* mVoiceChannel; @@ -315,6 +318,7 @@ public: void clearPendingInvitation(const LLUUID& session_id); + void processAgentListUpdates(const LLUUID& session_id, const LLSD& body); LLSD getPendingAgentListUpdates(const LLUUID& session_id); void addPendingAgentListUpdates( const LLUUID& sessioN_id, diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 9989a3b473..8dc7833f6a 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -47,6 +47,7 @@ #include "llstartup.h" #include "llviewermenu.h" #include "llvoiceclient.h" +#include "llviewerobjectlist.h" // Linden libraries #include "llfloater.h" @@ -113,6 +114,7 @@ private: void onClickFindOnMap(); bool onVisibleFindOnMap(); bool onVisibleFreezeEject(); + bool onVisibleZoomIn(); void onClickMuteVolume(); void onVolumeChange(const LLSD& data); @@ -204,6 +206,8 @@ LLInspectAvatar::LLInspectAvatar(const LLSD& sd) mVisibleCallbackRegistrar.add("InspectAvatar.VisibleFindOnMap", boost::bind(&LLInspectAvatar::onVisibleFindOnMap, this)); mVisibleCallbackRegistrar.add("InspectAvatar.VisibleFreezeEject", boost::bind(&LLInspectAvatar::onVisibleFreezeEject, this)); + mVisibleCallbackRegistrar.add("InspectAvatar.VisibleZoomIn", + boost::bind(&LLInspectAvatar::onVisibleZoomIn, this)); // can't make the properties request until the widgets are constructed // as it might return immediately, so do it in postBuild. @@ -479,6 +483,11 @@ bool LLInspectAvatar::onVisibleFreezeEject() return enable_freeze_eject( LLSD(mAvatarID) ); } +bool LLInspectAvatar::onVisibleZoomIn() +{ + return gObjectList.findObject(mAvatarID); +} + void LLInspectAvatar::onClickIM() { LLAvatarActions::startIM(mAvatarID); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index b9a25d5dc7..84e0f58c4b 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1,5156 +1,5208 @@ -/** - * @file llinventorybridge.cpp - * @brief Implementation of the Inventory-Folder-View-Bridge classes. - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include <utility> // for std::pair<> - -#include "llfloaterinventory.h" -#include "llinventorybridge.h" - -#include "message.h" - -#include "llagent.h" -#include "llagentwearables.h" -#include "llcallingcard.h" -#include "llcheckboxctrl.h" // for radio buttons -#include "llfloaterreg.h" -#include "llradiogroup.h" -#include "llspinctrl.h" -#include "lltextbox.h" -#include "llui.h" - -#include "llviewercontrol.h" -#include "llfirstuse.h" -#include "llfoldertype.h" -#include "llfloaterchat.h" -#include "llfloatercustomize.h" -#include "llfloaterproperties.h" -#include "llfloaterworldmap.h" -#include "llfocusmgr.h" -#include "llfolderview.h" -#include "llfriendcard.h" -#include "llavataractions.h" -#include "llgesturemgr.h" -#include "lliconctrl.h" -#include "llinventoryfunctions.h" -#include "llinventorymodel.h" -#include "llinventorypanel.h" -#include "llinventoryclipboard.h" -#include "lllineeditor.h" -#include "llmenugl.h" -#include "llpreviewanim.h" -#include "llpreviewgesture.h" -#include "llpreviewnotecard.h" -#include "llpreviewscript.h" -#include "llpreviewsound.h" -#include "llpreviewtexture.h" -#include "llresmgr.h" -#include "llscrollcontainer.h" -#include "llimview.h" -#include "lltooldraganddrop.h" -#include "llviewerfoldertype.h" -#include "llviewertexturelist.h" -#include "llviewerinventory.h" -#include "llviewerobjectlist.h" -#include "llviewerwindow.h" -#include "llvoavatar.h" -#include "llwearable.h" -#include "llwearablelist.h" -#include "llviewerassettype.h" -#include "llviewermessage.h" -#include "llviewerregion.h" -#include "llvoavatarself.h" -#include "lltabcontainer.h" -#include "lluictrlfactory.h" -#include "llselectmgr.h" -#include "llsidetray.h" -#include "llfloateropenobject.h" -#include "lltrans.h" -#include "llappearancemgr.h" - -using namespace LLOldEvents; - -// Helpers -// bug in busy count inc/dec right now, logic is complex... do we really need it? -void inc_busy_count() -{ -// gViewerWindow->getWindow()->incBusyCount(); -// check balance of these calls if this code is changed to ever actually -// *do* something! -} -void dec_busy_count() -{ -// gViewerWindow->getWindow()->decBusyCount(); -// check balance of these calls if this code is changed to ever actually -// *do* something! -} - -// Function declarations -void wear_add_inventory_item_on_avatar(LLInventoryItem* item); -void remove_inventory_category_from_avatar(LLInventoryCategory* category); -void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id); -bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*); -bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response); - -std::string ICON_NAME[ICON_NAME_COUNT] = -{ - "Inv_Texture", - "Inv_Sound", - "Inv_CallingCard", - "Inv_CallingCard", - "Inv_Landmark", - "Inv_Landmark", - "Inv_Script", - "Inv_Clothing", - "Inv_Object", - "Inv_Object", - "Inv_Notecard", - "Inv_Skin", - "Inv_Snapshot", - - "Inv_BodyShape", - "Inv_Skin", - "Inv_Hair", - "Inv_Eye", - "Inv_Shirt", - "Inv_Pants", - "Inv_Shoe", - "Inv_Socks", - "Inv_Jacket", - "Inv_Gloves", - "Inv_Undershirt", - "Inv_Underpants", - "Inv_Skirt", - "Inv_Alpha", - "Inv_Tattoo", - - "Inv_Animation", - "Inv_Gesture", - - "inv_item_linkitem.tga", - "inv_item_linkfolder.tga" -}; - - -// +=================================================+ -// | LLInventoryPanelObserver | -// +=================================================+ -void LLInventoryPanelObserver::changed(U32 mask) -{ - mIP->modelChanged(mask); -} - - -// +=================================================+ -// | LLInvFVBridge | -// +=================================================+ - -LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) : -mUUID(uuid), mInvType(LLInventoryType::IT_NONE) -{ - mInventoryPanel = inventory->getHandle(); -} - -const std::string& LLInvFVBridge::getName() const -{ - LLInventoryObject* obj = getInventoryObject(); - if(obj) - { - return obj->getName(); - } - return LLStringUtil::null; -} - -const std::string& LLInvFVBridge::getDisplayName() const -{ - return getName(); -} - -// Folders have full perms -PermissionMask LLInvFVBridge::getPermissionMask() const -{ - - return PERM_ALL; -} - -// virtual -LLFolderType::EType LLInvFVBridge::getPreferredType() const -{ - return LLFolderType::FT_NONE; -} - - -// Folders don't have creation dates. -time_t LLInvFVBridge::getCreationDate() const -{ - return 0; -} - -// Can be destoryed (or moved to trash) -BOOL LLInvFVBridge::isItemRemovable() -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - if(model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) - { - return TRUE; - } - return FALSE; -} - -// Sends an update to all link items that point to the base item. -void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string& new_name) -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - - LLInventoryItem* itemp = model->getItem(mUUID); - if (!itemp) return; - - if (itemp->getIsLinkType()) - { - return; - } - - LLInventoryModel::item_array_t item_array = model->collectLinkedItems(item_id); - for (LLInventoryModel::item_array_t::iterator iter = item_array.begin(); - iter != item_array.end(); - iter++) - { - LLViewerInventoryItem *linked_item = (*iter); - if (linked_item->getUUID() == item_id) continue; - - LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(linked_item); - new_item->rename(new_name); - new_item->updateServer(FALSE); - model->updateItem(new_item); - // model->addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID()); - } - model->notifyObservers(); -} - -// Can be moved to another folder -BOOL LLInvFVBridge::isItemMovable() const -{ - return TRUE; -} - -/*virtual*/ -/** - * @brief Adds this item into clipboard storage - */ -void LLInvFVBridge::cutToClipboard() -{ - if(isItemMovable()) - { - LLInventoryClipboard::instance().cut(mUUID); - } -} -// *TODO: make sure this does the right thing -void LLInvFVBridge::showProperties() -{ - LLSD key; - key["id"] = mUUID; - LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); - - // LLFloaterReg::showInstance("properties", mUUID); -} - -void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch) -{ - // Deactivate gestures when moving them into Trash - LLInvFVBridge* bridge; - LLInventoryModel* model = getInventoryModel(); - LLViewerInventoryItem* item = NULL; - LLViewerInventoryCategory* cat = NULL; - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - 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()); - if (item) - { - if(LLAssetType::AT_GESTURE == item->getType()) - { - LLGestureManager::instance().deactivateGesture(item->getUUID()); - } - } - } - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); - if (cat) - { - gInventory.collectDescendents( cat->getUUID(), descendent_categories, descendent_items, FALSE ); - for (j=0; j<descendent_items.count(); j++) - { - if(LLAssetType::AT_GESTURE == descendent_items[j]->getType()) - { - LLGestureManager::instance().deactivateGesture(descendent_items[j]->getUUID()); - } - } - } - } - removeBatchNoCheck(batch); -} - -void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch) -{ - // this method moves a bunch of items and folders to the trash. As - // per design guidelines for the inventory model, the message is - // built and the accounting is performed first. After all of that, - // we call LLInventoryModel::moveObject() to move everything - // around. - LLInvFVBridge* bridge; - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLMessageSystem* msg = gMessageSystem; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - LLViewerInventoryItem* item = NULL; - LLViewerInventoryCategory* cat = NULL; - std::vector<LLUUID> move_ids; - LLInventoryModel::update_map_t update; - bool start_new_message = true; - S32 count = batch.count(); - S32 i; - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID()); - if(item) - { - if(item->getParentUUID() == trash_id) continue; - move_ids.push_back(item->getUUID()); - LLPreview::hide(item->getUUID()); - --update[item->getParentUUID()]; - ++update[trash_id]; - if(start_new_message) - { - start_new_message = false; - msg->newMessageFast(_PREHASH_MoveInventoryItem); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addBOOLFast(_PREHASH_Stamp, TRUE); - } - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_ItemID, item->getUUID()); - msg->addUUIDFast(_PREHASH_FolderID, trash_id); - msg->addString("NewName", NULL); - if(msg->isSendFullFast(_PREHASH_InventoryData)) - { - start_new_message = true; - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - update.clear(); - } - } - } - if(!start_new_message) - { - start_new_message = true; - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - update.clear(); - } - for(i = 0; i < count; ++i) - { - bridge = (LLInvFVBridge*)(batch.get(i)); - if(!bridge || !bridge->isItemRemovable()) continue; - cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID()); - if(cat) - { - if(cat->getParentUUID() == trash_id) continue; - move_ids.push_back(cat->getUUID()); - --update[cat->getParentUUID()]; - ++update[trash_id]; - if(start_new_message) - { - start_new_message = false; - msg->newMessageFast(_PREHASH_MoveInventoryFolder); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addBOOL("Stamp", TRUE); - } - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID()); - msg->addUUIDFast(_PREHASH_ParentID, trash_id); - if(msg->isSendFullFast(_PREHASH_InventoryData)) - { - start_new_message = true; - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - update.clear(); - } - } - } - if(!start_new_message) - { - gAgent.sendReliableMessage(); - gInventory.accountForUpdate(update); - } - - // move everything. - std::vector<LLUUID>::iterator it = move_ids.begin(); - std::vector<LLUUID>::iterator end = move_ids.end(); - for(; it != end; ++it) - { - gInventory.moveObject((*it), trash_id); - } - - // notify inventory observers. - model->notifyObservers(); -} - -BOOL LLInvFVBridge::isClipboardPasteable() const -{ - if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) - { - return FALSE; - } - LLInventoryModel* model = getInventoryModel(); - if (!model) - { - return FALSE; - } - - const LLUUID &agent_id = gAgent.getID(); - - LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - for(S32 i = 0; i < count; i++) - { - const LLUUID &item_id = objects.get(i); - - // Can't paste folders - const LLInventoryCategory *cat = model->getCategory(item_id); - if (cat) - { - return FALSE; - } - - const LLInventoryItem *item = model->getItem(item_id); - if (item) - { - if (!item->getPermissions().allowCopyBy(agent_id)) - { - return FALSE; - } - } - } - return TRUE; -} - -BOOL LLInvFVBridge::isClipboardPasteableAsLink() const -{ - if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory()) - { - return FALSE; - } - const LLInventoryModel* model = getInventoryModel(); - if (!model) - { - return FALSE; - } - - LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - for(S32 i = 0; i < count; i++) - { - const LLInventoryItem *item = model->getItem(objects.get(i)); - if (item) - { - if (!LLAssetType::lookupCanLink(item->getActualType())) - { - return FALSE; - } - } - const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i)); - if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())) - { - return FALSE; - } - } - return TRUE; -} - -void hide_context_entries(LLMenuGL& menu, - const std::vector<std::string> &entries_to_show, - const std::vector<std::string> &disabled_entries) -{ - const LLView::child_list_t *list = menu.getChildList(); - - LLView::child_list_t::const_iterator itor; - for (itor = list->begin(); itor != list->end(); ++itor) - { - std::string name = (*itor)->getName(); - - // descend into split menus: - LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(*itor); - if ((name == "More") && branchp) - { - hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries); - } - - - bool found = false; - std::vector<std::string>::const_iterator itor2; - for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2) - { - if (*itor2 == name) - { - found = true; - } - } - if (!found) - { - (*itor)->setVisible(FALSE); - } - else - { - for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2) - { - if (*itor2 == name) - { - (*itor)->setEnabled(FALSE); - } - } - } - } -} - -// Helper for commonly-used entries -void LLInvFVBridge::getClipboardEntries(bool show_asset_id, - std::vector<std::string> &items, - std::vector<std::string> &disabled_items, U32 flags) -{ - items.push_back(std::string("Rename")); - if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Rename")); - } - - if (show_asset_id) - { - items.push_back(std::string("Copy Asset UUID")); - if ( (! ( isItemPermissive() || gAgent.isGodlike() ) ) - || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Copy Asset UUID")); - } - } - - items.push_back(std::string("Copy Separator")); - - items.push_back(std::string("Copy")); - if (!isItemCopyable()) - { - disabled_items.push_back(std::string("Copy")); - } - - items.push_back(std::string("Paste")); - if (!isClipboardPasteable() || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Paste")); - } - - items.push_back(std::string("Paste As Link")); - if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Paste As Link")); - } - items.push_back(std::string("Paste Separator")); - - items.push_back(std::string("Delete")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Delete")); - } - - // If multiple items are selected, disable properties (if it exists). - if ((flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Properties")); - } -} - -void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - if(isInTrash()) - { - items.push_back(std::string("PurgeItem")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("PurgeItem")); - } - items.push_back(std::string("RestoreItem")); - } - else - { - items.push_back(std::string("Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - hide_context_entries(menu, items, disabled_items); -} - -// *TODO: remove this -BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const -{ - BOOL rv = FALSE; - - const LLInventoryObject* obj = getInventoryObject(); - - if(obj) - { - *type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType()); - if(*type == DAD_NONE) - { - return FALSE; - } - - *id = obj->getUUID(); - //object_ids.put(obj->getUUID()); - - if (*type == DAD_CATEGORY) - { - gInventory.startBackgroundFetch(obj->getUUID()); - } - - rv = TRUE; - } - - return rv; -} - -LLInventoryObject* LLInvFVBridge::getInventoryObject() const -{ - LLInventoryObject* obj = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - obj = (LLInventoryObject*)model->getObject(mUUID); - } - return obj; -} - -LLInventoryModel* LLInvFVBridge::getInventoryModel() const -{ - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); - return panel ? panel->getModel() : NULL; -} - -BOOL LLInvFVBridge::isInTrash() const -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - return model->isObjectDescendentOf(mUUID, trash_id); -} - -BOOL LLInvFVBridge::isLinkedObjectInTrash() const -{ - if (isInTrash()) return TRUE; - - const LLInventoryObject *obj = getInventoryObject(); - if (obj && obj->getIsLinkType()) - { - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id); - } - return FALSE; -} - -BOOL LLInvFVBridge::isAgentInventory() const -{ - const LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - if(gInventory.getRootFolderID() == mUUID) return TRUE; - return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); -} - -BOOL LLInvFVBridge::isCOFFolder() const -{ - const LLInventoryModel* model = getInventoryModel(); - if(!model) return TRUE; - const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id)) - { - return TRUE; - } - return FALSE; -} - -BOOL LLInvFVBridge::isItemPermissive() const -{ - return FALSE; -} - -// static -void LLInvFVBridge::changeItemParent(LLInventoryModel* model, - LLViewerInventoryItem* item, - const LLUUID& new_parent, - BOOL restamp) -{ - if(item->getParentUUID() != new_parent) - { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1); - update.push_back(new_folder); - gInventory.accountForUpdate(update); - - LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); - new_item->setParent(new_parent); - new_item->updateParentOnServer(restamp); - model->updateItem(new_item); - model->notifyObservers(); - } -} - -// static -void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model, - LLViewerInventoryCategory* cat, - const LLUUID& new_parent, - BOOL restamp) -{ - if(cat->getParentUUID() != new_parent) - { - LLInventoryModel::update_list_t update; - LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1); - update.push_back(old_folder); - LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1); - update.push_back(new_folder); - gInventory.accountForUpdate(update); - - LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat); - new_cat->setParent(new_parent); - new_cat->updateParentOnServer(restamp); - model->updateCategory(new_cat); - model->notifyObservers(); - } -} - - -const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type) -{ - const std::string rv= LLInventoryType::lookup(inv_type); - if(rv.empty()) - { - return std::string("<invalid>"); - } - return rv; -} - -LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type, - LLAssetType::EType actual_asset_type, - LLInventoryType::EType inv_type, - LLInventoryPanel* inventory, - const LLUUID& uuid, - U32 flags) -{ - LLInvFVBridge* new_listener = NULL; - switch(asset_type) - { - case LLAssetType::AT_TEXTURE: - if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLTextureBridge(inventory, uuid, inv_type); - break; - - case LLAssetType::AT_SOUND: - if(!(inv_type == LLInventoryType::IT_SOUND)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLSoundBridge(inventory, uuid); - break; - - case LLAssetType::AT_LANDMARK: - if(!(inv_type == LLInventoryType::IT_LANDMARK)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLLandmarkBridge(inventory, uuid, flags); - break; - - case LLAssetType::AT_CALLINGCARD: - if(!(inv_type == LLInventoryType::IT_CALLINGCARD)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLCallingCardBridge(inventory, uuid); - break; - - case LLAssetType::AT_SCRIPT: - if(!(inv_type == LLInventoryType::IT_LSL)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLScriptBridge(inventory, uuid); - break; - - case LLAssetType::AT_OBJECT: - if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags); - break; - - case LLAssetType::AT_NOTECARD: - if(!(inv_type == LLInventoryType::IT_NOTECARD)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLNotecardBridge(inventory, uuid); - break; - - case LLAssetType::AT_ANIMATION: - if(!(inv_type == LLInventoryType::IT_ANIMATION)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLAnimationBridge(inventory, uuid); - break; - - case LLAssetType::AT_GESTURE: - if(!(inv_type == LLInventoryType::IT_GESTURE)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLGestureBridge(inventory, uuid); - break; - - case LLAssetType::AT_LSL_TEXT: - if(!(inv_type == LLInventoryType::IT_LSL)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLLSLTextBridge(inventory, uuid); - break; - - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - if(!(inv_type == LLInventoryType::IT_WEARABLE)) - { - llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl; - } - new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags); - break; - case LLAssetType::AT_CATEGORY: - case LLAssetType::AT_ROOT_CATEGORY: - if (actual_asset_type == LLAssetType::AT_LINK_FOLDER) - { - // Create a link folder handler instead. - new_listener = new LLLinkFolderBridge(inventory, uuid); - break; - } - new_listener = new LLFolderBridge(inventory, uuid); - break; - case LLAssetType::AT_LINK: - // Only should happen for broken links. - new_listener = new LLLinkItemBridge(inventory, uuid); - break; - case LLAssetType::AT_LINK_FOLDER: - // Only should happen for broken links. - new_listener = new LLLinkItemBridge(inventory, uuid); - break; - default: - llinfos << "Unhandled asset type (llassetstorage.h): " - << (S32)asset_type << llendl; - break; - } - - if (new_listener) - { - new_listener->mInvType = inv_type; - } - - return new_listener; -} - -void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid) -{ - LLInventoryCategory* cat = model->getCategory(uuid); - if (cat) - { - model->purgeDescendentsOf(uuid); - model->notifyObservers(); - } - LLInventoryObject* obj = model->getObject(uuid); - if (obj) - { - model->purgeObject(uuid); - model->notifyObservers(); - } -} - -// +=================================================+ -// | InventoryFVBridgeBuilder | -// +=================================================+ -LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type, - LLAssetType::EType actual_asset_type, - LLInventoryType::EType inv_type, - LLInventoryPanel* inventory, - const LLUUID& uuid, - U32 flags /* = 0x00 */) const -{ - return LLInvFVBridge::createBridge(asset_type, - actual_asset_type, - inv_type, - inventory, - uuid, - flags); -} - -// +=================================================+ -// | LLItemBridge | -// +=================================================+ - -void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("goto" == action) - { - gotoItem(folder); - } - if ("open" == action) - { - openItem(); - return; - } - else if ("properties" == action) - { - showProperties(); - return; - } - else if ("purge" == action) - { - purgeItem(model, mUUID); - return; - } - else if ("restoreToWorld" == action) - { - restoreToWorld(); - return; - } - else if ("restore" == action) - { - restoreItem(); - return; - } - else if ("copy_uuid" == action) - { - // Single item only - LLInventoryItem* item = model->getItem(mUUID); - if(!item) return; - LLUUID asset_id = item->getAssetUUID(); - std::string buffer; - asset_id.toString(buffer); - - gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer)); - return; - } - else if ("copy" == action) - { - copyToClipboard(); - return; - } - else if ("paste" == action) - { - // Single item only - LLInventoryItem* itemp = model->getItem(mUUID); - if (!itemp) return; - - LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID()); - if (!folder_view_itemp) return; - - folder_view_itemp->getListener()->pasteFromClipboard(); - return; - } - else if ("paste_link" == action) - { - // Single item only - LLInventoryItem* itemp = model->getItem(mUUID); - if (!itemp) return; - - LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID()); - if (!folder_view_itemp) return; - - folder_view_itemp->getListener()->pasteLinkFromClipboard(); - return; - } -} - -void LLItemBridge::selectItem() -{ - LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); - if(item && !item->isComplete()) - { - item->fetchFromServer(); - } -} - -void LLItemBridge::restoreItem() -{ - LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem(); - if(item) - { - LLInventoryModel* model = getInventoryModel(); - const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType())); - // do not restamp on restore. - LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE); - } -} - -void LLItemBridge::restoreToWorld() -{ - LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)getItem(); - if (itemp) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("RezRestoreToWorld"); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - - msg->nextBlockFast(_PREHASH_InventoryData); - itemp->packMessage(msg); - msg->sendReliable(gAgent.getRegion()->getHost()); - } - - //Similar functionality to the drag and drop rez logic - BOOL remove_from_inventory = FALSE; - - //remove local inventory copy, sim will deal with permissions and removing the item - //from the actual inventory if its a no-copy etc - if(!itemp->getPermissions().allowCopyBy(gAgent.getID())) - { - remove_from_inventory = TRUE; - } - - // Check if it's in the trash. (again similar to the normal rez logic) - const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id)) - { - remove_from_inventory = TRUE; - } - - if(remove_from_inventory) - { - gInventory.deleteObject(itemp->getUUID()); - gInventory.notifyObservers(); - } -} - -void LLItemBridge::gotoItem(LLFolderView *folder) -{ - LLInventoryObject *obj = getInventoryObject(); - if (obj && obj->getIsLinkType()) - { - LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel(); - if (active_panel) - { - active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO); - } - } -} - -LLUIImagePtr LLItemBridge::getIcon() const -{ - return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]); -} - -PermissionMask LLItemBridge::getPermissionMask() const -{ - LLViewerInventoryItem* item = getItem(); - PermissionMask perm_mask = 0; - if(item) - { - BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); - BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); - BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, - gAgent.getID()); - - if (copy) perm_mask |= PERM_COPY; - if (mod) perm_mask |= PERM_MODIFY; - if (xfer) perm_mask |= PERM_TRANSFER; - - } - return perm_mask; -} - -const std::string& LLItemBridge::getDisplayName() const -{ - if(mDisplayName.empty()) - { - buildDisplayName(getItem(), mDisplayName); - } - return mDisplayName; -} - -void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name) -{ - if(item) - { - name.assign(item->getName()); - } - else - { - name.assign(LLStringUtil::null); - } -} - -LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const -{ - U8 font = LLFontGL::NORMAL; - - if( gAgentWearables.isWearingItem( mUUID ) ) - { - // llinfos << "BOLD" << llendl; - font |= LLFontGL::BOLD; - } - - const LLViewerInventoryItem* item = getItem(); - if (item && item->getIsLinkType()) - { - font |= LLFontGL::ITALIC; - } - return (LLFontGL::StyleFlags)font; -} - -std::string LLItemBridge::getLabelSuffix() const -{ - // String table is loaded before login screen and inventory items are - // loaded after login, so LLTrans should be ready. - static std::string NO_COPY =LLTrans::getString("no_copy"); - static std::string NO_MOD = LLTrans::getString("no_modify"); - static std::string NO_XFER = LLTrans::getString("no_transfer"); - static std::string LINK = LLTrans::getString("link"); - static std::string BROKEN_LINK = LLTrans::getString("broken_link"); - std::string suffix; - LLInventoryItem* item = getItem(); - if(item) - { - // it's a bit confusing to put nocopy/nomod/etc on calling cards. - if(LLAssetType::AT_CALLINGCARD != item->getType() - && item->getPermissions().getOwner() == gAgent.getID()) - { - BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType()); - if (broken_link) return BROKEN_LINK; - - BOOL link = item->getIsLinkType(); - if (link) return LINK; - - BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID()); - if (!copy) - { - suffix += NO_COPY; - } - BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID()); - if (!mod) - { - suffix += NO_MOD; - } - BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER, - gAgent.getID()); - if (!xfer) - { - suffix += NO_XFER; - } - } - } - return suffix; -} - -time_t LLItemBridge::getCreationDate() const -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - return item->getCreationDate(); - } - return 0; -} - - -BOOL LLItemBridge::isItemRenameable() const -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - // (For now) Don't allow calling card rename since that may confuse users as to - // what the calling card points to. - if (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD) - { - return FALSE; - } - return (item->getPermissions().allowModifyBy(gAgent.getID())); - } - return FALSE; -} - -BOOL LLItemBridge::renameItem(const std::string& new_name) -{ - if(!isItemRenameable()) - return FALSE; - LLPreview::dirty(mUUID); - LLInventoryModel* model = getInventoryModel(); - if(!model) - return FALSE; - LLViewerInventoryItem* item = getItem(); - if(item && (item->getName() != new_name)) - { - LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); - new_item->rename(new_name); - buildDisplayName(new_item, mDisplayName); - new_item->updateServer(FALSE); - model->updateItem(new_item); - - model->notifyObservers(); - } - // return FALSE because we either notified observers (& therefore - // rebuilt) or we didn't update. - return FALSE; -} - - -BOOL LLItemBridge::removeItem() -{ - if(!isItemRemovable()) - { - return FALSE; - } - // move it to the trash - LLPreview::hide(mUUID, TRUE); - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - LLViewerInventoryItem* item = getItem(); - - // if item is not already in trash - if(item && !model->isObjectDescendentOf(mUUID, trash_id)) - { - // move to trash, and restamp - LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE); - // delete was successful - return TRUE; - } - else - { - // tried to delete already item in trash (should purge?) - return FALSE; - } -} - -BOOL LLItemBridge::isItemCopyable() const -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - // can't copy worn objects. DEV-15183 - LLVOAvatarSelf *avatarp = gAgent.getAvatarObject(); - if( !avatarp ) - { - return FALSE; - } - - if(avatarp->isWearingAttachment(mUUID)) - { - return FALSE; - } - - // All items can be copied, not all can be pasted. - // The only time an item can't be copied is if it's a link - // return (item->getPermissions().allowCopyBy(gAgent.getID())); - if (item->getIsLinkType()) - { - return FALSE; - } - return TRUE; - } - return FALSE; -} -BOOL LLItemBridge::copyToClipboard() const -{ - if(isItemCopyable()) - { - LLInventoryClipboard::instance().add(mUUID); - return TRUE; - } - return FALSE; -} - -LLViewerInventoryItem* LLItemBridge::getItem() const -{ - LLViewerInventoryItem* item = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - item = (LLViewerInventoryItem*)model->getItem(mUUID); - } - return item; -} - -BOOL LLItemBridge::isItemPermissive() const -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - U32 mask = item->getPermissions().getMaskBase(); - if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) - { - return TRUE; - } - } - return FALSE; -} - -// +=================================================+ -// | LLFolderBridge | -// +=================================================+ - -LLFolderBridge* LLFolderBridge::sSelf=NULL; - -// Can be moved to another folder -BOOL LLFolderBridge::isItemMovable() const -{ - LLInventoryObject* obj = getInventoryObject(); - if(obj) - { - return (!LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType())); - } - return FALSE; -} - -void LLFolderBridge::selectItem() -{ -} - - -// Can be destroyed (or moved to trash) -BOOL LLFolderBridge::isItemRemovable() -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) - { - return FALSE; - } - - if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) - { - return FALSE; - } - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( !avatar ) - { - return FALSE; - } - - LLInventoryCategory* category = model->getCategory(mUUID); - if( !category ) - { - return FALSE; - } - - if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) - { - return FALSE; - } - - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE ); - - S32 i; - for( i = 0; i < descendent_categories.count(); i++ ) - { - LLInventoryCategory* category = descendent_categories[i]; - if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) - { - return FALSE; - } - } - - for( i = 0; i < descendent_items.count(); i++ ) - { - LLInventoryItem* item = descendent_items[i]; - if( (item->getType() == LLAssetType::AT_CLOTHING) || - (item->getType() == LLAssetType::AT_BODYPART) ) - { - if(gAgentWearables.isWearingItem(item->getUUID())) - { - return FALSE; - } - } - else - if( item->getType() == LLAssetType::AT_OBJECT ) - { - if(avatar->isWearingAttachment(item->getUUID())) - { - return FALSE; - } - } - } - - return TRUE; -} - -BOOL LLFolderBridge::isUpToDate() const -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); - if( !category ) - { - return FALSE; - } - - return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN; -} - -BOOL LLFolderBridge::isItemCopyable() const -{ - return TRUE; -} - -BOOL LLFolderBridge::copyToClipboard() const -{ - if(isItemCopyable()) - { - LLInventoryClipboard::instance().add(mUUID); - return TRUE; - } - return FALSE; -} - -BOOL LLFolderBridge::isClipboardPasteable() const -{ - if ( ! LLInvFVBridge::isClipboardPasteable() ) - return FALSE; - - // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 - if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) ) - { - LLInventoryModel* model = getInventoryModel(); - if ( !model ) - { - return FALSE; - } - - LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); - const LLViewerInventoryCategory *current_cat = getCategory(); - - // Search for the direct descendent of current Friends subfolder among all pasted items, - // and return false if is found. - for(S32 i = objects.count() - 1; i >= 0; --i) - { - const LLUUID &obj_id = objects.get(i); - if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) - { - return FALSE; - } - } - - } - return TRUE; -} - -BOOL LLFolderBridge::isClipboardPasteableAsLink() const -{ - // Check normal paste-as-link permissions - if (!LLInvFVBridge::isClipboardPasteableAsLink()) - { - return FALSE; - } - - const LLInventoryModel* model = getInventoryModel(); - if (!model) - { - return FALSE; - } - - const LLViewerInventoryCategory *current_cat = getCategory(); - if (current_cat) - { - const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat ); - const LLUUID ¤t_cat_id = current_cat->getUUID(); - LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - for(S32 i = 0; i < count; i++) - { - const LLUUID &obj_id = objects.get(i); - const LLInventoryCategory *cat = model->getCategory(obj_id); - if (cat) - { - const LLUUID &cat_id = cat->getUUID(); - // Don't allow recursive pasting - if ((cat_id == current_cat_id) || - model->isObjectDescendentOf(current_cat_id, cat_id)) - { - return FALSE; - } - } - // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599 - if ( is_in_friend_folder ) - { - // If object is direct descendent of current Friends subfolder than return false. - // Note: We can't use 'const LLInventoryCategory *cat', because it may be null - // in case type of obj_id is LLInventoryItem. - if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) ) - { - return FALSE; - } - } - } - } - return TRUE; - -} - -BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, - BOOL drop) -{ - // This should never happen, but if an inventory item is incorrectly parented, - // the UI will get confused and pass in a NULL. - if(!inv_cat) return FALSE; - - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if(!avatar) return FALSE; - - // cannot drag categories into library - if(!isAgentInventory()) - { - return FALSE; - } - - // check to make sure source is agent inventory, and is represented there. - LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); - BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL) - && (LLToolDragAndDrop::SOURCE_AGENT == source); - - BOOL accept = FALSE; - S32 i; - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - if(is_agent_inventory) - { - const LLUUID& cat_id = inv_cat->getUUID(); - - // Is the destination the trash? - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - BOOL move_is_into_trash = (mUUID == trash_id) - || model->isObjectDescendentOf(mUUID, trash_id); - BOOL is_movable = (!LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())); - const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); - if (move_is_into_current_outfit || move_is_into_outfit) - { - // BAP - restrictions? - is_movable = true; - } - - if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)) - { - is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604 - } - - if( is_movable ) - { - gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE ); - - for( i = 0; i < descendent_categories.count(); i++ ) - { - LLInventoryCategory* category = descendent_categories[i]; - if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) - { - // ...can't move "special folders" like Textures - is_movable = FALSE; - break; - } - } - - if( is_movable ) - { - if( move_is_into_trash ) - { - for( i = 0; i < descendent_items.count(); i++ ) - { - LLInventoryItem* item = descendent_items[i]; - if( (item->getType() == LLAssetType::AT_CLOTHING) || - (item->getType() == LLAssetType::AT_BODYPART) ) - { - if( gAgentWearables.isWearingItem( item->getUUID() ) ) - { - is_movable = FALSE; // It's generally movable, but not into the trash! - break; - } - } - else - if( item->getType() == LLAssetType::AT_OBJECT ) - { - if( avatar->isWearingAttachment( item->getUUID() ) ) - { - is_movable = FALSE; // It's generally movable, but not into the trash! - break; - } - } - } - } - } - } - - - accept = is_movable - && (mUUID != cat_id) // Can't move a folder into itself - && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing - && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity - if(accept && drop) - { - // Look for any gestures and deactivate them - if (move_is_into_trash) - { - for (i = 0; i < descendent_items.count(); i++) - { - LLInventoryItem* item = descendent_items[i]; - if (item->getType() == LLAssetType::AT_GESTURE - && LLGestureManager::instance().isGestureActive(item->getUUID())) - { - LLGestureManager::instance().deactivateGesture(item->getUUID()); - } - } - } - // if target is an outfit or current outfit folder we use link - if (move_is_into_current_outfit || move_is_into_outfit) - { -#if SUPPORT_ENSEMBLES - // BAP - should skip if dup. - if (move_is_into_current_outfit) - { - LLAppearanceManager::wearEnsemble(inv_cat); - } - else - { - LLPointer<LLInventoryCallback> cb = NULL; - link_inventory_item( - gAgent.getID(), - inv_cat->getUUID(), - mUUID, - inv_cat->getName(), - LLAssetType::AT_LINK_FOLDER, - cb); - } -#endif - } - else - { - - // Reparent the folder and restamp children if it's moving - // into trash. - LLInvFVBridge::changeCategoryParent( - model, - (LLViewerInventoryCategory*)inv_cat, - mUUID, - move_is_into_trash); - } - } - } - else if(LLToolDragAndDrop::SOURCE_WORLD == source) - { - // content category has same ID as object itself - LLUUID object_id = inv_cat->getUUID(); - LLUUID category_id = mUUID; - accept = move_inv_category_world_to_agent(object_id, category_id, drop); - } - return accept; -} - -void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv) -{ - const char* dialog = NULL; - if (object->flagScripted()) - { - dialog = "MoveInventoryFromScriptedObject"; - } - else - { - dialog = "MoveInventoryFromObject"; - } - LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv)); -} - -// Move/copy all inventory items from the Contents folder of an in-world -// object to the agent's inventory, inside a given category. -BOOL move_inv_category_world_to_agent(const LLUUID& object_id, - const LLUUID& category_id, - BOOL drop, - void (*callback)(S32, void*), - void* user_data) -{ - // Make sure the object exists. If we allowed dragging from - // anonymous objects, it would be possible to bypass - // permissions. - // content category has same ID as object itself - LLViewerObject* object = gObjectList.findObject(object_id); - if(!object) - { - llinfos << "Object not found for drop." << llendl; - return FALSE; - } - - // this folder is coming from an object, as there is only one folder in an object, the root, - // we need to collect the entire contents and handle them as a group - InventoryObjectList inventory_objects; - object->getInventoryContents(inventory_objects); - - if (inventory_objects.empty()) - { - llinfos << "Object contents not found for drop." << llendl; - return FALSE; - } - - BOOL accept = TRUE; - BOOL is_move = FALSE; - - // coming from a task. Need to figure out if the person can - // move/copy this item. - InventoryObjectList::iterator it = inventory_objects.begin(); - InventoryObjectList::iterator end = inventory_objects.end(); - for ( ; it != end; ++it) - { - // coming from a task. Need to figure out if the person can - // move/copy this item. - LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions()); - if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) - && perm.allowTransferTo(gAgent.getID()))) -// || gAgent.isGodlike()) - { - accept = TRUE; - } - else if(object->permYouOwner()) - { - // If the object cannot be copied, but the object the - // inventory is owned by the agent, then the item can be - // moved from the task to agent inventory. - is_move = TRUE; - accept = TRUE; - } - else - { - accept = FALSE; - break; - } - } - - if(drop && accept) - { - it = inventory_objects.begin(); - InventoryObjectList::iterator first_it = inventory_objects.begin(); - LLMoveInv* move_inv = new LLMoveInv; - move_inv->mObjectID = object_id; - move_inv->mCategoryID = category_id; - move_inv->mCallback = callback; - move_inv->mUserData = user_data; - - for ( ; it != end; ++it) - { - two_uuids_t two(category_id, (*it)->getUUID()); - move_inv->mMoveList.push_back(two); - } - - if(is_move) - { - // Callback called from within here. - warn_move_inventory(object, move_inv); - } - else - { - LLNotification::Params params("MoveInventoryFromObject"); - params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); - LLNotifications::instance().forceResponse(params, 0); - } - } - return accept; -} - -bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat, - LLInventoryItem* item) -{ - // Valid COF items are: - // - links to wearables (body parts or clothing) - // - links to attachments - // - links to gestures - // - links to ensemble folders - LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); // BAP - safe? - if (linked_item) - { - LLAssetType::EType type = linked_item->getType(); - return (type == LLAssetType::AT_CLOTHING || - type == LLAssetType::AT_BODYPART || - type == LLAssetType::AT_GESTURE || - type == LLAssetType::AT_OBJECT); - } - else - { - LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe? - // BAP remove AT_NONE support after ensembles are fully working? - return (linked_category && - ((linked_category->getPreferredType() == LLFolderType::FT_NONE) || - (LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType())))); - } -} - - -bool LLFindWearables::operator()(LLInventoryCategory* cat, - LLInventoryItem* item) -{ - if(item) - { - if((item->getType() == LLAssetType::AT_CLOTHING) - || (item->getType() == LLAssetType::AT_BODYPART)) - { - return TRUE; - } - } - return FALSE; -} - - - -//Used by LLFolderBridge as callback for directory recursion. -class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver -{ -public: - LLRightClickInventoryFetchObserver() : - mCopyItems(false) - { }; - LLRightClickInventoryFetchObserver(const LLUUID& cat_id, bool copy_items) : - mCatID(cat_id), - mCopyItems(copy_items) - { }; - virtual void done() - { - // we've downloaded all the items, so repaint the dialog - LLFolderBridge::staticFolderOptionsMenu(); - - gInventory.removeObserver(this); - delete this; - } - - -protected: - LLUUID mCatID; - bool mCopyItems; - -}; - -//Used by LLFolderBridge as callback for directory recursion. -class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver -{ -public: - LLRightClickInventoryFetchDescendentsObserver(bool copy_items) : mCopyItems(copy_items) {} - ~LLRightClickInventoryFetchDescendentsObserver() {} - virtual void done(); -protected: - bool mCopyItems; -}; - -void LLRightClickInventoryFetchDescendentsObserver::done() -{ - // Avoid passing a NULL-ref as mCompleteFolders.front() down to - // gInventory.collectDescendents() - if( mCompleteFolders.empty() ) - { - llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl; - dec_busy_count(); - gInventory.removeObserver(this); - delete this; - return; - } - - // What we do here is get the complete information on the items in - // the library, and set up an observer that will wait for that to - // happen. - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(mCompleteFolders.front(), - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH); - S32 count = item_array.count(); -#if 0 // HACK/TODO: Why? - // This early causes a giant menu to get produced, and doesn't seem to be needed. - if(!count) - { - llwarns << "Nothing fetched in category " << mCompleteFolders.front() - << llendl; - dec_busy_count(); - gInventory.removeObserver(this); - delete this; - return; - } -#endif - - LLRightClickInventoryFetchObserver* outfit; - outfit = new LLRightClickInventoryFetchObserver(mCompleteFolders.front(), mCopyItems); - LLInventoryFetchObserver::item_ref_t ids; - for(S32 i = 0; i < count; ++i) - { - ids.push_back(item_array.get(i)->getUUID()); - } - - // clean up, and remove this as an observer since the call to the - // outfit could notify observers and throw us into an infinite - // loop. - dec_busy_count(); - gInventory.removeObserver(this); - delete this; - - // increment busy count and either tell the inventory to check & - // call done, or add this object to the inventory for observation. - inc_busy_count(); - - // do the fetch - outfit->fetchItems(ids); - outfit->done(); //Not interested in waiting and this will be right 99% of the time. -//Uncomment the following code for laggy Inventory UI. -/* if(outfit->isEverythingComplete()) - { - // everything is already here - call done. - outfit->done(); - } - else - { - // it's all on it's way - add an observer, and the inventory - // will call done for us when everything is here. - gInventory.addObserver(outfit); - }*/ -} - - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLInventoryWearObserver -// -// Observer for "copy and wear" operation to support knowing -// when the all of the contents have been added to inventory. -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLInventoryCopyAndWearObserver : public LLInventoryObserver -{ -public: - LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) :mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {} - virtual ~LLInventoryCopyAndWearObserver() {} - virtual void changed(U32 mask); - -protected: - LLUUID mCatID; - int mContentsCount; - BOOL mFolderAdded; -}; - - - -void LLInventoryCopyAndWearObserver::changed(U32 mask) -{ - if((mask & (LLInventoryObserver::ADD)) != 0) - { - if (!mFolderAdded) - { - const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); - - std::set<LLUUID>::const_iterator id_it = changed_items.begin(); - std::set<LLUUID>::const_iterator id_end = changed_items.end(); - for (;id_it != id_end; ++id_it) - { - if ((*id_it) == mCatID) - { - mFolderAdded = TRUE; - break; - } - } - } - - if (mFolderAdded) - { - LLViewerInventoryCategory* category = gInventory.getCategory(mCatID); - - if (NULL == category) - { - llwarns << "gInventory.getCategory(" << mCatID - << ") was NULL" << llendl; - } - else - { - if (category->getDescendentCount() == - mContentsCount) - { - gInventory.removeObserver(this); - LLAppearanceManager::wearInventoryCategory(category, FALSE, TRUE); - delete this; - } - } - } - - } -} - - - -void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("open" == action) - { - openItem(); - return; - } - else if ("paste" == action) - { - pasteFromClipboard(); - return; - } - else if ("paste_link" == action) - { - pasteLinkFromClipboard(); - return; - } - else if ("properties" == action) - { - showProperties(); - return; - } - else if ("replaceoutfit" == action) - { - modifyOutfit(FALSE); - return; - } -#if SUPPORT_ENSEMBLES - else if ("wearasensemble" == action) - { - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLViewerInventoryCategory* cat = getCategory(); - if(!cat) return; - LLAppearanceManager::wearEnsemble(cat,true); - return; - } -#endif - else if ("addtooutfit" == action) - { - modifyOutfit(TRUE); - return; - } - else if ("copy" == action) - { - copyToClipboard(); - return; - } - else if ("removefromoutfit" == action) - { - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLViewerInventoryCategory* cat = getCategory(); - if(!cat) return; - - remove_inventory_category_from_avatar ( cat ); - return; - } - else if ("purge" == action) - { - purgeItem(model, mUUID); - return; - } - else if ("restore" == action) - { - restoreItem(); - return; - } -} - -void LLFolderBridge::openItem() -{ - lldebugs << "LLFolderBridge::openItem()" << llendl; - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - bool fetching_inventory = model->fetchDescendentsOf(mUUID); - // Only change folder type if we have the folder contents. - if (!fetching_inventory) - { - // Disabling this for now, it's causing crash when new items are added to folders - // since folder type may change before new item item has finished processing. - // determineFolderType(); - } -} - -void LLFolderBridge::closeItem() -{ - determineFolderType(); -} - -void LLFolderBridge::determineFolderType() -{ - if (isUpToDate()) - { - LLInventoryModel* model = getInventoryModel(); - LLViewerInventoryCategory* category = model->getCategory(mUUID); - category->determineFolderType(); - } -} - -BOOL LLFolderBridge::isItemRenameable() const -{ - LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory(); - if(cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) - && (cat->getOwnerID() == gAgent.getID())) - { - return TRUE; - } - return FALSE; -} - -void LLFolderBridge::restoreItem() -{ - LLViewerInventoryCategory* cat; - cat = (LLViewerInventoryCategory*)getCategory(); - if(cat) - { - LLInventoryModel* model = getInventoryModel(); - const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType())); - // do not restamp children on restore - LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE); - } -} - -LLFolderType::EType LLFolderBridge::getPreferredType() const -{ - LLFolderType::EType preferred_type = LLFolderType::FT_NONE; - LLViewerInventoryCategory* cat = getCategory(); - if(cat) - { - preferred_type = cat->getPreferredType(); - } - - return preferred_type; -} - -// Icons for folders are based on the preferred type -LLUIImagePtr LLFolderBridge::getIcon() const -{ - LLFolderType::EType preferred_type = LLFolderType::FT_NONE; - LLViewerInventoryCategory* cat = getCategory(); - if(cat) - { - preferred_type = cat->getPreferredType(); - } - return getIcon(preferred_type); -} - -LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type) -{ - // we only have one folder image now - return LLUI::getUIImage("Inv_FolderClosed"); -} - -BOOL LLFolderBridge::renameItem(const std::string& new_name) -{ - if(!isItemRenameable()) - return FALSE; - LLInventoryModel* model = getInventoryModel(); - if(!model) - return FALSE; - LLViewerInventoryCategory* cat = getCategory(); - if(cat && (cat->getName() != new_name)) - { - LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat); - new_cat->rename(new_name); - new_cat->updateServer(FALSE); - model->updateCategory(new_cat); - - model->notifyObservers(); - } - // return FALSE because we either notified observers (& therefore - // rebuilt) or we didn't update. - return FALSE; -} - -BOOL LLFolderBridge::removeItem() -{ - if(!isItemRemovable()) - { - return FALSE; - } - // move it to the trash - LLPreview::hide(mUUID); - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - - // Look for any gestures and deactivate them - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE ); - - S32 i; - for (i = 0; i < descendent_items.count(); i++) - { - LLInventoryItem* item = descendent_items[i]; - if (item->getType() == LLAssetType::AT_GESTURE - && LLGestureManager::instance().isGestureActive(item->getUUID())) - { - LLGestureManager::instance().deactivateGesture(item->getUUID()); - } - } - - // go ahead and do the normal remove if no 'last calling - // cards' are being removed. - LLViewerInventoryCategory* cat = getCategory(); - if(cat) - { - LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE); - } - - return TRUE; -} - -void LLFolderBridge::pasteFromClipboard() -{ - LLInventoryModel* model = getInventoryModel(); - if(model && isClipboardPasteable()) - { - LLInventoryItem* item = NULL; - LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - const LLUUID parent_id(mUUID); - for(S32 i = 0; i < count; i++) - { - item = model->getItem(objects.get(i)); - if (item) - { - if(LLInventoryClipboard::instance().isCutMode()) - { - // move_inventory_item() is not enough, - //we have to update inventory locally too - changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE); - } - else - { - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - parent_id, - std::string(), - LLPointer<LLInventoryCallback>(NULL)); - } - } - } - } -} - -void LLFolderBridge::pasteLinkFromClipboard() -{ - const LLInventoryModel* model = getInventoryModel(); - if(model) - { - LLDynamicArray<LLUUID> objects; - LLInventoryClipboard::instance().retrieve(objects); - S32 count = objects.count(); - LLUUID parent_id(mUUID); - for(S32 i = 0; i < count; i++) - { - const LLUUID &object_id = objects.get(i); -#if SUPPORT_ENSEMBLES - if (LLInventoryCategory *cat = model->getCategory(object_id)) - { - link_inventory_item( - gAgent.getID(), - cat->getUUID(), - parent_id, - cat->getName(), - LLAssetType::AT_LINK_FOLDER, - LLPointer<LLInventoryCallback>(NULL)); - } - else -#endif - if (LLInventoryItem *item = model->getItem(object_id)) - { - link_inventory_item( - gAgent.getID(), - item->getUUID(), - parent_id, - item->getName(), - LLAssetType::AT_LINK, - LLPointer<LLInventoryCallback>(NULL)); - } - } - } -} - -void LLFolderBridge::staticFolderOptionsMenu() -{ - if (!sSelf) return; - sSelf->folderOptionsMenu(); -} - -void LLFolderBridge::folderOptionsMenu() -{ - std::vector<std::string> disabled_items; - - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - - const LLInventoryCategory* category = model->getCategory(mUUID); - LLFolderType::EType type = category->getPreferredType(); - const bool is_default_folder = category && LLFolderType::lookupIsProtectedType(type); - // BAP change once we're no longer treating regular categories as ensembles. - const bool is_ensemble = category && (type == LLFolderType::FT_NONE || - LLFolderType::lookupIsEnsembleType(type)); - - // calling card related functionality for folders. - - // Only enable calling-card related options for non-default folders. - if (!is_default_folder) - { - LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); - if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) - { - mItems.push_back(std::string("Calling Card Separator")); - mItems.push_back(std::string("Conference Chat Folder")); - mItems.push_back(std::string("IM All Contacts In Folder")); - } - } - - // wearables related functionality for folders. - //is_wearable - LLFindWearables is_wearable; - LLIsType is_object( LLAssetType::AT_OBJECT ); - LLIsType is_gesture( LLAssetType::AT_GESTURE ); - - if (mWearables || - checkFolderForContentsOfType(model, is_wearable) || - checkFolderForContentsOfType(model, is_object) || - checkFolderForContentsOfType(model, is_gesture) ) - { - mItems.push_back(std::string("Folder Wearables Separator")); - - // Only enable add/replace outfit for non-default folders. - if (!is_default_folder) - { - mItems.push_back(std::string("Add To Outfit")); - mItems.push_back(std::string("Replace Outfit")); - } - if (is_ensemble) - { - mItems.push_back(std::string("Wear As Ensemble")); - } - mItems.push_back(std::string("Take Off Items")); - } - hide_context_entries(*mMenu, mItems, disabled_items); -} - -BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type) -{ - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - model->collectDescendentsIf(mUUID, - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_type); - return ((item_array.count() > 0) ? TRUE : FALSE ); -} - -// Flags unused -void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - mItems.clear(); - mDisabledItems.clear(); - - lldebugs << "LLFolderBridge::buildContextMenu()" << llendl; -// std::vector<std::string> disabled_items; - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); - - mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point) - mDisabledItems.clear(); //adding code to clear out disabled members from previous - if (lost_and_found_id == mUUID) - { - // This is the lost+found folder. - mItems.push_back(std::string("Empty Lost And Found")); - } - - if(trash_id == mUUID) - { - // This is the trash. - mItems.push_back(std::string("Empty Trash")); - } - else if(model->isObjectDescendentOf(mUUID, trash_id)) - { - // This is a folder in the trash. - mItems.clear(); // clear any items that used to exist - mItems.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - mDisabledItems.push_back(std::string("Purge Item")); - } - - mItems.push_back(std::string("Restore Item")); - } - else if(isAgentInventory()) // do not allow creating in library - { - LLViewerInventoryCategory *cat = getCategory(); - // BAP removed protected check to re-enable standard ops in untyped folders. - // Not sure what the right thing is to do here. - if (!isCOFFolder() && cat /*&& - LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/) - { - // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. - if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) - mItems.push_back(std::string("New Folder")); - mItems.push_back(std::string("New Script")); - mItems.push_back(std::string("New Note")); - mItems.push_back(std::string("New Gesture")); - mItems.push_back(std::string("New Clothes")); - mItems.push_back(std::string("New Body Parts")); - mItems.push_back(std::string("Change Type")); - - LLViewerInventoryCategory *cat = getCategory(); - if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) - { - mDisabledItems.push_back(std::string("Change Type")); - } - - getClipboardEntries(false, mItems, mDisabledItems, flags); - } - else - { - // Want some but not all of the items from getClipboardEntries for outfits. - if (cat && cat->getPreferredType()==LLFolderType::FT_OUTFIT) - { - mItems.push_back(std::string("Rename")); - mItems.push_back(std::string("Delete")); - } - } - - //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06 - mCallingCards = mWearables = FALSE; - - LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); - if (checkFolderForContentsOfType(model, is_callingcard)) - { - mCallingCards=TRUE; - } - - LLFindWearables is_wearable; - LLIsType is_object( LLAssetType::AT_OBJECT ); - LLIsType is_gesture( LLAssetType::AT_GESTURE ); - - if (checkFolderForContentsOfType(model, is_wearable) || - checkFolderForContentsOfType(model, is_object) || - checkFolderForContentsOfType(model, is_gesture) ) - { - mWearables=TRUE; - } - - mMenu = &menu; - sSelf = this; - LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE); - - LLInventoryFetchDescendentsObserver::folder_ref_t folders; - LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID); - if (category) - { - folders.push_back(category->getUUID()); - } - fetch->fetchDescendents(folders); - inc_busy_count(); - if(fetch->isEverythingComplete()) - { - // everything is already here - call done. - fetch->done(); - } - else - { - // it's all on it's way - add an observer, and the inventory - // will call done for us when everything is here. - gInventory.addObserver(fetch); - } - } - else - { - mItems.push_back(std::string("--no options--")); - mDisabledItems.push_back(std::string("--no options--")); - } - hide_context_entries(menu, mItems, mDisabledItems); -} - -BOOL LLFolderBridge::hasChildren() const -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - LLInventoryModel::EHasChildren has_children; - has_children = gInventory.categoryHasChildren(mUUID); - return has_children != LLInventoryModel::CHILDREN_NO; -} - -BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data) -{ - //llinfos << "LLFolderBridge::dragOrDrop()" << llendl; - BOOL accept = FALSE; - switch(cargo_type) - { - case DAD_TEXTURE: - case DAD_SOUND: - case DAD_CALLINGCARD: - case DAD_LANDMARK: - case DAD_SCRIPT: - case DAD_OBJECT: - case DAD_NOTECARD: - case DAD_CLOTHING: - case DAD_BODYPART: - case DAD_ANIMATION: - case DAD_GESTURE: - case DAD_LINK: - accept = dragItemIntoFolder((LLInventoryItem*)cargo_data, - drop); - break; - case DAD_CATEGORY: - if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID)) - { - accept = FALSE; - } - else - { - accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop); - } - break; - default: - break; - } - return accept; -} - -LLViewerInventoryCategory* LLFolderBridge::getCategory() const -{ - LLViewerInventoryCategory* cat = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - cat = (LLViewerInventoryCategory*)model->getCategory(mUUID); - } - return cat; -} - - -// static -void LLFolderBridge::pasteClipboard(void* user_data) -{ - LLFolderBridge* self = (LLFolderBridge*)user_data; - if(self) self->pasteFromClipboard(); -} - -void LLFolderBridge::createNewCategory(void* user_data) -{ - LLFolderBridge* bridge = (LLFolderBridge*)user_data; - if(!bridge) return; - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel.get()); - if (!panel) return; - LLInventoryModel* model = panel->getModel(); - if(!model) return; - LLUUID id; - id = model->createNewCategory(bridge->getUUID(), - LLFolderType::FT_NONE, - LLStringUtil::null); - model->notifyObservers(); - - // At this point, the bridge has probably been deleted, but the - // view is still there. - panel->setSelection(id, TAKE_FOCUS_YES); -} - -void LLFolderBridge::createNewShirt(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHIRT); -} - -void LLFolderBridge::createNewPants(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_PANTS); -} - -void LLFolderBridge::createNewShoes(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHOES); -} - -void LLFolderBridge::createNewSocks(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SOCKS); -} - -void LLFolderBridge::createNewJacket(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_JACKET); -} - -void LLFolderBridge::createNewSkirt(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIRT); -} - -void LLFolderBridge::createNewGloves(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_GLOVES); -} - -void LLFolderBridge::createNewUndershirt(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERSHIRT); -} - -void LLFolderBridge::createNewUnderpants(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERPANTS); -} - -void LLFolderBridge::createNewShape(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHAPE); -} - -void LLFolderBridge::createNewSkin(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIN); -} - -void LLFolderBridge::createNewHair(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_HAIR); -} - -void LLFolderBridge::createNewEyes(void* user_data) -{ - LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_EYES); -} - -// static -void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type) -{ - if(!bridge) return; - LLUUID parent_id = bridge->getUUID(); - createWearable(parent_id, type); -} - -// Separate function so can be called by global menu as well as right-click -// menu. -// static -void LLFolderBridge::createWearable(const LLUUID &parent_id, EWearableType type) -{ - LLWearable* wearable = LLWearableList::instance().createNewWearable(type); - LLAssetType::EType asset_type = wearable->getAssetType(); - LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE; - create_inventory_item(gAgent.getID(), gAgent.getSessionID(), - parent_id, wearable->getTransactionID(), wearable->getName(), - wearable->getDescription(), asset_type, inv_type, wearable->getType(), - wearable->getPermissions().getMaskNextOwner(), - LLPointer<LLInventoryCallback>(NULL)); -} - -void LLFolderBridge::modifyOutfit(BOOL append) -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return; - LLViewerInventoryCategory* cat = getCategory(); - if(!cat) return; - - // BAP - was: - // wear_inventory_category_on_avatar( cat, append ); - LLAppearanceManager::wearInventoryCategory( cat, FALSE, append ); -} - -// helper stuff -bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv) -{ - LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData; - LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID); - S32 option = LLNotification::getSelectedOption(notification, response); - - if(option == 0 && object) - { - if (cat_and_wear && cat_and_wear->mWear) - { - InventoryObjectList inventory_objects; - object->getInventoryContents(inventory_objects); - int contents_count = inventory_objects.size()-1; //subtract one for containing folder - - LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count); - gInventory.addObserver(inventoryObserver); - } - - two_uuids_list_t::iterator move_it; - for (move_it = move_inv->mMoveList.begin(); - move_it != move_inv->mMoveList.end(); - ++move_it) - { - object->moveInventory(move_it->first, move_it->second); - } - - // update the UI. - dialog_refresh_all(); - } - - if (move_inv->mCallback) - { - move_inv->mCallback(option, move_inv->mUserData); - } - - delete move_inv; - return false; -} - -/* -Next functions intended to reorder items in the inventory folder and save order on server -Is now used for Favorites folder. - -*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel -*/ -void saveItemsOrder(LLInventoryModel::item_array_t& items) -{ - int sortField = 0; - - // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field - for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) - { - LLViewerInventoryItem* item = *i; - - item->setSortField(++sortField); - item->setComplete(TRUE); - item->updateServer(FALSE); - - gInventory.updateItem(item); - } - - gInventory.notifyObservers(); -} - -LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id) -{ - LLInventoryModel::item_array_t::iterator result = items.end(); - - for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i) - { - if ((*i)->getUUID() == id) - { - result = i; - break; - } - } - - return result; -} - -void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId) -{ - LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId); - LLViewerInventoryItem* destItem = gInventory.getItem(destItemId); - - items.erase(findItemByUUID(items, srcItem->getUUID())); - items.insert(findItemByUUID(items, destItem->getUUID()), srcItem); -} - -BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, - BOOL drop) -{ - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - - // cannot drag into library - if(!isAgentInventory()) - { - return FALSE; - } - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if(!avatar) return FALSE; - - LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); - BOOL accept = FALSE; - LLViewerObject* object = NULL; - if(LLToolDragAndDrop::SOURCE_AGENT == source) - { - - BOOL is_movable = TRUE; - switch( inv_item->getActualType() ) - { - case LLAssetType::AT_ROOT_CATEGORY: - is_movable = FALSE; - break; - - case LLAssetType::AT_CATEGORY: - is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType()); - break; - default: - break; - } - - const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); - BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); - const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); - - if(is_movable && move_is_into_trash) - { - switch(inv_item->getType()) - { - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID()); - break; - - case LLAssetType::AT_OBJECT: - is_movable = !avatar->isWearingAttachment(inv_item->getUUID()); - break; - default: - break; - } - } - - if ( is_movable ) - { - // Don't allow creating duplicates in the Calling Card/Friends - // subfolders, see bug EXT-1599. Check is item direct descendent - // of target folder and forbid item's movement if it so. - // Note: isItemDirectDescendentOfCategory checks if - // passed category is in the Calling Card/Friends folder - is_movable = ! LLFriendCardsManager::instance() - .isObjDirectDescendentOfCategory (inv_item, getCategory()); - } - - const LLUUID& favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - - // we can move item inside a folder only if this folder is Favorites. See EXT-719 - accept = is_movable && ((mUUID != inv_item->getParentUUID()) || (mUUID == favorites_id)); - if(accept && drop) - { - if (inv_item->getType() == LLAssetType::AT_GESTURE - && LLGestureManager::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash) - { - LLGestureManager::instance().deactivateGesture(inv_item->getUUID()); - } - // If an item is being dragged between windows, unselect - // everything in the active window so that we don't follow - // the selection to its new location (which is very - // annoying). - if (LLFloaterInventory::getActiveInventory()) - { - LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel(); - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); - if (active_panel && (panel != active_panel)) - { - active_panel->unSelectAll(); - } - } - - // if dragging from/into favorites folder only reorder items - if ((mUUID == inv_item->getParentUUID()) && (favorites_id == mUUID)) - { - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLIsType is_type(LLAssetType::AT_LANDMARK); - model->collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); - - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); - LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; - if (itemp) - { - LLUUID srcItemId = inv_item->getUUID(); - LLUUID destItemId = itemp->getListener()->getUUID(); - - // update order - updateItemsOrder(items, srcItemId, destItemId); - - saveItemsOrder(items); - } - } - else if (favorites_id == mUUID) // if target is the favorites folder we use copy - { - copy_inventory_item( - gAgent.getID(), - inv_item->getPermissions().getOwner(), - inv_item->getUUID(), - mUUID, - std::string(), - LLPointer<LLInventoryCallback>(NULL)); - } - else if (move_is_into_current_outfit || move_is_into_outfit) - { - // BAP - should skip if dup. - if (move_is_into_current_outfit) - { - LLAppearanceManager::wearItem(inv_item); - } - else - { - LLPointer<LLInventoryCallback> cb = NULL; - link_inventory_item( - gAgent.getID(), - inv_item->getUUID(), - mUUID, - std::string(), - LLAssetType::AT_LINK, - cb); - } - } - else - { - // restamp if the move is into the trash. - LLInvFVBridge::changeItemParent( - model, - (LLViewerInventoryItem*)inv_item, - mUUID, - move_is_into_trash); - } - } - } - else if(LLToolDragAndDrop::SOURCE_WORLD == source) - { - // Make sure the object exists. If we allowed dragging from - // anonymous objects, it would be possible to bypass - // permissions. - object = gObjectList.findObject(inv_item->getParentUUID()); - if(!object) - { - llinfos << "Object not found for drop." << llendl; - return FALSE; - } - - // coming from a task. Need to figure out if the person can - // move/copy this item. - LLPermissions perm(inv_item->getPermissions()); - BOOL is_move = FALSE; - if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) - && perm.allowTransferTo(gAgent.getID()))) -// || gAgent.isGodlike()) - - { - accept = TRUE; - } - else if(object->permYouOwner()) - { - // If the object cannot be copied, but the object the - // inventory is owned by the agent, then the item can be - // moved from the task to agent inventory. - is_move = TRUE; - accept = TRUE; - } - if(drop && accept) - { - LLMoveInv* move_inv = new LLMoveInv; - move_inv->mObjectID = inv_item->getParentUUID(); - two_uuids_t item_pair(mUUID, inv_item->getUUID()); - move_inv->mMoveList.push_back(item_pair); - move_inv->mCallback = NULL; - move_inv->mUserData = NULL; - if(is_move) - { - warn_move_inventory(object, move_inv); - } - else - { - LLNotification::Params params("MoveInventoryFromObject"); - params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv)); - LLNotifications::instance().forceResponse(params, 0); - } - } - - } - else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) - { - accept = TRUE; - if(drop) - { - copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(), - LLToolDragAndDrop::getInstance()->getSourceID(), inv_item); - } - } - else if(LLToolDragAndDrop::SOURCE_LIBRARY == source) - { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item; - if(item && item->isComplete()) - { - accept = TRUE; - if(drop) - { - copy_inventory_item( - gAgent.getID(), - inv_item->getPermissions().getOwner(), - inv_item->getUUID(), - mUUID, - std::string(), - LLPointer<LLInventoryCallback>(NULL)); - } - } - } - else - { - llwarns << "unhandled drag source" << llendl; - } - return accept; -} - -// +=================================================+ -// | LLScriptBridge (DEPRECTED) | -// +=================================================+ - -LLUIImagePtr LLScriptBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE); -} - -// +=================================================+ -// | LLTextureBridge | -// +=================================================+ - -LLUIImagePtr LLTextureBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE); -} - -void LLTextureBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -} - -// +=================================================+ -// | LLSoundBridge | -// +=================================================+ - -LLUIImagePtr LLSoundBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE); -} - -void LLSoundBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* -// Changed this back to the way it USED to work: -// only open the preview dialog through the contextual right-click menu -// double-click just plays the sound - - LLViewerInventoryItem* item = getItem(); - if(item) - { - openSoundPreview((void*)this); - //send_uuid_sound_trigger(item->getAssetUUID(), 1.0); - } -*/ -} - -void LLSoundBridge::previewItem() -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - send_sound_trigger(item->getAssetUUID(), 1.0); - } -} - -void LLSoundBridge::openSoundPreview(void* which) -{ - LLSoundBridge *me = (LLSoundBridge *)which; - LLFloaterReg::showInstance("preview_sound", LLSD(me->mUUID), TAKE_FOCUS_YES); -} - -void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLTextureBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Sound Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - - items.push_back(std::string("Sound Separator")); - items.push_back(std::string("Sound Play")); - - hide_context_entries(menu, items, disabled_items); -} - -// +=================================================+ -// | LLLandmarkBridge | -// +=================================================+ - -LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) : -LLItemBridge(inventory, uuid) -{ - mVisited = FALSE; - if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED) - { - mVisited = TRUE; - } -} - -LLUIImagePtr LLLandmarkBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE); -} - -void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - std::vector<std::string> items; - std::vector<std::string> disabled_items; - - lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Landmark Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - - items.push_back(std::string("Landmark Separator")); - items.push_back(std::string("About Landmark")); - - // Disable "About Landmark" menu item for - // multiple landmarks selected. Only one landmark - // info panel can be shown at a time. - if ((flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("About Landmark")); - } - - hide_context_entries(menu, items, disabled_items); -} - -// Convenience function for the two functions below. -void teleport_via_landmark(const LLUUID& asset_id) -{ - gAgent.teleportViaLandmark( asset_id ); - - // we now automatically track the landmark you're teleporting to - // because you'll probably arrive at a telehub instead - LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance(); - if( floater_world_map ) - { - floater_world_map->trackLandmark( asset_id ); - } -} - -// virtual -void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("teleport" == action) - { - LLViewerInventoryItem* item = getItem(); - if(item) - { - teleport_via_landmark(item->getAssetUUID()); - } - } - else if ("about" == action) - { - LLViewerInventoryItem* item = getItem(); - if(item) - { - LLSD key; - key["type"] = "landmark"; - key["id"] = item->getUUID(); - - LLSideTray::getInstance()->showPanel("panel_places", key); - } - } - else - { - LLItemBridge::performAction(folder, model, action); - } -} - -static bool open_landmark_callback(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - - LLUUID asset_id = notification["payload"]["asset_id"].asUUID(); - if (option == 0) - { - teleport_via_landmark(asset_id); - } - - return false; -} -static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFromLandmark", open_landmark_callback); - - -void LLLandmarkBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if( item ) - { - // Opening (double-clicking) a landmark immediately teleports, - // but warns you the first time. - // open_landmark(item); - LLSD payload; - payload["asset_id"] = item->getAssetUUID(); - LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); - } -*/ -} - - -// +=================================================+ -// | LLCallingCardObserver | -// +=================================================+ -void LLCallingCardObserver::changed(U32 mask) -{ - mBridgep->refreshFolderViewItem(); -} - -// +=================================================+ -// | LLCallingCardBridge | -// +=================================================+ - -LLCallingCardBridge::LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ) : - LLItemBridge(inventory, uuid) -{ - mObserver = new LLCallingCardObserver(this); - LLAvatarTracker::instance().addObserver(mObserver); -} - -LLCallingCardBridge::~LLCallingCardBridge() -{ - LLAvatarTracker::instance().removeObserver(mObserver); - delete mObserver; -} - -void LLCallingCardBridge::refreshFolderViewItem() -{ - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); - LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL; - if (itemp) - { - itemp->refresh(); - } -} - -// virtual -void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("begin_im" == action) - { - LLViewerInventoryItem *item = getItem(); - if (item && (item->getCreatorUUID() != gAgent.getID()) && - (!item->getCreatorUUID().isNull())) - { - std::string callingcard_name; - gCacheName->getFullName(item->getCreatorUUID(), callingcard_name); - gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID()); - } - } - else if ("lure" == action) - { - LLViewerInventoryItem *item = getItem(); - if (item && (item->getCreatorUUID() != gAgent.getID()) && - (!item->getCreatorUUID().isNull())) - { - LLAvatarActions::offerTeleport(item->getCreatorUUID()); - } - } - else LLItemBridge::performAction(folder, model, action); -} - -LLUIImagePtr LLCallingCardBridge::getIcon() const -{ - BOOL online = FALSE; - LLViewerInventoryItem* item = getItem(); - if(item) - { - online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()); - } - return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE); -} - -std::string LLCallingCardBridge::getLabelSuffix() const -{ - LLViewerInventoryItem* item = getItem(); - if( item && LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()) ) - { - return LLItemBridge::getLabelSuffix() + " (online)"; - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -void LLCallingCardBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if(item && !item->getCreatorUUID().isNull()) - { - LLAvatarActions::showProfile(item->getCreatorUUID()); - } -*/ -} - -void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - LLInventoryItem* item = getItem(); - BOOL good_card = (item - && (LLUUID::null != item->getCreatorUUID()) - && (item->getCreatorUUID() != gAgent.getID())); - BOOL user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID())); - items.push_back(std::string("Send Instant Message Separator")); - items.push_back(std::string("Send Instant Message")); - items.push_back(std::string("Offer Teleport...")); - items.push_back(std::string("Conference Chat")); - - if (!good_card) - { - disabled_items.push_back(std::string("Send Instant Message")); - } - if (!good_card || !user_online) - { - disabled_items.push_back(std::string("Offer Teleport...")); - disabled_items.push_back(std::string("Conference Chat")); - } - } - hide_context_entries(menu, items, disabled_items); -} - -BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data) -{ - LLViewerInventoryItem* item = getItem(); - BOOL rv = FALSE; - if(item) - { - // check the type - switch(cargo_type) - { - case DAD_TEXTURE: - case DAD_SOUND: - case DAD_LANDMARK: - case DAD_SCRIPT: - case DAD_CLOTHING: - case DAD_OBJECT: - case DAD_NOTECARD: - case DAD_BODYPART: - case DAD_ANIMATION: - case DAD_GESTURE: - { - LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data; - const LLPermissions& perm = inv_item->getPermissions(); - if(gInventory.getItem(inv_item->getUUID()) - && perm.allowOperationBy(PERM_TRANSFER, gAgent.getID())) - { - rv = TRUE; - if(drop) - { - LLToolDragAndDrop::giveInventory(item->getCreatorUUID(), - (LLInventoryItem*)cargo_data); - } - } - else - { - // It's not in the user's inventory (it's probably in - // an object's contents), so disallow dragging it here. - // You can't give something you don't yet have. - rv = FALSE; - } - break; - } - case DAD_CATEGORY: - { - LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data; - if( gInventory.getCategory( inv_cat->getUUID() ) ) - { - rv = TRUE; - if(drop) - { - LLToolDragAndDrop::giveInventoryCategory( - item->getCreatorUUID(), - inv_cat); - } - } - else - { - // It's not in the user's inventory (it's probably in - // an object's contents), so disallow dragging it here. - // You can't give something you don't yet have. - rv = FALSE; - } - break; - } - default: - break; - } - } - return rv; -} - -BOOL LLCallingCardBridge::removeItem() -{ - if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem())) - { - LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID()); - return FALSE; - } - else - { - return LLItemBridge::removeItem(); - } -} -// +=================================================+ -// | LLNotecardBridge | -// +=================================================+ - -LLUIImagePtr LLNotecardBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE); -} - -void LLNotecardBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } - -/* - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES); - } -*/ -} - - -// +=================================================+ -// | LLGestureBridge | -// +=================================================+ - -LLUIImagePtr LLGestureBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE); -} - -LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const -{ - if( LLGestureManager::instance().isGestureActive(mUUID) ) - { - return LLFontGL::BOLD; - } - else - { - return LLFontGL::NORMAL; - } -} - -std::string LLGestureBridge::getLabelSuffix() const -{ - if( LLGestureManager::instance().isGestureActive(mUUID) ) - { - return LLItemBridge::getLabelSuffix() + " (active)"; - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -// virtual -void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("activate" == action) - { - LLGestureManager::instance().activateGesture(mUUID); - - LLViewerInventoryItem* item = gInventory.getItem(mUUID); - if (!item) return; - - // Since we just changed the suffix to indicate (active) - // the server doesn't need to know, just the viewer. - gInventory.updateItem(item); - gInventory.notifyObservers(); - } - else if ("deactivate" == action) - { - LLGestureManager::instance().deactivateGesture(mUUID); - - LLViewerInventoryItem* item = gInventory.getItem(mUUID); - if (!item) return; - - // Since we just changed the suffix to indicate (active) - // the server doesn't need to know, just the viewer. - gInventory.updateItem(item); - gInventory.notifyObservers(); - } - else LLItemBridge::performAction(folder, model, action); -} - -void LLGestureBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null); - preview->setFocus(TRUE); - } -*/ -} - -BOOL LLGestureBridge::removeItem() -{ - // Force close the preview window, if it exists - LLGestureManager::instance().deactivateGesture(mUUID); - return LLItemBridge::removeItem(); -} - -void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLGestureBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - items.push_back(std::string("Gesture Separator")); - items.push_back(std::string("Activate")); - items.push_back(std::string("Deactivate")); - } - hide_context_entries(menu, items, disabled_items); -} - -// +=================================================+ -// | LLAnimationBridge | -// +=================================================+ - -LLUIImagePtr LLAnimationBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE); -} - -void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - std::vector<std::string> items; - std::vector<std::string> disabled_items; - - lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Animation Open")); - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - } - - items.push_back(std::string("Animation Separator")); - items.push_back(std::string("Animation Play")); - items.push_back(std::string("Animation Audition")); - - hide_context_entries(menu, items, disabled_items); - -} - -// virtual -void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ((action == "playworld") || (action == "playlocal")) - { - if (getItem()) - { - LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE; - if ("playworld" == action) activate = LLPreviewAnim::PLAY; - if ("playlocal" == action) activate = LLPreviewAnim::AUDITION; - - LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID)); - if (preview) - { - preview->activate(activate); - } - } - } - else - { - LLItemBridge::performAction(folder, model, action); - } -} - -void LLAnimationBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } -/* - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); - } -*/ -} - -// +=================================================+ -// | LLObjectBridge | -// +=================================================+ - -// static -LLUUID LLObjectBridge::sContextMenuItemID; - -LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) : -LLItemBridge(inventory, uuid), mInvType(type) -{ - mAttachPt = (flags & 0xff); // low bye of inventory flags - - mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE; -} - -BOOL LLObjectBridge::isItemRemovable() -{ - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if(!avatar) return FALSE; - if(avatar->isWearingAttachment(mUUID)) return FALSE; - return LLInvFVBridge::isItemRemovable(); -} - -LLUIImagePtr LLObjectBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject ); -} - -LLInventoryObject* LLObjectBridge::getObject() const -{ - LLInventoryObject* object = NULL; - LLInventoryModel* model = getInventoryModel(); - if(model) - { - object = (LLInventoryObject*)model->getObject(mUUID); - } - return object; -} - -// virtual -void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("attach" == action) - { - LLUUID object_id = mUUID; - LLViewerInventoryItem* item; - item = (LLViewerInventoryItem*)gInventory.getItem(object_id); - if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID())) - { - rez_attachment(item, NULL); - } - else if(item && item->isComplete()) - { - // must be in library. copy it to our inventory and put it on. - LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - gFocusMgr.setKeyboardFocus(NULL); - } - else if ("detach" == action) - { - LLInventoryItem* item = gInventory.getItem(mUUID); - if(item) - { - gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); - gMessageSystem->sendReliable( gAgent.getRegion()->getHost()); - } - // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = - gObjectList.findObject(item->getUUID()); - if (found_obj) - { - LLSelectMgr::getInstance()->remove(found_obj); - } - else - { - llwarns << "object not found - ignoring" << llendl; - } - } - else LLItemBridge::performAction(folder, model, action); -} - -void LLObjectBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } - - LLSD key; - key["id"] = mUUID; - LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); - - /* - LLFloaterReg::showInstance("properties", mUUID); - */ -} - -LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const -{ - U8 font = LLFontGL::NORMAL; - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( avatar && avatar->isWearingAttachment( mUUID ) ) - { - font |= LLFontGL::BOLD; - } - - LLInventoryItem* item = getItem(); - if (item && item->getIsLinkType()) - { - font |= LLFontGL::ITALIC; - } - - return (LLFontGL::StyleFlags)font; -} - -std::string LLObjectBridge::getLabelSuffix() const -{ - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( avatar && avatar->isWearingAttachment( mUUID ) ) - { - std::string attachment_point_name = avatar->getAttachedPointName(mUUID); - LLStringUtil::toLower(attachment_point_name); - - LLStringUtil::format_map_t args; - args["[ATTACHMENT_POINT]"] = attachment_point_name.c_str(); - return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args); - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment) -{ - LLSD payload; - payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link. - - S32 attach_pt = 0; - if (gAgent.getAvatarObject() && attachment) - { - for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin(); - iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter) - { - if (iter->second == attachment) - { - attach_pt = iter->first; - break; - } - } - } - - payload["attachment_point"] = attach_pt; - -#if !ENABLE_MULTIATTACHMENTS - if (attachment && attachment->getNumObjects() > 0) - { - LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez); - } - else -#endif - { - LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/); - } -} - -bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response) -{ - LLVOAvatar *avatarp = gAgent.getAvatarObject(); - - if (!avatarp->canAttachMoreObjects()) - { - LLSD args; - args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS); - LLNotifications::instance().add("MaxAttachmentsOnOutfit", args); - return false; - } - - S32 option = LLNotification::getSelectedOption(notification, response); - if (option == 0/*YES*/) - { - LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID()); - - if (itemp) - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID()); - msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner()); - U8 attachment_pt = notification["payload"]["attachment_point"].asInteger(); -#if ENABLE_MULTIATTACHMENTS - attachment_pt |= ATTACHMENT_ADD; -#endif - msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt); - pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions()); - msg->addStringFast(_PREHASH_Name, itemp->getName()); - msg->addStringFast(_PREHASH_Description, itemp->getDescription()); - msg->sendReliable(gAgent.getRegion()->getHost()); - } - } - return false; -} -static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_replace_attachment_rez); - -void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - std::vector<std::string> items; - std::vector<std::string> disabled_items; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - LLInventoryItem* item = getItem(); - if (item && item->getIsLinkType()) - { - items.push_back(std::string("Goto Link")); - } - - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - LLObjectBridge::sContextMenuItemID = mUUID; - - if(item) - { - LLVOAvatarSelf* avatarp = gAgent.getAvatarObject(); - if( !avatarp ) - { - return; - } - - if( avatarp->isWearingAttachment( mUUID ) ) - { - items.push_back(std::string("Detach From Yourself")); - } - else - if( !isInTrash() && !isLinkedObjectInTrash() ) - { - items.push_back(std::string("Attach Separator")); - items.push_back(std::string("Object Wear")); - items.push_back(std::string("Attach To")); - items.push_back(std::string("Attach To HUD")); - // commented out for DEV-32347 - //items.push_back(std::string("Restore to Last Position")); - - if (!avatarp->canAttachMoreObjects()) - { - disabled_items.push_back(std::string("Object Wear")); - disabled_items.push_back(std::string("Attach To")); - disabled_items.push_back(std::string("Attach To HUD")); - } - LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE); - LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE); - LLVOAvatar *avatarp = gAgent.getAvatarObject(); - if (attach_menu - && (attach_menu->getChildCount() == 0) - && attach_hud_menu - && (attach_hud_menu->getChildCount() == 0) - && avatarp) - { - for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); - iter != avatarp->mAttachmentPoints.end(); ) - { - LLVOAvatar::attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; - LLMenuItemCallGL::Params p; - std::string submenu_name = attachment->getName(); - if (LLTrans::getString(submenu_name) != "") - { - p.name = (" ")+LLTrans::getString(submenu_name)+" "; - } - else - { - p.name = submenu_name; - } - LLSD cbparams; - cbparams["index"] = curiter->first; - cbparams["label"] = attachment->getName(); - p.on_click.function_name = "Inventory.AttachObject"; - p.on_click.parameter = LLSD(attachment->getName()); - p.on_enable.function_name = "Attachment.Label"; - p.on_enable.parameter = cbparams; - LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu; - LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent); - } - } - } - } - } - hide_context_entries(menu, items, disabled_items); -} - -BOOL LLObjectBridge::renameItem(const std::string& new_name) -{ - if(!isItemRenameable()) - return FALSE; - LLPreview::dirty(mUUID); - LLInventoryModel* model = getInventoryModel(); - if(!model) - return FALSE; - LLViewerInventoryItem* item = getItem(); - if(item && (item->getName() != new_name)) - { - LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); - new_item->rename(new_name); - buildDisplayName(new_item, mDisplayName); - new_item->updateServer(FALSE); - model->updateItem(new_item); - - model->notifyObservers(); - - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if( avatar ) - { - LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() ); - if( obj ) - { - LLSelectMgr::getInstance()->deselectAll(); - LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE ); - LLSelectMgr::getInstance()->selectionSetObjectName( new_name ); - LLSelectMgr::getInstance()->deselectAll(); - } - } - } - // return FALSE because we either notified observers (& therefore - // rebuilt) or we didn't update. - return FALSE; -} - -// +=================================================+ -// | LLLSLTextBridge | -// +=================================================+ - -LLUIImagePtr LLLSLTextBridge::getIcon() const -{ - return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE); -} - -void LLLSLTextBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } - /* - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES); - } - */ -} - -// +=================================================+ -// | LLWearableBridge | -// +=================================================+ - -// *NOTE: hack to get from avatar inventory to avatar -void wear_inventory_item_on_avatar( LLInventoryItem* item ) -{ - if(item) - { - lldebugs << "wear_inventory_item_on_avatar( " << item->getName() - << " )" << llendl; - - LLAppearanceManager::wearItem(item); - } -} - -void wear_add_inventory_item_on_avatar( LLInventoryItem* item ) -{ - if(item) - { - lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName() - << " )" << llendl; - - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - LLWearableBridge::onWearAddOnAvatarArrived, - new LLUUID(item->getUUID())); - } -} - -void remove_inventory_category_from_avatar( LLInventoryCategory* category ) -{ - if(!category) return; - lldebugs << "remove_inventory_category_from_avatar( " << category->getName() - << " )" << llendl; - - - if( gFloaterCustomize ) - { - gFloaterCustomize->askToSaveIfDirty( - boost::bind(remove_inventory_category_from_avatar_step2, _1, category->getUUID())); - } - else - { - remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() ); - } -} - -struct OnRemoveStruct -{ - LLUUID mUUID; - OnRemoveStruct(const LLUUID& uuid): - mUUID(uuid) - { - } -}; - -void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id) -{ - - // Find all the wearables that are in the category's subtree. - lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl; - if(proceed) - { - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - LLFindWearables is_wearable; - gInventory.collectDescendentsIf(category_id, - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_wearable); - S32 i; - S32 wearable_count = item_array.count(); - - LLInventoryModel::cat_array_t obj_cat_array; - LLInventoryModel::item_array_t obj_item_array; - LLIsType is_object( LLAssetType::AT_OBJECT ); - gInventory.collectDescendentsIf(category_id, - obj_cat_array, - obj_item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_object); - S32 obj_count = obj_item_array.count(); - - // Find all gestures in this folder - LLInventoryModel::cat_array_t gest_cat_array; - LLInventoryModel::item_array_t gest_item_array; - LLIsType is_gesture( LLAssetType::AT_GESTURE ); - gInventory.collectDescendentsIf(category_id, - gest_cat_array, - gest_item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_gesture); - S32 gest_count = gest_item_array.count(); - - if (wearable_count > 0) //Loop through wearables. If worn, remove. - { - for(i = 0; i < wearable_count; ++i) - { - if( gAgentWearables.isWearingItem (item_array.get(i)->getUUID()) ) - { - LLWearableList::instance().getAsset(item_array.get(i)->getAssetUUID(), - item_array.get(i)->getName(), - item_array.get(i)->getType(), - LLWearableBridge::onRemoveFromAvatarArrived, - new OnRemoveStruct(item_array.get(i)->getUUID())); - - } - } - } - - - if (obj_count > 0) - { - for(i = 0; i < obj_count; ++i) - { - gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item_array.get(i)->getUUID() ); - - gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); - - // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID()); - if (found_obj) - { - LLSelectMgr::getInstance()->remove(found_obj); - } - else - { - llwarns << "object not found, ignoring" << llendl; - } - } - } - - if (gest_count > 0) - { - for(i = 0; i < gest_count; ++i) - { - if ( LLGestureManager::instance().isGestureActive( gest_item_array.get(i)->getUUID()) ) - { - LLGestureManager::instance().deactivateGesture( gest_item_array.get(i)->getUUID() ); - gInventory.updateItem( gest_item_array.get(i) ); - gInventory.notifyObservers(); - } - - } - } - } -} - -BOOL LLWearableBridge::renameItem(const std::string& new_name) -{ - if( gAgentWearables.isWearingItem( mUUID ) ) - { - gAgentWearables.setWearableName( mUUID, new_name ); - } - return LLItemBridge::renameItem(new_name); -} - -BOOL LLWearableBridge::isItemRemovable() -{ - if (gAgentWearables.isWearingItem(mUUID)) return FALSE; - return LLInvFVBridge::isItemRemovable(); -} - -std::string LLWearableBridge::getLabelSuffix() const -{ - if( gAgentWearables.isWearingItem( mUUID ) ) - { - return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn"); - } - else - { - return LLItemBridge::getLabelSuffix(); - } -} - -LLUIImagePtr LLWearableBridge::getIcon() const -{ - return get_item_icon(mAssetType, mInvType, mWearableType, FALSE); -} - -// virtual -void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("wear" == action) - { - wearOnAvatar(); - } - else if ("wear_add" == action) - { - wearAddOnAvatar(); - } - else if ("edit" == action) - { - editOnAvatar(); - return; - } - else if ("take_off" == action) - { - if(gAgentWearables.isWearingItem(mUUID)) - { - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - LLWearableBridge::onRemoveFromAvatarArrived, - new OnRemoveStruct(mUUID)); - } - } - } - else LLItemBridge::performAction(folder, model, action); -} - -void LLWearableBridge::openItem() -{ - LLViewerInventoryItem* item = getItem(); - - if (item) - { - LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel()); - } - /* - if( isInTrash() ) - { - LLNotifications::instance().add("CannotWearTrash"); - } - else if(isAgentInventory()) - { - if( !gAgentWearables.isWearingItem( mUUID ) ) - { - wearOnAvatar(); - } - } - else - { - // must be in the inventory library. copy it to our inventory - // and put it on right away. - LLViewerInventoryItem* item = getItem(); - if(item && item->isComplete()) - { - LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else if(item) - { - // *TODO: We should fetch the item details, and then do - // the operation above. - LLNotifications::instance().add("CannotWearInfoNotComplete"); - } - } - */ -} - -void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - lldebugs << "LLWearableBridge::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere - BOOL no_open = ((flags & SUPPRESS_OPEN_ITEM) == SUPPRESS_OPEN_ITEM); - - // If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976 - LLViewerInventoryItem* item = getItem(); - if( !no_open && item ) - { - no_open = (item->getType() == LLAssetType::AT_CLOTHING) || - (item->getType() == LLAssetType::AT_BODYPART); - } - if (!no_open) - { - items.push_back(std::string("Open")); - } - - if (item && item->getIsLinkType()) - { - items.push_back(std::string("Goto Link")); - } - - items.push_back(std::string("Properties")); - - getClipboardEntries(true, items, disabled_items, flags); - - items.push_back(std::string("Wearable Separator")); - - items.push_back(std::string("Wearable Wear")); - items.push_back(std::string("Wearable Add")); - items.push_back(std::string("Wearable Edit")); - - if ((flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Wearable Edit")); - } - // Don't allow items to be worn if their baseobj is in the trash. - if (isLinkedObjectInTrash()) - { - disabled_items.push_back(std::string("Wearable Wear")); - disabled_items.push_back(std::string("Wearable Add")); - disabled_items.push_back(std::string("Wearable Edit")); - } - - // Disable wear and take off based on whether the item is worn. - if(item) - { - switch (item->getType()) - { - case LLAssetType::AT_CLOTHING: - items.push_back(std::string("Take Off")); - case LLAssetType::AT_BODYPART: - if (gAgentWearables.isWearingItem(item->getUUID())) - { - disabled_items.push_back(std::string("Wearable Wear")); - disabled_items.push_back(std::string("Wearable Add")); - } - else - { - disabled_items.push_back(std::string("Take Off")); - } - break; - default: - break; - } - } - } - hide_context_entries(menu, items, disabled_items); -} - -// Called from menus -// static -BOOL LLWearableBridge::canWearOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return FALSE; - if(!self->isAgentInventory()) - { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem(); - if(!item || !item->isComplete()) return FALSE; - } - return (!gAgentWearables.isWearingItem(self->mUUID)); -} - -// Called from menus -// static -void LLWearableBridge::onWearOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return; - self->wearOnAvatar(); -} - -void LLWearableBridge::wearOnAvatar() -{ - // Don't wear anything until initial wearables are loaded, can - // destroy clothing items. - if (!gAgentWearables.areWearablesLoaded()) - { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); - return; - } - - LLViewerInventoryItem* item = getItem(); - if(item) - { - if(!isAgentInventory()) - { - LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else - { - wear_inventory_item_on_avatar(item); - } - } -} - -void LLWearableBridge::wearAddOnAvatar() -{ - // Don't wear anything until initial wearables are loaded, can - // destroy clothing items. - if (!gAgentWearables.areWearablesLoaded()) - { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); - return; - } - - LLViewerInventoryItem* item = getItem(); - if(item) - { - if(!isAgentInventory()) - { - LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else - { - wear_add_inventory_item_on_avatar(item); - } - } -} - -// static -void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata ) -{ - LLUUID* item_id = (LLUUID*) userdata; - if(wearable) - { - LLViewerInventoryItem* item = NULL; - item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); - if(item) - { - if(item->getAssetUUID() == wearable->getAssetID()) - { - gAgentWearables.setWearableItem(item, wearable); - gInventory.notifyObservers(); - //self->getFolderItem()->refreshFromRoot(); - } - else - { - llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl; - } - } - } - delete item_id; -} - -// static -// BAP remove the "add" code path once everything is fully COF-ified. -void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata ) -{ - LLUUID* item_id = (LLUUID*) userdata; - if(wearable) - { - LLViewerInventoryItem* item = NULL; - item = (LLViewerInventoryItem*)gInventory.getItem(*item_id); - if(item) - { - if(item->getAssetUUID() == wearable->getAssetID()) - { - bool do_append = true; - gAgentWearables.setWearableItem(item, wearable, do_append); - gInventory.notifyObservers(); - //self->getFolderItem()->refreshFromRoot(); - } - else - { - llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl; - } - } - } - delete item_id; -} - -// static -BOOL LLWearableBridge::canEditOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return FALSE; - - return (gAgentWearables.isWearingItem(self->mUUID)); -} - -// static -void LLWearableBridge::onEditOnAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(self) - { - self->editOnAvatar(); - } -} - -void LLWearableBridge::editOnAvatar() -{ - const LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID); - if( wearable ) - { - // Set the tab to the right wearable. - if (gFloaterCustomize) - gFloaterCustomize->setCurrentWearableType( wearable->getType() ); - - if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() ) - { - // Start Avatar Customization - gAgent.changeCameraToCustomizeAvatar(); - } - } -} - -// static -BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if( self && (LLAssetType::AT_BODYPART != self->mAssetType) ) - { - return gAgentWearables.isWearingItem( self->mUUID ); - } - return FALSE; -} - -// static -void LLWearableBridge::onRemoveFromAvatar(void* user_data) -{ - LLWearableBridge* self = (LLWearableBridge*)user_data; - if(!self) return; - if(gAgentWearables.isWearingItem(self->mUUID)) - { - LLViewerInventoryItem* item = self->getItem(); - if (item) - { - LLUUID parent_id = item->getParentUUID(); - LLWearableList::instance().getAsset(item->getAssetUUID(), - item->getName(), - item->getType(), - onRemoveFromAvatarArrived, - new OnRemoveStruct(LLUUID(self->mUUID))); - } - } -} - -// static -void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable, - void* userdata) -{ - OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata; - const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID); - if(wearable) - { - if( gAgentWearables.isWearingItem( item_id ) ) - { - EWearableType type = wearable->getType(); - - if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&& - //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) ) - { - // MULTI_WEARABLE: FIXME HACK - always remove all - bool do_remove_all = false; - gAgentWearables.removeWearable( type, do_remove_all, 0 ); - } - } - } - - // Find and remove this item from the COF. - LLInventoryModel::item_array_t items = gInventory.collectLinkedItems(item_id, LLAppearanceManager::getCOF()); - llassert(items.size() == 1); // Should always have one and only one item linked to this in the COF. - for (LLInventoryModel::item_array_t::const_iterator iter = items.begin(); - iter != items.end(); - ++iter) - { - const LLViewerInventoryItem *linked_item = (*iter); - const LLUUID &item_id = linked_item->getUUID(); - gInventory.purgeObject(item_id); - } - gInventory.notifyObservers(); - - delete on_remove_struct; -} - -LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type, - const LLUUID& uuid,LLInventoryModel* model) -{ - LLInvFVBridgeAction* action = NULL; - switch(asset_type) - { - case LLAssetType::AT_TEXTURE: - action = new LLTextureBridgeAction(uuid,model); - break; - - case LLAssetType::AT_SOUND: - action = new LLSoundBridgeAction(uuid,model); - break; - - case LLAssetType::AT_LANDMARK: - action = new LLLandmarkBridgeAction(uuid,model); - break; - - case LLAssetType::AT_CALLINGCARD: - action = new LLCallingCardBridgeAction(uuid,model); - break; - - case LLAssetType::AT_OBJECT: - action = new LLObjectBridgeAction(uuid,model); - break; - - case LLAssetType::AT_NOTECARD: - action = new LLNotecardBridgeAction(uuid,model); - break; - - case LLAssetType::AT_ANIMATION: - action = new LLAnimationBridgeAction(uuid,model); - break; - - case LLAssetType::AT_GESTURE: - action = new LLGestureBridgeAction(uuid,model); - break; - - case LLAssetType::AT_LSL_TEXT: - action = new LLLSLTextBridgeAction(uuid,model); - break; - - case LLAssetType::AT_CLOTHING: - case LLAssetType::AT_BODYPART: - action = new LLWearableBridgeAction(uuid,model); - - break; - - default: - break; - } - return action; -} - -//static -void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type, - const LLUUID& uuid,LLInventoryModel* model) -{ - LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); - if(action) - { - action->doIt(); - delete action; - } -} - -//static -void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model) -{ - LLAssetType::EType asset_type = model->getItem(uuid)->getType(); - LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); - if(action) - { - action->doIt(); - delete action; - } -} - -LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const -{ - if(mModel) - return (LLViewerInventoryItem*)mModel->getItem(mUUID); - return NULL; -} - -//virtual -void LLTextureBridgeAction::doIt() -{ - if (getItem()) - { - LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - -//virtual -void LLSoundBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if(item) - { - LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - - -//virtual -void LLLandmarkBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if( item ) - { - // Opening (double-clicking) a landmark immediately teleports, - // but warns you the first time. - LLSD payload; - payload["asset_id"] = item->getAssetUUID(); - LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); - } - - LLInvFVBridgeAction::doIt(); -} - - -//virtual -void LLCallingCardBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if(item && item->getCreatorUUID().notNull()) - { - LLAvatarActions::showProfile(item->getCreatorUUID()); - } - - LLInvFVBridgeAction::doIt(); -} - -//virtual -void -LLNotecardBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - -//virtual -void LLGestureBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null); - preview->setFocus(TRUE); - } - - LLInvFVBridgeAction::doIt(); -} - -//virtual -void LLAnimationBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - - -//virtual -void LLObjectBridgeAction::doIt() -{ - LLFloaterReg::showInstance("properties", mUUID); - - LLInvFVBridgeAction::doIt(); -} - - -//virtual -void LLLSLTextBridgeAction::doIt() -{ - LLViewerInventoryItem* item = getItem(); - if (item) - { - LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES); - } - - LLInvFVBridgeAction::doIt(); -} - - -BOOL LLWearableBridgeAction::isInTrash() const -{ - if(!mModel) return FALSE; - const LLUUID trash_id = mModel->findCategoryUUIDForType(LLFolderType::FT_TRASH); - return mModel->isObjectDescendentOf(mUUID, trash_id); -} - -BOOL LLWearableBridgeAction::isAgentInventory() const -{ - if(!mModel) return FALSE; - if(gInventory.getRootFolderID() == mUUID) return TRUE; - return mModel->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()); -} - -void LLWearableBridgeAction::wearOnAvatar() -{ - // Don't wear anything until initial wearables are loaded, can - // destroy clothing items. - if (!gAgentWearables.areWearablesLoaded()) - { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); - return; - } - - LLViewerInventoryItem* item = getItem(); - if(item) - { - if(!isAgentInventory()) - { - LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else - { - wear_inventory_item_on_avatar(item); - } - } -} - -//virtual -void LLWearableBridgeAction::doIt() -{ - if(isInTrash()) - { - LLNotifications::instance().add("CannotWearTrash"); - } - else if(isAgentInventory()) - { - if(!gAgentWearables.isWearingItem(mUUID)) - { - wearOnAvatar(); - } - } - else - { - // must be in the inventory library. copy it to our inventory - // and put it on right away. - LLViewerInventoryItem* item = getItem(); - if(item && item->isComplete()) - { - LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback(); - copy_inventory_item( - gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - else if(item) - { - // *TODO: We should fetch the item details, and then do - // the operation above. - LLNotifications::instance().add("CannotWearInfoNotComplete"); - } - } - - LLInvFVBridgeAction::doIt(); -} - -// +=================================================+ -// | LLLinkItemBridge | -// +=================================================+ -// For broken links - -std::string LLLinkItemBridge::sPrefix("Link: "); - - -LLUIImagePtr LLLinkItemBridge::getIcon() const -{ - if (LLViewerInventoryItem *item = getItem()) - { - return get_item_icon(item->getActualType(), LLInventoryType::IT_NONE, 0, FALSE); - } - return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE); -} - -void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - // *TODO: Translate - lldebugs << "LLLink::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Delete")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Delete")); - } - } - hide_context_entries(menu, items, disabled_items); -} - - -// +=================================================+ -// | LLLinkBridge | -// +=================================================+ -// For broken links. - -std::string LLLinkFolderBridge::sPrefix("Link: "); - - -LLUIImagePtr LLLinkFolderBridge::getIcon() const -{ - LLFolderType::EType preferred_type = LLFolderType::FT_NONE; - if (LLViewerInventoryItem *item = getItem()) - { - if (const LLViewerInventoryCategory* cat = item->getLinkedCategory()) - { - preferred_type = cat->getPreferredType(); - } - } - return LLFolderBridge::getIcon(preferred_type); -} - -void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) -{ - // *TODO: Translate - lldebugs << "LLLink::buildContextMenu()" << llendl; - std::vector<std::string> items; - std::vector<std::string> disabled_items; - - if(isInTrash()) - { - items.push_back(std::string("Purge Item")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Purge Item")); - } - - items.push_back(std::string("Restore Item")); - } - else - { - items.push_back(std::string("Goto Link")); - items.push_back(std::string("Delete")); - if (!isItemRemovable()) - { - disabled_items.push_back(std::string("Delete")); - } - } - hide_context_entries(menu, items, disabled_items); -} - -void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action) -{ - if ("goto" == action) - { - gotoItem(folder); - return; - } - LLItemBridge::performAction(folder,model,action); -} - -void LLLinkFolderBridge::gotoItem(LLFolderView *folder) -{ - const LLUUID &cat_uuid = getFolderID(); - if (!cat_uuid.isNull()) - { - if (LLFolderViewItem *base_folder = folder->getItemByID(cat_uuid)) - { - if (LLInventoryModel* model = getInventoryModel()) - { - model->fetchDescendentsOf(cat_uuid); - } - base_folder->setOpen(TRUE); - folder->setSelectionFromRoot(base_folder,TRUE); - folder->scrollToShowSelection(); - } - } -} - -const LLUUID &LLLinkFolderBridge::getFolderID() const -{ - if (LLViewerInventoryItem *link_item = getItem()) - { - if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory()) - { - const LLUUID& cat_uuid = cat->getUUID(); - return cat_uuid; - } - } - return LLUUID::null; -} +/**
+ * @file llinventorybridge.cpp
+ * @brief Implementation of the Inventory-Folder-View-Bridge classes.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include <utility> // for std::pair<>
+
+#include "llfloaterinventory.h"
+#include "llinventorybridge.h"
+
+#include "message.h"
+
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "llcallingcard.h"
+#include "llcheckboxctrl.h" // for radio buttons
+#include "llfloaterreg.h"
+#include "llradiogroup.h"
+#include "llspinctrl.h"
+#include "lltextbox.h"
+#include "llui.h"
+
+#include "llviewercontrol.h"
+#include "llfirstuse.h"
+#include "llfoldertype.h"
+#include "llfloaterchat.h"
+#include "llfloatercustomize.h"
+#include "llfloaterproperties.h"
+#include "llfloaterworldmap.h"
+#include "llfocusmgr.h"
+#include "llfolderview.h"
+#include "llfriendcard.h"
+#include "llavataractions.h"
+#include "llgesturemgr.h"
+#include "lliconctrl.h"
+#include "llinventoryfunctions.h"
+#include "llinventorymodel.h"
+#include "llinventorypanel.h"
+#include "llinventoryclipboard.h"
+#include "lllineeditor.h"
+#include "llmenugl.h"
+#include "llpreviewanim.h"
+#include "llpreviewgesture.h"
+#include "llpreviewnotecard.h"
+#include "llpreviewscript.h"
+#include "llpreviewsound.h"
+#include "llpreviewtexture.h"
+#include "llresmgr.h"
+#include "llscrollcontainer.h"
+#include "llimview.h"
+#include "lltooldraganddrop.h"
+#include "llviewerfoldertype.h"
+#include "llviewertexturelist.h"
+#include "llviewerinventory.h"
+#include "llviewerobjectlist.h"
+#include "llviewerwindow.h"
+#include "llvoavatar.h"
+#include "llwearable.h"
+#include "llwearablelist.h"
+#include "llviewerassettype.h"
+#include "llviewermessage.h"
+#include "llviewerregion.h"
+#include "llvoavatarself.h"
+#include "lltabcontainer.h"
+#include "lluictrlfactory.h"
+#include "llselectmgr.h"
+#include "llsidetray.h"
+#include "llfloateropenobject.h"
+#include "lltrans.h"
+#include "llappearancemgr.h"
+#include "llimfloater.h"
+
+using namespace LLOldEvents;
+
+// Helpers
+// bug in busy count inc/dec right now, logic is complex... do we really need it?
+void inc_busy_count()
+{
+// gViewerWindow->getWindow()->incBusyCount();
+// check balance of these calls if this code is changed to ever actually
+// *do* something!
+}
+void dec_busy_count()
+{
+// gViewerWindow->getWindow()->decBusyCount();
+// check balance of these calls if this code is changed to ever actually
+// *do* something!
+}
+
+// Function declarations
+void wear_add_inventory_item_on_avatar(LLInventoryItem* item);
+void remove_inventory_category_from_avatar(LLInventoryCategory* category);
+void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id);
+bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*);
+bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response);
+
+std::string ICON_NAME[ICON_NAME_COUNT] =
+{
+ "Inv_Texture",
+ "Inv_Sound",
+ "Inv_CallingCard",
+ "Inv_CallingCard",
+ "Inv_Landmark",
+ "Inv_Landmark",
+ "Inv_Script",
+ "Inv_Clothing",
+ "Inv_Object",
+ "Inv_Object",
+ "Inv_Notecard",
+ "Inv_Skin",
+ "Inv_Snapshot",
+
+ "Inv_BodyShape",
+ "Inv_Skin",
+ "Inv_Hair",
+ "Inv_Eye",
+ "Inv_Shirt",
+ "Inv_Pants",
+ "Inv_Shoe",
+ "Inv_Socks",
+ "Inv_Jacket",
+ "Inv_Gloves",
+ "Inv_Undershirt",
+ "Inv_Underpants",
+ "Inv_Skirt",
+ "Inv_Alpha",
+ "Inv_Tattoo",
+
+ "Inv_Animation",
+ "Inv_Gesture",
+
+ "inv_item_linkitem.tga",
+ "inv_item_linkfolder.tga"
+};
+
+
+// +=================================================+
+// | LLInventoryPanelObserver |
+// +=================================================+
+void LLInventoryPanelObserver::changed(U32 mask)
+{
+ mIP->modelChanged(mask);
+}
+
+
+// +=================================================+
+// | LLInvFVBridge |
+// +=================================================+
+
+LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
+mUUID(uuid), mInvType(LLInventoryType::IT_NONE)
+{
+ mInventoryPanel = inventory->getHandle();
+}
+
+const std::string& LLInvFVBridge::getName() const
+{
+ LLInventoryObject* obj = getInventoryObject();
+ if(obj)
+ {
+ return obj->getName();
+ }
+ return LLStringUtil::null;
+}
+
+const std::string& LLInvFVBridge::getDisplayName() const
+{
+ return getName();
+}
+
+// Folders have full perms
+PermissionMask LLInvFVBridge::getPermissionMask() const
+{
+
+ return PERM_ALL;
+}
+
+// virtual
+LLFolderType::EType LLInvFVBridge::getPreferredType() const
+{
+ return LLFolderType::FT_NONE;
+}
+
+
+// Folders don't have creation dates.
+time_t LLInvFVBridge::getCreationDate() const
+{
+ return 0;
+}
+
+// Can be destoryed (or moved to trash)
+BOOL LLInvFVBridge::isItemRemovable()
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ if(model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// Sends an update to all link items that point to the base item.
+void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string& new_name)
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+
+ LLInventoryItem* itemp = model->getItem(mUUID);
+ if (!itemp) return;
+
+ if (itemp->getIsLinkType())
+ {
+ return;
+ }
+
+ LLInventoryModel::item_array_t item_array = model->collectLinkedItems(item_id);
+ for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
+ iter != item_array.end();
+ iter++)
+ {
+ LLViewerInventoryItem *linked_item = (*iter);
+ if (linked_item->getUUID() == item_id) continue;
+
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(linked_item);
+ new_item->rename(new_name);
+ new_item->updateServer(FALSE);
+ model->updateItem(new_item);
+ // model->addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID());
+ }
+ model->notifyObservers();
+}
+
+// Can be moved to another folder
+BOOL LLInvFVBridge::isItemMovable() const
+{
+ return TRUE;
+}
+
+/*virtual*/
+/**
+ * @brief Adds this item into clipboard storage
+ */
+void LLInvFVBridge::cutToClipboard()
+{
+ if(isItemMovable())
+ {
+ LLInventoryClipboard::instance().cut(mUUID);
+ }
+}
+// *TODO: make sure this does the right thing
+void LLInvFVBridge::showProperties()
+{
+ LLSD key;
+ key["id"] = mUUID;
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
+
+ // Disable old properties floater; this is replaced by the sidepanel.
+ /*
+ LLFloaterReg::showInstance("properties", mUUID);
+ */
+}
+
+void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch)
+{
+ // Deactivate gestures when moving them into Trash
+ LLInvFVBridge* bridge;
+ LLInventoryModel* model = getInventoryModel();
+ LLViewerInventoryItem* item = NULL;
+ LLViewerInventoryCategory* cat = NULL;
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ 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());
+ if (item)
+ {
+ if(LLAssetType::AT_GESTURE == item->getType())
+ {
+ LLGestureManager::instance().deactivateGesture(item->getUUID());
+ }
+ }
+ }
+ for(i = 0; i < count; ++i)
+ {
+ bridge = (LLInvFVBridge*)(batch.get(i));
+ if(!bridge || !bridge->isItemRemovable()) continue;
+ cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
+ if (cat)
+ {
+ gInventory.collectDescendents( cat->getUUID(), descendent_categories, descendent_items, FALSE );
+ for (j=0; j<descendent_items.count(); j++)
+ {
+ if(LLAssetType::AT_GESTURE == descendent_items[j]->getType())
+ {
+ LLGestureManager::instance().deactivateGesture(descendent_items[j]->getUUID());
+ }
+ }
+ }
+ }
+ removeBatchNoCheck(batch);
+}
+
+void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch)
+{
+ // this method moves a bunch of items and folders to the trash. As
+ // per design guidelines for the inventory model, the message is
+ // built and the accounting is performed first. After all of that,
+ // we call LLInventoryModel::moveObject() to move everything
+ // around.
+ LLInvFVBridge* bridge;
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ LLMessageSystem* msg = gMessageSystem;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ LLViewerInventoryItem* item = NULL;
+ LLViewerInventoryCategory* cat = NULL;
+ std::vector<LLUUID> move_ids;
+ LLInventoryModel::update_map_t update;
+ bool start_new_message = true;
+ S32 count = batch.count();
+ S32 i;
+ for(i = 0; i < count; ++i)
+ {
+ bridge = (LLInvFVBridge*)(batch.get(i));
+ if(!bridge || !bridge->isItemRemovable()) continue;
+ item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
+ if(item)
+ {
+ if(item->getParentUUID() == trash_id) continue;
+ move_ids.push_back(item->getUUID());
+ LLPreview::hide(item->getUUID());
+ --update[item->getParentUUID()];
+ ++update[trash_id];
+ if(start_new_message)
+ {
+ start_new_message = false;
+ msg->newMessageFast(_PREHASH_MoveInventoryItem);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addBOOLFast(_PREHASH_Stamp, TRUE);
+ }
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ msg->addUUIDFast(_PREHASH_ItemID, item->getUUID());
+ msg->addUUIDFast(_PREHASH_FolderID, trash_id);
+ msg->addString("NewName", NULL);
+ if(msg->isSendFullFast(_PREHASH_InventoryData))
+ {
+ start_new_message = true;
+ gAgent.sendReliableMessage();
+ gInventory.accountForUpdate(update);
+ update.clear();
+ }
+ }
+ }
+ if(!start_new_message)
+ {
+ start_new_message = true;
+ gAgent.sendReliableMessage();
+ gInventory.accountForUpdate(update);
+ update.clear();
+ }
+ for(i = 0; i < count; ++i)
+ {
+ bridge = (LLInvFVBridge*)(batch.get(i));
+ if(!bridge || !bridge->isItemRemovable()) continue;
+ cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
+ if(cat)
+ {
+ if(cat->getParentUUID() == trash_id) continue;
+ move_ids.push_back(cat->getUUID());
+ --update[cat->getParentUUID()];
+ ++update[trash_id];
+ if(start_new_message)
+ {
+ start_new_message = false;
+ msg->newMessageFast(_PREHASH_MoveInventoryFolder);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addBOOL("Stamp", TRUE);
+ }
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID());
+ msg->addUUIDFast(_PREHASH_ParentID, trash_id);
+ if(msg->isSendFullFast(_PREHASH_InventoryData))
+ {
+ start_new_message = true;
+ gAgent.sendReliableMessage();
+ gInventory.accountForUpdate(update);
+ update.clear();
+ }
+ }
+ }
+ if(!start_new_message)
+ {
+ gAgent.sendReliableMessage();
+ gInventory.accountForUpdate(update);
+ }
+
+ // move everything.
+ std::vector<LLUUID>::iterator it = move_ids.begin();
+ std::vector<LLUUID>::iterator end = move_ids.end();
+ for(; it != end; ++it)
+ {
+ gInventory.moveObject((*it), trash_id);
+ }
+
+ // notify inventory observers.
+ model->notifyObservers();
+}
+
+BOOL LLInvFVBridge::isClipboardPasteable() const
+{
+ if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+ {
+ return FALSE;
+ }
+ LLInventoryModel* model = getInventoryModel();
+ if (!model)
+ {
+ return FALSE;
+ }
+
+ const LLUUID &agent_id = gAgent.getID();
+
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLUUID &item_id = objects.get(i);
+
+ // Can't paste folders
+ const LLInventoryCategory *cat = model->getCategory(item_id);
+ if (cat)
+ {
+ return FALSE;
+ }
+
+ const LLInventoryItem *item = model->getItem(item_id);
+ if (item)
+ {
+ if (!item->getPermissions().allowCopyBy(agent_id))
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
+{
+ if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+ {
+ return FALSE;
+ }
+ const LLInventoryModel* model = getInventoryModel();
+ if (!model)
+ {
+ return FALSE;
+ }
+
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLInventoryItem *item = model->getItem(objects.get(i));
+ if (item)
+ {
+ if (!LLAssetType::lookupCanLink(item->getActualType()))
+ {
+ return FALSE;
+ }
+ }
+ const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i));
+ if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+void hide_context_entries(LLMenuGL& menu,
+ const std::vector<std::string> &entries_to_show,
+ const std::vector<std::string> &disabled_entries)
+{
+ const LLView::child_list_t *list = menu.getChildList();
+
+ LLView::child_list_t::const_iterator itor;
+ for (itor = list->begin(); itor != list->end(); ++itor)
+ {
+ std::string name = (*itor)->getName();
+
+ // descend into split menus:
+ LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(*itor);
+ if ((name == "More") && branchp)
+ {
+ hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries);
+ }
+
+
+ bool found = false;
+ std::vector<std::string>::const_iterator itor2;
+ for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2)
+ {
+ if (*itor2 == name)
+ {
+ found = true;
+ }
+ }
+ if (!found)
+ {
+ (*itor)->setVisible(FALSE);
+ }
+ else
+ {
+ for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
+ {
+ if (*itor2 == name)
+ {
+ (*itor)->setEnabled(FALSE);
+ }
+ }
+ }
+ }
+}
+
+// Helper for commonly-used entries
+void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
+ std::vector<std::string> &items,
+ std::vector<std::string> &disabled_items, U32 flags)
+{
+ items.push_back(std::string("Rename"));
+ if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Rename"));
+ }
+
+ if (show_asset_id)
+ {
+ items.push_back(std::string("Copy Asset UUID"));
+ if ( (! ( isItemPermissive() || gAgent.isGodlike() ) )
+ || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Copy Asset UUID"));
+ }
+ }
+
+ items.push_back(std::string("Copy Separator"));
+
+ items.push_back(std::string("Copy"));
+ if (!isItemCopyable())
+ {
+ disabled_items.push_back(std::string("Copy"));
+ }
+
+ items.push_back(std::string("Paste"));
+ if (!isClipboardPasteable() || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Paste"));
+ }
+
+ items.push_back(std::string("Paste As Link"));
+ if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Paste As Link"));
+ }
+ items.push_back(std::string("Paste Separator"));
+
+ items.push_back(std::string("Delete"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
+
+ // If multiple items are selected, disable properties (if it exists).
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Properties"));
+ }
+}
+
+void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("PurgeItem"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("PurgeItem"));
+ }
+ items.push_back(std::string("RestoreItem"));
+ }
+ else
+ {
+ items.push_back(std::string("Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// *TODO: remove this
+BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
+{
+ BOOL rv = FALSE;
+
+ const LLInventoryObject* obj = getInventoryObject();
+
+ if(obj)
+ {
+ *type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType());
+ if(*type == DAD_NONE)
+ {
+ return FALSE;
+ }
+
+ *id = obj->getUUID();
+ //object_ids.put(obj->getUUID());
+
+ if (*type == DAD_CATEGORY)
+ {
+ gInventory.startBackgroundFetch(obj->getUUID());
+ }
+
+ rv = TRUE;
+ }
+
+ return rv;
+}
+
+LLInventoryObject* LLInvFVBridge::getInventoryObject() const
+{
+ LLInventoryObject* obj = NULL;
+ LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ obj = (LLInventoryObject*)model->getObject(mUUID);
+ }
+ return obj;
+}
+
+LLInventoryModel* LLInvFVBridge::getInventoryModel() const
+{
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ return panel ? panel->getModel() : NULL;
+}
+
+BOOL LLInvFVBridge::isInTrash() const
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ return model->isObjectDescendentOf(mUUID, trash_id);
+}
+
+BOOL LLInvFVBridge::isLinkedObjectInTrash() const
+{
+ if (isInTrash()) return TRUE;
+
+ const LLInventoryObject *obj = getInventoryObject();
+ if (obj && obj->getIsLinkType())
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id);
+ }
+ return FALSE;
+}
+
+BOOL LLInvFVBridge::isAgentInventory() const
+{
+ const LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ if(gInventory.getRootFolderID() == mUUID) return TRUE;
+ return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
+}
+
+BOOL LLInvFVBridge::isCOFFolder() const
+{
+ const LLInventoryModel* model = getInventoryModel();
+ if(!model) return TRUE;
+ const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL LLInvFVBridge::isItemPermissive() const
+{
+ return FALSE;
+}
+
+// static
+void LLInvFVBridge::changeItemParent(LLInventoryModel* model,
+ LLViewerInventoryItem* item,
+ const LLUUID& new_parent,
+ BOOL restamp)
+{
+ if(item->getParentUUID() != new_parent)
+ {
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
+
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->setParent(new_parent);
+ new_item->updateParentOnServer(restamp);
+ model->updateItem(new_item);
+ model->notifyObservers();
+ }
+}
+
+// static
+void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model,
+ LLViewerInventoryCategory* cat,
+ const LLUUID& new_parent,
+ BOOL restamp)
+{
+ if(cat->getParentUUID() != new_parent)
+ {
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
+
+ LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
+ new_cat->setParent(new_parent);
+ new_cat->updateParentOnServer(restamp);
+ model->updateCategory(new_cat);
+ model->notifyObservers();
+ }
+}
+
+
+const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type)
+{
+ const std::string rv= LLInventoryType::lookup(inv_type);
+ if(rv.empty())
+ {
+ return std::string("<invalid>");
+ }
+ return rv;
+}
+
+LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags)
+{
+ LLInvFVBridge* new_listener = NULL;
+ switch(asset_type)
+ {
+ case LLAssetType::AT_TEXTURE:
+ if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLTextureBridge(inventory, uuid, inv_type);
+ break;
+
+ case LLAssetType::AT_SOUND:
+ if(!(inv_type == LLInventoryType::IT_SOUND))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLSoundBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_LANDMARK:
+ if(!(inv_type == LLInventoryType::IT_LANDMARK))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLLandmarkBridge(inventory, uuid, flags);
+ break;
+
+ case LLAssetType::AT_CALLINGCARD:
+ if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLCallingCardBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_SCRIPT:
+ if(!(inv_type == LLInventoryType::IT_LSL))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLScriptBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_OBJECT:
+ if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags);
+ break;
+
+ case LLAssetType::AT_NOTECARD:
+ if(!(inv_type == LLInventoryType::IT_NOTECARD))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLNotecardBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_ANIMATION:
+ if(!(inv_type == LLInventoryType::IT_ANIMATION))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLAnimationBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_GESTURE:
+ if(!(inv_type == LLInventoryType::IT_GESTURE))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLGestureBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_LSL_TEXT:
+ if(!(inv_type == LLInventoryType::IT_LSL))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLLSLTextBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ if(!(inv_type == LLInventoryType::IT_WEARABLE))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags);
+ break;
+ case LLAssetType::AT_CATEGORY:
+ case LLAssetType::AT_ROOT_CATEGORY:
+ if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
+ {
+ // Create a link folder handler instead.
+ new_listener = new LLLinkFolderBridge(inventory, uuid);
+ break;
+ }
+ new_listener = new LLFolderBridge(inventory, uuid);
+ break;
+ case LLAssetType::AT_LINK:
+ // Only should happen for broken links.
+ new_listener = new LLLinkItemBridge(inventory, uuid);
+ break;
+ case LLAssetType::AT_LINK_FOLDER:
+ // Only should happen for broken links.
+ new_listener = new LLLinkItemBridge(inventory, uuid);
+ break;
+ default:
+ llinfos << "Unhandled asset type (llassetstorage.h): "
+ << (S32)asset_type << llendl;
+ break;
+ }
+
+ if (new_listener)
+ {
+ new_listener->mInvType = inv_type;
+ }
+
+ return new_listener;
+}
+
+void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
+{
+ LLInventoryCategory* cat = model->getCategory(uuid);
+ if (cat)
+ {
+ model->purgeDescendentsOf(uuid);
+ model->notifyObservers();
+ }
+ LLInventoryObject* obj = model->getObject(uuid);
+ if (obj)
+ {
+ model->purgeObject(uuid);
+ model->notifyObservers();
+ }
+}
+
+// +=================================================+
+// | InventoryFVBridgeBuilder |
+// +=================================================+
+LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags /* = 0x00 */) const
+{
+ return LLInvFVBridge::createBridge(asset_type,
+ actual_asset_type,
+ inv_type,
+ inventory,
+ uuid,
+ flags);
+}
+
+// +=================================================+
+// | LLItemBridge |
+// +=================================================+
+
+void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("goto" == action)
+ {
+ gotoItem(folder);
+ }
+ if ("open" == action)
+ {
+ openItem();
+ return;
+ }
+ else if ("properties" == action)
+ {
+ showProperties();
+ return;
+ }
+ else if ("purge" == action)
+ {
+ purgeItem(model, mUUID);
+ return;
+ }
+ else if ("restoreToWorld" == action)
+ {
+ restoreToWorld();
+ return;
+ }
+ else if ("restore" == action)
+ {
+ restoreItem();
+ return;
+ }
+ else if ("copy_uuid" == action)
+ {
+ // Single item only
+ LLInventoryItem* item = model->getItem(mUUID);
+ if(!item) return;
+ LLUUID asset_id = item->getAssetUUID();
+ std::string buffer;
+ asset_id.toString(buffer);
+
+ gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer));
+ return;
+ }
+ else if ("copy" == action)
+ {
+ copyToClipboard();
+ return;
+ }
+ else if ("paste" == action)
+ {
+ // Single item only
+ LLInventoryItem* itemp = model->getItem(mUUID);
+ if (!itemp) return;
+
+ LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
+ if (!folder_view_itemp) return;
+
+ folder_view_itemp->getListener()->pasteFromClipboard();
+ return;
+ }
+ else if ("paste_link" == action)
+ {
+ // Single item only
+ LLInventoryItem* itemp = model->getItem(mUUID);
+ if (!itemp) return;
+
+ LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
+ if (!folder_view_itemp) return;
+
+ folder_view_itemp->getListener()->pasteLinkFromClipboard();
+ return;
+ }
+}
+
+void LLItemBridge::selectItem()
+{
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
+ if(item && !item->isComplete())
+ {
+ item->fetchFromServer();
+ }
+}
+
+void LLItemBridge::restoreItem()
+{
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
+ if(item)
+ {
+ LLInventoryModel* model = getInventoryModel();
+ const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType()));
+ // do not restamp on restore.
+ LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE);
+ }
+}
+
+void LLItemBridge::restoreToWorld()
+{
+ LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)getItem();
+ if (itemp)
+ {
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessage("RezRestoreToWorld");
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ itemp->packMessage(msg);
+ msg->sendReliable(gAgent.getRegion()->getHost());
+ }
+
+ //Similar functionality to the drag and drop rez logic
+ BOOL remove_from_inventory = FALSE;
+
+ //remove local inventory copy, sim will deal with permissions and removing the item
+ //from the actual inventory if its a no-copy etc
+ if(!itemp->getPermissions().allowCopyBy(gAgent.getID()))
+ {
+ remove_from_inventory = TRUE;
+ }
+
+ // Check if it's in the trash. (again similar to the normal rez logic)
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id))
+ {
+ remove_from_inventory = TRUE;
+ }
+
+ if(remove_from_inventory)
+ {
+ gInventory.deleteObject(itemp->getUUID());
+ gInventory.notifyObservers();
+ }
+}
+
+void LLItemBridge::gotoItem(LLFolderView *folder)
+{
+ LLInventoryObject *obj = getInventoryObject();
+ if (obj && obj->getIsLinkType())
+ {
+ LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel();
+ if (active_panel)
+ {
+ active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO);
+ }
+ }
+}
+
+LLUIImagePtr LLItemBridge::getIcon() const
+{
+ return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]);
+}
+
+PermissionMask LLItemBridge::getPermissionMask() const
+{
+ LLViewerInventoryItem* item = getItem();
+ PermissionMask perm_mask = 0;
+ if(item)
+ {
+ BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
+ BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
+ BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
+ gAgent.getID());
+
+ if (copy) perm_mask |= PERM_COPY;
+ if (mod) perm_mask |= PERM_MODIFY;
+ if (xfer) perm_mask |= PERM_TRANSFER;
+
+ }
+ return perm_mask;
+}
+
+const std::string& LLItemBridge::getDisplayName() const
+{
+ if(mDisplayName.empty())
+ {
+ buildDisplayName(getItem(), mDisplayName);
+ }
+ return mDisplayName;
+}
+
+void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
+{
+ if(item)
+ {
+ name.assign(item->getName());
+ }
+ else
+ {
+ name.assign(LLStringUtil::null);
+ }
+}
+
+LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
+{
+ U8 font = LLFontGL::NORMAL;
+
+ if( gAgentWearables.isWearingItem( mUUID ) )
+ {
+ // llinfos << "BOLD" << llendl;
+ font |= LLFontGL::BOLD;
+ }
+
+ const LLViewerInventoryItem* item = getItem();
+ if (item && item->getIsLinkType())
+ {
+ font |= LLFontGL::ITALIC;
+ }
+ return (LLFontGL::StyleFlags)font;
+}
+
+std::string LLItemBridge::getLabelSuffix() const
+{
+ // String table is loaded before login screen and inventory items are
+ // loaded after login, so LLTrans should be ready.
+ static std::string NO_COPY =LLTrans::getString("no_copy");
+ static std::string NO_MOD = LLTrans::getString("no_modify");
+ static std::string NO_XFER = LLTrans::getString("no_transfer");
+ static std::string LINK = LLTrans::getString("link");
+ static std::string BROKEN_LINK = LLTrans::getString("broken_link");
+ std::string suffix;
+ LLInventoryItem* item = getItem();
+ if(item)
+ {
+ // it's a bit confusing to put nocopy/nomod/etc on calling cards.
+ if(LLAssetType::AT_CALLINGCARD != item->getType()
+ && item->getPermissions().getOwner() == gAgent.getID())
+ {
+ BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType());
+ if (broken_link) return BROKEN_LINK;
+
+ BOOL link = item->getIsLinkType();
+ if (link) return LINK;
+
+ BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
+ if (!copy)
+ {
+ suffix += NO_COPY;
+ }
+ BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
+ if (!mod)
+ {
+ suffix += NO_MOD;
+ }
+ BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
+ gAgent.getID());
+ if (!xfer)
+ {
+ suffix += NO_XFER;
+ }
+ }
+ }
+ return suffix;
+}
+
+time_t LLItemBridge::getCreationDate() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ return item->getCreationDate();
+ }
+ return 0;
+}
+
+
+BOOL LLItemBridge::isItemRenameable() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ // (For now) Don't allow calling card rename since that may confuse users as to
+ // what the calling card points to.
+ if (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD)
+ {
+ return FALSE;
+ }
+ return (item->getPermissions().allowModifyBy(gAgent.getID()));
+ }
+ return FALSE;
+}
+
+BOOL LLItemBridge::renameItem(const std::string& new_name)
+{
+ if(!isItemRenameable())
+ return FALSE;
+ LLPreview::dirty(mUUID);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ return FALSE;
+ LLViewerInventoryItem* item = getItem();
+ if(item && (item->getName() != new_name))
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->rename(new_name);
+ buildDisplayName(new_item, mDisplayName);
+ new_item->updateServer(FALSE);
+ model->updateItem(new_item);
+
+ model->notifyObservers();
+ }
+ // return FALSE because we either notified observers (& therefore
+ // rebuilt) or we didn't update.
+ return FALSE;
+}
+
+
+BOOL LLItemBridge::removeItem()
+{
+ if(!isItemRemovable())
+ {
+ return FALSE;
+ }
+ // move it to the trash
+ LLPreview::hide(mUUID, TRUE);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ LLViewerInventoryItem* item = getItem();
+
+ // if item is not already in trash
+ if(item && !model->isObjectDescendentOf(mUUID, trash_id))
+ {
+ // move to trash, and restamp
+ LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE);
+ // delete was successful
+ return TRUE;
+ }
+ else
+ {
+ // tried to delete already item in trash (should purge?)
+ return FALSE;
+ }
+}
+
+BOOL LLItemBridge::isItemCopyable() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ // can't copy worn objects. DEV-15183
+ LLVOAvatarSelf *avatarp = gAgent.getAvatarObject();
+ if( !avatarp )
+ {
+ return FALSE;
+ }
+
+ if(avatarp->isWearingAttachment(mUUID))
+ {
+ return FALSE;
+ }
+
+ // All items can be copied, not all can be pasted.
+ // The only time an item can't be copied is if it's a link
+ // return (item->getPermissions().allowCopyBy(gAgent.getID()));
+ if (item->getIsLinkType())
+ {
+ return FALSE;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+BOOL LLItemBridge::copyToClipboard() const
+{
+ if(isItemCopyable())
+ {
+ LLInventoryClipboard::instance().add(mUUID);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+LLViewerInventoryItem* LLItemBridge::getItem() const
+{
+ LLViewerInventoryItem* item = NULL;
+ LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ item = (LLViewerInventoryItem*)model->getItem(mUUID);
+ }
+ return item;
+}
+
+BOOL LLItemBridge::isItemPermissive() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ U32 mask = item->getPermissions().getMaskBase();
+ if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+// +=================================================+
+// | LLFolderBridge |
+// +=================================================+
+
+LLFolderBridge* LLFolderBridge::sSelf=NULL;
+
+// Can be moved to another folder
+BOOL LLFolderBridge::isItemMovable() const
+{
+ LLInventoryObject* obj = getInventoryObject();
+ if(obj)
+ {
+ return (!LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType()));
+ }
+ return FALSE;
+}
+
+void LLFolderBridge::selectItem()
+{
+}
+
+
+// Can be destroyed (or moved to trash)
+BOOL LLFolderBridge::isItemRemovable()
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ {
+ return FALSE;
+ }
+
+ if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
+ {
+ return FALSE;
+ }
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( !avatar )
+ {
+ return FALSE;
+ }
+
+ LLInventoryCategory* category = model->getCategory(mUUID);
+ if( !category )
+ {
+ return FALSE;
+ }
+
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
+ {
+ return FALSE;
+ }
+
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
+
+ S32 i;
+ for( i = 0; i < descendent_categories.count(); i++ )
+ {
+ LLInventoryCategory* category = descendent_categories[i];
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
+ {
+ return FALSE;
+ }
+ }
+
+ for( i = 0; i < descendent_items.count(); i++ )
+ {
+ LLInventoryItem* item = descendent_items[i];
+ if( (item->getType() == LLAssetType::AT_CLOTHING) ||
+ (item->getType() == LLAssetType::AT_BODYPART) )
+ {
+ if(gAgentWearables.isWearingItem(item->getUUID()))
+ {
+ return FALSE;
+ }
+ }
+ else
+ if( item->getType() == LLAssetType::AT_OBJECT )
+ {
+ if(avatar->isWearingAttachment(item->getUUID()))
+ {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+BOOL LLFolderBridge::isUpToDate() const
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
+ if( !category )
+ {
+ return FALSE;
+ }
+
+ return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN;
+}
+
+BOOL LLFolderBridge::isItemCopyable() const
+{
+ return TRUE;
+}
+
+BOOL LLFolderBridge::copyToClipboard() const
+{
+ if(isItemCopyable())
+ {
+ LLInventoryClipboard::instance().add(mUUID);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL LLFolderBridge::isClipboardPasteable() const
+{
+ if ( ! LLInvFVBridge::isClipboardPasteable() )
+ return FALSE;
+
+ // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
+ if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) )
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if ( !model )
+ {
+ return FALSE;
+ }
+
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ const LLViewerInventoryCategory *current_cat = getCategory();
+
+ // Search for the direct descendent of current Friends subfolder among all pasted items,
+ // and return false if is found.
+ for(S32 i = objects.count() - 1; i >= 0; --i)
+ {
+ const LLUUID &obj_id = objects.get(i);
+ if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
+ {
+ return FALSE;
+ }
+ }
+
+ }
+ return TRUE;
+}
+
+BOOL LLFolderBridge::isClipboardPasteableAsLink() const
+{
+ // Check normal paste-as-link permissions
+ if (!LLInvFVBridge::isClipboardPasteableAsLink())
+ {
+ return FALSE;
+ }
+
+ const LLInventoryModel* model = getInventoryModel();
+ if (!model)
+ {
+ return FALSE;
+ }
+
+ const LLViewerInventoryCategory *current_cat = getCategory();
+ if (current_cat)
+ {
+ const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat );
+ const LLUUID ¤t_cat_id = current_cat->getUUID();
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLUUID &obj_id = objects.get(i);
+ const LLInventoryCategory *cat = model->getCategory(obj_id);
+ if (cat)
+ {
+ const LLUUID &cat_id = cat->getUUID();
+ // Don't allow recursive pasting
+ if ((cat_id == current_cat_id) ||
+ model->isObjectDescendentOf(current_cat_id, cat_id))
+ {
+ return FALSE;
+ }
+ }
+ // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
+ if ( is_in_friend_folder )
+ {
+ // If object is direct descendent of current Friends subfolder than return false.
+ // Note: We can't use 'const LLInventoryCategory *cat', because it may be null
+ // in case type of obj_id is LLInventoryItem.
+ if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
+ {
+ return FALSE;
+ }
+ }
+ }
+ }
+ return TRUE;
+
+}
+
+BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
+ BOOL drop)
+{
+ // This should never happen, but if an inventory item is incorrectly parented,
+ // the UI will get confused and pass in a NULL.
+ if(!inv_cat) return FALSE;
+
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if(!avatar) return FALSE;
+
+ // cannot drag categories into library
+ if(!isAgentInventory())
+ {
+ return FALSE;
+ }
+
+ // check to make sure source is agent inventory, and is represented there.
+ LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
+ BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL)
+ && (LLToolDragAndDrop::SOURCE_AGENT == source);
+
+ BOOL accept = FALSE;
+ S32 i;
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ if(is_agent_inventory)
+ {
+ const LLUUID& cat_id = inv_cat->getUUID();
+
+ // Is the destination the trash?
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ BOOL move_is_into_trash = (mUUID == trash_id)
+ || model->isObjectDescendentOf(mUUID, trash_id);
+ BOOL is_movable = (!LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType()));
+ const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+ if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ // BAP - restrictions?
+ is_movable = true;
+ }
+
+ if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE))
+ {
+ is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604
+ }
+
+ if( is_movable )
+ {
+ gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE );
+
+ for( i = 0; i < descendent_categories.count(); i++ )
+ {
+ LLInventoryCategory* category = descendent_categories[i];
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
+ {
+ // ...can't move "special folders" like Textures
+ is_movable = FALSE;
+ break;
+ }
+ }
+
+ if( is_movable )
+ {
+ if( move_is_into_trash )
+ {
+ for( i = 0; i < descendent_items.count(); i++ )
+ {
+ LLInventoryItem* item = descendent_items[i];
+ if( (item->getType() == LLAssetType::AT_CLOTHING) ||
+ (item->getType() == LLAssetType::AT_BODYPART) )
+ {
+ if( gAgentWearables.isWearingItem( item->getUUID() ) )
+ {
+ is_movable = FALSE; // It's generally movable, but not into the trash!
+ break;
+ }
+ }
+ else
+ if( item->getType() == LLAssetType::AT_OBJECT )
+ {
+ if( avatar->isWearingAttachment( item->getUUID() ) )
+ {
+ is_movable = FALSE; // It's generally movable, but not into the trash!
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ accept = is_movable
+ && (mUUID != cat_id) // Can't move a folder into itself
+ && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing
+ && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity
+ if(accept && drop)
+ {
+ // Look for any gestures and deactivate them
+ if (move_is_into_trash)
+ {
+ for (i = 0; i < descendent_items.count(); i++)
+ {
+ LLInventoryItem* item = descendent_items[i];
+ if (item->getType() == LLAssetType::AT_GESTURE
+ && LLGestureManager::instance().isGestureActive(item->getUUID()))
+ {
+ LLGestureManager::instance().deactivateGesture(item->getUUID());
+ }
+ }
+ }
+ // if target is an outfit or current outfit folder we use link
+ if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+#if SUPPORT_ENSEMBLES
+ // BAP - should skip if dup.
+ if (move_is_into_current_outfit)
+ {
+ LLAppearanceManager::wearEnsemble(inv_cat);
+ }
+ else
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_item(
+ gAgent.getID(),
+ inv_cat->getUUID(),
+ mUUID,
+ inv_cat->getName(),
+ LLAssetType::AT_LINK_FOLDER,
+ cb);
+ }
+#endif
+ }
+ else
+ {
+
+ // Reparent the folder and restamp children if it's moving
+ // into trash.
+ LLInvFVBridge::changeCategoryParent(
+ model,
+ (LLViewerInventoryCategory*)inv_cat,
+ mUUID,
+ move_is_into_trash);
+ }
+ }
+ }
+ else if(LLToolDragAndDrop::SOURCE_WORLD == source)
+ {
+ // content category has same ID as object itself
+ LLUUID object_id = inv_cat->getUUID();
+ LLUUID category_id = mUUID;
+ accept = move_inv_category_world_to_agent(object_id, category_id, drop);
+ }
+ return accept;
+}
+
+void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv)
+{
+ const char* dialog = NULL;
+ if (object->flagScripted())
+ {
+ dialog = "MoveInventoryFromScriptedObject";
+ }
+ else
+ {
+ dialog = "MoveInventoryFromObject";
+ }
+ LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+}
+
+// Move/copy all inventory items from the Contents folder of an in-world
+// object to the agent's inventory, inside a given category.
+BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
+ const LLUUID& category_id,
+ BOOL drop,
+ void (*callback)(S32, void*),
+ void* user_data)
+{
+ // Make sure the object exists. If we allowed dragging from
+ // anonymous objects, it would be possible to bypass
+ // permissions.
+ // content category has same ID as object itself
+ LLViewerObject* object = gObjectList.findObject(object_id);
+ if(!object)
+ {
+ llinfos << "Object not found for drop." << llendl;
+ return FALSE;
+ }
+
+ // this folder is coming from an object, as there is only one folder in an object, the root,
+ // we need to collect the entire contents and handle them as a group
+ InventoryObjectList inventory_objects;
+ object->getInventoryContents(inventory_objects);
+
+ if (inventory_objects.empty())
+ {
+ llinfos << "Object contents not found for drop." << llendl;
+ return FALSE;
+ }
+
+ BOOL accept = TRUE;
+ BOOL is_move = FALSE;
+
+ // coming from a task. Need to figure out if the person can
+ // move/copy this item.
+ InventoryObjectList::iterator it = inventory_objects.begin();
+ InventoryObjectList::iterator end = inventory_objects.end();
+ for ( ; it != end; ++it)
+ {
+ // coming from a task. Need to figure out if the person can
+ // move/copy this item.
+ LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions());
+ if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
+ && perm.allowTransferTo(gAgent.getID())))
+// || gAgent.isGodlike())
+ {
+ accept = TRUE;
+ }
+ else if(object->permYouOwner())
+ {
+ // If the object cannot be copied, but the object the
+ // inventory is owned by the agent, then the item can be
+ // moved from the task to agent inventory.
+ is_move = TRUE;
+ accept = TRUE;
+ }
+ else
+ {
+ accept = FALSE;
+ break;
+ }
+ }
+
+ if(drop && accept)
+ {
+ it = inventory_objects.begin();
+ InventoryObjectList::iterator first_it = inventory_objects.begin();
+ LLMoveInv* move_inv = new LLMoveInv;
+ move_inv->mObjectID = object_id;
+ move_inv->mCategoryID = category_id;
+ move_inv->mCallback = callback;
+ move_inv->mUserData = user_data;
+
+ for ( ; it != end; ++it)
+ {
+ two_uuids_t two(category_id, (*it)->getUUID());
+ move_inv->mMoveList.push_back(two);
+ }
+
+ if(is_move)
+ {
+ // Callback called from within here.
+ warn_move_inventory(object, move_inv);
+ }
+ else
+ {
+ LLNotification::Params params("MoveInventoryFromObject");
+ params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+ LLNotifications::instance().forceResponse(params, 0);
+ }
+ }
+ return accept;
+}
+
+bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item)
+{
+ // Valid COF items are:
+ // - links to wearables (body parts or clothing)
+ // - links to attachments
+ // - links to gestures
+ // - links to ensemble folders
+ LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); // BAP - safe?
+ if (linked_item)
+ {
+ LLAssetType::EType type = linked_item->getType();
+ return (type == LLAssetType::AT_CLOTHING ||
+ type == LLAssetType::AT_BODYPART ||
+ type == LLAssetType::AT_GESTURE ||
+ type == LLAssetType::AT_OBJECT);
+ }
+ else
+ {
+ LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe?
+ // BAP remove AT_NONE support after ensembles are fully working?
+ return (linked_category &&
+ ((linked_category->getPreferredType() == LLFolderType::FT_NONE) ||
+ (LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType()))));
+ }
+}
+
+
+bool LLFindWearables::operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item)
+{
+ if(item)
+ {
+ if((item->getType() == LLAssetType::AT_CLOTHING)
+ || (item->getType() == LLAssetType::AT_BODYPART))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+
+//Used by LLFolderBridge as callback for directory recursion.
+class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver
+{
+public:
+ LLRightClickInventoryFetchObserver() :
+ mCopyItems(false)
+ { };
+ LLRightClickInventoryFetchObserver(const LLUUID& cat_id, bool copy_items) :
+ mCatID(cat_id),
+ mCopyItems(copy_items)
+ { };
+ virtual void done()
+ {
+ // we've downloaded all the items, so repaint the dialog
+ LLFolderBridge::staticFolderOptionsMenu();
+
+ gInventory.removeObserver(this);
+ delete this;
+ }
+
+
+protected:
+ LLUUID mCatID;
+ bool mCopyItems;
+
+};
+
+//Used by LLFolderBridge as callback for directory recursion.
+class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
+{
+public:
+ LLRightClickInventoryFetchDescendentsObserver(bool copy_items) : mCopyItems(copy_items) {}
+ ~LLRightClickInventoryFetchDescendentsObserver() {}
+ virtual void done();
+protected:
+ bool mCopyItems;
+};
+
+void LLRightClickInventoryFetchDescendentsObserver::done()
+{
+ // Avoid passing a NULL-ref as mCompleteFolders.front() down to
+ // gInventory.collectDescendents()
+ if( mCompleteFolders.empty() )
+ {
+ llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl;
+ dec_busy_count();
+ gInventory.removeObserver(this);
+ delete this;
+ return;
+ }
+
+ // What we do here is get the complete information on the items in
+ // the library, and set up an observer that will wait for that to
+ // happen.
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ gInventory.collectDescendents(mCompleteFolders.front(),
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ S32 count = item_array.count();
+#if 0 // HACK/TODO: Why?
+ // This early causes a giant menu to get produced, and doesn't seem to be needed.
+ if(!count)
+ {
+ llwarns << "Nothing fetched in category " << mCompleteFolders.front()
+ << llendl;
+ dec_busy_count();
+ gInventory.removeObserver(this);
+ delete this;
+ return;
+ }
+#endif
+
+ LLRightClickInventoryFetchObserver* outfit;
+ outfit = new LLRightClickInventoryFetchObserver(mCompleteFolders.front(), mCopyItems);
+ LLInventoryFetchObserver::item_ref_t ids;
+ for(S32 i = 0; i < count; ++i)
+ {
+ ids.push_back(item_array.get(i)->getUUID());
+ }
+
+ // clean up, and remove this as an observer since the call to the
+ // outfit could notify observers and throw us into an infinite
+ // loop.
+ dec_busy_count();
+ gInventory.removeObserver(this);
+ delete this;
+
+ // increment busy count and either tell the inventory to check &
+ // call done, or add this object to the inventory for observation.
+ inc_busy_count();
+
+ // do the fetch
+ outfit->fetchItems(ids);
+ outfit->done(); //Not interested in waiting and this will be right 99% of the time.
+//Uncomment the following code for laggy Inventory UI.
+/* if(outfit->isEverythingComplete())
+ {
+ // everything is already here - call done.
+ outfit->done();
+ }
+ else
+ {
+ // it's all on it's way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(outfit);
+ }*/
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryWearObserver
+//
+// Observer for "copy and wear" operation to support knowing
+// when the all of the contents have been added to inventory.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLInventoryCopyAndWearObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) :mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {}
+ virtual ~LLInventoryCopyAndWearObserver() {}
+ virtual void changed(U32 mask);
+
+protected:
+ LLUUID mCatID;
+ int mContentsCount;
+ BOOL mFolderAdded;
+};
+
+
+
+void LLInventoryCopyAndWearObserver::changed(U32 mask)
+{
+ if((mask & (LLInventoryObserver::ADD)) != 0)
+ {
+ if (!mFolderAdded)
+ {
+ const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
+
+ std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+ std::set<LLUUID>::const_iterator id_end = changed_items.end();
+ for (;id_it != id_end; ++id_it)
+ {
+ if ((*id_it) == mCatID)
+ {
+ mFolderAdded = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (mFolderAdded)
+ {
+ LLViewerInventoryCategory* category = gInventory.getCategory(mCatID);
+
+ if (NULL == category)
+ {
+ llwarns << "gInventory.getCategory(" << mCatID
+ << ") was NULL" << llendl;
+ }
+ else
+ {
+ if (category->getDescendentCount() ==
+ mContentsCount)
+ {
+ gInventory.removeObserver(this);
+ LLAppearanceManager::wearInventoryCategory(category, FALSE, TRUE);
+ delete this;
+ }
+ }
+ }
+
+ }
+}
+
+
+
+void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("open" == action)
+ {
+ openItem();
+ return;
+ }
+ else if ("paste" == action)
+ {
+ pasteFromClipboard();
+ return;
+ }
+ else if ("paste_link" == action)
+ {
+ pasteLinkFromClipboard();
+ return;
+ }
+ else if ("properties" == action)
+ {
+ showProperties();
+ return;
+ }
+ else if ("replaceoutfit" == action)
+ {
+ modifyOutfit(FALSE);
+ return;
+ }
+#if SUPPORT_ENSEMBLES
+ else if ("wearasensemble" == action)
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(!cat) return;
+ LLAppearanceManager::wearEnsemble(cat,true);
+ return;
+ }
+#endif
+ else if ("addtooutfit" == action)
+ {
+ modifyOutfit(TRUE);
+ return;
+ }
+ else if ("copy" == action)
+ {
+ copyToClipboard();
+ return;
+ }
+ else if ("removefromoutfit" == action)
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(!cat) return;
+
+ remove_inventory_category_from_avatar ( cat );
+ return;
+ }
+ else if ("purge" == action)
+ {
+ purgeItem(model, mUUID);
+ return;
+ }
+ else if ("restore" == action)
+ {
+ restoreItem();
+ return;
+ }
+}
+
+void LLFolderBridge::openItem()
+{
+ lldebugs << "LLFolderBridge::openItem()" << llendl;
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ bool fetching_inventory = model->fetchDescendentsOf(mUUID);
+ // Only change folder type if we have the folder contents.
+ if (!fetching_inventory)
+ {
+ // Disabling this for now, it's causing crash when new items are added to folders
+ // since folder type may change before new item item has finished processing.
+ // determineFolderType();
+ }
+}
+
+void LLFolderBridge::closeItem()
+{
+ determineFolderType();
+}
+
+void LLFolderBridge::determineFolderType()
+{
+ if (isUpToDate())
+ {
+ LLInventoryModel* model = getInventoryModel();
+ LLViewerInventoryCategory* category = model->getCategory(mUUID);
+ category->determineFolderType();
+ }
+}
+
+BOOL LLFolderBridge::isItemRenameable() const
+{
+ LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory();
+ if(cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())
+ && (cat->getOwnerID() == gAgent.getID()))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void LLFolderBridge::restoreItem()
+{
+ LLViewerInventoryCategory* cat;
+ cat = (LLViewerInventoryCategory*)getCategory();
+ if(cat)
+ {
+ LLInventoryModel* model = getInventoryModel();
+ const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType()));
+ // do not restamp children on restore
+ LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE);
+ }
+}
+
+LLFolderType::EType LLFolderBridge::getPreferredType() const
+{
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(cat)
+ {
+ preferred_type = cat->getPreferredType();
+ }
+
+ return preferred_type;
+}
+
+// Icons for folders are based on the preferred type
+LLUIImagePtr LLFolderBridge::getIcon() const
+{
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(cat)
+ {
+ preferred_type = cat->getPreferredType();
+ }
+ return getIcon(preferred_type);
+}
+
+LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type)
+{
+ // we only have one folder image now
+ return LLUI::getUIImage("Inv_FolderClosed");
+}
+
+BOOL LLFolderBridge::renameItem(const std::string& new_name)
+{
+ if(!isItemRenameable())
+ return FALSE;
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ return FALSE;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(cat && (cat->getName() != new_name))
+ {
+ LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
+ new_cat->rename(new_name);
+ new_cat->updateServer(FALSE);
+ model->updateCategory(new_cat);
+
+ model->notifyObservers();
+ }
+ // return FALSE because we either notified observers (& therefore
+ // rebuilt) or we didn't update.
+ return FALSE;
+}
+
+BOOL LLFolderBridge::removeItem()
+{
+ if(!isItemRemovable())
+ {
+ return FALSE;
+ }
+ // move it to the trash
+ LLPreview::hide(mUUID);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+
+ // Look for any gestures and deactivate them
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
+
+ S32 i;
+ for (i = 0; i < descendent_items.count(); i++)
+ {
+ LLInventoryItem* item = descendent_items[i];
+ if (item->getType() == LLAssetType::AT_GESTURE
+ && LLGestureManager::instance().isGestureActive(item->getUUID()))
+ {
+ LLGestureManager::instance().deactivateGesture(item->getUUID());
+ }
+ }
+
+ // go ahead and do the normal remove if no 'last calling
+ // cards' are being removed.
+ LLViewerInventoryCategory* cat = getCategory();
+ if(cat)
+ {
+ LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE);
+ }
+
+ return TRUE;
+}
+
+void LLFolderBridge::pasteFromClipboard()
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(model && isClipboardPasteable())
+ {
+ LLInventoryItem* item = NULL;
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ const LLUUID parent_id(mUUID);
+ for(S32 i = 0; i < count; i++)
+ {
+ item = model->getItem(objects.get(i));
+ if (item)
+ {
+ if(LLInventoryClipboard::instance().isCutMode())
+ {
+ // move_inventory_item() is not enough,
+ //we have to update inventory locally too
+ changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE);
+ }
+ else
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ parent_id,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ }
+ }
+ }
+}
+
+void LLFolderBridge::pasteLinkFromClipboard()
+{
+ const LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ LLUUID parent_id(mUUID);
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLUUID &object_id = objects.get(i);
+#if SUPPORT_ENSEMBLES
+ if (LLInventoryCategory *cat = model->getCategory(object_id))
+ {
+ link_inventory_item(
+ gAgent.getID(),
+ cat->getUUID(),
+ parent_id,
+ cat->getName(),
+ LLAssetType::AT_LINK_FOLDER,
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ else
+#endif
+ if (LLInventoryItem *item = model->getItem(object_id))
+ {
+ link_inventory_item(
+ gAgent.getID(),
+ item->getUUID(),
+ parent_id,
+ item->getName(),
+ LLAssetType::AT_LINK,
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ }
+ }
+}
+
+void LLFolderBridge::staticFolderOptionsMenu()
+{
+ if (!sSelf) return;
+ sSelf->folderOptionsMenu();
+}
+
+void LLFolderBridge::folderOptionsMenu()
+{
+ std::vector<std::string> disabled_items;
+
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+
+ const LLInventoryCategory* category = model->getCategory(mUUID);
+ LLFolderType::EType type = category->getPreferredType();
+ const bool is_default_folder = category && LLFolderType::lookupIsProtectedType(type);
+ // BAP change once we're no longer treating regular categories as ensembles.
+ const bool is_ensemble = category && (type == LLFolderType::FT_NONE ||
+ LLFolderType::lookupIsEnsembleType(type));
+
+ // calling card related functionality for folders.
+
+ // Only enable calling-card related options for non-default folders.
+ if (!is_default_folder)
+ {
+ LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
+ if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))
+ {
+ mItems.push_back(std::string("Calling Card Separator"));
+ mItems.push_back(std::string("Conference Chat Folder"));
+ mItems.push_back(std::string("IM All Contacts In Folder"));
+ }
+ }
+
+ // wearables related functionality for folders.
+ //is_wearable
+ LLFindWearables is_wearable;
+ LLIsType is_object( LLAssetType::AT_OBJECT );
+ LLIsType is_gesture( LLAssetType::AT_GESTURE );
+
+ if (mWearables ||
+ checkFolderForContentsOfType(model, is_wearable) ||
+ checkFolderForContentsOfType(model, is_object) ||
+ checkFolderForContentsOfType(model, is_gesture) )
+ {
+ mItems.push_back(std::string("Folder Wearables Separator"));
+
+ // Only enable add/replace outfit for non-default folders.
+ if (!is_default_folder)
+ {
+ mItems.push_back(std::string("Add To Outfit"));
+ mItems.push_back(std::string("Replace Outfit"));
+ }
+ if (is_ensemble)
+ {
+ mItems.push_back(std::string("Wear As Ensemble"));
+ }
+ mItems.push_back(std::string("Take Off Items"));
+ }
+ hide_context_entries(*mMenu, mItems, disabled_items);
+}
+
+BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ model->collectDescendentsIf(mUUID,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_type);
+ return ((item_array.count() > 0) ? TRUE : FALSE );
+}
+
+// Flags unused
+void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ mItems.clear();
+ mDisabledItems.clear();
+
+ lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;
+// std::vector<std::string> disabled_items;
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
+
+ mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point)
+ mDisabledItems.clear(); //adding code to clear out disabled members from previous
+ if (lost_and_found_id == mUUID)
+ {
+ // This is the lost+found folder.
+ mItems.push_back(std::string("Empty Lost And Found"));
+ }
+
+ if(trash_id == mUUID)
+ {
+ // This is the trash.
+ mItems.push_back(std::string("Empty Trash"));
+ }
+ else if(model->isObjectDescendentOf(mUUID, trash_id))
+ {
+ // This is a folder in the trash.
+ mItems.clear(); // clear any items that used to exist
+ mItems.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ mDisabledItems.push_back(std::string("Purge Item"));
+ }
+
+ mItems.push_back(std::string("Restore Item"));
+ }
+ else if(isAgentInventory()) // do not allow creating in library
+ {
+ LLViewerInventoryCategory *cat = getCategory();
+ // BAP removed protected check to re-enable standard ops in untyped folders.
+ // Not sure what the right thing is to do here.
+ if (!isCOFFolder() && cat /*&&
+ LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/)
+ {
+ // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
+ if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
+ mItems.push_back(std::string("New Folder"));
+ mItems.push_back(std::string("New Script"));
+ mItems.push_back(std::string("New Note"));
+ mItems.push_back(std::string("New Gesture"));
+ mItems.push_back(std::string("New Clothes"));
+ mItems.push_back(std::string("New Body Parts"));
+ mItems.push_back(std::string("Change Type"));
+
+ LLViewerInventoryCategory *cat = getCategory();
+ if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
+ {
+ mDisabledItems.push_back(std::string("Change Type"));
+ }
+
+ getClipboardEntries(false, mItems, mDisabledItems, flags);
+ }
+ else
+ {
+ // Want some but not all of the items from getClipboardEntries for outfits.
+ if (cat && cat->getPreferredType()==LLFolderType::FT_OUTFIT)
+ {
+ mItems.push_back(std::string("Rename"));
+ mItems.push_back(std::string("Delete"));
+ }
+ }
+
+ //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06
+ mCallingCards = mWearables = FALSE;
+
+ LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
+ if (checkFolderForContentsOfType(model, is_callingcard))
+ {
+ mCallingCards=TRUE;
+ }
+
+ LLFindWearables is_wearable;
+ LLIsType is_object( LLAssetType::AT_OBJECT );
+ LLIsType is_gesture( LLAssetType::AT_GESTURE );
+
+ if (checkFolderForContentsOfType(model, is_wearable) ||
+ checkFolderForContentsOfType(model, is_object) ||
+ checkFolderForContentsOfType(model, is_gesture) )
+ {
+ mWearables=TRUE;
+ }
+
+ mMenu = &menu;
+ sSelf = this;
+ LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE);
+
+ LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+ LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
+ if (category)
+ {
+ folders.push_back(category->getUUID());
+ }
+ fetch->fetchDescendents(folders);
+ inc_busy_count();
+ if(fetch->isEverythingComplete())
+ {
+ // everything is already here - call done.
+ fetch->done();
+ }
+ else
+ {
+ // it's all on it's way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(fetch);
+ }
+ }
+ else
+ {
+ mItems.push_back(std::string("--no options--"));
+ mDisabledItems.push_back(std::string("--no options--"));
+ }
+ hide_context_entries(menu, mItems, mDisabledItems);
+}
+
+BOOL LLFolderBridge::hasChildren() const
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ LLInventoryModel::EHasChildren has_children;
+ has_children = gInventory.categoryHasChildren(mUUID);
+ return has_children != LLInventoryModel::CHILDREN_NO;
+}
+
+BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data)
+{
+ //llinfos << "LLFolderBridge::dragOrDrop()" << llendl;
+ BOOL accept = FALSE;
+ switch(cargo_type)
+ {
+ case DAD_TEXTURE:
+ case DAD_SOUND:
+ case DAD_CALLINGCARD:
+ case DAD_LANDMARK:
+ case DAD_SCRIPT:
+ case DAD_OBJECT:
+ case DAD_NOTECARD:
+ case DAD_CLOTHING:
+ case DAD_BODYPART:
+ case DAD_ANIMATION:
+ case DAD_GESTURE:
+ case DAD_LINK:
+ accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
+ drop);
+ break;
+ case DAD_CATEGORY:
+ if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID))
+ {
+ accept = FALSE;
+ }
+ else
+ {
+ accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop);
+ }
+ break;
+ default:
+ break;
+ }
+ return accept;
+}
+
+LLViewerInventoryCategory* LLFolderBridge::getCategory() const
+{
+ LLViewerInventoryCategory* cat = NULL;
+ LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ cat = (LLViewerInventoryCategory*)model->getCategory(mUUID);
+ }
+ return cat;
+}
+
+
+// static
+void LLFolderBridge::pasteClipboard(void* user_data)
+{
+ LLFolderBridge* self = (LLFolderBridge*)user_data;
+ if(self) self->pasteFromClipboard();
+}
+
+void LLFolderBridge::createNewCategory(void* user_data)
+{
+ LLFolderBridge* bridge = (LLFolderBridge*)user_data;
+ if(!bridge) return;
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel.get());
+ if (!panel) return;
+ LLInventoryModel* model = panel->getModel();
+ if(!model) return;
+ LLUUID id;
+ id = model->createNewCategory(bridge->getUUID(),
+ LLFolderType::FT_NONE,
+ LLStringUtil::null);
+ model->notifyObservers();
+
+ // At this point, the bridge has probably been deleted, but the
+ // view is still there.
+ panel->setSelection(id, TAKE_FOCUS_YES);
+}
+
+void LLFolderBridge::createNewShirt(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHIRT);
+}
+
+void LLFolderBridge::createNewPants(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_PANTS);
+}
+
+void LLFolderBridge::createNewShoes(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHOES);
+}
+
+void LLFolderBridge::createNewSocks(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SOCKS);
+}
+
+void LLFolderBridge::createNewJacket(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_JACKET);
+}
+
+void LLFolderBridge::createNewSkirt(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIRT);
+}
+
+void LLFolderBridge::createNewGloves(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_GLOVES);
+}
+
+void LLFolderBridge::createNewUndershirt(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERSHIRT);
+}
+
+void LLFolderBridge::createNewUnderpants(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERPANTS);
+}
+
+void LLFolderBridge::createNewShape(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHAPE);
+}
+
+void LLFolderBridge::createNewSkin(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIN);
+}
+
+void LLFolderBridge::createNewHair(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_HAIR);
+}
+
+void LLFolderBridge::createNewEyes(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_EYES);
+}
+
+// static
+void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type)
+{
+ if(!bridge) return;
+ LLUUID parent_id = bridge->getUUID();
+ createWearable(parent_id, type);
+}
+
+// Separate function so can be called by global menu as well as right-click
+// menu.
+// static
+void LLFolderBridge::createWearable(const LLUUID &parent_id, EWearableType type)
+{
+ LLWearable* wearable = LLWearableList::instance().createNewWearable(type);
+ LLAssetType::EType asset_type = wearable->getAssetType();
+ LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
+ parent_id, wearable->getTransactionID(), wearable->getName(),
+ wearable->getDescription(), asset_type, inv_type, wearable->getType(),
+ wearable->getPermissions().getMaskNextOwner(),
+ LLPointer<LLInventoryCallback>(NULL));
+}
+
+void LLFolderBridge::modifyOutfit(BOOL append)
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(!cat) return;
+
+ // BAP - was:
+ // wear_inventory_category_on_avatar( cat, append );
+ LLAppearanceManager::wearInventoryCategory( cat, FALSE, append );
+}
+
+// helper stuff
+bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv)
+{
+ LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData;
+ LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID);
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
+ if(option == 0 && object)
+ {
+ if (cat_and_wear && cat_and_wear->mWear)
+ {
+ InventoryObjectList inventory_objects;
+ object->getInventoryContents(inventory_objects);
+ int contents_count = inventory_objects.size()-1; //subtract one for containing folder
+
+ LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count);
+ gInventory.addObserver(inventoryObserver);
+ }
+
+ two_uuids_list_t::iterator move_it;
+ for (move_it = move_inv->mMoveList.begin();
+ move_it != move_inv->mMoveList.end();
+ ++move_it)
+ {
+ object->moveInventory(move_it->first, move_it->second);
+ }
+
+ // update the UI.
+ dialog_refresh_all();
+ }
+
+ if (move_inv->mCallback)
+ {
+ move_inv->mCallback(option, move_inv->mUserData);
+ }
+
+ delete move_inv;
+ return false;
+}
+
+/*
+Next functions intended to reorder items in the inventory folder and save order on server
+Is now used for Favorites folder.
+
+*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel
+*/
+void saveItemsOrder(LLInventoryModel::item_array_t& items)
+{
+ int sortField = 0;
+
+ // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ LLViewerInventoryItem* item = *i;
+
+ item->setSortField(++sortField);
+ item->setComplete(TRUE);
+ item->updateServer(FALSE);
+
+ gInventory.updateItem(item);
+ }
+
+ gInventory.notifyObservers();
+}
+
+LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id)
+{
+ LLInventoryModel::item_array_t::iterator result = items.end();
+
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ if ((*i)->getUUID() == id)
+ {
+ result = i;
+ break;
+ }
+ }
+
+ return result;
+}
+
+void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId)
+{
+ LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId);
+ LLViewerInventoryItem* destItem = gInventory.getItem(destItemId);
+
+ items.erase(findItemByUUID(items, srcItem->getUUID()));
+ items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
+}
+
+BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
+ BOOL drop)
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+
+ // cannot drag into library
+ if(!isAgentInventory())
+ {
+ return FALSE;
+ }
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if(!avatar) return FALSE;
+
+ LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
+ BOOL accept = FALSE;
+ LLViewerObject* object = NULL;
+ if(LLToolDragAndDrop::SOURCE_AGENT == source)
+ {
+
+ BOOL is_movable = TRUE;
+ switch( inv_item->getActualType() )
+ {
+ case LLAssetType::AT_ROOT_CATEGORY:
+ is_movable = FALSE;
+ break;
+
+ case LLAssetType::AT_CATEGORY:
+ is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType());
+ break;
+ default:
+ break;
+ }
+
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
+ const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+
+ if(is_movable && move_is_into_trash)
+ {
+ switch(inv_item->getType())
+ {
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID());
+ break;
+
+ case LLAssetType::AT_OBJECT:
+ is_movable = !avatar->isWearingAttachment(inv_item->getUUID());
+ break;
+ default:
+ break;
+ }
+ }
+
+ if ( is_movable )
+ {
+ // Don't allow creating duplicates in the Calling Card/Friends
+ // subfolders, see bug EXT-1599. Check is item direct descendent
+ // of target folder and forbid item's movement if it so.
+ // Note: isItemDirectDescendentOfCategory checks if
+ // passed category is in the Calling Card/Friends folder
+ is_movable = ! LLFriendCardsManager::instance()
+ .isObjDirectDescendentOfCategory (inv_item, getCategory());
+ }
+
+ const LLUUID& favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+
+ // we can move item inside a folder only if this folder is Favorites. See EXT-719
+ accept = is_movable && ((mUUID != inv_item->getParentUUID()) || (mUUID == favorites_id));
+ if(accept && drop)
+ {
+ if (inv_item->getType() == LLAssetType::AT_GESTURE
+ && LLGestureManager::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash)
+ {
+ LLGestureManager::instance().deactivateGesture(inv_item->getUUID());
+ }
+ // If an item is being dragged between windows, unselect
+ // everything in the active window so that we don't follow
+ // the selection to its new location (which is very
+ // annoying).
+ if (LLFloaterInventory::getActiveInventory())
+ {
+ LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel();
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ if (active_panel && (panel != active_panel))
+ {
+ active_panel->unSelectAll();
+ }
+ }
+
+ // if dragging from/into favorites folder only reorder items
+ if ((mUUID == inv_item->getParentUUID()) && (favorites_id == mUUID))
+ {
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLIsType is_type(LLAssetType::AT_LANDMARK);
+ model->collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
+
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
+ if (itemp)
+ {
+ LLUUID srcItemId = inv_item->getUUID();
+ LLUUID destItemId = itemp->getListener()->getUUID();
+
+ // update order
+ updateItemsOrder(items, srcItemId, destItemId);
+
+ saveItemsOrder(items);
+ }
+ }
+ else if (favorites_id == mUUID) // if target is the favorites folder we use copy
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ inv_item->getPermissions().getOwner(),
+ inv_item->getUUID(),
+ mUUID,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ else if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ // BAP - should skip if dup.
+ if (move_is_into_current_outfit)
+ {
+ LLAppearanceManager::wearItem(inv_item);
+ }
+ else
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_item(
+ gAgent.getID(),
+ inv_item->getUUID(),
+ mUUID,
+ std::string(),
+ LLAssetType::AT_LINK,
+ cb);
+ }
+ }
+ else
+ {
+ // restamp if the move is into the trash.
+ LLInvFVBridge::changeItemParent(
+ model,
+ (LLViewerInventoryItem*)inv_item,
+ mUUID,
+ move_is_into_trash);
+ }
+ }
+ }
+ else if(LLToolDragAndDrop::SOURCE_WORLD == source)
+ {
+ // Make sure the object exists. If we allowed dragging from
+ // anonymous objects, it would be possible to bypass
+ // permissions.
+ object = gObjectList.findObject(inv_item->getParentUUID());
+ if(!object)
+ {
+ llinfos << "Object not found for drop." << llendl;
+ return FALSE;
+ }
+
+ // coming from a task. Need to figure out if the person can
+ // move/copy this item.
+ LLPermissions perm(inv_item->getPermissions());
+ BOOL is_move = FALSE;
+ if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
+ && perm.allowTransferTo(gAgent.getID())))
+// || gAgent.isGodlike())
+
+ {
+ accept = TRUE;
+ }
+ else if(object->permYouOwner())
+ {
+ // If the object cannot be copied, but the object the
+ // inventory is owned by the agent, then the item can be
+ // moved from the task to agent inventory.
+ is_move = TRUE;
+ accept = TRUE;
+ }
+ if(drop && accept)
+ {
+ LLMoveInv* move_inv = new LLMoveInv;
+ move_inv->mObjectID = inv_item->getParentUUID();
+ two_uuids_t item_pair(mUUID, inv_item->getUUID());
+ move_inv->mMoveList.push_back(item_pair);
+ move_inv->mCallback = NULL;
+ move_inv->mUserData = NULL;
+ if(is_move)
+ {
+ warn_move_inventory(object, move_inv);
+ }
+ else
+ {
+ LLNotification::Params params("MoveInventoryFromObject");
+ params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+ LLNotifications::instance().forceResponse(params, 0);
+ }
+ }
+
+ }
+ else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
+ {
+ accept = TRUE;
+ if(drop)
+ {
+ copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(),
+ LLToolDragAndDrop::getInstance()->getSourceID(), inv_item);
+ }
+ }
+ else if(LLToolDragAndDrop::SOURCE_LIBRARY == source)
+ {
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item;
+ if(item && item->isComplete())
+ {
+ accept = TRUE;
+ if(drop)
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ inv_item->getPermissions().getOwner(),
+ inv_item->getUUID(),
+ mUUID,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ }
+ }
+ else
+ {
+ llwarns << "unhandled drag source" << llendl;
+ }
+ return accept;
+}
+
+// +=================================================+
+// | LLScriptBridge (DEPRECTED) |
+// +=================================================+
+
+LLUIImagePtr LLScriptBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
+}
+
+// +=================================================+
+// | LLTextureBridge |
+// +=================================================+
+
+LLUIImagePtr LLTextureBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE);
+}
+
+void LLTextureBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+}
+
+void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLTextureBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ items.push_back(std::string("Texture Separator"));
+ items.push_back(std::string("Save As"));
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// virtual
+void LLTextureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("save_as" == action)
+ {
+ LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
+ LLPreviewTexture* preview_texture = LLFloaterReg::findTypedInstance<LLPreviewTexture>("preview_texture", mUUID);
+ if (preview_texture)
+ {
+ preview_texture->openToSave();
+ }
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+// +=================================================+
+// | LLSoundBridge |
+// +=================================================+
+
+LLUIImagePtr LLSoundBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE);
+}
+
+void LLSoundBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+// Changed this back to the way it USED to work:
+// only open the preview dialog through the contextual right-click menu
+// double-click just plays the sound
+
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ openSoundPreview((void*)this);
+ //send_uuid_sound_trigger(item->getAssetUUID(), 1.0);
+ }
+*/
+}
+
+void LLSoundBridge::previewItem()
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ send_sound_trigger(item->getAssetUUID(), 1.0);
+ }
+}
+
+void LLSoundBridge::openSoundPreview(void* which)
+{
+ LLSoundBridge *me = (LLSoundBridge *)which;
+ LLFloaterReg::showInstance("preview_sound", LLSD(me->mUUID), TAKE_FOCUS_YES);
+}
+
+void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLSoundBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Sound Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+
+ items.push_back(std::string("Sound Separator"));
+ items.push_back(std::string("Sound Play"));
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// +=================================================+
+// | LLLandmarkBridge |
+// +=================================================+
+
+LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) :
+LLItemBridge(inventory, uuid)
+{
+ mVisited = FALSE;
+ if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
+ {
+ mVisited = TRUE;
+ }
+}
+
+LLUIImagePtr LLLandmarkBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE);
+}
+
+void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Landmark Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+
+ items.push_back(std::string("Landmark Separator"));
+ items.push_back(std::string("About Landmark"));
+
+ // Disable "About Landmark" menu item for
+ // multiple landmarks selected. Only one landmark
+ // info panel can be shown at a time.
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("About Landmark"));
+ }
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// Convenience function for the two functions below.
+void teleport_via_landmark(const LLUUID& asset_id)
+{
+ gAgent.teleportViaLandmark( asset_id );
+
+ // we now automatically track the landmark you're teleporting to
+ // because you'll probably arrive at a telehub instead
+ LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance();
+ if( floater_world_map )
+ {
+ floater_world_map->trackLandmark( asset_id );
+ }
+}
+
+// virtual
+void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("teleport" == action)
+ {
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ teleport_via_landmark(item->getAssetUUID());
+ }
+ }
+ else if ("about" == action)
+ {
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ LLSD key;
+ key["type"] = "landmark";
+ key["id"] = item->getUUID();
+
+ LLSideTray::getInstance()->showPanel("panel_places", key);
+ }
+ }
+ else
+ {
+ LLItemBridge::performAction(folder, model, action);
+ }
+}
+
+static bool open_landmark_callback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
+ LLUUID asset_id = notification["payload"]["asset_id"].asUUID();
+ if (option == 0)
+ {
+ teleport_via_landmark(asset_id);
+ }
+
+ return false;
+}
+static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFromLandmark", open_landmark_callback);
+
+
+void LLLandmarkBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
+ if( item )
+ {
+ // Opening (double-clicking) a landmark immediately teleports,
+ // but warns you the first time.
+ // open_landmark(item);
+ LLSD payload;
+ payload["asset_id"] = item->getAssetUUID();
+ LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload);
+ }
+*/
+}
+
+
+// +=================================================+
+// | LLCallingCardObserver |
+// +=================================================+
+void LLCallingCardObserver::changed(U32 mask)
+{
+ mBridgep->refreshFolderViewItem();
+}
+
+// +=================================================+
+// | LLCallingCardBridge |
+// +=================================================+
+
+LLCallingCardBridge::LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ) :
+ LLItemBridge(inventory, uuid)
+{
+ mObserver = new LLCallingCardObserver(this);
+ LLAvatarTracker::instance().addObserver(mObserver);
+}
+
+LLCallingCardBridge::~LLCallingCardBridge()
+{
+ LLAvatarTracker::instance().removeObserver(mObserver);
+ delete mObserver;
+}
+
+void LLCallingCardBridge::refreshFolderViewItem()
+{
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL;
+ if (itemp)
+ {
+ itemp->refresh();
+ }
+}
+
+// virtual
+void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("begin_im" == action)
+ {
+ LLViewerInventoryItem *item = getItem();
+ if (item && (item->getCreatorUUID() != gAgent.getID()) &&
+ (!item->getCreatorUUID().isNull()))
+ {
+ std::string callingcard_name;
+ gCacheName->getFullName(item->getCreatorUUID(), callingcard_name);
+ LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID());
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
+ }
+ }
+ else if ("lure" == action)
+ {
+ LLViewerInventoryItem *item = getItem();
+ if (item && (item->getCreatorUUID() != gAgent.getID()) &&
+ (!item->getCreatorUUID().isNull()))
+ {
+ LLAvatarActions::offerTeleport(item->getCreatorUUID());
+ }
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+LLUIImagePtr LLCallingCardBridge::getIcon() const
+{
+ BOOL online = FALSE;
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID());
+ }
+ return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE);
+}
+
+std::string LLCallingCardBridge::getLabelSuffix() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if( item && LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()) )
+ {
+ return LLItemBridge::getLabelSuffix() + " (online)";
+ }
+ else
+ {
+ return LLItemBridge::getLabelSuffix();
+ }
+}
+
+void LLCallingCardBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
+ if(item && !item->getCreatorUUID().isNull())
+ {
+ LLAvatarActions::showProfile(item->getCreatorUUID());
+ }
+*/
+}
+
+void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ LLInventoryItem* item = getItem();
+ BOOL good_card = (item
+ && (LLUUID::null != item->getCreatorUUID())
+ && (item->getCreatorUUID() != gAgent.getID()));
+ BOOL user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()));
+ items.push_back(std::string("Send Instant Message Separator"));
+ items.push_back(std::string("Send Instant Message"));
+ items.push_back(std::string("Offer Teleport..."));
+ items.push_back(std::string("Conference Chat"));
+
+ if (!good_card)
+ {
+ disabled_items.push_back(std::string("Send Instant Message"));
+ }
+ if (!good_card || !user_online)
+ {
+ disabled_items.push_back(std::string("Offer Teleport..."));
+ disabled_items.push_back(std::string("Conference Chat"));
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data)
+{
+ LLViewerInventoryItem* item = getItem();
+ BOOL rv = FALSE;
+ if(item)
+ {
+ // check the type
+ switch(cargo_type)
+ {
+ case DAD_TEXTURE:
+ case DAD_SOUND:
+ case DAD_LANDMARK:
+ case DAD_SCRIPT:
+ case DAD_CLOTHING:
+ case DAD_OBJECT:
+ case DAD_NOTECARD:
+ case DAD_BODYPART:
+ case DAD_ANIMATION:
+ case DAD_GESTURE:
+ {
+ LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
+ const LLPermissions& perm = inv_item->getPermissions();
+ if(gInventory.getItem(inv_item->getUUID())
+ && perm.allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+ {
+ rv = TRUE;
+ if(drop)
+ {
+ LLToolDragAndDrop::giveInventory(item->getCreatorUUID(),
+ (LLInventoryItem*)cargo_data);
+ }
+ }
+ else
+ {
+ // It's not in the user's inventory (it's probably in
+ // an object's contents), so disallow dragging it here.
+ // You can't give something you don't yet have.
+ rv = FALSE;
+ }
+ break;
+ }
+ case DAD_CATEGORY:
+ {
+ LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data;
+ if( gInventory.getCategory( inv_cat->getUUID() ) )
+ {
+ rv = TRUE;
+ if(drop)
+ {
+ LLToolDragAndDrop::giveInventoryCategory(
+ item->getCreatorUUID(),
+ inv_cat);
+ }
+ }
+ else
+ {
+ // It's not in the user's inventory (it's probably in
+ // an object's contents), so disallow dragging it here.
+ // You can't give something you don't yet have.
+ rv = FALSE;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return rv;
+}
+
+BOOL LLCallingCardBridge::removeItem()
+{
+ if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem()))
+ {
+ LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID());
+ return FALSE;
+ }
+ else
+ {
+ return LLItemBridge::removeItem();
+ }
+}
+// +=================================================+
+// | LLNotecardBridge |
+// +=================================================+
+
+LLUIImagePtr LLNotecardBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE);
+}
+
+void LLNotecardBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+
+/*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
+ }
+*/
+}
+
+
+// +=================================================+
+// | LLGestureBridge |
+// +=================================================+
+
+LLUIImagePtr LLGestureBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE);
+}
+
+LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const
+{
+ if( LLGestureManager::instance().isGestureActive(mUUID) )
+ {
+ return LLFontGL::BOLD;
+ }
+ else
+ {
+ return LLFontGL::NORMAL;
+ }
+}
+
+std::string LLGestureBridge::getLabelSuffix() const
+{
+ if( LLGestureManager::instance().isGestureActive(mUUID) )
+ {
+ return LLItemBridge::getLabelSuffix() + " (active)";
+ }
+ else
+ {
+ return LLItemBridge::getLabelSuffix();
+ }
+}
+
+// virtual
+void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("activate" == action)
+ {
+ LLGestureManager::instance().activateGesture(mUUID);
+
+ LLViewerInventoryItem* item = gInventory.getItem(mUUID);
+ if (!item) return;
+
+ // Since we just changed the suffix to indicate (active)
+ // the server doesn't need to know, just the viewer.
+ gInventory.updateItem(item);
+ gInventory.notifyObservers();
+ }
+ else if ("deactivate" == action)
+ {
+ LLGestureManager::instance().deactivateGesture(mUUID);
+
+ LLViewerInventoryItem* item = gInventory.getItem(mUUID);
+ if (!item) return;
+
+ // Since we just changed the suffix to indicate (active)
+ // the server doesn't need to know, just the viewer.
+ gInventory.updateItem(item);
+ gInventory.notifyObservers();
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+void LLGestureBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
+ preview->setFocus(TRUE);
+ }
+*/
+}
+
+BOOL LLGestureBridge::removeItem()
+{
+ // Force close the preview window, if it exists
+ LLGestureManager::instance().deactivateGesture(mUUID);
+ return LLItemBridge::removeItem();
+}
+
+void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLGestureBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ items.push_back(std::string("Gesture Separator"));
+ items.push_back(std::string("Activate"));
+ items.push_back(std::string("Deactivate"));
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// +=================================================+
+// | LLAnimationBridge |
+// +=================================================+
+
+LLUIImagePtr LLAnimationBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE);
+}
+
+void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Animation Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+
+ items.push_back(std::string("Animation Separator"));
+ items.push_back(std::string("Animation Play"));
+ items.push_back(std::string("Animation Audition"));
+
+ hide_context_entries(menu, items, disabled_items);
+
+}
+
+// virtual
+void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ((action == "playworld") || (action == "playlocal"))
+ {
+ if (getItem())
+ {
+ LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE;
+ if ("playworld" == action) activate = LLPreviewAnim::PLAY;
+ if ("playlocal" == action) activate = LLPreviewAnim::AUDITION;
+
+ LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID));
+ if (preview)
+ {
+ preview->activate(activate);
+ }
+ }
+ }
+ else
+ {
+ LLItemBridge::performAction(folder, model, action);
+ }
+}
+
+void LLAnimationBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+*/
+}
+
+// +=================================================+
+// | LLObjectBridge |
+// +=================================================+
+
+// static
+LLUUID LLObjectBridge::sContextMenuItemID;
+
+LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) :
+LLItemBridge(inventory, uuid), mInvType(type)
+{
+ mAttachPt = (flags & 0xff); // low bye of inventory flags
+
+ mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE;
+}
+
+BOOL LLObjectBridge::isItemRemovable()
+{
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if(!avatar) return FALSE;
+ if(avatar->isWearingAttachment(mUUID)) return FALSE;
+ return LLInvFVBridge::isItemRemovable();
+}
+
+LLUIImagePtr LLObjectBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject );
+}
+
+LLInventoryObject* LLObjectBridge::getObject() const
+{
+ LLInventoryObject* object = NULL;
+ LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ object = (LLInventoryObject*)model->getObject(mUUID);
+ }
+ return object;
+}
+
+// virtual
+void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("attach" == action)
+ {
+ LLUUID object_id = mUUID;
+ LLViewerInventoryItem* item;
+ item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
+ if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID()))
+ {
+ rez_attachment(item, NULL);
+ }
+ else if(item && item->isComplete())
+ {
+ // must be in library. copy it to our inventory and put it on.
+ LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0);
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ gFocusMgr.setKeyboardFocus(NULL);
+ }
+ else if ("detach" == action)
+ {
+ LLInventoryItem* item = gInventory.getItem(mUUID);
+ if(item)
+ {
+ gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
+ gMessageSystem->sendReliable( gAgent.getRegion()->getHost());
+ }
+ // this object might have been selected, so let the selection manager know it's gone now
+ LLViewerObject *found_obj =
+ gObjectList.findObject(item->getUUID());
+ if (found_obj)
+ {
+ LLSelectMgr::getInstance()->remove(found_obj);
+ }
+ else
+ {
+ llwarns << "object not found - ignoring" << llendl;
+ }
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+void LLObjectBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+
+ LLSD key;
+ key["id"] = mUUID;
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
+
+ // Disable old properties floater; this is replaced by the sidepanel.
+ /*
+ LLFloaterReg::showInstance("properties", mUUID);
+ */
+}
+
+LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
+{
+ U8 font = LLFontGL::NORMAL;
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( avatar && avatar->isWearingAttachment( mUUID ) )
+ {
+ font |= LLFontGL::BOLD;
+ }
+
+ LLInventoryItem* item = getItem();
+ if (item && item->getIsLinkType())
+ {
+ font |= LLFontGL::ITALIC;
+ }
+
+ return (LLFontGL::StyleFlags)font;
+}
+
+std::string LLObjectBridge::getLabelSuffix() const
+{
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( avatar && avatar->isWearingAttachment( mUUID ) )
+ {
+ std::string attachment_point_name = avatar->getAttachedPointName(mUUID);
+ LLStringUtil::toLower(attachment_point_name);
+
+ LLStringUtil::format_map_t args;
+ args["[ATTACHMENT_POINT]"] = attachment_point_name.c_str();
+ return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args);
+ }
+ else
+ {
+ return LLItemBridge::getLabelSuffix();
+ }
+}
+
+void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment)
+{
+ LLSD payload;
+ payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link.
+
+ S32 attach_pt = 0;
+ if (gAgent.getAvatarObject() && attachment)
+ {
+ for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin();
+ iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter)
+ {
+ if (iter->second == attachment)
+ {
+ attach_pt = iter->first;
+ break;
+ }
+ }
+ }
+
+ payload["attachment_point"] = attach_pt;
+
+#if !ENABLE_MULTIATTACHMENTS
+ if (attachment && attachment->getNumObjects() > 0)
+ {
+ LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez);
+ }
+ else
+#endif
+ {
+ LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
+ }
+}
+
+bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response)
+{
+ LLVOAvatar *avatarp = gAgent.getAvatarObject();
+
+ if (!avatarp->canAttachMoreObjects())
+ {
+ LLSD args;
+ args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS);
+ LLNotifications::instance().add("MaxAttachmentsOnOutfit", args);
+ return false;
+ }
+
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ if (option == 0/*YES*/)
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID());
+
+ if (itemp)
+ {
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ObjectData);
+ msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID());
+ msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner());
+ U8 attachment_pt = notification["payload"]["attachment_point"].asInteger();
+#if ENABLE_MULTIATTACHMENTS
+ attachment_pt |= ATTACHMENT_ADD;
+#endif
+ msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt);
+ pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions());
+ msg->addStringFast(_PREHASH_Name, itemp->getName());
+ msg->addStringFast(_PREHASH_Description, itemp->getDescription());
+ msg->sendReliable(gAgent.getRegion()->getHost());
+ }
+ }
+ return false;
+}
+static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_replace_attachment_rez);
+
+void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ LLInventoryItem* item = getItem();
+ if (item && item->getIsLinkType())
+ {
+ items.push_back(std::string("Goto Link"));
+ }
+
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ LLObjectBridge::sContextMenuItemID = mUUID;
+
+ if(item)
+ {
+ LLVOAvatarSelf* avatarp = gAgent.getAvatarObject();
+ if( !avatarp )
+ {
+ return;
+ }
+
+ if( avatarp->isWearingAttachment( mUUID ) )
+ {
+ items.push_back(std::string("Detach From Yourself"));
+ }
+ else
+ if( !isInTrash() && !isLinkedObjectInTrash() )
+ {
+ items.push_back(std::string("Attach Separator"));
+ items.push_back(std::string("Object Wear"));
+ items.push_back(std::string("Attach To"));
+ items.push_back(std::string("Attach To HUD"));
+ // commented out for DEV-32347
+ //items.push_back(std::string("Restore to Last Position"));
+
+ if (!avatarp->canAttachMoreObjects())
+ {
+ disabled_items.push_back(std::string("Object Wear"));
+ disabled_items.push_back(std::string("Attach To"));
+ disabled_items.push_back(std::string("Attach To HUD"));
+ }
+ LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE);
+ LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE);
+ LLVOAvatar *avatarp = gAgent.getAvatarObject();
+ if (attach_menu
+ && (attach_menu->getChildCount() == 0)
+ && attach_hud_menu
+ && (attach_hud_menu->getChildCount() == 0)
+ && avatarp)
+ {
+ for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
+ iter != avatarp->mAttachmentPoints.end(); )
+ {
+ LLVOAvatar::attachment_map_t::iterator curiter = iter++;
+ LLViewerJointAttachment* attachment = curiter->second;
+ LLMenuItemCallGL::Params p;
+ std::string submenu_name = attachment->getName();
+ if (LLTrans::getString(submenu_name) != "")
+ {
+ p.name = (" ")+LLTrans::getString(submenu_name)+" ";
+ }
+ else
+ {
+ p.name = submenu_name;
+ }
+ LLSD cbparams;
+ cbparams["index"] = curiter->first;
+ cbparams["label"] = attachment->getName();
+ p.on_click.function_name = "Inventory.AttachObject";
+ p.on_click.parameter = LLSD(attachment->getName());
+ p.on_enable.function_name = "Attachment.Label";
+ p.on_enable.parameter = cbparams;
+ LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu;
+ LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent);
+ }
+ }
+ }
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+BOOL LLObjectBridge::renameItem(const std::string& new_name)
+{
+ if(!isItemRenameable())
+ return FALSE;
+ LLPreview::dirty(mUUID);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ return FALSE;
+ LLViewerInventoryItem* item = getItem();
+ if(item && (item->getName() != new_name))
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->rename(new_name);
+ buildDisplayName(new_item, mDisplayName);
+ new_item->updateServer(FALSE);
+ model->updateItem(new_item);
+
+ model->notifyObservers();
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( avatar )
+ {
+ LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() );
+ if( obj )
+ {
+ LLSelectMgr::getInstance()->deselectAll();
+ LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE );
+ LLSelectMgr::getInstance()->selectionSetObjectName( new_name );
+ LLSelectMgr::getInstance()->deselectAll();
+ }
+ }
+ }
+ // return FALSE because we either notified observers (& therefore
+ // rebuilt) or we didn't update.
+ return FALSE;
+}
+
+// +=================================================+
+// | LLLSLTextBridge |
+// +=================================================+
+
+LLUIImagePtr LLLSLTextBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
+}
+
+void LLLSLTextBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+ /*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+ */
+}
+
+// +=================================================+
+// | LLWearableBridge |
+// +=================================================+
+
+// *NOTE: hack to get from avatar inventory to avatar
+void wear_inventory_item_on_avatar( LLInventoryItem* item )
+{
+ if(item)
+ {
+ lldebugs << "wear_inventory_item_on_avatar( " << item->getName()
+ << " )" << llendl;
+
+ LLAppearanceManager::wearItem(item);
+ }
+}
+
+void wear_add_inventory_item_on_avatar( LLInventoryItem* item )
+{
+ if(item)
+ {
+ lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName()
+ << " )" << llendl;
+
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ LLWearableBridge::onWearAddOnAvatarArrived,
+ new LLUUID(item->getUUID()));
+ }
+}
+
+void remove_inventory_category_from_avatar( LLInventoryCategory* category )
+{
+ if(!category) return;
+ lldebugs << "remove_inventory_category_from_avatar( " << category->getName()
+ << " )" << llendl;
+
+
+ if( gFloaterCustomize )
+ {
+ gFloaterCustomize->askToSaveIfDirty(
+ boost::bind(remove_inventory_category_from_avatar_step2, _1, category->getUUID()));
+ }
+ else
+ {
+ remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() );
+ }
+}
+
+struct OnRemoveStruct
+{
+ LLUUID mUUID;
+ OnRemoveStruct(const LLUUID& uuid):
+ mUUID(uuid)
+ {
+ }
+};
+
+void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id)
+{
+
+ // Find all the wearables that are in the category's subtree.
+ lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl;
+ if(proceed)
+ {
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ LLFindWearables is_wearable;
+ gInventory.collectDescendentsIf(category_id,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_wearable);
+ S32 i;
+ S32 wearable_count = item_array.count();
+
+ LLInventoryModel::cat_array_t obj_cat_array;
+ LLInventoryModel::item_array_t obj_item_array;
+ LLIsType is_object( LLAssetType::AT_OBJECT );
+ gInventory.collectDescendentsIf(category_id,
+ obj_cat_array,
+ obj_item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_object);
+ S32 obj_count = obj_item_array.count();
+
+ // Find all gestures in this folder
+ LLInventoryModel::cat_array_t gest_cat_array;
+ LLInventoryModel::item_array_t gest_item_array;
+ LLIsType is_gesture( LLAssetType::AT_GESTURE );
+ gInventory.collectDescendentsIf(category_id,
+ gest_cat_array,
+ gest_item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_gesture);
+ S32 gest_count = gest_item_array.count();
+
+ if (wearable_count > 0) //Loop through wearables. If worn, remove.
+ {
+ for(i = 0; i < wearable_count; ++i)
+ {
+ if( gAgentWearables.isWearingItem (item_array.get(i)->getUUID()) )
+ {
+ LLWearableList::instance().getAsset(item_array.get(i)->getAssetUUID(),
+ item_array.get(i)->getName(),
+ item_array.get(i)->getType(),
+ LLWearableBridge::onRemoveFromAvatarArrived,
+ new OnRemoveStruct(item_array.get(i)->getUUID()));
+
+ }
+ }
+ }
+
+
+ if (obj_count > 0)
+ {
+ for(i = 0; i < obj_count; ++i)
+ {
+ gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item_array.get(i)->getUUID() );
+
+ gMessageSystem->sendReliable( gAgent.getRegion()->getHost() );
+
+ // this object might have been selected, so let the selection manager know it's gone now
+ LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID());
+ if (found_obj)
+ {
+ LLSelectMgr::getInstance()->remove(found_obj);
+ }
+ else
+ {
+ llwarns << "object not found, ignoring" << llendl;
+ }
+ }
+ }
+
+ if (gest_count > 0)
+ {
+ for(i = 0; i < gest_count; ++i)
+ {
+ if ( LLGestureManager::instance().isGestureActive( gest_item_array.get(i)->getUUID()) )
+ {
+ LLGestureManager::instance().deactivateGesture( gest_item_array.get(i)->getUUID() );
+ gInventory.updateItem( gest_item_array.get(i) );
+ gInventory.notifyObservers();
+ }
+
+ }
+ }
+ }
+}
+
+BOOL LLWearableBridge::renameItem(const std::string& new_name)
+{
+ if( gAgentWearables.isWearingItem( mUUID ) )
+ {
+ gAgentWearables.setWearableName( mUUID, new_name );
+ }
+ return LLItemBridge::renameItem(new_name);
+}
+
+BOOL LLWearableBridge::isItemRemovable()
+{
+ if (gAgentWearables.isWearingItem(mUUID)) return FALSE;
+ return LLInvFVBridge::isItemRemovable();
+}
+
+std::string LLWearableBridge::getLabelSuffix() const
+{
+ if( gAgentWearables.isWearingItem( mUUID ) )
+ {
+ return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn");
+ }
+ else
+ {
+ return LLItemBridge::getLabelSuffix();
+ }
+}
+
+LLUIImagePtr LLWearableBridge::getIcon() const
+{
+ return get_item_icon(mAssetType, mInvType, mWearableType, FALSE);
+}
+
+// virtual
+void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("wear" == action)
+ {
+ wearOnAvatar();
+ }
+ else if ("wear_add" == action)
+ {
+ wearAddOnAvatar();
+ }
+ else if ("edit" == action)
+ {
+ editOnAvatar();
+ return;
+ }
+ else if ("take_off" == action)
+ {
+ if(gAgentWearables.isWearingItem(mUUID))
+ {
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ LLWearableBridge::onRemoveFromAvatarArrived,
+ new OnRemoveStruct(mUUID));
+ }
+ }
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+void LLWearableBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+ /*
+ if( isInTrash() )
+ {
+ LLNotifications::instance().add("CannotWearTrash");
+ }
+ else if(isAgentInventory())
+ {
+ if( !gAgentWearables.isWearingItem( mUUID ) )
+ {
+ wearOnAvatar();
+ }
+ }
+ else
+ {
+ // must be in the inventory library. copy it to our inventory
+ // and put it on right away.
+ LLViewerInventoryItem* item = getItem();
+ if(item && item->isComplete())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else if(item)
+ {
+ // *TODO: We should fetch the item details, and then do
+ // the operation above.
+ LLNotifications::instance().add("CannotWearInfoNotComplete");
+ }
+ }
+ */
+}
+
+void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLWearableBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere
+ BOOL no_open = ((flags & SUPPRESS_OPEN_ITEM) == SUPPRESS_OPEN_ITEM);
+
+ // If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976
+ LLViewerInventoryItem* item = getItem();
+ if( !no_open && item )
+ {
+ no_open = (item->getType() == LLAssetType::AT_CLOTHING) ||
+ (item->getType() == LLAssetType::AT_BODYPART);
+ }
+ if (!no_open)
+ {
+ items.push_back(std::string("Open"));
+ }
+
+ if (item && item->getIsLinkType())
+ {
+ items.push_back(std::string("Goto Link"));
+ }
+
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ items.push_back(std::string("Wearable Separator"));
+
+ items.push_back(std::string("Wearable Wear"));
+ items.push_back(std::string("Wearable Add"));
+ items.push_back(std::string("Wearable Edit"));
+
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Wearable Edit"));
+ }
+ // Don't allow items to be worn if their baseobj is in the trash.
+ if (isLinkedObjectInTrash())
+ {
+ disabled_items.push_back(std::string("Wearable Wear"));
+ disabled_items.push_back(std::string("Wearable Add"));
+ disabled_items.push_back(std::string("Wearable Edit"));
+ }
+
+ // Disable wear and take off based on whether the item is worn.
+ if(item)
+ {
+ switch (item->getType())
+ {
+ case LLAssetType::AT_CLOTHING:
+ items.push_back(std::string("Take Off"));
+ case LLAssetType::AT_BODYPART:
+ if (gAgentWearables.isWearingItem(item->getUUID()))
+ {
+ disabled_items.push_back(std::string("Wearable Wear"));
+ disabled_items.push_back(std::string("Wearable Add"));
+ }
+ else
+ {
+ disabled_items.push_back(std::string("Take Off"));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// Called from menus
+// static
+BOOL LLWearableBridge::canWearOnAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(!self) return FALSE;
+ if(!self->isAgentInventory())
+ {
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem();
+ if(!item || !item->isComplete()) return FALSE;
+ }
+ return (!gAgentWearables.isWearingItem(self->mUUID));
+}
+
+// Called from menus
+// static
+void LLWearableBridge::onWearOnAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(!self) return;
+ self->wearOnAvatar();
+}
+
+void LLWearableBridge::wearOnAvatar()
+{
+ // Don't wear anything until initial wearables are loaded, can
+ // destroy clothing items.
+ if (!gAgentWearables.areWearablesLoaded())
+ {
+ LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
+ return;
+ }
+
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ if(!isAgentInventory())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else
+ {
+ wear_inventory_item_on_avatar(item);
+ }
+ }
+}
+
+void LLWearableBridge::wearAddOnAvatar()
+{
+ // Don't wear anything until initial wearables are loaded, can
+ // destroy clothing items.
+ if (!gAgentWearables.areWearablesLoaded())
+ {
+ LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
+ return;
+ }
+
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ if(!isAgentInventory())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else
+ {
+ wear_add_inventory_item_on_avatar(item);
+ }
+ }
+}
+
+// static
+void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata )
+{
+ LLUUID* item_id = (LLUUID*) userdata;
+ if(wearable)
+ {
+ LLViewerInventoryItem* item = NULL;
+ item = (LLViewerInventoryItem*)gInventory.getItem(*item_id);
+ if(item)
+ {
+ if(item->getAssetUUID() == wearable->getAssetID())
+ {
+ gAgentWearables.setWearableItem(item, wearable);
+ gInventory.notifyObservers();
+ //self->getFolderItem()->refreshFromRoot();
+ }
+ else
+ {
+ llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl;
+ }
+ }
+ }
+ delete item_id;
+}
+
+// static
+// BAP remove the "add" code path once everything is fully COF-ified.
+void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata )
+{
+ LLUUID* item_id = (LLUUID*) userdata;
+ if(wearable)
+ {
+ LLViewerInventoryItem* item = NULL;
+ item = (LLViewerInventoryItem*)gInventory.getItem(*item_id);
+ if(item)
+ {
+ if(item->getAssetUUID() == wearable->getAssetID())
+ {
+ bool do_append = true;
+ gAgentWearables.setWearableItem(item, wearable, do_append);
+ gInventory.notifyObservers();
+ //self->getFolderItem()->refreshFromRoot();
+ }
+ else
+ {
+ llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl;
+ }
+ }
+ }
+ delete item_id;
+}
+
+// static
+BOOL LLWearableBridge::canEditOnAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(!self) return FALSE;
+
+ return (gAgentWearables.isWearingItem(self->mUUID));
+}
+
+// static
+void LLWearableBridge::onEditOnAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(self)
+ {
+ self->editOnAvatar();
+ }
+}
+
+void LLWearableBridge::editOnAvatar()
+{
+ const LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID);
+ if( wearable )
+ {
+ // Set the tab to the right wearable.
+ if (gFloaterCustomize)
+ gFloaterCustomize->setCurrentWearableType( wearable->getType() );
+
+ if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() )
+ {
+ // Start Avatar Customization
+ gAgent.changeCameraToCustomizeAvatar();
+ }
+ }
+}
+
+// static
+BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if( self && (LLAssetType::AT_BODYPART != self->mAssetType) )
+ {
+ return gAgentWearables.isWearingItem( self->mUUID );
+ }
+ return FALSE;
+}
+
+// static
+void LLWearableBridge::onRemoveFromAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(!self) return;
+ if(gAgentWearables.isWearingItem(self->mUUID))
+ {
+ LLViewerInventoryItem* item = self->getItem();
+ if (item)
+ {
+ LLUUID parent_id = item->getParentUUID();
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ onRemoveFromAvatarArrived,
+ new OnRemoveStruct(LLUUID(self->mUUID)));
+ }
+ }
+}
+
+// static
+void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
+ void* userdata)
+{
+ OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata;
+ const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID);
+ if(wearable)
+ {
+ if( gAgentWearables.isWearingItem( item_id ) )
+ {
+ EWearableType type = wearable->getType();
+
+ if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&&
+ //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) )
+ {
+ // MULTI_WEARABLE: FIXME HACK - always remove all
+ bool do_remove_all = false;
+ gAgentWearables.removeWearable( type, do_remove_all, 0 );
+ }
+ }
+ }
+
+ // Find and remove this item from the COF.
+ LLInventoryModel::item_array_t items = gInventory.collectLinkedItems(item_id, LLAppearanceManager::getCOF());
+ llassert(items.size() == 1); // Should always have one and only one item linked to this in the COF.
+ for (LLInventoryModel::item_array_t::const_iterator iter = items.begin();
+ iter != items.end();
+ ++iter)
+ {
+ const LLViewerInventoryItem *linked_item = (*iter);
+ const LLUUID &item_id = linked_item->getUUID();
+ gInventory.purgeObject(item_id);
+ }
+ gInventory.notifyObservers();
+
+ delete on_remove_struct;
+}
+
+LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
+ const LLUUID& uuid,LLInventoryModel* model)
+{
+ LLInvFVBridgeAction* action = NULL;
+ switch(asset_type)
+ {
+ case LLAssetType::AT_TEXTURE:
+ action = new LLTextureBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_SOUND:
+ action = new LLSoundBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_LANDMARK:
+ action = new LLLandmarkBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_CALLINGCARD:
+ action = new LLCallingCardBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_OBJECT:
+ action = new LLObjectBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_NOTECARD:
+ action = new LLNotecardBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_ANIMATION:
+ action = new LLAnimationBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_GESTURE:
+ action = new LLGestureBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_LSL_TEXT:
+ action = new LLLSLTextBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ action = new LLWearableBridgeAction(uuid,model);
+
+ break;
+
+ default:
+ break;
+ }
+ return action;
+}
+
+//static
+void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
+ const LLUUID& uuid,LLInventoryModel* model)
+{
+ LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
+ if(action)
+ {
+ action->doIt();
+ delete action;
+ }
+}
+
+//static
+void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model)
+{
+ LLAssetType::EType asset_type = model->getItem(uuid)->getType();
+ LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
+ if(action)
+ {
+ action->doIt();
+ delete action;
+ }
+}
+
+LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const
+{
+ if(mModel)
+ return (LLViewerInventoryItem*)mModel->getItem(mUUID);
+ return NULL;
+}
+
+//virtual
+void LLTextureBridgeAction::doIt()
+{
+ if (getItem())
+ {
+ LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void LLSoundBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLLandmarkBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if( item )
+ {
+ // Opening (double-clicking) a landmark immediately teleports,
+ // but warns you the first time.
+ LLSD payload;
+ payload["asset_id"] = item->getAssetUUID();
+ LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLCallingCardBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item && item->getCreatorUUID().notNull())
+ {
+ LLAvatarActions::showProfile(item->getCreatorUUID());
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void
+LLNotecardBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void LLGestureBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
+ preview->setFocus(TRUE);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void LLAnimationBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLObjectBridgeAction::doIt()
+{
+ LLFloaterReg::showInstance("properties", mUUID);
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLLSLTextBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+BOOL LLWearableBridgeAction::isInTrash() const
+{
+ if(!mModel) return FALSE;
+ const LLUUID trash_id = mModel->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ return mModel->isObjectDescendentOf(mUUID, trash_id);
+}
+
+BOOL LLWearableBridgeAction::isAgentInventory() const
+{
+ if(!mModel) return FALSE;
+ if(gInventory.getRootFolderID() == mUUID) return TRUE;
+ return mModel->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
+}
+
+void LLWearableBridgeAction::wearOnAvatar()
+{
+ // Don't wear anything until initial wearables are loaded, can
+ // destroy clothing items.
+ if (!gAgentWearables.areWearablesLoaded())
+ {
+ LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
+ return;
+ }
+
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ if(!isAgentInventory())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else
+ {
+ wear_inventory_item_on_avatar(item);
+ }
+ }
+}
+
+//virtual
+void LLWearableBridgeAction::doIt()
+{
+ if(isInTrash())
+ {
+ LLNotifications::instance().add("CannotWearTrash");
+ }
+ else if(isAgentInventory())
+ {
+ if(!gAgentWearables.isWearingItem(mUUID))
+ {
+ wearOnAvatar();
+ }
+ }
+ else
+ {
+ // must be in the inventory library. copy it to our inventory
+ // and put it on right away.
+ LLViewerInventoryItem* item = getItem();
+ if(item && item->isComplete())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else if(item)
+ {
+ // *TODO: We should fetch the item details, and then do
+ // the operation above.
+ LLNotifications::instance().add("CannotWearInfoNotComplete");
+ }
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+// +=================================================+
+// | LLLinkItemBridge |
+// +=================================================+
+// For broken links
+
+std::string LLLinkItemBridge::sPrefix("Link: ");
+
+
+LLUIImagePtr LLLinkItemBridge::getIcon() const
+{
+ if (LLViewerInventoryItem *item = getItem())
+ {
+ return get_item_icon(item->getActualType(), LLInventoryType::IT_NONE, 0, FALSE);
+ }
+ return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE);
+}
+
+void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ // *TODO: Translate
+ lldebugs << "LLLink::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Delete"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+
+// +=================================================+
+// | LLLinkBridge |
+// +=================================================+
+// For broken links.
+
+std::string LLLinkFolderBridge::sPrefix("Link: ");
+
+
+LLUIImagePtr LLLinkFolderBridge::getIcon() const
+{
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
+ if (LLViewerInventoryItem *item = getItem())
+ {
+ if (const LLViewerInventoryCategory* cat = item->getLinkedCategory())
+ {
+ preferred_type = cat->getPreferredType();
+ }
+ }
+ return LLFolderBridge::getIcon(preferred_type);
+}
+
+void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ // *TODO: Translate
+ lldebugs << "LLLink::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Goto Link"));
+ items.push_back(std::string("Delete"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("goto" == action)
+ {
+ gotoItem(folder);
+ return;
+ }
+ LLItemBridge::performAction(folder,model,action);
+}
+
+void LLLinkFolderBridge::gotoItem(LLFolderView *folder)
+{
+ const LLUUID &cat_uuid = getFolderID();
+ if (!cat_uuid.isNull())
+ {
+ if (LLFolderViewItem *base_folder = folder->getItemByID(cat_uuid))
+ {
+ if (LLInventoryModel* model = getInventoryModel())
+ {
+ model->fetchDescendentsOf(cat_uuid);
+ }
+ base_folder->setOpen(TRUE);
+ folder->setSelectionFromRoot(base_folder,TRUE);
+ folder->scrollToShowSelection();
+ }
+ }
+}
+
+const LLUUID &LLLinkFolderBridge::getFolderID() const
+{
+ if (LLViewerInventoryItem *link_item = getItem())
+ {
+ if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory())
+ {
+ const LLUUID& cat_uuid = cat->getUUID();
+ return cat_uuid;
+ }
+ }
+ return LLUUID::null;
+}
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index f95e8f9361..3ffeb55d6c 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -383,6 +383,8 @@ class LLTextureBridge : public LLItemBridge public: virtual LLUIImagePtr getIcon() const; virtual void openItem(); + virtual void buildContextMenu(LLMenuGL& menu, U32 flags); + virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action); protected: LLTextureBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type) : diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 178e7d0823..7f69ce9641 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1,902 +1,907 @@ -/** - * @file llfloaterinventory.cpp - * @brief Implementation of the inventory view and associated stuff. - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include <utility> // for std::pair<> - -#include "llinventorypanel.h" - -// Seraph TODO: Remove unnecessary headers - -// library includes -#include "llagent.h" -#include "llagentwearables.h" -#include "llcallingcard.h" -#include "llfloaterreg.h" -#include "llsdserialize.h" -#include "llfiltereditor.h" -#include "llspinctrl.h" -#include "llui.h" -#include "message.h" - -// newview includes -#include "llappearancemgr.h" -#include "llappviewer.h" -#include "llfirstuse.h" -#include "llfloaterchat.h" -#include "llfloatercustomize.h" -#include "llfocusmgr.h" -#include "llfolderview.h" -#include "llgesturemgr.h" -#include "lliconctrl.h" -#include "llimview.h" -#include "llinventorybridge.h" -#include "llinventoryclipboard.h" -#include "llinventorymodel.h" -#include "lllineeditor.h" -#include "llmenugl.h" -#include "llpreviewanim.h" -#include "llpreviewgesture.h" -#include "llpreviewnotecard.h" -#include "llpreviewscript.h" -#include "llpreviewsound.h" -#include "llpreviewtexture.h" -#include "llresmgr.h" -#include "llscrollbar.h" -#include "llscrollcontainer.h" -#include "llselectmgr.h" -#include "lltabcontainer.h" -#include "lltooldraganddrop.h" -#include "lluictrlfactory.h" -#include "llviewerfoldertype.h" -#include "llviewerinventory.h" -#include "llviewermessage.h" -#include "llviewerobjectlist.h" -#include "llviewerregion.h" -#include "llviewerwindow.h" -#include "llvoavatarself.h" -#include "llwearablelist.h" - -static LLDefaultChildRegistry::Register<LLInventoryPanel> r("inventory_panel"); - -const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder"); -const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder"); -const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string(""); -static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER; - -LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) : - LLPanel(p), - mInventoryObserver(NULL), - mFolders(NULL), - mScroller(NULL), - mSortOrderSetting(p.sort_order_setting), - mInventory(p.inventory), - mAllowMultiSelect(p.allow_multi_select), - mHasInventoryConnection(false), - mStartFolderString(p.start_folder), - mBuildDefaultHierarchy(true), - mInvFVBridgeBuilder(NULL) -{ - mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER; - - // contex menu callbacks - mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2)); - mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH)); - mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)); - mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLInventoryPanel::doCreate, this, _2)); - mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&LLInventoryPanel::attachObject, this, _2)); - mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this)); - - setBackgroundColor(LLUIColorTable::instance().getColor("InventoryBackgroundColor")); - setBackgroundVisible(TRUE); - setBackgroundOpaque(TRUE); -} - -BOOL LLInventoryPanel::postBuild() -{ - LLMemType mt(LLMemType::MTYPE_INVENTORY_POST_BUILD); - - mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves - - // create root folder - { - LLRect folder_rect(0, - 0, - getRect().getWidth(), - 0); - LLFolderView::Params p; - p.name = getName(); - p.rect = folder_rect; - p.parent_panel = this; - mFolders = LLUICtrlFactory::create<LLFolderView>(p); - mFolders->setAllowMultiSelect(mAllowMultiSelect); - } - - mCommitCallbackRegistrar.popScope(); - - mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); - - // scroller - { - LLRect scroller_view_rect = getRect(); - scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom); - LLScrollContainer::Params p; - p.name("Inventory Scroller"); - p.rect(scroller_view_rect); - p.follows.flags(FOLLOWS_ALL); - p.reserve_scroll_corner(true); - p.tab_stop(true); - mScroller = LLUICtrlFactory::create<LLScrollContainer>(p); - } - addChild(mScroller); - mScroller->addChild(mFolders); - - mFolders->setScrollContainer(mScroller); - - // set up the callbacks from the inventory we're viewing, and then - // build everything. - mInventoryObserver = new LLInventoryPanelObserver(this); - mInventory->addObserver(mInventoryObserver); - - // determine the root folder, if any, so inventory contents show just the children - // of that folder (i.e. not including the folder itself). - const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString); - - if ("INVENTORY" == mStartFolderString) - { - mStartFolderID = gInventory.getRootFolderID(); - } - else if ("LIBRARY" == mStartFolderString) - { - mStartFolderID = gInventory.getLibraryRootFolderID(); - } - else - { - mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null); - } - - // build view of inventory if we need default full hierarchy and inventory ready, otherwise wait for modelChanged() callback - if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mHasInventoryConnection) - { - rebuildViewsFor(mStartFolderID); - mHasInventoryConnection = true; - } - - // bit of a hack to make sure the inventory is open. - mFolders->openFolder(preferred_type != LLFolderType::FT_NONE ? LLViewerFolderType::lookupNewCategoryName(preferred_type) : "My Inventory"); - - if (mSortOrderSetting != INHERIT_SORT_ORDER) - { - setSortOrder(gSavedSettings.getU32(mSortOrderSetting)); - } - else - { - setSortOrder(gSavedSettings.getU32(DEFAULT_SORT_ORDER)); - } - mFolders->setSortOrder(mFolders->getFilter()->getSortOrder()); - - return TRUE; -} - -LLInventoryPanel::~LLInventoryPanel() -{ - // should this be a global setting? - if (mFolders) - { - U32 sort_order = mFolders->getSortOrder(); - if (mSortOrderSetting != INHERIT_SORT_ORDER) - { - gSavedSettings.setU32(mSortOrderSetting, sort_order); - } - } - - // LLView destructor will take care of the sub-views. - mInventory->removeObserver(mInventoryObserver); - delete mInventoryObserver; - mScroller = NULL; -} - -LLMemType mt(LLMemType::MTYPE_INVENTORY_FROM_XML); // ! BUG ! Should this be removed? -void LLInventoryPanel::draw() -{ - // select the desired item (in case it wasn't loaded when the selection was requested) - mFolders->updateSelection(); - LLPanel::draw(); -} - -LLInventoryFilter* LLInventoryPanel::getFilter() -{ - if (mFolders) return mFolders->getFilter(); - return NULL; -} - -void LLInventoryPanel::setFilterTypes(U64 filter_types, BOOL filter_for_categories) -{ - mFolders->getFilter()->setFilterTypes(filter_types, filter_for_categories); -} - -void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask) -{ - mFolders->getFilter()->setFilterPermissions(filter_perm_mask); -} - -void LLInventoryPanel::setFilterSubString(const std::string& string) -{ - mFolders->getFilter()->setFilterSubString(string); -} - -void LLInventoryPanel::setSortOrder(U32 order) -{ - mFolders->getFilter()->setSortOrder(order); - if (mFolders->getFilter()->isModified()) - { - mFolders->setSortOrder(order); - // try to keep selection onscreen, even if it wasn't to start with - mFolders->scrollToShowSelection(); - } -} - -void LLInventoryPanel::setSinceLogoff(BOOL sl) -{ - mFolders->getFilter()->setDateRangeLastLogoff(sl); -} - -void LLInventoryPanel::setHoursAgo(U32 hours) -{ - mFolders->getFilter()->setHoursAgo(hours); -} - -void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show) -{ - mFolders->getFilter()->setShowFolderState(show); -} - -LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState() -{ - return mFolders->getFilter()->getShowFolderState(); -} - -static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh"); - -void LLInventoryPanel::modelChanged(U32 mask) -{ - LLFastTimer t2(FTM_REFRESH); - - bool handled = false; - - // inventory just initialized, do complete build - if ((mask & LLInventoryObserver::ADD) && gInventory.getChangedIDs().empty() && !mHasInventoryConnection) - { - rebuildViewsFor(mStartFolderID); - mHasInventoryConnection = true; - return; - } - - if(mask & LLInventoryObserver::LABEL) - { - handled = true; - // label change - empty out the display name for each object - // in this change set. - const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); - std::set<LLUUID>::const_iterator id_it = changed_items.begin(); - std::set<LLUUID>::const_iterator id_end = changed_items.end(); - LLFolderViewItem* view = NULL; - LLInvFVBridge* bridge = NULL; - for (;id_it != id_end; ++id_it) - { - view = mFolders->getItemByID(*id_it); - if(view) - { - // request refresh on this item (also flags for filtering) - bridge = (LLInvFVBridge*)view->getListener(); - if(bridge) - { // Clear the display name first, so it gets properly re-built during refresh() - bridge->clearDisplayName(); - } - view->refresh(); - } - } - } - if((mask & (LLInventoryObserver::STRUCTURE - | LLInventoryObserver::ADD - | LLInventoryObserver::REMOVE)) != 0) - { - handled = true; - // Record which folders are open by uuid. - LLInventoryModel* model = getModel(); - if (model) - { - const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); - - std::set<LLUUID>::const_iterator id_it = changed_items.begin(); - std::set<LLUUID>::const_iterator id_end = changed_items.end(); - for (;id_it != id_end; ++id_it) - { - // sync view with model - LLInventoryObject* model_item = model->getObject(*id_it); - LLFolderViewItem* view_item = mFolders->getItemByID(*id_it); - - if (model_item) - { - if (!view_item) - { - // this object was just created, need to build a view for it - if ((mask & LLInventoryObserver::ADD) != LLInventoryObserver::ADD) - { - llwarns << *id_it << " is in model but not in view, but ADD flag not set" << llendl; - } - buildNewViews(*id_it); - - // select any newly created object - // that has the auto rename at top of folder - // root set - if(mFolders->getRoot()->needsAutoRename()) - { - setSelection(*id_it, FALSE); - } - } - else - { - // this object was probably moved, check its parent - if ((mask & LLInventoryObserver::STRUCTURE) != LLInventoryObserver::STRUCTURE) - { - llwarns << *id_it << " is in model and in view, but STRUCTURE flag not set" << llendl; - } - - LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID()); - - // added check against NULL for cases when Inventory panel contains startFolder. - // in this case parent is LLFolderView (LLInventoryPanel::mFolders) itself. - // this check is a fix for bug EXT-1859. - if (NULL != new_parent && view_item->getParentFolder() != new_parent) - { - view_item->getParentFolder()->extractItem(view_item); - view_item->addToFolder(new_parent, mFolders); - } -/* - on the other side in case Inventory Panel has content of the any folder - it is possible that item moved to some folder which is absent in current - Panel. For ex. removing item (via moving to trash). - In this case we need to check if new parent is other then inventory start folder - and simply remove its View from the hierarchy. - See details in EXT-2098. -*/ - // So, let check if item was moved into folder out of this Inventory Panel. - else if (mStartFolderID.notNull() && NULL == new_parent && model_item->getParentUUID() != mStartFolderID) - { - view_item->getParentFolder()->extractItem(view_item); - } - } - } - else - { - if (view_item) - { - if ((mask & LLInventoryObserver::REMOVE) != LLInventoryObserver::REMOVE) - { - llwarns << *id_it << " is not in model but in view, but REMOVE flag not set" << llendl; - } - // item in view but not model, need to delete view - view_item->destroyView(); - } - else - { - llwarns << *id_it << "Item does not exist in either view or model, but notification triggered" << llendl; - } - } - } - } - } - - if (!handled) - { - // it's a small change that only requires a refresh. - // *TODO: figure out a more efficient way to do the refresh - // since it is expensive on large inventories - mFolders->refresh(); - } -} - - -void LLInventoryPanel::rebuildViewsFor(const LLUUID& id) -{ - LLFolderViewItem* old_view = NULL; - - // get old LLFolderViewItem - old_view = mFolders->getItemByID(id); - if (old_view && id.notNull()) - { - old_view->destroyView(); - } - - buildNewViews(id); -} - -void LLInventoryPanel::buildNewViews(const LLUUID& id) -{ - LLMemType mt(LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS); - LLFolderViewItem* itemp = NULL; - LLInventoryObject* objectp = NULL; - - // Don't add the start folder (the inventory panel will show contents - // beginning with the children of the starting folder, excluding the starting folder itself). - if (id != mStartFolderID) - { - objectp = gInventory.getObject(id); - if (objectp) - { - const LLUUID &parent_id = objectp->getParentUUID(); - // If this item's parent is the starting folder, then just add it to the top level (recall that - // the starting folder isn't actually represented in the view, parent_folder would be NULL in - // this case otherwise). - LLFolderViewFolder* parent_folder = (parent_id == mStartFolderID ? - mFolders : (LLFolderViewFolder*)mFolders->getItemByID(parent_id)); - - // This item exists outside the inventory's hierarchy, so don't add it. - if (!parent_folder) - { - return; - } - - if (objectp->getType() <= LLAssetType::AT_NONE || - objectp->getType() >= LLAssetType::AT_COUNT) - { - llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " << - ((S32) objectp->getType()) << llendl; - return; - } - - if (objectp->getType() == LLAssetType::AT_CATEGORY && - objectp->getActualType() != LLAssetType::AT_LINK_FOLDER) - { - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(), - objectp->getType(), - LLInventoryType::IT_CATEGORY, - this, - objectp->getUUID()); - - if (new_listener) - { - LLFolderViewFolder::Params p; - p.name = new_listener->getDisplayName(); - p.icon = new_listener->getIcon(); - p.root = mFolders; - p.listener = new_listener; - LLFolderViewFolder* folderp = LLUICtrlFactory::create<LLFolderViewFolder>(p); - - folderp->setItemSortOrder(mFolders->getSortOrder()); - itemp = folderp; - } - } - else - { - // Build new view for item - LLInventoryItem* item = (LLInventoryItem*)objectp; - LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(), - item->getActualType(), - item->getInventoryType(), - this, - item->getUUID(), - item->getFlags()); - - if (new_listener) - { - LLFolderViewItem::Params params; - params.name(new_listener->getDisplayName()); - params.icon(new_listener->getIcon()); - params.creation_date(new_listener->getCreationDate()); - params.root(mFolders); - params.listener(new_listener); - params.rect(LLRect (0, 0, 0, 0)); - itemp = LLUICtrlFactory::create<LLFolderViewItem> (params); - } - } - - if (itemp) - { - itemp->addToFolder(parent_folder, mFolders); - } - } - } - - // If this is a folder, add the children of the folder and recursively add any - // child folders. - if ((id == mStartFolderID) || - (objectp && objectp->getType() == LLAssetType::AT_CATEGORY)) - { - LLViewerInventoryCategory::cat_array_t* categories; - LLViewerInventoryItem::item_array_t* items; - - mInventory->lockDirectDescendentArrays(id, categories, items); - if(categories) - { - S32 count = categories->count(); - for(S32 i = 0; i < count; ++i) - { - LLInventoryCategory* cat = categories->get(i); - buildNewViews(cat->getUUID()); - } - } - if(items) - { - S32 count = items->count(); - for(S32 i = 0; i < count; ++i) - { - LLInventoryItem* item = items->get(i); - buildNewViews(item->getUUID()); - } - } - mInventory->unlockDirectDescendentArrays(id); - } -} - -struct LLConfirmPurgeData -{ - LLUUID mID; - LLInventoryModel* mModel; -}; - -class LLIsNotWorn : public LLInventoryCollectFunctor -{ -public: - LLIsNotWorn() {} - virtual ~LLIsNotWorn() {} - virtual bool operator()(LLInventoryCategory* cat, - LLInventoryItem* item) - { - return !gAgentWearables.isWearingItem(item->getUUID()); - } -}; - -class LLOpenFolderByID : public LLFolderViewFunctor -{ -public: - LLOpenFolderByID(const LLUUID& id) : mID(id) {} - virtual ~LLOpenFolderByID() {} - virtual void doFolder(LLFolderViewFolder* folder) - { - if (folder->getListener() && folder->getListener()->getUUID() == mID) folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP); - } - virtual void doItem(LLFolderViewItem* item) {} -protected: - const LLUUID& mID; -}; - - -void LLInventoryPanel::openSelected() -{ - LLFolderViewItem* folder_item = mFolders->getCurSelectedItem(); - if(!folder_item) return; - LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener(); - if(!bridge) return; - bridge->openItem(); -} - -BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask) -{ - BOOL handled = LLView::handleHover(x, y, mask); - if(handled) - { - ECursorType cursor = getWindow()->getCursor(); - if (LLInventoryModel::backgroundFetchActive() && cursor == UI_CURSOR_ARROW) - { - // replace arrow cursor with arrow and hourglass cursor - getWindow()->setCursor(UI_CURSOR_WORKING); - } - } - else - { - getWindow()->setCursor(UI_CURSOR_ARROW); - } - return TRUE; -} - -BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - - BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - - if (handled) - { - mFolders->setDragAndDropThisFrame(); - } - - return handled; -} - -void LLInventoryPanel::onFocusLost() -{ - // inventory no longer handles cut/copy/paste/delete - if (LLEditMenuHandler::gEditMenuHandler == mFolders) - { - LLEditMenuHandler::gEditMenuHandler = NULL; - } - - LLPanel::onFocusLost(); -} - -void LLInventoryPanel::onFocusReceived() -{ - // inventory now handles cut/copy/paste/delete - LLEditMenuHandler::gEditMenuHandler = mFolders; - - LLPanel::onFocusReceived(); -} - - -void LLInventoryPanel::openAllFolders() -{ - mFolders->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN); - mFolders->arrangeAll(); -} - -void LLInventoryPanel::openDefaultFolderForType(LLFolderType::EType type) -{ - LLUUID category_id = mInventory->findCategoryUUIDForType(type); - LLOpenFolderByID opener(category_id); - mFolders->applyFunctorRecursively(opener); -} - -void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus) -{ - // Don't select objects in COF (e.g. to prevent refocus when items are worn). - const LLInventoryObject *obj = gInventory.getObject(obj_id); - if (obj && obj->getParentUUID() == LLAppearanceManager::getCOF()) - { - return; - } - mFolders->setSelectionByID(obj_id, take_keyboard_focus); -} - -void LLInventoryPanel::clearSelection() -{ - mFolders->clearSelection(); -} - -void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action) -{ - LLFolderView* fv = getRootFolder(); - if (fv->needsAutoRename()) // auto-selecting a new user-created asset and preparing to rename - { - fv->setNeedsAutoRename(FALSE); - if (items.size()) // new asset is visible and selected - { - fv->startRenamingSelectedItem(); - } - } - // Seraph - Put determineFolderType in here for ensemble typing? -} - -//---------------------------------------------------------------------------- - -void LLInventoryPanel::doToSelected(const LLSD& userdata) -{ - mFolders->doToSelected(&gInventory, userdata); -} - -void LLInventoryPanel::doCreate(const LLSD& userdata) -{ - menu_create_inventory_item(mFolders, LLFolderBridge::sSelf, userdata); -} - -bool LLInventoryPanel::beginIMSession() -{ - std::set<LLUUID> selected_items; - mFolders->getSelectionList(selected_items); - - std::string name; - static int session_num = 1; - - LLDynamicArray<LLUUID> members; - EInstantMessage type = IM_SESSION_CONFERENCE_START; - - std::set<LLUUID>::const_iterator iter; - for (iter = selected_items.begin(); iter != selected_items.end(); iter++) - { - - LLUUID item = *iter; - LLFolderViewItem* folder_item = mFolders->getItemByID(item); - - if(folder_item) - { - LLFolderViewEventListener* fve_listener = folder_item->getListener(); - if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY)) - { - - LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener(); - if(!bridge) return true; - LLViewerInventoryCategory* cat = bridge->getCategory(); - if(!cat) return true; - name = cat->getName(); - LLUniqueBuddyCollector is_buddy; - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - gInventory.collectDescendentsIf(bridge->getUUID(), - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH, - is_buddy); - S32 count = item_array.count(); - if(count > 0) - { - LLFloaterReg::showInstance("communicate"); - // create the session - LLAvatarTracker& at = LLAvatarTracker::instance(); - LLUUID id; - for(S32 i = 0; i < count; ++i) - { - id = item_array.get(i)->getCreatorUUID(); - if(at.isBuddyOnline(id)) - { - members.put(id); - } - } - } - } - else - { - LLFolderViewItem* folder_item = mFolders->getItemByID(item); - if(!folder_item) return true; - LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener(); - - if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD) - { - LLInventoryItem* inv_item = gInventory.getItem(listenerp->getUUID()); - - if (inv_item) - { - LLAvatarTracker& at = LLAvatarTracker::instance(); - LLUUID id = inv_item->getCreatorUUID(); - - if(at.isBuddyOnline(id)) - { - members.put(id); - } - } - } //if IT_CALLINGCARD - } //if !IT_CATEGORY - } - } //for selected_items - - // the session_id is randomly generated UUID which will be replaced later - // with a server side generated number - - if (name.empty()) - { - name = llformat("Session %d", session_num++); - } - - gIMMgr->addSession(name, type, members[0], members); - - return true; -} - -bool LLInventoryPanel::attachObject(const LLSD& userdata) -{ - std::set<LLUUID> selected_items; - mFolders->getSelectionList(selected_items); - - std::string joint_name = userdata.asString(); - LLVOAvatar *avatarp = static_cast<LLVOAvatar*>(gAgent.getAvatarObject()); - LLViewerJointAttachment* attachmentp = NULL; - for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); - iter != avatarp->mAttachmentPoints.end(); ) - { - LLVOAvatar::attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachment = curiter->second; - if (attachment->getName() == joint_name) - { - attachmentp = attachment; - break; - } - } - if (attachmentp == NULL) - { - return true; - } - - for (std::set<LLUUID>::const_iterator set_iter = selected_items.begin(); - set_iter != selected_items.end(); - ++set_iter) - { - const LLUUID &id = *set_iter; - LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(id); - if(item && gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID())) - { - rez_attachment(item, attachmentp); - } - else if(item && item->isComplete()) - { - // must be in library. copy it to our inventory and put it on. - LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(attachmentp); - copy_inventory_item(gAgent.getID(), - item->getPermissions().getOwner(), - item->getUUID(), - LLUUID::null, - std::string(), - cb); - } - } - gFocusMgr.setKeyboardFocus(NULL); - - return true; -} - - -//---------------------------------------------------------------------------- - -// static DEBUG ONLY: -void LLInventoryPanel::dumpSelectionInformation(void* user_data) -{ - LLInventoryPanel* iv = (LLInventoryPanel*)user_data; - iv->mFolders->dumpSelectionInformation(); -} - -BOOL LLInventoryPanel::getSinceLogoff() -{ - return mFolders->getFilter()->isSinceLogoff(); -} - -void example_param_block_usage() -{ - LLInventoryPanel::Params param_block; - param_block.name(std::string("inventory")); - - param_block.sort_order_setting(LLInventoryPanel::RECENTITEMS_SORT_ORDER); - param_block.allow_multi_select(true); - param_block.filter(LLInventoryPanel::Filter() - .sort_order(1) - .types(0xffff0000)); - param_block.inventory(&gInventory); - param_block.has_border(true); - - LLUICtrlFactory::create<LLInventoryPanel>(param_block); - - param_block = LLInventoryPanel::Params(); - param_block.name(std::string("inventory")); - - //LLSD param_block_sd; - //param_block_sd["sort_order_setting"] = LLInventoryPanel::RECENTITEMS_SORT_ORDER; - //param_block_sd["allow_multi_select"] = true; - //param_block_sd["filter"]["sort_order"] = 1; - //param_block_sd["filter"]["types"] = (S32)0xffff0000; - //param_block_sd["has_border"] = true; - - //LLInitParam::LLSDParser(param_block_sd).parse(param_block); - - LLUICtrlFactory::create<LLInventoryPanel>(param_block); -} +/*
+ * @file llinventorypanel.cpp
+ * @brief Implementation of the inventory panel and associated stuff.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include <utility> // for std::pair<>
+
+#include "llinventorypanel.h"
+
+// Seraph TODO: Remove unnecessary headers
+
+// library includes
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "llcallingcard.h"
+#include "llfloaterreg.h"
+#include "llsdserialize.h"
+#include "llfiltereditor.h"
+#include "llspinctrl.h"
+#include "llui.h"
+#include "message.h"
+
+// newview includes
+#include "llappearancemgr.h"
+#include "llappviewer.h"
+#include "llfirstuse.h"
+#include "llfloaterchat.h"
+#include "llfloatercustomize.h"
+#include "llfocusmgr.h"
+#include "llfolderview.h"
+#include "llgesturemgr.h"
+#include "lliconctrl.h"
+#include "llimview.h"
+#include "llinventorybridge.h"
+#include "llinventoryclipboard.h"
+#include "llinventorymodel.h"
+#include "lllineeditor.h"
+#include "llmenugl.h"
+#include "llpreviewanim.h"
+#include "llpreviewgesture.h"
+#include "llpreviewnotecard.h"
+#include "llpreviewscript.h"
+#include "llpreviewsound.h"
+#include "llpreviewtexture.h"
+#include "llresmgr.h"
+#include "llscrollbar.h"
+#include "llscrollcontainer.h"
+#include "llselectmgr.h"
+#include "lltabcontainer.h"
+#include "lltooldraganddrop.h"
+#include "lluictrlfactory.h"
+#include "llviewerfoldertype.h"
+#include "llviewerinventory.h"
+#include "llviewermessage.h"
+#include "llviewerobjectlist.h"
+#include "llviewerregion.h"
+#include "llviewerwindow.h"
+#include "llvoavatarself.h"
+#include "llwearablelist.h"
+#include "llimfloater.h"
+
+static LLDefaultChildRegistry::Register<LLInventoryPanel> r("inventory_panel");
+
+const std::string LLInventoryPanel::DEFAULT_SORT_ORDER = std::string("InventorySortOrder");
+const std::string LLInventoryPanel::RECENTITEMS_SORT_ORDER = std::string("RecentItemsSortOrder");
+const std::string LLInventoryPanel::INHERIT_SORT_ORDER = std::string("");
+static const LLInventoryFVBridgeBuilder INVENTORY_BRIDGE_BUILDER;
+
+LLInventoryPanel::LLInventoryPanel(const LLInventoryPanel::Params& p) :
+ LLPanel(p),
+ mInventoryObserver(NULL),
+ mFolders(NULL),
+ mScroller(NULL),
+ mSortOrderSetting(p.sort_order_setting),
+ mInventory(p.inventory),
+ mAllowMultiSelect(p.allow_multi_select),
+ mHasInventoryConnection(false),
+ mStartFolderString(p.start_folder),
+ mBuildDefaultHierarchy(true),
+ mInvFVBridgeBuilder(NULL)
+{
+ mInvFVBridgeBuilder = &INVENTORY_BRIDGE_BUILDER;
+
+ // contex menu callbacks
+ mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));
+ mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND));
+ mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLInventoryPanel::doCreate, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.AttachObject", boost::bind(&LLInventoryPanel::attachObject, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.BeginIMSession", boost::bind(&LLInventoryPanel::beginIMSession, this));
+
+ setBackgroundColor(LLUIColorTable::instance().getColor("InventoryBackgroundColor"));
+ setBackgroundVisible(TRUE);
+ setBackgroundOpaque(TRUE);
+}
+
+BOOL LLInventoryPanel::postBuild()
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_POST_BUILD);
+
+ mCommitCallbackRegistrar.pushScope(); // registered as a widget; need to push callback scope ourselves
+
+ // create root folder
+ {
+ LLRect folder_rect(0,
+ 0,
+ getRect().getWidth(),
+ 0);
+ LLFolderView::Params p;
+ p.name = getName();
+ p.rect = folder_rect;
+ p.parent_panel = this;
+ mFolders = LLUICtrlFactory::create<LLFolderView>(p);
+ mFolders->setAllowMultiSelect(mAllowMultiSelect);
+ }
+
+ mCommitCallbackRegistrar.popScope();
+
+ mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar);
+
+ // scroller
+ {
+ LLRect scroller_view_rect = getRect();
+ scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
+ LLScrollContainer::Params p;
+ p.name("Inventory Scroller");
+ p.rect(scroller_view_rect);
+ p.follows.flags(FOLLOWS_ALL);
+ p.reserve_scroll_corner(true);
+ p.tab_stop(true);
+ mScroller = LLUICtrlFactory::create<LLScrollContainer>(p);
+ }
+ addChild(mScroller);
+ mScroller->addChild(mFolders);
+
+ mFolders->setScrollContainer(mScroller);
+
+ // set up the callbacks from the inventory we're viewing, and then
+ // build everything.
+ mInventoryObserver = new LLInventoryPanelObserver(this);
+ mInventory->addObserver(mInventoryObserver);
+
+ // determine the root folder, if any, so inventory contents show just the children
+ // of that folder (i.e. not including the folder itself).
+ const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
+
+ if ("INVENTORY" == mStartFolderString)
+ {
+ mStartFolderID = gInventory.getRootFolderID();
+ }
+ else if ("LIBRARY" == mStartFolderString)
+ {
+ mStartFolderID = gInventory.getLibraryRootFolderID();
+ }
+ else
+ {
+ mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
+ }
+
+ // build view of inventory if we need default full hierarchy and inventory ready, otherwise wait for modelChanged() callback
+ if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mHasInventoryConnection)
+ {
+ rebuildViewsFor(mStartFolderID);
+ mHasInventoryConnection = true;
+ }
+
+ // bit of a hack to make sure the inventory is open.
+ mFolders->openFolder(preferred_type != LLFolderType::FT_NONE ? LLViewerFolderType::lookupNewCategoryName(preferred_type) : "My Inventory");
+
+ if (mSortOrderSetting != INHERIT_SORT_ORDER)
+ {
+ setSortOrder(gSavedSettings.getU32(mSortOrderSetting));
+ }
+ else
+ {
+ setSortOrder(gSavedSettings.getU32(DEFAULT_SORT_ORDER));
+ }
+ mFolders->setSortOrder(mFolders->getFilter()->getSortOrder());
+
+ return TRUE;
+}
+
+LLInventoryPanel::~LLInventoryPanel()
+{
+ // should this be a global setting?
+ if (mFolders)
+ {
+ U32 sort_order = mFolders->getSortOrder();
+ if (mSortOrderSetting != INHERIT_SORT_ORDER)
+ {
+ gSavedSettings.setU32(mSortOrderSetting, sort_order);
+ }
+ }
+
+ // LLView destructor will take care of the sub-views.
+ mInventory->removeObserver(mInventoryObserver);
+ delete mInventoryObserver;
+ mScroller = NULL;
+}
+
+LLMemType mt(LLMemType::MTYPE_INVENTORY_FROM_XML); // ! BUG ! Should this be removed?
+void LLInventoryPanel::draw()
+{
+ // select the desired item (in case it wasn't loaded when the selection was requested)
+ mFolders->updateSelection();
+ LLPanel::draw();
+}
+
+LLInventoryFilter* LLInventoryPanel::getFilter()
+{
+ if (mFolders) return mFolders->getFilter();
+ return NULL;
+}
+
+void LLInventoryPanel::setFilterTypes(U64 filter_types, BOOL filter_for_categories)
+{
+ mFolders->getFilter()->setFilterTypes(filter_types, filter_for_categories);
+}
+
+void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask)
+{
+ mFolders->getFilter()->setFilterPermissions(filter_perm_mask);
+}
+
+void LLInventoryPanel::setFilterSubString(const std::string& string)
+{
+ mFolders->getFilter()->setFilterSubString(string);
+}
+
+void LLInventoryPanel::setSortOrder(U32 order)
+{
+ mFolders->getFilter()->setSortOrder(order);
+ if (mFolders->getFilter()->isModified())
+ {
+ mFolders->setSortOrder(order);
+ // try to keep selection onscreen, even if it wasn't to start with
+ mFolders->scrollToShowSelection();
+ }
+}
+
+void LLInventoryPanel::setSinceLogoff(BOOL sl)
+{
+ mFolders->getFilter()->setDateRangeLastLogoff(sl);
+}
+
+void LLInventoryPanel::setHoursAgo(U32 hours)
+{
+ mFolders->getFilter()->setHoursAgo(hours);
+}
+
+void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show)
+{
+ mFolders->getFilter()->setShowFolderState(show);
+}
+
+LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()
+{
+ return mFolders->getFilter()->getShowFolderState();
+}
+
+static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh");
+
+void LLInventoryPanel::modelChanged(U32 mask)
+{
+ LLFastTimer t2(FTM_REFRESH);
+
+ bool handled = false;
+
+ // inventory just initialized, do complete build
+ if ((mask & LLInventoryObserver::ADD) && gInventory.getChangedIDs().empty() && !mHasInventoryConnection)
+ {
+ rebuildViewsFor(mStartFolderID);
+ mHasInventoryConnection = true;
+ return;
+ }
+
+ if(mask & LLInventoryObserver::LABEL)
+ {
+ handled = true;
+ // label change - empty out the display name for each object
+ // in this change set.
+ const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
+ std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+ std::set<LLUUID>::const_iterator id_end = changed_items.end();
+ LLFolderViewItem* view = NULL;
+ LLInvFVBridge* bridge = NULL;
+ for (;id_it != id_end; ++id_it)
+ {
+ view = mFolders->getItemByID(*id_it);
+ if(view)
+ {
+ // request refresh on this item (also flags for filtering)
+ bridge = (LLInvFVBridge*)view->getListener();
+ if(bridge)
+ { // Clear the display name first, so it gets properly re-built during refresh()
+ bridge->clearDisplayName();
+ }
+ view->refresh();
+ }
+ }
+ }
+ if((mask & (LLInventoryObserver::STRUCTURE
+ | LLInventoryObserver::ADD
+ | LLInventoryObserver::REMOVE)) != 0)
+ {
+ handled = true;
+ // Record which folders are open by uuid.
+ LLInventoryModel* model = getModel();
+ if (model)
+ {
+ const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
+
+ std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+ std::set<LLUUID>::const_iterator id_end = changed_items.end();
+ for (;id_it != id_end; ++id_it)
+ {
+ // sync view with model
+ LLInventoryObject* model_item = model->getObject(*id_it);
+ LLFolderViewItem* view_item = mFolders->getItemByID(*id_it);
+
+ if (model_item)
+ {
+ if (!view_item)
+ {
+ // this object was just created, need to build a view for it
+ if ((mask & LLInventoryObserver::ADD) != LLInventoryObserver::ADD)
+ {
+ llwarns << *id_it << " is in model but not in view, but ADD flag not set" << llendl;
+ }
+ buildNewViews(*id_it);
+
+ // select any newly created object
+ // that has the auto rename at top of folder
+ // root set
+ if(mFolders->getRoot()->needsAutoRename())
+ {
+ setSelection(*id_it, FALSE);
+ }
+ }
+ else
+ {
+ // this object was probably moved, check its parent
+ if ((mask & LLInventoryObserver::STRUCTURE) != LLInventoryObserver::STRUCTURE)
+ {
+ llwarns << *id_it << " is in model and in view, but STRUCTURE flag not set" << llendl;
+ }
+
+ LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID());
+
+ // added check against NULL for cases when Inventory panel contains startFolder.
+ // in this case parent is LLFolderView (LLInventoryPanel::mFolders) itself.
+ // this check is a fix for bug EXT-1859.
+ if (NULL != new_parent && view_item->getParentFolder() != new_parent)
+ {
+ view_item->getParentFolder()->extractItem(view_item);
+ view_item->addToFolder(new_parent, mFolders);
+ }
+/*
+ on the other side in case Inventory Panel has content of the any folder
+ it is possible that item moved to some folder which is absent in current
+ Panel. For ex. removing item (via moving to trash).
+ In this case we need to check if new parent is other then inventory start folder
+ and simply remove its View from the hierarchy.
+ See details in EXT-2098.
+*/
+ // So, let check if item was moved into folder out of this Inventory Panel.
+ else if (mStartFolderID.notNull() && NULL == new_parent && model_item->getParentUUID() != mStartFolderID)
+ {
+ view_item->getParentFolder()->extractItem(view_item);
+ }
+ }
+ }
+ else
+ {
+ if (view_item)
+ {
+ if ((mask & LLInventoryObserver::REMOVE) != LLInventoryObserver::REMOVE)
+ {
+ llwarns << *id_it << " is not in model but in view, but REMOVE flag not set" << llendl;
+ }
+ // item in view but not model, need to delete view
+ view_item->destroyView();
+ }
+ else
+ {
+ llwarns << *id_it << "Item does not exist in either view or model, but notification triggered" << llendl;
+ }
+ }
+ }
+ }
+ }
+
+ if (!handled)
+ {
+ // it's a small change that only requires a refresh.
+ // *TODO: figure out a more efficient way to do the refresh
+ // since it is expensive on large inventories
+ mFolders->refresh();
+ }
+}
+
+
+void LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
+{
+ LLFolderViewItem* old_view = NULL;
+
+ // get old LLFolderViewItem
+ old_view = mFolders->getItemByID(id);
+ if (old_view && id.notNull())
+ {
+ old_view->destroyView();
+ }
+
+ buildNewViews(id);
+}
+
+void LLInventoryPanel::buildNewViews(const LLUUID& id)
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS);
+ LLFolderViewItem* itemp = NULL;
+ LLInventoryObject* objectp = NULL;
+
+ // Don't add the start folder (the inventory panel will show contents
+ // beginning with the children of the starting folder, excluding the starting folder itself).
+ if (id != mStartFolderID)
+ {
+ objectp = gInventory.getObject(id);
+ if (objectp)
+ {
+ const LLUUID &parent_id = objectp->getParentUUID();
+ // If this item's parent is the starting folder, then just add it to the top level (recall that
+ // the starting folder isn't actually represented in the view, parent_folder would be NULL in
+ // this case otherwise).
+ LLFolderViewFolder* parent_folder = (parent_id == mStartFolderID ?
+ mFolders : (LLFolderViewFolder*)mFolders->getItemByID(parent_id));
+
+ // This item exists outside the inventory's hierarchy, so don't add it.
+ if (!parent_folder)
+ {
+ return;
+ }
+
+ if (objectp->getType() <= LLAssetType::AT_NONE ||
+ objectp->getType() >= LLAssetType::AT_COUNT)
+ {
+ lldebugs << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " <<
+ ((S32) objectp->getType()) << " name " << objectp->getName() << " UUID " << objectp->getUUID() << llendl;
+ return;
+ }
+
+ if (objectp->getType() == LLAssetType::AT_CATEGORY &&
+ objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)
+ {
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(objectp->getType(),
+ objectp->getType(),
+ LLInventoryType::IT_CATEGORY,
+ this,
+ objectp->getUUID());
+
+ if (new_listener)
+ {
+ LLFolderViewFolder::Params p;
+ p.name = new_listener->getDisplayName();
+ p.icon = new_listener->getIcon();
+ p.root = mFolders;
+ p.listener = new_listener;
+ LLFolderViewFolder* folderp = LLUICtrlFactory::create<LLFolderViewFolder>(p);
+
+ folderp->setItemSortOrder(mFolders->getSortOrder());
+ itemp = folderp;
+ }
+ }
+ else
+ {
+ // Build new view for item
+ LLInventoryItem* item = (LLInventoryItem*)objectp;
+ LLInvFVBridge* new_listener = mInvFVBridgeBuilder->createBridge(item->getType(),
+ item->getActualType(),
+ item->getInventoryType(),
+ this,
+ item->getUUID(),
+ item->getFlags());
+
+ if (new_listener)
+ {
+ LLFolderViewItem::Params params;
+ params.name(new_listener->getDisplayName());
+ params.icon(new_listener->getIcon());
+ params.creation_date(new_listener->getCreationDate());
+ params.root(mFolders);
+ params.listener(new_listener);
+ params.rect(LLRect (0, 0, 0, 0));
+ itemp = LLUICtrlFactory::create<LLFolderViewItem> (params);
+ }
+ }
+
+ if (itemp)
+ {
+ itemp->addToFolder(parent_folder, mFolders);
+ }
+ }
+ }
+
+ // If this is a folder, add the children of the folder and recursively add any
+ // child folders.
+ if ((id == mStartFolderID) ||
+ (objectp && objectp->getType() == LLAssetType::AT_CATEGORY))
+ {
+ LLViewerInventoryCategory::cat_array_t* categories;
+ LLViewerInventoryItem::item_array_t* items;
+
+ mInventory->lockDirectDescendentArrays(id, categories, items);
+ if(categories)
+ {
+ S32 count = categories->count();
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLInventoryCategory* cat = categories->get(i);
+ buildNewViews(cat->getUUID());
+ }
+ }
+ if(items)
+ {
+ S32 count = items->count();
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLInventoryItem* item = items->get(i);
+ buildNewViews(item->getUUID());
+ }
+ }
+ mInventory->unlockDirectDescendentArrays(id);
+ }
+}
+
+struct LLConfirmPurgeData
+{
+ LLUUID mID;
+ LLInventoryModel* mModel;
+};
+
+class LLIsNotWorn : public LLInventoryCollectFunctor
+{
+public:
+ LLIsNotWorn() {}
+ virtual ~LLIsNotWorn() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item)
+ {
+ return !gAgentWearables.isWearingItem(item->getUUID());
+ }
+};
+
+class LLOpenFolderByID : public LLFolderViewFunctor
+{
+public:
+ LLOpenFolderByID(const LLUUID& id) : mID(id) {}
+ virtual ~LLOpenFolderByID() {}
+ virtual void doFolder(LLFolderViewFolder* folder)
+ {
+ if (folder->getListener() && folder->getListener()->getUUID() == mID) folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ }
+ virtual void doItem(LLFolderViewItem* item) {}
+protected:
+ const LLUUID& mID;
+};
+
+
+void LLInventoryPanel::openSelected()
+{
+ LLFolderViewItem* folder_item = mFolders->getCurSelectedItem();
+ if(!folder_item) return;
+ LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener();
+ if(!bridge) return;
+ bridge->openItem();
+}
+
+BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = LLView::handleHover(x, y, mask);
+ if(handled)
+ {
+ ECursorType cursor = getWindow()->getCursor();
+ if (LLInventoryModel::backgroundFetchActive() && cursor == UI_CURSOR_ARROW)
+ {
+ // replace arrow cursor with arrow and hourglass cursor
+ getWindow()->setCursor(UI_CURSOR_WORKING);
+ }
+ }
+ else
+ {
+ getWindow()->setCursor(UI_CURSOR_ARROW);
+ }
+ return TRUE;
+}
+
+BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+{
+
+ BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+
+ if (handled)
+ {
+ mFolders->setDragAndDropThisFrame();
+ }
+
+ return handled;
+}
+
+void LLInventoryPanel::onFocusLost()
+{
+ // inventory no longer handles cut/copy/paste/delete
+ if (LLEditMenuHandler::gEditMenuHandler == mFolders)
+ {
+ LLEditMenuHandler::gEditMenuHandler = NULL;
+ }
+
+ LLPanel::onFocusLost();
+}
+
+void LLInventoryPanel::onFocusReceived()
+{
+ // inventory now handles cut/copy/paste/delete
+ LLEditMenuHandler::gEditMenuHandler = mFolders;
+
+ LLPanel::onFocusReceived();
+}
+
+
+void LLInventoryPanel::openAllFolders()
+{
+ mFolders->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN);
+ mFolders->arrangeAll();
+}
+
+void LLInventoryPanel::openDefaultFolderForType(LLFolderType::EType type)
+{
+ LLUUID category_id = mInventory->findCategoryUUIDForType(type);
+ LLOpenFolderByID opener(category_id);
+ mFolders->applyFunctorRecursively(opener);
+}
+
+void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus)
+{
+ // Don't select objects in COF (e.g. to prevent refocus when items are worn).
+ const LLInventoryObject *obj = gInventory.getObject(obj_id);
+ if (obj && obj->getParentUUID() == LLAppearanceManager::getCOF())
+ {
+ return;
+ }
+ mFolders->setSelectionByID(obj_id, take_keyboard_focus);
+}
+
+void LLInventoryPanel::clearSelection()
+{
+ mFolders->clearSelection();
+}
+
+void LLInventoryPanel::onSelectionChange(const std::deque<LLFolderViewItem*>& items, BOOL user_action)
+{
+ LLFolderView* fv = getRootFolder();
+ if (fv->needsAutoRename()) // auto-selecting a new user-created asset and preparing to rename
+ {
+ fv->setNeedsAutoRename(FALSE);
+ if (items.size()) // new asset is visible and selected
+ {
+ fv->startRenamingSelectedItem();
+ }
+ }
+ // Seraph - Put determineFolderType in here for ensemble typing?
+}
+
+//----------------------------------------------------------------------------
+
+void LLInventoryPanel::doToSelected(const LLSD& userdata)
+{
+ mFolders->doToSelected(&gInventory, userdata);
+}
+
+void LLInventoryPanel::doCreate(const LLSD& userdata)
+{
+ menu_create_inventory_item(mFolders, LLFolderBridge::sSelf, userdata);
+}
+
+bool LLInventoryPanel::beginIMSession()
+{
+ std::set<LLUUID> selected_items;
+ mFolders->getSelectionList(selected_items);
+
+ std::string name;
+ static int session_num = 1;
+
+ LLDynamicArray<LLUUID> members;
+ EInstantMessage type = IM_SESSION_CONFERENCE_START;
+
+ std::set<LLUUID>::const_iterator iter;
+ for (iter = selected_items.begin(); iter != selected_items.end(); iter++)
+ {
+
+ LLUUID item = *iter;
+ LLFolderViewItem* folder_item = mFolders->getItemByID(item);
+
+ if(folder_item)
+ {
+ LLFolderViewEventListener* fve_listener = folder_item->getListener();
+ if (fve_listener && (fve_listener->getInventoryType() == LLInventoryType::IT_CATEGORY))
+ {
+
+ LLFolderBridge* bridge = (LLFolderBridge*)folder_item->getListener();
+ if(!bridge) return true;
+ LLViewerInventoryCategory* cat = bridge->getCategory();
+ if(!cat) return true;
+ name = cat->getName();
+ LLUniqueBuddyCollector is_buddy;
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ gInventory.collectDescendentsIf(bridge->getUUID(),
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_buddy);
+ S32 count = item_array.count();
+ if(count > 0)
+ {
+ LLFloaterReg::showInstance("communicate");
+ // create the session
+ LLAvatarTracker& at = LLAvatarTracker::instance();
+ LLUUID id;
+ for(S32 i = 0; i < count; ++i)
+ {
+ id = item_array.get(i)->getCreatorUUID();
+ if(at.isBuddyOnline(id))
+ {
+ members.put(id);
+ }
+ }
+ }
+ }
+ else
+ {
+ LLFolderViewItem* folder_item = mFolders->getItemByID(item);
+ if(!folder_item) return true;
+ LLInvFVBridge* listenerp = (LLInvFVBridge*)folder_item->getListener();
+
+ if (listenerp->getInventoryType() == LLInventoryType::IT_CALLINGCARD)
+ {
+ LLInventoryItem* inv_item = gInventory.getItem(listenerp->getUUID());
+
+ if (inv_item)
+ {
+ LLAvatarTracker& at = LLAvatarTracker::instance();
+ LLUUID id = inv_item->getCreatorUUID();
+
+ if(at.isBuddyOnline(id))
+ {
+ members.put(id);
+ }
+ }
+ } //if IT_CALLINGCARD
+ } //if !IT_CATEGORY
+ }
+ } //for selected_items
+
+ // the session_id is randomly generated UUID which will be replaced later
+ // with a server side generated number
+
+ if (name.empty())
+ {
+ name = llformat("Session %d", session_num++);
+ }
+
+ LLUUID session_id = gIMMgr->addSession(name, type, members[0], members);
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
+
+ return true;
+}
+
+bool LLInventoryPanel::attachObject(const LLSD& userdata)
+{
+ std::set<LLUUID> selected_items;
+ mFolders->getSelectionList(selected_items);
+
+ std::string joint_name = userdata.asString();
+ LLVOAvatar *avatarp = static_cast<LLVOAvatar*>(gAgent.getAvatarObject());
+ LLViewerJointAttachment* attachmentp = NULL;
+ for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
+ iter != avatarp->mAttachmentPoints.end(); )
+ {
+ LLVOAvatar::attachment_map_t::iterator curiter = iter++;
+ LLViewerJointAttachment* attachment = curiter->second;
+ if (attachment->getName() == joint_name)
+ {
+ attachmentp = attachment;
+ break;
+ }
+ }
+ if (attachmentp == NULL)
+ {
+ return true;
+ }
+
+ for (std::set<LLUUID>::const_iterator set_iter = selected_items.begin();
+ set_iter != selected_items.end();
+ ++set_iter)
+ {
+ const LLUUID &id = *set_iter;
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(id);
+ if(item && gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID()))
+ {
+ rez_attachment(item, attachmentp);
+ }
+ else if(item && item->isComplete())
+ {
+ // must be in library. copy it to our inventory and put it on.
+ LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(attachmentp);
+ copy_inventory_item(gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ }
+ gFocusMgr.setKeyboardFocus(NULL);
+
+ return true;
+}
+
+
+//----------------------------------------------------------------------------
+
+// static DEBUG ONLY:
+void LLInventoryPanel::dumpSelectionInformation(void* user_data)
+{
+ LLInventoryPanel* iv = (LLInventoryPanel*)user_data;
+ iv->mFolders->dumpSelectionInformation();
+}
+
+BOOL LLInventoryPanel::getSinceLogoff()
+{
+ return mFolders->getFilter()->isSinceLogoff();
+}
+
+void example_param_block_usage()
+{
+ LLInventoryPanel::Params param_block;
+ param_block.name(std::string("inventory"));
+
+ param_block.sort_order_setting(LLInventoryPanel::RECENTITEMS_SORT_ORDER);
+ param_block.allow_multi_select(true);
+ param_block.filter(LLInventoryPanel::Filter()
+ .sort_order(1)
+ .types(0xffff0000));
+ param_block.inventory(&gInventory);
+ param_block.has_border(true);
+
+ LLUICtrlFactory::create<LLInventoryPanel>(param_block);
+
+ param_block = LLInventoryPanel::Params();
+ param_block.name(std::string("inventory"));
+
+ //LLSD param_block_sd;
+ //param_block_sd["sort_order_setting"] = LLInventoryPanel::RECENTITEMS_SORT_ORDER;
+ //param_block_sd["allow_multi_select"] = true;
+ //param_block_sd["filter"]["sort_order"] = 1;
+ //param_block_sd["filter"]["types"] = (S32)0xffff0000;
+ //param_block_sd["has_border"] = true;
+
+ //LLInitParam::LLSDParser(param_block_sd).parse(param_block);
+
+ LLUICtrlFactory::create<LLInventoryPanel>(param_block);
+}
diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index bcb4edd7c1..d54545971b 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -695,11 +695,6 @@ LLWString LLNearbyChatBar::stripChannelNumber(const LLWString &mesg, S32* channe } } -void LLNearbyChatBar::setPTTState(bool state) -{ - mSpeakBtn->setSpeakBtnToggleState(state); -} - void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) { LLMessageSystem* msg = gMessageSystem; diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index aa25b6aa68..56ee706a97 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -96,7 +96,6 @@ public: std::string getCurrentChat(); virtual BOOL handleKeyHere( KEY key, MASK mask ); - void setPTTState(bool state); static void startChat(const char* line); static void stopChat(); diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp index 8e3a44682c..75ef5208e7 100644 --- a/indra/newview/llnotificationofferhandler.cpp +++ b/indra/newview/llnotificationofferhandler.cpp @@ -99,6 +99,10 @@ bool LLOfferHandler::processNotification(const LLSD& notify) session_id = LLIMMgr::instance().addSession( notification->getSubstitutions()["NAME"], IM_NOTHING_SPECIAL, notification->getPayload()["from_id"]); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } } LLIMMgr::instance().addMessage(session_id, LLUUID(), notification->getSubstitutions()["NAME"], diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index c516546282..ce1a7f98df 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -267,7 +267,7 @@ LLLandmark* LLLandmarksPanel::getCurSelectedLandmark() const return NULL; } -LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem () const +LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem() const { return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL; } @@ -499,6 +499,7 @@ void LLLandmarksPanel::updateListCommands() // keep Options & Add Landmark buttons always enabled mListCommands->childSetEnabled(ADD_FOLDER_BUTTON_NAME, add_folder_enabled); mListCommands->childSetEnabled(TRASH_BUTTON_NAME, trash_enabled); + mListCommands->childSetEnabled(OPTIONS_BUTTON_NAME,getCurSelectedItem() != NULL); } void LLLandmarksPanel::onActionsButtonClick() @@ -829,17 +830,18 @@ bool LLLandmarksPanel::canSelectedBeModified(const std::string& command_name) co // then ask LLFolderView permissions if (can_be_modified) { + LLFolderViewItem* selected = getCurSelectedItem(); if ("cut" == command_name) { can_be_modified = mCurrentSelectedList->getRootFolder()->canCut(); } else if ("rename" == command_name) { - can_be_modified = getCurSelectedItem()->getListener()->isItemRenameable(); + can_be_modified = selected? selected->getListener()->isItemRenameable() : false; } else if ("delete" == command_name) { - can_be_modified = getCurSelectedItem()->getListener()->isItemRemovable(); + can_be_modified = selected? selected->getListener()->isItemRemovable(): false; } else if("paste" == command_name) { diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h index d54761ed59..745f9364c2 100644 --- a/indra/newview/llpanellandmarks.h +++ b/indra/newview/llpanellandmarks.h @@ -69,7 +69,7 @@ protected: bool isLandmarkSelected() const; bool isReceivedFolderSelected() const; LLLandmark* getCurSelectedLandmark() const; - LLFolderViewItem* getCurSelectedItem () const; + LLFolderViewItem* getCurSelectedItem() const; void updateSortOrder(LLInventoryPanel* panel, bool byDate); //LLRemoteParcelInfoObserver interface diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 25be09fa24..15a75cb930 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -1,818 +1,1025 @@ -/** - * @file llsidepanelmaininventory.cpp - * @brief Implementation of llsidepanelmaininventory. - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llpanelmaininventory.h" - -#include "llfloaterinventory.h" -#include "llinventorybridge.h" -#include "llinventoryfunctions.h" -#include "llinventorypanel.h" -#include "llfiltereditor.h" -#include "llfloaterreg.h" -#include "llscrollcontainer.h" -#include "llsdserialize.h" -#include "llspinctrl.h" -#include "lltooldraganddrop.h" - -static LLRegisterPanelClassWrapper<LLPanelMainInventory> t_inventory("panel_main_inventory"); // Seraph is this redundant with constructor? - -///---------------------------------------------------------------------------- -/// LLFloaterInventoryFinder -///---------------------------------------------------------------------------- - -class LLFloaterInventoryFinder : public LLFloater -{ -public: - LLFloaterInventoryFinder( LLPanelMainInventory* inventory_view); - virtual void draw(); - /*virtual*/ BOOL postBuild(); - void changeFilter(LLInventoryFilter* filter); - void updateElementsFromFilter(); - BOOL getCheckShowEmpty(); - BOOL getCheckSinceLogoff(); - - static void onTimeAgo(LLUICtrl*, void *); - static void onCheckSinceLogoff(LLUICtrl*, void *); - static void onCloseBtn(void* user_data); - static void selectAllTypes(void* user_data); - static void selectNoTypes(void* user_data); -private: - LLPanelMainInventory* mPanelInventoryDecorated; - LLSpinCtrl* mSpinSinceDays; - LLSpinCtrl* mSpinSinceHours; - LLInventoryFilter* mFilter; -}; - -///---------------------------------------------------------------------------- -/// LLPanelMainInventory -///---------------------------------------------------------------------------- - -LLPanelMainInventory::LLPanelMainInventory() - : LLPanel() -{ - LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_INIT); - // Menu Callbacks (non contex menus) - mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelMainInventory::doToSelected, this, _2)); - mCommitCallbackRegistrar.add("Inventory.CloseAllFolders", boost::bind(&LLPanelMainInventory::closeAllFolders, this)); - mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH)); - mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)); - mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLPanelMainInventory::doCreate, this, _2)); - mCommitCallbackRegistrar.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow, this)); - mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLPanelMainInventory::toggleFindOptions, this)); - mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLPanelMainInventory::resetFilters, this)); - mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLPanelMainInventory::setSortBy, this, _2)); - - // Controls - // *TODO: Just use persistant settings for each of these - U32 sort_order = gSavedSettings.getU32("InventorySortOrder"); - BOOL sort_by_name = ! ( sort_order & LLInventoryFilter::SO_DATE ); - BOOL sort_folders_by_name = ( sort_order & LLInventoryFilter::SO_FOLDERS_BY_NAME ); - BOOL sort_system_folders_to_top = ( sort_order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP ); - - gSavedSettings.declareBOOL("Inventory.SortByName", sort_by_name, "Declared in code", FALSE); - gSavedSettings.declareBOOL("Inventory.SortByDate", !sort_by_name, "Declared in code", FALSE); - gSavedSettings.declareBOOL("Inventory.FoldersAlwaysByName", sort_folders_by_name, "Declared in code", FALSE); - gSavedSettings.declareBOOL("Inventory.SystemFoldersToTop", sort_system_folders_to_top, "Declared in code", FALSE); - - mSavedFolderState = new LLSaveFolderState(); - mSavedFolderState->setApply(FALSE); -} - -BOOL LLPanelMainInventory::postBuild() -{ - gInventory.addObserver(this); - - mFilterTabs = getChild<LLTabContainer>("inventory filter tabs"); - mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this)); - - //panel->getFilter()->markDefault(); - - // Set up the default inv. panel/filter settings. - mActivePanel = getChild<LLInventoryPanel>("All Items"); - if (mActivePanel) - { - // "All Items" is the previous only view, so it gets the InventorySortOrder - mActivePanel->setSortOrder(gSavedSettings.getU32("InventorySortOrder")); - mActivePanel->getFilter()->markDefault(); - mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); - mActivePanel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, mActivePanel, _1, _2)); - } - LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items"); - if (recent_items_panel) - { - recent_items_panel->setSinceLogoff(TRUE); - recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE); - recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - recent_items_panel->getFilter()->markDefault(); - recent_items_panel->setSelectCallback(boost::bind(&LLInventoryPanel::onSelectionChange, recent_items_panel, _1, _2)); - } - - // Now load the stored settings from disk, if available. - std::ostringstream filterSaveName; - filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml"); - llinfos << "LLPanelMainInventory::init: reading from " << filterSaveName << llendl; - llifstream file(filterSaveName.str()); - LLSD savedFilterState; - if (file.is_open()) - { - LLSDSerialize::fromXML(savedFilterState, file); - file.close(); - - // Load the persistent "Recent Items" settings. - // Note that the "All Items" settings do not persist. - if(recent_items_panel) - { - if(savedFilterState.has(recent_items_panel->getFilter()->getName())) - { - LLSD recent_items = savedFilterState.get( - recent_items_panel->getFilter()->getName()); - recent_items_panel->getFilter()->fromLLSD(recent_items); - } - } - - } - - - mFilterEditor = getChild<LLFilterEditor>("inventory search editor"); - if (mFilterEditor) - { - mFilterEditor->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterEdit, this, _2)); - } - - // *TODO:Get the cost info from the server - const std::string upload_cost("10"); - childSetLabelArg("Upload Image", "[COST]", upload_cost); - childSetLabelArg("Upload Sound", "[COST]", upload_cost); - childSetLabelArg("Upload Animation", "[COST]", upload_cost); - childSetLabelArg("Bulk Upload", "[COST]", upload_cost); - - return TRUE; -} - -// Destroys the object -LLPanelMainInventory::~LLPanelMainInventory( void ) -{ - // Save the filters state. - LLSD filterRoot; - LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>("All Items"); - if (all_items_panel) - { - LLInventoryFilter* filter = all_items_panel->getFilter(); - if (filter) - { - LLSD filterState; - filter->toLLSD(filterState); - filterRoot[filter->getName()] = filterState; - } - } - - LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items"); - if (recent_items_panel) - { - LLInventoryFilter* filter = recent_items_panel->getFilter(); - if (filter) - { - LLSD filterState; - filter->toLLSD(filterState); - filterRoot[filter->getName()] = filterState; - } - } - - std::ostringstream filterSaveName; - filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml"); - llofstream filtersFile(filterSaveName.str()); - if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile)) - { - llwarns << "Could not write to filters save file " << filterSaveName << llendl; - } - else - filtersFile.close(); - - gInventory.removeObserver(this); - delete mSavedFolderState; -} - -void LLPanelMainInventory::startSearch() -{ - // this forces focus to line editor portion of search editor - if (mFilterEditor) - { - mFilterEditor->focusFirstItem(TRUE); - } -} - -BOOL LLPanelMainInventory::handleKeyHere(KEY key, MASK mask) -{ - LLFolderView* root_folder = mActivePanel ? mActivePanel->getRootFolder() : NULL; - if (root_folder) - { - // first check for user accepting current search results - if (mFilterEditor - && mFilterEditor->hasFocus() - && (key == KEY_RETURN - || key == KEY_DOWN) - && mask == MASK_NONE) - { - // move focus to inventory proper - mActivePanel->setFocus(TRUE); - root_folder->scrollToShowSelection(); - return TRUE; - } - - if (mActivePanel->hasFocus() && key == KEY_UP) - { - startSearch(); - } - } - - return LLPanel::handleKeyHere(key, mask); - -} - -//---------------------------------------------------------------------------- -// menu callbacks - -void LLPanelMainInventory::doToSelected(const LLSD& userdata) -{ - getPanel()->getRootFolder()->doToSelected(&gInventory, userdata); -} - -void LLPanelMainInventory::closeAllFolders() -{ - getPanel()->getRootFolder()->closeAllFolders(); -} - -void LLPanelMainInventory::newWindow() -{ - LLFloaterInventory::showAgentInventory(); -} - -void LLPanelMainInventory::doCreate(const LLSD& userdata) -{ - menu_create_inventory_item(getPanel()->getRootFolder(), NULL, userdata); -} - -void LLPanelMainInventory::resetFilters() -{ - LLFloaterInventoryFinder *finder = getFinder(); - getActivePanel()->getFilter()->resetDefault(); - if (finder) - { - finder->updateElementsFromFilter(); - } - - setFilterTextFromFilter(); -} - -void LLPanelMainInventory::setSortBy(const LLSD& userdata) -{ - std::string sort_field = userdata.asString(); - if (sort_field == "name") - { - U32 order = getActivePanel()->getSortOrder(); - getActivePanel()->setSortOrder( order & ~LLInventoryFilter::SO_DATE ); - - gSavedSettings.setBOOL("Inventory.SortByName", TRUE ); - gSavedSettings.setBOOL("Inventory.SortByDate", FALSE ); - } - else if (sort_field == "date") - { - U32 order = getActivePanel()->getSortOrder(); - getActivePanel()->setSortOrder( order | LLInventoryFilter::SO_DATE ); - - gSavedSettings.setBOOL("Inventory.SortByName", FALSE ); - gSavedSettings.setBOOL("Inventory.SortByDate", TRUE ); - } - else if (sort_field == "foldersalwaysbyname") - { - U32 order = getActivePanel()->getSortOrder(); - if ( order & LLInventoryFilter::SO_FOLDERS_BY_NAME ) - { - order &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME; - - gSavedSettings.setBOOL("Inventory.FoldersAlwaysByName", FALSE ); - } - else - { - order |= LLInventoryFilter::SO_FOLDERS_BY_NAME; - - gSavedSettings.setBOOL("Inventory.FoldersAlwaysByName", TRUE ); - } - getActivePanel()->setSortOrder( order ); - } - else if (sort_field == "systemfolderstotop") - { - U32 order = getActivePanel()->getSortOrder(); - if ( order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP ) - { - order &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; - - gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", FALSE ); - } - else - { - order |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP; - - gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", TRUE ); - } - getActivePanel()->setSortOrder( order ); - } -} - -// static -BOOL LLPanelMainInventory::filtersVisible(void* user_data) -{ - LLPanelMainInventory* self = (LLPanelMainInventory*)user_data; - if(!self) return FALSE; - - return self->getFinder() != NULL; -} - -void LLPanelMainInventory::onClearSearch() -{ - LLFloater *finder = getFinder(); - if (mActivePanel) - { - mActivePanel->setFilterSubString(LLStringUtil::null); - mActivePanel->setFilterTypes(0xffffffff); - } - - if (finder) - { - LLFloaterInventoryFinder::selectAllTypes(finder); - } - - // re-open folders that were initially open - if (mActivePanel) - { - mSavedFolderState->setApply(TRUE); - mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); - LLOpenFoldersWithSelection opener; - mActivePanel->getRootFolder()->applyFunctorRecursively(opener); - mActivePanel->getRootFolder()->scrollToShowSelection(); - } -} - -void LLPanelMainInventory::onFilterEdit(const std::string& search_string ) -{ - if (search_string == "") - { - onClearSearch(); - } - if (!mActivePanel) - { - return; - } - - gInventory.startBackgroundFetch(); - - std::string uppercase_search_string = search_string; - LLStringUtil::toUpper(uppercase_search_string); - if (mActivePanel->getFilterSubString().empty() && uppercase_search_string.empty()) - { - // current filter and new filter empty, do nothing - return; - } - - // save current folder open state if no filter currently applied - if (!mActivePanel->getRootFolder()->isFilterModified()) - { - mSavedFolderState->setApply(FALSE); - mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); - } - - // set new filter string - mActivePanel->setFilterSubString(uppercase_search_string); -} - - - //static - BOOL LLPanelMainInventory::incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward) - { - LLPanelMainInventory* active_view = NULL; - - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); - for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) - { - LLPanelMainInventory* iv = dynamic_cast<LLPanelMainInventory*>(*iter); - if (iv) - { - if (gFocusMgr.childHasKeyboardFocus(iv)) - { - active_view = iv; - break; - } - } - } - - if (!active_view) - { - return FALSE; - } - - std::string search_string(find_text); - - if (search_string.empty()) - { - return FALSE; - } - - if (active_view->getPanel() && - active_view->getPanel()->getRootFolder()->search(first_item, search_string, backward)) - { - return TRUE; - } - - return FALSE; - } - -void LLPanelMainInventory::onFilterSelected() -{ - // Find my index - mActivePanel = (LLInventoryPanel*)childGetVisibleTab("inventory filter tabs"); - - if (!mActivePanel) - { - return; - } - LLInventoryFilter* filter = mActivePanel->getFilter(); - LLFloaterInventoryFinder *finder = getFinder(); - if (finder) - { - finder->changeFilter(filter); - } - if (filter->isActive()) - { - // If our filter is active we may be the first thing requiring a fetch so we better start it here. - gInventory.startBackgroundFetch(); - } - setFilterTextFromFilter(); -} - -const std::string LLPanelMainInventory::getFilterSubString() -{ - return mActivePanel->getFilterSubString(); -} - -void LLPanelMainInventory::setFilterSubString(const std::string& string) -{ - mActivePanel->setFilterSubString(string); -} - -BOOL LLPanelMainInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg) -{ - // Check to see if we are auto scrolling from the last frame - LLInventoryPanel* panel = (LLInventoryPanel*)this->getActivePanel(); - BOOL needsToScroll = panel->getScrollableContainer()->autoScroll(x, y); - if(mFilterTabs) - { - if(needsToScroll) - { - mFilterTabs->startDragAndDropDelayTimer(); - } - } - - BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - - return handled; -} - -void LLPanelMainInventory::changed(U32 mask) -{ -} - - -void LLPanelMainInventory::setFilterTextFromFilter() -{ - mFilterText = mActivePanel->getFilter()->getFilterText(); -} - -void LLPanelMainInventory::toggleFindOptions() -{ - LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_TOGGLE); - LLFloater *floater = getFinder(); - if (!floater) - { - LLFloaterInventoryFinder * finder = new LLFloaterInventoryFinder(this); - mFinderHandle = finder->getHandle(); - finder->openFloater(); - - LLFloater* parent_floater = gFloaterView->getParentFloater(this); - if (parent_floater) // Seraph: Fix this, shouldn't be null even for sidepanel - parent_floater->addDependentFloater(mFinderHandle); - // start background fetch of folders - gInventory.startBackgroundFetch(); - } - else - { - floater->closeFloater(); - } -} - -void LLPanelMainInventory::setSelectCallback(const LLFolderView::signal_t::slot_type& cb) -{ - getChild<LLInventoryPanel>("All Items")->setSelectCallback(cb); - getChild<LLInventoryPanel>("Recent Items")->setSelectCallback(cb); -} - -///---------------------------------------------------------------------------- -/// LLFloaterInventoryFinder -///---------------------------------------------------------------------------- - -LLFloaterInventoryFinder* LLPanelMainInventory::getFinder() -{ - return (LLFloaterInventoryFinder*)mFinderHandle.get(); -} - - -LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLPanelMainInventory* inventory_view) : - LLFloater(LLSD()), - mPanelInventoryDecorated(inventory_view), - mFilter(inventory_view->getPanel()->getFilter()) -{ - LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory_view_finder.xml", NULL); - updateElementsFromFilter(); -} - - -void LLFloaterInventoryFinder::onCheckSinceLogoff(LLUICtrl *ctrl, void *user_data) -{ - LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data; - if (!self) return; - - bool since_logoff= self->childGetValue("check_since_logoff"); - - if (!since_logoff && - !( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) ) - { - self->mSpinSinceHours->set(1.0f); - } -} -BOOL LLFloaterInventoryFinder::postBuild() -{ - const LLRect& viewrect = mPanelInventoryDecorated->getRect(); - setRect(LLRect(viewrect.mLeft - getRect().getWidth(), viewrect.mTop, viewrect.mLeft, viewrect.mTop - getRect().getHeight())); - - childSetAction("All", selectAllTypes, this); - childSetAction("None", selectNoTypes, this); - - mSpinSinceHours = getChild<LLSpinCtrl>("spin_hours_ago"); - childSetCommitCallback("spin_hours_ago", onTimeAgo, this); - - mSpinSinceDays = getChild<LLSpinCtrl>("spin_days_ago"); - childSetCommitCallback("spin_days_ago", onTimeAgo, this); - - // mCheckSinceLogoff = getChild<LLSpinCtrl>("check_since_logoff"); - childSetCommitCallback("check_since_logoff", onCheckSinceLogoff, this); - - childSetAction("Close", onCloseBtn, this); - - updateElementsFromFilter(); - return TRUE; -} -void LLFloaterInventoryFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data) -{ - LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data; - if (!self) return; - - bool since_logoff=true; - if ( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) - { - since_logoff = false; - } - self->childSetValue("check_since_logoff", since_logoff); -} - -void LLFloaterInventoryFinder::changeFilter(LLInventoryFilter* filter) -{ - mFilter = filter; - updateElementsFromFilter(); -} - -void LLFloaterInventoryFinder::updateElementsFromFilter() -{ - if (!mFilter) - return; - - // Get data needed for filter display - U32 filter_types = mFilter->getFilterTypes(); - std::string filter_string = mFilter->getFilterSubString(); - LLInventoryFilter::EFolderShow show_folders = mFilter->getShowFolderState(); - U32 hours = mFilter->getHoursAgo(); - - // update the ui elements - setTitle(mFilter->getName()); - - childSetValue("check_animation", (S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION)); - - childSetValue("check_calling_card", (S32) (filter_types & 0x1 << LLInventoryType::IT_CALLINGCARD)); - childSetValue("check_clothing", (S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE)); - childSetValue("check_gesture", (S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE)); - childSetValue("check_landmark", (S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK)); - childSetValue("check_notecard", (S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD)); - childSetValue("check_object", (S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT)); - childSetValue("check_script", (S32) (filter_types & 0x1 << LLInventoryType::IT_LSL)); - childSetValue("check_sound", (S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND)); - childSetValue("check_texture", (S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE)); - childSetValue("check_snapshot", (S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT)); - childSetValue("check_show_empty", show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS); - childSetValue("check_since_logoff", mFilter->isSinceLogoff()); - mSpinSinceHours->set((F32)(hours % 24)); - mSpinSinceDays->set((F32)(hours / 24)); -} - -void LLFloaterInventoryFinder::draw() -{ - LLMemType mt(LLMemType::MTYPE_INVENTORY_DRAW); - U32 filter = 0xffffffff; - BOOL filtered_by_all_types = TRUE; - - if (!childGetValue("check_animation")) - { - filter &= ~(0x1 << LLInventoryType::IT_ANIMATION); - filtered_by_all_types = FALSE; - } - - - if (!childGetValue("check_calling_card")) - { - filter &= ~(0x1 << LLInventoryType::IT_CALLINGCARD); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_clothing")) - { - filter &= ~(0x1 << LLInventoryType::IT_WEARABLE); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_gesture")) - { - filter &= ~(0x1 << LLInventoryType::IT_GESTURE); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_landmark")) - - - { - filter &= ~(0x1 << LLInventoryType::IT_LANDMARK); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_notecard")) - { - filter &= ~(0x1 << LLInventoryType::IT_NOTECARD); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_object")) - { - filter &= ~(0x1 << LLInventoryType::IT_OBJECT); - filter &= ~(0x1 << LLInventoryType::IT_ATTACHMENT); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_script")) - { - filter &= ~(0x1 << LLInventoryType::IT_LSL); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_sound")) - { - filter &= ~(0x1 << LLInventoryType::IT_SOUND); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_texture")) - { - filter &= ~(0x1 << LLInventoryType::IT_TEXTURE); - filtered_by_all_types = FALSE; - } - - if (!childGetValue("check_snapshot")) - { - filter &= ~(0x1 << LLInventoryType::IT_SNAPSHOT); - filtered_by_all_types = FALSE; - } - - if (!filtered_by_all_types) - { - // don't include folders in filter, unless I've selected everything - filter &= ~(0x1 << LLInventoryType::IT_CATEGORY); - } - - // update the panel, panel will update the filter - mPanelInventoryDecorated->getPanel()->setShowFolderState(getCheckShowEmpty() ? - LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); - mPanelInventoryDecorated->getPanel()->setFilterTypes(filter); - if (getCheckSinceLogoff()) - { - mSpinSinceDays->set(0); - mSpinSinceHours->set(0); - } - U32 days = (U32)mSpinSinceDays->get(); - U32 hours = (U32)mSpinSinceHours->get(); - if (hours > 24) - { - days += hours / 24; - hours = (U32)hours % 24; - mSpinSinceDays->set((F32)days); - mSpinSinceHours->set((F32)hours); - } - hours += days * 24; - mPanelInventoryDecorated->getPanel()->setHoursAgo(hours); - mPanelInventoryDecorated->getPanel()->setSinceLogoff(getCheckSinceLogoff()); - mPanelInventoryDecorated->setFilterTextFromFilter(); - - LLPanel::draw(); -} - -BOOL LLFloaterInventoryFinder::getCheckShowEmpty() -{ - return childGetValue("check_show_empty"); -} - -BOOL LLFloaterInventoryFinder::getCheckSinceLogoff() -{ - return childGetValue("check_since_logoff"); -} - -void LLFloaterInventoryFinder::onCloseBtn(void* user_data) -{ - LLFloaterInventoryFinder* finderp = (LLFloaterInventoryFinder*)user_data; - finderp->closeFloater(); -} - -// static -void LLFloaterInventoryFinder::selectAllTypes(void* user_data) -{ - LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data; - if(!self) return; - - self->childSetValue("check_animation", TRUE); - self->childSetValue("check_calling_card", TRUE); - self->childSetValue("check_clothing", TRUE); - self->childSetValue("check_gesture", TRUE); - self->childSetValue("check_landmark", TRUE); - self->childSetValue("check_notecard", TRUE); - self->childSetValue("check_object", TRUE); - self->childSetValue("check_script", TRUE); - self->childSetValue("check_sound", TRUE); - self->childSetValue("check_texture", TRUE); - self->childSetValue("check_snapshot", TRUE); -} - -//static -void LLFloaterInventoryFinder::selectNoTypes(void* user_data) -{ - LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data; - if(!self) return; - - self->childSetValue("check_animation", FALSE); - self->childSetValue("check_calling_card", FALSE); - self->childSetValue("check_clothing", FALSE); - self->childSetValue("check_gesture", FALSE); - self->childSetValue("check_landmark", FALSE); - self->childSetValue("check_notecard", FALSE); - self->childSetValue("check_object", FALSE); - self->childSetValue("check_script", FALSE); - self->childSetValue("check_sound", FALSE); - self->childSetValue("check_texture", FALSE); - self->childSetValue("check_snapshot", FALSE); -} +/**
+ * @file llsidepanelmaininventory.cpp
+ * @brief Implementation of llsidepanelmaininventory.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llpanelmaininventory.h"
+
+#include "lldndbutton.h"
+#include "llfilepicker.h"
+#include "llfloaterinventory.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llinventorypanel.h"
+#include "llfiltereditor.h"
+#include "llfloaterreg.h"
+#include "llpreviewtexture.h"
+#include "llscrollcontainer.h"
+#include "llsdserialize.h"
+#include "llspinctrl.h"
+#include "lltooldraganddrop.h"
+#include "llviewermenu.h"
+#include "llviewertexturelist.h"
+
+static LLRegisterPanelClassWrapper<LLPanelMainInventory> t_inventory("panel_main_inventory"); // Seraph is this redundant with constructor?
+
+void on_file_loaded_for_save(BOOL success,
+ LLViewerFetchedTexture *src_vi,
+ LLImageRaw* src,
+ LLImageRaw* aux_src,
+ S32 discard_level,
+ BOOL final,
+ void* userdata);
+
+///----------------------------------------------------------------------------
+/// LLFloaterInventoryFinder
+///----------------------------------------------------------------------------
+
+class LLFloaterInventoryFinder : public LLFloater
+{
+public:
+ LLFloaterInventoryFinder( LLPanelMainInventory* inventory_view);
+ virtual void draw();
+ /*virtual*/ BOOL postBuild();
+ void changeFilter(LLInventoryFilter* filter);
+ void updateElementsFromFilter();
+ BOOL getCheckShowEmpty();
+ BOOL getCheckSinceLogoff();
+
+ static void onTimeAgo(LLUICtrl*, void *);
+ static void onCheckSinceLogoff(LLUICtrl*, void *);
+ static void onCloseBtn(void* user_data);
+ static void selectAllTypes(void* user_data);
+ static void selectNoTypes(void* user_data);
+private:
+ LLPanelMainInventory* mPanelMainInventory;
+ LLSpinCtrl* mSpinSinceDays;
+ LLSpinCtrl* mSpinSinceHours;
+ LLInventoryFilter* mFilter;
+};
+
+///----------------------------------------------------------------------------
+/// LLPanelMainInventory
+///----------------------------------------------------------------------------
+
+LLPanelMainInventory::LLPanelMainInventory()
+ : LLPanel(),
+ mActivePanel(NULL),
+ mSavedFolderState(NULL),
+ mFilterText(""),
+ mMenuGearDefault(NULL),
+ mMenuAdd(NULL)
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_INIT);
+ // Menu Callbacks (non contex menus)
+ mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelMainInventory::doToSelected, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.CloseAllFolders", boost::bind(&LLPanelMainInventory::closeAllFolders, this));
+ mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH));
+ mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND));
+ mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLPanelMainInventory::doCreate, this, _2));
+ mCommitCallbackRegistrar.add("Inventory.NewWindow", boost::bind(&LLPanelMainInventory::newWindow, this));
+ mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLPanelMainInventory::toggleFindOptions, this));
+ mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLPanelMainInventory::resetFilters, this));
+ mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLPanelMainInventory::setSortBy, this, _2));
+
+ // Controls
+ // *TODO: Just use persistant settings for each of these
+ U32 sort_order = gSavedSettings.getU32("InventorySortOrder");
+ BOOL sort_by_name = ! ( sort_order & LLInventoryFilter::SO_DATE );
+ BOOL sort_folders_by_name = ( sort_order & LLInventoryFilter::SO_FOLDERS_BY_NAME );
+ BOOL sort_system_folders_to_top = ( sort_order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP );
+
+ gSavedSettings.declareBOOL("Inventory.SortByName", sort_by_name, "Declared in code", FALSE);
+ gSavedSettings.declareBOOL("Inventory.SortByDate", !sort_by_name, "Declared in code", FALSE);
+ gSavedSettings.declareBOOL("Inventory.FoldersAlwaysByName", sort_folders_by_name, "Declared in code", FALSE);
+ gSavedSettings.declareBOOL("Inventory.SystemFoldersToTop", sort_system_folders_to_top, "Declared in code", FALSE);
+
+ mSavedFolderState = new LLSaveFolderState();
+ mSavedFolderState->setApply(FALSE);
+}
+
+BOOL LLPanelMainInventory::postBuild()
+{
+ gInventory.addObserver(this);
+
+ mFilterTabs = getChild<LLTabContainer>("inventory filter tabs");
+ mFilterTabs->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterSelected, this));
+
+ //panel->getFilter()->markDefault();
+
+ // Set up the default inv. panel/filter settings.
+ mActivePanel = getChild<LLInventoryPanel>("All Items");
+ if (mActivePanel)
+ {
+ // "All Items" is the previous only view, so it gets the InventorySortOrder
+ mActivePanel->setSortOrder(gSavedSettings.getU32("InventorySortOrder"));
+ mActivePanel->getFilter()->markDefault();
+ mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+ mActivePanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mActivePanel, _1, _2));
+ }
+ LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items");
+ if (recent_items_panel)
+ {
+ recent_items_panel->setSinceLogoff(TRUE);
+ recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE);
+ recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+ recent_items_panel->getFilter()->markDefault();
+ recent_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, recent_items_panel, _1, _2));
+ }
+
+ // Now load the stored settings from disk, if available.
+ std::ostringstream filterSaveName;
+ filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml");
+ llinfos << "LLPanelMainInventory::init: reading from " << filterSaveName << llendl;
+ llifstream file(filterSaveName.str());
+ LLSD savedFilterState;
+ if (file.is_open())
+ {
+ LLSDSerialize::fromXML(savedFilterState, file);
+ file.close();
+
+ // Load the persistent "Recent Items" settings.
+ // Note that the "All Items" settings do not persist.
+ if(recent_items_panel)
+ {
+ if(savedFilterState.has(recent_items_panel->getFilter()->getName()))
+ {
+ LLSD recent_items = savedFilterState.get(
+ recent_items_panel->getFilter()->getName());
+ recent_items_panel->getFilter()->fromLLSD(recent_items);
+ }
+ }
+
+ }
+
+ mFilterEditor = getChild<LLFilterEditor>("inventory search editor");
+ if (mFilterEditor)
+ {
+ mFilterEditor->setCommitCallback(boost::bind(&LLPanelMainInventory::onFilterEdit, this, _2));
+ }
+
+ // *TODO:Get the cost info from the server
+ const std::string upload_cost("10");
+ childSetLabelArg("Upload Image", "[COST]", upload_cost);
+ childSetLabelArg("Upload Sound", "[COST]", upload_cost);
+ childSetLabelArg("Upload Animation", "[COST]", upload_cost);
+ childSetLabelArg("Bulk Upload", "[COST]", upload_cost);
+
+ initListCommandsHandlers();
+ return TRUE;
+}
+
+void LLPanelMainInventory::initListCommandsHandlers()
+{
+ mListCommands = getChild<LLPanel>("bottom_panel");
+
+ mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelMainInventory::onGearButtonClick, this));
+ mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelMainInventory::onTrashButtonClick, this));
+ mListCommands->childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this));
+ /*
+ mListCommands->getChild<LLButton>("add_btn")->setHeldDownCallback(boost::bind(&LLPanelMainInventory::onAddButtonHeldDown, this));
+ static const LLSD add_landmark_command("add_landmark");
+ mListCommands->childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddAction, this, add_landmark_command));
+ */
+
+ LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn");
+ trash_btn->setDragAndDropHandler(boost::bind(&LLPanelMainInventory::handleDragAndDropToTrash, this
+ , _4 // BOOL drop
+ , _5 // EDragAndDropType cargo_type
+ , _7 // EAcceptance* accept
+ ));
+
+ mCommitCallbackRegistrar.add("Inventory.GearDefault.Custom.Action", boost::bind(&LLPanelMainInventory::onCustomAction, this, _2));
+ mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2));
+ mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+ mMenuAdd = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
+
+}
+
+// Destroys the object
+LLPanelMainInventory::~LLPanelMainInventory( void )
+{
+ // Save the filters state.
+ LLSD filterRoot;
+ LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>("All Items");
+ if (all_items_panel)
+ {
+ LLInventoryFilter* filter = all_items_panel->getFilter();
+ if (filter)
+ {
+ LLSD filterState;
+ filter->toLLSD(filterState);
+ filterRoot[filter->getName()] = filterState;
+ }
+ }
+
+ LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items");
+ if (recent_items_panel)
+ {
+ LLInventoryFilter* filter = recent_items_panel->getFilter();
+ if (filter)
+ {
+ LLSD filterState;
+ filter->toLLSD(filterState);
+ filterRoot[filter->getName()] = filterState;
+ }
+ }
+
+ std::ostringstream filterSaveName;
+ filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml");
+ llofstream filtersFile(filterSaveName.str());
+ if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile))
+ {
+ llwarns << "Could not write to filters save file " << filterSaveName << llendl;
+ }
+ else
+ filtersFile.close();
+
+ gInventory.removeObserver(this);
+ delete mSavedFolderState;
+}
+
+void LLPanelMainInventory::startSearch()
+{
+ // this forces focus to line editor portion of search editor
+ if (mFilterEditor)
+ {
+ mFilterEditor->focusFirstItem(TRUE);
+ }
+}
+
+BOOL LLPanelMainInventory::handleKeyHere(KEY key, MASK mask)
+{
+ LLFolderView* root_folder = mActivePanel ? mActivePanel->getRootFolder() : NULL;
+ if (root_folder)
+ {
+ // first check for user accepting current search results
+ if (mFilterEditor
+ && mFilterEditor->hasFocus()
+ && (key == KEY_RETURN
+ || key == KEY_DOWN)
+ && mask == MASK_NONE)
+ {
+ // move focus to inventory proper
+ mActivePanel->setFocus(TRUE);
+ root_folder->scrollToShowSelection();
+ return TRUE;
+ }
+
+ if (mActivePanel->hasFocus() && key == KEY_UP)
+ {
+ startSearch();
+ }
+ }
+
+ return LLPanel::handleKeyHere(key, mask);
+
+}
+
+//----------------------------------------------------------------------------
+// menu callbacks
+
+void LLPanelMainInventory::doToSelected(const LLSD& userdata)
+{
+ getPanel()->getRootFolder()->doToSelected(&gInventory, userdata);
+}
+
+void LLPanelMainInventory::closeAllFolders()
+{
+ getPanel()->getRootFolder()->closeAllFolders();
+}
+
+void LLPanelMainInventory::newWindow()
+{
+ LLFloaterInventory::showAgentInventory();
+}
+
+void LLPanelMainInventory::doCreate(const LLSD& userdata)
+{
+ menu_create_inventory_item(getPanel()->getRootFolder(), NULL, userdata);
+}
+
+void LLPanelMainInventory::resetFilters()
+{
+ LLFloaterInventoryFinder *finder = getFinder();
+ getActivePanel()->getFilter()->resetDefault();
+ if (finder)
+ {
+ finder->updateElementsFromFilter();
+ }
+
+ setFilterTextFromFilter();
+}
+
+void LLPanelMainInventory::setSortBy(const LLSD& userdata)
+{
+ std::string sort_field = userdata.asString();
+ if (sort_field == "name")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ getActivePanel()->setSortOrder( order & ~LLInventoryFilter::SO_DATE );
+
+ gSavedSettings.setBOOL("Inventory.SortByName", TRUE );
+ gSavedSettings.setBOOL("Inventory.SortByDate", FALSE );
+ }
+ else if (sort_field == "date")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ getActivePanel()->setSortOrder( order | LLInventoryFilter::SO_DATE );
+
+ gSavedSettings.setBOOL("Inventory.SortByName", FALSE );
+ gSavedSettings.setBOOL("Inventory.SortByDate", TRUE );
+ }
+ else if (sort_field == "foldersalwaysbyname")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ if ( order & LLInventoryFilter::SO_FOLDERS_BY_NAME )
+ {
+ order &= ~LLInventoryFilter::SO_FOLDERS_BY_NAME;
+
+ gSavedSettings.setBOOL("Inventory.FoldersAlwaysByName", FALSE );
+ }
+ else
+ {
+ order |= LLInventoryFilter::SO_FOLDERS_BY_NAME;
+
+ gSavedSettings.setBOOL("Inventory.FoldersAlwaysByName", TRUE );
+ }
+ getActivePanel()->setSortOrder( order );
+ }
+ else if (sort_field == "systemfolderstotop")
+ {
+ U32 order = getActivePanel()->getSortOrder();
+ if ( order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP )
+ {
+ order &= ~LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
+
+ gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", FALSE );
+ }
+ else
+ {
+ order |= LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP;
+
+ gSavedSettings.setBOOL("Inventory.SystemFoldersToTop", TRUE );
+ }
+ getActivePanel()->setSortOrder( order );
+ }
+}
+
+// static
+BOOL LLPanelMainInventory::filtersVisible(void* user_data)
+{
+ LLPanelMainInventory* self = (LLPanelMainInventory*)user_data;
+ if(!self) return FALSE;
+
+ return self->getFinder() != NULL;
+}
+
+void LLPanelMainInventory::onClearSearch()
+{
+ LLFloater *finder = getFinder();
+ if (mActivePanel)
+ {
+ mActivePanel->setFilterSubString(LLStringUtil::null);
+ mActivePanel->setFilterTypes(0xffffffff);
+ }
+
+ if (finder)
+ {
+ LLFloaterInventoryFinder::selectAllTypes(finder);
+ }
+
+ // re-open folders that were initially open
+ if (mActivePanel)
+ {
+ mSavedFolderState->setApply(TRUE);
+ mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+ LLOpenFoldersWithSelection opener;
+ mActivePanel->getRootFolder()->applyFunctorRecursively(opener);
+ mActivePanel->getRootFolder()->scrollToShowSelection();
+ }
+}
+
+void LLPanelMainInventory::onFilterEdit(const std::string& search_string )
+{
+ if (search_string == "")
+ {
+ onClearSearch();
+ }
+ if (!mActivePanel)
+ {
+ return;
+ }
+
+ gInventory.startBackgroundFetch();
+
+ std::string uppercase_search_string = search_string;
+ LLStringUtil::toUpper(uppercase_search_string);
+ if (mActivePanel->getFilterSubString().empty() && uppercase_search_string.empty())
+ {
+ // current filter and new filter empty, do nothing
+ return;
+ }
+
+ // save current folder open state if no filter currently applied
+ if (!mActivePanel->getRootFolder()->isFilterModified())
+ {
+ mSavedFolderState->setApply(FALSE);
+ mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
+ }
+
+ // set new filter string
+ mActivePanel->setFilterSubString(uppercase_search_string);
+}
+
+
+ //static
+ BOOL LLPanelMainInventory::incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward)
+ {
+ LLPanelMainInventory* active_view = NULL;
+
+ LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory");
+ for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter)
+ {
+ LLPanelMainInventory* iv = dynamic_cast<LLPanelMainInventory*>(*iter);
+ if (iv)
+ {
+ if (gFocusMgr.childHasKeyboardFocus(iv))
+ {
+ active_view = iv;
+ break;
+ }
+ }
+ }
+
+ if (!active_view)
+ {
+ return FALSE;
+ }
+
+ std::string search_string(find_text);
+
+ if (search_string.empty())
+ {
+ return FALSE;
+ }
+
+ if (active_view->getPanel() &&
+ active_view->getPanel()->getRootFolder()->search(first_item, search_string, backward))
+ {
+ return TRUE;
+ }
+
+ return FALSE;
+ }
+
+void LLPanelMainInventory::onFilterSelected()
+{
+ // Find my index
+ mActivePanel = (LLInventoryPanel*)childGetVisibleTab("inventory filter tabs");
+
+ if (!mActivePanel)
+ {
+ return;
+ }
+ LLInventoryFilter* filter = mActivePanel->getFilter();
+ LLFloaterInventoryFinder *finder = getFinder();
+ if (finder)
+ {
+ finder->changeFilter(filter);
+ }
+ if (filter->isActive())
+ {
+ // If our filter is active we may be the first thing requiring a fetch so we better start it here.
+ gInventory.startBackgroundFetch();
+ }
+ setFilterTextFromFilter();
+}
+
+const std::string LLPanelMainInventory::getFilterSubString()
+{
+ return mActivePanel->getFilterSubString();
+}
+
+void LLPanelMainInventory::setFilterSubString(const std::string& string)
+{
+ mActivePanel->setFilterSubString(string);
+}
+
+BOOL LLPanelMainInventory::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg)
+{
+ // Check to see if we are auto scrolling from the last frame
+ LLInventoryPanel* panel = (LLInventoryPanel*)this->getActivePanel();
+ BOOL needsToScroll = panel->getScrollableContainer()->autoScroll(x, y);
+ if(mFilterTabs)
+ {
+ if(needsToScroll)
+ {
+ mFilterTabs->startDragAndDropDelayTimer();
+ }
+ }
+
+ BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
+
+ return handled;
+}
+
+void LLPanelMainInventory::changed(U32 mask)
+{
+}
+
+
+void LLPanelMainInventory::setFilterTextFromFilter()
+{
+ mFilterText = mActivePanel->getFilter()->getFilterText();
+}
+
+void LLPanelMainInventory::toggleFindOptions()
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_TOGGLE);
+ LLFloater *floater = getFinder();
+ if (!floater)
+ {
+ LLFloaterInventoryFinder * finder = new LLFloaterInventoryFinder(this);
+ mFinderHandle = finder->getHandle();
+ finder->openFloater();
+
+ LLFloater* parent_floater = gFloaterView->getParentFloater(this);
+ if (parent_floater) // Seraph: Fix this, shouldn't be null even for sidepanel
+ parent_floater->addDependentFloater(mFinderHandle);
+ // start background fetch of folders
+ gInventory.startBackgroundFetch();
+ }
+ else
+ {
+ floater->closeFloater();
+ }
+}
+
+void LLPanelMainInventory::setSelectCallback(const LLFolderView::signal_t::slot_type& cb)
+{
+ getChild<LLInventoryPanel>("All Items")->setSelectCallback(cb);
+ getChild<LLInventoryPanel>("Recent Items")->setSelectCallback(cb);
+}
+
+void LLPanelMainInventory::onSelectionChange(LLInventoryPanel *panel, const std::deque<LLFolderViewItem*>& items, BOOL user_action)
+{
+ updateListCommands();
+ panel->onSelectionChange(items, user_action);
+}
+
+///----------------------------------------------------------------------------
+/// LLFloaterInventoryFinder
+///----------------------------------------------------------------------------
+
+LLFloaterInventoryFinder* LLPanelMainInventory::getFinder()
+{
+ return (LLFloaterInventoryFinder*)mFinderHandle.get();
+}
+
+
+LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLPanelMainInventory* inventory_view) :
+ LLFloater(LLSD()),
+ mPanelMainInventory(inventory_view),
+ mFilter(inventory_view->getPanel()->getFilter())
+{
+ LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory_view_finder.xml", NULL);
+ updateElementsFromFilter();
+}
+
+
+void LLFloaterInventoryFinder::onCheckSinceLogoff(LLUICtrl *ctrl, void *user_data)
+{
+ LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data;
+ if (!self) return;
+
+ bool since_logoff= self->childGetValue("check_since_logoff");
+
+ if (!since_logoff &&
+ !( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() ) )
+ {
+ self->mSpinSinceHours->set(1.0f);
+ }
+}
+BOOL LLFloaterInventoryFinder::postBuild()
+{
+ const LLRect& viewrect = mPanelMainInventory->getRect();
+ setRect(LLRect(viewrect.mLeft - getRect().getWidth(), viewrect.mTop, viewrect.mLeft, viewrect.mTop - getRect().getHeight()));
+
+ childSetAction("All", selectAllTypes, this);
+ childSetAction("None", selectNoTypes, this);
+
+ mSpinSinceHours = getChild<LLSpinCtrl>("spin_hours_ago");
+ childSetCommitCallback("spin_hours_ago", onTimeAgo, this);
+
+ mSpinSinceDays = getChild<LLSpinCtrl>("spin_days_ago");
+ childSetCommitCallback("spin_days_ago", onTimeAgo, this);
+
+ // mCheckSinceLogoff = getChild<LLSpinCtrl>("check_since_logoff");
+ childSetCommitCallback("check_since_logoff", onCheckSinceLogoff, this);
+
+ childSetAction("Close", onCloseBtn, this);
+
+ updateElementsFromFilter();
+ return TRUE;
+}
+void LLFloaterInventoryFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data)
+{
+ LLFloaterInventoryFinder *self = (LLFloaterInventoryFinder *)user_data;
+ if (!self) return;
+
+ bool since_logoff=true;
+ if ( self->mSpinSinceDays->get() || self->mSpinSinceHours->get() )
+ {
+ since_logoff = false;
+ }
+ self->childSetValue("check_since_logoff", since_logoff);
+}
+
+void LLFloaterInventoryFinder::changeFilter(LLInventoryFilter* filter)
+{
+ mFilter = filter;
+ updateElementsFromFilter();
+}
+
+void LLFloaterInventoryFinder::updateElementsFromFilter()
+{
+ if (!mFilter)
+ return;
+
+ // Get data needed for filter display
+ U32 filter_types = mFilter->getFilterTypes();
+ std::string filter_string = mFilter->getFilterSubString();
+ LLInventoryFilter::EFolderShow show_folders = mFilter->getShowFolderState();
+ U32 hours = mFilter->getHoursAgo();
+
+ // update the ui elements
+ setTitle(mFilter->getName());
+
+ childSetValue("check_animation", (S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION));
+
+ childSetValue("check_calling_card", (S32) (filter_types & 0x1 << LLInventoryType::IT_CALLINGCARD));
+ childSetValue("check_clothing", (S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE));
+ childSetValue("check_gesture", (S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE));
+ childSetValue("check_landmark", (S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK));
+ childSetValue("check_notecard", (S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD));
+ childSetValue("check_object", (S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT));
+ childSetValue("check_script", (S32) (filter_types & 0x1 << LLInventoryType::IT_LSL));
+ childSetValue("check_sound", (S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND));
+ childSetValue("check_texture", (S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE));
+ childSetValue("check_snapshot", (S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT));
+ childSetValue("check_show_empty", show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS);
+ childSetValue("check_since_logoff", mFilter->isSinceLogoff());
+ mSpinSinceHours->set((F32)(hours % 24));
+ mSpinSinceDays->set((F32)(hours / 24));
+}
+
+void LLFloaterInventoryFinder::draw()
+{
+ LLMemType mt(LLMemType::MTYPE_INVENTORY_DRAW);
+ U32 filter = 0xffffffff;
+ BOOL filtered_by_all_types = TRUE;
+
+ if (!childGetValue("check_animation"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_ANIMATION);
+ filtered_by_all_types = FALSE;
+ }
+
+
+ if (!childGetValue("check_calling_card"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_CALLINGCARD);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_clothing"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_WEARABLE);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_gesture"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_GESTURE);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_landmark"))
+
+
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_LANDMARK);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_notecard"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_NOTECARD);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_object"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_OBJECT);
+ filter &= ~(0x1 << LLInventoryType::IT_ATTACHMENT);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_script"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_LSL);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_sound"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_SOUND);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_texture"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_TEXTURE);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!childGetValue("check_snapshot"))
+ {
+ filter &= ~(0x1 << LLInventoryType::IT_SNAPSHOT);
+ filtered_by_all_types = FALSE;
+ }
+
+ if (!filtered_by_all_types)
+ {
+ // don't include folders in filter, unless I've selected everything
+ filter &= ~(0x1 << LLInventoryType::IT_CATEGORY);
+ }
+
+ // update the panel, panel will update the filter
+ mPanelMainInventory->getPanel()->setShowFolderState(getCheckShowEmpty() ?
+ LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+ mPanelMainInventory->getPanel()->setFilterTypes(filter);
+ if (getCheckSinceLogoff())
+ {
+ mSpinSinceDays->set(0);
+ mSpinSinceHours->set(0);
+ }
+ U32 days = (U32)mSpinSinceDays->get();
+ U32 hours = (U32)mSpinSinceHours->get();
+ if (hours > 24)
+ {
+ days += hours / 24;
+ hours = (U32)hours % 24;
+ mSpinSinceDays->set((F32)days);
+ mSpinSinceHours->set((F32)hours);
+ }
+ hours += days * 24;
+ mPanelMainInventory->getPanel()->setHoursAgo(hours);
+ mPanelMainInventory->getPanel()->setSinceLogoff(getCheckSinceLogoff());
+ mPanelMainInventory->setFilterTextFromFilter();
+
+ LLPanel::draw();
+}
+
+BOOL LLFloaterInventoryFinder::getCheckShowEmpty()
+{
+ return childGetValue("check_show_empty");
+}
+
+BOOL LLFloaterInventoryFinder::getCheckSinceLogoff()
+{
+ return childGetValue("check_since_logoff");
+}
+
+void LLFloaterInventoryFinder::onCloseBtn(void* user_data)
+{
+ LLFloaterInventoryFinder* finderp = (LLFloaterInventoryFinder*)user_data;
+ finderp->closeFloater();
+}
+
+// static
+void LLFloaterInventoryFinder::selectAllTypes(void* user_data)
+{
+ LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data;
+ if(!self) return;
+
+ self->childSetValue("check_animation", TRUE);
+ self->childSetValue("check_calling_card", TRUE);
+ self->childSetValue("check_clothing", TRUE);
+ self->childSetValue("check_gesture", TRUE);
+ self->childSetValue("check_landmark", TRUE);
+ self->childSetValue("check_notecard", TRUE);
+ self->childSetValue("check_object", TRUE);
+ self->childSetValue("check_script", TRUE);
+ self->childSetValue("check_sound", TRUE);
+ self->childSetValue("check_texture", TRUE);
+ self->childSetValue("check_snapshot", TRUE);
+}
+
+//static
+void LLFloaterInventoryFinder::selectNoTypes(void* user_data)
+{
+ LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data;
+ if(!self) return;
+
+ self->childSetValue("check_animation", FALSE);
+ self->childSetValue("check_calling_card", FALSE);
+ self->childSetValue("check_clothing", FALSE);
+ self->childSetValue("check_gesture", FALSE);
+ self->childSetValue("check_landmark", FALSE);
+ self->childSetValue("check_notecard", FALSE);
+ self->childSetValue("check_object", FALSE);
+ self->childSetValue("check_script", FALSE);
+ self->childSetValue("check_sound", FALSE);
+ self->childSetValue("check_texture", FALSE);
+ self->childSetValue("check_snapshot", FALSE);
+}
+
+
+
+
+
+void LLPanelMainInventory::updateListCommands()
+{
+ bool trash_enabled = isActionEnabled("delete");
+
+ mListCommands->childSetEnabled("trash_btn", trash_enabled);
+}
+
+void LLPanelMainInventory::onGearButtonClick()
+{
+ showActionMenu(mMenuGearDefault,"options_gear_btn");
+}
+
+void LLPanelMainInventory::onAddButtonClick()
+{
+ showActionMenu(mMenuAdd,"add_btn");
+}
+
+void LLPanelMainInventory::showActionMenu(LLMenuGL* menu, std::string spawning_view_name)
+{
+ if (menu)
+ {
+ menu->buildDrawLabels();
+ menu->updateParent(LLMenuGL::sMenuContainer);
+ LLView* spawning_view = getChild<LLView> (spawning_view_name);
+ S32 menu_x, menu_y;
+ //show menu in co-ordinates of panel
+ spawning_view->localPointToOtherView(0, spawning_view->getRect().getHeight(), &menu_x, &menu_y, this);
+ menu_y += menu->getRect().getHeight();
+ LLMenuGL::showPopup(this, menu, menu_x, menu_y);
+ }
+}
+
+void LLPanelMainInventory::onTrashButtonClick()
+{
+ onClipboardAction("delete");
+}
+
+void LLPanelMainInventory::onClipboardAction(const LLSD& userdata)
+{
+ std::string command_name = userdata.asString();
+ getActivePanel()->getRootFolder()->doToSelected(getActivePanel()->getModel(),command_name);
+}
+
+void LLPanelMainInventory::onCustomAction(const LLSD& userdata)
+{
+ if (!isActionEnabled(userdata))
+ return;
+
+ const std::string command_name = userdata.asString();
+ if (command_name == "new_window")
+ {
+ newWindow();
+ }
+ if (command_name == "sort_by_name")
+ {
+ const LLSD arg = "name";
+ setSortBy(arg);
+ }
+ if (command_name == "sort_by_recent")
+ {
+ const LLSD arg = "date";
+ setSortBy(arg);
+ }
+ if (command_name == "show_filters")
+ {
+ toggleFindOptions();
+ }
+ if (command_name == "reset_filters")
+ {
+ resetFilters();
+ }
+ if (command_name == "close_folders")
+ {
+ closeAllFolders();
+ }
+ if (command_name == "empty_trash")
+ {
+ const std::string notification = "ConfirmEmptyTrash";
+ gInventory.emptyFolderType(notification, LLFolderType::FT_TRASH);
+ }
+ if (command_name == "empty_lostnfound")
+ {
+ const std::string notification = "ConfirmEmptyLostAndFound";
+ gInventory.emptyFolderType(notification, LLFolderType::FT_LOST_AND_FOUND);
+ }
+ if (command_name == "save_texture")
+ {
+ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ {
+ return;
+ }
+
+ const LLUUID& item_id = current_item->getListener()->getUUID();
+ LLPreviewTexture* preview_texture = LLFloaterReg::showTypedInstance<LLPreviewTexture>("preview_texture", LLSD(item_id), TAKE_FOCUS_YES);
+ if (preview_texture)
+ {
+ preview_texture->openToSave();
+ }
+ }
+}
+
+BOOL LLPanelMainInventory::isActionEnabled(const LLSD& userdata)
+{
+ const std::string command_name = userdata.asString();
+ if (command_name == "delete")
+ {
+ BOOL can_delete = FALSE;
+ LLFolderView *folder = getActivePanel()->getRootFolder();
+ if (folder)
+ {
+ can_delete = TRUE;
+ std::set<LLUUID> selection_set;
+ folder->getSelectionList(selection_set);
+ for (std::set<LLUUID>::iterator iter = selection_set.begin();
+ iter != selection_set.end();
+ ++iter)
+ {
+ const LLUUID &item_id = (*iter);
+ LLFolderViewItem *item = folder->getItemByID(item_id);
+ can_delete &= item->getListener()->isItemRemovable();
+ }
+ return can_delete;
+ }
+ return FALSE;
+ }
+ if (command_name == "save_texture")
+ {
+ LLFolderViewItem* current_item = getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (current_item)
+ {
+ return (current_item->getListener()->getInventoryType() == LLInventoryType::IT_TEXTURE);
+ }
+ return FALSE;
+ }
+ return TRUE;
+}
+
+bool LLPanelMainInventory::handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept)
+{
+ *accept = ACCEPT_NO;
+
+ const bool is_enabled = isActionEnabled("delete");
+ if (is_enabled) *accept = ACCEPT_YES_MULTI;
+
+ if (is_enabled && drop)
+ {
+ onClipboardAction("delete");
+ }
+ return true;
+}
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index a2b988e80c..29e9baa6cf 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -1,125 +1,145 @@ -/** - * @file llpanelmaininventory.h - * @brief llpanelmaininventory.h - * class definition - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLPANELMAININVENTORY_H -#define LL_LLPANELMAININVENTORY_H - -#include "llpanel.h" -#include "llinventorymodel.h" -#include "llfolderview.h" - -class LLFolderViewItem; -class LLInventoryPanel; -class LLSaveFolderState; -class LLFilterEditor; -class LLTabContainer; -class LLFloaterInventoryFinder; - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Class LLPanelMainInventory -// -// This is a panel used to view and control an agent's inventory, -// including all the fixin's (e.g. AllItems/RecentItems tabs, filter floaters). -// -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLPanelMainInventory : public LLPanel, LLInventoryObserver -{ -public: - friend class LLFloaterInventoryFinder; - - LLPanelMainInventory(); - ~LLPanelMainInventory(); - - BOOL postBuild(); - - virtual BOOL handleKeyHere(KEY key, MASK mask); - - // Inherited functionality - /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, - EDragAndDropType cargo_type, - void* cargo_data, - EAcceptance* accept, - std::string& tooltip_msg); - /*virtual*/ void changed(U32 mask); - - LLInventoryPanel* getPanel() { return mActivePanel; } - LLInventoryPanel* getActivePanel() { return mActivePanel; } - - const std::string& getFilterText() const { return mFilterText; } - - void setSelectCallback(const LLFolderView::signal_t::slot_type& cb); - -protected: - // - // Misc functions - // - void setFilterTextFromFilter(); - void startSearch(); - - void toggleFindOptions(); - - static BOOL filtersVisible(void* user_data); - void onClearSearch(); - static void onFoldersByName(void *user_data); - static BOOL checkFoldersByName(void *user_data); - void onFilterEdit(const std::string& search_string ); - static BOOL incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward); - void onFilterSelected(); - - const std::string getFilterSubString(); - void setFilterSubString(const std::string& string); - - // menu callbacks - void doToSelected(const LLSD& userdata); - void closeAllFolders(); - void newWindow(); - void doCreate(const LLSD& userdata); - void resetFilters(); - void setSortBy(const LLSD& userdata); - -private: - LLFloaterInventoryFinder* getFinder(); - - LLFilterEditor* mFilterEditor; - LLTabContainer* mFilterTabs; - LLHandle<LLFloater> mFinderHandle; - LLInventoryPanel* mActivePanel; - LLSaveFolderState* mSavedFolderState; - - std::string mFilterText; -}; - -#endif // LL_LLPANELMAININVENTORY_H - - - +/**
+ * @file llpanelmaininventory.h
+ * @brief llpanelmaininventory.h
+ * class definition
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLPANELMAININVENTORY_H
+#define LL_LLPANELMAININVENTORY_H
+
+#include "llpanel.h"
+#include "llinventorymodel.h"
+#include "llfolderview.h"
+
+class LLFolderViewItem;
+class LLInventoryPanel;
+class LLSaveFolderState;
+class LLFilterEditor;
+class LLTabContainer;
+class LLFloaterInventoryFinder;
+class LLMenuGL;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLPanelMainInventory
+//
+// This is a panel used to view and control an agent's inventory,
+// including all the fixin's (e.g. AllItems/RecentItems tabs, filter floaters).
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLPanelMainInventory : public LLPanel, LLInventoryObserver
+{
+public:
+ friend class LLFloaterInventoryFinder;
+
+ LLPanelMainInventory();
+ ~LLPanelMainInventory();
+
+ BOOL postBuild();
+
+ virtual BOOL handleKeyHere(KEY key, MASK mask);
+
+ // Inherited functionality
+ /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ EAcceptance* accept,
+ std::string& tooltip_msg);
+ /*virtual*/ void changed(U32 mask);
+
+ LLInventoryPanel* getPanel() { return mActivePanel; }
+ LLInventoryPanel* getActivePanel() { return mActivePanel; }
+ const LLInventoryPanel* getActivePanel() const { return mActivePanel; }
+
+ const std::string& getFilterText() const { return mFilterText; }
+
+ void setSelectCallback(const LLFolderView::signal_t::slot_type& cb);
+
+protected:
+ //
+ // Misc functions
+ //
+ void setFilterTextFromFilter();
+ void startSearch();
+
+ void toggleFindOptions();
+ void onSelectionChange(LLInventoryPanel *panel, const std::deque<LLFolderViewItem*>& items, BOOL user_action);
+
+ static BOOL filtersVisible(void* user_data);
+ void onClearSearch();
+ static void onFoldersByName(void *user_data);
+ static BOOL checkFoldersByName(void *user_data);
+ void onFilterEdit(const std::string& search_string );
+ static BOOL incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward);
+ void onFilterSelected();
+
+ const std::string getFilterSubString();
+ void setFilterSubString(const std::string& string);
+
+ // menu callbacks
+ void doToSelected(const LLSD& userdata);
+ void closeAllFolders();
+ void newWindow();
+ void doCreate(const LLSD& userdata);
+ void resetFilters();
+ void setSortBy(const LLSD& userdata);
+
+ // List Commands Handlers
+ void initListCommandsHandlers();
+ void updateListCommands();
+ void onGearButtonClick();
+ void onAddButtonClick();
+ void showActionMenu(LLMenuGL* menu, std::string spawning_view_name);
+ void onTrashButtonClick();
+ void onClipboardAction(const LLSD& userdata);
+ BOOL isActionEnabled(const LLSD& command_name);
+ void onCustomAction(const LLSD& command_name);
+ bool handleDragAndDropToTrash(BOOL drop, EDragAndDropType cargo_type, EAcceptance* accept);
+
+
+private:
+ LLFloaterInventoryFinder* getFinder();
+
+ LLFilterEditor* mFilterEditor;
+ LLTabContainer* mFilterTabs;
+ LLHandle<LLFloater> mFinderHandle;
+ LLInventoryPanel* mActivePanel;
+ LLSaveFolderState* mSavedFolderState;
+
+ LLPanel* mListCommands;
+ LLMenuGL* mMenuGearDefault;
+ LLMenuGL* mMenuAdd;
+
+ std::string mFilterText;
+};
+
+#endif // LL_LLPANELMAININVENTORY_H
+
+
+
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 79b33e29f5..a5e9407a41 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -165,7 +165,9 @@ void LLTaskInvFVBridge::showProperties() key["object"] = mPanel->getTaskUUID(); key["id"] = mUUID; LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); - + + + // Disable old properties floater; this is replaced by the sidepanel. /* LLFloaterProperties* floater = LLFloaterReg::showTypedInstance<LLFloaterProperties>("properties", mUUID); if (floater) diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 65a7b5322b..bb6cdd2f78 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -667,8 +667,10 @@ void LLPanelPeople::updateButtons() buttonSetEnabled("im_btn", (selected_uuids.size() >= 1)); // allow starting the friends conference for multiple selection buttonSetEnabled("call_btn", item_selected && false); // not implemented yet buttonSetEnabled("share_btn", item_selected && false); // not implemented yet - buttonSetEnabled("group_info_btn", item_selected); - buttonSetEnabled("chat_btn", item_selected); + + bool none_group_selected = item_selected && selected_id.isNull(); + buttonSetEnabled("group_info_btn", !none_group_selected); + buttonSetEnabled("chat_btn", !none_group_selected); } std::string LLPanelPeople::getActiveTabName() const diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index 28e89fd619..72856d5b82 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -406,6 +406,7 @@ void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, L if (tab_idx <= tabs_cnt - 4) { + // All tabs, except last three, are tabs for one day, so just push tab_date back by one day tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() - seconds_in_day); } else if (tab_idx == tabs_cnt - 3) // 6 day and older, low boundary is 1 month @@ -442,6 +443,7 @@ void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, L } } +// Called to add items, no more, than ADD_LIMIT at time void LLTeleportHistoryPanel::refresh() { if (!mHistoryAccordion) @@ -452,12 +454,16 @@ void LLTeleportHistoryPanel::refresh() const LLTeleportHistoryStorage::slurl_list_t& items = mTeleportHistory->getItems(); + // Setting tab_boundary_date to "now", so date from any item would be earlier, than boundary. + // That leads to call to getNextTab to get right tab_idx in first pass LLDate tab_boundary_date = LLDate::now(); + LLFlatListView* curr_flat_view = NULL; U32 added_items = 0; while (mCurrentItem >= 0) { + // Filtering std::string landmark_title = items[mCurrentItem].mTitle; LLStringUtil::toUpper(landmark_title); @@ -470,10 +476,14 @@ void LLTeleportHistoryPanel::refresh() continue; } + // Checking whether date of item is earlier, than tab_boundary_date. + // In that case, item should be added to another tab const LLDate &date = items[mCurrentItem].mDate; if (date < tab_boundary_date) { + // Getting apropriate tab_idx for this and subsequent items, + // tab_boundary_date would be earliest possible date for this tab S32 tab_idx = 0; getNextTab(date, tab_idx, tab_boundary_date); @@ -580,6 +590,9 @@ void LLTeleportHistoryPanel::replaceItem(S32 removed_index) void LLTeleportHistoryPanel::showTeleportHistory() { mDirty = true; + + // Starting to add items from last one, in reverse order, + // since TeleportHistory keeps most recent item at the end mCurrentItem = mTeleportHistory->getItems().size() - 1; for (S32 n = mItemContainers.size() - 1; n >= 0; --n) diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 32223e314e..2be0781487 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -53,13 +53,16 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av mSpeakerAddListener = new SpeakerAddListener(*this); mSpeakerRemoveListener = new SpeakerRemoveListener(*this); mSpeakerClearListener = new SpeakerClearListener(*this); + mSpeakerModeratorListener = new SpeakerModeratorUpdateListener(*this); mSpeakerMgr->addListener(mSpeakerAddListener, "add"); mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove"); mSpeakerMgr->addListener(mSpeakerClearListener, "clear"); + mSpeakerMgr->addListener(mSpeakerModeratorListener, "update_moderator"); mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData")); mAvatarList->setDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList)); + mAvatarList->setRefreshCompleteCallback(boost::bind(&LLParticipantList::onAvatarListRefreshed, this, _1, _2)); //Lets fill avatarList with existing speakers LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs(); @@ -68,7 +71,12 @@ LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* av mSpeakerMgr->getSpeakerList(&speaker_list, true); for(LLSpeakerMgr::speaker_list_t::iterator it = speaker_list.begin(); it != speaker_list.end(); it++) { - group_members.push_back((*it)->mID); + const LLPointer<LLSpeaker>& speakerp = *it; + group_members.push_back(speakerp->mID); + if ( speakerp->mIsModerator ) + { + mModeratorList.insert(speakerp->mID); + } } sort(); } @@ -87,6 +95,56 @@ void LLParticipantList::onAvatarListDoubleClicked(LLAvatarList* list) LLAvatarActions::startIM(clicked_id); } +void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param) +{ + LLAvatarList* list = dynamic_cast<LLAvatarList*>(ctrl); + if (list) + { + const std::string moderator_indicator(LLTrans::getString("IM_moderator_label")); + const std::size_t moderator_indicator_len = moderator_indicator.length(); + + // Firstly remove moderators indicator + std::set<LLUUID>::const_iterator + moderator_list_it = mModeratorToRemoveList.begin(), + moderator_list_end = mModeratorToRemoveList.end(); + for (;moderator_list_it != moderator_list_end; ++moderator_list_it) + { + LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it)); + if ( item ) + { + std::string name = item->getAvatarName(); + size_t found = name.find(moderator_indicator); + if (found == std::string::npos) + { + name.erase(found, moderator_indicator_len); + item->setName(name); + } + } + } + + mModeratorToRemoveList.clear(); + + // Add moderators indicator + moderator_list_it = mModeratorList.begin(); + moderator_list_end = mModeratorList.end(); + for (;moderator_list_it != moderator_list_end; ++moderator_list_it) + { + LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*> (list->getItemByValue(*moderator_list_it)); + if ( item ) + { + std::string name = item->getAvatarName(); + size_t found = name.find(moderator_indicator); + if (found == std::string::npos) + { + name += " "; + name += moderator_indicator; + item->setName(name); + } + } + } + } +} + void LLParticipantList::setSortOrder(EParticipantSortOrder order) { if ( mSortOrder != order ) @@ -109,6 +167,8 @@ bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, co } group_members.push_back(uu_id); + // Mark AvatarList as dirty one + mAvatarList->setDirty(); sort(); return true; } @@ -133,14 +193,36 @@ bool LLParticipantList::onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, return true; } +bool LLParticipantList::onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) +{ + const LLSD& evt_data = event->getValue(); + if ( evt_data.has("id") && evt_data.has("is_moderator") ) + { + LLUUID id = evt_data["id"]; + bool is_moderator = evt_data["is_moderator"]; + if ( id.notNull() ) + { + if ( is_moderator ) + mModeratorList.insert(id); + else + { + std::set<LLUUID>::iterator it = mModeratorList.find (id); + if ( it != mModeratorList.end () ) + { + mModeratorToRemoveList.insert(id); + mModeratorList.erase(id); + } + } + } + } + return true; +} + void LLParticipantList::sort() { if ( !mAvatarList ) return; - // Mark AvatarList as dirty one - mAvatarList->setDirty(); - // TODO: Implement more sorting orders after specs updating (EM) switch ( mSortOrder ) { case E_SORT_BY_NAME : @@ -175,3 +257,11 @@ bool LLParticipantList::SpeakerClearListener::handleEvent(LLPointer<LLOldEvents: { return mParent.onClearListEvent(event, userdata); } + +// +// LLParticipantList::SpeakerModeratorListener +// +bool LLParticipantList::SpeakerModeratorUpdateListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata) +{ + return mParent.onModeratorUpdateEvent(event, userdata); +} diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index 8c209c0b20..fc34dd308b 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -35,6 +35,7 @@ class LLSpeakerMgr; class LLAvatarList; +class LLUICtrl; class LLParticipantList { @@ -59,6 +60,7 @@ class LLParticipantList bool onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); bool onRemoveItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); bool onClearListEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + bool onModeratorUpdateEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); /** * Sorts the Avatarlist by stored order @@ -97,15 +99,27 @@ class LLParticipantList /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); }; + class SpeakerModeratorUpdateListener : public BaseSpeakerListner + { + public: + SpeakerModeratorUpdateListener(LLParticipantList& parent) : BaseSpeakerListner(parent) {} + /*virtual*/ bool handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata); + }; + private: void onAvatarListDoubleClicked(LLAvatarList* list); + void onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param); LLSpeakerMgr* mSpeakerMgr; LLAvatarList* mAvatarList; - LLPointer<SpeakerAddListener> mSpeakerAddListener; - LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener; - LLPointer<SpeakerClearListener> mSpeakerClearListener; + std::set<LLUUID> mModeratorList; + std::set<LLUUID> mModeratorToRemoveList; + + LLPointer<SpeakerAddListener> mSpeakerAddListener; + LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener; + LLPointer<SpeakerClearListener> mSpeakerClearListener; + LLPointer<SpeakerModeratorUpdateListener> mSpeakerModeratorListener; EParticipantSortOrder mSortOrder; }; diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index 62847d15e2..3eab13fc4a 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -48,6 +48,7 @@ #include "lltextbox.h" #include "lltextureview.h" #include "llui.h" +#include "llviewerinventory.h" #include "llviewertexture.h" #include "llviewertexturelist.h" #include "lluictrlfactory.h" @@ -63,7 +64,7 @@ const F32 PREVIEW_TEXTURE_MIN_ASPECT = 0.005f; LLPreviewTexture::LLPreviewTexture(const LLSD& key) - : LLPreview( key ), + : LLPreview(key), mLoadingFullImage( FALSE ), mShowKeepDiscard(FALSE), mCopyToInv(FALSE), @@ -71,7 +72,8 @@ LLPreviewTexture::LLPreviewTexture(const LLSD& key) mUpdateDimensions(TRUE), mLastHeight(0), mLastWidth(0), - mAspectRatio(0.f) + mAspectRatio(0.f), + mPreviewToSave(FALSE) { const LLInventoryItem *item = getItem(); if(item) @@ -104,6 +106,10 @@ LLPreviewTexture::LLPreviewTexture(const LLSD& key) mIsCopyable = TRUE; } + if (key.has("save_as")) + { + mPreviewToSave = TRUE; + } //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_preview_texture.xml", FALSE); } @@ -181,6 +187,12 @@ void LLPreviewTexture::draw() if ( mImage.notNull() ) { + // Automatically bring up SaveAs dialog if we opened this to save the texture. + if (mPreviewToSave) + { + mPreviewToSave = FALSE; + saveAs(); + } // Draw the texture glColor3f( 1.f, 1.f, 1.f ); gl_draw_scaled_image(interior.mLeft, @@ -192,11 +204,6 @@ void LLPreviewTexture::draw() // Pump the texture priority F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA : (F32)(interior.getWidth() * interior.getHeight() ); mImage->addTextureStats( pixel_area ); - if(pixel_area > 0.f) - { - //boost the previewed image priority to the highest to make it to get loaded first. - mImage->setAdditionalDecodePriority(1.0f) ; - } // Don't bother decoding more than we can display, unless // we're loading the full image. @@ -214,7 +221,7 @@ void LLPreviewTexture::draw() if( mLoadingFullImage ) { - LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("Receiving:"), 0, + LLFontGL::getFontSansSerif()->renderUTF8(LLTrans::getString("Receiving"), 0, interior.mLeft + 4, interior.mBottom + 4, LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM, @@ -309,6 +316,11 @@ void LLPreviewTexture::onFocusReceived() LLPreview::onFocusReceived(); } +void LLPreviewTexture::openToSave() +{ + mPreviewToSave = TRUE; +} + // static void LLPreviewTexture::onFileLoadedForSave(BOOL success, LLViewerFetchedTexture *src_vi, @@ -361,6 +373,7 @@ void LLPreviewTexture::onFileLoadedForSave(BOOL success, { LLNotifications::instance().add("CannotDownloadFile"); } + } diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h index 520626b49f..9b3c91d831 100644 --- a/indra/newview/llpreviewtexture.h +++ b/indra/newview/llpreviewtexture.h @@ -67,8 +67,7 @@ public: S32 discard_level, BOOL final, void* userdata ); - - + void openToSave(); protected: void init(); /* virtual */ BOOL postBuild(); @@ -77,14 +76,17 @@ protected: private: void updateDimensions(); - LLUUID mImageID; + LLUUID mImageID; LLPointer<LLViewerFetchedTexture> mImage; BOOL mLoadingFullImage; std::string mSaveFileName; LLFrameTimer mSavedFileTimer; BOOL mShowKeepDiscard; BOOL mCopyToInv; - + + // Save the image once it's loaded. + BOOL mPreviewToSave; + // This is stored off in a member variable, because the save-as // button and drag and drop functionality need to know. BOOL mIsCopyable; @@ -94,6 +96,4 @@ private: F32 mAspectRatio; BOOL mUpdateDimensions; }; - - #endif // LL_LLPREVIEWTEXTURE_H diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index dd07a3c015..4cb561381d 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -67,6 +67,7 @@ #include "llinventorymodel.h" #include "llmenugl.h" #include "llmutelist.h" +#include "llsidepaneltaskinfo.h" #include "llslurl.h" #include "llstatusbar.h" #include "llsurface.h" @@ -4907,12 +4908,20 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) } if (mSelectedObjects->getNumNodes()) { - LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance<LLFloaterInspect>("inspect"); LLUUID inspect_item_id= LLUUID::null; +#if 0 + LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance<LLFloaterInspect>("inspect"); if(inspect_instance) { inspect_item_id = inspect_instance->getSelectedUUID(); } +#endif + LLSidepanelTaskInfo *panel_task_info = LLSidepanelTaskInfo::getActivePanel(); + if (panel_task_info) + { + inspect_item_id = panel_task_info->getSelectedUUID(); + } + LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getFocusedObjectID(); for (S32 pass = 0; pass < 2; pass++) { @@ -5487,12 +5496,19 @@ void dialog_refresh_all() } LLFloaterProperties::dirtyAll(); - + +#if 0 LLFloaterInspect* inspect_instance = LLFloaterReg::getTypedInstance<LLFloaterInspect>("inspect"); if(inspect_instance) { inspect_instance->dirty(); } +#endif + LLSidepanelTaskInfo *panel_task_info = LLSidepanelTaskInfo::getActivePanel(); + if (panel_task_info) + { + panel_task_info->dirty(); + } } S32 get_family_count(LLViewerObject *parent) diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 3cf17fb7f2..6aa5c53194 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -1,244 +1,274 @@ -/** - * @file LLSidepanelInventory.cpp - * @brief Side Bar "Inventory" panel - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llsidepanelinventory.h" - -#include "llagent.h" -#include "llbutton.h" -#include "llinventorybridge.h" -#include "llinventorypanel.h" -#include "llpanelmaininventory.h" -#include "llsidepanelobjectinfo.h" -#include "lltabcontainer.h" - -static const S32 LANDMARK_FOLDERS_MENU_WIDTH = 250; -static const std::string AGENT_INFO_TYPE = "agent"; -static const std::string CREATE_LANDMARK_INFO_TYPE = "create_landmark"; -static const std::string LANDMARK_INFO_TYPE = "landmark"; -static const std::string REMOTE_PLACE_INFO_TYPE = "remote_place"; -static const std::string TELEPORT_HISTORY_INFO_TYPE = "teleport_history"; - -static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_inventory"); - -LLSidepanelInventory::LLSidepanelInventory() - : LLPanel(), - mSidepanelObjectInfo(NULL) -{ - - //LLUICtrlFactory::getInstance()->buildPanel(this, "panel_inventory.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder() -} - -LLSidepanelInventory::~LLSidepanelInventory() -{ -} - -BOOL LLSidepanelInventory::postBuild() -{ - mInfoBtn = getChild<LLButton>("info_btn"); - mInfoBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onInfoButtonClicked, this)); - - mShareBtn = getChild<LLButton>("share_btn"); - mShareBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onShareButtonClicked, this)); - - mShareBtn = getChild<LLButton>("share_btn"); - mShareBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onShareButtonClicked, this)); - - mWearBtn = getChild<LLButton>("wear_btn"); - mWearBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onWearButtonClicked, this)); - - mPlayBtn = getChild<LLButton>("play_btn"); - mPlayBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onPlayButtonClicked, this)); - - mTeleportBtn = getChild<LLButton>("teleport_btn"); - mTeleportBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onTeleportButtonClicked, this)); - - mOverflowBtn = getChild<LLButton>("overflow_btn"); - mOverflowBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onOverflowButtonClicked, this)); - - mTabContainer = getChild<LLTabContainer>("Inventory Tabs"); - mSidepanelObjectInfo = getChild<LLSidepanelObjectInfo>("sidepanel_object_info"); - - mPanelMainInventory = getChild<LLPanelMainInventory>("panel_main_inventory"); - mPanelMainInventory->setSelectCallback(boost::bind(&LLSidepanelInventory::onSelectionChange, this, _1, _2)); - - LLButton* back_btn = mSidepanelObjectInfo->getChild<LLButton>("back_btn"); - back_btn->setClickedCallback(boost::bind(&LLSidepanelInventory::onBackButtonClicked, this)); - - return TRUE; -} - -void LLSidepanelInventory::onOpen(const LLSD& key) -{ - if(key.size() == 0) - return; - - mSidepanelObjectInfo->reset(); - - if (key.has("id")) - { - mSidepanelObjectInfo->setItemID(key["id"].asUUID()); - } - - if (key.has("object")) - { - mSidepanelObjectInfo->setObjectID(key["object"].asUUID()); - } - - toggleObjectInfoPanel(TRUE); -} - -void LLSidepanelInventory::onInfoButtonClicked() -{ - LLInventoryItem *item = getSelectedItem(); - if (item) - { - mSidepanelObjectInfo->reset(); - mSidepanelObjectInfo->setItemID(item->getUUID()); - toggleObjectInfoPanel(TRUE); - } -} - -void LLSidepanelInventory::onShareButtonClicked() -{ -} - -void LLSidepanelInventory::performActionOnSelection(const std::string &action) -{ - LLInventoryPanel *panel = mPanelMainInventory->getActivePanel(); - LLFolderViewItem* current_item = panel->getRootFolder()->getCurSelectedItem(); - if (!current_item) - { - return; - } - current_item->getListener()->performAction(panel->getRootFolder(), panel->getModel(), action); -} - -void LLSidepanelInventory::onWearButtonClicked() -{ - performActionOnSelection("wear"); - performActionOnSelection("attach"); -} - -void LLSidepanelInventory::onPlayButtonClicked() -{ - performActionOnSelection("activate"); -} - -void LLSidepanelInventory::onTeleportButtonClicked() -{ - performActionOnSelection("teleport"); -} - -void LLSidepanelInventory::onOverflowButtonClicked() -{ -} - -void LLSidepanelInventory::onBackButtonClicked() -{ - toggleObjectInfoPanel(FALSE); - updateVerbs(); -} - -void LLSidepanelInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action) -{ - updateVerbs(); -} - -void LLSidepanelInventory::toggleObjectInfoPanel(BOOL visible) -{ - mSidepanelObjectInfo->setVisible(visible); - mTabContainer->setVisible(!visible); - - if (visible) - { - mSidepanelObjectInfo->reset(); - mSidepanelObjectInfo->setEditMode(FALSE); - - LLRect rect = getRect(); - LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom); - mSidepanelObjectInfo->reshape(new_rect.getWidth(),new_rect.getHeight()); - } -} - -void LLSidepanelInventory::updateVerbs() -{ - mInfoBtn->setEnabled(FALSE); - mShareBtn->setEnabled(FALSE); - - mWearBtn->setVisible(FALSE); - mWearBtn->setEnabled(FALSE); - mPlayBtn->setVisible(FALSE); - mPlayBtn->setEnabled(FALSE); - mTeleportBtn->setVisible(FALSE); - mTeleportBtn->setEnabled(FALSE); - - const LLInventoryItem *item = getSelectedItem(); - if (!item) - return; - - mInfoBtn->setEnabled(TRUE); - mShareBtn->setEnabled(TRUE); - - switch(item->getInventoryType()) - { - case LLInventoryType::IT_WEARABLE: - case LLInventoryType::IT_OBJECT: - case LLInventoryType::IT_ATTACHMENT: - mWearBtn->setVisible(TRUE); - mWearBtn->setEnabled(TRUE); - break; - case LLInventoryType::IT_SOUND: - case LLInventoryType::IT_GESTURE: - case LLInventoryType::IT_ANIMATION: - mPlayBtn->setVisible(TRUE); - mPlayBtn->setEnabled(TRUE); - break; - case LLInventoryType::IT_LANDMARK: - mTeleportBtn->setVisible(TRUE); - mTeleportBtn->setEnabled(TRUE); - break; - default: - break; - } -} - -LLInventoryItem *LLSidepanelInventory::getSelectedItem() -{ - LLFolderViewItem* current_item = mPanelMainInventory->getActivePanel()->getRootFolder()->getCurSelectedItem(); - if (!current_item) - { - return NULL; - } - const LLUUID &item_id = current_item->getListener()->getUUID(); - LLInventoryItem *item = gInventory.getItem(item_id); - return item; -} +/**
+ * @file LLSidepanelInventory.cpp
+ * @brief Side Bar "Inventory" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llsidepanelinventory.h"
+
+#include "llagent.h"
+#include "llbutton.h"
+#include "llinventorybridge.h"
+#include "llinventorypanel.h"
+#include "llpanelmaininventory.h"
+#include "llsidepaneliteminfo.h"
+#include "llsidepaneltaskinfo.h"
+#include "lltabcontainer.h"
+#include "llselectmgr.h"
+
+static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_inventory");
+
+LLSidepanelInventory::LLSidepanelInventory()
+ : LLPanel(),
+ mItemPanel(NULL)
+{
+
+ //LLUICtrlFactory::getInstance()->buildPanel(this, "panel_inventory.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
+}
+
+LLSidepanelInventory::~LLSidepanelInventory()
+{
+}
+
+BOOL LLSidepanelInventory::postBuild()
+{
+ // UI elements from inventory panel
+ {
+ mInventoryPanel = getChild<LLPanel>("sidepanel__inventory_panel");
+
+ mInfoBtn = mInventoryPanel->getChild<LLButton>("info_btn");
+ mInfoBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onInfoButtonClicked, this));
+
+ mShareBtn = mInventoryPanel->getChild<LLButton>("share_btn");
+ mShareBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onShareButtonClicked, this));
+
+ mWearBtn = mInventoryPanel->getChild<LLButton>("wear_btn");
+ mWearBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onWearButtonClicked, this));
+
+ mPlayBtn = mInventoryPanel->getChild<LLButton>("play_btn");
+ mPlayBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onPlayButtonClicked, this));
+
+ mTeleportBtn = mInventoryPanel->getChild<LLButton>("teleport_btn");
+ mTeleportBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onTeleportButtonClicked, this));
+
+ mOverflowBtn = mInventoryPanel->getChild<LLButton>("overflow_btn");
+ mOverflowBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onOverflowButtonClicked, this));
+
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
+ panel_main_inventory->setSelectCallback(boost::bind(&LLSidepanelInventory::onSelectionChange, this, _1, _2));
+ }
+
+ // UI elements from item panel
+ {
+ mItemPanel = getChild<LLSidepanelItemInfo>("sidepanel__item_panel");
+
+ LLButton* back_btn = mItemPanel->getChild<LLButton>("back_btn");
+ back_btn->setClickedCallback(boost::bind(&LLSidepanelInventory::onBackButtonClicked, this));
+ }
+
+ // UI elements from task panel
+ {
+ mTaskPanel = getChild<LLSidepanelTaskInfo>("sidepanel__task_panel");
+ if (mTaskPanel)
+ {
+ LLButton* back_btn = mTaskPanel->getChild<LLButton>("back_btn");
+ back_btn->setClickedCallback(boost::bind(&LLSidepanelInventory::onBackButtonClicked, this));
+ }
+ }
+
+ return TRUE;
+}
+
+void LLSidepanelInventory::onOpen(const LLSD& key)
+{
+ if(key.size() == 0)
+ return;
+
+ mItemPanel->reset();
+
+ if (key.has("id"))
+ {
+ mItemPanel->setItemID(key["id"].asUUID());
+ if (key.has("object"))
+ {
+ mItemPanel->setObjectID(key["object"].asUUID());
+ }
+ showItemInfoPanel();
+ }
+ if (key.has("task"))
+ {
+ if (mTaskPanel)
+ mTaskPanel->setObjectSelection(LLSelectMgr::getInstance()->getSelection());
+ showTaskInfoPanel();
+ }
+}
+
+void LLSidepanelInventory::onInfoButtonClicked()
+{
+ LLInventoryItem *item = getSelectedItem();
+ if (item)
+ {
+ mItemPanel->reset();
+ mItemPanel->setItemID(item->getUUID());
+ showItemInfoPanel();
+ }
+}
+
+void LLSidepanelInventory::onShareButtonClicked()
+{
+}
+
+void LLSidepanelInventory::performActionOnSelection(const std::string &action)
+{
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
+ LLFolderViewItem* current_item = panel_main_inventory->getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ {
+ return;
+ }
+ current_item->getListener()->performAction(panel_main_inventory->getActivePanel()->getRootFolder(), panel_main_inventory->getActivePanel()->getModel(), action);
+}
+
+void LLSidepanelInventory::onWearButtonClicked()
+{
+ performActionOnSelection("wear");
+ performActionOnSelection("attach");
+}
+
+void LLSidepanelInventory::onPlayButtonClicked()
+{
+ performActionOnSelection("activate");
+}
+
+void LLSidepanelInventory::onTeleportButtonClicked()
+{
+ performActionOnSelection("teleport");
+}
+
+void LLSidepanelInventory::onOverflowButtonClicked()
+{
+}
+
+void LLSidepanelInventory::onBackButtonClicked()
+{
+ showInventoryPanel();
+}
+
+void LLSidepanelInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
+{
+ updateVerbs();
+}
+
+void LLSidepanelInventory::showItemInfoPanel()
+{
+ mItemPanel->setVisible(TRUE);
+ if (mTaskPanel)
+ mTaskPanel->setVisible(FALSE);
+ mInventoryPanel->setVisible(FALSE);
+
+ mItemPanel->dirty();
+ mItemPanel->setIsEditing(FALSE);
+}
+
+void LLSidepanelInventory::showTaskInfoPanel()
+{
+ mItemPanel->setVisible(FALSE);
+ mInventoryPanel->setVisible(FALSE);
+
+ if (mTaskPanel)
+ {
+ mTaskPanel->setVisible(TRUE);
+ mTaskPanel->dirty();
+ mTaskPanel->setIsEditing(FALSE);
+ }
+}
+
+void LLSidepanelInventory::showInventoryPanel()
+{
+ mItemPanel->setVisible(FALSE);
+ if (mTaskPanel)
+ mTaskPanel->setVisible(FALSE);
+ mInventoryPanel->setVisible(TRUE);
+ updateVerbs();
+}
+
+void LLSidepanelInventory::updateVerbs()
+{
+ mInfoBtn->setEnabled(FALSE);
+ mShareBtn->setEnabled(FALSE);
+
+ mWearBtn->setVisible(FALSE);
+ mWearBtn->setEnabled(FALSE);
+ mPlayBtn->setVisible(FALSE);
+ mPlayBtn->setEnabled(FALSE);
+ mTeleportBtn->setVisible(FALSE);
+ mTeleportBtn->setEnabled(FALSE);
+
+ const LLInventoryItem *item = getSelectedItem();
+ if (!item)
+ return;
+
+ mInfoBtn->setEnabled(TRUE);
+ mShareBtn->setEnabled(TRUE);
+
+ switch(item->getInventoryType())
+ {
+ case LLInventoryType::IT_WEARABLE:
+ case LLInventoryType::IT_OBJECT:
+ case LLInventoryType::IT_ATTACHMENT:
+ mWearBtn->setVisible(TRUE);
+ mWearBtn->setEnabled(TRUE);
+ break;
+ case LLInventoryType::IT_SOUND:
+ case LLInventoryType::IT_GESTURE:
+ case LLInventoryType::IT_ANIMATION:
+ mPlayBtn->setVisible(TRUE);
+ mPlayBtn->setEnabled(TRUE);
+ break;
+ case LLInventoryType::IT_LANDMARK:
+ mTeleportBtn->setVisible(TRUE);
+ mTeleportBtn->setEnabled(TRUE);
+ break;
+ default:
+ break;
+ }
+}
+
+LLInventoryItem *LLSidepanelInventory::getSelectedItem()
+{
+ LLPanelMainInventory *panel_main_inventory = mInventoryPanel->getChild<LLPanelMainInventory>("panel_main_inventory");
+ LLFolderViewItem* current_item = panel_main_inventory->getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ {
+ return NULL;
+ }
+ const LLUUID &item_id = current_item->getListener()->getUUID();
+ LLInventoryItem *item = gInventory.getItem(item_id);
+ return item;
+}
diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h index 62eeecc5e2..681af7fafa 100644 --- a/indra/newview/llsidepanelinventory.h +++ b/indra/newview/llsidepanelinventory.h @@ -1,80 +1,90 @@ -/** - * @file LLSidepanelInventory.h - * @brief Side Bar "Inventory" panel - * - * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2004-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_LLSIDEPANELINVENTORY_H -#define LL_LLSIDEPANELINVENTORY_H - -#include "llpanel.h" - -class LLInventoryItem; -class LLSidepanelObjectInfo; -class LLTabContainer; -class LLPanelMainInventory; -class LLFolderViewItem; - -class LLSidepanelInventory : public LLPanel -{ -public: - LLSidepanelInventory(); - virtual ~LLSidepanelInventory(); - - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onOpen(const LLSD& key); - -protected: - LLInventoryItem *getSelectedItem(); - void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); - void onTabSelected(); - void toggleObjectInfoPanel(BOOL visible); - void updateVerbs(); - void performActionOnSelection(const std::string &action); - - LLTabContainer* mTabContainer; - LLSidepanelObjectInfo* mSidepanelObjectInfo; - LLPanelMainInventory* mPanelMainInventory; - - void onInfoButtonClicked(); - void onShareButtonClicked(); - void onWearButtonClicked(); - void onPlayButtonClicked(); - void onTeleportButtonClicked(); - void onOverflowButtonClicked(); - void onBackButtonClicked(); - - LLButton* mInfoBtn; - LLButton* mShareBtn; - LLButton* mWearBtn; - LLButton* mPlayBtn; - LLButton* mTeleportBtn; - LLButton* mOverflowBtn; -}; - -#endif //LL_LLSIDEPANELINVENTORY_H +/**
+ * @file LLSidepanelInventory.h
+ * @brief Side Bar "Inventory" panel
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSIDEPANELINVENTORY_H
+#define LL_LLSIDEPANELINVENTORY_H
+
+#include "llpanel.h"
+
+class LLFolderViewItem;
+class LLInventoryItem;
+class LLPanelMainInventory;
+class LLSidepanelItemInfo;
+class LLSidepanelTaskInfo;
+
+class LLSidepanelInventory : public LLPanel
+{
+public:
+ LLSidepanelInventory();
+ virtual ~LLSidepanelInventory();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+protected:
+ // Tracks highlighted (selected) item in inventory panel.
+ LLInventoryItem *getSelectedItem();
+ void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+ // "wear", "teleport", etc.
+ void performActionOnSelection(const std::string &action);
+
+ void showItemInfoPanel();
+ void showTaskInfoPanel();
+ void showInventoryPanel();
+ void updateVerbs();
+
+ //
+ // UI Elements
+ //
+private:
+ LLPanel* mInventoryPanel; // Main inventory view
+ LLSidepanelItemInfo* mItemPanel; // Individual item view
+ LLSidepanelTaskInfo* mTaskPanel; // Individual in-world object view
+
+protected:
+ void onInfoButtonClicked();
+ void onShareButtonClicked();
+ void onWearButtonClicked();
+ void onPlayButtonClicked();
+ void onTeleportButtonClicked();
+ void onOverflowButtonClicked();
+ void onBackButtonClicked();
+private:
+ LLButton* mInfoBtn;
+ LLButton* mShareBtn;
+ LLButton* mWearBtn;
+ LLButton* mPlayBtn;
+ LLButton* mTeleportBtn;
+ LLButton* mOverflowBtn;
+
+};
+
+#endif //LL_LLSIDEPANELINVENTORY_H
diff --git a/indra/newview/llsidepanelinventorysubpanel.cpp b/indra/newview/llsidepanelinventorysubpanel.cpp new file mode 100644 index 0000000000..162198f1c5 --- /dev/null +++ b/indra/newview/llsidepanelinventorysubpanel.cpp @@ -0,0 +1,155 @@ +/**
+ * @file llsidepanelinventorysubpanel.cpp
+ * @brief A floater which shows an inventory item's properties.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llsidepanelinventorysubpanel.h"
+
+#include "roles_constants.h"
+
+#include "llagent.h"
+#include "llavataractions.h"
+#include "llbutton.h"
+#include "llfloaterreg.h"
+#include "llgroupactions.h"
+#include "llinventorymodel.h"
+#include "lllineeditor.h"
+#include "llradiogroup.h"
+#include "llviewercontrol.h"
+#include "llviewerinventory.h"
+#include "llviewerobjectlist.h"
+
+
+///----------------------------------------------------------------------------
+/// Class LLSidepanelInventorySubpanel
+///----------------------------------------------------------------------------
+
+// Default constructor
+LLSidepanelInventorySubpanel::LLSidepanelInventorySubpanel()
+ : LLPanel(),
+ mIsDirty(TRUE),
+ mIsEditing(FALSE),
+ mEditBtn(NULL),
+ mCancelBtn(NULL),
+ mSaveBtn(NULL)
+{
+}
+
+// Destroys the object
+LLSidepanelInventorySubpanel::~LLSidepanelInventorySubpanel()
+{
+}
+
+// virtual
+BOOL LLSidepanelInventorySubpanel::postBuild()
+{
+ mEditBtn = getChild<LLButton>("edit_btn");
+ mEditBtn->setClickedCallback(boost::bind(&LLSidepanelInventorySubpanel::onEditButtonClicked, this));
+
+ mSaveBtn = getChild<LLButton>("save_btn");
+ mSaveBtn->setClickedCallback(boost::bind(&LLSidepanelInventorySubpanel::onSaveButtonClicked, this));
+
+ mCancelBtn = getChild<LLButton>("cancel_btn");
+ mCancelBtn->setClickedCallback(boost::bind(&LLSidepanelInventorySubpanel::onCancelButtonClicked, this));
+ return TRUE;
+}
+
+void LLSidepanelInventorySubpanel::setVisible(BOOL visible)
+{
+ if (visible)
+ {
+ dirty();
+ }
+ LLPanel::setVisible(visible);
+}
+
+void LLSidepanelInventorySubpanel::setIsEditing(BOOL edit)
+{
+ mIsEditing = edit;
+ mIsDirty = TRUE;
+}
+
+BOOL LLSidepanelInventorySubpanel::getIsEditing() const
+{
+ return mIsEditing;
+}
+
+void LLSidepanelInventorySubpanel::reset()
+{
+ mIsDirty = TRUE;
+}
+
+void LLSidepanelInventorySubpanel::draw()
+{
+ if (mIsDirty)
+ {
+ mIsDirty = FALSE;
+ refresh();
+ updateVerbs();
+ }
+
+ LLPanel::draw();
+}
+
+void LLSidepanelInventorySubpanel::dirty()
+{
+ mIsDirty = TRUE;
+ setIsEditing(FALSE);
+}
+
+void LLSidepanelInventorySubpanel::updateVerbs()
+{
+ mEditBtn->setVisible(!mIsEditing);
+ mSaveBtn->setVisible(mIsEditing);
+ mCancelBtn->setVisible(mIsEditing);
+}
+
+void LLSidepanelInventorySubpanel::onEditButtonClicked()
+{
+ setIsEditing(TRUE);
+ refresh();
+ updateVerbs();
+}
+
+void LLSidepanelInventorySubpanel::onSaveButtonClicked()
+{
+ save();
+ setIsEditing(FALSE);
+ refresh();
+ updateVerbs();
+}
+
+void LLSidepanelInventorySubpanel::onCancelButtonClicked()
+{
+ setIsEditing(FALSE);
+ refresh();
+ updateVerbs();
+}
diff --git a/indra/newview/llsidepanelinventorysubpanel.h b/indra/newview/llsidepanelinventorysubpanel.h new file mode 100644 index 0000000000..6503887cd1 --- /dev/null +++ b/indra/newview/llsidepanelinventorysubpanel.h @@ -0,0 +1,82 @@ +/**
+ * @file llsidepanelinventorysubpanel.h
+ * @brief A panel which shows an inventory item's properties.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSIDEPANELINVENTORYSUBPANEL_H
+#define LL_LLSIDEPANELINVENTORYSUBPANEL_H
+
+#include "llpanel.h"
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLSidepanelInventorySubpanel
+// Base class for inventory sidepanel panels (e.g. item info, task info).
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLButton;
+class LLInventoryItem;
+
+class LLSidepanelInventorySubpanel : public LLPanel
+{
+public:
+ LLSidepanelInventorySubpanel();
+ virtual ~LLSidepanelInventorySubpanel();
+
+ /*virtual*/ void setVisible(BOOL visible);
+ virtual BOOL postBuild();
+ virtual void draw();
+ virtual void reset();
+
+ void dirty();
+ void setIsEditing(BOOL edit);
+protected:
+ virtual void refresh() = 0;
+ virtual void save() = 0;
+ virtual void updateVerbs();
+
+ BOOL getIsEditing() const;
+
+ //
+ // UI Elements
+ //
+protected:
+ void onEditButtonClicked();
+ void onSaveButtonClicked();
+ void onCancelButtonClicked();
+ LLButton* mEditBtn;
+ LLButton* mSaveBtn;
+ LLButton* mCancelBtn;
+
+private:
+ BOOL mIsDirty; // item properties need to be updated
+ BOOL mIsEditing; // if we're in edit mode
+};
+
+#endif // LL_LLSIDEPANELINVENTORYSUBPANEL_H
diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp new file mode 100644 index 0000000000..9d2960fbed --- /dev/null +++ b/indra/newview/llsidepaneliteminfo.cpp @@ -0,0 +1,882 @@ +/**
+ * @file llsidepaneliteminfo.cpp
+ * @brief A floater which shows an inventory item's properties.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llsidepaneliteminfo.h"
+
+#include "roles_constants.h"
+
+#include "llagent.h"
+#include "llavataractions.h"
+#include "llbutton.h"
+#include "llfloaterreg.h"
+#include "llgroupactions.h"
+#include "llinventorymodel.h"
+#include "lllineeditor.h"
+#include "llradiogroup.h"
+#include "llviewercontrol.h"
+#include "llviewerinventory.h"
+#include "llviewerobjectlist.h"
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLItemPropertiesObserver
+//
+// Helper class to watch for changes to the item.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLItemPropertiesObserver : public LLInventoryObserver
+{
+public:
+ LLItemPropertiesObserver(LLSidepanelItemInfo* floater)
+ : mFloater(floater)
+ {
+ gInventory.addObserver(this);
+ }
+ virtual ~LLItemPropertiesObserver()
+ {
+ gInventory.removeObserver(this);
+ }
+ virtual void changed(U32 mask);
+private:
+ LLSidepanelItemInfo* mFloater;
+};
+
+void LLItemPropertiesObserver::changed(U32 mask)
+{
+ // if there's a change we're interested in.
+ if((mask & (LLInventoryObserver::LABEL | LLInventoryObserver::INTERNAL | LLInventoryObserver::REMOVE)) != 0)
+ {
+ mFloater->dirty();
+ }
+}
+
+
+
+///----------------------------------------------------------------------------
+/// Class LLSidepanelItemInfo
+///----------------------------------------------------------------------------
+
+static LLRegisterPanelClassWrapper<LLSidepanelItemInfo> t_item_info("sidepanel_item_info");
+
+// Default constructor
+LLSidepanelItemInfo::LLSidepanelItemInfo()
+ : mItemID(LLUUID::null)
+{
+ mPropertiesObserver = new LLItemPropertiesObserver(this);
+
+ //LLUICtrlFactory::getInstance()->buildFloater(this,"floater_inventory_item_properties.xml");
+}
+
+// Destroys the object
+LLSidepanelItemInfo::~LLSidepanelItemInfo()
+{
+ delete mPropertiesObserver;
+ mPropertiesObserver = NULL;
+}
+
+// virtual
+BOOL LLSidepanelItemInfo::postBuild()
+{
+ LLSidepanelInventorySubpanel::postBuild();
+
+ // build the UI
+ // item name & description
+ childSetPrevalidate("LabelItemName",&LLLineEditor::prevalidatePrintableNotPipe);
+ //getChild<LLUICtrl>("LabelItemName")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitName,this));
+ childSetPrevalidate("LabelItemDesc",&LLLineEditor::prevalidatePrintableNotPipe);
+ //getChild<LLUICtrl>("LabelItemDesc")->setCommitCallback(boost::bind(&LLSidepanelItemInfo:: onCommitDescription, this));
+
+ // Creator information
+ getChild<LLUICtrl>("BtnCreator")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onClickCreator,this));
+
+ // owner information
+ getChild<LLUICtrl>("BtnOwner")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onClickOwner,this));
+
+ refresh();
+ return TRUE;
+}
+
+void LLSidepanelItemInfo::setObjectID(const LLUUID& object_id)
+{
+ mObjectID = object_id;
+}
+
+void LLSidepanelItemInfo::setItemID(const LLUUID& item_id)
+{
+ mItemID = item_id;
+}
+
+void LLSidepanelItemInfo::reset()
+{
+ LLSidepanelInventorySubpanel::reset();
+
+ mObjectID = LLUUID::null;
+ mItemID = LLUUID::null;
+}
+
+void LLSidepanelItemInfo::refresh()
+{
+ LLInventoryItem* item = findItem();
+ if(item)
+ {
+ refreshFromItem(item);
+ updateVerbs();
+ }
+ else
+ {
+ if (getIsEditing())
+ {
+ setIsEditing(FALSE);
+ return;
+ }
+ }
+
+ if (!getIsEditing())
+ {
+ const std::string no_item_names[]={
+ "LabelItemName",
+ "LabelItemDesc",
+ "LabelCreatorName",
+ "LabelOwnerName",
+ "CheckOwnerModify",
+ "CheckOwnerCopy",
+ "CheckOwnerTransfer",
+ "CheckShareWithGroup",
+ "CheckEveryoneCopy",
+ "CheckNextOwnerModify",
+ "CheckNextOwnerCopy",
+ "CheckNextOwnerTransfer",
+ "CheckPurchase",
+ "RadioSaleType",
+ "Edit Cost"
+ };
+
+ for(size_t t=0; t<LL_ARRAY_SIZE(no_item_names); ++t)
+ {
+ childSetEnabled(no_item_names[t],false);
+ }
+
+ const std::string hide_names[]={
+ "BaseMaskDebug",
+ "OwnerMaskDebug",
+ "GroupMaskDebug",
+ "EveryoneMaskDebug",
+ "NextMaskDebug"
+ };
+ for(size_t t=0; t<LL_ARRAY_SIZE(hide_names); ++t)
+ {
+ childSetVisible(hide_names[t],false);
+ }
+ }
+
+ if (!item)
+ {
+ const std::string no_edit_mode_names[]={
+ "BtnCreator",
+ "BtnOwner",
+ };
+ for(size_t t=0; t<LL_ARRAY_SIZE(no_edit_mode_names); ++t)
+ {
+ childSetEnabled(no_edit_mode_names[t],false);
+ }
+ }
+
+ updateVerbs();
+}
+
+void LLSidepanelItemInfo::refreshFromItem(LLInventoryItem* item)
+{
+ ////////////////////////
+ // PERMISSIONS LOOKUP //
+ ////////////////////////
+
+ // do not enable the UI for incomplete items.
+ LLViewerInventoryItem* i = (LLViewerInventoryItem*)item;
+ BOOL is_complete = i->isComplete();
+ const BOOL cannot_restrict_permissions = LLInventoryType::cannotRestrictPermissions(i->getInventoryType());
+ const BOOL is_calling_card = (i->getInventoryType() == LLInventoryType::IT_CALLINGCARD);
+ const LLPermissions& perm = item->getPermissions();
+ const BOOL can_agent_manipulate = gAgent.allowOperation(PERM_OWNER, perm,
+ GP_OBJECT_MANIPULATE);
+ const BOOL can_agent_sell = gAgent.allowOperation(PERM_OWNER, perm,
+ GP_OBJECT_SET_SALE) &&
+ !cannot_restrict_permissions;
+ const BOOL is_link = i->getIsLinkType();
+
+ // You need permission to modify the object to modify an inventory
+ // item in it.
+ LLViewerObject* object = NULL;
+ if(!mObjectID.isNull()) object = gObjectList.findObject(mObjectID);
+ BOOL is_obj_modify = TRUE;
+ if(object)
+ {
+ is_obj_modify = object->permOwnerModify();
+ }
+
+ //////////////////////
+ // ITEM NAME & DESC //
+ //////////////////////
+ BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY, perm,
+ GP_OBJECT_MANIPULATE)
+ && is_obj_modify && is_complete;
+
+ childSetEnabled("LabelItemNameTitle",TRUE);
+ childSetEnabled("LabelItemName",is_modifiable && !is_calling_card); // for now, don't allow rename of calling cards
+ childSetText("LabelItemName",item->getName());
+ childSetEnabled("LabelItemDescTitle",TRUE);
+ childSetEnabled("LabelItemDesc",is_modifiable);
+ childSetVisible("IconLocked",!is_modifiable);
+ childSetText("LabelItemDesc",item->getDescription());
+
+ //////////////////
+ // CREATOR NAME //
+ //////////////////
+ if(!gCacheName) return;
+ if(!gAgent.getRegion()) return;
+
+ if (item->getCreatorUUID().notNull())
+ {
+ std::string name;
+ gCacheName->getFullName(item->getCreatorUUID(), name);
+ childSetEnabled("BtnCreator",TRUE);
+ childSetEnabled("LabelCreatorTitle",TRUE);
+ childSetEnabled("LabelCreatorName",TRUE);
+ childSetText("LabelCreatorName",name);
+ }
+ else
+ {
+ childSetEnabled("BtnCreator",FALSE);
+ childSetEnabled("LabelCreatorTitle",FALSE);
+ childSetEnabled("LabelCreatorName",FALSE);
+ childSetText("LabelCreatorName",getString("unknown"));
+ }
+
+ ////////////////
+ // OWNER NAME //
+ ////////////////
+ if(perm.isOwned())
+ {
+ std::string name;
+ if (perm.isGroupOwned())
+ {
+ gCacheName->getGroupName(perm.getGroup(), name);
+ }
+ else
+ {
+ gCacheName->getFullName(perm.getOwner(), name);
+ }
+ childSetEnabled("BtnOwner",TRUE);
+ childSetEnabled("LabelOwnerTitle",TRUE);
+ childSetEnabled("LabelOwnerName",TRUE);
+ childSetText("LabelOwnerName",name);
+ }
+ else
+ {
+ childSetEnabled("BtnOwner",FALSE);
+ childSetEnabled("LabelOwnerTitle",FALSE);
+ childSetEnabled("LabelOwnerName",FALSE);
+ childSetText("LabelOwnerName",getString("public"));
+ }
+
+ //////////////////
+ // ACQUIRE DATE //
+ //////////////////
+
+ time_t time_utc = item->getCreationDate();
+ if (0 == time_utc)
+ {
+ childSetText("LabelAcquiredDate",getString("unknown"));
+ }
+ else
+ {
+ std::string timeStr = getString("acquiredDate");
+ LLSD substitution;
+ substitution["datetime"] = (S32) time_utc;
+ LLStringUtil::format (timeStr, substitution);
+ childSetText ("LabelAcquiredDate", timeStr);
+ }
+
+ ///////////////////////
+ // OWNER PERMISSIONS //
+ ///////////////////////
+ if(can_agent_manipulate)
+ {
+ childSetText("OwnerLabel",getString("you_can"));
+ }
+ else
+ {
+ childSetText("OwnerLabel",getString("owner_can"));
+ }
+
+ U32 base_mask = perm.getMaskBase();
+ U32 owner_mask = perm.getMaskOwner();
+ U32 group_mask = perm.getMaskGroup();
+ U32 everyone_mask = perm.getMaskEveryone();
+ U32 next_owner_mask = perm.getMaskNextOwner();
+
+ childSetEnabled("OwnerLabel",TRUE);
+ childSetEnabled("CheckOwnerModify",FALSE);
+ childSetValue("CheckOwnerModify",LLSD((BOOL)(owner_mask & PERM_MODIFY)));
+ childSetEnabled("CheckOwnerCopy",FALSE);
+ childSetValue("CheckOwnerCopy",LLSD((BOOL)(owner_mask & PERM_COPY)));
+ childSetEnabled("CheckOwnerTransfer",FALSE);
+ childSetValue("CheckOwnerTransfer",LLSD((BOOL)(owner_mask & PERM_TRANSFER)));
+
+ ///////////////////////
+ // DEBUG PERMISSIONS //
+ ///////////////////////
+
+ if( gSavedSettings.getBOOL("DebugPermissions") )
+ {
+ BOOL slam_perm = FALSE;
+ BOOL overwrite_group = FALSE;
+ BOOL overwrite_everyone = FALSE;
+
+ if (item->getType() == LLAssetType::AT_OBJECT)
+ {
+ U32 flags = item->getFlags();
+ slam_perm = flags & LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM;
+ overwrite_everyone = flags & LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
+ overwrite_group = flags & LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
+ }
+
+ std::string perm_string;
+
+ perm_string = "B: ";
+ perm_string += mask_to_string(base_mask);
+ childSetText("BaseMaskDebug",perm_string);
+ childSetVisible("BaseMaskDebug",TRUE);
+
+ perm_string = "O: ";
+ perm_string += mask_to_string(owner_mask);
+ childSetText("OwnerMaskDebug",perm_string);
+ childSetVisible("OwnerMaskDebug",TRUE);
+
+ perm_string = "G";
+ perm_string += overwrite_group ? "*: " : ": ";
+ perm_string += mask_to_string(group_mask);
+ childSetText("GroupMaskDebug",perm_string);
+ childSetVisible("GroupMaskDebug",TRUE);
+
+ perm_string = "E";
+ perm_string += overwrite_everyone ? "*: " : ": ";
+ perm_string += mask_to_string(everyone_mask);
+ childSetText("EveryoneMaskDebug",perm_string);
+ childSetVisible("EveryoneMaskDebug",TRUE);
+
+ perm_string = "N";
+ perm_string += slam_perm ? "*: " : ": ";
+ perm_string += mask_to_string(next_owner_mask);
+ childSetText("NextMaskDebug",perm_string);
+ childSetVisible("NextMaskDebug",TRUE);
+ }
+ else
+ {
+ childSetVisible("BaseMaskDebug",FALSE);
+ childSetVisible("OwnerMaskDebug",FALSE);
+ childSetVisible("GroupMaskDebug",FALSE);
+ childSetVisible("EveryoneMaskDebug",FALSE);
+ childSetVisible("NextMaskDebug",FALSE);
+ }
+
+ /////////////
+ // SHARING //
+ /////////////
+
+ // Check for ability to change values.
+ if (is_link || cannot_restrict_permissions)
+ {
+ childSetEnabled("CheckShareWithGroup",FALSE);
+ childSetEnabled("CheckEveryoneCopy",FALSE);
+ }
+ else if (is_obj_modify && can_agent_manipulate)
+ {
+ childSetEnabled("CheckShareWithGroup",TRUE);
+ childSetEnabled("CheckEveryoneCopy",(owner_mask & PERM_COPY) && (owner_mask & PERM_TRANSFER));
+ }
+ else
+ {
+ childSetEnabled("CheckShareWithGroup",FALSE);
+ childSetEnabled("CheckEveryoneCopy",FALSE);
+ }
+
+ // Set values.
+ BOOL is_group_copy = (group_mask & PERM_COPY) ? TRUE : FALSE;
+ BOOL is_group_modify = (group_mask & PERM_MODIFY) ? TRUE : FALSE;
+ BOOL is_group_move = (group_mask & PERM_MOVE) ? TRUE : FALSE;
+
+ if (is_group_copy && is_group_modify && is_group_move)
+ {
+ childSetValue("CheckShareWithGroup",LLSD((BOOL)TRUE));
+
+ LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
+ if(ctl)
+ {
+ ctl->setTentative(FALSE);
+ }
+ }
+ else if (!is_group_copy && !is_group_modify && !is_group_move)
+ {
+ childSetValue("CheckShareWithGroup",LLSD((BOOL)FALSE));
+ LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
+ if(ctl)
+ {
+ ctl->setTentative(FALSE);
+ }
+ }
+ else
+ {
+ LLCheckBoxCtrl* ctl = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
+ if(ctl)
+ {
+ ctl->setTentative(TRUE);
+ ctl->set(TRUE);
+ }
+ }
+
+ childSetValue("CheckEveryoneCopy",LLSD((BOOL)(everyone_mask & PERM_COPY)));
+
+ ///////////////
+ // SALE INFO //
+ ///////////////
+
+ const LLSaleInfo& sale_info = item->getSaleInfo();
+ BOOL is_for_sale = sale_info.isForSale();
+ // Check for ability to change values.
+ if (is_obj_modify && can_agent_sell
+ && gAgent.allowOperation(PERM_TRANSFER, perm, GP_OBJECT_MANIPULATE))
+ {
+ childSetEnabled("SaleLabel",is_complete);
+ childSetEnabled("CheckPurchase",is_complete);
+
+ childSetEnabled("NextOwnerLabel",TRUE);
+ childSetEnabled("CheckNextOwnerModify",(base_mask & PERM_MODIFY) && !cannot_restrict_permissions);
+ childSetEnabled("CheckNextOwnerCopy",(base_mask & PERM_COPY) && !cannot_restrict_permissions);
+ childSetEnabled("CheckNextOwnerTransfer",(next_owner_mask & PERM_COPY) && !cannot_restrict_permissions);
+
+ childSetEnabled("RadioSaleType",is_complete && is_for_sale);
+ childSetEnabled("TextPrice",is_complete && is_for_sale);
+ childSetEnabled("Edit Cost",is_complete && is_for_sale);
+ }
+ else
+ {
+ childSetEnabled("SaleLabel",FALSE);
+ childSetEnabled("CheckPurchase",FALSE);
+
+ childSetEnabled("NextOwnerLabel",FALSE);
+ childSetEnabled("CheckNextOwnerModify",FALSE);
+ childSetEnabled("CheckNextOwnerCopy",FALSE);
+ childSetEnabled("CheckNextOwnerTransfer",FALSE);
+
+ childSetEnabled("RadioSaleType",FALSE);
+ childSetEnabled("TextPrice",FALSE);
+ childSetEnabled("Edit Cost",FALSE);
+ }
+
+ // Set values.
+ childSetValue("CheckPurchase", is_for_sale);
+ childSetEnabled("combobox sale copy", is_for_sale);
+ childSetEnabled("Edit Cost", is_for_sale);
+ childSetValue("CheckNextOwnerModify",LLSD(BOOL(next_owner_mask & PERM_MODIFY)));
+ childSetValue("CheckNextOwnerCopy",LLSD(BOOL(next_owner_mask & PERM_COPY)));
+ childSetValue("CheckNextOwnerTransfer",LLSD(BOOL(next_owner_mask & PERM_TRANSFER)));
+
+ LLRadioGroup* radioSaleType = getChild<LLRadioGroup>("RadioSaleType");
+ if (is_for_sale)
+ {
+ radioSaleType->setSelectedIndex((S32)sale_info.getSaleType() - 1);
+ S32 numerical_price;
+ numerical_price = sale_info.getSalePrice();
+ childSetText("Edit Cost",llformat("%d",numerical_price));
+ }
+ else
+ {
+ radioSaleType->setSelectedIndex(-1);
+ childSetText("Edit Cost",llformat("%d",0));
+ }
+}
+
+void LLSidepanelItemInfo::onClickCreator()
+{
+ LLInventoryItem* item = findItem();
+ if(!item) return;
+ if(!item->getCreatorUUID().isNull())
+ {
+ LLAvatarActions::showProfile(item->getCreatorUUID());
+ }
+}
+
+// static
+void LLSidepanelItemInfo::onClickOwner()
+{
+ LLInventoryItem* item = findItem();
+ if(!item) return;
+ if(item->getPermissions().isGroupOwned())
+ {
+ LLGroupActions::show(item->getPermissions().getGroup());
+ }
+ else
+ {
+ LLAvatarActions::showProfile(item->getPermissions().getOwner());
+ }
+}
+
+// static
+void LLSidepanelItemInfo::onCommitName()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitName()" << llendl;
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
+ if(!item)
+ {
+ return;
+ }
+ LLLineEditor* labelItemName = getChild<LLLineEditor>("LabelItemName");
+
+ if(labelItemName&&
+ (item->getName() != labelItemName->getText()) &&
+ (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)) )
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->rename(labelItemName->getText());
+ if(mObjectID.isNull())
+ {
+ new_item->updateServer(FALSE);
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ object->updateInventory(
+ new_item,
+ TASK_INVENTORY_ITEM_KEY,
+ false);
+ }
+ }
+ }
+}
+
+void LLSidepanelItemInfo::onCommitDescription()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitDescription()" << llendl;
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
+ if(!item) return;
+
+ LLLineEditor* labelItemDesc = getChild<LLLineEditor>("LabelItemDesc");
+ if(!labelItemDesc)
+ {
+ return;
+ }
+ if((item->getDescription() != labelItemDesc->getText()) &&
+ (gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE)))
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+
+ new_item->setDescription(labelItemDesc->getText());
+ if(mObjectID.isNull())
+ {
+ new_item->updateServer(FALSE);
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ object->updateInventory(
+ new_item,
+ TASK_INVENTORY_ITEM_KEY,
+ false);
+ }
+ }
+ }
+}
+
+// static
+void LLSidepanelItemInfo::onCommitPermissions()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitPermissions()" << llendl;
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
+ if(!item) return;
+ LLPermissions perm(item->getPermissions());
+
+
+ LLCheckBoxCtrl* CheckShareWithGroup = getChild<LLCheckBoxCtrl>("CheckShareWithGroup");
+
+ if(CheckShareWithGroup)
+ {
+ perm.setGroupBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckShareWithGroup->get(),
+ PERM_MODIFY | PERM_MOVE | PERM_COPY);
+ }
+ LLCheckBoxCtrl* CheckEveryoneCopy = getChild<LLCheckBoxCtrl>("CheckEveryoneCopy");
+ if(CheckEveryoneCopy)
+ {
+ perm.setEveryoneBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckEveryoneCopy->get(), PERM_COPY);
+ }
+
+ LLCheckBoxCtrl* CheckNextOwnerModify = getChild<LLCheckBoxCtrl>("CheckNextOwnerModify");
+ if(CheckNextOwnerModify)
+ {
+ perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckNextOwnerModify->get(), PERM_MODIFY);
+ }
+ LLCheckBoxCtrl* CheckNextOwnerCopy = getChild<LLCheckBoxCtrl>("CheckNextOwnerCopy");
+ if(CheckNextOwnerCopy)
+ {
+ perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckNextOwnerCopy->get(), PERM_COPY);
+ }
+ LLCheckBoxCtrl* CheckNextOwnerTransfer = getChild<LLCheckBoxCtrl>("CheckNextOwnerTransfer");
+ if(CheckNextOwnerTransfer)
+ {
+ perm.setNextOwnerBits(gAgent.getID(), gAgent.getGroupID(),
+ CheckNextOwnerTransfer->get(), PERM_TRANSFER);
+ }
+ if(perm != item->getPermissions()
+ && item->isComplete())
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->setPermissions(perm);
+ U32 flags = new_item->getFlags();
+ // If next owner permissions have changed (and this is an object)
+ // then set the slam permissions flag so that they are applied on rez.
+ if((perm.getMaskNextOwner()!=item->getPermissions().getMaskNextOwner())
+ && (item->getType() == LLAssetType::AT_OBJECT))
+ {
+ flags |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_PERM;
+ }
+ // If everyone permissions have changed (and this is an object)
+ // then set the overwrite everyone permissions flag so they
+ // are applied on rez.
+ if ((perm.getMaskEveryone()!=item->getPermissions().getMaskEveryone())
+ && (item->getType() == LLAssetType::AT_OBJECT))
+ {
+ flags |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE;
+ }
+ // If group permissions have changed (and this is an object)
+ // then set the overwrite group permissions flag so they
+ // are applied on rez.
+ if ((perm.getMaskGroup()!=item->getPermissions().getMaskGroup())
+ && (item->getType() == LLAssetType::AT_OBJECT))
+ {
+ flags |= LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP;
+ }
+ new_item->setFlags(flags);
+ if(mObjectID.isNull())
+ {
+ new_item->updateServer(FALSE);
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ object->updateInventory(
+ new_item,
+ TASK_INVENTORY_ITEM_KEY,
+ false);
+ }
+ }
+ }
+ else
+ {
+ // need to make sure we don't just follow the click
+ refresh();
+ }
+}
+
+// static
+void LLSidepanelItemInfo::onCommitSaleInfo()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitSaleInfo()" << llendl;
+ updateSaleInfo();
+}
+
+// static
+void LLSidepanelItemInfo::onCommitSaleType()
+{
+ //llinfos << "LLSidepanelItemInfo::onCommitSaleType()" << llendl;
+ updateSaleInfo();
+}
+
+void LLSidepanelItemInfo::updateSaleInfo()
+{
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
+ if(!item) return;
+ LLSaleInfo sale_info(item->getSaleInfo());
+ if(!gAgent.allowOperation(PERM_TRANSFER, item->getPermissions(), GP_OBJECT_SET_SALE))
+ {
+ childSetValue("CheckPurchase",LLSD((BOOL)FALSE));
+ }
+
+ if((BOOL)childGetValue("CheckPurchase"))
+ {
+ // turn on sale info
+ LLSaleInfo::EForSale sale_type = LLSaleInfo::FS_COPY;
+
+ LLRadioGroup* RadioSaleType = getChild<LLRadioGroup>("RadioSaleType");
+ if(RadioSaleType)
+ {
+ switch (RadioSaleType->getSelectedIndex())
+ {
+ case 0:
+ sale_type = LLSaleInfo::FS_ORIGINAL;
+ break;
+ case 1:
+ sale_type = LLSaleInfo::FS_COPY;
+ break;
+ case 2:
+ sale_type = LLSaleInfo::FS_CONTENTS;
+ break;
+ default:
+ sale_type = LLSaleInfo::FS_COPY;
+ break;
+ }
+ }
+
+ if (sale_type == LLSaleInfo::FS_COPY
+ && !gAgent.allowOperation(PERM_COPY, item->getPermissions(),
+ GP_OBJECT_SET_SALE))
+ {
+ sale_type = LLSaleInfo::FS_ORIGINAL;
+ }
+
+
+
+ S32 price = -1;
+ price = getChild<LLUICtrl>("Edit Cost")->getValue().asInteger();;
+
+ // Invalid data - turn off the sale
+ if (price < 0)
+ {
+ sale_type = LLSaleInfo::FS_NOT;
+ price = 0;
+ }
+
+ sale_info.setSaleType(sale_type);
+ sale_info.setSalePrice(price);
+ }
+ else
+ {
+ sale_info.setSaleType(LLSaleInfo::FS_NOT);
+ }
+ if(sale_info != item->getSaleInfo()
+ && item->isComplete())
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+
+ // Force an update on the sale price at rez
+ if (item->getType() == LLAssetType::AT_OBJECT)
+ {
+ U32 flags = new_item->getFlags();
+ flags |= LLInventoryItem::II_FLAGS_OBJECT_SLAM_SALE;
+ new_item->setFlags(flags);
+ }
+
+ new_item->setSaleInfo(sale_info);
+ if(mObjectID.isNull())
+ {
+ // This is in the agent's inventory.
+ new_item->updateServer(FALSE);
+ gInventory.updateItem(new_item);
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ // This is in an object's contents.
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ object->updateInventory(
+ new_item,
+ TASK_INVENTORY_ITEM_KEY,
+ false);
+ }
+ }
+ }
+ else
+ {
+ // need to make sure we don't just follow the click
+ refresh();
+ }
+}
+
+LLInventoryItem* LLSidepanelItemInfo::findItem() const
+{
+ LLInventoryItem* item = NULL;
+ if(mObjectID.isNull())
+ {
+ // it is in agent inventory
+ item = gInventory.getItem(mItemID);
+ }
+ else
+ {
+ LLViewerObject* object = gObjectList.findObject(mObjectID);
+ if(object)
+ {
+ item = (LLInventoryItem*)object->getInventoryObject(mItemID);
+ }
+ }
+ return item;
+}
+
+// virtual
+void LLSidepanelItemInfo::updateVerbs()
+{
+ LLSidepanelInventorySubpanel::updateVerbs();
+
+ const LLViewerInventoryItem* item = (LLViewerInventoryItem*)findItem();
+ if (item)
+ {
+ const LLPermissions& perm = item->getPermissions();
+ BOOL is_modifiable = gAgent.allowOperation(PERM_MODIFY, perm,
+ GP_OBJECT_MANIPULATE);
+ mEditBtn->setEnabled(is_modifiable);
+ }
+}
+
+// virtual
+void LLSidepanelItemInfo::save()
+{
+ onCommitName();
+ onCommitDescription();
+ onCommitPermissions();
+ onCommitSaleInfo();
+ onCommitSaleType();
+}
diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h new file mode 100644 index 0000000000..b348b5cceb --- /dev/null +++ b/indra/newview/llsidepaneliteminfo.h @@ -0,0 +1,91 @@ +/**
+ * @file llsidepaneliteminfo.h
+ * @brief A panel which shows an inventory item's properties.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLSIDEPANELITEMINFO_H
+#define LL_LLSIDEPANELITEMINFO_H
+
+#include "llsidepanelinventorysubpanel.h"
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLSidepanelItemInfo
+// Object properties for inventory side panel.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLButton;
+class LLInventoryItem;
+class LLItemPropertiesObserver;
+class LLViewerObject;
+class LLPermissions;
+
+class LLSidepanelItemInfo : public LLSidepanelInventorySubpanel
+{
+public:
+ LLSidepanelItemInfo();
+ virtual ~LLSidepanelItemInfo();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void reset();
+
+ void setObjectID(const LLUUID& object_id);
+ void setItemID(const LLUUID& item_id);
+ void setEditMode(BOOL edit);
+
+protected:
+ /*virtual*/ void refresh();
+ /*virtual*/ void save();
+ /*virtual*/ void updateVerbs();
+
+ LLInventoryItem* findItem() const;
+ LLViewerObject* findObject() const;
+
+ void refreshFromItem(LLInventoryItem* item);
+
+private:
+ LLUUID mItemID; // inventory UUID for the inventory item.
+ LLUUID mObjectID; // in-world task UUID, or null if in agent inventory.
+ LLItemPropertiesObserver* mPropertiesObserver; // for syncing changes to item
+
+ //
+ // UI Elements
+ //
+protected:
+ void onClickCreator();
+ void onClickOwner();
+ void onCommitName();
+ void onCommitDescription();
+ void onCommitPermissions();
+ void onCommitSaleInfo();
+ void onCommitSaleType();
+ void updateSaleInfo();
+};
+
+#endif // LL_LLSIDEPANELITEMINFO_H
diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp new file mode 100644 index 0000000000..01c832d7d5 --- /dev/null +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -0,0 +1,1124 @@ +/** + * @file llsidepaneltaskinfo.cpp + * @brief LLSidepanelTaskInfo class implementation + * This class represents the panel in the build view for + * viewing/editing object names, owners, permissions, etc. + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llsidepaneltaskinfo.h" + +#include "lluuid.h" +#include "llpermissions.h" +#include "llcategory.h" +#include "llclickaction.h" +#include "llfocusmgr.h" +#include "llstring.h" + +#include "llviewerwindow.h" +#include "llresmgr.h" +#include "lltextbox.h" +#include "llbutton.h" +#include "llcheckboxctrl.h" +#include "llviewerobject.h" +#include "llselectmgr.h" +#include "llagent.h" +#include "llstatusbar.h" // for getBalance() +#include "lllineeditor.h" +#include "llcombobox.h" +#include "lluiconstants.h" +#include "lldbstrings.h" +#include "llfloatergroups.h" +#include "llfloaterreg.h" +#include "llavataractions.h" +#include "llnamebox.h" +#include "llviewercontrol.h" +#include "llviewermenu.h" +#include "lluictrlfactory.h" +#include "llspinctrl.h" +#include "roles_constants.h" +#include "llgroupactions.h" + +///---------------------------------------------------------------------------- +/// Class llsidepaneltaskinfo +///---------------------------------------------------------------------------- + +LLSidepanelTaskInfo* LLSidepanelTaskInfo::sActivePanel = NULL; + +static LLRegisterPanelClassWrapper<LLSidepanelTaskInfo> t_task_info("sidepanel_task_info"); + +// Default constructor +LLSidepanelTaskInfo::LLSidepanelTaskInfo() +{ + setMouseOpaque(FALSE); +} + + +LLSidepanelTaskInfo::~LLSidepanelTaskInfo() +{ + if (sActivePanel == this) + sActivePanel = NULL; +} + +// virtual +BOOL LLSidepanelTaskInfo::postBuild() +{ + LLSidepanelInventorySubpanel::postBuild(); + + mOpenBtn = getChild<LLButton>("open_btn"); + mOpenBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onOpenButtonClicked, this)); + mPayBtn = getChild<LLButton>("pay_btn"); + mPayBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onPayButtonClicked, this)); + mBuyBtn = getChild<LLButton>("buy_btn"); + mBuyBtn->setClickedCallback(boost::bind(&LLSidepanelTaskInfo::onBuyButtonClicked, this)); + + childSetPrevalidate("Object Name",LLLineEditor::prevalidatePrintableNotPipe); + childSetPrevalidate("Object Description",LLLineEditor::prevalidatePrintableNotPipe); + +// getChild<LLUICtrl>("button set group")->setCommitCallback(boost::bind(&LLSidepanelTaskInfo::onClickGroup,this)); +// childSetAction("button deed",LLSidepanelTaskInfo::onClickDeedToGroup,this); + + mLabelGroupName = getChild<LLNameBox>("Group Name Proxy"); + + return TRUE; +} + +// virtual +void LLSidepanelTaskInfo::setVisible(BOOL visible) +{ + LLPanel::setVisible(visible); + if (visible) + { + sActivePanel = this; + } + else + { + sActivePanel = NULL; + } +} + +void LLSidepanelTaskInfo::refresh() +{ + LLButton* BtnDeedToGroup = getChild<LLButton>("button deed"); + if(BtnDeedToGroup) + { + std::string deedText; + if (gWarningSettings.getBOOL("DeedObject")) + { + deedText = getString("text deed continued"); + } + else + { + deedText = getString("text deed"); + } + BtnDeedToGroup->setLabelSelected(deedText); + BtnDeedToGroup->setLabelUnselected(deedText); + } + BOOL root_selected = TRUE; + LLSelectNode* nodep = mObjectSelection->getFirstRootNode(); + S32 object_count = mObjectSelection->getRootObjectCount(); + if(!nodep || 0 == object_count) + { + nodep = mObjectSelection->getFirstNode(); + object_count = mObjectSelection->getObjectCount(); + root_selected = FALSE; + } + + //BOOL attachment_selected = mObjectSelection->isAttachment(); + //attachment_selected = false; + LLViewerObject* objectp = NULL; + if(nodep) objectp = nodep->getObject(); + if(!nodep || !objectp)// || attachment_selected) + { + // ...nothing selected + childSetEnabled("perm_modify",false); + childSetText("perm_modify",LLStringUtil::null); + + childSetEnabled("Creator:",false); + childSetText("Creator Name",LLStringUtil::null); + childSetEnabled("Creator Name",false); + + childSetEnabled("Owner:",false); + childSetText("Owner Name",LLStringUtil::null); + childSetEnabled("Owner Name",false); + + childSetEnabled("Group:",false); + childSetText("Group Name",LLStringUtil::null); + childSetEnabled("Group Name",false); + childSetEnabled("button set group",false); + + childSetText("Object Name",LLStringUtil::null); + childSetEnabled("Object Name",false); + childSetEnabled("Name:",false); + childSetText("Group Name",LLStringUtil::null); + childSetEnabled("Group Name",false); + childSetEnabled("Description:",false); + childSetText("Object Description",LLStringUtil::null); + childSetEnabled("Object Description",false); + + childSetEnabled("Permissions:",false); + + childSetValue("checkbox share with group",FALSE); + childSetEnabled("checkbox share with group",false); + childSetEnabled("button deed",false); + + childSetValue("checkbox allow everyone move",FALSE); + childSetEnabled("checkbox allow everyone move",false); + childSetValue("checkbox allow everyone copy",FALSE); + childSetEnabled("checkbox allow everyone copy",false); + + //Next owner can: + childSetEnabled("Next owner can:",false); + childSetValue("checkbox next owner can modify",FALSE); + childSetEnabled("checkbox next owner can modify",false); + childSetValue("checkbox next owner can copy",FALSE); + childSetEnabled("checkbox next owner can copy",false); + childSetValue("checkbox next owner can transfer",FALSE); + childSetEnabled("checkbox next owner can transfer",false); + + //checkbox for sale + childSetValue("checkbox for sale",FALSE); + childSetEnabled("checkbox for sale",false); + + //checkbox include in search + childSetValue("search_check", FALSE); + childSetEnabled("search_check", false); + + LLComboBox* combo_sale_type = getChild<LLComboBox>("sale type"); + combo_sale_type->setValue(LLSaleInfo::FS_COPY); + combo_sale_type->setEnabled(FALSE); + + childSetEnabled("Cost",false); + childSetText("Cost",getString("Cost Default")); + childSetText("Edit Cost",LLStringUtil::null); + childSetEnabled("Edit Cost",false); + + childSetEnabled("label click action",false); + LLComboBox* ComboClickAction = getChild<LLComboBox>("clickaction"); + if(ComboClickAction) + { + ComboClickAction->setEnabled(FALSE); + ComboClickAction->clear(); + } + childSetVisible("B:",false); + childSetVisible("O:",false); + childSetVisible("G:",false); + childSetVisible("E:",false); + childSetVisible("N:",false); + childSetVisible("F:",false); + + return; + } + + // figure out a few variables + BOOL is_one_object = (object_count == 1); + + // BUG: fails if a root and non-root are both single-selected. + BOOL is_perm_modify = (mObjectSelection->getFirstRootNode() + && LLSelectMgr::getInstance()->selectGetRootsModify()) + || LLSelectMgr::getInstance()->selectGetModify(); + const LLFocusableElement* keyboard_focus_view = gFocusMgr.getKeyboardFocus(); + S32 string_index = 0; + std::string MODIFY_INFO_STRINGS[] = + { + getString("text modify info 1"), + getString("text modify info 2"), + getString("text modify info 3"), + getString("text modify info 4") + }; + if(!is_perm_modify) + { + string_index += 2; + } + if(!is_one_object) + { + ++string_index; + } + childSetEnabled("perm_modify",true); + childSetText("perm_modify",MODIFY_INFO_STRINGS[string_index]); + + childSetEnabled("Permissions:",true); + + // Update creator text field + childSetEnabled("Creator:",true); + BOOL creators_identical; + std::string creator_name; + creators_identical = LLSelectMgr::getInstance()->selectGetCreator(mCreatorID, + creator_name); + + childSetText("Creator Name",creator_name); + childSetEnabled("Creator Name",TRUE); + + // Update owner text field + childSetEnabled("Owner:",true); + + BOOL owners_identical; + std::string owner_name; + owners_identical = LLSelectMgr::getInstance()->selectGetOwner(mOwnerID, owner_name); + +// llinfos << "owners_identical " << (owners_identical ? "TRUE": "FALSE") << llendl; + + if (mOwnerID.isNull()) + { + if(LLSelectMgr::getInstance()->selectIsGroupOwned()) + { + // Group owned already displayed by selectGetOwner + } + else + { + // Display last owner if public + std::string last_owner_name; + LLSelectMgr::getInstance()->selectGetLastOwner(mLastOwnerID, last_owner_name); + + // It should never happen that the last owner is null and the owner + // is null, but it seems to be a bug in the simulator right now. JC + if (!mLastOwnerID.isNull() && !last_owner_name.empty()) + { + owner_name.append(", last "); + owner_name.append( last_owner_name ); + } + } + } + + childSetText("Owner Name",owner_name); + childSetEnabled("Owner Name",TRUE); + + // update group text field + childSetEnabled("Group:",true); + childSetText("Group Name",LLStringUtil::null); + LLUUID group_id; + BOOL groups_identical = LLSelectMgr::getInstance()->selectGetGroup(group_id); + if (groups_identical) + { + if(mLabelGroupName) + { + mLabelGroupName->setNameID(group_id, TRUE); + mLabelGroupName->setEnabled(TRUE); + } + } + else + { + if(mLabelGroupName) + { + mLabelGroupName->setNameID(LLUUID::null, TRUE); + mLabelGroupName->refresh(LLUUID::null, LLStringUtil::null, LLStringUtil::null, TRUE); + mLabelGroupName->setEnabled(FALSE); + } + } + + childSetEnabled("button set group",owners_identical && (mOwnerID == gAgent.getID())); + + // figure out the contents of the name, description, & category + BOOL edit_name_desc = FALSE; + if(is_one_object && objectp->permModify()) + { + edit_name_desc = TRUE; + } + + childSetEnabled("Name:",true); + LLLineEditor* LineEditorObjectName = getChild<LLLineEditor>("Object Name"); + childSetEnabled("Description:",true); + LLLineEditor* LineEditorObjectDesc = getChild<LLLineEditor>("Object Description"); + + if(is_one_object) + { + if(keyboard_focus_view != LineEditorObjectName) + { + childSetText("Object Name",nodep->mName); + } + + if(LineEditorObjectDesc) + { + if(keyboard_focus_view != LineEditorObjectDesc) + { + LineEditorObjectDesc->setText(nodep->mDescription); + } + } + } + else + { + childSetText("Object Name",LLStringUtil::null); + LineEditorObjectDesc->setText(LLStringUtil::null); + } + + if(edit_name_desc) + { + childSetEnabled("Object Name",true); + childSetEnabled("Object Description",true); + } + else + { + childSetEnabled("Object Name",false); + childSetEnabled("Object Description",false); + } + + S32 total_sale_price = 0; + S32 individual_sale_price = 0; + BOOL is_for_sale_mixed = FALSE; + BOOL is_sale_price_mixed = FALSE; + U32 num_for_sale = FALSE; + LLSelectMgr::getInstance()->selectGetAggregateSaleInfo(num_for_sale, + is_for_sale_mixed, + is_sale_price_mixed, + total_sale_price, + individual_sale_price); + + const BOOL self_owned = (gAgent.getID() == mOwnerID); + const BOOL group_owned = LLSelectMgr::getInstance()->selectIsGroupOwned() ; + const BOOL public_owned = (mOwnerID.isNull() && !LLSelectMgr::getInstance()->selectIsGroupOwned()); + const BOOL can_transfer = LLSelectMgr::getInstance()->selectGetRootsTransfer(); + const BOOL can_copy = LLSelectMgr::getInstance()->selectGetRootsCopy(); + + if(!owners_identical) + { + childSetEnabled("Cost",false); + childSetText("Edit Cost",LLStringUtil::null); + childSetEnabled("Edit Cost",false); + } + // You own these objects. + else if(self_owned || (group_owned && gAgent.hasPowerInGroup(group_id,GP_OBJECT_SET_SALE))) + { + // If there are multiple items for sale then set text to PRICE PER UNIT. + if (num_for_sale > 1) + { + childSetText("Cost",getString("Cost Per Unit")); + } + else + { + childSetText("Cost",getString("Cost Default")); + } + + LLSpinCtrl *edit_price = getChild<LLSpinCtrl>("Edit Cost"); + if(!edit_price->hasFocus()) + { + // If the sale price is mixed then set the cost to MIXED, otherwise + // set to the actual cost. + if (num_for_sale > 0 && is_for_sale_mixed) + { + edit_price->setTentative(TRUE); + } + else if (num_for_sale > 0 && is_sale_price_mixed) + { + edit_price->setTentative(TRUE); + } + else + { + edit_price->setValue(individual_sale_price); + } + } + // The edit fields are only enabled if you can sell this object + // and the sale price is not mixed. + bool enable_edit = (num_for_sale && can_transfer) ? !is_for_sale_mixed : false; + childSetEnabled("Cost",enable_edit); + childSetEnabled("Edit Cost",enable_edit); + } + // Someone, not you, owns these objects. + else if(!public_owned) + { + childSetEnabled("Cost",false); + childSetEnabled("Edit Cost",false); + + // Don't show a price if none of the items are for sale. + if (num_for_sale) + childSetText("Edit Cost",llformat("%d",total_sale_price)); + else + childSetText("Edit Cost",LLStringUtil::null); + + // If multiple items are for sale, set text to TOTAL PRICE. + if (num_for_sale > 1) + childSetText("Cost",getString("Cost Total")); + else + childSetText("Cost",getString("Cost Default")); + } + // This is a public object. + else + { + childSetEnabled("Cost",false); + childSetText("Cost",getString("Cost Default")); + + childSetText("Edit Cost",LLStringUtil::null); + childSetEnabled("Edit Cost",false); + } + + // Enable and disable the permissions checkboxes + // based on who owns the object. + // TODO: Creator permissions + + BOOL valid_base_perms = FALSE; + BOOL valid_owner_perms = FALSE; + BOOL valid_group_perms = FALSE; + BOOL valid_everyone_perms = FALSE; + BOOL valid_next_perms = FALSE; + + U32 base_mask_on; + U32 base_mask_off; + U32 owner_mask_on; + U32 owner_mask_off; + U32 group_mask_on; + U32 group_mask_off; + U32 everyone_mask_on; + U32 everyone_mask_off; + U32 next_owner_mask_on = 0; + U32 next_owner_mask_off = 0; + + valid_base_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_BASE, + &base_mask_on, + &base_mask_off); + + valid_owner_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_OWNER, + &owner_mask_on, + &owner_mask_off); + + valid_group_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_GROUP, + &group_mask_on, + &group_mask_off); + + valid_everyone_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_EVERYONE, + &everyone_mask_on, + &everyone_mask_off); + + valid_next_perms = LLSelectMgr::getInstance()->selectGetPerm(PERM_NEXT_OWNER, + &next_owner_mask_on, + &next_owner_mask_off); + + + if( gSavedSettings.getBOOL("DebugPermissions") ) + { + std::string perm_string; + if (valid_base_perms) + { + perm_string = "B: "; + perm_string += mask_to_string(base_mask_on); + childSetText("B:",perm_string); + childSetVisible("B:",true); + + perm_string = "O: "; + perm_string += mask_to_string(owner_mask_on); + childSetText("O:",perm_string); + childSetVisible("O:",true); + + perm_string = "G: "; + perm_string += mask_to_string(group_mask_on); + childSetText("G:",perm_string); + childSetVisible("G:",true); + + perm_string = "E: "; + perm_string += mask_to_string(everyone_mask_on); + childSetText("E:",perm_string); + childSetVisible("E:",true); + + perm_string = "N: "; + perm_string += mask_to_string(next_owner_mask_on); + childSetText("N:",perm_string); + childSetVisible("N:",true); + } + perm_string = "F: "; + U32 flag_mask = 0x0; + if (objectp->permMove()) + flag_mask |= PERM_MOVE; + if (objectp->permModify()) + flag_mask |= PERM_MODIFY; + if (objectp->permCopy()) + flag_mask |= PERM_COPY; + if (objectp->permTransfer()) + flag_mask |= PERM_TRANSFER; + perm_string += mask_to_string(flag_mask); + childSetText("F:",perm_string); + childSetVisible("F:",true); + } + else + { + childSetVisible("B:",false); + childSetVisible("O:",false); + childSetVisible("G:",false); + childSetVisible("E:",false); + childSetVisible("N:",false); + childSetVisible("F:",false); + } + + bool has_change_perm_ability = false; + bool has_change_sale_ability = false; + + if(valid_base_perms + && (self_owned + || (group_owned && gAgent.hasPowerInGroup(group_id, GP_OBJECT_MANIPULATE)))) + { + has_change_perm_ability = true; + } + if(valid_base_perms + && (self_owned + || (group_owned && gAgent.hasPowerInGroup(group_id, GP_OBJECT_SET_SALE)))) + { + has_change_sale_ability = true; + } + + if (!has_change_perm_ability && !has_change_sale_ability && !root_selected) + { + // ...must select root to choose permissions + childSetValue("perm_modify", getString("text modify warning")); + } + + if (has_change_perm_ability) + { + childSetEnabled("checkbox share with group",true); + childSetEnabled("checkbox allow everyone move",owner_mask_on & PERM_MOVE); + childSetEnabled("checkbox allow everyone copy",owner_mask_on & PERM_COPY && owner_mask_on & PERM_TRANSFER); + } + else + { + childSetEnabled("checkbox share with group", FALSE); + childSetEnabled("checkbox allow everyone move", FALSE); + childSetEnabled("checkbox allow everyone copy", FALSE); + } + + if (has_change_sale_ability && (owner_mask_on & PERM_TRANSFER)) + { + childSetEnabled("checkbox for sale", can_transfer || (!can_transfer && num_for_sale)); + // Set the checkbox to tentative if the prices of each object selected + // are not the same. + childSetTentative("checkbox for sale", is_for_sale_mixed); + childSetEnabled("sale type",num_for_sale && can_transfer && !is_sale_price_mixed); + + childSetEnabled("Next owner can:", TRUE); + childSetEnabled("checkbox next owner can modify",base_mask_on & PERM_MODIFY); + childSetEnabled("checkbox next owner can copy",base_mask_on & PERM_COPY); + childSetEnabled("checkbox next owner can transfer",next_owner_mask_on & PERM_COPY); + } + else + { + childSetEnabled("checkbox for sale",FALSE); + childSetEnabled("sale type",FALSE); + + childSetEnabled("Next owner can:",FALSE); + childSetEnabled("checkbox next owner can modify",FALSE); + childSetEnabled("checkbox next owner can copy",FALSE); + childSetEnabled("checkbox next owner can transfer",FALSE); + } + + if(valid_group_perms) + { + if((group_mask_on & PERM_COPY) && (group_mask_on & PERM_MODIFY) && (group_mask_on & PERM_MOVE)) + { + childSetValue("checkbox share with group",TRUE); + childSetTentative("checkbox share with group",FALSE); + childSetEnabled("button deed",gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) && (owner_mask_on & PERM_TRANSFER) && !group_owned && can_transfer); + } + else if((group_mask_off & PERM_COPY) && (group_mask_off & PERM_MODIFY) && (group_mask_off & PERM_MOVE)) + { + childSetValue("checkbox share with group",FALSE); + childSetTentative("checkbox share with group",false); + childSetEnabled("button deed",false); + } + else + { + childSetValue("checkbox share with group",TRUE); + childSetTentative("checkbox share with group",true); + childSetEnabled("button deed",gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) && (group_mask_on & PERM_MOVE) && (owner_mask_on & PERM_TRANSFER) && !group_owned && can_transfer); + } + } + + if(valid_everyone_perms) + { + // Move + if(everyone_mask_on & PERM_MOVE) + { + childSetValue("checkbox allow everyone move",TRUE); + childSetTentative("checkbox allow everyone move",false); + } + else if(everyone_mask_off & PERM_MOVE) + { + childSetValue("checkbox allow everyone move",FALSE); + childSetTentative("checkbox allow everyone move",false); + } + else + { + childSetValue("checkbox allow everyone move",TRUE); + childSetTentative("checkbox allow everyone move",true); + } + + // Copy == everyone can't copy + if(everyone_mask_on & PERM_COPY) + { + childSetValue("checkbox allow everyone copy",TRUE); + childSetTentative("checkbox allow everyone copy",!can_copy || !can_transfer); + } + else if(everyone_mask_off & PERM_COPY) + { + childSetValue("checkbox allow everyone copy",FALSE); + childSetTentative("checkbox allow everyone copy",false); + } + else + { + childSetValue("checkbox allow everyone copy",TRUE); + childSetTentative("checkbox allow everyone copy",true); + } + } + + if(valid_next_perms) + { + // Modify == next owner canot modify + if(next_owner_mask_on & PERM_MODIFY) + { + childSetValue("checkbox next owner can modify",TRUE); + childSetTentative("checkbox next owner can modify",false); + } + else if(next_owner_mask_off & PERM_MODIFY) + { + childSetValue("checkbox next owner can modify",FALSE); + childSetTentative("checkbox next owner can modify",false); + } + else + { + childSetValue("checkbox next owner can modify",TRUE); + childSetTentative("checkbox next owner can modify",true); + } + + // Copy == next owner cannot copy + if(next_owner_mask_on & PERM_COPY) + { + childSetValue("checkbox next owner can copy",TRUE); + childSetTentative("checkbox next owner can copy",!can_copy); + } + else if(next_owner_mask_off & PERM_COPY) + { + childSetValue("checkbox next owner can copy",FALSE); + childSetTentative("checkbox next owner can copy",FALSE); + } + else + { + childSetValue("checkbox next owner can copy",TRUE); + childSetTentative("checkbox next owner can copy",TRUE); + } + + // Transfer == next owner cannot transfer + if(next_owner_mask_on & PERM_TRANSFER) + { + childSetValue("checkbox next owner can transfer",TRUE); + childSetTentative("checkbox next owner can transfer",!can_transfer); + } + else if(next_owner_mask_off & PERM_TRANSFER) + { + childSetValue("checkbox next owner can transfer",FALSE); + childSetTentative("checkbox next owner can transfer",FALSE); + } + else + { + childSetValue("checkbox next owner can transfer",TRUE); + childSetTentative("checkbox next owner can transfer",TRUE); + } + } + + // reflect sale information + LLSaleInfo sale_info; + BOOL valid_sale_info = LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info); + LLSaleInfo::EForSale sale_type = sale_info.getSaleType(); + + LLComboBox* combo_sale_type = getChild<LLComboBox>("sale type"); + if (valid_sale_info) + { + combo_sale_type->setValue(sale_type == LLSaleInfo::FS_NOT ? LLSaleInfo::FS_COPY : sale_type); + combo_sale_type->setTentative(FALSE); // unfortunately this doesn't do anything at the moment. + } + else + { + // default option is sell copy, determined to be safest + combo_sale_type->setValue(LLSaleInfo::FS_COPY); + combo_sale_type->setTentative(TRUE); // unfortunately this doesn't do anything at the moment. + } + + childSetValue("checkbox for sale", num_for_sale != 0); + + // HACK: There are some old objects in world that are set for sale, + // but are no-transfer. We need to let users turn for-sale off, but only + // if for-sale is set. + bool cannot_actually_sell = !can_transfer || (!can_copy && sale_type == LLSaleInfo::FS_COPY); + if (num_for_sale && has_change_sale_ability && cannot_actually_sell) + { + childSetEnabled("checkbox for sale", true); + } + + // Check search status of objects + BOOL all_volume = LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ); + bool include_in_search; + bool all_include_in_search = LLSelectMgr::getInstance()->selectionGetIncludeInSearch(&include_in_search); + childSetEnabled("search_check", has_change_sale_ability && all_volume); + childSetValue("search_check", include_in_search); + childSetTentative("search_check", ! all_include_in_search); + + // Click action (touch, sit, buy) + U8 click_action = 0; + if (LLSelectMgr::getInstance()->selectionGetClickAction(&click_action)) + { + LLComboBox* ComboClickAction = getChild<LLComboBox>("clickaction"); + if(ComboClickAction) + { + ComboClickAction->setCurrentByIndex((S32)click_action); + } + } + childSetEnabled("label click action",is_perm_modify && all_volume); + childSetEnabled("clickaction",is_perm_modify && all_volume); + + if (!getIsEditing()) + { + const std::string no_item_names[]={ + "Object Name", + "Object Description", + "button set group", + "checkbox share with group", + "button deed", + "checkbox allow everyone move", + "checkbox allow everyone copy", + "checkbox for sale", + "sale type", + "Edit Cost", + "checkbox next owner can modify", + "checkbox next owner can copy", + "checkbox next owner can transfer", + "clickaction", + "search_check", + "perm_modify", + "Group Name", + }; + for(size_t t=0; t<LL_ARRAY_SIZE(no_item_names); ++t) + { + childSetEnabled(no_item_names[t],false); + } + } + updateVerbs(); +} + + +// static +void LLSidepanelTaskInfo::onClickClaim(void*) +{ + // try to claim ownership + LLSelectMgr::getInstance()->sendOwner(gAgent.getID(), gAgent.getGroupID()); +} + +// static +void LLSidepanelTaskInfo::onClickRelease(void*) +{ + // try to release ownership + LLSelectMgr::getInstance()->sendOwner(LLUUID::null, LLUUID::null); +} + +void LLSidepanelTaskInfo::onClickGroup() +{ + LLUUID owner_id; + std::string name; + BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, name); + LLFloater* parent_floater = gFloaterView->getParentFloater(this); + + if(owners_identical && (owner_id == gAgent.getID())) + { + LLFloaterGroupPicker* fg = LLFloaterReg::showTypedInstance<LLFloaterGroupPicker>("group_picker", LLSD(gAgent.getID())); + if (fg) + { + fg->setSelectGroupCallback( boost::bind(&LLSidepanelTaskInfo::cbGroupID, this, _1) ); + + if (parent_floater) + { + LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, fg); + fg->setOrigin(new_rect.mLeft, new_rect.mBottom); + parent_floater->addDependentFloater(fg); + } + } + } +} + +void LLSidepanelTaskInfo::cbGroupID(LLUUID group_id) +{ + if(mLabelGroupName) + { + mLabelGroupName->setNameID(group_id, TRUE); + } + LLSelectMgr::getInstance()->sendGroup(group_id); +} + +static bool callback_deed_to_group(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + if (0 == option) + { + LLUUID group_id; + BOOL groups_identical = LLSelectMgr::getInstance()->selectGetGroup(group_id); + if(group_id.notNull() && groups_identical && (gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED))) + { + LLSelectMgr::getInstance()->sendOwner(LLUUID::null, group_id, FALSE); +// LLViewerStats::getInstance()->incStat(LLViewerStats::ST_RELEASE_COUNT); + } + } + return false; +} + +void LLSidepanelTaskInfo::onClickDeedToGroup() +{ + LLNotifications::instance().add( "DeedObjectToGroup", LLSD(), LLSD(), callback_deed_to_group); +} + +///---------------------------------------------------------------------------- +/// Permissions checkboxes +///---------------------------------------------------------------------------- + +void LLSidepanelTaskInfo::onCommitPerm(LLCheckBoxCtrl *ctrl, U8 field, U32 perm) +{ + LLViewerObject* object = mObjectSelection->getFirstRootObject(); + if(!object) return; + + BOOL new_state = ctrl->get(); + LLSelectMgr::getInstance()->selectionSetObjectPermissions(field, new_state, perm); +} + +void LLSidepanelTaskInfo::onCommitGroupShare() +{ + LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox share with group"); + onCommitPerm(ctrl, PERM_GROUP, PERM_MODIFY | PERM_MOVE | PERM_COPY); +} + +void LLSidepanelTaskInfo::onCommitEveryoneMove() +{ + LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox allow everyone move"); + onCommitPerm(ctrl, PERM_EVERYONE, PERM_MOVE); +} + + +void LLSidepanelTaskInfo::onCommitEveryoneCopy() +{ + LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox allow everyone copy"); + onCommitPerm(ctrl, PERM_EVERYONE, PERM_COPY); +} + +void LLSidepanelTaskInfo::onCommitNextOwnerModify() +{ + LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox next owner can modify"); + onCommitPerm(ctrl, PERM_NEXT_OWNER, PERM_MODIFY); +} + +void LLSidepanelTaskInfo::onCommitNextOwnerCopy() +{ + LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox next owner can copy"); + onCommitPerm(ctrl, PERM_NEXT_OWNER, PERM_COPY); +} + +void LLSidepanelTaskInfo::onCommitNextOwnerTransfer() +{ + LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("checkbox next owner can transfer"); + onCommitPerm(ctrl, PERM_NEXT_OWNER, PERM_TRANSFER); +} + +void LLSidepanelTaskInfo::onCommitName() +{ + LLLineEditor* tb = getChild<LLLineEditor>("Object Name"); + LLSelectMgr::getInstance()->selectionSetObjectName(tb->getText()); +} + +void LLSidepanelTaskInfo::onCommitDesc() +{ + LLLineEditor* le = getChild<LLLineEditor>("Object Description"); + LLSelectMgr::getInstance()->selectionSetObjectDescription(le->getText()); +} + +void LLSidepanelTaskInfo::onCommitSaleInfo() +{ + setAllSaleInfo(); +} + +void LLSidepanelTaskInfo::onCommitSaleType() +{ + setAllSaleInfo(); +} + +void LLSidepanelTaskInfo::setAllSaleInfo() +{ + llinfos << "LLSidepanelTaskInfo::setAllSaleInfo()" << llendl; + LLSaleInfo::EForSale sale_type = LLSaleInfo::FS_NOT; + + LLCheckBoxCtrl *checkPurchase = getChild<LLCheckBoxCtrl>("checkbox for sale"); + + // Set the sale type if the object(s) are for sale. + if(checkPurchase && checkPurchase->get()) + { + sale_type = static_cast<LLSaleInfo::EForSale>(getChild<LLComboBox>("sale type")->getValue().asInteger()); + } + + S32 price = -1; + + LLSpinCtrl *edit_price = getChild<LLSpinCtrl>("Edit Cost"); + price = (edit_price->getTentative()) ? DEFAULT_PRICE : edit_price->getValue().asInteger(); + + // If somehow an invalid price, turn the sale off. + if (price < 0) + sale_type = LLSaleInfo::FS_NOT; + + LLSaleInfo sale_info(sale_type, price); + LLSelectMgr::getInstance()->selectionSetObjectSaleInfo(sale_info); + + // If turned off for-sale, make sure click-action buy is turned + // off as well + if (sale_type == LLSaleInfo::FS_NOT) + { + U8 click_action = 0; + LLSelectMgr::getInstance()->selectionGetClickAction(&click_action); + if (click_action == CLICK_ACTION_BUY) + { + LLSelectMgr::getInstance()->selectionSetClickAction(CLICK_ACTION_TOUCH); + } + } +} + +struct LLSelectionPayable : public LLSelectedObjectFunctor +{ + virtual bool apply(LLViewerObject* obj) + { + // can pay if you or your parent has money() event in script + LLViewerObject* parent = (LLViewerObject*)obj->getParent(); + return (obj->flagTakesMoney() + || (parent && parent->flagTakesMoney())); + } +}; + +// static +void LLSidepanelTaskInfo::onCommitClickAction(U8 click_action) +{ + if (click_action == CLICK_ACTION_BUY) + { + LLSaleInfo sale_info; + LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info); + if (!sale_info.isForSale()) + { + LLNotifications::instance().add("CantSetBuyObject"); + + // Set click action back to its old value + U8 click_action = 0; + LLSelectMgr::getInstance()->selectionGetClickAction(&click_action); +// box->setCurrentByIndex((S32)click_action); + + return; + } + } + else if (click_action == CLICK_ACTION_PAY) + { + // Verify object has script with money() handler + LLSelectionPayable payable; + bool can_pay = mObjectSelection->applyToObjects(&payable); + if (!can_pay) + { + // Warn, but do it anyway. + LLNotifications::instance().add("ClickActionNotPayable"); + } + } + LLSelectMgr::getInstance()->selectionSetClickAction(click_action); +} + +// static +void LLSidepanelTaskInfo::onCommitIncludeInSearch() +{ + LLCheckBoxCtrl *ctrl = getChild<LLCheckBoxCtrl>("search_check"); + LLSelectMgr::getInstance()->selectionSetIncludeInSearch(ctrl->get()); +} + +// virtual +void LLSidepanelTaskInfo::updateVerbs() +{ + LLSidepanelInventorySubpanel::updateVerbs(); + + mOpenBtn->setVisible(!getIsEditing()); + mPayBtn->setVisible(!getIsEditing()); + mBuyBtn->setVisible(!getIsEditing()); + + mOpenBtn->setEnabled(enable_object_open()); + const LLViewerObject *obj = getFirstSelectedObject(); + mEditBtn->setEnabled(obj && obj->permModify()); +} + +void LLSidepanelTaskInfo::onOpenButtonClicked() +{ + if (enable_object_open()) + { + handle_object_open(); + } +} + +void LLSidepanelTaskInfo::onPayButtonClicked() +{ + onCommitClickAction(CLICK_ACTION_PAY); +} + +void LLSidepanelTaskInfo::onBuyButtonClicked() +{ + onCommitClickAction(CLICK_ACTION_BUY); +} + +// virtual +void LLSidepanelTaskInfo::save() +{ + onCommitGroupShare(); + onCommitEveryoneMove(); + onCommitEveryoneCopy(); + onCommitNextOwnerModify(); + onCommitNextOwnerCopy(); + onCommitNextOwnerTransfer(); + onCommitName(); + onCommitDesc(); + onCommitSaleInfo(); + onCommitSaleType(); + onCommitIncludeInSearch(); +} + +void LLSidepanelTaskInfo::setObjectSelection(LLObjectSelectionHandle selection) +{ + mObjectSelection = selection; +} + +LLSidepanelTaskInfo* LLSidepanelTaskInfo::getActivePanel() +{ + return sActivePanel; +} + +LLViewerObject* LLSidepanelTaskInfo::getFirstSelectedObject() +{ + LLSelectNode *node = mObjectSelection->getFirstRootNode(); + if (node) + { + return node->getObject(); + } + return NULL; +} + +const LLUUID& LLSidepanelTaskInfo::getSelectedUUID() +{ + const LLViewerObject* obj = getFirstSelectedObject(); + if (obj) + { + return obj->getID(); + } + return LLUUID::null; +} diff --git a/indra/newview/llsidepaneltaskinfo.h b/indra/newview/llsidepaneltaskinfo.h new file mode 100644 index 0000000000..b6dd4dfb2c --- /dev/null +++ b/indra/newview/llsidepaneltaskinfo.h @@ -0,0 +1,115 @@ +/** + * @file llsidepaneltaskinfo.h + * @brief LLSidepanelTaskInfo class header file + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLSIDEPANELTASKINFO_H +#define LL_LLSIDEPANELTASKINFO_H + +#include "llsidepanelinventorysubpanel.h" +#include "lluuid.h" +#include "llselectmgr.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLSidepanelTaskInfo +// +// Panel for permissions of an object. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLNameBox; +class LLCheckBoxCtrl; +class LLViewerObject; + +class LLSidepanelTaskInfo : public LLSidepanelInventorySubpanel +{ +public: + LLSidepanelTaskInfo(); + virtual ~LLSidepanelTaskInfo(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void setVisible(BOOL visible); + + void setObjectSelection(LLObjectSelectionHandle selection); + + const LLUUID& getSelectedUUID(); + LLViewerObject* getFirstSelectedObject(); + + static LLSidepanelTaskInfo *getActivePanel(); +protected: + /*virtual*/ void refresh(); // refresh all labels as needed + /*virtual*/ void save(); + /*virtual*/ void updateVerbs(); + + // statics + static void onClickClaim(void*); + static void onClickRelease(void*); + void onClickGroup(); + void cbGroupID(LLUUID group_id); + + void onClickDeedToGroup(); + void onCommitPerm(LLCheckBoxCtrl* ctrl, U8 field, U32 perm); + void onCommitGroupShare(); + void onCommitEveryoneMove(); + void onCommitEveryoneCopy(); + void onCommitNextOwnerModify(); + void onCommitNextOwnerCopy(); + void onCommitNextOwnerTransfer(); + void onCommitName(); + void onCommitDesc(); + void onCommitSaleInfo(); + void onCommitSaleType(); + + void onCommitClickAction(U8 click_action); + void onCommitIncludeInSearch(); + + void setAllSaleInfo(); + +private: + LLNameBox* mLabelGroupName; // group name + + LLUUID mCreatorID; + LLUUID mOwnerID; + LLUUID mLastOwnerID; + +protected: + void onOpenButtonClicked(); + void onPayButtonClicked(); + void onBuyButtonClicked(); +private: + LLButton* mOpenBtn; + LLButton* mPayBtn; + LLButton* mBuyBtn; + + LLObjectSelectionHandle mObjectSelection; + static LLSidepanelTaskInfo* sActivePanel; +}; + + +#endif // LL_LLSIDEPANELTASKINFO_H diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp index cd765b0338..d441762fa6 100644 --- a/indra/newview/llspeakbutton.cpp +++ b/indra/newview/llspeakbutton.cpp @@ -62,6 +62,14 @@ LLSpeakButton::Params::Params() // See widgets/talk_button.xml } +void LLSpeakButton::draw() +{ + // gVoiceClient is the authoritative global source of info regarding our open-mic state, we merely reflect that state. + bool openmic = gVoiceClient->getUserPTTState(); + mSpeakBtn->setToggleState(openmic); + LLUICtrl::draw(); +} + LLSpeakButton::LLSpeakButton(const Params& p) : LLUICtrl(p) , mPrivateCallPanel(NULL) @@ -84,7 +92,8 @@ LLSpeakButton::LLSpeakButton(const Params& p) addChild(mSpeakBtn); LLTransientFloaterMgr::getInstance()->addControlView(mSpeakBtn); - mSpeakBtn->setClickedCallback(boost::bind(&LLSpeakButton::onClick_SpeakBtn, this)); + mSpeakBtn->setMouseDownCallback(boost::bind(&LLSpeakButton::onMouseDown_SpeakBtn, this)); + mSpeakBtn->setMouseUpCallback(boost::bind(&LLSpeakButton::onMouseUp_SpeakBtn, this)); mSpeakBtn->setToggleState(FALSE); LLButton::Params show_params = p.show_button; @@ -122,15 +131,15 @@ LLSpeakButton::~LLSpeakButton() { } -void LLSpeakButton::setSpeakBtnToggleState(bool state) +void LLSpeakButton::onMouseDown_SpeakBtn() { - mSpeakBtn->setToggleState(state); + bool down = true; + gVoiceClient->inputUserControlState(down); // this method knows/care about whether this translates into a toggle-to-talk or down-to-talk } - -void LLSpeakButton::onClick_SpeakBtn() +void LLSpeakButton::onMouseUp_SpeakBtn() { - bool speaking = mSpeakBtn->getToggleState(); - gVoiceClient->setUserPTTState(speaking); + bool down = false; + gVoiceClient->inputUserControlState(down); } void LLSpeakButton::onClick_ShowBtn() diff --git a/indra/newview/llspeakbutton.h b/indra/newview/llspeakbutton.h index f59ded2133..e213c562dd 100644 --- a/indra/newview/llspeakbutton.h +++ b/indra/newview/llspeakbutton.h @@ -45,7 +45,6 @@ class LLOutputMonitorCtrl; * clicked. */ class LLSpeakButton : public LLUICtrl - { public: @@ -61,14 +60,14 @@ public: }; /*virtual*/ ~LLSpeakButton(); - - void setSpeakBtnToggleState(bool state); + /*virtual*/ void draw(); protected: friend class LLUICtrlFactory; LLSpeakButton(const Params& p); - void onClick_SpeakBtn(); + void onMouseDown_SpeakBtn(); + void onMouseUp_SpeakBtn(); void onClick_ShowBtn(); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 2341fcfc6d..2ed82b7d62 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -87,6 +87,21 @@ void LLSpeaker::onAvatarNameLookup(const LLUUID& id, const std::string& first, c mDisplayName = first + " " + last; } +LLSpeakerUpdateModeratorEvent::LLSpeakerUpdateModeratorEvent(LLSpeaker* source) +: LLEvent(source, "Speaker add moderator event"), + mSpeakerID (source->mID), + mIsModerator (source->mIsModerator) +{ +} + +LLSD LLSpeakerUpdateModeratorEvent::getValue() +{ + LLSD ret; + ret["id"] = mSpeakerID; + ret["is_moderator"] = mIsModerator; + return ret; +} + LLSpeakerTextModerationEvent::LLSpeakerTextModerationEvent(LLSpeaker* source) : LLEvent(source, "Speaker text moderation event") { @@ -437,9 +452,13 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers) if ( speaker_it->second.isMap() ) { + BOOL is_moderator = speakerp->mIsModerator; speakerp->mIsModerator = speaker_it->second["is_moderator"]; speakerp->mModeratorMutedText = speaker_it->second["mutes"]["text"]; + // Fire event only if moderator changed + if ( is_moderator != speakerp->mIsModerator ) + fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator"); } } } @@ -507,7 +526,11 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) if (agent_info.has("is_moderator")) { + BOOL is_moderator = speakerp->mIsModerator; speakerp->mIsModerator = agent_info["is_moderator"]; + // Fire event only if moderator changed + if ( is_moderator != speakerp->mIsModerator ) + fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator"); } if (agent_info.has("mutes")) diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index e0f22bff4f..04046a8587 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -84,6 +84,16 @@ public: BOOL mModeratorMutedText; }; +class LLSpeakerUpdateModeratorEvent : public LLOldEvents::LLEvent +{ +public: + LLSpeakerUpdateModeratorEvent(LLSpeaker* source); + /*virtual*/ LLSD getValue(); +private: + const LLUUID& mSpeakerID; + BOOL mIsModerator; +}; + class LLSpeakerTextModerationEvent : public LLOldEvents::LLEvent { public: diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 4c322810d5..2c1f468f77 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -744,6 +744,7 @@ bool idle_startup() // We have at least some login information on a SLURL gFirstname = gLoginHandler.getFirstName(); gLastname = gLoginHandler.getLastName(); + LL_DEBUGS("LLStartup") << "STATE_FIRST: setting gFirstname, gLastname from gLoginHandler: '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; // Show the login screen if we don't have everything show_connect_box = @@ -754,6 +755,7 @@ bool idle_startup() LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo"); gFirstname = cmd_line_login[0].asString(); gLastname = cmd_line_login[1].asString(); + LL_DEBUGS("LLStartup") << "Setting gFirstname, gLastname from gSavedSettings(\"UserLoginInfo\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; LLMD5 pass((unsigned char*)cmd_line_login[2].asString().c_str()); char md5pass[33]; /* Flawfinder: ignore */ @@ -771,6 +773,7 @@ bool idle_startup() { gFirstname = gSavedSettings.getString("FirstName"); gLastname = gSavedSettings.getString("LastName"); + LL_DEBUGS("LLStartup") << "AutoLogin: setting gFirstname, gLastname from gSavedSettings(\"First|LastName\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; gPassword = LLStartUp::loadPasswordFromDisk(); gSavedSettings.setBOOL("RememberPassword", TRUE); @@ -786,6 +789,7 @@ bool idle_startup() // a valid grid is selected gFirstname = gSavedSettings.getString("FirstName"); gLastname = gSavedSettings.getString("LastName"); + LL_DEBUGS("LLStartup") << "normal login: setting gFirstname, gLastname from gSavedSettings(\"First|LastName\"): '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; gPassword = LLStartUp::loadPasswordFromDisk(); show_connect_box = true; } @@ -896,8 +900,15 @@ bool idle_startup() gViewerWindow->moveProgressViewToFront(); //reset the values that could have come in from a slurl - gFirstname = gLoginHandler.getFirstName(); - gLastname = gLoginHandler.getLastName(); + // DEV-42215: Make sure they're not empty -- gFirstname and gLastname + // might already have been set from gSavedSettings, and it's too bad + // to overwrite valid values with empty strings. + if (! gLoginHandler.getFirstName().empty() && ! gLoginHandler.getLastName().empty()) + { + gFirstname = gLoginHandler.getFirstName(); + gLastname = gLoginHandler.getLastName(); + LL_DEBUGS("LLStartup") << "STATE_LOGIN_CLEANUP: setting gFirstname, gLastname from gLoginHandler: '" << gFirstname << "' '" << gLastname << "'" << LL_ENDL; + } if (show_connect_box) { diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 9ca2d3f61d..edbac69e1b 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -170,6 +170,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>); LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloater>); + LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>); LLFloaterReg::add("inventory", "floater_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInventory>); LLFloaterReg::add("inspect", "floater_inspect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInspect>); LLInspectAvatarUtil::registerFloater(); diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp index b2a0fa4b1c..70a7d835a3 100644 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -499,8 +499,14 @@ void LLViewerMediaFocus::focusZoomOnMedia(LLUUID media_id) S32 face = obj->getFaceIndexWithMediaImpl(impl, -1); // We don't have a proper pick normal here, and finding a face's real normal is... complicated. - // For now, use +z to look at the top of the object. - LLVector3 normal(0.0f, 0.0f, 1.0f); + LLVector3 normal = obj->getApproximateFaceNormal(face); + if(normal.isNull()) + { + // If that didn't work, use the inverse of the camera "look at" axis, which should keep the camera pointed in the same direction. +// llinfos << "approximate face normal invalid, using camera direction." << llendl; + normal = LLViewerCamera::getInstance()->getAtAxis(); + normal *= (F32)-1.0f; + } // Attempt to focus/zoom on that face. setFocusFace(obj, face, impl, normal); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index d158fc29a6..4d4ad1c022 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -210,6 +210,7 @@ #include "lltexlayer.h" #include "llappearancemgr.h" +#include "llimfloater.h" using namespace LLVOAvatarDefines; @@ -2516,24 +2517,12 @@ class LLObjectEnableTouch : public view_listener_t // label.assign("Touch"); // } //} -/* -bool handle_object_open() -{ - LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if(!obj) return true; - LLFloaterOpenObject::show(); - return true; +void handle_object_open() +{ + LLFloaterReg::showInstance("openobject"); } -class LLObjectOpen : public view_listener_t -{ - bool handleEvent(const LLSD& userdata) - { - return handle_object_open(); - } -}; -*/ bool enable_object_open() { // Look for contents in root object, which is all the LLFloaterOpenObject @@ -2641,8 +2630,25 @@ void handle_object_edit() // Could be first use LLFirstUse::useBuild(); return; - } + +void handle_object_inspect() +{ + // Disable sidepanel inspector + /* + LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); + LLViewerObject* selected_objectp = selection->getFirstRootObject(); + if (selected_objectp) + { + LLSD key; + key["task"] = "task"; + LLSideTray::getInstance()->showPanel("sidepanel_inventory", key); + } + */ + + LLFloaterReg::showInstance("inspect", LLSD()); +} + //--------------------------------------------------------------------------- // Land pie menu //--------------------------------------------------------------------------- @@ -5190,7 +5196,7 @@ void show_debug_menus() gMenuBarView->setItemEnabled("Develop", qamode); // Server ('Admin') menu hidden when not in godmode. - const bool show_server_menu = debug && (gAgent.getGodLevel() > GOD_NOT); + const bool show_server_menu = debug && (gAgent.getGodLevel() > GOD_NOT || gAgent.getAdminOverride()); gMenuBarView->setItemVisible("Admin", show_server_menu); gMenuBarView->setItemEnabled("Admin", show_server_menu); } @@ -6258,9 +6264,13 @@ class LLAvatarSendIM : public view_listener_t //EInstantMessage type = have_agent_callingcard(gLastHitObjectID) // ? IM_SESSION_ADD : IM_SESSION_CARDLESS_START; - gIMMgr->addSession(name, + LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, avatar->getID()); + if (session_id != LLUUID::null) + { + LLIMFloater::show(session_id); + } } return true; } @@ -7953,6 +7963,8 @@ void initialize_menus() commit.add("Object.Buy", boost::bind(&handle_buy)); commit.add("Object.Edit", boost::bind(&handle_object_edit)); + commit.add("Object.Inspect", boost::bind(&handle_object_inspect)); + commit.add("Object.Open", boost::bind(&handle_object_open)); commit.add("Object.Take", boost::bind(&handle_take)); diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h index b65878b5e6..db4eb3be9d 100644 --- a/indra/newview/llviewermenu.h +++ b/indra/newview/llviewermenu.h @@ -94,6 +94,7 @@ void handle_sit_down(void*); void handle_object_build(void*); void handle_object_touch(); bool enable_object_open(); +void handle_object_open(); // Buy either contents or object itself void handle_buy(); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index b2d7d71b53..9923c9ac74 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -986,8 +986,6 @@ void LLViewerFetchedTexture::init(bool firstinit) mFetchPriority = 0; mDownloadProgress = 0.f; mFetchDeltaTime = 999999.f; - mDecodeFrame = 0; - mVisibleFrame = 0; mForSculpt = FALSE ; mIsFetched = FALSE ; @@ -1370,16 +1368,6 @@ void LLViewerFetchedTexture::processTextureStats() } } -//texture does not have any data, so we don't know the size of the image, treat it like 32 * 32. -F32 LLViewerFetchedTexture::calcDecodePriorityForUnknownTexture(F32 pixel_priority) -{ - F32 desired = (F32)(log(32.0/pixel_priority) / log_2); - S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired + 1; - ddiscard = llclamp(ddiscard, 1, 9); - - return ddiscard*100000.f; -} - F32 LLViewerFetchedTexture::calcDecodePriority() { #ifndef LL_RELEASE_FOR_DOWNLOAD @@ -1406,12 +1394,6 @@ F32 LLViewerFetchedTexture::calcDecodePriority() S32 cur_discard = getDiscardLevel(); bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); F32 pixel_priority = fsqrtf(mMaxVirtualSize); - const S32 MIN_NOT_VISIBLE_FRAMES = 30; // NOTE: this function is not called every frame - mDecodeFrame++; - if (pixel_priority > 0.f) - { - mVisibleFrame = mDecodeFrame; - } F32 priority; if (mIsMissingAsset) @@ -1422,10 +1404,6 @@ F32 LLViewerFetchedTexture::calcDecodePriority() { priority = -1.0f ; } - else if (!isJustBound() && mCachedRawImageReady && !mBoostLevel) - { - priority = -1.0f; - } else if(mCachedRawDiscardLevel > -1 && mDesiredDiscardLevel >= mCachedRawDiscardLevel) { priority = -1.0f; @@ -1447,11 +1425,6 @@ F32 LLViewerFetchedTexture::calcDecodePriority() // Always want high boosted images priority = 1.f; } - else if (mVisibleFrame == 0 || (mDecodeFrame - mVisibleFrame > MIN_NOT_VISIBLE_FRAMES)) - { - // Don't decode anything that isn't visible unless it's important - priority = -2.0f; - } else { // Leave the priority as-is @@ -1460,7 +1433,13 @@ F32 LLViewerFetchedTexture::calcDecodePriority() } else if (cur_discard < 0) { - priority = calcDecodePriorityForUnknownTexture(pixel_priority) ; + //texture does not have any data, so we don't know the size of the image, treat it like 32 * 32. + // priority range = 100,000 - 500,000 + static const F64 log_2 = log(2.0); + F32 desired = (F32)(log(32.0/pixel_priority) / log_2); + S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired; + ddiscard = llclamp(ddiscard, 0, 4); + priority = (ddiscard+1)*100000.f; } else if ((mMinDiscardLevel > 0) && (cur_discard <= mMinDiscardLevel)) { @@ -1473,38 +1452,47 @@ F32 LLViewerFetchedTexture::calcDecodePriority() } else { - // priority range = 100000-400000 - S32 ddiscard = cur_discard - mDesiredDiscardLevel; + // priority range = 100,000 - 500,000 + S32 desired_discard = mDesiredDiscardLevel; if (getDontDiscard()) { - ddiscard+=2; + desired_discard -= 2; } - else if (ddiscard > 2 && mGLTexturep.notNull() && !mGLTexturep->getBoundRecently() && mBoostLevel == LLViewerTexture::BOOST_NONE) + else if (!isJustBound() && mCachedRawImageReady && !mBoostLevel) { - ddiscard-=2; + // We haven't rendered this in the last half second, and we have a cached raw image, leave the desired discard as-is + desired_discard = cur_discard; } + else if (mGLTexturep.notNull() && !mGLTexturep->getBoundRecently() && mBoostLevel == LLViewerTexture::BOOST_NONE) + { + // We haven't rendered this in a while, de-prioritize it + desired_discard += 2; + } + S32 ddiscard = cur_discard - desired_discard; ddiscard = llclamp(ddiscard, 0, 4); - priority = ddiscard*100000.f; + priority = (ddiscard+1)*100000.f; } + + // Priority Formula: + // BOOST_HIGH + ADDITIONAL PRI + DELTA DISCARD + BOOST LEVEL + PIXELS + // [10,000,000] + [1-9,000,000] + [1-400,000] + [1-20,000] + [0-999] if (priority > 0.0f) { - // priority range = 100000-900000 - pixel_priority = llclamp(pixel_priority, 0.0f, priority-1.f); + pixel_priority = llclamp(pixel_priority, 0.0f, 999.f); + + priority = pixel_priority + 1000.f * mBoostLevel; - // priority range = [100000.f, 2000000.f] if ( mBoostLevel > BOOST_HIGH) { - priority = 1000000.f + pixel_priority + 1000.f * (mBoostLevel - LLViewerTexture::BOOST_NONE); + priority += 10000000.f; } - else - { - priority += 0.f + pixel_priority + 1000.f * (mBoostLevel - LLViewerTexture::BOOST_NONE); - } - - // priority range = [2100000.f, 5000000.f] if mAdditionalDecodePriority > 1.0 - if(mAdditionalDecodePriority > 1.0f) + + if(mAdditionalDecodePriority > 0.0f) { - priority += 2000000.f + mAdditionalDecodePriority ; + // 1-9 + S32 additional_priority = (S32)(1.0f + mAdditionalDecodePriority*8.0f + .5f); // round + // priority range += 0-9,000,000 + priority += 1000000.f * (F32)additional_priority; } } return priority; @@ -1517,13 +1505,9 @@ void LLViewerFetchedTexture::setDecodePriority(F32 priority) mDecodePriority = priority; } -F32 LLViewerFetchedTexture::maxAdditionalDecodePriority() -{ - return 2000000.f; -} void LLViewerFetchedTexture::setAdditionalDecodePriority(F32 priority) { - priority *= maxAdditionalDecodePriority(); + priority = llclamp(priority, 0.f, 1.f); if(mAdditionalDecodePriority < priority) { mAdditionalDecodePriority = priority; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 4da6620658..bde87d1dd5 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -383,7 +383,6 @@ public: F32 getDecodePriority() const { return mDecodePriority; }; void setAdditionalDecodePriority(F32 priority) ; - F32 maxAdditionalDecodePriority() ; void updateVirtualSize() ; @@ -454,7 +453,6 @@ private: void init(bool firstinit) ; void cleanup() ; - F32 calcDecodePriorityForUnknownTexture(F32 pixel_priority) ; void saveRawImage() ; BOOL forceFetch() ; void setCachedRawImage() ; @@ -488,8 +486,6 @@ protected: F32 mDownloadProgress; F32 mFetchDeltaTime; F32 mRequestDeltaTime; - S32 mDecodeFrame; - S32 mVisibleFrame; // decode frame where image was last visible F32 mDecodePriority; // The priority for decoding this image. S32 mMinDiscardLevel; S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index df5481c874..39d4bb0c02 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -68,9 +68,6 @@ #include "llfloaterfriends.h" //VIVOX, inorder to refresh communicate panel #include "llfloaterchat.h" // for LLFloaterChat::addChat() -// for Talk Button's state updating -#include "llnearbychatbar.h" - // for base64 decoding #include "apr_base64.h" @@ -5791,7 +5788,6 @@ bool LLVoiceClient::getMuteMic() const void LLVoiceClient::setUserPTTState(bool ptt) { mUserPTTState = ptt; - if (LLNearbyChatBar::instanceExists()) LLNearbyChatBar::getInstance()->setPTTState(ptt); } bool LLVoiceClient::getUserPTTState() @@ -5802,7 +5798,6 @@ bool LLVoiceClient::getUserPTTState() void LLVoiceClient::toggleUserPTTState(void) { mUserPTTState = !mUserPTTState; - if (LLNearbyChatBar::instanceExists()) LLNearbyChatBar::getInstance()->setPTTState(mUserPTTState); } void LLVoiceClient::setVoiceEnabled(bool enabled) @@ -5930,8 +5925,6 @@ void LLVoiceClient::setMicGain(F32 volume) void LLVoiceClient::keyDown(KEY key, MASK mask) { -// LL_DEBUGS("Voice") << "key is " << LLKeyboard::stringFromKey(key) << LL_ENDL; - if (gKeyboard->getKeyRepeated(key)) { // ignore auto-repeat keys @@ -5940,44 +5933,39 @@ void LLVoiceClient::keyDown(KEY key, MASK mask) if(!mPTTIsMiddleMouse) { - if(mPTTIsToggle) - { - if(key == mPTTKey) - { - toggleUserPTTState(); - } - } - else if(mPTTKey != KEY_NONE) - { - setUserPTTState(gKeyboard->getKeyDown(mPTTKey)); - } + bool down = (mPTTKey != KEY_NONE) + && gKeyboard->getKeyDown(mPTTKey); + inputUserControlState(down); } } void LLVoiceClient::keyUp(KEY key, MASK mask) { if(!mPTTIsMiddleMouse) { - if(!mPTTIsToggle && (mPTTKey != KEY_NONE)) + bool down = (mPTTKey != KEY_NONE) + && gKeyboard->getKeyDown(mPTTKey); + inputUserControlState(down); + } +} +void LLVoiceClient::inputUserControlState(bool down) +{ + if(mPTTIsToggle) + { + if(down) // toggle open-mic state on 'down' { - setUserPTTState(gKeyboard->getKeyDown(mPTTKey)); + toggleUserPTTState(); } } + else // set open-mic state as an absolute + { + setUserPTTState(down); + } } void LLVoiceClient::middleMouseState(bool down) { if(mPTTIsMiddleMouse) { - if(mPTTIsToggle) - { - if(down) - { - toggleUserPTTState(); - } - } - else - { - setUserPTTState(down); - } + inputUserControlState(down); } } diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 9df96d9a52..347fae6156 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -188,6 +188,7 @@ static void updatePosition(void); void setUserPTTState(bool ptt); bool getUserPTTState(); void toggleUserPTTState(void); + void inputUserControlState(bool down); // interpret any sort of up-down mic-open control input according to ptt-toggle prefs void setVoiceEnabled(bool enabled); static bool voiceEnabled(); void setUsePTT(bool usePTT); @@ -196,7 +197,7 @@ static void updatePosition(void); void setEarLocation(S32 loc); void setVoiceVolume(F32 volume); void setMicGain(F32 volume); - void setUserVolume(const LLUUID& id, F32 volume); // set's volume for specified agent, from 0-1 (where .5 is nominal) + void setUserVolume(const LLUUID& id, F32 volume); // sets volume for specified agent, from 0-1 (where .5 is nominal) void setLipSyncEnabled(BOOL enabled); BOOL lipSyncEnabled(); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 78f534bacd..021fc74648 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -1638,6 +1638,45 @@ bool LLVOVolume::hasMedia() const return result; } +LLVector3 LLVOVolume::getApproximateFaceNormal(U8 face_id) +{ + LLVector3 result = LLVector3::zero; + + LLFace* facep = mDrawable->getFace(face_id); + if(facep) + { + LLStrider<LLVector3> verticesp; + LLStrider<LLVector3> normalsp; + LLStrider<LLVector2> texCoordsp; + LLStrider<U16> indicesp; + S32 index_offset; + index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp); + + if(index_offset != -1 && (normalsp.get() != NULL)) + { + U16 count = facep->getGeomCount(); + U16 i; + + for(i=0; i < count; i++) + { + LLVector3 normal = *normalsp++; +// llinfos << "adding " << normal << llendl; + result += normal; + } + } + } + + if(!result.isNull()) + { +// llinfos << "before conversion: " << result << llendl; + result = volumeDirectionToAgent(result); + result.normalize(); +// llinfos << "after conversion: " << result << llendl; + } + + return result; +} + void LLVOVolume::requestMediaDataUpdate() { sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this)); diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 0574d3e385..784ef16ba3 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -263,6 +263,8 @@ public: F64 getTotalMediaInterest() const; bool hasMedia() const; + + LLVector3 getApproximateFaceNormal(U8 face_id); protected: S32 computeLODDetail(F32 distance, F32 radius); diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index e5ff62746e..a8c4625f6e 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -55,8 +55,6 @@ const BOOL gUseRoam = FALSE; /////////////////////////////////// -#include "randgauss.h" - template<class T> inline T LERP(T a, T b, F32 factor) { return a + (b - a) * factor; diff --git a/indra/newview/res/viewerRes.rc b/indra/newview/res/viewerRes.rc index 433070ce34..38291e45c9 100644 --- a/indra/newview/res/viewerRes.rc +++ b/indra/newview/res/viewerRes.rc @@ -134,8 +134,8 @@ TOOLMEDIAOPEN CURSOR "toolmediaopen.cur" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,0,0,3256 - PRODUCTVERSION 2,0,0,3256 + FILEVERSION 2,0,0,200030 + PRODUCTVERSION 2,0,0,200030 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -152,12 +152,12 @@ BEGIN BEGIN VALUE "CompanyName", "Linden Lab" VALUE "FileDescription", "Second Life" - VALUE "FileVersion", "2.0.0.3256" + VALUE "FileVersion", "2.0.0.200030" VALUE "InternalName", "Second Life" VALUE "LegalCopyright", "Copyright © 2001-2008, Linden Research, Inc." VALUE "OriginalFilename", "SecondLife.exe" VALUE "ProductName", "Second Life" - VALUE "ProductVersion", "2.0.0.3256" + VALUE "ProductVersion", "2.0.0.200030" END END BLOCK "VarFileInfo" diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_Off.png Binary files differnew file mode 100644 index 0000000000..3cfe2e850e --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_Off.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_On.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_On.png Binary files differnew file mode 100644 index 0000000000..bb5d85e410 --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Back_On.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Eye_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Eye_Off.png Binary files differnew file mode 100644 index 0000000000..2b50986780 --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Eye_Off.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_Off.png Binary files differnew file mode 100644 index 0000000000..9876aa456c --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_Off.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_On.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_On.png Binary files differnew file mode 100644 index 0000000000..f481fed88c --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Front_On.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_Off.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_Off.png Binary files differnew file mode 100644 index 0000000000..d58b4ff990 --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_Off.png diff --git a/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_On.png b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_On.png Binary files differnew file mode 100644 index 0000000000..6e73898992 --- /dev/null +++ b/indra/newview/skins/default/textures/bottomtray/Cam_Preset_Side_On.png diff --git a/indra/newview/skins/default/textures/icons/Inv_Alpha.png b/indra/newview/skins/default/textures/icons/Inv_Alpha.png Binary files differindex e8d246c6fa..b65dc1929d 100644 --- a/indra/newview/skins/default/textures/icons/Inv_Alpha.png +++ b/indra/newview/skins/default/textures/icons/Inv_Alpha.png diff --git a/indra/newview/skins/default/textures/icons/Inv_Tattoo.png b/indra/newview/skins/default/textures/icons/Inv_Tattoo.png Binary files differindex e8d246c6fa..a632197eb5 100644 --- a/indra/newview/skins/default/textures/icons/Inv_Tattoo.png +++ b/indra/newview/skins/default/textures/icons/Inv_Tattoo.png diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 7f33330123..fba8e0b06c 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -28,7 +28,7 @@ <texture name="BackArrow_Press" file_name="icons/BackArrow_Press.png" preload="false" /> <texture name="Blank" file_name="Blank.png" preload="false" /> - + <texture name="BottomTray_BG" file_name="bottomtray/BottomTray_BG.png" preload="false" /> <texture name="BuyArrow_Off" file_name="navbar/BuyArrow_Off.png" preload="true" scale.left="1" scale.top="1" scale.right="0" scale.bottom="0" /> @@ -51,6 +51,16 @@ <texture name="Cam_Pan_Off" file_name="bottomtray/Cam_Pan_Off.png" preload="false" /> <texture name="Cam_Pan_Over" file_name="bottomtray/CCam_Pan_Over.png" preload="false" /> <texture name="Cam_Pan_Press" file_name="bottomtray/Cam_Pan_Press.png" preload="false" /> + + <texture name="Cam_Preset_Back_Off" file_name="bottomtray/Cam_Preset_Back_Off.png" preload="false" /> + <texture name="Cam_Preset_Back_On" file_name="bottomtray/Cam_Preset_Back_On.png" preload="false" /> + <texture name="Cam_Preset_Eye_Off" file_name="bottomtray/Cam_Preset_Eye_Off.png" preload="false" /> + <texture name="Cam_Preset_Eye_On" file_name="bottomtray/Cam_Preset_Eye_On.png" preload="false" /> + <texture name="Cam_Preset_Front_Off" file_name="bottomtray/Cam_Preset_Front_Off.png" preload="false" /> + <texture name="Cam_Preset_Front_On" file_name="bottomtray/Cam_Preset_Front_On.png" preload="false" /> + <texture name="Cam_Preset_Side_Off" file_name="bottomtray/Cam_Preset_Side_Off.png" preload="false" /> + <texture name="Cam_Preset_Side_On" file_name="bottomtray/Cam_Preset_Side_On.png" preload="false" /> + <texture name="Cam_Rotate_In" file_name="bottomtray/Cam_Rotate_In.png" preload="false" /> <texture name="Cam_Rotate_Out" file_name="bottomtray/Cam_Rotate_Out.png" preload="false" /> <texture name="Cam_Tracking_In" file_name="bottomtray/Cam_Tracking_In.png" preload="false" /> @@ -499,9 +509,6 @@ <!--WARNING OLD ART *do not use*--> - <texture name="Banner_ForSale" file_name="Banner_ForSale.png" preload="false" /> - <texture name="Banner_YouAreHere" file_name="Banner_YouAreHere.png" preload="false" /> - <texture name="btn_chatbar.tga" scale.left="20" scale.top="24" scale.right="44" scale.bottom="0" /> <texture name="btn_chatbar_selected.tga" scale.left="20" scale.top="24" scale.right="44" scale.bottom="0" /> diff --git a/indra/newview/skins/default/xui/en/floater_buy_land.xml b/indra/newview/skins/default/xui/en/floater_buy_land.xml index 0f710a8047..6e0c3dfe54 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_land.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_land.xml @@ -115,7 +115,7 @@ Try selecting a smaller area. </floater.string> <floater.string name="buy_for_US"> - Buy L$ [AMOUNT] for approx. US$ [AMOUNT2], + Buy L$ [AMOUNT] for approx. [LOCAL_AMOUNT], </floater.string> <floater.string name="parcel_meters"> @@ -172,10 +172,6 @@ supports [AMOUNT2] objects name="no_parcel_selected"> (no parcel selected) </floater.string> - <floater.string - name="buy_currency"> - Buy L$ [LINDENS] for approx. US$ [USD] - </floater.string> <text type="string" length="1" @@ -667,7 +663,7 @@ This parcel is 512 m² of land. name="currency_est" top="409" width="178"> - for approx. US$ [AMOUNT2] + for approx. [LOCAL_AMOUNT] </text> <text type="string" diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml index a569b62e96..5c09bc3a02 100644 --- a/indra/newview/skins/default/xui/en/floater_camera.xml +++ b/indra/newview/skins/default/xui/en/floater_camera.xml @@ -34,7 +34,7 @@ mouse_opaque="false" name="controls" width="148"> - <joystick_track + <joystick_track follows="top|left" height="78" image_selected="Cam_Tracking_In" @@ -50,7 +50,7 @@ visible="false" width="78" /> <!--TODO: replace with slider, + - images --> - <joystick_zoom + <joystick_zoom follows="top|left" height="78" image_unselected="ScrollThumb_Vert" @@ -80,66 +80,65 @@ tool_tip="Orbit camera around focus" top="22" width="78" /> - <panel + <panel height="78" layout="topleft" left="36" name="camera_presets" - top="30" + top="20" visible="false" width="78"> <button - height="30" - image_selected="CameraPreset_Rear" - image_unselected="CameraPreset_Rear" + height="40" + image_selected="Cam_Preset_Back_On" + image_unselected="Cam_Preset_Back_Off" layout="topleft" - left="5" + left="0" name="rear_view" tool_tip="Rear View" top="2" - width="30"> + width="40"> <click_callback function="CameraPresets.ChangeView" parameter="rear_view" /> </button> <button - height="30" - image_selected="CameraPreset_3_4" - image_unselected="CameraPreset_3_4" + height="40" + image_selected="Cam_Preset_Side_On" + image_unselected="Cam_Preset_Side_Off" layout="topleft" left_pad="5" name="group_view" tool_tip="Group View" top="2" - width="30"> + width="40"> <click_callback function="CameraPresets.ChangeView" parameter="group_view" /> </button> <button - height="30" - image_selected="CameraPreset_Front" - image_unselected="CameraPreset_Front" + height="40" + image_selected="Cam_Preset_Front_On" + image_unselected="Cam_Preset_Front_Off" layout="topleft" - left="5" + left="0" name="front_view" tool_tip="Front View" top_pad="5" - width="30"> + width="40"> <click_callback function="CameraPresets.ChangeView" parameter="front_view" /> </button> <button - height="30" - image_selected="CameraPreset_Mouselook" - image_unselected="CameraPreset_Mouselook" + height="40" + image_selected="Cam_Preset_Eye_Off" + image_unselected="Cam_Preset_Eye_Off" layout="topleft" left_pad="5" name="mouselook_view" tool_tip="Mouselook View" - top_pad="-30" - width="30"> + width="40"> <click_callback function="CameraPresets.ChangeView" parameter="mouselook_view" /> @@ -165,7 +164,6 @@ name="orbit_btn" tab_stop="false" tool_tip="Orbit camera" - value="true" width="25"> </button> <button diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml index 70af2f63b6..452d28d4ea 100644 --- a/indra/newview/skins/default/xui/en/floater_im_session.xml +++ b/indra/newview/skins/default/xui/en/floater_im_session.xml @@ -15,7 +15,7 @@ width="520" can_resize="true" min_width="350" - min_height="350"> + min_height="369"> <layout_stack follows="left|top|right|bottom" height="354" width="520" diff --git a/indra/newview/skins/default/xui/en/floater_pay.xml b/indra/newview/skins/default/xui/en/floater_pay.xml index b4becfa022..509cffe490 100644 --- a/indra/newview/skins/default/xui/en/floater_pay.xml +++ b/indra/newview/skins/default/xui/en/floater_pay.xml @@ -2,22 +2,29 @@ <floater legacy_header_height="18" can_minimize="false" - height="185" + height="200" layout="topleft" name="Give Money" help_topic="give_money" save_rect="true" width="225"> + <string + name="payee_group"> + Pay Group + </string> + <string + name="payee_resident"> + Pay Resident + </string> <text type="string" length="1" follows="left|top" - font="SansSerifBold" height="18" layout="topleft" left="12" name="payee_label" - top="7" + top="22" width="75"> Pay: </text> @@ -45,7 +52,6 @@ </text> <button height="23" - font="SansSerifSmall" label="L$1" label_selected="L$1" layout="topleft" @@ -55,8 +61,7 @@ width="80" /> <button height="23" - label="L$1" - font="SansSerif" + label="L$5" label_selected="L$5" layout="topleft" left_pad="15" @@ -65,7 +70,6 @@ <button height="23" label="L$10" - font="SansSerifHuge" label_selected="L$10" layout="topleft" left="25" diff --git a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml index 8ee67b9a02..590621062c 100644 --- a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml @@ -91,6 +91,8 @@ name="zoom_in">
<menu_item_call.on_click
function="InspectAvatar.ZoomIn"/>
+ <menu_item_call.on_visible
+ function="InspectAvatar.VisibleZoomIn"/>
</menu_item_call>
<menu_item_call
label="Pay"
diff --git a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml index 93c53981f3..04a247fd54 100644 --- a/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_inspect_object_gear.xml @@ -73,7 +73,7 @@ <menu_item_call label="Edit" layout="topleft" - name="report"> + name="edit"> <menu_item_call.on_click function="Object.Edit" /> <menu_item_call.on_enable diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 62940b87dc..8b6ab4e4d8 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -553,6 +553,16 @@ <menu_item_separator layout="topleft" /> <menu_item_call + label="Save As" + layout="topleft" + name="Save As"> + <menu_item_call.on_click + function="Inventory.DoToSelected" + parameter="save_as" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call label="Detach From Yourself" layout="topleft" name="Detach From Yourself"> diff --git a/indra/newview/skins/default/xui/en/menu_inventory_add.xml b/indra/newview/skins/default/xui/en/menu_inventory_add.xml new file mode 100644 index 0000000000..b07a8bb512 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_inventory_add.xml @@ -0,0 +1,229 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<menu + layout="topleft" + left="0" + mouse_opaque="false" + name="menu_inventory_add" + visible="false"> + <menu + create_jump_keys="true" + label="Upload" + layout="topleft" + name="upload" + tear_off="true"> + <menu_item_call + label="Image (L$[COST])..." + layout="topleft" + name="Upload Image" + shortcut="control|U"> + <menu_item_call.on_click + function="File.UploadImage" + parameter="" /> + <menu_item_call.on_enable + function="File.EnableUpload" /> + </menu_item_call> + <menu_item_call + label="Sound (L$[COST])..." + layout="topleft" + name="Upload Sound"> + <menu_item_call.on_click + function="File.UploadSound" + parameter="" /> + <menu_item_call.on_enable + function="File.EnableUpload" /> + </menu_item_call> + <menu_item_call + label="Animation (L$[COST])..." + layout="topleft" + name="Upload Animation"> + <menu_item_call.on_click + function="File.UploadAnim" + parameter="" /> + <menu_item_call.on_enable + function="File.EnableUpload" /> + </menu_item_call> + <menu_item_call + label="Bulk (L$[COST] per file)..." + layout="topleft" + name="Bulk Upload"> + <menu_item_call.on_click + function="File.UploadBulk" + parameter="" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + </menu> + + <menu_item_call + label="New Folder" + layout="topleft" + name="New Folder"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="category" /> + </menu_item_call> + <menu_item_call + label="New Script" + layout="topleft" + name="New Script"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="lsl" /> + </menu_item_call> + <menu_item_call + label="New Note" + layout="topleft" + name="New Note"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="notecard" /> + </menu_item_call> + <menu_item_call + label="New Gesture" + layout="topleft" + name="New Gesture"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="gesture" /> + </menu_item_call> + <menu + height="175" + label="New Clothes" + layout="topleft" + left_delta="0" + mouse_opaque="false" + name="New Clothes" + top_pad="514" + width="125"> + <menu_item_call + label="New Shirt" + layout="topleft" + name="New Shirt"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="shirt" /> + </menu_item_call> + <menu_item_call + label="New Pants" + layout="topleft" + name="New Pants"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="pants" /> + </menu_item_call> + <menu_item_call + label="New Shoes" + layout="topleft" + name="New Shoes"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="shoes" /> + </menu_item_call> + <menu_item_call + label="New Socks" + layout="topleft" + name="New Socks"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="socks" /> + </menu_item_call> + <menu_item_call + label="New Jacket" + layout="topleft" + name="New Jacket"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="jacket" /> + </menu_item_call> + <menu_item_call + label="New Skirt" + layout="topleft" + name="New Skirt"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="skirt" /> + </menu_item_call> + <menu_item_call + label="New Gloves" + layout="topleft" + name="New Gloves"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="gloves" /> + </menu_item_call> + <menu_item_call + label="New Undershirt" + layout="topleft" + name="New Undershirt"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="undershirt" /> + </menu_item_call> + <menu_item_call + label="New Underpants" + layout="topleft" + name="New Underpants"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="underpants" /> + </menu_item_call> + <menu_item_call + label="New Alpha" + layout="topleft" + name="New Alpha"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="alpha" /> + </menu_item_call> + <menu_item_call + label="New Tattoo" + layout="topleft" + name="New Tattoo"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="tattoo" /> + </menu_item_call> + </menu> + <menu + height="85" + label="New Body Parts" + layout="topleft" + left_delta="0" + mouse_opaque="false" + name="New Body Parts" + top_pad="514" + width="118"> + <menu_item_call + label="New Shape" + layout="topleft" + name="New Shape"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="shape" /> + </menu_item_call> + <menu_item_call + label="New Skin" + layout="topleft" + name="New Skin"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="skin" /> + </menu_item_call> + <menu_item_call + label="New Hair" + layout="topleft" + name="New Hair"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="hair" /> + </menu_item_call> + <menu_item_call + label="New Eyes" + layout="topleft" + name="New Eyes"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="eyes" /> + </menu_item_call> + </menu> +</menu>
\ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml new file mode 100644 index 0000000000..435a3e6d34 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_inventory_gear_default.xml @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<menu + bottom="806" + layout="topleft" + left="0" + mouse_opaque="false" + name="menu_gear_default" + visible="false"> + <menu_item_call + label="New Inventory Window" + layout="topleft" + name="new_window"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="new_window" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call + label="Sort by Name" + layout="topleft" + name="sort_by_name"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="sort_by_name" /> + </menu_item_call> + <menu_item_call + label="Sort by Most Recent" + layout="topleft" + name="sort_by_recent"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="sort_by_recent" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call + label="Show Filters" + layout="topleft" + name="show_filters"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="show_filters" /> + </menu_item_call> + <menu_item_call + label="Reset Filters" + layout="topleft" + name="reset_filters"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="reset_filters" /> + </menu_item_call> + <menu_item_call + label="Close All Folders" + layout="topleft" + name="close_folders"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="close_folders" /> + </menu_item_call> + <menu_item_separator + layout="topleft" /> + <menu_item_call + label="Empty Trash" + layout="topleft" + name="empty_trash"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="empty_trash" /> + </menu_item_call> + <menu_item_call + label="Empty Lost and Found" + layout="topleft" + name="empty_lostnfound"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="empty_lostnfound" /> + </menu_item_call> + <menu_item_call + label="Save Texture As" + layout="topleft" + name="Save Texture As"> + <on_click + function="Inventory.GearDefault.Custom.Action" + parameter="save_texture" /> + <on_enable + function="Inventory.GearDefault.Enable" + parameter="save_texture" /> + </menu_item_call> +</menu> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 215a25ffda..df2c2465c5 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -98,6 +98,24 @@ function="World.SetBusy"/> </menu_item_call> </menu> + <menu_item_call + label="Request Admin Status" + layout="topleft" + name="Request Admin Options" + shortcut="control|alt|G" + visible="false"> + <menu_item_call.on_click + function="Advanced.RequestAdminStatus" /> + </menu_item_call> + <menu_item_call + label="Leave Admin Status" + layout="topleft" + name="Leave Admin Options" + shortcut="control|alt|shift|G" + visible="false"> + <menu_item_call.on_click + function="Advanced.LeaveAdminStatus" /> + </menu_item_call> <menu_item_separator layout="topleft" /> <menu_item_call diff --git a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml index c8b134cdf0..e81532ec3e 100644 --- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml +++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml @@ -14,7 +14,7 @@ width="125"/> <text - follows="left|right" + follows="top|left|right" font="SansSerifBig" height="16" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index 9a3fdcc327..fcee0ef953 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -1,415 +1,467 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - background_visible="true" - follows="all" - height="400" - label="Things" - layout="topleft" - min_height="350" - min_width="240" - name="inventory panel" - width="330"> - <panel.string - name="Title"> - Things - </panel.string> - <filter_editor - text_pad_left="12" - follows="left|top|right" - font="SanSerif" - height="20" - label="Filter" - layout="topleft" - left="15" - name="inventory search editor" - top="34" - width="300" /> - <tab_container - follows="left|top|right|bottom" - height="300" - layout="topleft" - left_delta="-4" - name="inventory filter tabs" - tab_position="top" - top_pad="4" - width="305"> - <inventory_panel - follows="left|top|right|bottom" - height="295" - label="All Items" - layout="topleft" - left="1" - name="All Items" - top="16" - width="290" /> - <inventory_panel - follows="left|top|right|bottom" - height="295" - label="Recent Items" - layout="topleft" - left_delta="0" - name="Recent Items" - top_delta="0" - width="290" /> - </tab_container> - <menu_bar - bg_visible="false" - follows="left|top|right" - height="18" - layout="topleft" - left_delta="0" - mouse_opaque="false" - name="Inventory Menu" - top_delta="-45" - width="290"> - <menu - height="101" - label="File" - layout="topleft" - left="0" - mouse_opaque="false" - name="File" - tear_off="true" - top="-117" - width="128"> - <menu_item_call - label="Open" - layout="topleft" - name="Open"> - <menu_item_call.on_click - function="Inventory.DoToSelected" - parameter="open" /> - </menu_item_call> - <menu - create_jump_keys="true" - label="Upload" - layout="topleft" - name="upload" - tear_off="true"> - <menu_item_call - label="Image (L$[COST])..." - layout="topleft" - name="Upload Image" - shortcut="control|U"> - <menu_item_call.on_click - function="File.UploadImage" - parameter="" /> - <menu_item_call.on_enable - function="File.EnableUpload" /> - </menu_item_call> - <menu_item_call - label="Sound (L$[COST])..." - layout="topleft" - name="Upload Sound"> - <menu_item_call.on_click - function="File.UploadSound" - parameter="" /> - <menu_item_call.on_enable - function="File.EnableUpload" /> - </menu_item_call> - <menu_item_call - label="Animation (L$[COST])..." - layout="topleft" - name="Upload Animation"> - <menu_item_call.on_click - function="File.UploadAnim" - parameter="" /> - <menu_item_call.on_enable - function="File.EnableUpload" /> - </menu_item_call> - <menu_item_call - label="Bulk (L$[COST] per file)..." - layout="topleft" - name="Bulk Upload"> - <menu_item_call.on_click - function="File.UploadBulk" - parameter="" /> - </menu_item_call> - <menu_item_separator - layout="topleft" /> - </menu> - <menu_item_separator - layout="topleft" /> - <menu_item_call - label="New Window" - layout="topleft" - name="New Window"> - <menu_item_call.on_click - function="Inventory.NewWindow" /> - </menu_item_call> - <menu_item_separator - layout="topleft" - name="separator2" /> - <menu_item_call - label="Show Filters" - layout="topleft" - name="Show Filters"> - <menu_item_call.on_click - function="Inventory.ShowFilters" /> - </menu_item_call> - <menu_item_call - label="Reset Filters" - layout="topleft" - name="Reset Current"> - <menu_item_call.on_click - function="Inventory.ResetFilter" /> - </menu_item_call> - <menu_item_call - label="Close All Folders" - layout="topleft" - name="Close All Folders"> - <menu_item_call.on_click - function="Inventory.CloseAllFolders" /> - </menu_item_call> - <menu_item_separator - layout="topleft" - name="separator3" /> - <menu_item_call - label="Empty Trash" - layout="topleft" - name="Empty Trash"> - <menu_item_call.on_click - function="Inventory.EmptyTrash" /> - </menu_item_call> - <menu_item_call - label="Empty Lost And Found" - layout="topleft" - name="Empty Lost And Found"> - <menu_item_call.on_click - function="Inventory.EmptyLostAndFound" /> - </menu_item_call> - </menu> - <menu - height="121" - label="Create" - layout="topleft" - left="0" - mouse_opaque="false" - name="Create" - tear_off="true" - top="-201" - width="121"> - <menu_item_call - label="New Folder" - layout="topleft" - name="New Folder"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="category" /> - </menu_item_call> - <menu_item_call - label="New Script" - layout="topleft" - name="New Script"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="lsl" /> - </menu_item_call> - <menu_item_call - label="New Note" - layout="topleft" - name="New Note"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="notecard" /> - </menu_item_call> - <menu_item_call - label="New Gesture" - layout="topleft" - name="New Gesture"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="gesture" /> - </menu_item_call> - <menu - height="175" - label="New Clothes" - layout="topleft" - left_delta="0" - mouse_opaque="false" - name="New Clothes" - top_pad="514" - width="125"> - <menu_item_call - label="New Shirt" - layout="topleft" - name="New Shirt"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="shirt" /> - </menu_item_call> - <menu_item_call - label="New Pants" - layout="topleft" - name="New Pants"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="pants" /> - </menu_item_call> - <menu_item_call - label="New Shoes" - layout="topleft" - name="New Shoes"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="shoes" /> - </menu_item_call> - <menu_item_call - label="New Socks" - layout="topleft" - name="New Socks"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="socks" /> - </menu_item_call> - <menu_item_call - label="New Jacket" - layout="topleft" - name="New Jacket"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="jacket" /> - </menu_item_call> - <menu_item_call - label="New Skirt" - layout="topleft" - name="New Skirt"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="skirt" /> - </menu_item_call> - <menu_item_call - label="New Gloves" - layout="topleft" - name="New Gloves"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="gloves" /> - </menu_item_call> - <menu_item_call - label="New Undershirt" - layout="topleft" - name="New Undershirt"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="undershirt" /> - </menu_item_call> - <menu_item_call - label="New Underpants" - layout="topleft" - name="New Underpants"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="underpants" /> - </menu_item_call> - <menu_item_call - label="New Alpha" - layout="topleft" - name="New Alpha"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="alpha" /> - </menu_item_call> - <menu_item_call - label="New Tattoo" - layout="topleft" - name="New Tattoo"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="tattoo" /> - </menu_item_call> - </menu> - <menu - height="85" - label="New Body Parts" - layout="topleft" - left_delta="0" - mouse_opaque="false" - name="New Body Parts" - top_pad="514" - width="118"> - <menu_item_call - label="New Shape" - layout="topleft" - name="New Shape"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="shape" /> - </menu_item_call> - <menu_item_call - label="New Skin" - layout="topleft" - name="New Skin"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="skin" /> - </menu_item_call> - <menu_item_call - label="New Hair" - layout="topleft" - name="New Hair"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="hair" /> - </menu_item_call> - <menu_item_call - label="New Eyes" - layout="topleft" - name="New Eyes"> - <menu_item_call.on_click - function="Inventory.DoCreate" - parameter="eyes" /> - </menu_item_call> - </menu> - </menu> - <menu - height="49" - label="Sort" - layout="topleft" - left="0" - mouse_opaque="false" - name="Sort" - tear_off="true" - top="-113" - width="118"> - <menu_item_check - control_name="Inventory.SortByName" - label="By Name" - layout="topleft" - name="By Name"> - <menu_item_check.on_click - function="Inventory.SetSortBy" - parameter="name" /> - </menu_item_check> - <menu_item_check - control_name="Inventory.SortByDate" - label="By Date" - layout="topleft" - name="By Date"> - <menu_item_check.on_click - function="Inventory.SetSortBy" - parameter="date" /> - </menu_item_check> - <menu_item_separator - layout="topleft" /> - <menu_item_check - control_name="Inventory.FoldersAlwaysByName" - label="Folders Always By Name" - layout="topleft" - name="Folders Always By Name"> - <menu_item_check.on_click - function="Inventory.SetSortBy" - parameter="foldersalwaysbyname" /> - </menu_item_check> - <menu_item_check - control_name="Inventory.SystemFoldersToTop" - label="System Folders To Top" - layout="topleft" - name="System Folders To Top"> - <menu_item_check.on_click - function="Inventory.SetSortBy" - parameter="systemfolderstotop" /> - </menu_item_check> - </menu> - </menu_bar> -</panel> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ follows="all"
+ height="400"
+ label="Things"
+ layout="topleft"
+ min_height="350"
+ min_width="240"
+ name="main inventory panel"
+ width="330">
+ <panel.string
+ name="Title">
+ Things
+ </panel.string>
+ <filter_editor
+ text_pad_left="12"
+ follows="left|top|right"
+ font="SanSerif"
+ height="20"
+ label="Filter"
+ layout="topleft"
+ left="15"
+ name="inventory search editor"
+ top="34"
+ width="300" />
+ <tab_container
+ follows="left|top|right|bottom"
+ height="300"
+ layout="topleft"
+ left_delta="-4"
+ name="inventory filter tabs"
+ tab_position="top"
+ top_pad="4"
+ width="305">
+ <inventory_panel
+ follows="left|top|right|bottom"
+ height="295"
+ label="All Items"
+ layout="topleft"
+ left="1"
+ name="All Items"
+ top="16"
+ width="290" />
+ <inventory_panel
+ follows="left|top|right|bottom"
+ height="295"
+ label="Recent Items"
+ layout="topleft"
+ left_delta="0"
+ name="Recent Items"
+ top_delta="0"
+ width="290" />
+ </tab_container>
+
+ <panel
+ background_visible="true"
+ bevel_style="none"
+ bottom="0"
+ follows="left|right|bottom"
+ height="30"
+ layout="bottomleft"
+ left="0"
+ visible="true"
+ name="bottom_panel"
+ width="330">
+ <button
+ follows="bottom|left"
+ tool_tip="Show additional options"
+ height="18"
+ image_disabled="OptionsMenu_Disabled"
+ image_selected="OptionsMenu_Press"
+ image_unselected="OptionsMenu_Off"
+ layout="topleft"
+ left="10"
+ name="options_gear_btn"
+ picture_style="true"
+ top="6"
+ width="18" />
+ <button
+ follows="bottom|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="5"
+ name="add_btn"
+ picture_style="true"
+ tool_tip="Add new item"
+ width="18" />
+ <dnd_button
+ follows="bottom|right"
+ height="18"
+ image_selected="TrashItem_Press"
+ image_unselected="TrashItem_Off"
+ layout="topleft"
+ right="-5"
+ name="trash_btn"
+ picture_style="true"
+ tool_tip="Remove selected item"
+ top="6"
+ width="18" />
+ </panel>
+
+ <menu_bar
+ bg_visible="false"
+ follows="left|top|right"
+ height="18"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="Inventory Menu"
+ top="15"
+ visible="true"
+ width="290">
+ <menu
+ height="101"
+ label="File"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="File"
+ tear_off="true"
+ top="-117"
+ width="128">
+ <menu_item_call
+ label="Open"
+ layout="topleft"
+ name="Open">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="open" />
+ </menu_item_call>
+ <menu
+ create_jump_keys="true"
+ label="Upload"
+ layout="topleft"
+ name="upload"
+ tear_off="true">
+ <menu_item_call
+ label="Image (L$[COST])..."
+ layout="topleft"
+ name="Upload Image"
+ shortcut="control|U">
+ <menu_item_call.on_click
+ function="File.UploadImage"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
+ label="Sound (L$[COST])..."
+ layout="topleft"
+ name="Upload Sound">
+ <menu_item_call.on_click
+ function="File.UploadSound"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
+ label="Animation (L$[COST])..."
+ layout="topleft"
+ name="Upload Animation">
+ <menu_item_call.on_click
+ function="File.UploadAnim"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
+ label="Bulk (L$[COST] per file)..."
+ layout="topleft"
+ name="Bulk Upload">
+ <menu_item_call.on_click
+ function="File.UploadBulk"
+ parameter="" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="New Window"
+ layout="topleft"
+ name="New Window">
+ <menu_item_call.on_click
+ function="Inventory.NewWindow" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="separator2" />
+ <menu_item_call
+ label="Show Filters"
+ layout="topleft"
+ name="Show Filters">
+ <menu_item_call.on_click
+ function="Inventory.ShowFilters" />
+ </menu_item_call>
+ <menu_item_call
+ label="Reset Filters"
+ layout="topleft"
+ name="Reset Current">
+ <menu_item_call.on_click
+ function="Inventory.ResetFilter" />
+ </menu_item_call>
+ <menu_item_call
+ label="Close All Folders"
+ layout="topleft"
+ name="Close All Folders">
+ <menu_item_call.on_click
+ function="Inventory.CloseAllFolders" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"
+ name="separator3" />
+ <menu_item_call
+ label="Empty Trash"
+ layout="topleft"
+ name="Empty Trash">
+ <menu_item_call.on_click
+ function="Inventory.EmptyTrash" />
+ </menu_item_call>
+ <menu_item_call
+ label="Empty Lost And Found"
+ layout="topleft"
+ name="Empty Lost And Found">
+ <menu_item_call.on_click
+ function="Inventory.EmptyLostAndFound" />
+ </menu_item_call>
+ </menu>
+ <menu
+ height="121"
+ label="Create"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="Create"
+ tear_off="true"
+ top="-201"
+ width="121">
+ <menu_item_call
+ label="New Folder"
+ layout="topleft"
+ name="New Folder">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="category" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Script"
+ layout="topleft"
+ name="New Script">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="lsl" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Note"
+ layout="topleft"
+ name="New Note">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="notecard" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gesture"
+ layout="topleft"
+ name="New Gesture">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gesture" />
+ </menu_item_call>
+ <menu
+ height="175"
+ label="New Clothes"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="New Clothes"
+ top_pad="514"
+ width="125">
+ <menu_item_call
+ label="New Shirt"
+ layout="topleft"
+ name="New Shirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Pants"
+ layout="topleft"
+ name="New Pants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="pants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Shoes"
+ layout="topleft"
+ name="New Shoes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shoes" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Socks"
+ layout="topleft"
+ name="New Socks">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="socks" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Jacket"
+ layout="topleft"
+ name="New Jacket">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="jacket" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skirt"
+ layout="topleft"
+ name="New Skirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Gloves"
+ layout="topleft"
+ name="New Gloves">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="gloves" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Undershirt"
+ layout="topleft"
+ name="New Undershirt">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="undershirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Underpants"
+ layout="topleft"
+ name="New Underpants">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="underpants" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Alpha"
+ layout="topleft"
+ name="New Alpha">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="alpha" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Tattoo"
+ layout="topleft"
+ name="New Tattoo">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="tattoo" />
+ </menu_item_call>
+ </menu>
+ <menu
+ height="85"
+ label="New Body Parts"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="New Body Parts"
+ top_pad="514"
+ width="118">
+ <menu_item_call
+ label="New Shape"
+ layout="topleft"
+ name="New Shape">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="shape" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Skin"
+ layout="topleft"
+ name="New Skin">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="skin" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Hair"
+ layout="topleft"
+ name="New Hair">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="hair" />
+ </menu_item_call>
+ <menu_item_call
+ label="New Eyes"
+ layout="topleft"
+ name="New Eyes">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="eyes" />
+ </menu_item_call>
+ </menu>
+ </menu>
+ <menu
+ height="49"
+ label="Sort"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="Sort"
+ tear_off="true"
+ top="-113"
+ width="118">
+ <menu_item_check
+ control_name="Inventory.SortByName"
+ label="By Name"
+ layout="topleft"
+ name="By Name">
+ <menu_item_check.on_click
+ function="Inventory.SetSortBy"
+ parameter="name" />
+ </menu_item_check>
+ <menu_item_check
+ control_name="Inventory.SortByDate"
+ label="By Date"
+ layout="topleft"
+ name="By Date">
+ <menu_item_check.on_click
+ function="Inventory.SetSortBy"
+ parameter="date" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ control_name="Inventory.FoldersAlwaysByName"
+ label="Folders Always By Name"
+ layout="topleft"
+ name="Folders Always By Name">
+ <menu_item_check.on_click
+ function="Inventory.SetSortBy"
+ parameter="foldersalwaysbyname" />
+ </menu_item_check>
+ <menu_item_check
+ control_name="Inventory.SystemFoldersToTop"
+ label="System Folders To Top"
+ layout="topleft"
+ name="System Folders To Top">
+ <menu_item_check.on_click
+ function="Inventory.SetSortBy"
+ parameter="systemfolderstotop" />
+ </menu_item_check>
+ </menu>
+ </menu_bar>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml index 44fd44cde5..a90337d31a 100644 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -7,7 +7,7 @@ height="65" layout="topleft" name="navigation_bar" - chrome="true" + chrome="true" width="600"> <icon follows="all" @@ -145,7 +145,8 @@ top_delta="0" width="200" > <combo_editor - label="Search" /> + label="Search [SECOND_LIFE]" + name="search_combo_editor"/> </search_combo_box> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_notes.xml b/indra/newview/skins/default/xui/en/panel_notes.xml index 5333dfa2f5..b9c9100ebc 100644 --- a/indra/newview/skins/default/xui/en/panel_notes.xml +++ b/indra/newview/skins/default/xui/en/panel_notes.xml @@ -17,13 +17,16 @@ left="0" top="0" height="517" + width="313" border_size="0"> <panel name="notes_stack" follows="all" layout="topleft" top="0" - left="0"> + left="0" + height="475" + width="313"> <scroll_container color="DkGray2" follows="all" @@ -31,8 +34,11 @@ left="0" name="profile_scroll" opaque="true" + height="475" + width="313" top="0"> <panel + height="450" layout="topleft" name="profile_scroll_panel" top="0" @@ -104,7 +110,8 @@ layout="topleft" left="0" name="notes_buttons_panel" - auto_resize="false"> + auto_resize="false" + width="313"> <button follows="bottom|left" height="19" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml index 613decad8d..06f0710406 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml @@ -272,7 +272,7 @@ Avatars: width="315" /> <radio_item height="16" - label="In window" + label="In a window" layout="topleft" left_delta="175" name="1" @@ -284,13 +284,13 @@ Avatars: enabled_control="EnableVoiceChat" control_name="PushToTalkToggle" height="20" - label="Use Push-to-talk in toggle mode" + label="Toggle mode for microphone when I press the Speak trigger key:" layout="topleft" left="30" name="push_to_talk_toggle_check" width="237" top_pad="-25" - tool_tip="When in toggle mode, press and release the push-to-talk trigger to switch your microphone on and off. When not in toggle mode, the microphone is active only when the trigger is held down."/> + tool_tip="When in toggle mode, press and release the trigger key ONCE to switch your microphone on or off. When not in toggle mode, the microphone broadcasts your voice only while the trigger is being held down."/> <line_editor follows="top|left" control_name="PushToTalkButton" @@ -300,7 +300,7 @@ Avatars: left_delta="50" max_length="254" name="modifier_combo" - label="Push-to-talk trigger" + label="Push-to-Speak trigger" top_pad="0" width="280" /> <button diff --git a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml index ce7939c00f..acf4601bfe 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml @@ -94,6 +94,7 @@ layout="topleft" left="30" mouse_opaque="false" + name="Logs:" top_pad="10" width="350"> Logs: @@ -184,6 +185,7 @@ layout="topleft" left_delta="0" mouse_opaque="false" + name="log_path_desc" top_pad="1" width="128" text_color="LtGray_50"> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml index c3e0cb352b..d454b9e5c8 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml @@ -336,7 +336,7 @@ follows="left|bottom" height="19" is_toggle="true" - label="Input / Output Devices" + label="Input/Output Devices" layout="topleft" left="165" top_pad="12" @@ -504,17 +504,4 @@ top_pad="0" width="200" /> </panel> - <!-- Until new panel is hooked up to code, we need to be able to get to - the old window to change input devices. James --> - <button - follows="left|bottom" - label="Old" - name="legacy_device_window_btn" - height="16" - left="20" - top="-270" - width="40" - commit_callback.function="Floater.Show" - commit_callback.parameter="pref_voicedevicesettings" - /> </panel> diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml index 3582de1c71..a9874f4553 100644 --- a/indra/newview/skins/default/xui/en/panel_side_tray.xml +++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<!-- Side tray cannot show background because it is always +<!-- Side tray cannot show background because it is always partially on screen to hold tab buttons. --> <side_tray name="sidebar" @@ -10,7 +10,7 @@ > <!-- Individual tabs must show background to have seemless appearance up to tray panel header word like "Home". - Embedded panels are inset by a pixel and so their + Embedded panels are inset by a pixel and so their backgrounds will not block the world fully. --> <sidetray_tab name="sidebar_home" @@ -70,7 +70,7 @@ </panel_container> </sidetray_tab> - + <sidetray_tab name="sidebar_places" help_topic="sidebar_places" @@ -133,8 +133,8 @@ help_topic="sidebar_inventory" tab_title="Inventory" description="Browse your inventory." - image="TabIcon_Inventory_Off" - image_selected="TabIcon_Inventory_Selected" + image="TabIcon_Things_Off" + image_selected="TabIcon_Things_Selected" mouse_opaque="false" background_visible="true" > diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml index d0c3cdfafc..cbcc3f10ad 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml @@ -1,122 +1,127 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<panel - background_visible="true" - follows="all" - height="400" - label="Things" - layout="topleft" - min_height="350" - min_width="240" - name="objects panel" - width="333"> - <tab_container - follows="all" - height="390" - layout="topleft" - left="9" - name="Inventory Tabs" - tab_position="top" - top="0" - width="313" - tab_height="0" - visible="true"> - <panel - class="panel_main_inventory" - filename="panel_main_inventory.xml" - follows="all" - layout="topleft" - left="0" - name="panel_main_inventory" - top="15" - label="" - height="330" - width="467"> - <panel - height="25" - layout="bottomright" - left="0" - help_topic="objects_button_tab" - name="button_panel" - bottom="0" - width="313"> - <button - enabled="true" - follows="bottom|left" - font="SansSerifSmallBold" - height="25" - label="Info" - layout="topleft" - left="0" - name="info_btn" - top="0" - width="60" /> - <button - enabled="true" - follows="bottom|left" - font="SansSerifSmallBold" - height="25" - label="Share" - layout="topleft" - left_pad="5" - name="share_btn" - top="0" - width="60" /> - <button - enabled="false" - follows="bottom|left" - font="SansSerifSmallBold" - height="25" - label="Wear" - layout="topleft" - left="130" - name="wear_btn" - top="0" - width="60" /> - <button - enabled="false" - follows="bottom|left" - font="SansSerifSmallBold" - height="25" - label="Play" - layout="topleft" - name="play_btn" - left="130" - top="0" - width="50" /> - <button - enabled="false" - follows="bottom|left" - font="SansSerifSmallBold" - height="25" - label="Teleport" - layout="topleft" - left="130" - name="teleport_btn" - top="0" - width="77" /> - <button - follows="bottom|right" - font="SansSerifSmallBold" - height="25" - label="v" - layout="topleft" - name="overflow_btn" - right="-10" - top="0" - width="30" /> - </panel> - </panel> - </tab_container> - - <panel - class="sidepanel_object_info" - filename="sidepanel_object_info.xml" - follows="all" - height="360" - layout="topleft" - left="0" - help_topic="objects_info_tab" - name="sidepanel_object_info" - top="30" - visible="false" /> -</panel> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ follows="all"
+ height="570"
+ label="Things"
+ layout="topleft"
+ min_height="350"
+ min_width="240"
+ name="objects panel"
+ width="333">
+ <panel
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="sidepanel__inventory_panel"
+ top="0"
+ label=""
+ height="570"
+ visible="true"
+ width="330">
+ <panel
+ class="panel_main_inventory"
+ filename="panel_main_inventory.xml"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="panel_main_inventory"
+ top="0"
+ label=""
+ height="500"
+ width="330" />
+ <panel
+ height="25"
+ layout="bottomright"
+ help_topic="item_button_tab"
+ name="button_panel"
+ left="5"
+ bottom="5"
+ width="313">
+ <button
+ enabled="true"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Info"
+ layout="topleft"
+ left="0"
+ name="info_btn"
+ top="0"
+ width="60" />
+ <button
+ enabled="true"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Share"
+ layout="topleft"
+ left_pad="5"
+ name="share_btn"
+ top="0"
+ width="60" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Wear"
+ layout="topleft"
+ left="130"
+ name="wear_btn"
+ top="0"
+ width="60" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Play"
+ layout="topleft"
+ name="play_btn"
+ left="130"
+ top="0"
+ width="50" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Teleport"
+ layout="topleft"
+ left="130"
+ name="teleport_btn"
+ top="0"
+ width="77" />
+ </panel>
+ </panel>
+
+ <panel
+ follows="all"
+ layout="topleft"
+ left="0"
+ class="sidepanel_item_info"
+ filename="sidepanel_item_info.xml"
+ name="sidepanel__item_panel"
+ top="0"
+ label=""
+ height="570"
+ visible="false"
+ width="330">
+ </panel>
+
+ <panel
+ follows="all"
+ layout="topleft"
+ left="0"
+ class="sidepanel_task_info"
+ filename="sidepanel_task_info.xml"
+ name="sidepanel__task_panel"
+ top="0"
+ label=""
+ height="570"
+ visible="false"
+ width="330">
+ </panel>
+
+</panel>
diff --git a/indra/newview/skins/default/xui/en/sidepanel_item_info.xml b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml new file mode 100644 index 0000000000..39cd75074e --- /dev/null +++ b/indra/newview/skins/default/xui/en/sidepanel_item_info.xml @@ -0,0 +1,511 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ auto_tile="true"
+ height="570"
+ layout="topleft"
+ name="item properties"
+ help_topic="item_properties"
+ save_rect="true"
+ title="Inventory Item Properties"
+ width="333">
+ <panel.string
+ name="unknown">
+ (unknown)
+ </panel.string>
+ <panel.string
+ name="public">
+ (public)
+ </panel.string>
+ <panel.string
+ name="you_can">
+ You can:
+ </panel.string>
+ <panel.string
+ name="owner_can">
+ Owner can:
+ </panel.string>
+ <panel.string
+ name="acquiredDate">
+ [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]
+ </panel.string>
+ <icon
+ follows="top|right"
+ height="18"
+ image_name="Lock"
+ layout="topleft"
+ right="-50"
+ mouse_opaque="true"
+ name="IconLocked"
+ top="4"
+ width="18" />
+ <button
+ follows="top|right"
+ height="25"
+ image_overlay="BackArrow_Off"
+ layout="topleft"
+ name="back_btn"
+ picture_style="true"
+ right="-5"
+ tab_stop="false"
+ top="0"
+ width="25" />
+ <panel
+ follows="all"
+ height="500"
+ label=""
+ layout="topleft"
+ left="5"
+ help_topic=""
+ top="30"
+ border="1"
+ width="313">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="5"
+ name="LabelItemNameTitle"
+ top="5"
+ width="78">
+ Name:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ max_length="63"
+ name="LabelItemName"
+ top_delta="0"
+ width="225" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="5"
+ name="LabelItemDescTitle"
+ top_delta="20"
+ width="78">
+ Description:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ max_length="127"
+ name="LabelItemDesc"
+ top_delta="0"
+ width="225" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="LabelCreatorTitle"
+ top="65"
+ width="78">
+ Creator:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ name="LabelCreatorName"
+ top_delta="0"
+ width="200">
+ Nicole Linden
+ </text>
+ <button
+ follows="top|right"
+ font="SansSerifSmall"
+ height="16"
+ label="Profile..."
+ layout="topleft"
+ left_delta="144"
+ name="BtnCreator"
+ top_delta="0"
+ width="78" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="LabelOwnerTitle"
+ top="85"
+ width="78">
+ Owner:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ name="LabelOwnerName"
+ top_delta="0"
+ width="200">
+ Thrax Linden
+ </text>
+ <button
+ follows="top|right"
+ font="SansSerifSmall"
+ height="16"
+ label="Profile..."
+ layout="topleft"
+ left_delta="144"
+ name="BtnOwner"
+ top_delta="0"
+ width="78" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="LabelAcquiredTitle"
+ top="105"
+ width="78">
+ Acquired:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ name="LabelAcquiredDate"
+ top_delta="0"
+ width="252">
+ Wed May 24 12:50:46 2006
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="OwnerLabel"
+ top="125"
+ width="78">
+ You:
+ </text>
+ <check_box
+ height="16"
+ label="Edit"
+ layout="topleft"
+ left_pad="5"
+ name="CheckOwnerModify"
+ top_delta="0"
+ width="78" />
+ <check_box
+ height="16"
+ label="Copy"
+ layout="topleft"
+ left_delta="0"
+ name="CheckOwnerCopy"
+ top_pad="5"
+ width="88" />
+ <check_box
+ height="16"
+ label="Resell"
+ layout="topleft"
+ left_delta="0"
+ name="CheckOwnerTransfer"
+ top_pad="5"
+ width="106" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="AnyoneLabel"
+ top_pad="5"
+ width="78">
+ Anyone:
+ </text>
+ <check_box
+ height="16"
+ label="Copy"
+ layout="topleft"
+ left_pad="5"
+ name="CheckEveryoneCopy"
+ top_delta="0"
+ width="130" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="GroupLabel"
+ top_pad="5"
+ width="78">
+ Group:
+ </text>
+ <check_box
+ height="16"
+ label="Share"
+ layout="topleft"
+ left_pad="5"
+ name="CheckShareWithGroup"
+ top_delta="5"
+ width="106" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="NextOwnerLabel"
+ top_pad="5"
+ width="78">
+ Next owner:
+ </text>
+ <check_box
+ height="16"
+ label="Edit"
+ layout="topleft"
+ left_pad="5"
+ name="CheckNextOwnerModify"
+ top_delta="0"
+ width="78" />
+ <check_box
+ height="16"
+ label="Copy"
+ layout="topleft"
+ left_delta="0"
+ name="CheckNextOwnerCopy"
+ top_pad="5"
+ width="88" />
+ <check_box
+ height="16"
+ label="Resell"
+ layout="topleft"
+ left_delta="0"
+ name="CheckNextOwnerTransfer"
+ top_pad="5"
+ width="106" />
+ <check_box
+ height="16"
+ label="For Sale"
+ layout="topleft"
+ left="10"
+ name="CheckPurchase"
+ top_pad="5"
+ width="78" />
+ <combo_box
+ height="19"
+ left_pad="5"
+ layout="topleft"
+ follows="left|top"
+ name="combobox sale copy"
+ width="90">
+ <combo_box.item
+ label="Copy"
+ name="Copy"
+ value="Copy" />
+ <combo_box.item
+ label="Original"
+ name="Original"
+ value="Original" />
+ </combo_box>
+ <spinner
+ follows="left|top"
+ decimal_digits="0"
+ increment="1"
+ control_name="Edit Cost"
+ name="Edit Cost"
+ label="Price: L$"
+ label_width="60"
+ left="10"
+ width="180"
+ min_val="1"
+ height="19"
+ max_val="999999999"
+ top_pad="5"/>
+ <!--line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_pad="5"
+ max_length="25"
+ name="EditPrice"
+ top_delta="0"
+ width="242" /-->
+ <!--text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="BaseMaskDebug"
+ top="155"
+ width="330">
+ B:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="60"
+ name="OwnerMaskDebug"
+ top_delta="0"
+ width="270">
+ O:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="60"
+ name="GroupMaskDebug"
+ top_delta="0"
+ width="210">
+ G:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="60"
+ name="EveryoneMaskDebug"
+ top_delta="0"
+ width="150">
+ E:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="60"
+ name="NextMaskDebug"
+ top_delta="0"
+ width="90">
+ N:
+ </text-->
+ <!--text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="SaleLabel"
+ top_pad="5"
+ width="330">
+ Mark Item:
+ </text-->
+ <!--radio_group
+ draw_border="false"
+ follows="left|top|right"
+ height="16"
+ layout="topleft"
+ left_delta="78"
+ name="RadioSaleType"
+ top_delta="0"
+ width="252">
+ <radio_item
+ height="16"
+ label="Original"
+ layout="topleft"
+ left="0"
+ name="radio"
+ top="0"
+ width="70" />
+ <radio_item
+ height="16"
+ label="Copy"
+ layout="topleft"
+ left_delta="60"
+ name="radio2"
+ top_delta="0"
+ width="70" />
+ </radio_group-->
+ <!--text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="TextPrice"
+ top_pad="5"
+ width="78">
+ Price: L$
+ </text-->
+ </panel>
+ <panel
+ height="25"
+ layout="bottomright"
+ help_topic="button_tab"
+ name="button_panel"
+ left="5"
+ bottom="5"
+ width="313">
+ <button
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Edit"
+ layout="topleft"
+ left="0"
+ name="edit_btn"
+ top="0"
+ width="50" />
+ <button
+ follows="bottom|right"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Cancel"
+ layout="topleft"
+ name="cancel_btn"
+ right="-1"
+ top="0"
+ width="70" />
+ <button
+ follows="bottom|right"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Save"
+ layout="topleft"
+ name="save_btn"
+ left_pad="-135"
+ top="0"
+ width="60" />
+ </panel>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/sidepanel_task_info.xml b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml new file mode 100644 index 0000000000..8eb2254112 --- /dev/null +++ b/indra/newview/skins/default/xui/en/sidepanel_task_info.xml @@ -0,0 +1,547 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<panel + auto_tile="true" + height="570" + layout="topleft" + name="object properties" + help_topic="object_properties" + save_rect="true" + title="Object Properties" + width="333"> + <panel.string + name="text deed continued"> + Deed + </panel.string> + <panel.string + name="text deed"> + Deed + </panel.string> + <panel.string + name="text modify info 1"> + You can modify this object + </panel.string> + <panel.string + name="text modify info 2"> + You can modify these objects + </panel.string> + <panel.string + name="text modify info 3"> + You can't modify this object + </panel.string> + <panel.string + name="text modify info 4"> + You can't modify these objects + </panel.string> + <panel.string + name="text modify warning"> + This object has linked parts + </panel.string> + <panel.string + name="Cost Default"> + Price: L$ + </panel.string> + <panel.string + name="Cost Total"> + Total Price: L$ + </panel.string> + <panel.string + name="Cost Per Unit"> + Price Per: L$ + </panel.string> + <panel.string + name="Cost Mixed"> + Mixed Price + </panel.string> + <panel.string + name="Sale Mixed"> + Mixed Sale + </panel.string> + <button + follows="top|right" + height="25" + image_overlay="BackArrow_Off" + layout="topleft" + name="back_btn" + picture_style="true" + right="-5" + tab_stop="false" + top="0" + width="25" /> + <panel + follows="all" + height="500" + label="" + layout="topleft" + left="5" + help_topic="" + top="30" + border="1" + width="313"> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left="10" + name="Name:" + top_pad="5" + width="90"> + Name: + </text> + <line_editor + follows="left|top|right" + height="19" + layout="topleft" + left_pad="0" + max_length="63" + name="Object Name" + select_on_focus="true" + top_delta="0" + width="170" /> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left="10" + name="Description:" + top_pad="3" + width="90"> + Description: + </text> + <line_editor + follows="left|top|right" + height="19" + layout="topleft" + left_pad="0" + max_length="127" + name="Object Description" + select_on_focus="true" + top_delta="0" + width="170" /> + <text + type="string" + left="10" + length="1" + follows="left|top" + height="19" + layout="topleft" + name="Creator:" + width="90"> + Creator: + </text> + <text + type="string" + length="1" + follows="left|top" + left_pad="0" + height="19" + layout="topleft" + name="Creator Name" + width="175"> + Esbee Linden + </text> + <text + type="string" + length="1" + left="10" + follows="left|top" + height="19" + layout="topleft" + name="Owner:" + width="90"> + Owner: + </text> + <text + type="string" + length="1" + follows="left|top" + height="19" + layout="topleft" + name="Owner Name" + left_pad="0" + width="175"> + Erica Linden + </text> + <text + type="string" + length="1" + follows="left|top" + layout="topleft" + left="10" + height="18" + name="Group:" + top_pad="4" + width="75"> + Group: + </text> + <button + follows="top|left" + height="10" + image_disabled="Activate_Checkmark" + image_selected="Activate_Checkmark" + image_unselected="Activate_Checkmark" + image_color="White_50" + layout="topleft" + left_pad="0" + top_delta="0" + name="button set group" + picture_style="true" + tab_stop="false" + tool_tip="Choose a group to share this object's permissions" + width="10" /> + <name_box + follows="left|top" + height="18" + initial_value="Loading..." + layout="topleft" + left_pad="5" + top_delta="-1" + name="Group Name Proxy" + width="150" /> + <button + follows="top|left" + font="SansSerifSmall" + height="20" + label="Deed" + label_selected="Deed" + layout="topleft" + name="button deed" + top_pad="0" + left="100" + tool_tip="Deeding gives this item away with next owner permissions. Group shared objects can be deeded by a group officer." + width="80" /> + <check_box + height="19" + follows="left|top" + label="Share" + layout="topleft" + name="checkbox share with group" + tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions." + left_pad="3" + width="100" /> + <text + type="string" + length="1" + follows="left|top" + height="16" + layout="topleft" + top_pad="15" + left="10" + name="label click action" + width="90"> + Click to: + </text> + <combo_box + follows="left|top" + height="20" + layout="topleft" + name="clickaction" + width="168" + left_pad="0"> + <combo_box.item + label="Touch (default)" + name="Touch/grab(default)" + value="Touch/grab (default)" /> + <combo_box.item + label="Sit on object" + name="Sitonobject" + value="Sit on object" /> + <combo_box.item + label="Buy object" + name="Buyobject" + value="Buy object" /> + <combo_box.item + label="Pay object" + name="Payobject" + value="Pay object" /> + <combo_box.item + label="Open" + name="Open" + value="Open" /> + </combo_box> + <check_box + height="16" + top_pad="15" + label="For Sale:" + layout="topleft" + name="checkbox for sale" + left="10" + width="90" /> +<!-- NEW SALE TYPE COMBO BOX --> + <combo_box + left_pad="0" + layout="topleft" + follows="left|top" + allow_text_entry="false" + height="20" + intial_value="2" + max_chars="20" + mouse_opaque="true" + name="sale type" + width="158"> + <combo_box.item + name="Copy" + label="Copy" + value="2" /> + <combo_box.item + name="Contents" + label="Contents" + value="3" /> + <combo_box.item + name="Original" + label="Original" + value="1" /> + </combo_box> +<!-- NEW PRICE SPINNER --> + <spinner + follows="left|top" + decimal_digits="0" + increment="1" + top_pad="8" + left="100" + control_name="Edit Cost" + name="Edit Cost" + label="Price: L$" + label_width="65" + width="150" + min_val="1" + height="20" + max_val="999999999" /> + <check_box + height="15" + width="110" + top_pad="3" + label="Show in search" + layout="topleft" + left="100" + name="search_check" + tool_tip="Let people see this object in search results" /> + <panel + border="false" + follows="left|top" + layout="topleft" + mouse_opaque="false" + background_visible="true" + bg_alpha_color="DkGray" + name="perms_build" + left="0" + top="241" + height="120" + width="278"> + <text + type="string" + length="1" + left="10" + top_pad="9" + text_color="EmphasisColor" + height="16" + follows="left|top|right" + layout="topleft" + name="perm_modify" + width="250"> + You can modify this object + </text> + <text + type="string" + follows="left|top" + name="Anyone can:" + width="250" + left="10"> + Anyone: + </text> + <check_box + height="19" + label="Move" + layout="topleft" + name="checkbox allow everyone move" + left="15" + width="85" /> + <check_box + height="19" + label="Copy" + layout="topleft" + left_pad="0" + name="checkbox allow everyone copy" + width="90" /> + <text + type="string" + follows="left|top" + height="19" + name="Next owner can:" + width="250" + left="10"> + Next owner: + </text> + <check_box + follows="left|top|right" + label="Modify" + layout="topleft" + left="15" + name="checkbox next owner can modify" + width="85" /> + <check_box + follows="left|top|right" + height="19" + label="Copy" + layout="topleft" + left_pad="0" + name="checkbox next owner can copy" + width="90" /> + <check_box + follows="left|top|right" + height="19" + label="Transfer" + layout="topleft" + name="checkbox next owner can transfer" + left_pad="0" + top_delta="0" + tool_tip="Next owner can give away or resell this object" + width="90" /> + <text + type="string" + text_color="EmphasisColor" + length="1" + top_pad="5" + follows="left|top" + layout="topleft" + left="10" + name="B:" + height="10" + width="45"> + B: + </text> + <text + type="string" + text_color="White" + length="1" + follows="left|top" + layout="topleft" + left_pad="0" + name="O:" + height="10" + width="44"> + O: + </text> + <text + type="string" + text_color="EmphasisColor" + length="1" + follows="left|top" + layout="topleft" + left_pad="0" + name="G:" + height="10" + width="43"> + G: + </text> + <text + type="string" + text_color="White" + length="1" + follows="left|top" + left_pad="0" + layout="topleft" + name="E:" + height="10" + width="43"> + E: + </text> + <text + type="string" + text_color="EmphasisColor" + length="1" + follows="left|top" + layout="topleft" + left_pad="0" + name="N:" + height="10" + width="48"> + N: + </text> + <text + type="string" + text_color="White" + length="1" + follows="left|top" + layout="topleft" + left_pad="0" + name="F:" + height="10" + width="50"> + F: + </text> + </panel> + </panel> + <panel + height="25" + layout="bottomright" + help_topic="button_tab" + name="button_panel" + left="5" + bottom="5" + width="313"> + <button + follows="bottom|left" + font="SansSerifSmallBold" + height="25" + label="Edit" + layout="topleft" + left="0" + name="edit_btn" + top="0" + width="50" /> + <button + follows="bottom|left" + font="SansSerifSmallBold" + height="25" + label="Open" + layout="topleft" + left_pad="5" + name="open_btn" + top="0" + width="60" /> + <button + follows="bottom|left" + font="SansSerifSmallBold" + height="25" + label="Pay" + layout="topleft" + left_pad="5" + name="pay_btn" + top="0" + width="50" /> + <button + follows="bottom|left" + font="SansSerifSmallBold" + height="25" + label="Buy" + layout="topleft" + left_pad="5" + name="buy_btn" + top="0" + width="60" /> + <button + follows="bottom|right" + font="SansSerifSmallBold" + height="25" + label="Cancel" + layout="topleft" + name="cancel_btn" + right="-1" + top="0" + width="70" /> + <button + follows="bottom|right" + font="SansSerifSmallBold" + height="25" + label="Save" + layout="topleft" + name="save_btn" + left_pad="-135" + top="0" + width="60" /> + </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 ec2673644f..c850dce141 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2845,6 +2845,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. <string name="Unnamed">(Unnamed)</string> <string name="IM_moderated_chat_label">(Moderated: Voices off by default)</string> <string name="IM_unavailable_text_label">Text chat is not available for this call.</string> + <string name="IM_muted_text_label">Your text chat has been disabled by a Group Moderator.</string> + <string name="IM_default_text_label">Click here to instant message.</string> + <string name="IM_to_label">To</string> + <string name="IM_moderator_label">(Moderator)</string> <string name="ringing-im"> diff --git a/indra/newview/skins/default/xui/en/widgets/talk_button.xml b/indra/newview/skins/default/xui/en/widgets/talk_button.xml index d9f39b6937..1d8257fbc8 100644 --- a/indra/newview/skins/default/xui/en/widgets/talk_button.xml +++ b/indra/newview/skins/default/xui/en/widgets/talk_button.xml @@ -11,7 +11,6 @@ label_selected="Speak" font="SansSerifSmall" tab_stop="false" - is_toggle="true" /> <show_button name="right" |