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

Generated on Thu Jul 1 06:08:46 2010 for Second Life Viewer by  doxygen 1.4.7