aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llfloaterbulkpermission.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/newview/llfloaterbulkpermission.cpp')
-rw-r--r--linden/indra/newview/llfloaterbulkpermission.cpp594
1 files changed, 594 insertions, 0 deletions
diff --git a/linden/indra/newview/llfloaterbulkpermission.cpp b/linden/indra/newview/llfloaterbulkpermission.cpp
new file mode 100644
index 0000000..e66d1af
--- /dev/null
+++ b/linden/indra/newview/llfloaterbulkpermission.cpp
@@ -0,0 +1,594 @@
1/**
2 * @file llfloaterbulkpermissions.cpp
3 * @brief A floater which allows task inventory item's properties to be changed on mass.
4 *
5 * $LicenseInfo:firstyear=2008&license=viewergpl$
6 *
7 * Copyright (c) 2008, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
21 *
22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above,
24 * and agree to abide by those obligations.
25 *
26 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
27 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
28 * COMPLETENESS OR PERFORMANCE.
29 * $/LicenseInfo$
30 */
31
32/* Allow multiple task inventory properties to be set in one go, by Michelle2 Zenovka */
33
34/* TODO
35
36 * Add in the option to select objects or task inventory
37s
38
39It would be nice to set the permissions on groups of prims as well as task inventory
40
41*/
42
43
44#include "llviewerprecompiledheaders.h"
45#include "llfloaterbulkpermission.h"
46#include "llagent.h"
47#include "llchat.h"
48#include "llviewerwindow.h"
49#include "llviewerobject.h"
50#include "llviewerobjectlist.h"
51#include "llviewerregion.h"
52#include "lscript_rt_interface.h"
53#include "llviewercontrol.h"
54#include "llviewerobject.h"
55#include "llviewerregion.h"
56#include "llresmgr.h"
57#include "llbutton.h"
58#include "lldir.h"
59#include "llfloaterchat.h"
60#include "llviewerstats.h"
61#include "lluictrlfactory.h"
62#include "llselectmgr.h"
63#include "llinventory.h"
64
65
66#include <algorithm>
67#include <functional>
68#include "llcachename.h"
69#include "lldbstrings.h"
70#include "llinventory.h"
71
72#include "llagent.h"
73#include "llbutton.h"
74#include "llcheckboxctrl.h"
75#include "llfloateravatarinfo.h"
76#include "llfloatergroupinfo.h"
77#include "llinventorymodel.h"
78#include "lllineeditor.h"
79#include "llradiogroup.h"
80#include "llresmgr.h"
81#include "roles_constants.h"
82#include "llselectmgr.h"
83#include "lltextbox.h"
84#include "lluiconstants.h"
85#include "llviewerinventory.h"
86#include "llviewerobjectlist.h"
87#include "llviewerregion.h"
88#include "llviewercontrol.h"
89
90#include "lluictrlfactory.h"
91
92
93const char* BULKPERM_QUEUE_TITLE = "Update Progress";
94const char* BULKPERM_START_STRING = "update";
95
96namespace
97{
98 struct BulkQueueObjects : public LLSelectedObjectFunctor
99 {
100 BOOL scripted;
101 BOOL modifiable;
102 LLFloaterBulkPermission* mQueue;
103 BulkQueueObjects(LLFloaterBulkPermission* q) : mQueue(q), scripted(FALSE), modifiable(FALSE) {}
104 virtual bool apply(LLViewerObject* obj)
105 {
106 scripted = obj->flagScripted();
107 modifiable = obj->permModify();
108
109 mQueue->addObject(obj->getID());
110 return false;
111
112 }
113 };
114}
115
116///----------------------------------------------------------------------------
117/// Class LLFloaterBulkPermission
118///----------------------------------------------------------------------------
119
120// static
121LLMap<LLUUID, LLFloaterBulkPermission*> LLFloaterBulkPermission::sInstances;
122
123
124// Default constructor
125LLFloaterBulkPermission::LLFloaterBulkPermission(const std::string& name,
126 const LLRect& rect,
127 const char* title,
128 const char* start_string) :
129 LLFloater(name, rect, title,
130 RESIZE_YES, DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT,
131 DRAG_ON_TOP, MINIMIZE_YES, CLOSE_YES)
132{
133
134 req_perm_mask=0; // This should match the default state the checkboxes are set to
135 recurse=false;
136
137 LLUICtrlFactory::getInstance()->buildFloater(this,"floater_bulk_perms.xml");
138
139 childSetAction("Apply...",onApplyBtn,this);
140 childSetEnabled("Apply...",TRUE);
141
142 childSetCommitCallback("Modify",&onCommitPermissions, this);
143 childSetCommitCallback("Trans",&onCommitPermissions, this);
144 childSetCommitCallback("Copy",&onCommitPermissions, this);
145
146 //childSetCommitCallback("Recurse",&onRecurse, this);
147
148 childSetCommitCallback("Parent",&onParent, this);
149
150 childSetCommitCallback("objects",&InvSelection, this);
151 childSetCommitCallback("scripts",&InvSelection, this);
152 childSetCommitCallback("textures",&InvSelection, this);
153 childSetCommitCallback("sounds",&InvSelection, this);
154 childSetCommitCallback("animations",&InvSelection, this);
155 childSetCommitCallback("notecards",&InvSelection, this);
156 childSetCommitCallback("landmarks",&InvSelection, this);
157 childSetCommitCallback("bodyparts",&InvSelection, this);
158 childSetCommitCallback("clothing",&InvSelection, this);
159 childSetCommitCallback("gestures",&InvSelection, this);
160
161 //Set variable state to XUI default state consistancy
162 processObject=getChild<LLCheckBoxCtrl>("objects")->get();
163 processScript=getChild<LLCheckBoxCtrl>("scripts")->get();
164 processTexture=getChild<LLCheckBoxCtrl>("textures")->get();
165 processSound=getChild<LLCheckBoxCtrl>("sounds")->get();
166 processAnimation=getChild<LLCheckBoxCtrl>("animations")->get();
167 processNotecard=getChild<LLCheckBoxCtrl>("notecards")->get();
168 processGesture=getChild<LLCheckBoxCtrl>("gestures")->get();
169 processClothing=getChild<LLCheckBoxCtrl>("clothing")->get();
170 processBodypart=getChild<LLCheckBoxCtrl>("bodyparts")->get();
171 processLandmark=getChild<LLCheckBoxCtrl>("landmarks")->get();
172 parent=getChild<LLCheckBoxCtrl>("Parent")->get();
173
174
175 setTitle(title);
176
177 if (!getHost())
178 {
179 LLRect curRect = getRect();
180 translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
181 }
182
183 mStartString = start_string;
184 mDone = FALSE;
185 sInstances.addData(mID, this);
186
187}
188
189void LLFloaterBulkPermission::doApply()
190{
191 // Its alive now do the nasty work that the ScriptQueue and friends try to do in the menu code
192 // but first grab the user options
193
194 LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
195 list->deleteAllItems();
196
197 //Apply to selected objects if requested first
198
199 if(parent)
200 {
201 llinfos<< "Setting permission on parent items" << llendl;
202 LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_NEXT_OWNER,true, req_perm_mask);
203 LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_NEXT_OWNER,false, ~req_perm_mask); //How annoying need to set and unset
204 }
205
206
207 LLFloaterBulkPermission* q;
208 q=(LLFloaterBulkPermission*)this;
209
210 BulkQueueObjects func(q);
211 bool fail = LLSelectMgr::getInstance()->getSelection()->applyToObjects(&func);
212 if(fail)
213 {
214 if ( !func.modifiable )
215 {
216 gViewerWindow->alertXml("NO MODIFY");
217 }
218 else
219 {
220 llwarns << "Bad logic. Are there actualy any items in that prim?" << llendl;
221 }
222 }
223 else
224 {
225 if (!q->start())
226 {
227 llwarns << "Unexpected failure attepmting to set permissions." << llendl;
228 }
229 }
230}
231
232// Destroys the object
233LLFloaterBulkPermission::~LLFloaterBulkPermission()
234{
235 sInstances.removeData(mID);
236}
237
238// find an instance by ID. Return NULL if it does not exist.
239// static
240LLFloaterBulkPermission* LLFloaterBulkPermission::findInstance(const LLUUID& id)
241{
242 if(sInstances.checkData(id))
243 {
244 return sInstances.getData(id);
245 }
246 return NULL;
247}
248
249
250// This is the callback method for the viewer object currently being
251// worked on.
252// NOT static, virtual!
253void LLFloaterBulkPermission::inventoryChanged(LLViewerObject* viewer_object,
254 InventoryObjectList* inv,
255 S32,
256 void* q_id)
257{
258 llinfos << "LLFloaterBulkPermission::inventoryChanged() for object "
259 << viewer_object->getID() << llendl;
260
261 //Remove this listener from the object since its
262 //listener callback is now being executed.
263
264 //We remove the listener here because the function
265 //removeVOInventoryListener removes the listener from a ViewerObject
266 //which it internally stores.
267
268 //If we call this further down in the function, calls to handleInventory
269 //and nextObject may update the interally stored viewer object causing
270 //the removal of the incorrect listener from an incorrect object.
271
272 //Fixes SL-6119:Recompile scripts fails to complete
273 removeVOInventoryListener();
274
275 if (viewer_object && inv && (viewer_object->getID() == mCurrentObjectID) )
276 {
277 handleInventory(viewer_object, inv);
278 }
279 else
280 {
281 // something went wrong...
282 // note that we're not working on this one, and move onto the
283 // next object in the list.
284 llwarns << "No inventory for " << mCurrentObjectID
285 << llendl;
286 nextObject();
287 }
288}
289
290void LLFloaterBulkPermission::onApplyBtn(void* user_data)
291{
292 LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)user_data;
293 self->doApply();
294}
295
296
297// static
298void LLFloaterBulkPermission::InvSelection(LLUICtrl* ctrl, void* data)
299{
300 LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)data;
301
302 self->processObject=self->getChild<LLCheckBoxCtrl>("objects")->get();
303 self->processScript=self->getChild<LLCheckBoxCtrl>("scripts")->get();
304 self->processTexture=self->getChild<LLCheckBoxCtrl>("textures")->get();
305 self->processSound=self->getChild<LLCheckBoxCtrl>("sounds")->get();
306 self->processAnimation=self->getChild<LLCheckBoxCtrl>("animations")->get();
307 self->processNotecard=self->getChild<LLCheckBoxCtrl>("notecards")->get();
308 self->processGesture=self->getChild<LLCheckBoxCtrl>("gestures")->get();
309 self->processClothing=self->getChild<LLCheckBoxCtrl>("clothing")->get();
310 self->processBodypart=self->getChild<LLCheckBoxCtrl>("bodyparts")->get();
311 self->processLandmark=self->getChild<LLCheckBoxCtrl>("landmarks")->get();
312
313
314}
315
316// static
317void LLFloaterBulkPermission::onParent(LLUICtrl* ctrl, void* data)
318{
319 LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)data;
320 self->parent=self->getChild<LLCheckBoxCtrl>("Parent")->get();
321}
322
323// static
324void LLFloaterBulkPermission::onRecurse(LLUICtrl* ctrl, void* data)
325{
326 LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)data;
327 self->recurse=self->getChild<LLCheckBoxCtrl>("Recurse")->get();
328}
329
330// static
331void LLFloaterBulkPermission::onCommitPermissions(LLUICtrl* ctrl, void* data)
332{
333 LLFloaterBulkPermission* self = (LLFloaterBulkPermission*)data;
334 LLCheckBoxCtrl* CheckModify = self->getChild<LLCheckBoxCtrl>("Modify");
335 LLCheckBoxCtrl* CheckCopy = self->getChild<LLCheckBoxCtrl>("Copy");
336 LLCheckBoxCtrl* CheckTrans = self->getChild<LLCheckBoxCtrl>("Trans");
337
338 self->req_perm_mask=0;
339
340 if(CheckModify->get())
341 {
342 self->req_perm_mask|=PERM_MODIFY;
343 }
344 else
345 {
346 self->req_perm_mask&=~PERM_MODIFY;
347 }
348
349 if(CheckCopy->get())
350 {
351 self->req_perm_mask|=PERM_COPY;
352 }
353 else
354 {
355 self->req_perm_mask&=~PERM_COPY;
356 }
357
358 if(CheckTrans->get())
359 {
360 self->req_perm_mask|=PERM_TRANSFER;
361 }
362 else
363 {
364 self->req_perm_mask&=~PERM_TRANSFER;
365 }
366
367
368}
369
370void LLFloaterBulkPermission::addObject(const LLUUID& id)
371{
372 mObjectIDs.put(id);
373}
374
375BOOL LLFloaterBulkPermission::start()
376{
377 llinfos << "LLFloaterBulkPermission::start()" << llendl;
378 char buffer[MAX_STRING]; /*Flawfinder: ignore*/
379 snprintf(buffer, sizeof(buffer), "Starting %s of %d items.", mStartString, mObjectIDs.count()); /* Flawfinder: ignore */
380
381 LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
382 list->addCommentText(buffer);
383
384 return nextObject();
385}
386
387BOOL LLFloaterBulkPermission::isDone() const
388{
389 return (mCurrentObjectID.isNull() || (mObjectIDs.count() == 0));
390}
391
392// go to the next object. If no objects left, it falls out silently
393// and waits to be killed by the window being closed.
394BOOL LLFloaterBulkPermission::nextObject()
395{
396 S32 count;
397 BOOL successful_start = FALSE;
398 do
399 {
400 count = mObjectIDs.count();
401 llinfos << "LLFloaterBulkPermission::nextObject() - " << count
402 << " objects left to process." << llendl;
403 mCurrentObjectID.setNull();
404 if(count > 0)
405 {
406 successful_start = popNext();
407 }
408 llinfos << "LLFloaterBulkPermission::nextObject() "
409 << (successful_start ? "successful" : "unsuccessful")
410 << llendl;
411 } while((mObjectIDs.count() > 0) && !successful_start);
412
413 if(isDone() && !mDone)
414 {
415
416 LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
417 mDone = TRUE;
418 char buffer[MAX_STRING]; /*Flawfinder: ignore*/
419 snprintf(buffer, sizeof(buffer), "Done."); /* Flawfinder: ignore */
420 list->addCommentText(buffer);
421
422 }
423 return successful_start;
424}
425
426// returns true if the queue has started, otherwise false. This
427// method pops the top object off of the queue.
428BOOL LLFloaterBulkPermission::popNext()
429{
430 // get the first element off of the container, and attempt to get
431 // the inventory.
432 BOOL rv = FALSE;
433 S32 count = mObjectIDs.count();
434 if(mCurrentObjectID.isNull() && (count > 0))
435 {
436 mCurrentObjectID = mObjectIDs.get(0);
437 llinfos << "LLFloaterBulkPermission::popNext() - mCurrentID: "
438 << mCurrentObjectID << llendl;
439 mObjectIDs.remove(0);
440 LLViewerObject* obj = gObjectList.findObject(mCurrentObjectID);
441 if(obj)
442 {
443 llinfos << "LLFloaterBulkPermission::popNext() requesting inv for "
444 << mCurrentObjectID << llendl;
445 LLUUID* id = new LLUUID(mID);
446
447 registerVOInventoryListener(obj,id);
448 requestVOInventory();
449 rv = TRUE;
450 }
451 else
452 {
453 llinfos<<"LLFloaterBulkPermission::popNext() returned a NULL LLViewerObject" <<llendl;
454 //Arrrg what do we do here?
455 }
456 }
457
458 return rv;
459}
460
461
462// static
463LLFloaterBulkPermission* LLFloaterBulkPermission::create()
464{
465 S32 left, top;
466 gFloaterView->getNewFloaterPosition(&left, &top);
467 LLRect rect = gSavedSettings.getRect("CompileOutputRect");
468 rect.translate(left - rect.mLeft, top - rect.mTop);
469 LLFloaterBulkPermission* new_queue = new LLFloaterBulkPermission("queue",rect,"Setting Bulk permissions","Results");
470 new_queue->open(); /*Flawfinder: ignore*/
471 return new_queue;
472}
473
474
475void LLFloaterBulkPermission::handleInventory(LLViewerObject* viewer_obj, InventoryObjectList* inv)
476{
477 // find all of the lsl, leaving off duplicates. We'll remove
478 // all matching asset uuids on compilation success.
479
480 llinfos<<"handleInventory"<<llendl;
481
482 char buffer[MAX_STRING]; /*Flawfinder: ignore*/
483 LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
484
485 InventoryObjectList::const_iterator it = inv->begin();
486 InventoryObjectList::const_iterator end = inv->end();
487 for ( ; it != end; ++it)
488 {
489 llinfos<<"Doing iterator of inventory"<<llendl;
490
491 if( ( (*it)->getType() == LLAssetType::AT_LSL_TEXT && processScript) ||
492 ( (*it)->getType() == LLAssetType::AT_TEXTURE && processTexture) ||
493 ( (*it)->getType() == LLAssetType::AT_SOUND && processSound) ||
494 ( (*it)->getType() == LLAssetType::AT_LANDMARK && processLandmark) ||
495 ( (*it)->getType() == LLAssetType::AT_CLOTHING && processClothing) ||
496 ( (*it)->getType() == LLAssetType::AT_OBJECT && processObject) ||
497 ( (*it)->getType() == LLAssetType::AT_NOTECARD && processNotecard) ||
498 ( (*it)->getType() == LLAssetType::AT_BODYPART && processBodypart) ||
499 ( (*it)->getType() == LLAssetType::AT_ANIMATION && processAnimation) ||
500 ( (*it)->getType() == LLAssetType::AT_GESTURE && processGesture))
501 {
502
503 LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
504
505 if (object)
506 {
507 LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
508 LLViewerInventoryItem* new_item = (LLViewerInventoryItem*)item;
509 LLPermissions perm(new_item->getPermissions());
510
511 // chomp the inventory name so it fits in the scroll window nicely
512 // and the user can see the [OK]
513 std::string invname;
514 invname=item->getName().substr(0,item->getName().size() < 30 ? item->getName().size() : 30 );
515
516 // My attempt at checking valid permissions, CHECK ME
517 // note its not actually bad to try to set permissions that are not allowed as the
518 // server will protect against this, but it will piss the user off if its wrong
519 if(
520 (perm.getCreator()==gAgentID) ||
521 (perm.getMaskOwner() & PERM_TRANSFER) && (perm.getMaskOwner() & PERM_MODIFY) ||
522 (gAgent.getGroupID()==perm.getGroup() && (perm.getMaskGroup() & PERM_TRANSFER) && (perm.getMaskGroup() & PERM_MODIFY))
523 ){
524 llinfos<<"Setting perms"<<llendl;
525 perm.setMaskNext(req_perm_mask);
526 new_item->setPermissions(perm);
527 updateInventory(object,new_item,TASK_INVENTORY_ITEM_KEY,FALSE);
528 snprintf(buffer, sizeof(buffer), "Setting perms on '%s' [OK]", invname.c_str()); /* Flawfinder: ignore */
529 }
530 else
531 {
532 llinfos<<"NOT setting perms"<<llendl;
533 snprintf(buffer, sizeof(buffer), "Setting perms on '%s' [FAILED]", invname.c_str()); /* Flawfinder: ignore */
534
535 }
536
537 list->addCommentText(buffer);
538
539 if(recurse && ( (*it)->getType() == LLAssetType::AT_OBJECT && processObject))
540 {
541 //Add this object back to the queue to be processed as it has inventory
542 snprintf(buffer, sizeof(buffer), "Queueing object '%s' for open", invname.c_str());
543 llwarns << "Queueing object "<< invname.c_str() << " ID "<< (*it)->getUUID()<<llendl;
544 mObjectIDs.put((*it)->getUUID());
545 // This will not YET work. as this is not a viewer object the unpack will fail
546 }
547
548 }
549 }
550 }
551
552 nextObject();
553}
554
555
556// Avoid inventory callbacks etc by just fire and forgetting the message with the permissions update
557// we could do this via LLViewerObject::updateInventory but that uses inventory call backs and buggers
558// us up and we would have a dodgy item iterator
559
560void LLFloaterBulkPermission::updateInventory(
561 LLViewerObject* object,
562 LLViewerInventoryItem* item,
563 U8 key,
564 bool is_new)
565{
566 LLMemType mt(LLMemType::MTYPE_OBJECT);
567
568
569 // This slices the object into what we're concerned about on the
570 // viewer. The simulator will take the permissions and transfer
571 // ownership.
572 LLPointer<LLViewerInventoryItem> task_item =
573 new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(),
574 item->getAssetUUID(), item->getType(),
575 item->getInventoryType(),
576 item->getName(), item->getDescription(),
577 item->getSaleInfo(),
578 item->getFlags(),
579 item->getCreationDate());
580 task_item->setTransactionID(item->getTransactionID());
581 LLMessageSystem* msg = gMessageSystem;
582 msg->newMessageFast(_PREHASH_UpdateTaskInventory);
583 msg->nextBlockFast(_PREHASH_AgentData);
584 msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
585 msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
586 msg->nextBlockFast(_PREHASH_UpdateData);
587 msg->addU32Fast(_PREHASH_LocalID, object->mLocalID);
588 msg->addU8Fast(_PREHASH_Key, key);
589 msg->nextBlockFast(_PREHASH_InventoryData);
590 task_item->packMessage(msg);
591 msg->sendReliable(object->getRegion()->getHost());
592
593}
594