diff options
Diffstat (limited to 'indra')
51 files changed, 633 insertions, 256 deletions
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 9cfc67af14..3694ecd4f4 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -711,19 +711,12 @@ void LLFlatListView::selectLastItem () void LLFlatListView::ensureSelectedVisible() { - LLRect visible_rc = getVisibleContentRect(); LLRect selected_rc = getLastSelectedItemRect(); - if ( !visible_rc.contains (selected_rc) ) + if ( selected_rc.isValid() ) { - // But scroll in Items panel coordinates scrollToShowRect(selected_rc); } - - // In case we are in accordion tab notify parent to show selected rectangle - LLRect screen_rc; - localRectToScreen(selected_rc, &screen_rc); - notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue())); } diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index aba35773ee..c4f10038f8 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -93,6 +93,8 @@ public: void updateLayout(BOOL force_resize = FALSE); S32 getPanelSpacing() const { return mPanelSpacing; } + BOOL getAnimate () const { return mAnimate; } + void setAnimate (BOOL animate) { mAnimate = animate; } static void updateClass(); diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index a5e47e8547..94465a67ce 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -668,6 +668,11 @@ void LLScrollContainer::scrollToShowRect(const LLRect& rect, const LLRect& const // propagate scroll to document updateScroll(); + + // In case we are in accordion tab notify parent to show selected rectangle + LLRect screen_rc; + localRectToScreen(rect_to_constrain, &screen_rc); + notifyParent(LLSD().with("scrollToShowRect",screen_rc.getValue())); } void LLScrollContainer::pageUp(S32 overlap) diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index b2b17fdd56..da4abde451 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -200,6 +200,11 @@ const std::string &LLDir::getOSUserAppDir() const const std::string &LLDir::getLindenUserDir() const { + if (mLindenUserDir.empty()) + { + lldebugs << "getLindenUserDir() called early, we don't have the user name yet - returning empty string to caller" << llendl; + } + return mLindenUserDir; } @@ -337,7 +342,7 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd break; case LL_PATH_CACHE: - prefix = getCacheDir(); + prefix = getCacheDir(); break; case LL_PATH_USER_SETTINGS: @@ -348,6 +353,11 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd case LL_PATH_PER_SL_ACCOUNT: prefix = getLindenUserDir(); + if (prefix.empty()) + { + // if we're asking for the per-SL-account directory but we haven't logged in yet (or otherwise don't know the account name from which to build this string), then intentionally return a blank string to the caller and skip the below warning about a blank prefix. + return std::string(); + } break; case LL_PATH_CHAT_LOGS: @@ -557,7 +567,7 @@ std::string LLDir::getForbiddenFileChars() void LLDir::setLindenUserDir(const std::string &first, const std::string &last) { - // if both first and last aren't set, assume we're grabbing the cached dir + // if both first and last aren't set, that's bad. if (!first.empty() && !last.empty()) { // some platforms have case-sensitive filesystems, so be @@ -571,6 +581,7 @@ void LLDir::setLindenUserDir(const std::string &first, const std::string &last) mLindenUserDir += firstlower; mLindenUserDir += "_"; mLindenUserDir += lastlower; + llinfos << "Got name for LLDir::setLindenUserDir(first='" << first << "', last='" << last << "')" << llendl; } else { diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 206e3223e3..9067d75bac 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -44,7 +44,7 @@ typedef enum ELLPath LL_PATH_NONE = 0, LL_PATH_USER_SETTINGS = 1, LL_PATH_APP_SETTINGS = 2, - LL_PATH_PER_SL_ACCOUNT = 3, + LL_PATH_PER_SL_ACCOUNT = 3, // returns/expands to blank string if we don't know the account name yet LL_PATH_CACHE = 4, LL_PATH_CHARACTER = 5, LL_PATH_HELP = 6, diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp index ee902d1de7..a9736560ec 100644 --- a/indra/llvfs/lldir_linux.cpp +++ b/indra/llvfs/lldir_linux.cpp @@ -112,9 +112,10 @@ LLDir_Linux::LLDir_Linux() // ...normal installation running mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins"; } + mOSUserDir = getCurrentUserHome(tmp_str); mOSUserAppDir = ""; - mLindenUserDir = tmp_str; + mLindenUserDir = ""; char path [32]; /* Flawfinder: ignore */ diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp index a8fad8e5bd..8ac5a41e93 100644 --- a/indra/llvfs/lldir_solaris.cpp +++ b/indra/llvfs/lldir_solaris.cpp @@ -100,7 +100,7 @@ LLDir_Solaris::LLDir_Solaris() mAppRODataDir = strdup(tmp_str); mOSUserDir = getCurrentUserHome(tmp_str); mOSUserAppDir = ""; - mLindenUserDir = tmp_str; + mLindenUserDir = ""; char path [LL_MAX_PATH]; /* Flawfinder: ignore */ diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 9c4c8387a8..d0bbcc222d 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5062,6 +5062,18 @@ <key>Value</key> <integer>5</integer> </map> + <key>ToastButtonWidth</key> + <map> + <key>Comment</key> + <string>Default width of buttons in the toast. + Note if required width will be less then this one, a button will be reshaped to default size , otherwise to required</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>90</integer> + </map> <key>ChannelBottomPanelMargin</key> <map> <key>Comment</key> diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 297bcfd1df..da0e9238d6 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2806,6 +2806,7 @@ void LLAgent::endAnimationUpdateUI() gStatusBar->setVisibleForMouselook(true); LLBottomTray::getInstance()->setVisible(TRUE); + LLBottomTray::getInstance()->onMouselookModeOut(); LLSideTray::getInstance()->getButtonsPanel()->setVisible(TRUE); LLSideTray::getInstance()->updateSidetrayVisibility(); @@ -2904,6 +2905,7 @@ void LLAgent::endAnimationUpdateUI() LLNavigationBar::getInstance()->setVisible(FALSE); gStatusBar->setVisibleForMouselook(false); + LLBottomTray::getInstance()->onMouselookModeIn(); LLBottomTray::getInstance()->setVisible(FALSE); LLSideTray::getInstance()->getButtonsPanel()->setVisible(FALSE); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 4a61096ad8..638a8f759d 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1376,7 +1376,7 @@ bool LLAppViewer::cleanup() if( gViewerWindow) gViewerWindow->shutdownViews(); - llinfos << "Cleaning up Inevntory" << llendflush; + llinfos << "Cleaning up Inventory" << llendflush; // Cleanup Inventory after the UI since it will delete any remaining observers // (Deleted observers should have already removed themselves) @@ -1478,10 +1478,17 @@ bool LLAppViewer::cleanup() LLUIColorTable::instance().saveUserSettings(); - // PerAccountSettingsFile should be empty if no use has been logged on. + // PerAccountSettingsFile should be empty if no user has been logged on. // *FIX:Mani This should get really saved in a "logoff" mode. - gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); - llinfos << "Saved settings" << llendflush; + if (gSavedSettings.getString("PerAccountSettingsFile").empty()) + { + llinfos << "Not saving per-account settings; don't know the account name yet." << llendl; + } + else + { + gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE); + llinfos << "Saved settings" << llendflush; + } std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE); // save all settings, even if equals defaults @@ -1676,7 +1683,7 @@ bool LLAppViewer::initThreads() // Image decoding LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true); LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true); - LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && true); + LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && false); LLImage::initClass(); if (LLFastTimer::sLog || LLFastTimer::sMetricLog) diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp index 42ae122ff9..87b8d807c4 100644 --- a/indra/newview/llavatariconctrl.cpp +++ b/indra/newview/llavatariconctrl.cpp @@ -64,7 +64,7 @@ void LLAvatarIconIDCache::load () llinfos << "Loading avatar icon id cache." << llendl; // build filename for each user - std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, mFilename); + std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, mFilename); llifstream file(resolved_filename); if (!file.is_open()) @@ -97,7 +97,7 @@ void LLAvatarIconIDCache::load () void LLAvatarIconIDCache::save () { - std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, mFilename); + std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, mFilename); // open a file for writing llofstream file (resolved_filename); diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp index beccefa430..9b215e4096 100644 --- a/indra/newview/llbottomtray.cpp +++ b/indra/newview/llbottomtray.cpp @@ -48,10 +48,20 @@ #include "llsyswellwindow.h" #include "llfloatercamera.h" #include "lltexteditor.h" +#include "llnotifications.h" // Build time optimization, generate extern template once in .cpp file template class LLBottomTray* LLSingleton<class LLBottomTray>::getInstance(); +namespace +{ + const std::string& PANEL_CHICLET_NAME = "chiclet_list_panel"; + const std::string& PANEL_CHATBAR_NAME = "chat_bar"; + const std::string& PANEL_MOVEMENT_NAME = "movement_panel"; + const std::string& PANEL_CAMERA_NAME = "cam_panel"; + const std::string& PANEL_GESTURE_NAME = "gesture_panel"; +} + LLBottomTray::LLBottomTray(const LLSD&) : mChicletPanel(NULL), mSpeakPanel(NULL), @@ -236,6 +246,61 @@ void LLBottomTray::onFocusLost() } } +void LLBottomTray::savePanelsShape() +{ + mSavedShapeList.clear(); + for (child_list_const_iter_t + child_it = mToolbarStack->beginChild(), + child_it_end = mToolbarStack->endChild(); + child_it != child_it_end; ++child_it) + { + mSavedShapeList.push_back( (*child_it)->getRect() ); + } +} + +void LLBottomTray::restorePanelsShape() +{ + if (mSavedShapeList.size() != mToolbarStack->getChildCount()) + return; + int i = 0; + for (child_list_const_iter_t + child_it = mToolbarStack->beginChild(), + child_it_end = mToolbarStack->endChild(); + child_it != child_it_end; ++child_it) + { + (*child_it)->setShape(mSavedShapeList[i++]); + } +} + +void LLBottomTray::onMouselookModeOut() +{ + // Apply the saved settings when we are not in mouselook mode, see EXT-3988. + { + setTrayButtonVisibleIfPossible (RS_BUTTON_GESTURES, gSavedSettings.getBOOL("ShowGestureButton"), false); + setTrayButtonVisibleIfPossible (RS_BUTTON_MOVEMENT, gSavedSettings.getBOOL("ShowMoveButton"), false); + setTrayButtonVisibleIfPossible (RS_BUTTON_CAMERA, gSavedSettings.getBOOL("ShowCameraButton"), false); + setTrayButtonVisibleIfPossible (RS_BUTTON_SNAPSHOT, gSavedSettings.getBOOL("ShowSnapshotButton"),false); + } + // HACK: To avoid usage the LLLayoutStack logic of resizing, we force the updateLayout + // and then restore children saved shapes. See EXT-4309. + BOOL saved_anim = mToolbarStack->getAnimate(); + mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, FALSE); + // Disable animation to prevent layout updating in several frames. + mToolbarStack->setAnimate(FALSE); + // Force the updating of layout to reset panels collapse factor. + mToolbarStack->updateLayout(); + // Restore animate state. + mToolbarStack->setAnimate(saved_anim); + // Restore saved shapes. + restorePanelsShape(); +} + +void LLBottomTray::onMouselookModeIn() +{ + savePanelsShape(); + mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, TRUE); +} + //virtual // setVisible used instead of onVisibilityChange, since LLAgent calls it on entering/leaving mouselook mode. // If bottom tray is already visible in mouselook mode, then onVisibilityChange will not be called from setVisible(true), @@ -255,23 +320,15 @@ void LLBottomTray::setVisible(BOOL visible) LLView* viewp = *child_it; std::string name = viewp->getName(); - // Chat bar and gesture button are shown even in mouselook mode. But the move, camera and snapshot buttons shouldn't be displayed. See EXT-3988. - if ("chat_bar" == name || "gesture_panel" == name || (visibility && ("movement_panel" == name || "cam_panel" == name || "snapshot_panel" == name))) + // Chat bar and gesture button are shown even in mouselook mode. + // But the move, camera and snapshot buttons shouldn't be displayed. See EXT-3988. + if ("chat_bar" == name || "gesture_panel" == name) continue; else { viewp->setVisible(visibility); } } - - // Apply the saved settings when we are not in mouselook mode, see EXT-3988. - if (visibility) - { - showCameraButton(gSavedSettings.getBOOL("ShowCameraButton")); - showSnapshotButton(gSavedSettings.getBOOL("ShowSnapshotButton")); - showMoveButton(gSavedSettings.getBOOL("ShowMoveButton")); - showGestureButton(gSavedSettings.getBOOL("ShowGestureButton")); - } } } @@ -337,15 +394,6 @@ void LLBottomTray::showSnapshotButton(BOOL visible) setTrayButtonVisibleIfPossible(RS_BUTTON_SNAPSHOT, visible); } -namespace -{ - const std::string& PANEL_CHICLET_NAME = "chiclet_list_panel"; - const std::string& PANEL_CHATBAR_NAME = "chat_bar"; - const std::string& PANEL_MOVEMENT_NAME = "movement_panel"; - const std::string& PANEL_CAMERA_NAME = "cam_panel"; - const std::string& PANEL_GESTURE_NAME = "gesture_panel"; -} - BOOL LLBottomTray::postBuild() { @@ -1018,7 +1066,7 @@ void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool vis panel->setVisible(visible); } -void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible) +void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification) { bool can_be_set = true; @@ -1058,7 +1106,11 @@ void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type { // mark this button to show it while future bottom tray extending mResizeState |= shown_object_type; - LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown"); + if ( raise_notification ) + LLNotificationsUtil::add("BottomTrayButtonCanNotBeShown", + LLSD(), + LLSD(), + LLNotificationFunctorRegistry::instance().DONOTHING); } } diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h index 9be0e5810f..562ee56912 100644 --- a/indra/newview/llbottomtray.h +++ b/indra/newview/llbottomtray.h @@ -92,7 +92,10 @@ public: void showMoveButton(BOOL visible); void showCameraButton(BOOL visible); void showSnapshotButton(BOOL visible); - + + void onMouselookModeIn(); + void onMouselookModeOut(); + /** * Creates IM Chiclet based on session type (IM chat or Group chat) */ @@ -167,7 +170,14 @@ private: * - if hidden via context menu button should be shown but there is no enough room for now * it will be shown while extending. */ - void setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible); + void setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible, bool raise_notification = true); + + /** + * Save and restore children shapes. + * Used to avoid the LLLayoutStack resizing logic between mouse look mode switching. + */ + void savePanelsShape(); + void restorePanelsShape(); MASK mResizeState; @@ -177,6 +187,9 @@ private: typedef std::map<EResizeState, S32> state_object_width_map_t; state_object_width_map_t mObjectDefaultWidthMap; + typedef std::vector<LLRect> shape_list_t; + shape_list_t mSavedShapeList; + protected: LLBottomTray(const LLSD& key = LLSD()); diff --git a/indra/newview/llchatitemscontainerctrl.cpp b/indra/newview/llchatitemscontainerctrl.cpp index 9ce3f29853..f7f7ee83af 100644 --- a/indra/newview/llchatitemscontainerctrl.cpp +++ b/indra/newview/llchatitemscontainerctrl.cpp @@ -168,27 +168,30 @@ void LLNearbyChatToastPanel::init(LLSD& notification) msg_text->setText(std::string("")); - std::string str_sender; - - str_sender = fromName; + if ( notification["chat_style"].asInteger() != CHAT_STYLE_IRC ) + { + std::string str_sender; - str_sender+=" "; + str_sender = fromName; - //append user name - { - LLStyle::Params style_params_name; + str_sender+=" "; - LLColor4 userNameColor = LLUIColorTable::instance().getColor("ChatToastAgentNameColor"); + //append user name + { + LLStyle::Params style_params_name; - style_params_name.color(userNameColor); - - std::string font_name = LLFontGL::nameFromFont(messageFont); - std::string font_style_size = LLFontGL::sizeFromFont(messageFont); - style_params_name.font.name(font_name); - style_params_name.font.size(font_style_size); - - msg_text->appendText(str_sender, FALSE, style_params_name); - + LLColor4 userNameColor = LLUIColorTable::instance().getColor("ChatToastAgentNameColor"); + + style_params_name.color(userNameColor); + + std::string font_name = LLFontGL::nameFromFont(messageFont); + std::string font_style_size = LLFontGL::sizeFromFont(messageFont); + style_params_name.font.name(font_name); + style_params_name.font.size(font_style_size); + + msg_text->appendText(str_sender, FALSE, style_params_name); + + } } //append text diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index fd6a92c47a..fb94657278 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -483,6 +483,10 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, if (drop) { + if (mItems.empty()) + { + setLandingTab(NULL); + } handleNewFavoriteDragAndDrop(item, favorites_id, x, y); showDragMarker(FALSE); } diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index a00d7abd17..f4d4ea3553 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -116,9 +116,12 @@ public: { if (params.size() == 0) { - return false; + // support the secondlife:///app/worldmap SLapp + LLFloaterReg::showInstance("world_map", "center"); + return true; } + // support the secondlife:///app/worldmap/{LOCATION}/{COORDS} SLapp const std::string region_name = params[0].asString(); S32 x = (params.size() > 1) ? params[1].asInteger() : 128; S32 y = (params.size() > 2) ? params[2].asInteger() : 128; diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index afde543ca8..a63fb73032 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -1885,8 +1885,8 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight(); S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight()); - // when navigating with keyboard, only move top of folders on screen, otherwise show whole folder - S32 max_height_to_show = mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); + // when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder + S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight(); // get portion of item that we want to see... LLRect item_local_rect = LLRect(item->getIndentation(), diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index e9176da715..099f863dc9 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2931,27 +2931,6 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response return false; } -// See also LLInventorySort where landmarks in the Favorites folder are sorted. -class LLViewerInventoryItemSort -{ -public: - bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) - { - return a->getSortField() < b->getSortField(); - } -}; - -/** - * Sorts passed items by LLViewerInventoryItem sort field. - * - * @param[in, out] items - array of items, not sorted. - */ -void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items) -{ - static LLViewerInventoryItemSort sort_functor; - std::sort(items.begin(), items.end(), sort_functor); -} - BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, BOOL drop) { @@ -3034,36 +3013,34 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // if dragging from/into favorites folder only reorder items if ((mUUID == inv_item->getParentUUID()) && folder_allows_reorder) { - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLIsType is_type(LLAssetType::AT_LANDMARK); - model->collectDescendentsIf(mUUID, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); - LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; if (itemp) { LLUUID srcItemId = inv_item->getUUID(); LLUUID destItemId = itemp->getListener()->getUUID(); - - // ensure items are sorted properly before changing order. EXT-3498 - rearrange_item_order_by_sort_field(items); - - // update order - LLInventoryModel::updateItemsOrder(items, srcItemId, destItemId); - - gInventory.saveItemsOrder(items); + gInventory.rearrangeFavoriteLandmarks(srcItemId, destItemId); } } else if (favorites_id == mUUID) // if target is the favorites folder we use copy { + // use callback to rearrange favorite landmarks after adding + // to have new one placed before target (on which it was dropped). See EXT-4312. + LLPointer<AddFavoriteLandmarkCallback> cb = new AddFavoriteLandmarkCallback(); + LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); + LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; + if (drag_over_item && drag_over_item->getListener()) + { + cb.get()->setTargetLandmarkId(drag_over_item->getListener()->getUUID()); + } + copy_inventory_item( gAgent.getID(), inv_item->getPermissions().getOwner(), inv_item->getUUID(), mUUID, std::string(), - LLPointer<LLInventoryCallback>(NULL)); + cb); } else if (move_is_into_current_outfit || move_is_into_outfit) { diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index ef18386e57..e44adfb511 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -3648,6 +3648,9 @@ void LLInventoryModel::updateItemsOrder(LLInventoryModel::item_array_t& items, c LLViewerInventoryItem* src_item = *it_src; items.erase(it_src); + + // target iterator can not be valid because the container was changed, so update it. + it_dest = find_item_iter_by_uuid(items, dest_item_id); items.insert(it_dest, src_item); } @@ -3673,6 +3676,44 @@ void LLInventoryModel::saveItemsOrder(const LLInventoryModel::item_array_t& item notifyObservers(); } +// See also LLInventorySort where landmarks in the Favorites folder are sorted. +class LLViewerInventoryItemSort +{ +public: + bool operator()(const LLPointer<LLViewerInventoryItem>& a, const LLPointer<LLViewerInventoryItem>& b) + { + return a->getSortField() < b->getSortField(); + } +}; + +/** + * Sorts passed items by LLViewerInventoryItem sort field. + * + * @param[in, out] items - array of items, not sorted. + */ +static void rearrange_item_order_by_sort_field(LLInventoryModel::item_array_t& items) +{ + static LLViewerInventoryItemSort sort_functor; + std::sort(items.begin(), items.end(), sort_functor); +} + +void LLInventoryModel::rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id) +{ + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLIsType is_type(LLAssetType::AT_LANDMARK); + LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + gInventory.collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type); + + // ensure items are sorted properly before changing order. EXT-3498 + rearrange_item_order_by_sort_field(items); + + // update order + updateItemsOrder(items, source_item_id, target_item_id); + + saveItemsOrder(items); +} + //---------------------------------------------------------------------------- // *NOTE: DEBUG functionality diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index e8698c0759..2a2b48ce3c 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -408,6 +408,15 @@ public: */ void saveItemsOrder(const LLInventoryModel::item_array_t& items); + /** + * Rearranges Landmarks inside Favorites folder. + * Moves source landmark before target one. + * + * @param source_item_id - LLUUID of the source item to be moved into new position + * @param target_item_id - LLUUID of the target item before which source item should be placed. + */ + void rearrangeFavoriteLandmarks(const LLUUID& source_item_id, const LLUUID& target_item_id); + protected: // Internal methods which add inventory and make sure that all of diff --git a/indra/newview/lllocationhistory.cpp b/indra/newview/lllocationhistory.cpp index d910dbf718..ae1b8f8540 100644 --- a/indra/newview/lllocationhistory.cpp +++ b/indra/newview/lllocationhistory.cpp @@ -123,6 +123,12 @@ void LLLocationHistory::save() const // build filename for each user std::string resolved_filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, mFilename); + if (resolved_filename.empty()) + { + llinfos << "can't get path to location history filename - probably not logged in yet." << llendl; + return; + } + // open a file for writing llofstream file (resolved_filename); if (!file.is_open()) diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index b520bc1c2d..af66b6e3de 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -258,7 +258,7 @@ LLMuteList::~LLMuteList() { // If we quit from the login screen we will not have an SL account // name. Don't try to save, otherwise we'll dump a file in - // C:\Program Files\SecondLife\ JC + // C:\Program Files\SecondLife\ or similar. JC std::string user_dir = gDirUtilp->getLindenUserDir(); if (!user_dir.empty()) { diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 96442fafcc..c50e049d4c 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -180,11 +180,6 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& notification) if(panel && panel->messageID() == fromID && panel->canAddText()) { - if (CHAT_STYLE_IRC == notification["chat_style"].asInteger()) - { - notification["message"] = notification["from"].asString() + notification["message"].asString(); - } - panel->addMessage(notification); toast->reshapeToPanel(); toast->resetTimer(); @@ -349,7 +344,10 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg) // Handle irc styled messages for toast panel if (tmp_chat.mChatStyle == CHAT_STYLE_IRC) { - tmp_chat.mText = tmp_chat.mText.substr(3); + if(!tmp_chat.mFromName.empty()) + tmp_chat.mText = tmp_chat.mFromName + tmp_chat.mText.substr(3); + else + tmp_chat.mText = tmp_chat.mText.substr(3); } // arrange a channel on a screen diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index daec793d75..01291c4012 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -419,9 +419,9 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) if(tab_land->getDisplayChildren()) tab_land->changeOpenClose(tab_land->getDisplayChildren()); - tab_roles->canOpenClose(false); - tab_notices->canOpenClose(false); - tab_land->canOpenClose(false); + tab_roles->setVisible(false); + tab_notices->setVisible(false); + tab_land->setVisible(false); getChild<LLUICtrl>("group_name")->setVisible(false); getChild<LLUICtrl>("group_name_editor")->setVisible(true); @@ -443,9 +443,9 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id) LLGroupData agent_gdatap; bool is_member = gAgent.getGroupData(mID,agent_gdatap); - tab_roles->canOpenClose(is_member); - tab_notices->canOpenClose(is_member); - tab_land->canOpenClose(is_member); + tab_roles->setVisible(is_member); + tab_notices->setVisible(is_member); + tab_land->setVisible(is_member); getChild<LLUICtrl>("group_name")->setVisible(true); getChild<LLUICtrl>("group_name_editor")->setVisible(false); diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 6210973dae..45fc3d4688 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -614,7 +614,7 @@ void LLPanelGroupNotices::showNotice(const std::string& subject, mViewInventoryIcon->setVisible(TRUE); std::stringstream ss; - ss << " " << inventory_name; + ss << " " << LLViewerInventoryItem::getDisplayName(inventory_name); mViewInventoryName->setText(ss.str()); mBtnOpenAttachment->setEnabled(TRUE); diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 30acf37f82..d6e407a0ed 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -35,6 +35,7 @@ #include "llbutton.h" #include "llfloaterreg.h" +#include "llnotificationsutil.h" #include "llsdutil.h" #include "llsdutil_math.h" #include "llregionhandle.h" @@ -632,8 +633,7 @@ void LLLandmarksPanel::onAddAction(const LLSD& userdata) const LLViewerInventoryItem* landmark = LLLandmarkActions::findLandmarkForAgentPos(); if(landmark) { - LLSideTray::getInstance()->showPanel("panel_places", - LLSD().with("type", "landmark").with("id",landmark->getUUID())); + LLNotificationsUtil::add("LandmarkAlreadyExists"); } else { diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index e74a39c85c..a5a61f0c7b 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -51,6 +51,8 @@ #include "llviewermenu.h" #include "llviewertexturelist.h" +const std::string FILTERS_FILENAME("filters.xml"); + static LLRegisterPanelClassWrapper<LLPanelMainInventory> t_inventory("panel_main_inventory"); void on_file_loaded_for_save(BOOL success, @@ -160,7 +162,7 @@ BOOL LLPanelMainInventory::postBuild() // Now load the stored settings from disk, if available. std::ostringstream filterSaveName; - filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml"); + filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME); llinfos << "LLPanelMainInventory::init: reading from " << filterSaveName << llendl; llifstream file(filterSaveName.str()); LLSD savedFilterState; @@ -230,7 +232,7 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) } std::ostringstream filterSaveName; - filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml"); + filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, FILTERS_FILENAME); llofstream filtersFile(filterSaveName.str()); if(!LLSDSerialize::toPrettyXML(filterRoot, filtersFile)) { diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index 43366ef814..d4376550d6 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -445,7 +445,7 @@ bool remove_task_inventory_callback(const LLSD& notification, const LLSD& respon } // helper for remove -// ! REFACTOR ! two_uuids_list_t is also defined in llinevntorybridge.h, but differently. +// ! REFACTOR ! two_uuids_list_t is also defined in llinventorybridge.h, but differently. typedef std::pair<LLUUID, std::list<LLUUID> > panel_two_uuids_list_t; typedef std::pair<LLPanelObjectInventory*, panel_two_uuids_list_t> remove_data_t; BOOL LLTaskInvFVBridge::removeItem() diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index df73c27f54..fd5ce7a46d 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -569,8 +569,6 @@ void LLPanelOutfitsInventory::initTabPanels() myoutfits_panel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); mTabPanels[1] = myoutfits_panel; - mActivePanel = mTabPanels[0]; - for (tabpanels_vec_t::iterator iter = mTabPanels.begin(); iter != mTabPanels.end(); ++iter) @@ -581,6 +579,7 @@ void LLPanelOutfitsInventory::initTabPanels() mAppearanceTabs = getChild<LLTabContainer>("appearance_tabs"); mAppearanceTabs->setCommitCallback(boost::bind(&LLPanelOutfitsInventory::onTabChange, this)); + mActivePanel = (LLInventoryPanel*)mAppearanceTabs->getCurrentPanel(); } void LLPanelOutfitsInventory::onTabSelectionChange(LLInventoryPanel* tab_panel, const std::deque<LLFolderViewItem*> &items, BOOL user_action) diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 027f3daffb..0adc9fc258 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -250,6 +250,13 @@ void LLScreenChannel::onToastDestroyed(LLToast* toast) { mToastList.erase(it); } + + it = find(mStoredToastList.begin(), mStoredToastList.end(), static_cast<LLPanel*>(toast)); + + if(it != mStoredToastList.end()) + { + mStoredToastList.erase(it); + } } @@ -279,6 +286,11 @@ void LLScreenChannel::onToastFade(LLToast* toast) //-------------------------------------------------------------------------- void LLScreenChannel::deleteToast(LLToast* toast) { + if (toast->isDead()) + { + return; + } + // send signal to observers about destroying of a toast toast->mOnDeleteToastSignal(toast); diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index fb8aa39445..50c47e293e 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -639,6 +639,21 @@ LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& para return NULL; } +void LLSideTray::togglePanel(LLPanel* &sub_panel, const std::string& panel_name, const LLSD& params) +{ + if(!sub_panel) + return; + + if (sub_panel->isInVisibleChain()) + { + LLSideTray::getInstance()->collapseSideBar(); + } + else + { + LLSideTray::getInstance()->showPanel(panel_name, params); + } +} + // This is just LLView::findChildView specialized to restrict the search to LLPanels. // Optimization for EXT-4068 to avoid searching down to the individual item level // when inventories are large. diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h index de2cfe9711..b1c8675793 100644 --- a/indra/newview/llsidetray.h +++ b/indra/newview/llsidetray.h @@ -94,7 +94,15 @@ public: * if no such tab - return NULL, otherwise a pointer to the panel * Pass params as array, or they may be overwritten(example - params["name"]="nearby") */ - LLPanel* showPanel (const std::string& panel_name, const LLSD& params); + LLPanel* showPanel (const std::string& panel_name, const LLSD& params); + + /** + * Toggling Side Tray tab which contains "sub_panel" child of "panel_name" panel. + * If "sub_panel" is not visible Side Tray is opened to display it, + * otherwise Side Tray is collapsed. + * params are passed to "panel_name" panel onOpen(). + */ + void togglePanel (LLPanel* &sub_panel, const std::string& panel_name, const LLSD& params); /* * get the panel (don't show it or do anything else with it) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index fbc98b7691..ad88534a5d 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -920,9 +920,9 @@ bool idle_startup() // create necessary directories // *FIX: these mkdir's should error check gDirUtilp->setLindenUserDir(gFirstname, gLastname); - LLFile::mkdir(gDirUtilp->getLindenUserDir()); - - // Set PerAccountSettingsFile to the default value. + LLFile::mkdir(gDirUtilp->getLindenUserDir()); + + // Set PerAccountSettingsFile to the default value. gSavedSettings.setString("PerAccountSettingsFile", gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount"))); diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 72ef383be9..4a7d784c3e 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -1139,7 +1139,7 @@ LLTexLayerInterface::LLTexLayerInterface(const LLTexLayerInterface &layer, LLWea BOOL LLTexLayerInterface::setInfo(const LLTexLayerInfo *info, LLWearable* wearable ) // This sets mInfo and calls initialization functions { - llassert(mInfo == NULL); + //llassert(mInfo == NULL); // nyx says this is probably bogus but needs investigating mInfo = info; //mID = info->mID; // No ID diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index a5ddb0a620..b980f65e68 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -1190,8 +1190,12 @@ void LLTextureCtrl::draw() } else if (!mImageAssetID.isNull()) { - mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES); - mTexturep->setBoostLevel(LLViewerTexture::BOOST_PREVIEW); + LLPointer<LLViewerFetchedTexture> texture = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES,LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + + texture->setBoostLevel(LLViewerTexture::BOOST_PREVIEW); + texture->forceToSaveRawImage(0) ; + + mTexturep = texture; } else if (!mFallbackImageName.empty()) { diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index d0c125eb77..94acb2ae8c 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -45,7 +45,7 @@ #include "lltrans.h" const S32 BOTTOM_PAD = VPAD * 3; -const S32 BUTTON_WIDTH = 90; +S32 BUTTON_WIDTH = 90; //static const LLFontGL* LLToastNotifyPanel::sFont = NULL; @@ -63,7 +63,7 @@ mAddedDefaultBtn(false) LLUICtrlFactory::getInstance()->buildPanel(this, "panel_notification.xml"); mInfoPanel = getChild<LLPanel>("info_panel"); mControlPanel = getChild<LLPanel>("control_panel"); - + BUTTON_WIDTH = gSavedSettings.getS32("ToastButtonWidth"); // customize panel's attributes // is it intended for displaying a tip mIsTip = notification->getType() == "notifytip"; @@ -96,7 +96,8 @@ mAddedDefaultBtn(false) // customize panel's outfit // preliminary adjust panel's layout - mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); + //move to the end + //mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form); // adjust text options according to the notification type // add a caution textbox at the top of a caution notification @@ -117,8 +118,14 @@ mAddedDefaultBtn(false) mTextBox->setValue(notification->getMessage()); // add buttons for a script notification - if (!mIsTip) + if (mIsTip) + { + adjustPanelForTipNotice(); + } + else { + std::vector<index_button_pair_t> buttons; + buttons.reserve(mNumOptions); for (S32 i = 0; i < mNumOptions; i++) { LLSD form_element = form->getElement(i); @@ -126,65 +133,155 @@ mAddedDefaultBtn(false) { continue; } - - addButton(form_element["name"].asString(), form_element["text"].asString(), TRUE, form_element["default"].asBoolean()); } - - if (mNumButtons == 0) + S32 buttons_width = 0; + // create all buttons and accumulate they total width to reshape mControlPanel + for (S32 i = 0; i < mNumOptions; i++) { - addButton("OK", LLTrans::getString("ok"), FALSE, TRUE); - mAddedDefaultBtn = true; + LLSD form_element = form->getElement(i); + if (form_element["type"].asString() != "button") + { + continue; + } + LLButton* new_button = createButton(form_element, TRUE); + buttons_width += new_button->getRect().getWidth(); + S32 index = form_element["index"].asInteger(); + buttons.push_back(index_button_pair_t(index,new_button)); + } + if (buttons.empty()) + { + addDefaultButton(); + } + else + { + //try get an average left_pad to spread out buttons + S32 left_pad = (getRect().getWidth() - buttons_width) / (S32(buttons.size() + 1)); + // left_pad can be < 2*HPAD if we have a lot of buttons. + if(left_pad < 2*HPAD) + { + //Probably it is a scriptdialog toast, set default left_pad + left_pad = 2*HPAD; + } + //how many rows we need to fit all buttons with current width of the panel + S32 button_rows = (buttons_width + left_pad * S32(buttons.size() + 1)) / getRect().getWidth() + 1; + //calculate required panel height + S32 button_panel_height = button_rows *( BTN_HEIGHT + VPAD) + BOTTOM_PAD; + + adjustPanelForScriptNotice(getRect().getWidth(), button_panel_height); + //we begin from lefttop angle and go to rightbottom. + updateButtonsLayout(buttons, left_pad, button_panel_height); } } - // adjust panel's height to the text size mInfoPanel->setFollowsAll(); snapToMessageHeight(mTextBox, MAX_LENGTH); } - -LLToastNotifyPanel::~LLToastNotifyPanel() +void LLToastNotifyPanel::addDefaultButton() { - std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); + LLSD form_element; + form_element.with("name", "OK").with("text", LLTrans::getString("ok")).with("default", true); + LLButton* ok_btn = createButton(form_element, FALSE); + LLRect new_btn_rect(ok_btn->getRect()); + + new_btn_rect.setOriginAndSize(llabs(getRect().getWidth() - BUTTON_WIDTH)/ 2, BOTTOM_PAD, + //auto_size for ok button makes it very small, so let's make it wider + BUTTON_WIDTH, new_btn_rect.getHeight()); + ok_btn->setRect(new_btn_rect); + addChild(ok_btn, -1); + mNumButtons = 1; + mAddedDefaultBtn = true; } +LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_option) +{ + InstanceAndS32* userdata = new InstanceAndS32; + userdata->mSelf = this; + userdata->mButtonName = is_option ? form_element["name"].asString() : ""; -void LLToastNotifyPanel::adjustPanelForScriptNotice(const LLNotificationFormPtr form) -{ - F32 buttons_num = 0; - S32 button_rows = 0; + mBtnCallbackData.push_back(userdata); - // calculate number of buttons - for (S32 i = 0; i < mNumOptions; i++) + LLButton::Params p; + const LLFontGL* font = form_element["index"].asInteger() == -1 ? sFontSmall: sFont; // for ignore button in script dialog + p.name(form_element["name"].asString()); + p.label(form_element["text"].asString()); + p.font(font); + p.rect.height = BTN_HEIGHT; + p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata)); + p.rect.width = BUTTON_WIDTH; + p.auto_resize = false; + p.follows.flags(FOLLOWS_RIGHT | FOLLOWS_LEFT | FOLLOWS_BOTTOM); + if (mIsCaution) { - if (form->getElement(i)["type"].asString() == "button") - { - buttons_num++; - } + p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); + p.image_color_disabled(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); } - - // calculate necessary height for the button panel - // if notification form contains no buttons - reserve a place for OK button - // script notifications have extra line for an IGNORE button - if(mIsScriptDialog) + if (!mIsScriptDialog && font->getWidth(form_element["text"].asString()) > BUTTON_WIDTH) { - button_rows = llceil((buttons_num - 1) / 3.0f) + 1; + p.rect.width = 1; + p.auto_resize = true; } - else + + LLButton* btn = LLUICtrlFactory::create<LLButton>(p); + mNumButtons++; + btn->autoResize(); + if (form_element["default"].asBoolean()) { - button_rows = llmax( 1, llceil(buttons_num / 3.0f)); + setDefaultBtn(btn); } - S32 button_panel_height = button_rows * BTN_HEIGHT + (button_rows + 1) * VPAD + BOTTOM_PAD; + return btn; +} + +LLToastNotifyPanel::~LLToastNotifyPanel() +{ + std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer()); +} +void LLToastNotifyPanel::updateButtonsLayout(const std::vector<index_button_pair_t>& buttons, S32 left_pad, S32 top) +{ + S32 left = left_pad; + LLButton* ignore_btn = NULL; + for (std::vector<index_button_pair_t>::const_iterator it = buttons.begin(); it != buttons.end(); it++) + { + if(left + it->second->getRect().getWidth() + 2*HPAD > getRect().getWidth()) + { + // looks like we need to add button to the next row + left = left_pad; + top-= (BTN_HEIGHT + VPAD); + } + LLRect btn_rect(it->second->getRect()); + if(mIsScriptDialog && it->first == -1) + { + //this is ignore button ( index == -1) we need to add it into new extra row at the end + ignore_btn = it->second; + continue; + } + btn_rect.setLeftTopAndSize(left, top, btn_rect.getWidth(), btn_rect.getHeight()); + it->second->setRect(btn_rect); + left = btn_rect.mLeft + btn_rect.getWidth() + left_pad; + addChild(it->second, -1); + } + if(ignore_btn) + { + LLRect btn_rect(ignore_btn->getRect()); + btn_rect.setOriginAndSize(getRect().getWidth() - btn_rect.getWidth() - left_pad, + BOTTOM_PAD,// move button at the bottom edge + btn_rect.getWidth(), btn_rect.getHeight()); + ignore_btn->setRect(btn_rect); + addChild(ignore_btn, -1); + } +} +void LLToastNotifyPanel::adjustPanelForScriptNotice(S32 button_panel_width, S32 button_panel_height) +{ //adjust layout + // we need to keep min width and max height to make visible all buttons, because width of the toast can not be changed LLRect button_rect = mControlPanel->getRect(); - reshape(getRect().getWidth(), mInfoPanel->getRect().getHeight() + button_panel_height); + reshape(getRect().getWidth(), mInfoPanel->getRect().getHeight() + button_panel_height + VPAD); button_rect.set(0, button_rect.mBottom + button_panel_height, button_rect.getWidth(), button_rect.mBottom); mControlPanel->reshape(button_rect.getWidth(), button_panel_height); mControlPanel->setRect(button_rect); } -// static void LLToastNotifyPanel::adjustPanelForTipNotice() { LLRect info_rect = mInfoPanel->getRect(); @@ -208,64 +305,3 @@ void LLToastNotifyPanel::onClickButton(void* data) } self->mNotification->respond(response); } - -// virtual -LLButton* LLToastNotifyPanel::addButton(const std::string& name, const std::string& label, BOOL is_option, BOOL is_default) -{ - LLRect btn_rect; - LLButton* btn; - S32 btn_height= BTN_HEIGHT; - const LLFontGL* font = sFont; - S32 ignore_pad = 0; - S32 button_index = mNumButtons; - S32 index = button_index; - S32 x = HPAD * 2; // *2 - to make a nice offset - - if (mIsScriptDialog) - { - // Add two "blank" option spaces, before the "Ignore" button - index = button_index + 2; - if (button_index == 0) - { - // Ignore button is smaller, less wide - btn_height = BTN_HEIGHT_SMALL; - font = sFontSmall; - ignore_pad = 10; - } - } - - btn_rect.setOriginAndSize(x + (index % 3) * (BUTTON_WIDTH+HPAD+HPAD) + ignore_pad, - BOTTOM_PAD + (index / 3) * (BTN_HEIGHT+VPAD), - BUTTON_WIDTH - 2*ignore_pad, - btn_height); - - InstanceAndS32* userdata = new InstanceAndS32; - userdata->mSelf = this; - userdata->mButtonName = is_option ? name : ""; - - mBtnCallbackData.push_back(userdata); - - LLButton::Params p; - p.name(name); - p.label(label); - p.rect(btn_rect); - p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata)); - p.font(font); - if (mIsCaution) - { - p.image_color(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); - p.image_color_disabled(LLUIColorTable::instance().getColor("ButtonCautionImageColor")); - } - btn = LLUICtrlFactory::create<LLButton>(p); - - - mControlPanel->addChild(btn, -1); - - if (is_default) - { - setDefaultBtn(btn); - } - - mNumButtons++; - return btn; -} diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index 04525387b3..1f50c21f6f 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -57,7 +57,7 @@ public: virtual ~LLToastNotifyPanel(); protected: - LLButton* addButton(std::string const &name, const std::string& label, BOOL is_option, BOOL is_default); + LLButton* createButton(const LLSD& form_element, BOOL is_option); // Used for callbacks struct InstanceAndS32 @@ -69,8 +69,11 @@ protected: private: - void adjustPanelForScriptNotice(const boost::shared_ptr<LLNotificationForm> form); + typedef std::pair<int,LLButton*> index_button_pair_t; + void adjustPanelForScriptNotice(S32 max_width, S32 max_height); void adjustPanelForTipNotice(); + void addDefaultButton(); + void updateButtonsLayout(const std::vector<index_button_pair_t>& buttons, S32 left_pad, S32 top); // panel elements LLTextBase* mTextBox; diff --git a/indra/newview/llurlhistory.cpp b/indra/newview/llurlhistory.cpp index e8b5aa7c74..08dd82ab86 100644 --- a/indra/newview/llurlhistory.cpp +++ b/indra/newview/llurlhistory.cpp @@ -77,7 +77,7 @@ bool LLURLHistory::saveFile(const std::string& filename) std::string temp_str = gDirUtilp->getLindenUserDir(); if( temp_str.empty() ) { - llwarns << "Can't save. No user directory set." << llendl; + llinfos << "Can't save URL history - no user directory set yet." << llendl; return false; } diff --git a/indra/newview/llurlwhitelist.cpp b/indra/newview/llurlwhitelist.cpp index da69039cf9..46bc9276c1 100644 --- a/indra/newview/llurlwhitelist.cpp +++ b/indra/newview/llurlwhitelist.cpp @@ -121,6 +121,12 @@ bool LLUrlWhiteList::save () // build filename for each user std::string resolvedFilename = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, mFilename ); + if (resolvedFilename.empty()) + { + llinfos << "No per-user dir for saving URL whitelist - presumably not logged in yet. Skipping." << llendl; + return false; + } + // open a file for writing llofstream file ( resolvedFilename ); if ( file.is_open () ) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 5605f425e0..b330c1ba83 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -44,6 +44,7 @@ #include "llconsole.h" #include "llinventorymodel.h" #include "llgesturemgr.h" +#include "llsidetray.h" #include "llinventorybridge.h" #include "llfloaterinventory.h" @@ -72,7 +73,23 @@ public: bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) { - if (params.size() < 2) return false; + if (params.size() < 1) + { + return false; + } + + // support secondlife:///app/inventory/show + if (params[0].asString() == "show") + { + LLSideTray::getInstance()->showPanel("sidepanel_inventory", LLSD()); + return true; + } + + // otherwise, we need a UUID and a verb... + if (params.size() < 2) + { + return false; + } LLUUID inventory_id; if (!inventory_id.set(params[0], FALSE)) { @@ -823,6 +840,13 @@ void CreateGestureCallback::fire(const LLUUID& inv_item) gFloaterView->adjustToFitScreen(preview, FALSE); } +void AddFavoriteLandmarkCallback::fire(const LLUUID& inv_item_id) +{ + if (mTargetLandmarkId.isNull()) return; + + gInventory.rearrangeFavoriteLandmarks(inv_item_id, mTargetLandmarkId); +} + LLInventoryCallbackManager gInventoryCallbacks; void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id, @@ -1158,6 +1182,15 @@ const std::string& LLViewerInventoryItem::getDisplayName() const return mDisplayName = hasSortField ? result : LLInventoryItem::getName(); } +// static +std::string LLViewerInventoryItem::getDisplayName(const std::string& name) +{ + std::string result; + BOOL hasSortField = extractSortFieldAndDisplayName(name, 0, &result); + + return hasSortField ? result : name; +} + S32 LLViewerInventoryItem::getSortField() const { S32 result; diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 412a2c66e6..917b8747ea 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -66,6 +66,7 @@ public: virtual const LLUUID& getAssetUUID() const; virtual const std::string& getName() const; virtual const std::string& getDisplayName() const; + static std::string getDisplayName(const std::string& name); virtual S32 getSortField() const; virtual void setSortField(S32 sortField); virtual void rename(const std::string& new_name); @@ -279,6 +280,18 @@ public: void fire(const LLUUID& inv_item); }; +class AddFavoriteLandmarkCallback : public LLInventoryCallback +{ +public: + AddFavoriteLandmarkCallback() : mTargetLandmarkId(LLUUID::null) {} + void setTargetLandmarkId(const LLUUID& target_uuid) { mTargetLandmarkId = target_uuid; } + +private: + void fire(const LLUUID& inv_item); + + LLUUID mTargetLandmarkId; +}; + // misc functions //void inventory_reliable_callback(void**, S32 status); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index d2ba898cf0..88a61c9d49 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3365,14 +3365,49 @@ void handle_show_side_tray() root->addChild(side_tray); } -class LLShowPanelPeopleTab : public view_listener_t +// Toggle one of "People" panel tabs in side tray. +class LLTogglePanelPeopleTab : public view_listener_t { bool handleEvent(const LLSD& userdata) { - // Open tab of the "People" panel in side tray. + std::string panel_name = userdata.asString(); + LLSD param; - param["people_panel_tab_name"] = userdata.asString(); - LLSideTray::getInstance()->showPanel("panel_people", param); + param["people_panel_tab_name"] = panel_name; + + static LLPanel* friends_panel = NULL; + static LLPanel* groups_panel = NULL; + static LLPanel* nearby_panel = NULL; + + if (panel_name == "friends_panel") + { + return togglePeoplePanel(friends_panel, panel_name, param); + } + else if (panel_name == "groups_panel") + { + return togglePeoplePanel(groups_panel, panel_name, param); + } + else if (panel_name == "nearby_panel") + { + return togglePeoplePanel(nearby_panel, panel_name, param); + } + else + { + return false; + } + } + + static bool togglePeoplePanel(LLPanel* &panel, const std::string& panel_name, const LLSD& param) + { + if(!panel) + { + panel = LLSideTray::getInstance()->getPanel(panel_name); + if(!panel) + return false; + } + + LLSideTray::getInstance()->togglePanel(panel, "panel_people", param); + return true; } }; @@ -7898,7 +7933,7 @@ void initialize_menus() view_listener_t::addMenu(new LLSelfEnableRemoveAllAttachments(), "Self.EnableRemoveAllAttachments"); // we don't use boost::bind directly to delay side tray construction - view_listener_t::addMenu( new LLShowPanelPeopleTab(), "SideTray.PanelPeopleTab"); + view_listener_t::addMenu( new LLTogglePanelPeopleTab(), "SideTray.PanelPeopleTab"); // Avatar pie menu view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 7f43213c5d..c929e81ea4 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -738,6 +738,7 @@ void start_new_inventory_observer() class LLDiscardAgentOffer : public LLInventoryFetchComboObserver { + LOG_CLASS(LLDiscardAgentOffer); public: LLDiscardAgentOffer(const LLUUID& folder_id, const LLUUID& object_id) : mFolderID(folder_id), @@ -1114,7 +1115,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& // * callback may be called immediately, // * adding the mute sends a message, // * we can't build two messages at once. - if (2 == button) + if (2 == button) // Block { gCacheName->get(mFromID, mFromGroup, boost::bind(&inventory_offer_mute_callback,_1,_2,_3,_4,this)); } @@ -2054,6 +2055,13 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) //if (((is_busy && !is_owned_by_me) || is_muted)) if ( is_muted || mute_im) { + // Prefetch the offered item so that it can be discarded by the appropriate observer. (EXT-4331) + LLInventoryFetchObserver::item_ref_t items; + items.push_back(info->mObjectID); + LLInventoryFetchObserver* fetch_item = new LLInventoryFetchObserver(); + fetch_item->fetchItems(items); + delete fetch_item; + // Same as closing window info->forceResponse(IOR_DECLINE); } @@ -2146,6 +2154,48 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Build a link to open the object IM info window. std::string location = ll_safe_string((char*)binary_bucket, binary_bucket_size-1); + if (session_id.notNull()) + { + chat.mFromID = session_id; + } + else + { + // This message originated on a region without the updated code for task id and slurl information. + // We just need a unique ID for this object that isn't the owner ID. + // If it is the owner ID it will overwrite the style that contains the link to that owner's profile. + // This isn't ideal - it will make 1 style for all objects owned by the the same person/group. + // This works because the only thing we can really do in this case is show the owner name and link to their profile. + chat.mFromID = from_id ^ gAgent.getSessionID(); + } + + LLSD query_string; + query_string["owner"] = from_id; + query_string["slurl"] = location; + query_string["name"] = name; + if (from_group) + { + query_string["groupowned"] = "true"; + } + + std::ostringstream link; + link << "secondlife:///app/objectim/" << session_id << LLURI::mapToQueryString(query_string); + + chat.mURL = link.str(); + chat.mText = message; + chat.mSourceType = CHAT_SOURCE_OBJECT; + + // Note: lie to Nearby Chat, pretending that this is NOT an IM, because + // IMs from obejcts don't open IM sessions. + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD()); + if(nearby_chat) + { + nearby_chat->addMessage(chat); + } + + + //Object IMs send with from name: 'Second Life' need to be displayed also in notification toasts (EXT-1590) + if (SYSTEM_FROM != name) break; + LLSD substitutions; substitutions["NAME"] = name; substitutions["MSG"] = message; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 8252b7df00..6bb547373c 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -178,7 +178,7 @@ static std::string get_texture_list_name() void LLViewerTextureList::doPrefetchImages() { - if (LLAppViewer::instance()->getPurgeCache()) + if (LLAppViewer::instance()->getPurgeCache()) { // cache was purged, no point return; diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index ddaf4a221c..769344d183 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1638,7 +1638,7 @@ void LLViewerWindow::shutdownGL() LLViewerTextureManager::cleanup() ; LLImageGL::cleanupClass() ; - llinfos << "All texturs and llimagegl images are destroyed!" << llendl ; + llinfos << "All textures and llimagegl images are destroyed!" << llendl ; llinfos << "Cleaning up select manager" << llendl; LLSelectMgr::getInstance()->cleanup(); diff --git a/indra/newview/skins/default/xui/en/alert_button.xml b/indra/newview/skins/default/xui/en/alert_button.xml index 48c67a3770..632564d793 100644 --- a/indra/newview/skins/default/xui/en/alert_button.xml +++ b/indra/newview/skins/default/xui/en/alert_button.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <button + name="Alert Button" label_shadow="true" auto_resize="false" image_overlay_alignment="center" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 957b4d74db..1ec004b194 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -1402,6 +1402,16 @@ You have added "[LANDMARK_NAME]" to your [FOLDER_NAME] folder. </notification> <notification + icon="alert.tga" + name="LandmarkAlreadyExists" + type="alert"> +You already have a landmark for this location. + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification icon="alertmodal.tga" name="CannotCreateLandmarkNotOwner" type="alertmodal"> diff --git a/indra/newview/skins/default/xui/en/panel_chat_separator.xml b/indra/newview/skins/default/xui/en/panel_chat_separator.xml index d0a2ddb289..357dbc07cc 100644 --- a/indra/newview/skins/default/xui/en/panel_chat_separator.xml +++ b/indra/newview/skins/default/xui/en/panel_chat_separator.xml @@ -3,6 +3,6 @@ background_visible="true" bg_alpha_color="black" follows="left|right|top" - height="1" + height="0" layout="topleft" name="chat_separator_panel" /> diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml index 9ad99b1f13..58cb5fed5d 100644 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -126,6 +126,8 @@ <combo_editor label="Search [SECOND_LIFE]" name="search_combo_editor"/> + <combo_list + draw_border="true" /> </search_combo_box> </panel> <favorites_bar diff --git a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml index fd540bdc7e..8895484326 100644 --- a/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outfits_inventory.xml @@ -21,22 +21,8 @@ halign="center" width="313"> <inventory_panel - follows="all" - background_visible="true" - background_opaque="true" - label="WEARING" - help_topic="now_wearing_tab" - allow_multi_select="true" - border="false" - left="0" - top="0" - mouse_opaque="true" - name="cof_accordionpanel" - start_folder="Current Outfit" - width="313" /> - <inventory_panel - background_visible="true" - background_opaque="true" + background_visible="true" + background_opaque="true" label="MY OUTFITS" help_topic="my_outfits_tab" allow_multi_select="true" @@ -48,6 +34,20 @@ mouse_opaque="true" name="outfitslist_tab" start_folder="My Outfits" /> + <inventory_panel + follows="all" + background_visible="true" + background_opaque="true" + label="WEARING" + help_topic="now_wearing_tab" + allow_multi_select="true" + border="false" + left="0" + top="0" + mouse_opaque="true" + name="cof_accordionpanel" + start_folder="Current Outfit" + width="313" /> </tab_container> <panel background_visible="true" @@ -103,5 +103,15 @@ top="26" tool_tip="Wear selected outfit" width="120" /> + <button + follows="bottom|left" + height="23" + label="M" + layout="topleft" + right="-140" + name="look_edit_btn" + top="26" + visible="false" + width="20" /> </panel> </panel> diff --git a/indra/newview/skins/default/xui/en/widgets/chat_history.xml b/indra/newview/skins/default/xui/en/widgets/chat_history.xml index f6d1992c8e..ef885e8045 100644 --- a/indra/newview/skins/default/xui/en/widgets/chat_history.xml +++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml @@ -6,8 +6,8 @@ right_text_pad="15" left_widget_pad="0" right_widget_pad="10" - top_separator_pad="2" - bottom_separator_pad="2" + top_separator_pad="1" + bottom_separator_pad="1" top_header_pad="12" bottom_header_pad="5" max_length="2147483647" @@ -21,5 +21,4 @@ mouse_opaque="true" word_wrap="true" /> -</chat_history> -enabledcontrol
\ No newline at end of file +</chat_history>
\ No newline at end of file |