diff options
Diffstat (limited to 'indra/newview/llpanelgroupnotices.cpp')
-rw-r--r-- | indra/newview/llpanelgroupnotices.cpp | 1360 |
1 files changed, 680 insertions, 680 deletions
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index e5c9acad8e..483c6876ed 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -1,680 +1,680 @@ -/**
- * @file llpanelgroupnotices.cpp
- * @brief A panel to display group notices.
- *
- * $LicenseInfo:firstyear=2006&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llpanelgroupnotices.h"
-
-#include "llview.h"
-
-#include "llavatarnamecache.h"
-#include "llinventory.h"
-#include "llviewerinventory.h"
-#include "llinventorydefines.h"
-#include "llinventoryfunctions.h"
-#include "llinventoryicon.h"
-#include "llinventorymodel.h"
-#include "llagent.h"
-#include "llagentui.h"
-
-#include "lllineeditor.h"
-#include "lltexteditor.h"
-#include "llbutton.h"
-#include "lliconctrl.h"
-#include "llcheckboxctrl.h"
-#include "llscrolllistctrl.h"
-#include "llscrolllistitem.h"
-#include "lltextbox.h"
-#include "lltrans.h"
-
-#include "roles_constants.h"
-#include "llviewerwindow.h"
-#include "llviewermessage.h"
-#include "llnotificationsutil.h"
-#include "llgiveinventory.h"
-
-static LLPanelInjector<LLPanelGroupNotices> t_panel_group_notices("panel_group_notices");
-
-
-/////////////////////////
-// LLPanelGroupNotices //
-/////////////////////////
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLDropTarget
-//
-// This handy class is a simple way to drop something on another
-// view. It handles drop events, always setting itself to the size of
-// its parent.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLGroupDropTarget : public LLView
-{
-public:
- struct Params : public LLInitParam::Block<Params, LLView::Params>
- {
- // *NOTE: These parameters logically Mandatory, but are not
- // specified in XML files, hence Optional
- Optional<LLPanelGroupNotices*> panel;
- Optional<LLUUID> group_id;
- Params()
- : panel("panel"),
- group_id("group_id")
- {
- changeDefault(mouse_opaque, false);
- changeDefault(follows.flags, FOLLOWS_ALL);
- }
- };
- LLGroupDropTarget(const Params&);
- ~LLGroupDropTarget() {};
-
- //
- // LLView functionality
- virtual bool handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg);
- void setPanel (LLPanelGroupNotices* panel) {mGroupNoticesPanel = panel;};
- void setGroup (LLUUID group) {mGroupID = group;};
-
-protected:
- LLPanelGroupNotices* mGroupNoticesPanel;
- LLUUID mGroupID;
-};
-
-static LLDefaultChildRegistry::Register<LLGroupDropTarget> r("group_drop_target");
-
-LLGroupDropTarget::LLGroupDropTarget(const LLGroupDropTarget::Params& p)
-: LLView(p),
- mGroupNoticesPanel(p.panel),
- mGroupID(p.group_id)
-{}
-
-bool LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg)
-{
- bool handled = false;
-
- if (!gAgent.hasPowerInGroup(mGroupID,GP_NOTICES_SEND))
- {
- *accept = ACCEPT_NO;
- return true;
- }
-
- if(getParent())
- {
- // check if inside
- //LLRect parent_rect = mParentView->getRect();
- //getRect().set(0, parent_rect.getHeight(), parent_rect.getWidth(), 0);
- handled = true;
-
- // check the type
- switch(cargo_type)
- {
- case DAD_TEXTURE:
- case DAD_SOUND:
- 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_CALLINGCARD:
- case DAD_MESH:
- case DAD_SETTINGS:
- case DAD_MATERIAL:
- {
- LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
- if(gInventory.getItem(inv_item->getUUID())
- && LLGiveInventory::isInventoryGroupGiveAcceptable(inv_item))
- {
- // *TODO: get multiple object transfers working
- *accept = ACCEPT_YES_COPY_SINGLE;
- if(drop)
- {
- mGroupNoticesPanel->setItem(inv_item);
- }
- }
- 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.
- *accept = ACCEPT_NO;
- }
- break;
- }
- case DAD_CATEGORY:
- default:
- *accept = ACCEPT_NO;
- break;
- }
- }
- return handled;
-}
-
-//-----------------------------------------------------------------------------
-// LLPanelGroupNotices
-//-----------------------------------------------------------------------------
-std::string build_notice_date(const U32& the_time)
-{
- // ISO 8601 date format
-
- time_t t = (time_t)the_time;
-
- if (!t)
- {
- time(&t);
- }
-
- std::string dateStr = "["+ LLTrans::getString("LTimeYear") + "]/["
- + LLTrans::getString("LTimeMthNum") + "]/["
- + LLTrans::getString("LTimeDay") + "] ["
- + LLTrans::getString("LTimeHour") + "]:["
- + LLTrans::getString("LTimeMin") + "]:["
- + LLTrans::getString("LTimeSec") + "]";
- LLSD substitution;
- substitution["datetime"] = (S32) t;
- LLStringUtil::format (dateStr, substitution);
- return dateStr;
-}
-
-LLPanelGroupNotices::LLPanelGroupNotices() :
- LLPanelGroupTab(),
- mInventoryItem(NULL),
- mInventoryOffer(NULL)
-{
-
-
-}
-
-LLPanelGroupNotices::~LLPanelGroupNotices()
-{
- sInstances.erase(mGroupID);
-
- if (mInventoryOffer)
- {
- // Cancel the inventory offer.
- mInventoryOffer->forceResponse(IOR_DECLINE);
-
- mInventoryOffer = NULL;
- }
-}
-
-
-bool LLPanelGroupNotices::isVisibleByAgent(LLAgent* agentp)
-{
- return mAllowEdit &&
- agentp->hasPowerInGroup(mGroupID, GP_NOTICES_SEND | GP_NOTICES_RECEIVE);
-}
-
-bool LLPanelGroupNotices::postBuild()
-{
- constexpr bool recurse = true;
-
- mNoticesList = getChild<LLScrollListCtrl>("notice_list",recurse);
- mNoticesList->setCommitOnSelectionChange(true);
- mNoticesList->setCommitCallback(onSelectNotice, this);
- mNoticesList->sortByColumn("date", false);
-
- mBtnNewMessage = getChild<LLButton>("create_new_notice",recurse);
- mBtnNewMessage->setClickedCallback(onClickNewMessage, this);
- mBtnNewMessage->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_NOTICES_SEND));
-
- mBtnGetPastNotices = getChild<LLButton>("refresh_notices",recurse);
- mBtnGetPastNotices->setClickedCallback(onClickRefreshNotices, this);
-
- // Create
- mCreateSubject = getChild<LLLineEditor>("create_subject",recurse);
- mCreateMessage = getChild<LLTextEditor>("create_message",recurse);
-
- mCreateInventoryName = getChild<LLLineEditor>("create_inventory_name",recurse);
- mCreateInventoryName->setTabStop(false);
- mCreateInventoryName->setEnabled(false);
-
- mCreateInventoryIcon = getChild<LLIconCtrl>("create_inv_icon",recurse);
- mCreateInventoryIcon->setVisible(false);
-
- mBtnSendMessage = getChild<LLButton>("send_notice",recurse);
- mBtnSendMessage->setClickedCallback(onClickSendMessage, this);
-
- mBtnRemoveAttachment = getChild<LLButton>("remove_attachment",recurse);
- mBtnRemoveAttachment->setClickedCallback(onClickRemoveAttachment, this);
- mBtnRemoveAttachment->setEnabled(false);
-
- // View
- mViewSubject = getChild<LLLineEditor>("view_subject",recurse);
- mViewMessage = getChild<LLTextEditor>("view_message",recurse);
-
- mViewInventoryName = getChild<LLLineEditor>("view_inventory_name",recurse);
- mViewInventoryName->setTabStop(false);
- mViewInventoryName->setEnabled(false);
-
- mViewInventoryIcon = getChild<LLIconCtrl>("view_inv_icon",recurse);
- mViewInventoryIcon->setVisible(false);
-
- mBtnOpenAttachment = getChild<LLButton>("open_attachment",recurse);
- mBtnOpenAttachment->setClickedCallback(onClickOpenAttachment, this);
-
- mNoNoticesStr = getString("no_notices_text");
-
- mPanelCreateNotice = getChild<LLPanel>("panel_create_new_notice",recurse);
- mPanelViewNotice = getChild<LLPanel>("panel_view_past_notice",recurse);
-
- LLGroupDropTarget* target = getChild<LLGroupDropTarget> ("drop_target");
- target->setPanel (this);
- target->setGroup (mGroupID);
-
- arrangeNoticeView(VIEW_PAST_NOTICE);
-
- return LLPanelGroupTab::postBuild();
-}
-
-void LLPanelGroupNotices::activate()
-{
- if (mNoticesList)
- {
- mNoticesList->deleteAllItems();
- mKnownNoticeIds.clear();
- }
-
- mPrevSelectedNotice = LLUUID();
-
- bool can_send = gAgent.hasPowerInGroup(mGroupID,GP_NOTICES_SEND);
- bool can_receive = gAgent.hasPowerInGroup(mGroupID,GP_NOTICES_RECEIVE);
-
- mPanelViewNotice->setEnabled(can_receive);
- mPanelCreateNotice->setEnabled(can_send);
-
- // Always disabled to stop direct editing of attachment names
- mCreateInventoryName->setEnabled(false);
- mViewInventoryName->setEnabled(false);
-
- // If we can receive notices, grab them right away.
- if (can_receive)
- {
- onClickRefreshNotices(this);
- }
-}
-
-void LLPanelGroupNotices::setItem(LLPointer<LLInventoryItem> inv_item)
-{
- mInventoryItem = inv_item;
-
- bool item_is_multi = false;
- if ( inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS )
- {
- item_is_multi = true;
- };
-
- std::string icon_name = LLInventoryIcon::getIconName(inv_item->getType(),
- inv_item->getInventoryType(),
- inv_item->getFlags(),
- item_is_multi );
-
- mCreateInventoryIcon->setValue(icon_name);
- mCreateInventoryIcon->setVisible(true);
-
- std::stringstream ss;
- ss << " " << mInventoryItem->getName();
-
- mCreateInventoryName->setText(ss.str());
- mBtnRemoveAttachment->setEnabled(true);
-}
-
-void LLPanelGroupNotices::onClickRemoveAttachment(void* data)
-{
- LLPanelGroupNotices* self = (LLPanelGroupNotices*)data;
- self->mInventoryItem = NULL;
- self->mCreateInventoryName->clear();
- self->mCreateInventoryIcon->setVisible(false);
- self->mBtnRemoveAttachment->setEnabled(false);
-}
-
-//static
-void LLPanelGroupNotices::onClickOpenAttachment(void* data)
-{
- LLPanelGroupNotices* self = (LLPanelGroupNotices*)data;
-
- self->mInventoryOffer->forceResponse(IOR_ACCEPT);
- self->mInventoryOffer = NULL;
- self->mBtnOpenAttachment->setEnabled(false);
-}
-
-void LLPanelGroupNotices::onClickSendMessage(void* data)
-{
- LLPanelGroupNotices* self = (LLPanelGroupNotices*)data;
-
- if (self->mCreateSubject->getText().empty())
- {
- // Must supply a subject
- LLNotificationsUtil::add("MustSpecifyGroupNoticeSubject");
- return;
- }
- send_group_notice(
- self->mGroupID,
- self->mCreateSubject->getText(),
- self->mCreateMessage->getText(),
- self->mInventoryItem);
-
-
- //instantly add new notice. actual notice will be added after ferreshNotices call
- LLUUID id = LLUUID::generateNewID();
- std::string subj = self->mCreateSubject->getText();
- std::string name ;
- LLAgentUI::buildFullname(name);
- U32 timestamp = 0;
-
- LLSD row;
- row["id"] = id;
-
- row["columns"][0]["column"] = "icon";
-
- row["columns"][1]["column"] = "subject";
- row["columns"][1]["value"] = subj;
-
- row["columns"][2]["column"] = "from";
- row["columns"][2]["value"] = name;
-
- row["columns"][3]["column"] = "date";
- row["columns"][3]["value"] = build_notice_date(timestamp);
-
- row["columns"][4]["column"] = "sort";
- row["columns"][4]["value"] = llformat( "%u", timestamp);
-
- self->mNoticesList->addElement(row, ADD_BOTTOM);
- self->mKnownNoticeIds.insert(id);
-
- self->mCreateMessage->clear();
- self->mCreateSubject->clear();
- onClickRemoveAttachment(data);
-
- self->arrangeNoticeView(VIEW_PAST_NOTICE);
-}
-
-//static
-void LLPanelGroupNotices::onClickNewMessage(void* data)
-{
- LLPanelGroupNotices* self = (LLPanelGroupNotices*)data;
-
- self->arrangeNoticeView(CREATE_NEW_NOTICE);
-
- if (self->mInventoryOffer)
- {
- self->mInventoryOffer->forceResponse(IOR_DECLINE);
- self->mInventoryOffer = NULL;
- }
-
- self->mCreateSubject->clear();
- self->mCreateMessage->clear();
- if (self->mInventoryItem) onClickRemoveAttachment(self);
- self->mNoticesList->deselectAllItems(true); // true == don't commit on chnage
-}
-
-void LLPanelGroupNotices::refreshNotices()
-{
- onClickRefreshNotices(this);
-}
-
-void LLPanelGroupNotices::clearNoticeList()
-{
- mPrevSelectedNotice = mNoticesList->getStringUUIDSelectedItem();
- mNoticesList->deleteAllItems();
- mKnownNoticeIds.clear();
-}
-
-void LLPanelGroupNotices::onClickRefreshNotices(void* data)
-{
- LL_DEBUGS() << "LLPanelGroupNotices::onClickGetPastNotices" << LL_ENDL;
- LLPanelGroupNotices* self = (LLPanelGroupNotices*)data;
-
- self->clearNoticeList();
-
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessage("GroupNoticesListRequest");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID",gAgent.getID());
- msg->addUUID("SessionID",gAgent.getSessionID());
- msg->nextBlock("Data");
- msg->addUUID("GroupID",self->mGroupID);
- gAgent.sendReliableMessage();
-}
-
-//static
-std::map<LLUUID,LLPanelGroupNotices*> LLPanelGroupNotices::sInstances;
-
-// static
-void LLPanelGroupNotices::processGroupNoticesListReply(LLMessageSystem* msg, void** data)
-{
- LLUUID group_id;
- msg->getUUID("AgentData", "GroupID", group_id);
-
- std::map<LLUUID,LLPanelGroupNotices*>::iterator it = sInstances.find(group_id);
- if (it == sInstances.end())
- {
- LL_INFOS() << "Group Panel Notices " << group_id << " no longer in existence."
- << LL_ENDL;
- return;
- }
-
- LLPanelGroupNotices* selfp = it->second;
- if(!selfp)
- {
- LL_INFOS() << "Group Panel Notices " << group_id << " no longer in existence."
- << LL_ENDL;
- return;
- }
-
- selfp->processNotices(msg);
-}
-
-void LLPanelGroupNotices::processNotices(LLMessageSystem* msg)
-{
- LLUUID id;
- std::string subj;
- std::string name;
- U32 timestamp;
- bool has_attachment;
- U8 asset_type;
-
- S32 i=0;
- S32 count = msg->getNumberOfBlocks("Data");
-
- mNoticesList->setEnabled(true);
-
- //save sort state and set unsorted state to prevent unnecessary
- //sorting while adding notices
- bool save_sort = mNoticesList->isSorted();
- mNoticesList->setNeedsSort(false);
-
- for (;i<count;++i)
- {
- msg->getUUID("Data","NoticeID",id,i);
- if (1 == count && id.isNull())
- {
- // Only one entry, the dummy entry.
- mNoticesList->setCommentText(mNoNoticesStr);
- mNoticesList->setEnabled(false);
- return;
- }
-
- // Due to some network delays we can receive notice list more than once...
- // So add only unique notices
- if (mKnownNoticeIds.find(id) != mKnownNoticeIds.end())
- {
- // If items with this ID already in the list - skip it
- continue;
- }
-
- msg->getString("Data","Subject",subj,i);
- msg->getString("Data","FromName",name,i);
- msg->getBOOL("Data","HasAttachment",has_attachment,i);
- msg->getU8("Data","AssetType",asset_type,i);
- msg->getU32("Data","Timestamp",timestamp,i);
-
- // we only have the legacy name here, convert it to a username
- name = LLCacheName::buildUsername(name);
-
- LLSD row;
- row["id"] = id;
- row["columns"][0]["column"] = "icon";
- if (has_attachment)
- {
- std::string icon_name = LLInventoryIcon::getIconName(
- (LLAssetType::EType)asset_type,
- LLInventoryType::IT_NONE);
- row["columns"][0]["type"] = "icon";
- row["columns"][0]["value"] = icon_name;
- }
-
- row["columns"][1]["column"] = "subject";
- row["columns"][1]["value"] = subj;
-
- row["columns"][2]["column"] = "from";
- row["columns"][2]["value"] = name;
-
- row["columns"][3]["column"] = "date";
- row["columns"][3]["value"] = build_notice_date(timestamp);
-
- row["columns"][4]["column"] = "sort";
- row["columns"][4]["value"] = llformat( "%u", timestamp);
-
- mNoticesList->addElement(row, ADD_BOTTOM);
- mKnownNoticeIds.insert(id);
- }
-
- mNoticesList->setNeedsSort(save_sort);
- mNoticesList->updateSort();
- if (mPanelViewNotice->getVisible())
- {
- if (!mNoticesList->selectByID(mPrevSelectedNotice))
- {
- mNoticesList->selectFirstItem();
- }
- }
-}
-
-void LLPanelGroupNotices::onSelectNotice(LLUICtrl* ctrl, void* data)
-{
- LLPanelGroupNotices* self = (LLPanelGroupNotices*)data;
-
- if(!self) return;
- LLScrollListItem* item = self->mNoticesList->getFirstSelected();
- if (!item) return;
-
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessage("GroupNoticeRequest");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID",gAgent.getID());
- msg->addUUID("SessionID",gAgent.getSessionID());
- msg->nextBlock("Data");
- msg->addUUID("GroupNoticeID",item->getUUID());
- gAgent.sendReliableMessage();
-
- LL_DEBUGS() << "Item " << item->getUUID() << " selected." << LL_ENDL;
-}
-
-void LLPanelGroupNotices::showNotice(const std::string& subject,
- const std::string& message,
- const bool& has_inventory,
- const std::string& inventory_name,
- LLOfferInfo* inventory_offer)
-{
- arrangeNoticeView(VIEW_PAST_NOTICE);
-
- if(mViewSubject) mViewSubject->setText(subject);
- if(mViewMessage) mViewMessage->setText(message);
-
- if (mInventoryOffer)
- {
- // Cancel the inventory offer for the previously viewed notice
- mInventoryOffer->forceResponse(IOR_DECLINE);
- mInventoryOffer = NULL;
- }
-
- if (inventory_offer)
- {
- mInventoryOffer = inventory_offer;
-
- std::string icon_name = LLInventoryIcon::getIconName(mInventoryOffer->mType,
- LLInventoryType::IT_TEXTURE);
-
- mViewInventoryIcon->setValue(icon_name);
- mViewInventoryIcon->setVisible(true);
-
- std::stringstream ss;
- ss << " " << inventory_name;
-
- mViewInventoryName->setText(ss.str());
- mBtnOpenAttachment->setEnabled(true);
- }
- else
- {
- mViewInventoryName->clear();
- mViewInventoryIcon->setVisible(false);
- mBtnOpenAttachment->setEnabled(false);
- }
-}
-
-void LLPanelGroupNotices::arrangeNoticeView(ENoticeView view_type)
-{
- if (CREATE_NEW_NOTICE == view_type)
- {
- mPanelCreateNotice->setVisible(true);
- mPanelViewNotice->setVisible(false);
- }
- else
- {
- mPanelCreateNotice->setVisible(false);
- mPanelViewNotice->setVisible(true);
- mBtnOpenAttachment->setEnabled(false);
- }
-}
-void LLPanelGroupNotices::setGroupID(const LLUUID& id)
-{
- sInstances.erase(mGroupID);
- LLPanelGroupTab::setGroupID(id);
- sInstances[mGroupID] = this;
-
- mBtnNewMessage->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_NOTICES_SEND));
-
- LLGroupDropTarget* target = getChild<LLGroupDropTarget> ("drop_target");
- target->setPanel (this);
- target->setGroup (mGroupID);
-
- if(mViewMessage)
- mViewMessage->clear();
-
- if(mViewInventoryName)
- mViewInventoryName->clear();
-
- activate();
-}
+/** + * @file llpanelgroupnotices.cpp + * @brief A panel to display group notices. + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llpanelgroupnotices.h" + +#include "llview.h" + +#include "llavatarnamecache.h" +#include "llinventory.h" +#include "llviewerinventory.h" +#include "llinventorydefines.h" +#include "llinventoryfunctions.h" +#include "llinventoryicon.h" +#include "llinventorymodel.h" +#include "llagent.h" +#include "llagentui.h" + +#include "lllineeditor.h" +#include "lltexteditor.h" +#include "llbutton.h" +#include "lliconctrl.h" +#include "llcheckboxctrl.h" +#include "llscrolllistctrl.h" +#include "llscrolllistitem.h" +#include "lltextbox.h" +#include "lltrans.h" + +#include "roles_constants.h" +#include "llviewerwindow.h" +#include "llviewermessage.h" +#include "llnotificationsutil.h" +#include "llgiveinventory.h" + +static LLPanelInjector<LLPanelGroupNotices> t_panel_group_notices("panel_group_notices"); + + +///////////////////////// +// LLPanelGroupNotices // +///////////////////////// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLDropTarget +// +// This handy class is a simple way to drop something on another +// view. It handles drop events, always setting itself to the size of +// its parent. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLGroupDropTarget : public LLView +{ +public: + struct Params : public LLInitParam::Block<Params, LLView::Params> + { + // *NOTE: These parameters logically Mandatory, but are not + // specified in XML files, hence Optional + Optional<LLPanelGroupNotices*> panel; + Optional<LLUUID> group_id; + Params() + : panel("panel"), + group_id("group_id") + { + changeDefault(mouse_opaque, false); + changeDefault(follows.flags, FOLLOWS_ALL); + } + }; + LLGroupDropTarget(const Params&); + ~LLGroupDropTarget() {}; + + // + // LLView functionality + virtual bool handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + void setPanel (LLPanelGroupNotices* panel) {mGroupNoticesPanel = panel;}; + void setGroup (LLUUID group) {mGroupID = group;}; + +protected: + LLPanelGroupNotices* mGroupNoticesPanel; + LLUUID mGroupID; +}; + +static LLDefaultChildRegistry::Register<LLGroupDropTarget> r("group_drop_target"); + +LLGroupDropTarget::LLGroupDropTarget(const LLGroupDropTarget::Params& p) +: LLView(p), + mGroupNoticesPanel(p.panel), + mGroupID(p.group_id) +{} + +bool LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, bool drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + bool handled = false; + + if (!gAgent.hasPowerInGroup(mGroupID,GP_NOTICES_SEND)) + { + *accept = ACCEPT_NO; + return true; + } + + if(getParent()) + { + // check if inside + //LLRect parent_rect = mParentView->getRect(); + //getRect().set(0, parent_rect.getHeight(), parent_rect.getWidth(), 0); + handled = true; + + // check the type + switch(cargo_type) + { + case DAD_TEXTURE: + case DAD_SOUND: + 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_CALLINGCARD: + case DAD_MESH: + case DAD_SETTINGS: + case DAD_MATERIAL: + { + LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data; + if(gInventory.getItem(inv_item->getUUID()) + && LLGiveInventory::isInventoryGroupGiveAcceptable(inv_item)) + { + // *TODO: get multiple object transfers working + *accept = ACCEPT_YES_COPY_SINGLE; + if(drop) + { + mGroupNoticesPanel->setItem(inv_item); + } + } + 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. + *accept = ACCEPT_NO; + } + break; + } + case DAD_CATEGORY: + default: + *accept = ACCEPT_NO; + break; + } + } + return handled; +} + +//----------------------------------------------------------------------------- +// LLPanelGroupNotices +//----------------------------------------------------------------------------- +std::string build_notice_date(const U32& the_time) +{ + // ISO 8601 date format + + time_t t = (time_t)the_time; + + if (!t) + { + time(&t); + } + + std::string dateStr = "["+ LLTrans::getString("LTimeYear") + "]/[" + + LLTrans::getString("LTimeMthNum") + "]/[" + + LLTrans::getString("LTimeDay") + "] [" + + LLTrans::getString("LTimeHour") + "]:[" + + LLTrans::getString("LTimeMin") + "]:[" + + LLTrans::getString("LTimeSec") + "]"; + LLSD substitution; + substitution["datetime"] = (S32) t; + LLStringUtil::format (dateStr, substitution); + return dateStr; +} + +LLPanelGroupNotices::LLPanelGroupNotices() : + LLPanelGroupTab(), + mInventoryItem(NULL), + mInventoryOffer(NULL) +{ + + +} + +LLPanelGroupNotices::~LLPanelGroupNotices() +{ + sInstances.erase(mGroupID); + + if (mInventoryOffer) + { + // Cancel the inventory offer. + mInventoryOffer->forceResponse(IOR_DECLINE); + + mInventoryOffer = NULL; + } +} + + +bool LLPanelGroupNotices::isVisibleByAgent(LLAgent* agentp) +{ + return mAllowEdit && + agentp->hasPowerInGroup(mGroupID, GP_NOTICES_SEND | GP_NOTICES_RECEIVE); +} + +bool LLPanelGroupNotices::postBuild() +{ + constexpr bool recurse = true; + + mNoticesList = getChild<LLScrollListCtrl>("notice_list",recurse); + mNoticesList->setCommitOnSelectionChange(true); + mNoticesList->setCommitCallback(onSelectNotice, this); + mNoticesList->sortByColumn("date", false); + + mBtnNewMessage = getChild<LLButton>("create_new_notice",recurse); + mBtnNewMessage->setClickedCallback(onClickNewMessage, this); + mBtnNewMessage->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_NOTICES_SEND)); + + mBtnGetPastNotices = getChild<LLButton>("refresh_notices",recurse); + mBtnGetPastNotices->setClickedCallback(onClickRefreshNotices, this); + + // Create + mCreateSubject = getChild<LLLineEditor>("create_subject",recurse); + mCreateMessage = getChild<LLTextEditor>("create_message",recurse); + + mCreateInventoryName = getChild<LLLineEditor>("create_inventory_name",recurse); + mCreateInventoryName->setTabStop(false); + mCreateInventoryName->setEnabled(false); + + mCreateInventoryIcon = getChild<LLIconCtrl>("create_inv_icon",recurse); + mCreateInventoryIcon->setVisible(false); + + mBtnSendMessage = getChild<LLButton>("send_notice",recurse); + mBtnSendMessage->setClickedCallback(onClickSendMessage, this); + + mBtnRemoveAttachment = getChild<LLButton>("remove_attachment",recurse); + mBtnRemoveAttachment->setClickedCallback(onClickRemoveAttachment, this); + mBtnRemoveAttachment->setEnabled(false); + + // View + mViewSubject = getChild<LLLineEditor>("view_subject",recurse); + mViewMessage = getChild<LLTextEditor>("view_message",recurse); + + mViewInventoryName = getChild<LLLineEditor>("view_inventory_name",recurse); + mViewInventoryName->setTabStop(false); + mViewInventoryName->setEnabled(false); + + mViewInventoryIcon = getChild<LLIconCtrl>("view_inv_icon",recurse); + mViewInventoryIcon->setVisible(false); + + mBtnOpenAttachment = getChild<LLButton>("open_attachment",recurse); + mBtnOpenAttachment->setClickedCallback(onClickOpenAttachment, this); + + mNoNoticesStr = getString("no_notices_text"); + + mPanelCreateNotice = getChild<LLPanel>("panel_create_new_notice",recurse); + mPanelViewNotice = getChild<LLPanel>("panel_view_past_notice",recurse); + + LLGroupDropTarget* target = getChild<LLGroupDropTarget> ("drop_target"); + target->setPanel (this); + target->setGroup (mGroupID); + + arrangeNoticeView(VIEW_PAST_NOTICE); + + return LLPanelGroupTab::postBuild(); +} + +void LLPanelGroupNotices::activate() +{ + if (mNoticesList) + { + mNoticesList->deleteAllItems(); + mKnownNoticeIds.clear(); + } + + mPrevSelectedNotice = LLUUID(); + + bool can_send = gAgent.hasPowerInGroup(mGroupID,GP_NOTICES_SEND); + bool can_receive = gAgent.hasPowerInGroup(mGroupID,GP_NOTICES_RECEIVE); + + mPanelViewNotice->setEnabled(can_receive); + mPanelCreateNotice->setEnabled(can_send); + + // Always disabled to stop direct editing of attachment names + mCreateInventoryName->setEnabled(false); + mViewInventoryName->setEnabled(false); + + // If we can receive notices, grab them right away. + if (can_receive) + { + onClickRefreshNotices(this); + } +} + +void LLPanelGroupNotices::setItem(LLPointer<LLInventoryItem> inv_item) +{ + mInventoryItem = inv_item; + + bool item_is_multi = false; + if ( inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) + { + item_is_multi = true; + }; + + std::string icon_name = LLInventoryIcon::getIconName(inv_item->getType(), + inv_item->getInventoryType(), + inv_item->getFlags(), + item_is_multi ); + + mCreateInventoryIcon->setValue(icon_name); + mCreateInventoryIcon->setVisible(true); + + std::stringstream ss; + ss << " " << mInventoryItem->getName(); + + mCreateInventoryName->setText(ss.str()); + mBtnRemoveAttachment->setEnabled(true); +} + +void LLPanelGroupNotices::onClickRemoveAttachment(void* data) +{ + LLPanelGroupNotices* self = (LLPanelGroupNotices*)data; + self->mInventoryItem = NULL; + self->mCreateInventoryName->clear(); + self->mCreateInventoryIcon->setVisible(false); + self->mBtnRemoveAttachment->setEnabled(false); +} + +//static +void LLPanelGroupNotices::onClickOpenAttachment(void* data) +{ + LLPanelGroupNotices* self = (LLPanelGroupNotices*)data; + + self->mInventoryOffer->forceResponse(IOR_ACCEPT); + self->mInventoryOffer = NULL; + self->mBtnOpenAttachment->setEnabled(false); +} + +void LLPanelGroupNotices::onClickSendMessage(void* data) +{ + LLPanelGroupNotices* self = (LLPanelGroupNotices*)data; + + if (self->mCreateSubject->getText().empty()) + { + // Must supply a subject + LLNotificationsUtil::add("MustSpecifyGroupNoticeSubject"); + return; + } + send_group_notice( + self->mGroupID, + self->mCreateSubject->getText(), + self->mCreateMessage->getText(), + self->mInventoryItem); + + + //instantly add new notice. actual notice will be added after ferreshNotices call + LLUUID id = LLUUID::generateNewID(); + std::string subj = self->mCreateSubject->getText(); + std::string name ; + LLAgentUI::buildFullname(name); + U32 timestamp = 0; + + LLSD row; + row["id"] = id; + + row["columns"][0]["column"] = "icon"; + + row["columns"][1]["column"] = "subject"; + row["columns"][1]["value"] = subj; + + row["columns"][2]["column"] = "from"; + row["columns"][2]["value"] = name; + + row["columns"][3]["column"] = "date"; + row["columns"][3]["value"] = build_notice_date(timestamp); + + row["columns"][4]["column"] = "sort"; + row["columns"][4]["value"] = llformat( "%u", timestamp); + + self->mNoticesList->addElement(row, ADD_BOTTOM); + self->mKnownNoticeIds.insert(id); + + self->mCreateMessage->clear(); + self->mCreateSubject->clear(); + onClickRemoveAttachment(data); + + self->arrangeNoticeView(VIEW_PAST_NOTICE); +} + +//static +void LLPanelGroupNotices::onClickNewMessage(void* data) +{ + LLPanelGroupNotices* self = (LLPanelGroupNotices*)data; + + self->arrangeNoticeView(CREATE_NEW_NOTICE); + + if (self->mInventoryOffer) + { + self->mInventoryOffer->forceResponse(IOR_DECLINE); + self->mInventoryOffer = NULL; + } + + self->mCreateSubject->clear(); + self->mCreateMessage->clear(); + if (self->mInventoryItem) onClickRemoveAttachment(self); + self->mNoticesList->deselectAllItems(true); // true == don't commit on chnage +} + +void LLPanelGroupNotices::refreshNotices() +{ + onClickRefreshNotices(this); +} + +void LLPanelGroupNotices::clearNoticeList() +{ + mPrevSelectedNotice = mNoticesList->getStringUUIDSelectedItem(); + mNoticesList->deleteAllItems(); + mKnownNoticeIds.clear(); +} + +void LLPanelGroupNotices::onClickRefreshNotices(void* data) +{ + LL_DEBUGS() << "LLPanelGroupNotices::onClickGetPastNotices" << LL_ENDL; + LLPanelGroupNotices* self = (LLPanelGroupNotices*)data; + + self->clearNoticeList(); + + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("GroupNoticesListRequest"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID",gAgent.getID()); + msg->addUUID("SessionID",gAgent.getSessionID()); + msg->nextBlock("Data"); + msg->addUUID("GroupID",self->mGroupID); + gAgent.sendReliableMessage(); +} + +//static +std::map<LLUUID,LLPanelGroupNotices*> LLPanelGroupNotices::sInstances; + +// static +void LLPanelGroupNotices::processGroupNoticesListReply(LLMessageSystem* msg, void** data) +{ + LLUUID group_id; + msg->getUUID("AgentData", "GroupID", group_id); + + std::map<LLUUID,LLPanelGroupNotices*>::iterator it = sInstances.find(group_id); + if (it == sInstances.end()) + { + LL_INFOS() << "Group Panel Notices " << group_id << " no longer in existence." + << LL_ENDL; + return; + } + + LLPanelGroupNotices* selfp = it->second; + if(!selfp) + { + LL_INFOS() << "Group Panel Notices " << group_id << " no longer in existence." + << LL_ENDL; + return; + } + + selfp->processNotices(msg); +} + +void LLPanelGroupNotices::processNotices(LLMessageSystem* msg) +{ + LLUUID id; + std::string subj; + std::string name; + U32 timestamp; + bool has_attachment; + U8 asset_type; + + S32 i=0; + S32 count = msg->getNumberOfBlocks("Data"); + + mNoticesList->setEnabled(true); + + //save sort state and set unsorted state to prevent unnecessary + //sorting while adding notices + bool save_sort = mNoticesList->isSorted(); + mNoticesList->setNeedsSort(false); + + for (;i<count;++i) + { + msg->getUUID("Data","NoticeID",id,i); + if (1 == count && id.isNull()) + { + // Only one entry, the dummy entry. + mNoticesList->setCommentText(mNoNoticesStr); + mNoticesList->setEnabled(false); + return; + } + + // Due to some network delays we can receive notice list more than once... + // So add only unique notices + if (mKnownNoticeIds.find(id) != mKnownNoticeIds.end()) + { + // If items with this ID already in the list - skip it + continue; + } + + msg->getString("Data","Subject",subj,i); + msg->getString("Data","FromName",name,i); + msg->getBOOL("Data","HasAttachment",has_attachment,i); + msg->getU8("Data","AssetType",asset_type,i); + msg->getU32("Data","Timestamp",timestamp,i); + + // we only have the legacy name here, convert it to a username + name = LLCacheName::buildUsername(name); + + LLSD row; + row["id"] = id; + row["columns"][0]["column"] = "icon"; + if (has_attachment) + { + std::string icon_name = LLInventoryIcon::getIconName( + (LLAssetType::EType)asset_type, + LLInventoryType::IT_NONE); + row["columns"][0]["type"] = "icon"; + row["columns"][0]["value"] = icon_name; + } + + row["columns"][1]["column"] = "subject"; + row["columns"][1]["value"] = subj; + + row["columns"][2]["column"] = "from"; + row["columns"][2]["value"] = name; + + row["columns"][3]["column"] = "date"; + row["columns"][3]["value"] = build_notice_date(timestamp); + + row["columns"][4]["column"] = "sort"; + row["columns"][4]["value"] = llformat( "%u", timestamp); + + mNoticesList->addElement(row, ADD_BOTTOM); + mKnownNoticeIds.insert(id); + } + + mNoticesList->setNeedsSort(save_sort); + mNoticesList->updateSort(); + if (mPanelViewNotice->getVisible()) + { + if (!mNoticesList->selectByID(mPrevSelectedNotice)) + { + mNoticesList->selectFirstItem(); + } + } +} + +void LLPanelGroupNotices::onSelectNotice(LLUICtrl* ctrl, void* data) +{ + LLPanelGroupNotices* self = (LLPanelGroupNotices*)data; + + if(!self) return; + LLScrollListItem* item = self->mNoticesList->getFirstSelected(); + if (!item) return; + + LLMessageSystem* msg = gMessageSystem; + msg->newMessage("GroupNoticeRequest"); + msg->nextBlock("AgentData"); + msg->addUUID("AgentID",gAgent.getID()); + msg->addUUID("SessionID",gAgent.getSessionID()); + msg->nextBlock("Data"); + msg->addUUID("GroupNoticeID",item->getUUID()); + gAgent.sendReliableMessage(); + + LL_DEBUGS() << "Item " << item->getUUID() << " selected." << LL_ENDL; +} + +void LLPanelGroupNotices::showNotice(const std::string& subject, + const std::string& message, + const bool& has_inventory, + const std::string& inventory_name, + LLOfferInfo* inventory_offer) +{ + arrangeNoticeView(VIEW_PAST_NOTICE); + + if(mViewSubject) mViewSubject->setText(subject); + if(mViewMessage) mViewMessage->setText(message); + + if (mInventoryOffer) + { + // Cancel the inventory offer for the previously viewed notice + mInventoryOffer->forceResponse(IOR_DECLINE); + mInventoryOffer = NULL; + } + + if (inventory_offer) + { + mInventoryOffer = inventory_offer; + + std::string icon_name = LLInventoryIcon::getIconName(mInventoryOffer->mType, + LLInventoryType::IT_TEXTURE); + + mViewInventoryIcon->setValue(icon_name); + mViewInventoryIcon->setVisible(true); + + std::stringstream ss; + ss << " " << inventory_name; + + mViewInventoryName->setText(ss.str()); + mBtnOpenAttachment->setEnabled(true); + } + else + { + mViewInventoryName->clear(); + mViewInventoryIcon->setVisible(false); + mBtnOpenAttachment->setEnabled(false); + } +} + +void LLPanelGroupNotices::arrangeNoticeView(ENoticeView view_type) +{ + if (CREATE_NEW_NOTICE == view_type) + { + mPanelCreateNotice->setVisible(true); + mPanelViewNotice->setVisible(false); + } + else + { + mPanelCreateNotice->setVisible(false); + mPanelViewNotice->setVisible(true); + mBtnOpenAttachment->setEnabled(false); + } +} +void LLPanelGroupNotices::setGroupID(const LLUUID& id) +{ + sInstances.erase(mGroupID); + LLPanelGroupTab::setGroupID(id); + sInstances[mGroupID] = this; + + mBtnNewMessage->setEnabled(gAgent.hasPowerInGroup(mGroupID, GP_NOTICES_SEND)); + + LLGroupDropTarget* target = getChild<LLGroupDropTarget> ("drop_target"); + target->setPanel (this); + target->setGroup (mGroupID); + + if(mViewMessage) + mViewMessage->clear(); + + if(mViewInventoryName) + mViewInventoryName->clear(); + + activate(); +} |