PageRenderTime 51ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/newview/llfloaterbulkpermission.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 364 lines | 239 code | 39 blank | 86 comment | 38 complexity | 7ffd57304fb0c69dcb9e48ad5abdfa8d MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llfloaterbulkpermissions.cpp
  3. * @author Michelle2 Zenovka
  4. * @brief A floater which allows task inventory item's properties to be changed on mass.
  5. *
  6. * $LicenseInfo:firstyear=2008&license=viewerlgpl$
  7. * Second Life Viewer Source Code
  8. * Copyright (C) 2010, Linden Research, Inc.
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation;
  13. * version 2.1 of the License only.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  25. * $/LicenseInfo$
  26. */
  27. #include "llviewerprecompiledheaders.h"
  28. #include "llfloaterbulkpermission.h"
  29. #include "llfloaterperms.h" // for utilities
  30. #include "llagent.h"
  31. #include "llchat.h"
  32. #include "llinventorydefines.h"
  33. #include "llviewerwindow.h"
  34. #include "llviewerobject.h"
  35. #include "llviewerobjectlist.h"
  36. #include "llviewerregion.h"
  37. #include "lscript_rt_interface.h"
  38. #include "llviewercontrol.h"
  39. #include "llviewerinventory.h"
  40. #include "llviewerobject.h"
  41. #include "llviewerregion.h"
  42. #include "llresmgr.h"
  43. #include "llbutton.h"
  44. #include "lldir.h"
  45. #include "llviewerstats.h"
  46. #include "lluictrlfactory.h"
  47. #include "llselectmgr.h"
  48. #include "llcheckboxctrl.h"
  49. #include "roles_constants.h" // for GP_OBJECT_MANIPULATE
  50. LLFloaterBulkPermission::LLFloaterBulkPermission(const LLSD& seed)
  51. : LLFloater(seed),
  52. mDone(FALSE)
  53. {
  54. mID.generate();
  55. mCommitCallbackRegistrar.add("BulkPermission.Apply", boost::bind(&LLFloaterBulkPermission::onApplyBtn, this));
  56. mCommitCallbackRegistrar.add("BulkPermission.Close", boost::bind(&LLFloaterBulkPermission::onCloseBtn, this));
  57. mCommitCallbackRegistrar.add("BulkPermission.CheckAll", boost::bind(&LLFloaterBulkPermission::onCheckAll, this));
  58. mCommitCallbackRegistrar.add("BulkPermission.UncheckAll", boost::bind(&LLFloaterBulkPermission::onUncheckAll, this));
  59. mCommitCallbackRegistrar.add("BulkPermission.CommitCopy", boost::bind(&LLFloaterBulkPermission::onCommitCopy, this));
  60. }
  61. BOOL LLFloaterBulkPermission::postBuild()
  62. {
  63. return TRUE;
  64. }
  65. void LLFloaterBulkPermission::doApply()
  66. {
  67. // Inspects a stream of selected object contents and adds modifiable ones to the given array.
  68. class ModifiableGatherer : public LLSelectedNodeFunctor
  69. {
  70. public:
  71. ModifiableGatherer(LLDynamicArray<LLUUID>& q) : mQueue(q) {}
  72. virtual bool apply(LLSelectNode* node)
  73. {
  74. if( node->allowOperationOnNode(PERM_MODIFY, GP_OBJECT_MANIPULATE) )
  75. {
  76. mQueue.put(node->getObject()->getID());
  77. }
  78. return true;
  79. }
  80. private:
  81. LLDynamicArray<LLUUID>& mQueue;
  82. };
  83. LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
  84. list->deleteAllItems();
  85. ModifiableGatherer gatherer(mObjectIDs);
  86. LLSelectMgr::getInstance()->getSelection()->applyToNodes(&gatherer);
  87. if(mObjectIDs.empty())
  88. {
  89. list->setCommentText(getString("nothing_to_modify_text"));
  90. }
  91. else
  92. {
  93. mDone = FALSE;
  94. if (!start())
  95. {
  96. llwarns << "Unexpected bulk permission change failure." << llendl;
  97. }
  98. }
  99. }
  100. // This is the callback method for the viewer object currently being
  101. // worked on.
  102. // NOT static, virtual!
  103. void LLFloaterBulkPermission::inventoryChanged(LLViewerObject* viewer_object,
  104. LLInventoryObject::object_list_t* inv,
  105. S32,
  106. void* q_id)
  107. {
  108. //llinfos << "changed object: " << viewer_object->getID() << llendl;
  109. //Remove this listener from the object since its
  110. //listener callback is now being executed.
  111. //We remove the listener here because the function
  112. //removeVOInventoryListener removes the listener from a ViewerObject
  113. //which it internally stores.
  114. //If we call this further down in the function, calls to handleInventory
  115. //and nextObject may update the interally stored viewer object causing
  116. //the removal of the incorrect listener from an incorrect object.
  117. //Fixes SL-6119:Recompile scripts fails to complete
  118. removeVOInventoryListener();
  119. if (viewer_object && inv && (viewer_object->getID() == mCurrentObjectID) )
  120. {
  121. handleInventory(viewer_object, inv);
  122. }
  123. else
  124. {
  125. // something went wrong...
  126. // note that we're not working on this one, and move onto the
  127. // next object in the list.
  128. llwarns << "No inventory for " << mCurrentObjectID << llendl;
  129. nextObject();
  130. }
  131. }
  132. void LLFloaterBulkPermission::onApplyBtn()
  133. {
  134. doApply();
  135. }
  136. void LLFloaterBulkPermission::onCloseBtn()
  137. {
  138. closeFloater();
  139. }
  140. //static
  141. void LLFloaterBulkPermission::onCommitCopy()
  142. {
  143. // Implements fair use
  144. BOOL copyable = gSavedSettings.getBOOL("BulkChangeNextOwnerCopy");
  145. if(!copyable)
  146. {
  147. gSavedSettings.setBOOL("BulkChangeNextOwnerTransfer", TRUE);
  148. }
  149. LLCheckBoxCtrl* xfer =getChild<LLCheckBoxCtrl>("next_owner_transfer");
  150. xfer->setEnabled(copyable);
  151. }
  152. BOOL LLFloaterBulkPermission::start()
  153. {
  154. // note: number of top-level objects to modify is mObjectIDs.count().
  155. getChild<LLScrollListCtrl>("queue output")->setCommentText(getString("start_text"));
  156. return nextObject();
  157. }
  158. // Go to the next object and start if found. Returns false if no objects left, true otherwise.
  159. BOOL LLFloaterBulkPermission::nextObject()
  160. {
  161. S32 count;
  162. BOOL successful_start = FALSE;
  163. do
  164. {
  165. count = mObjectIDs.count();
  166. //llinfos << "Objects left to process = " << count << llendl;
  167. mCurrentObjectID.setNull();
  168. if(count > 0)
  169. {
  170. successful_start = popNext();
  171. //llinfos << (successful_start ? "successful" : "unsuccessful") << llendl;
  172. }
  173. } while((mObjectIDs.count() > 0) && !successful_start);
  174. if(isDone() && !mDone)
  175. {
  176. getChild<LLScrollListCtrl>("queue output")->setCommentText(getString("done_text"));
  177. mDone = TRUE;
  178. }
  179. return successful_start;
  180. }
  181. // Pop the top object off of the queue.
  182. // Return TRUE if the queue has started, otherwise FALSE.
  183. BOOL LLFloaterBulkPermission::popNext()
  184. {
  185. // get the head element from the container, and attempt to get its inventory.
  186. BOOL rv = FALSE;
  187. S32 count = mObjectIDs.count();
  188. if(mCurrentObjectID.isNull() && (count > 0))
  189. {
  190. mCurrentObjectID = mObjectIDs.get(0);
  191. //llinfos << "mCurrentID: " << mCurrentObjectID << llendl;
  192. mObjectIDs.remove(0);
  193. LLViewerObject* obj = gObjectList.findObject(mCurrentObjectID);
  194. if(obj)
  195. {
  196. //llinfos << "requesting inv for " << mCurrentObjectID << llendl;
  197. LLUUID* id = new LLUUID(mID);
  198. registerVOInventoryListener(obj,id);
  199. requestVOInventory();
  200. rv = TRUE;
  201. }
  202. else
  203. {
  204. llinfos<<"NULL LLViewerObject" <<llendl;
  205. }
  206. }
  207. return rv;
  208. }
  209. void LLFloaterBulkPermission::doCheckUncheckAll(BOOL check)
  210. {
  211. gSavedSettings.setBOOL("BulkChangeIncludeAnimations", check);
  212. gSavedSettings.setBOOL("BulkChangeIncludeBodyParts" , check);
  213. gSavedSettings.setBOOL("BulkChangeIncludeClothing" , check);
  214. gSavedSettings.setBOOL("BulkChangeIncludeGestures" , check);
  215. gSavedSettings.setBOOL("BulkChangeIncludeNotecards" , check);
  216. gSavedSettings.setBOOL("BulkChangeIncludeObjects" , check);
  217. gSavedSettings.setBOOL("BulkChangeIncludeScripts" , check);
  218. gSavedSettings.setBOOL("BulkChangeIncludeSounds" , check);
  219. gSavedSettings.setBOOL("BulkChangeIncludeTextures" , check);
  220. }
  221. void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, LLInventoryObject::object_list_t* inv)
  222. {
  223. LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
  224. LLInventoryObject::object_list_t::const_iterator it = inv->begin();
  225. LLInventoryObject::object_list_t::const_iterator end = inv->end();
  226. for ( ; it != end; ++it)
  227. {
  228. LLAssetType::EType asstype = (*it)->getType();
  229. if(
  230. ( asstype == LLAssetType::AT_ANIMATION && gSavedSettings.getBOOL("BulkChangeIncludeAnimations")) ||
  231. ( asstype == LLAssetType::AT_BODYPART && gSavedSettings.getBOOL("BulkChangeIncludeBodyParts" )) ||
  232. ( asstype == LLAssetType::AT_CLOTHING && gSavedSettings.getBOOL("BulkChangeIncludeClothing" )) ||
  233. ( asstype == LLAssetType::AT_GESTURE && gSavedSettings.getBOOL("BulkChangeIncludeGestures" )) ||
  234. ( asstype == LLAssetType::AT_NOTECARD && gSavedSettings.getBOOL("BulkChangeIncludeNotecards" )) ||
  235. ( asstype == LLAssetType::AT_OBJECT && gSavedSettings.getBOOL("BulkChangeIncludeObjects" )) ||
  236. ( asstype == LLAssetType::AT_LSL_TEXT && gSavedSettings.getBOOL("BulkChangeIncludeScripts" )) ||
  237. ( asstype == LLAssetType::AT_SOUND && gSavedSettings.getBOOL("BulkChangeIncludeSounds" )) ||
  238. ( asstype == LLAssetType::AT_TEXTURE && gSavedSettings.getBOOL("BulkChangeIncludeTextures" )))
  239. {
  240. LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
  241. if (object)
  242. {
  243. LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
  244. LLViewerInventoryItem* new_item = (LLViewerInventoryItem*)item;
  245. LLPermissions perm(new_item->getPermissions());
  246. // chomp the inventory name so it fits in the scroll window nicely
  247. // and the user can see the [OK]
  248. std::string invname;
  249. invname=item->getName().substr(0,item->getName().size() < 30 ? item->getName().size() : 30 );
  250. LLUIString status_text = getString("status_text");
  251. status_text.setArg("[NAME]", invname.c_str());
  252. // Check whether we appear to have the appropriate permissions to change permission on this item.
  253. // Although the server will disallow any forbidden changes, it is a good idea to guess correctly
  254. // so that we can warn the user. The risk of getting this check wrong is therefore the possibility
  255. // of incorrectly choosing to not attempt to make a valid change.
  256. //
  257. // Trouble is this is extremely difficult to do and even when we know the results
  258. // it is difficult to design the best messaging. Therefore in this initial implementation
  259. // we'll always try to set the requested permissions and consider all cases successful
  260. // and perhaps later try to implement a smarter, friendlier solution. -MG
  261. if(true
  262. //gAgent.allowOperation(PERM_MODIFY, perm, GP_OBJECT_MANIPULATE) // for group and everyone masks
  263. //|| something else // for next owner perms
  264. )
  265. {
  266. perm.setMaskNext(LLFloaterPerms::getNextOwnerPerms("BulkChange"));
  267. perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("BulkChange"));
  268. perm.setMaskGroup(LLFloaterPerms::getGroupPerms("BulkChange"));
  269. new_item->setPermissions(perm); // here's the beef
  270. updateInventory(object,new_item,TASK_INVENTORY_ITEM_KEY,FALSE);
  271. //status_text.setArg("[STATUS]", getString("status_ok_text"));
  272. status_text.setArg("[STATUS]", "");
  273. }
  274. else
  275. {
  276. //status_text.setArg("[STATUS]", getString("status_bad_text"));
  277. status_text.setArg("[STATUS]", "");
  278. }
  279. list->setCommentText(status_text.getString());
  280. //TODO if we are an object inside an object we should check a recuse flag and if set
  281. //open the inventory of the object and recurse - Michelle2 Zenovka
  282. // if(recurse && ( (*it)->getType() == LLAssetType::AT_OBJECT && processObject))
  283. // {
  284. // I think we need to get the UUID of the object inside the inventory
  285. // call item->fetchFromServer();
  286. // we need a call back to say item has arrived *sigh*
  287. // we then need to do something like
  288. // LLUUID* id = new LLUUID(mID);
  289. // registerVOInventoryListener(obj,id);
  290. // requestVOInventory();
  291. // }
  292. }
  293. }
  294. }
  295. nextObject();
  296. }
  297. // Avoid inventory callbacks etc by just fire and forgetting the message with the permissions update
  298. // we could do this via LLViewerObject::updateInventory but that uses inventory call backs and buggers
  299. // us up and we would have a dodgy item iterator
  300. void LLFloaterBulkPermission::updateInventory(LLViewerObject* object, LLViewerInventoryItem* item, U8 key, bool is_new)
  301. {
  302. LLMemType mt(LLMemType::MTYPE_OBJECT);
  303. // This slices the object into what we're concerned about on the viewer.
  304. // The simulator will take the permissions and transfer ownership.
  305. LLPointer<LLViewerInventoryItem> task_item =
  306. new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(),
  307. item->getAssetUUID(), item->getType(),
  308. item->getInventoryType(),
  309. item->getName(), item->getDescription(),
  310. item->getSaleInfo(),
  311. item->getFlags(),
  312. item->getCreationDate());
  313. task_item->setTransactionID(item->getTransactionID());
  314. LLMessageSystem* msg = gMessageSystem;
  315. msg->newMessageFast(_PREHASH_UpdateTaskInventory);
  316. msg->nextBlockFast(_PREHASH_AgentData);
  317. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  318. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  319. msg->nextBlockFast(_PREHASH_UpdateData);
  320. msg->addU32Fast(_PREHASH_LocalID, object->mLocalID);
  321. msg->addU8Fast(_PREHASH_Key, key);
  322. msg->nextBlockFast(_PREHASH_InventoryData);
  323. task_item->packMessage(msg);
  324. msg->sendReliable(object->getRegion()->getHost());
  325. }