llinventoryview.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 #include <utility> // for std::pair<>
00035 
00036 #include "llinventoryview.h"
00037 #include "llinventorybridge.h"
00038 
00039 #include "message.h"
00040 
00041 #include "llagent.h"
00042 #include "llcallingcard.h"
00043 #include "llcheckboxctrl.h"             // for radio buttons
00044 #include "llradiogroup.h"
00045 #include "llspinctrl.h"
00046 #include "lltextbox.h"
00047 #include "llui.h"
00048 
00049 #include "llfirstuse.h"
00050 #include "llfloateravatarinfo.h"
00051 #include "llfloaterchat.h"
00052 #include "llfloatercustomize.h"
00053 #include "llfocusmgr.h"
00054 #include "llfolderview.h"
00055 #include "llgesturemgr.h"
00056 #include "lliconctrl.h"
00057 #include "llinventorymodel.h"
00058 #include "llinventoryclipboard.h"
00059 #include "lllineeditor.h"
00060 #include "llmenugl.h"
00061 #include "llpreviewanim.h"
00062 #include "llpreviewgesture.h"
00063 #include "llpreviewlandmark.h"
00064 #include "llpreviewnotecard.h"
00065 #include "llpreviewscript.h"
00066 #include "llpreviewsound.h"
00067 #include "llpreviewtexture.h"
00068 #include "llresmgr.h"
00069 #include "llscrollcontainer.h"
00070 #include "llscrollbar.h"
00071 #include "llimview.h"
00072 #include "lltooldraganddrop.h"
00073 #include "llviewerimagelist.h"
00074 #include "llviewerinventory.h"
00075 #include "llviewerobjectlist.h"
00076 #include "llviewerwindow.h"
00077 #include "llwearablelist.h"
00078 #include "llappviewer.h"
00079 #include "llviewermessage.h"
00080 #include "llviewerregion.h"
00081 #include "lltabcontainer.h"
00082 #include "lluictrlfactory.h"
00083 #include "llselectmgr.h"
00084 
00085 #include "llsdserialize.h"
00086 
00087 static LLRegisterWidget<LLInventoryPanel> r("inventory_panel");
00088 
00089 LLDynamicArray<LLInventoryView*> LLInventoryView::sActiveViews;
00090 
00091 //BOOL LLInventoryView::sOpenNextNewItem = FALSE;
00092 BOOL LLInventoryView::sWearNewClothing = FALSE;
00093 LLUUID LLInventoryView::sWearNewClothingTransactionID;
00094 
00098 
00099 const S32 INV_MIN_WIDTH = 240;
00100 const S32 INV_MIN_HEIGHT = 150;
00101 const S32 INV_FINDER_WIDTH = 160;
00102 const S32 INV_FINDER_HEIGHT = 408;
00103 
00107 
00108 LLInventoryViewFinder::LLInventoryViewFinder(const LLString& name,
00109                                                 const LLRect& rect,
00110                                                 LLInventoryView* inventory_view) :
00111         LLFloater(name, rect, "Filters", RESIZE_NO,
00112                                 INV_FINDER_WIDTH, INV_FINDER_HEIGHT, DRAG_ON_TOP,
00113                                 MINIMIZE_NO, CLOSE_YES),
00114         mInventoryView(inventory_view),
00115         mFilter(inventory_view->mActivePanel->getFilter())
00116 {
00117 
00118         LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory_view_finder.xml");
00119 
00120         childSetAction("All", selectAllTypes, this);
00121         childSetAction("None", selectNoTypes, this);
00122 
00123         mSpinSinceHours = getChild<LLSpinCtrl>("spin_hours_ago");
00124         childSetCommitCallback("spin_hours_ago", onTimeAgo, this);
00125 
00126         mSpinSinceDays = getChild<LLSpinCtrl>("spin_days_ago");
00127         childSetCommitCallback("spin_days_ago", onTimeAgo, this);
00128 
00129 //      mCheckSinceLogoff   = getChild<LLSpinCtrl>("check_since_logoff");
00130         childSetCommitCallback("check_since_logoff", onCheckSinceLogoff, this);
00131 
00132         childSetAction("Close", onCloseBtn, this);
00133 
00134         updateElementsFromFilter();
00135 }
00136 
00137 
00138 void LLInventoryViewFinder::onCheckSinceLogoff(LLUICtrl *ctrl, void *user_data)
00139 {
00140         LLInventoryViewFinder *self = (LLInventoryViewFinder *)user_data;
00141         if (!self) return;
00142 
00143         bool since_logoff= self->childGetValue("check_since_logoff");
00144         
00145         if (!since_logoff && 
00146             !(  self->mSpinSinceDays->get() ||  self->mSpinSinceHours->get() ) )
00147         {
00148                 self->mSpinSinceHours->set(1.0f);
00149         }       
00150 }
00151 
00152 void LLInventoryViewFinder::onTimeAgo(LLUICtrl *ctrl, void *user_data)
00153 {
00154         LLInventoryViewFinder *self = (LLInventoryViewFinder *)user_data;
00155         if (!self) return;
00156         
00157         bool since_logoff=true;
00158         if ( self->mSpinSinceDays->get() ||  self->mSpinSinceHours->get() )
00159         {
00160                 since_logoff = false;
00161         }
00162         self->childSetValue("check_since_logoff", since_logoff);
00163 }
00164 
00165 void LLInventoryViewFinder::changeFilter(LLInventoryFilter* filter)
00166 {
00167         mFilter = filter;
00168         updateElementsFromFilter();
00169 }
00170 
00171 void LLInventoryViewFinder::updateElementsFromFilter()
00172 {
00173         if (!mFilter)
00174                 return;
00175 
00176         // Get data needed for filter display
00177         U32 filter_types = mFilter->getFilterTypes();
00178         LLString filter_string = mFilter->getFilterSubString();
00179         LLInventoryFilter::EFolderShow show_folders = mFilter->getShowFolderState();
00180         U32 hours = mFilter->getHoursAgo();
00181 
00182         // update the ui elements
00183         LLFloater::setTitle(mFilter->getName());
00184         childSetValue("check_animation", (S32) (filter_types & 0x1 << LLInventoryType::IT_ANIMATION));
00185 
00186         childSetValue("check_calling_card", (S32) (filter_types & 0x1 << LLInventoryType::IT_CALLINGCARD));
00187         childSetValue("check_clothing", (S32) (filter_types & 0x1 << LLInventoryType::IT_WEARABLE));
00188         childSetValue("check_gesture", (S32) (filter_types & 0x1 << LLInventoryType::IT_GESTURE));
00189         childSetValue("check_landmark", (S32) (filter_types & 0x1 << LLInventoryType::IT_LANDMARK));
00190         childSetValue("check_notecard", (S32) (filter_types & 0x1 << LLInventoryType::IT_NOTECARD));
00191         childSetValue("check_object", (S32) (filter_types & 0x1 << LLInventoryType::IT_OBJECT));
00192         childSetValue("check_script", (S32) (filter_types & 0x1 << LLInventoryType::IT_LSL));
00193         childSetValue("check_sound", (S32) (filter_types & 0x1 << LLInventoryType::IT_SOUND));
00194         childSetValue("check_texture", (S32) (filter_types & 0x1 << LLInventoryType::IT_TEXTURE));
00195         childSetValue("check_snapshot", (S32) (filter_types & 0x1 << LLInventoryType::IT_SNAPSHOT));
00196         childSetValue("check_show_empty", show_folders == LLInventoryFilter::SHOW_ALL_FOLDERS);
00197         childSetValue("check_since_logoff", mFilter->isSinceLogoff());
00198         mSpinSinceHours->set((F32)(hours % 24));
00199         mSpinSinceDays->set((F32)(hours / 24));
00200 }
00201 
00202 void LLInventoryViewFinder::draw()
00203 {
00204         U32 filter = 0xffffffff;
00205         BOOL filtered_by_all_types = TRUE;
00206 
00207         if (!childGetValue("check_animation"))
00208         {
00209                 filter &= ~(0x1 << LLInventoryType::IT_ANIMATION);
00210                 filtered_by_all_types = FALSE;
00211         }
00212 
00213 
00214         if (!childGetValue("check_calling_card"))
00215         {
00216                 filter &= ~(0x1 << LLInventoryType::IT_CALLINGCARD);
00217                 filtered_by_all_types = FALSE;
00218         }
00219 
00220         if (!childGetValue("check_clothing"))
00221         {
00222                 filter &= ~(0x1 << LLInventoryType::IT_WEARABLE);
00223                 filtered_by_all_types = FALSE;
00224         }
00225 
00226         if (!childGetValue("check_gesture"))
00227         {
00228                 filter &= ~(0x1 << LLInventoryType::IT_GESTURE);
00229                 filtered_by_all_types = FALSE;
00230         }
00231 
00232         if (!childGetValue("check_landmark"))
00233 
00234 
00235         {
00236                 filter &= ~(0x1 << LLInventoryType::IT_LANDMARK);
00237                 filtered_by_all_types = FALSE;
00238         }
00239 
00240         if (!childGetValue("check_notecard"))
00241         {
00242                 filter &= ~(0x1 << LLInventoryType::IT_NOTECARD);
00243                 filtered_by_all_types = FALSE;
00244         }
00245 
00246         if (!childGetValue("check_object"))
00247         {
00248                 filter &= ~(0x1 << LLInventoryType::IT_OBJECT);
00249                 filter &= ~(0x1 << LLInventoryType::IT_ATTACHMENT);
00250                 filtered_by_all_types = FALSE;
00251         }
00252 
00253         if (!childGetValue("check_script"))
00254         {
00255                 filter &= ~(0x1 << LLInventoryType::IT_LSL);
00256                 filtered_by_all_types = FALSE;
00257         }
00258 
00259         if (!childGetValue("check_sound"))
00260         {
00261                 filter &= ~(0x1 << LLInventoryType::IT_SOUND);
00262                 filtered_by_all_types = FALSE;
00263         }
00264 
00265         if (!childGetValue("check_texture"))
00266         {
00267                 filter &= ~(0x1 << LLInventoryType::IT_TEXTURE);
00268                 filtered_by_all_types = FALSE;
00269         }
00270 
00271         if (!childGetValue("check_snapshot"))
00272         {
00273                 filter &= ~(0x1 << LLInventoryType::IT_SNAPSHOT);
00274                 filtered_by_all_types = FALSE;
00275         }
00276 
00277         if (!filtered_by_all_types)
00278         {
00279                 // don't include folders in filter, unless I've selected everything
00280                 filter &= ~(0x1 << LLInventoryType::IT_CATEGORY);
00281         }
00282 
00283         // update the panel, panel will update the filter
00284         mInventoryView->mActivePanel->setShowFolderState(getCheckShowEmpty() ?
00285                 LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
00286         mInventoryView->mActivePanel->setFilterTypes(filter);
00287         if (getCheckSinceLogoff())
00288         {
00289                 mSpinSinceDays->set(0);
00290                 mSpinSinceHours->set(0);
00291         }
00292         U32 days = (U32)mSpinSinceDays->get();
00293         U32 hours = (U32)mSpinSinceHours->get();
00294         if (hours > 24)
00295         {
00296                 days += hours / 24;
00297                 hours = (U32)hours % 24;
00298                 mSpinSinceDays->set((F32)days);
00299                 mSpinSinceHours->set((F32)hours);
00300         }
00301         hours += days * 24;
00302         mInventoryView->mActivePanel->setHoursAgo(hours);
00303         mInventoryView->mActivePanel->setSinceLogoff(getCheckSinceLogoff());
00304         mInventoryView->setFilterTextFromFilter();
00305 
00306         LLFloater::draw();
00307 }
00308 
00309 void  LLInventoryViewFinder::onClose(bool app_quitting)
00310 {
00311         if (mInventoryView) mInventoryView->getControl("Inventory.ShowFilters")->setValue(FALSE);
00312         // If you want to reset the filter on close, do it here.  This functionality was
00313         // hotly debated - Paulm
00314 #if 0
00315         if (mInventoryView)
00316         {
00317                 LLInventoryView::onResetFilter((void *)mInventoryView);
00318         }
00319 #endif
00320         destroy();
00321 }
00322 
00323 
00324 BOOL LLInventoryViewFinder::getCheckShowEmpty()
00325 {
00326         return childGetValue("check_show_empty");
00327 }
00328 
00329 BOOL LLInventoryViewFinder::getCheckSinceLogoff()
00330 {
00331         return childGetValue("check_since_logoff");
00332 }
00333 
00334 void LLInventoryViewFinder::onCloseBtn(void* user_data)
00335 {
00336         LLInventoryViewFinder* finderp = (LLInventoryViewFinder*)user_data;
00337         finderp->close();
00338 }
00339 
00340 // static
00341 void LLInventoryViewFinder::selectAllTypes(void* user_data)
00342 {
00343         LLInventoryViewFinder* self = (LLInventoryViewFinder*)user_data;
00344         if(!self) return;
00345 
00346         self->childSetValue("check_animation", TRUE);
00347         self->childSetValue("check_calling_card", TRUE);
00348         self->childSetValue("check_clothing", TRUE);
00349         self->childSetValue("check_gesture", TRUE);
00350         self->childSetValue("check_landmark", TRUE);
00351         self->childSetValue("check_notecard", TRUE);
00352         self->childSetValue("check_object", TRUE);
00353         self->childSetValue("check_script", TRUE);
00354         self->childSetValue("check_sound", TRUE);
00355         self->childSetValue("check_texture", TRUE);
00356         self->childSetValue("check_snapshot", TRUE);
00357 
00358 /*
00359         self->mCheckCallingCard->set(TRUE);
00360         self->mCheckClothing->set(TRUE);
00361         self->mCheckGesture->set(TRUE);
00362         self->mCheckLandmark->set(TRUE);
00363         self->mCheckNotecard->set(TRUE);
00364         self->mCheckObject->set(TRUE);
00365         self->mCheckScript->set(TRUE);
00366         self->mCheckSound->set(TRUE);
00367         self->mCheckTexture->set(TRUE);
00368         self->mCheckSnapshot->set(TRUE);*/
00369 }
00370 
00371 //static
00372 void LLInventoryViewFinder::selectNoTypes(void* user_data)
00373 {
00374         LLInventoryViewFinder* self = (LLInventoryViewFinder*)user_data;
00375         if(!self) return;
00376 
00377         /*
00378         self->childSetValue("check_animation", FALSE);
00379         self->mCheckCallingCard->set(FALSE);
00380         self->mCheckClothing->set(FALSE);
00381         self->mCheckGesture->set(FALSE);
00382         self->mCheckLandmark->set(FALSE);
00383         self->mCheckNotecard->set(FALSE);
00384         self->mCheckObject->set(FALSE);
00385         self->mCheckScript->set(FALSE);
00386         self->mCheckSound->set(FALSE);
00387         self->mCheckTexture->set(FALSE);
00388         self->mCheckSnapshot->set(FALSE);*/
00389 
00390 
00391         self->childSetValue("check_animation", FALSE);
00392         self->childSetValue("check_calling_card", FALSE);
00393         self->childSetValue("check_clothing", FALSE);
00394         self->childSetValue("check_gesture", FALSE);
00395         self->childSetValue("check_landmark", FALSE);
00396         self->childSetValue("check_notecard", FALSE);
00397         self->childSetValue("check_object", FALSE);
00398         self->childSetValue("check_script", FALSE);
00399         self->childSetValue("check_sound", FALSE);
00400         self->childSetValue("check_texture", FALSE);
00401         self->childSetValue("check_snapshot", FALSE);
00402 }
00403 
00404 
00408 void LLSaveFolderState::setApply(BOOL apply)
00409 {
00410         mApply = apply; 
00411         // before generating new list of open folders, clear the old one
00412         if(!apply) 
00413         {
00414                 clearOpenFolders(); 
00415         }
00416 }
00417 
00418 void LLSaveFolderState::doFolder(LLFolderViewFolder* folder)
00419 {
00420         if(mApply)
00421         {
00422                 // we're applying the open state
00423                 LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
00424                 if(!bridge) return;
00425                 LLUUID id(bridge->getUUID());
00426                 if(mOpenFolders.find(id) != mOpenFolders.end())
00427                 {
00428                         folder->setOpen(TRUE);
00429                 }
00430                 else
00431                 {
00432                         // keep selected filter in its current state, this is less jarring to user
00433                         if (!folder->isSelected())
00434                         {
00435                                 folder->setOpen(FALSE);
00436                         }
00437                 }
00438         }
00439         else
00440         {
00441                 // we're recording state at this point
00442                 if(folder->isOpen())
00443                 {
00444                         LLInvFVBridge* bridge = (LLInvFVBridge*)folder->getListener();
00445                         if(!bridge) return;
00446                         mOpenFolders.insert(bridge->getUUID());
00447                 }
00448         }
00449 }
00450 
00451 // Default constructor
00452 LLInventoryView::LLInventoryView(const LLString& name,
00453                                                                  const LLString& rect,
00454                                                                  LLInventoryModel* inventory) :
00455         LLFloater(name, rect, "Inventory", RESIZE_YES,
00456                           INV_MIN_WIDTH, INV_MIN_HEIGHT, DRAG_ON_TOP,
00457                           MINIMIZE_NO, CLOSE_YES)
00458         //LLHandle<LLFloater> mFinderHandle takes care of its own initialization
00459 {
00460         init(inventory);
00461 }
00462 
00463 LLInventoryView::LLInventoryView(const LLString& name,
00464                                                                  const LLRect& rect,
00465                                                                  LLInventoryModel* inventory) :
00466         LLFloater(name, rect, "Inventory", RESIZE_YES,
00467                           INV_MIN_WIDTH, INV_MIN_HEIGHT, DRAG_ON_TOP,
00468                           MINIMIZE_NO, CLOSE_YES)
00469         //LLHandle<LLFloater> mFinderHandle takes care of its own initialization
00470 {
00471         init(inventory);
00472         setRect(rect); // override XML
00473 }
00474 
00475 
00476 void LLInventoryView::init(LLInventoryModel* inventory)
00477 {
00478         // Callbacks
00479         init_inventory_actions(this);
00480 
00481         // Controls
00482         U32 sort_order = gSavedSettings.getU32("InventorySortOrder");
00483         BOOL sort_by_name = ! ( sort_order & LLInventoryFilter::SO_DATE );
00484         BOOL sort_folders_by_name = ( sort_order & LLInventoryFilter::SO_FOLDERS_BY_NAME );
00485         BOOL sort_system_folders_to_top = ( sort_order & LLInventoryFilter::SO_SYSTEM_FOLDERS_TO_TOP );
00486 
00487         addBoolControl("Inventory.ShowFilters", FALSE);
00488         addBoolControl("Inventory.SortByName", sort_by_name );
00489         addBoolControl("Inventory.SortByDate", ! sort_by_name );
00490         addBoolControl("Inventory.FoldersAlwaysByName", sort_folders_by_name );
00491         addBoolControl("Inventory.SystemFoldersToTop", sort_system_folders_to_top );
00492 
00493         mSavedFolderState = new LLSaveFolderState();
00494         mSavedFolderState->setApply(FALSE);
00495 
00496         LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory.xml", NULL);
00497 
00498         mFilterTabs = (LLTabContainer*)getChild<LLTabContainer>("inventory filter tabs");
00499 
00500         // Set up the default inv. panel/filter settings.
00501         mActivePanel = getChild<LLInventoryPanel>("All Items");
00502         if (mActivePanel)
00503         {
00504                 // "All Items" is the previous only view, so it gets the InventorySortOrder
00505                 mActivePanel->setSortOrder(gSavedSettings.getU32("InventorySortOrder"));
00506                 mActivePanel->getFilter()->markDefault();
00507                 mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
00508                 mActivePanel->setSelectCallback(onSelectionChange, mActivePanel);
00509         }
00510         LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items");
00511         if (recent_items_panel)
00512         {
00513                 recent_items_panel->setSinceLogoff(TRUE);
00514                 recent_items_panel->setSortOrder(LLInventoryFilter::SO_DATE);
00515                 recent_items_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
00516                 recent_items_panel->getFilter()->markDefault();
00517                 recent_items_panel->setSelectCallback(onSelectionChange, recent_items_panel);
00518         }
00519 
00520         // Now load the stored settings from disk, if available.
00521         std::ostringstream filterSaveName;
00522         filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml");
00523         llinfos << "LLInventoryView::init: reading from " << filterSaveName << llendl;
00524     llifstream file(filterSaveName.str().c_str());
00525         LLSD savedFilterState;
00526     if (file.is_open())
00527     {
00528         LLSDSerialize::fromXML(savedFilterState, file);
00529                 file.close();
00530 
00531                 // Load the persistent "Recent Items" settings.
00532                 // Note that the "All Items" settings do not persist.
00533                 if(recent_items_panel)
00534                 {
00535                         if(savedFilterState.has(recent_items_panel->getFilter()->getName()))
00536                         {
00537                                 LLSD recent_items = savedFilterState.get(
00538                                         recent_items_panel->getFilter()->getName());
00539                                 recent_items_panel->getFilter()->fromLLSD(recent_items);
00540                         }
00541                 }
00542 
00543     }
00544 
00545 
00546         mSearchEditor = getChild<LLSearchEditor>("inventory search editor");
00547         if (mSearchEditor)
00548         {
00549                 mSearchEditor->setSearchCallback(onSearchEdit, this);
00550         }
00551 
00552         sActiveViews.put(this);
00553 
00554         gInventory.addObserver(this);
00555 }
00556 
00557 BOOL LLInventoryView::postBuild()
00558 {
00559         childSetTabChangeCallback("inventory filter tabs", "All Items", onFilterSelected, this);
00560         childSetTabChangeCallback("inventory filter tabs", "Recent Items", onFilterSelected, this);
00561         //panel->getFilter()->markDefault();
00562         return TRUE;
00563 }
00564 
00565 // Destroys the object
00566 LLInventoryView::~LLInventoryView( void )
00567 {
00568         // Save the filters state.
00569         LLSD filterRoot;
00570         LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>("All Items");
00571         if (all_items_panel)
00572         {
00573                 LLInventoryFilter* filter = all_items_panel->getFilter();
00574                 LLSD filterState;
00575                 filter->toLLSD(filterState);
00576                 filterRoot[filter->getName()] = filterState;
00577         }
00578 
00579         LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items");
00580         if (recent_items_panel)
00581         {
00582                 LLInventoryFilter* filter = recent_items_panel->getFilter();
00583                 LLSD filterState;
00584                 filter->toLLSD(filterState);
00585                 filterRoot[filter->getName()] = filterState;
00586         }
00587 
00588         std::ostringstream filterSaveName;
00589         filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml");
00590         llofstream filtersFile(filterSaveName.str().c_str());
00591         if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile))
00592         {
00593                 llwarns << "Could not write to filters save file " << filterSaveName << llendl;
00594         }
00595         else
00596                 filtersFile.close();
00597 
00598         sActiveViews.removeObj(this);
00599         gInventory.removeObserver(this);
00600         delete mSavedFolderState;
00601 }
00602 
00603 void LLInventoryView::draw()
00604 {
00605         if (LLInventoryModel::isEverythingFetched())
00606         {
00607                 LLLocale locale(LLLocale::USER_LOCALE);
00608                 std::ostringstream title;
00609                 title << "Inventory";
00610                 LLString item_count_string;
00611                 LLResMgr::getInstance()->getIntegerString(item_count_string, gInventory.getItemCount());
00612                 title << " (" << item_count_string << " items)";
00613                 title << mFilterText;
00614                 setTitle(title.str());
00615         }
00616         if (mActivePanel && mSearchEditor)
00617         {
00618                 mSearchEditor->setText(mActivePanel->getFilterSubString());
00619         }
00620         LLFloater::draw();
00621 }
00622 
00623 void LLOpenFilteredFolders::doItem(LLFolderViewItem *item)
00624 {
00625         if (item->getFiltered())
00626         {
00627                 item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
00628         }
00629 }
00630 
00631 void LLOpenFilteredFolders::doFolder(LLFolderViewFolder* folder)
00632 {
00633         if (folder->getFiltered() && folder->getParentFolder())
00634         {
00635                 folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
00636         }
00637         // if this folder didn't pass the filter, and none of its descendants did
00638         else if (!folder->getFiltered() && !folder->hasFilteredDescendants())
00639         {
00640                 folder->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_NO);
00641         }
00642 }
00643 
00644 void LLSelectFirstFilteredItem::doItem(LLFolderViewItem *item)
00645 {
00646         if (item->getFiltered() && !mItemSelected)
00647         {
00648                 item->getRoot()->setSelection(item, FALSE, FALSE);
00649                 if (item->getParentFolder())
00650                 {
00651                         item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
00652                 }
00653                 item->getRoot()->scrollToShowSelection();
00654                 mItemSelected = TRUE;
00655         }
00656 }
00657 
00658 void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder)
00659 {
00660         if (folder->getFiltered() && !mItemSelected)
00661         {
00662                 folder->getRoot()->setSelection(folder, FALSE, FALSE);
00663                 if (folder->getParentFolder())
00664                 {
00665                         folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
00666                 }
00667                 folder->getRoot()->scrollToShowSelection();
00668                 mItemSelected = TRUE;
00669         }
00670 }
00671 
00672 void LLOpenFoldersWithSelection::doItem(LLFolderViewItem *item)
00673 {
00674         if (item->getParentFolder() && item->isSelected())
00675         {
00676                 item->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
00677         }
00678 }
00679 
00680 void LLOpenFoldersWithSelection::doFolder(LLFolderViewFolder* folder)
00681 {
00682         if (folder->getParentFolder() && folder->isSelected())
00683         {
00684                 folder->getParentFolder()->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
00685         }
00686 }
00687 
00688 void LLInventoryView::startSearch()
00689 {
00690         // this forces focus to line editor portion of search editor
00691         if (mSearchEditor)
00692         {
00693                 mSearchEditor->focusFirstItem(TRUE);
00694         }
00695 }
00696 
00697 // virtual, from LLView
00698 void LLInventoryView::setVisible( BOOL visible )
00699 {
00700         gSavedSettings.setBOOL("ShowInventory", visible);
00701         LLFloater::setVisible(visible);
00702 }
00703 
00704 // Destroy all but the last floater, which is made invisible.
00705 void LLInventoryView::onClose(bool app_quitting)
00706 {
00707         S32 count = sActiveViews.count();
00708         if (count > 1)
00709         {
00710                 destroy();
00711         }
00712         else
00713         {
00714                 if (!app_quitting)
00715                 {
00716                         gSavedSettings.setBOOL("ShowInventory", FALSE);
00717                 }
00718                 // clear filters, but save user's folder state first
00719                 if (!mActivePanel->getRootFolder()->isFilterModified())
00720                 {
00721                         mSavedFolderState->setApply(FALSE);
00722                         mActivePanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
00723                 }
00724                 
00725                 // onClearSearch(this);
00726 
00727                 // pass up
00728                 LLFloater::setVisible(FALSE);
00729         }
00730 }
00731 
00732 BOOL LLInventoryView::handleKeyHere(KEY key, MASK mask)
00733 {
00734         LLFolderView* root_folder = mActivePanel ? mActivePanel->getRootFolder() : NULL;
00735         if (root_folder)
00736         {
00737                 // first check for user accepting current search results
00738                 if (mSearchEditor 
00739                         && mSearchEditor->hasFocus()
00740                     && (key == KEY_RETURN 
00741                         || key == KEY_DOWN)
00742                     && mask == MASK_NONE)
00743                 {
00744                         // move focus to inventory proper
00745                         root_folder->setFocus(TRUE);
00746                         root_folder->scrollToShowSelection();
00747                         return TRUE;
00748                 }
00749 
00750                 if (root_folder->hasFocus() && key == KEY_UP)
00751                 {
00752                         startSearch();
00753                 }
00754         }
00755 
00756         return LLFloater::handleKeyHere(key, mask);
00757 
00758 }
00759 
00760 void LLInventoryView::changed(U32 mask)
00761 {
00762         std::ostringstream title;
00763         title << "Inventory";
00764         if (LLInventoryModel::backgroundFetchActive())
00765         {
00766                 LLLocale locale(LLLocale::USER_LOCALE);
00767                 LLString item_count_string;
00768                 LLResMgr::getInstance()->getIntegerString(item_count_string, gInventory.getItemCount());
00769                 title << " (Fetched " << item_count_string << " items...)";
00770         }
00771         title << mFilterText;
00772         setTitle(title.str());
00773 
00774 }
00775 
00776 // static
00777 // *TODO: remove take_keyboard_focus param
00778 LLInventoryView* LLInventoryView::showAgentInventory(BOOL take_keyboard_focus)
00779 {
00780         if (gDisconnected || gNoRender)
00781         {
00782                 return NULL;
00783         }
00784 
00785         LLInventoryView* iv = LLInventoryView::getActiveInventory();
00786 #if 0 && !LL_RELEASE_FOR_DOWNLOAD
00787         if (sActiveViews.count() == 1)
00788         {
00789                 delete iv;
00790                 iv = NULL;
00791         }
00792 #endif
00793         if(!iv && !gAgent.cameraMouselook())
00794         {
00795                 // create one.
00796                 iv = new LLInventoryView("Inventory",
00797                                                                  "FloaterInventoryRect",
00798                                                                  &gInventory);
00799                 iv->open();
00800                 // keep onscreen
00801                 gFloaterView->adjustToFitScreen(iv, FALSE);
00802 
00803                 gSavedSettings.setBOOL("ShowInventory", TRUE);
00804         }
00805         if(iv)
00806         {
00807                 // Make sure it's in front and it makes a noise
00808                 iv->setTitle("Inventory");
00809                 iv->open();             /*Flawfinder: ignore*/
00810         }
00811         //if (take_keyboard_focus)
00812         //{
00813         //      iv->startSearch();
00814         //      gFocusMgr.triggerFocusFlash();
00815         //}
00816         return iv;
00817 }
00818 
00819 // static
00820 LLInventoryView* LLInventoryView::getActiveInventory()
00821 {
00822         LLInventoryView* iv = NULL;
00823         S32 count = sActiveViews.count();
00824         if(count > 0)
00825         {
00826                 iv = sActiveViews.get(0);
00827                 S32 z_order = gFloaterView->getZOrder(iv);
00828                 S32 z_next = 0;
00829                 LLInventoryView* next_iv = NULL;
00830                 for(S32 i = 1; i < count; ++i)
00831                 {
00832                         next_iv = sActiveViews.get(i);
00833                         z_next = gFloaterView->getZOrder(next_iv);
00834                         if(z_next < z_order)
00835                         {
00836                                 iv = next_iv;
00837                                 z_order = z_next;
00838                         }
00839                 }
00840         }
00841         return iv;
00842 }
00843 
00844 // static
00845 void LLInventoryView::toggleVisibility()
00846 {
00847         S32 count = sActiveViews.count();
00848         if (0 == count)
00849         {
00850                 showAgentInventory(TRUE);
00851         }
00852         else if (1 == count)
00853         {
00854                 if (sActiveViews.get(0)->getVisible())
00855                 {
00856                         sActiveViews.get(0)->close();
00857                         gSavedSettings.setBOOL("ShowInventory", FALSE);
00858                 }
00859                 else
00860                 {
00861                         showAgentInventory(TRUE);
00862                 }
00863         }
00864         else
00865         {
00866                 // With more than one open, we know at least one
00867                 // is visible.
00868 
00869                 // Close all the last one spawned.
00870                 S32 last_index = sActiveViews.count() - 1;
00871                 sActiveViews.get(last_index)->close();
00872         }
00873 }
00874 
00875 // static
00876 void LLInventoryView::cleanup()
00877 {
00878         S32 count = sActiveViews.count();
00879         for (S32 i = 0; i < count; i++)
00880         {
00881                 sActiveViews.get(i)->destroy();
00882         }
00883 }
00884 
00885 void LLInventoryView::toggleFindOptions()
00886 {
00887         LLFloater *floater = getFinder();
00888         if (!floater)
00889         {
00890                 LLInventoryViewFinder * finder = new LLInventoryViewFinder("Inventory Finder",
00891                                                                                 LLRect(getRect().mLeft - INV_FINDER_WIDTH, getRect().mTop, getRect().mLeft, getRect().mTop - INV_FINDER_HEIGHT),
00892                                                                                 this);
00893                 mFinderHandle = finder->getHandle();
00894                 finder->open();         /*Flawfinder: ignore*/
00895                 addDependentFloater(mFinderHandle);
00896 
00897                 // start background fetch of folders
00898                 gInventory.startBackgroundFetch();
00899 
00900                 mFloaterControls["Inventory.ShowFilters"]->setValue(TRUE);
00901         }
00902         else
00903         {
00904                 floater->close();
00905 
00906                 mFloaterControls["Inventory.ShowFilters"]->setValue(FALSE);
00907         }
00908 }
00909 
00910 // static
00911 BOOL LLInventoryView::filtersVisible(void* user_data)
00912 {
00913         LLInventoryView* self = (LLInventoryView*)user_data;
00914         if(!self) return FALSE;
00915 
00916         return self->getFinder() != NULL;
00917 }
00918 
00919 // static
00920 void LLInventoryView::onClearSearch(void* user_data)
00921 {
00922         LLInventoryView* self = (LLInventoryView*)user_data;
00923         if(!self) return;
00924 
00925         LLFloater *finder = self->getFinder();
00926         if (self->mActivePanel)
00927         {
00928                 self->mActivePanel->setFilterSubString("");
00929                 self->mActivePanel->setFilterTypes(0xffffffff);
00930         }
00931 
00932         if (finder)
00933         {
00934                 LLInventoryViewFinder::selectAllTypes(finder);
00935         }
00936 
00937         // re-open folders that were initially open
00938         if (self->mActivePanel)
00939         {
00940                 self->mSavedFolderState->setApply(TRUE);
00941                 self->mActivePanel->getRootFolder()->applyFunctorRecursively(*self->mSavedFolderState);
00942                 LLOpenFoldersWithSelection opener;
00943                 self->mActivePanel->getRootFolder()->applyFunctorRecursively(opener);
00944                 self->mActivePanel->getRootFolder()->scrollToShowSelection();
00945         }
00946 }
00947 
00948 //static
00949 void LLInventoryView::onSearchEdit(const LLString& search_string, void* user_data )
00950 {
00951         if (search_string == "")
00952         {
00953                 onClearSearch(user_data);
00954         }
00955         LLInventoryView* self = (LLInventoryView*)user_data;
00956         if (!self->mActivePanel)
00957         {
00958                 return;
00959         }
00960 
00961         gInventory.startBackgroundFetch();
00962 
00963         LLString filter_text = search_string;
00964         LLString uppercase_search_string = filter_text;
00965         LLString::toUpper(uppercase_search_string);
00966         if (self->mActivePanel->getFilterSubString().empty() && uppercase_search_string.empty())
00967         {
00968                         // current filter and new filter empty, do nothing
00969                         return;
00970         }
00971 
00972         // save current folder open state if no filter currently applied
00973         if (!self->mActivePanel->getRootFolder()->isFilterModified())
00974         {
00975                 self->mSavedFolderState->setApply(FALSE);
00976                 self->mActivePanel->getRootFolder()->applyFunctorRecursively(*self->mSavedFolderState);
00977         }
00978 
00979         // set new filter string
00980         self->mActivePanel->setFilterSubString(uppercase_search_string);
00981 }
00982 
00983 
00984 // static
00985 BOOL LLInventoryView::incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward)
00986 {
00987         LLInventoryView* active_view = NULL;
00988 
00989         for (S32 i = 0; i < sActiveViews.count(); i++)
00990         {
00991                 if (gFocusMgr.childHasKeyboardFocus(sActiveViews[i]))
00992                 {
00993                         active_view = sActiveViews[i];
00994                         break;
00995                 }
00996         }
00997 
00998         if (!active_view)
00999         {
01000                 return FALSE;
01001         }
01002 
01003         LLString search_string(find_text);
01004 
01005         if (search_string.empty())
01006         {
01007                 return FALSE;
01008         }
01009 
01010         if (active_view->mActivePanel &&
01011                 active_view->mActivePanel->getRootFolder()->search(first_item, search_string, backward))
01012         {
01013                 return TRUE;
01014         }
01015 
01016         return FALSE;
01017 }
01018 
01019 //static
01020 void LLInventoryView::onFilterSelected(void* userdata, bool from_click)
01021 {
01022         LLInventoryView* self = (LLInventoryView*) userdata;
01023         LLInventoryFilter* filter;
01024 
01025         LLInventoryViewFinder *finder = self->getFinder();
01026         // Find my index
01027         self->mActivePanel = (LLInventoryPanel*)self->childGetVisibleTab("inventory filter tabs");
01028 
01029         if (!self->mActivePanel)
01030         {
01031                 return;
01032         }
01033         filter = self->mActivePanel->getFilter();
01034         if (finder)
01035         {
01036                 finder->changeFilter(filter);
01037         }
01038         if (filter->isActive())
01039         {
01040                 // If our filter is active we may be the first thing requiring a fetch so we better start it here.
01041                 gInventory.startBackgroundFetch();
01042         }
01043         self->setFilterTextFromFilter();
01044 }
01045 
01046 // static
01047 void LLInventoryView::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action, void* data)
01048 {
01049         LLInventoryPanel* panel = (LLInventoryPanel*)data;
01050         LLFolderView* fv = panel->getRootFolder();
01051         if (fv->needsAutoRename()) // auto-selecting a new user-created asset and preparing to rename
01052         {
01053                 fv->setNeedsAutoRename(FALSE);
01054                 if (items.size()) // new asset is visible and selected
01055                 {
01056                         fv->startRenamingSelectedItem();
01057                 }
01058         }
01059 }
01060 
01061 BOOL LLInventoryView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
01062                                                                                  EDragAndDropType cargo_type,
01063                                                                                  void* cargo_data,
01064                                                                                  EAcceptance* accept,
01065                                                                                  LLString& tooltip_msg)
01066 {
01067         // Check to see if we are auto scrolling from the last frame
01068         LLInventoryPanel* panel = (LLInventoryPanel*)this->getActivePanel();
01069         BOOL needsToScroll = panel->getScrollableContainer()->needsToScroll(x, y, LLScrollableContainerView::VERTICAL);
01070         if(mFilterTabs)
01071         {
01072                 if(needsToScroll)
01073                 {
01074                         mFilterTabs->startDragAndDropDelayTimer();
01075                 }
01076         }
01077         
01078         BOOL handled = LLFloater::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
01079 
01080         return handled;
01081 }
01082 LLString get_item_icon_name(LLAssetType::EType asset_type,
01083                                                          LLInventoryType::EType inventory_type,
01084                                                          U32 attachment_point,
01085                                                          BOOL item_is_multi )
01086 {
01087         EInventoryIcon idx = OBJECT_ICON_NAME;
01088         if ( item_is_multi )
01089         {
01090                 idx = OBJECT_MULTI_ICON_NAME;
01091         }
01092         
01093         switch(asset_type)
01094         {
01095         case LLAssetType::AT_TEXTURE:
01096                 if(LLInventoryType::IT_SNAPSHOT == inventory_type)
01097                 {
01098                         idx = SNAPSHOT_ICON_NAME;
01099                 }
01100                 else
01101                 {
01102                         idx = TEXTURE_ICON_NAME;
01103                 }
01104                 break;
01105 
01106         case LLAssetType::AT_SOUND:
01107                 idx = SOUND_ICON_NAME;
01108                 break;
01109         case LLAssetType::AT_CALLINGCARD:
01110                 if(attachment_point!= 0)
01111                 {
01112                         idx = CALLINGCARD_ONLINE_ICON_NAME;
01113                 }
01114                 else
01115                 {
01116                         idx = CALLINGCARD_OFFLINE_ICON_NAME;
01117                 }
01118                 break;
01119         case LLAssetType::AT_LANDMARK:
01120                 if(attachment_point!= 0)
01121                 {
01122                         idx = LANDMARK_VISITED_ICON_NAME;
01123                 }
01124                 else
01125                 {
01126                         idx = LANDMARK_ICON_NAME;
01127                 }
01128                 break;
01129         case LLAssetType::AT_SCRIPT:
01130         case LLAssetType::AT_LSL_TEXT:
01131         case LLAssetType::AT_LSL_BYTECODE:
01132                 idx = SCRIPT_ICON_NAME;
01133                 break;
01134         case LLAssetType::AT_CLOTHING:
01135                 idx = CLOTHING_ICON_NAME;
01136         case LLAssetType::AT_BODYPART :
01137                 if(LLAssetType::AT_BODYPART == asset_type)
01138                 {
01139                         idx = BODYPART_ICON_NAME;
01140                 }
01141                 switch(attachment_point)
01142                 {
01143                 case WT_SHAPE:
01144                         idx = BODYPART_SHAPE_ICON_NAME;
01145                         break;
01146                 case WT_SKIN:
01147                         idx = BODYPART_SKIN_ICON_NAME;
01148                         break;
01149                 case WT_HAIR:
01150                         idx = BODYPART_HAIR_ICON_NAME;
01151                         break;
01152                 case WT_EYES:
01153                         idx = BODYPART_EYES_ICON_NAME;
01154                         break;
01155                 case WT_SHIRT:
01156                         idx = CLOTHING_SHIRT_ICON_NAME;
01157                         break;
01158                 case WT_PANTS:
01159                         idx = CLOTHING_PANTS_ICON_NAME;
01160                         break;
01161                 case WT_SHOES:
01162                         idx = CLOTHING_SHOES_ICON_NAME;
01163                         break;
01164                 case WT_SOCKS:
01165                         idx = CLOTHING_SOCKS_ICON_NAME;
01166                         break;
01167                 case WT_JACKET:
01168                         idx = CLOTHING_JACKET_ICON_NAME;
01169                         break;
01170                 case WT_GLOVES:
01171                         idx = CLOTHING_GLOVES_ICON_NAME;
01172                         break;
01173                 case WT_UNDERSHIRT:
01174                         idx = CLOTHING_UNDERSHIRT_ICON_NAME;
01175                         break;
01176                 case WT_UNDERPANTS:
01177                         idx = CLOTHING_UNDERPANTS_ICON_NAME;
01178                         break;
01179                 case WT_SKIRT:
01180                         idx = CLOTHING_SKIRT_ICON_NAME;
01181                         break;
01182                 default:
01183                         // no-op, go with choice above
01184                         break;
01185                 }
01186                 break;
01187         case LLAssetType::AT_NOTECARD:
01188                 idx = NOTECARD_ICON_NAME;
01189                 break;
01190         case LLAssetType::AT_ANIMATION:
01191                 idx = ANIMATION_ICON_NAME;
01192                 break;
01193         case LLAssetType::AT_GESTURE:
01194                 idx = GESTURE_ICON_NAME;
01195                 break;
01196         default:
01197                 break;
01198         }
01199         
01200         return LLString(ICON_NAME[idx]);
01201 }
01202 
01203 LLUIImagePtr get_item_icon(LLAssetType::EType asset_type,
01204                                                          LLInventoryType::EType inventory_type,
01205                                                          U32 attachment_point,
01206                                                          BOOL item_is_multi)
01207 {
01208         const LLString& icon_name = get_item_icon_name(asset_type, inventory_type, attachment_point, item_is_multi );
01209         return LLUI::getUIImage(icon_name);
01210 }
01211 
01212 const LLString LLInventoryPanel::DEFAULT_SORT_ORDER = LLString("InventorySortOrder");
01213 const LLString LLInventoryPanel::RECENTITEMS_SORT_ORDER = LLString("RecentItemsSortOrder");
01214 const LLString LLInventoryPanel::INHERIT_SORT_ORDER = LLString("");
01215 
01216 LLInventoryPanel::LLInventoryPanel(const LLString& name,
01217                                                                     const LLString& sort_order_setting,
01218                                                                         const LLRect& rect,
01219                                                                         LLInventoryModel* inventory,
01220                                                                         LLFolderSearchFunction search,
01221                                                                         BOOL allow_multi_select,
01222                                                                         LLView *parent_view) :
01223         LLPanel(name, rect, TRUE),
01224         mInventory(inventory),
01225         mInventoryObserver(NULL),
01226         mFolders(NULL),
01227         mScroller(NULL),
01228         mAllowMultiSelect(allow_multi_select),
01229         mSortOrderSetting(sort_order_setting),
01230         mSearchFunction(search)
01231 {
01232         setBackgroundColor(gColors.getColor("InventoryBackgroundColor"));
01233         setBackgroundVisible(TRUE);
01234         setBackgroundOpaque(TRUE);
01235 }
01236 
01237 BOOL LLInventoryPanel::postBuild()
01238 {
01239         init_inventory_panel_actions(this);
01240 
01241         LLRect folder_rect(0,
01242                                            0,
01243                                            getRect().getWidth(),
01244                                            0);
01245         mFolders = new LLFolderView(getName(), NULL, folder_rect, LLUUID::null, this);
01246         mFolders->setAllowMultiSelect(mAllowMultiSelect);
01247 
01248         // scroller
01249         LLRect scroller_view_rect = getRect();
01250         scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
01251         mScroller = new LLScrollableContainerView("Inventory Scroller",
01252                                                                                            scroller_view_rect,
01253                                                                                           mFolders);
01254         mScroller->setFollowsAll();
01255         mScroller->setReserveScrollCorner(TRUE);
01256         addChild(mScroller);
01257         mFolders->setScrollContainer(mScroller);
01258 
01259         // set up the callbacks from the inventory we're viewing, and then
01260         // build everything.
01261         mInventoryObserver = new LLInventoryPanelObserver(this);
01262         mInventory->addObserver(mInventoryObserver);
01263         rebuildViewsFor(LLUUID::null, LLInventoryObserver::ADD);
01264 
01265         // bit of a hack to make sure the inventory is open.
01266         mFolders->openFolder("My Inventory");
01267 
01268         if (mSortOrderSetting != INHERIT_SORT_ORDER)
01269         {
01270                 setSortOrder(gSavedSettings.getU32(mSortOrderSetting));
01271         }
01272         else
01273         {
01274                 setSortOrder(gSavedSettings.getU32(DEFAULT_SORT_ORDER));
01275         }
01276         mFolders->setSortOrder(mFolders->getFilter()->getSortOrder());
01277 
01278 
01279         return TRUE;
01280 }
01281 
01282 LLInventoryPanel::~LLInventoryPanel()
01283 {
01284         // should this be a global setting?
01285         U32 sort_order = mFolders->getSortOrder();
01286         if (mSortOrderSetting != INHERIT_SORT_ORDER)
01287         {
01288                 gSavedSettings.setU32(mSortOrderSetting, sort_order);
01289         }
01290 
01291         // LLView destructor will take care of the sub-views.
01292         mInventory->removeObserver(mInventoryObserver);
01293         delete mInventoryObserver;
01294         mScroller = NULL;
01295 }
01296 
01297 // virtual
01298 LLXMLNodePtr LLInventoryPanel::getXML(bool save_children) const
01299 {
01300         LLXMLNodePtr node = LLPanel::getXML(false); // Do not print out children
01301 
01302         node->createChild("allow_multi_select", TRUE)->setBoolValue(mFolders->getAllowMultiSelect());
01303 
01304         return node;
01305 }
01306 
01307 LLView* LLInventoryPanel::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
01308 {
01309         LLInventoryPanel* panel;
01310 
01311         LLString name("inventory_panel");
01312         node->getAttributeString("name", name);
01313 
01314         BOOL allow_multi_select = TRUE;
01315         node->getAttributeBOOL("allow_multi_select", allow_multi_select);
01316 
01317         LLRect rect;
01318         createRect(node, rect, parent, LLRect());
01319 
01320         LLString sort_order(INHERIT_SORT_ORDER);
01321         node->getAttributeString("sort_order", sort_order);
01322 
01323         panel = new LLInventoryPanel(name, sort_order,
01324                                                                 rect, &gInventory,
01325                                                                  LLInventoryView::incrementalFind, allow_multi_select, parent);
01326 
01327         panel->initFromXML(node, parent);
01328 
01329         panel->postBuild();
01330 
01331         return panel;
01332 }
01333 
01334 void LLInventoryPanel::setFilterTypes(U32 filter_types)
01335 {
01336         mFolders->getFilter()->setFilterTypes(filter_types);
01337 }       
01338 
01339 void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask)
01340 {
01341         mFolders->getFilter()->setFilterPermissions(filter_perm_mask);
01342 }
01343 
01344 void LLInventoryPanel::setFilterSubString(const LLString& string)
01345 {
01346         mFolders->getFilter()->setFilterSubString(string);
01347 }
01348 
01349 void LLInventoryPanel::setSortOrder(U32 order)
01350 {
01351         mFolders->getFilter()->setSortOrder(order);
01352         if (mFolders->getFilter()->isModified())
01353         {
01354                 mFolders->setSortOrder(order);
01355                 // try to keep selection onscreen, even if it wasn't to start with
01356                 mFolders->scrollToShowSelection();
01357         }
01358 }
01359 
01360 void LLInventoryPanel::setSinceLogoff(BOOL sl)
01361 {
01362         mFolders->getFilter()->setDateRangeLastLogoff(sl);
01363 }
01364 
01365 void LLInventoryPanel::setHoursAgo(U32 hours)
01366 {
01367         mFolders->getFilter()->setHoursAgo(hours);
01368 }
01369 
01370 void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show)
01371 {
01372         mFolders->getFilter()->setShowFolderState(show);
01373 }
01374 
01375 LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()
01376 {
01377         return mFolders->getFilter()->getShowFolderState();
01378 }
01379 
01380 void LLInventoryPanel::modelChanged(U32 mask)
01381 {
01382         LLFastTimer t2(LLFastTimer::FTM_REFRESH);
01383 
01384         bool handled = false;
01385         if(mask & LLInventoryObserver::LABEL)
01386         {
01387                 handled = true;
01388                 // label change - empty out the display name for each object
01389                 // in this change set.
01390                 const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
01391                 std::set<LLUUID>::const_iterator id_it = changed_items.begin();
01392                 std::set<LLUUID>::const_iterator id_end = changed_items.end();
01393                 LLFolderViewItem* view = NULL;
01394                 LLInvFVBridge* bridge = NULL;
01395                 for (;id_it != id_end; ++id_it)
01396                 {
01397                         view = mFolders->getItemByID(*id_it);
01398                         if(view)
01399                         {
01400                                 // request refresh on this item (also flags for filtering)
01401                                 bridge = (LLInvFVBridge*)view->getListener();
01402                                 if(bridge)
01403                                 {       // Clear the display name first, so it gets properly re-built during refresh()
01404                                         bridge->clearDisplayName();
01405                                 }
01406                                 view->refresh();
01407                         }
01408                 }
01409         }
01410         if((mask & (LLInventoryObserver::STRUCTURE
01411                                 | LLInventoryObserver::ADD
01412                                 | LLInventoryObserver::REMOVE)) != 0)
01413         {
01414                 handled = true;
01415                 // Record which folders are open by uuid.
01416                 LLInventoryModel* model = getModel();
01417                 if (model)
01418                 {
01419                         const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
01420 
01421                         std::set<LLUUID>::const_iterator id_it = changed_items.begin();
01422                         std::set<LLUUID>::const_iterator id_end = changed_items.end();
01423                         for (;id_it != id_end; ++id_it)
01424                         {
01425                                 // sync view with model
01426                                 LLInventoryObject* model_item = model->getObject(*id_it);
01427                                 LLFolderViewItem* view_item = mFolders->getItemByID(*id_it);
01428 
01429                                 if (model_item)
01430                                 {
01431                                         if (!view_item)
01432                                         {
01433                                                 // this object was just created, need to build a view for it
01434                                                 if ((mask & LLInventoryObserver::ADD) != LLInventoryObserver::ADD)
01435                                                 {
01436                                                         llwarns << *id_it << " is in model but not in view, but ADD flag not set" << llendl;
01437                                                 }
01438                                                 buildNewViews(*id_it);
01439                                                 
01440                                                 // select any newly created object
01441                                                 // that has the auto rename at top of folder
01442                                                 // root set
01443                                                 if(mFolders->getRoot()->needsAutoRename())
01444                                                 {
01445                                                         setSelection(*id_it, FALSE);
01446                                                 }
01447                                         }
01448                                         else
01449                                         {
01450                                                 // this object was probably moved, check its parent
01451                                                 if ((mask & LLInventoryObserver::STRUCTURE) != LLInventoryObserver::STRUCTURE)
01452                                                 {
01453                                                         llwarns << *id_it << " is in model and in view, but STRUCTURE flag not set" << llendl;
01454                                                 }
01455 
01456                                                 LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID());
01457                                                 if (view_item->getParentFolder() != new_parent)
01458                                                 {
01459                                                         view_item->getParentFolder()->extractItem(view_item);
01460                                                         view_item->addToFolder(new_parent, mFolders);
01461                                                 }
01462                                         }
01463                                 }
01464                                 else
01465                                 {
01466                                         if (view_item)
01467                                         {
01468                                                 if ((mask & LLInventoryObserver::REMOVE) != LLInventoryObserver::REMOVE)
01469                                                 {
01470                                                         llwarns << *id_it << " is not in model but in view, but REMOVE flag not set" << llendl;
01471                                                 }
01472                                                 // item in view but not model, need to delete view
01473                                                 view_item->destroyView();
01474                                         }
01475                                         else
01476                                         {
01477                                                 llwarns << *id_it << "Item does not exist in either view or model, but notification triggered" << llendl;
01478                                         }
01479                                 }
01480                         }
01481                 }
01482         }
01483 
01484         if (!handled)
01485         {
01486                 // it's a small change that only requires a refresh.
01487                 // *TODO: figure out a more efficient way to do the refresh
01488                 // since it is expensive on large inventories
01489                 mFolders->refresh();
01490         }
01491 }
01492 
01493 void LLInventoryPanel::rebuildViewsFor(const LLUUID& id, U32 mask)
01494 {
01495         LLFolderViewItem* old_view = NULL;
01496 
01497         // get old LLFolderViewItem
01498         old_view = mFolders->getItemByID(id);
01499         if (old_view && id.notNull())
01500         {
01501                 old_view->destroyView();
01502         }
01503 
01504         buildNewViews(id);
01505 }
01506 
01507 void LLInventoryPanel::buildNewViews(const LLUUID& id)
01508 {
01509         LLFolderViewItem* itemp = NULL;
01510         LLInventoryObject* objectp = gInventory.getObject(id);
01511         S32 i;
01512         S32 count;
01513 
01514         if (objectp)
01515         {               
01516                 if (objectp->getType() <= LLAssetType::AT_NONE ||
01517                         objectp->getType() >= LLAssetType::AT_COUNT)
01518                 {
01519                         llwarns << "LLInventoryPanel::buildNewViews called with objectp->mType == " 
01520                                 << ((S32) objectp->getType())
01521                                 << " (shouldn't happen)" << llendl;
01522                 }
01523                 else if (objectp->getType() == LLAssetType::AT_CATEGORY) // build new view for category
01524                 {
01525                         LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(objectp->getType(),
01526                                                                                                         LLInventoryType::IT_CATEGORY,
01527                                                                                                         this,
01528                                                                                                         objectp->getUUID());
01529 
01530                         if (new_listener)
01531                         {
01532                                 LLFolderViewFolder* folderp = new LLFolderViewFolder(new_listener->getDisplayName(),
01533                                                                                                         new_listener->getIcon(),
01534                                                                                                         mFolders,
01535                                                                                                         new_listener);
01536                                 
01537                                 folderp->setItemSortOrder(mFolders->getSortOrder());
01538                                 itemp = folderp;
01539                         }
01540                 }
01541                 else // build new view for item
01542                 {
01543                         LLInventoryItem* item = (LLInventoryItem*)objectp;
01544                         LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(
01545                                 item->getType(),
01546                                 item->getInventoryType(),
01547                                 this,
01548                                 item->getUUID(),
01549                                 item->getFlags());
01550                         if (new_listener)
01551                         {
01552                                 itemp = new LLFolderViewItem(new_listener->getDisplayName(),
01553                                                                                                 new_listener->getIcon(),
01554                                                                                                 new_listener->getCreationDate(),
01555                                                                                                 mFolders,
01556                                                                                                 new_listener);
01557                         }
01558                 }
01559 
01560                 LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)mFolders->getItemByID(objectp->getParentUUID());
01561 
01562                 if (itemp)
01563                 {
01564                         if (parent_folder)
01565                         {
01566                                 itemp->addToFolder(parent_folder, mFolders);
01567                         }
01568                         else
01569                         {
01570                                 llwarns << "Couldn't find parent folder for child " << itemp->getLabel() << llendl;
01571                                 delete itemp;
01572                         }
01573                 }
01574         }
01575 
01576         if ((id.isNull() ||
01577                 (objectp && objectp->getType() == LLAssetType::AT_CATEGORY)))
01578         {
01579                 LLViewerInventoryCategory::cat_array_t* categories;
01580                 LLViewerInventoryItem::item_array_t* items;
01581 
01582                 mInventory->getDirectDescendentsOf(id, categories, items);
01583                 if(categories)
01584                 {
01585                         count = categories->count();
01586                         for(i = 0; i < count; ++i)
01587                         {
01588                                 LLInventoryCategory* cat = categories->get(i);
01589                                 buildNewViews(cat->getUUID());
01590                         }
01591                 }
01592                 if(items)
01593                 {
01594                         count = items->count();
01595                         for(i = 0; i < count; ++i)
01596                         {
01597                                 LLInventoryItem* item = items->get(i);
01598                                 buildNewViews(item->getUUID());
01599                         }
01600                 }
01601         }
01602 }
01603 
01604 struct LLConfirmPurgeData
01605 {
01606         LLUUID mID;
01607         LLInventoryModel* mModel;
01608 };
01609 
01610 class LLIsNotWorn : public LLInventoryCollectFunctor
01611 {
01612 public:
01613         LLIsNotWorn() {}
01614         virtual ~LLIsNotWorn() {}
01615         virtual bool operator()(LLInventoryCategory* cat,
01616                                                         LLInventoryItem* item)
01617         {
01618                 return !gAgent.isWearingItem(item->getUUID());
01619         }
01620 };
01621 
01622 class LLOpenFolderByID : public LLFolderViewFunctor
01623 {
01624 public:
01625         LLOpenFolderByID(const LLUUID& id) : mID(id) {}
01626         virtual ~LLOpenFolderByID() {}
01627         virtual void doFolder(LLFolderViewFolder* folder)
01628                 {
01629                         if (folder->getListener() && folder->getListener()->getUUID() == mID) folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
01630                 }
01631         virtual void doItem(LLFolderViewItem* item) {}
01632 protected:
01633         const LLUUID& mID;
01634 };
01635 
01636 
01637 void LLInventoryPanel::openSelected()
01638 {
01639         LLFolderViewItem* folder_item = mFolders->getCurSelectedItem();
01640         if(!folder_item) return;
01641         LLInvFVBridge* bridge = (LLInvFVBridge*)folder_item->getListener();
01642         if(!bridge) return;
01643         bridge->openItem();
01644 }
01645 
01646 BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask)
01647 {
01648         BOOL handled = LLView::handleHover(x, y, mask);
01649         if(handled)
01650         {
01651                 ECursorType cursor = getWindow()->getCursor();
01652                 if (LLInventoryModel::backgroundFetchActive() && cursor == UI_CURSOR_ARROW)
01653                 {
01654                         // replace arrow cursor with arrow and hourglass cursor
01655                         getWindow()->setCursor(UI_CURSOR_WORKING);
01656                 }
01657         }
01658         else
01659         {
01660                 getWindow()->setCursor(UI_CURSOR_ARROW);
01661         }
01662         return TRUE;
01663 }
01664 
01665 BOOL LLInventoryPanel::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
01666                                                                    EDragAndDropType cargo_type,
01667                                                                    void* cargo_data,
01668                                                                    EAcceptance* accept,
01669                                                                    LLString& tooltip_msg)
01670 {
01671 
01672         BOOL handled = LLPanel::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
01673 
01674         if (handled)
01675         {
01676                 mFolders->setDragAndDropThisFrame();
01677         }
01678 
01679         return handled;
01680 }
01681 
01682 
01683 void LLInventoryPanel::openAllFolders()
01684 {
01685         mFolders->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_DOWN);
01686         mFolders->arrangeAll();
01687 }
01688 
01689 void LLInventoryPanel::closeAllFolders()
01690 {
01691         mFolders->setOpenArrangeRecursively(FALSE, LLFolderViewFolder::RECURSE_DOWN);
01692         mFolders->arrangeAll();
01693 }
01694 
01695 void LLInventoryPanel::openDefaultFolderForType(LLAssetType::EType type)
01696 {
01697         LLUUID category_id = mInventory->findCategoryUUIDForType(type);
01698         LLOpenFolderByID opener(category_id);
01699         mFolders->applyFunctorRecursively(opener);
01700 }
01701 
01702 void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus)
01703 {
01704         LLFolderViewItem* itemp = mFolders->getItemByID(obj_id);
01705         if(itemp && itemp->getListener())
01706         {
01707                 itemp->getListener()->arrangeAndSet(itemp,
01708                                                                                           TRUE,
01709                                                                                           take_keyboard_focus);
01710         }
01711 }
01712 
01713 void LLInventoryPanel::clearSelection()
01714 {
01715         mFolders->clearSelection();
01716 }
01717 
01718 void LLInventoryPanel::createNewItem(const char* name,
01719                                                                         const LLUUID& parent_id,
01720                                                                         LLAssetType::EType asset_type,
01721                                                                         LLInventoryType::EType inv_type,
01722                                                                         U32 next_owner_perm)
01723 {
01724         LLString desc;
01725         LLAssetType::generateDescriptionFor(asset_type, desc);
01726         next_owner_perm = (next_owner_perm) ? next_owner_perm : PERM_MOVE | PERM_TRANSFER;
01727 
01728         
01729         if (inv_type == LLInventoryType::IT_GESTURE)
01730         {
01731                 LLPointer<LLInventoryCallback> cb = new CreateGestureCallback();
01732                 create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
01733                 parent_id, LLTransactionID::tnull, name, desc, asset_type, inv_type,
01734                 NOT_WEARABLE, next_owner_perm, cb);
01735         }
01736         else
01737         {
01738                 LLPointer<LLInventoryCallback> cb = NULL;
01739                 create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
01740                 parent_id, LLTransactionID::tnull, name, desc, asset_type, inv_type,
01741                 NOT_WEARABLE, next_owner_perm, cb);
01742         }
01743         
01744 }       
01745 
01746 // static DEBUG ONLY:
01747 void LLInventoryPanel::dumpSelectionInformation(void* user_data)
01748 {
01749         LLInventoryPanel* iv = (LLInventoryPanel*)user_data;
01750         iv->mFolders->dumpSelectionInformation();
01751 }

Generated on Fri May 16 08:33:43 2008 for SecondLife by  doxygen 1.5.5