diff options
107 files changed, 2531 insertions, 1262 deletions
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index e7fe656808..1193a4ef8d 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -1122,6 +1122,11 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token, struct tm * gmt = gmtime (&loc_seconds); replacement = LLStringOps::sMonthList[gmt->tm_mon]; } + else if(LLStringOps::sMonthShortList.size() == 12 && code == "%b") + { + struct tm * gmt = gmtime (&loc_seconds); + replacement = LLStringOps::sMonthShortList[gmt->tm_mon]; + } else if( !LLStringOps::sDayFormat.empty() && code == "%d" ) { struct tm * gmt = gmtime (&loc_seconds); diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 93d8282aa7..f0d92d597a 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -589,15 +589,23 @@ void LLButton::getOverlayImageSize(S32& overlay_width, S32& overlay_height) // virtual void LLButton::draw() { + static LLCachedControl<bool> sEnableButtonFlashing(*LLUI::sSettingGroups["config"], "EnableButtonFlashing", true); F32 alpha = mUseDrawContextAlpha ? getDrawContext().mAlpha : getCurrentTransparency(); bool flash = FALSE; - if( mFlashing ) + if( mFlashing) { - F32 elapsed = mFlashingTimer.getElapsedTimeF32(); - S32 flash_count = S32(elapsed * mButtonFlashRate * 2.f); - // flash on or off? - flash = (flash_count % 2 == 0) || flash_count > S32((F32)mButtonFlashCount * 2.f); + if ( sEnableButtonFlashing) + { + F32 elapsed = mFlashingTimer.getElapsedTimeF32(); + S32 flash_count = S32(elapsed * mButtonFlashRate * 2.f); + // flash on or off? + flash = (flash_count % 2 == 0) || flash_count > S32((F32)mButtonFlashCount * 2.f); + } + else + { // otherwise just highlight button in flash color + flash = true; + } } bool pressed_by_keyboard = FALSE; diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index ede6149a80..3b308a359d 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -191,13 +191,12 @@ public: return min_dim; } + F32 getCollapseFactor(); void setOrientation(LLLayoutStack::ELayoutOrientation orientation) { mOrientation = orientation; } protected: LLLayoutPanel(const Params& p); - F32 getCollapseFactor(); - bool mExpandedMinDimSpecified; S32 mExpandedMinDim; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index cb237fca7c..95ecbb1c94 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -947,9 +947,14 @@ LLMenuItemBranchGL::LLMenuItemBranchGL(const LLMenuItemBranchGL::Params& p) LLMenuItemBranchGL::~LLMenuItemBranchGL() { - delete mBranchHandle.get(); + if (mBranchHandle.get()) + { + mBranchHandle.get()->die(); + } } + + // virtual LLView* LLMenuItemBranchGL::getChildView(const std::string& name, BOOL recurse) const { diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index cd33938226..f620201020 100644 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -135,6 +135,8 @@ public: const LLColor4& getBackgroundColor() const { return mBgOpaqueColor; } void setTransparentColor(const LLColor4& color) { mBgAlphaColor = color; } const LLColor4& getTransparentColor() const { return mBgAlphaColor; } + void setBackgroundImage(LLUIImage* image) { mBgOpaqueImage = image; } + void setTransparentImage(LLUIImage* image) { mBgAlphaImage = image; } LLPointer<LLUIImage> getBackgroundImage() const { return mBgOpaqueImage; } LLPointer<LLUIImage> getTransparentImage() const { return mBgAlphaImage; } LLColor4 getBackgroundImageOverlay() { return mBgOpaqueImageOverlay; } diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index 9d25c7180d..786e18b187 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -29,6 +29,8 @@ #include "llscrolllistcell.h" +#include "lltrans.h" + #include "llcheckboxctrl.h" #include "llui.h" // LLUIImage #include "lluictrlfactory.h" @@ -428,7 +430,13 @@ LLScrollListDate::LLScrollListDate( const LLScrollListCell::Params& p) void LLScrollListDate::setValue(const LLSD& value) { mDate = value.asDate(); - LLScrollListText::setValue(mDate.asRFC1123()); + + std::string date_str = LLTrans::getString("ScrollListCellDateFormat"); + LLSD substitution; + substitution["datetime"] = mDate.secondsSinceEpoch(); + LLStringUtil::format(date_str, substitution); + + LLScrollListText::setValue(date_str); } const LLSD LLScrollListDate::getValue() const diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index d5f8707381..5fc2cc350d 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -98,24 +98,25 @@ class LLCustomButtonIconCtrl : public LLButton { public: struct Params - : public LLInitParam::Block<Params, LLButton::Params> + : public LLInitParam::Block<Params, LLButton::Params> { // LEFT, RIGHT, TOP, BOTTOM paddings of LLIconCtrl in this class has same value Optional<S32> icon_ctrl_pad; - Params(): - icon_ctrl_pad("icon_ctrl_pad", 1) + Params() + : icon_ctrl_pad("icon_ctrl_pad", 1) {} }; protected: friend class LLUICtrlFactory; - LLCustomButtonIconCtrl(const Params& p): - LLButton(p), + + LLCustomButtonIconCtrl(const Params& p) + : LLButton(p), mIcon(NULL), mIconAlignment(LLFontGL::HCENTER), mIconCtrlPad(p.icon_ctrl_pad) - {} + {} public: diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 3b768166f1..0040be45c7 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -598,7 +598,7 @@ S32 LLTextBase::insertStringNoUndo(S32 pos, const LLWString &wstr, LLTextBase::s pos = getEditableIndex(pos, true); - segment_set_t::iterator seg_iter = getSegIterContaining(pos); + segment_set_t::iterator seg_iter = getEditableSegIterContaining(pos); LLTextSegmentPtr default_segment; @@ -1510,8 +1510,48 @@ void LLTextBase::getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg } } +LLTextBase::segment_set_t::iterator LLTextBase::getEditableSegIterContaining(S32 index) +{ + segment_set_t::iterator it = getSegIterContaining(index); + segment_set_t::iterator orig_it = it; + + if (it == mSegments.end()) return it; + + if (!(*it)->canEdit() + && index == (*it)->getStart() + && it != mSegments.begin()) + { + it--; + if ((*it)->canEdit()) + { + return it; + } + } + return orig_it; +} + +LLTextBase::segment_set_t::const_iterator LLTextBase::getEditableSegIterContaining(S32 index) const +{ + segment_set_t::const_iterator it = getSegIterContaining(index); + segment_set_t::const_iterator orig_it = it; + if (it == mSegments.end()) return it; + + if (!(*it)->canEdit() + && index == (*it)->getStart() + && it != mSegments.begin()) + { + it--; + if ((*it)->canEdit()) + { + return it; + } + } + return orig_it; +} + LLTextBase::segment_set_t::iterator LLTextBase::getSegIterContaining(S32 index) { + static LLPointer<LLIndexSegment> index_segment = new LLIndexSegment(); if (index > getLength()) { return mSegments.end(); } diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index b699601908..0549141b72 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -461,6 +461,8 @@ protected: void getSegmentAndOffset( S32 startpos, segment_set_t::const_iterator* seg_iter, S32* offsetp ) const; void getSegmentAndOffset( S32 startpos, segment_set_t::iterator* seg_iter, S32* offsetp ); LLTextSegmentPtr getSegmentAtLocalPos( S32 x, S32 y, bool hit_past_end_of_line = true); + segment_set_t::iterator getEditableSegIterContaining(S32 index); + segment_set_t::const_iterator getEditableSegIterContaining(S32 index) const; segment_set_t::iterator getSegIterContaining(S32 index); segment_set_t::const_iterator getSegIterContaining(S32 index) const; void clearSegments(); diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 486babb0ab..b86d4d0d09 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -121,6 +121,7 @@ LLView::Params::Params() LLView::LLView(const LLView::Params& p) : mVisible(p.visible), + mInDraw(false), mName(p.name), mParentView(NULL), mReshapeFlags(FOLLOWS_NONE), @@ -281,6 +282,8 @@ void LLView::moveChildToBackOfTabGroup(LLUICtrl* child) // virtual bool LLView::addChild(LLView* child, S32 tab_group) { + llassert_always(mInDraw == false); + if (!child) { return false; @@ -330,6 +333,7 @@ bool LLView::addChildInBack(LLView* child, S32 tab_group) // remove the specified child from the view, and set it's parent to NULL. void LLView::removeChild(LLView* child) { + llassert_always(mInDraw == false); //llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs if (child->mParentView == this) { @@ -1081,6 +1085,7 @@ void LLView::draw() void LLView::drawChildren() { + mInDraw = true; if (!mChildList.empty()) { LLView* rootp = LLUI::getRootView(); @@ -1090,6 +1095,11 @@ void LLView::drawChildren() { child_list_reverse_iter_t child = child_iter++; LLView *viewp = *child; + + if (viewp == NULL) + { + continue; + } if (viewp->getVisible() && viewp->getRect().isValid()) { @@ -1119,6 +1129,7 @@ void LLView::drawChildren() } --sDepth; } + mInDraw = false; } void LLView::dirtyRect() diff --git a/indra/llui/llview.h b/indra/llui/llview.h index f21fb37e18..f1fac5f69c 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -612,6 +612,8 @@ private: S32 mNextInsertionOrdinal; + bool mInDraw; + static LLWindow* sWindow; // All root views must know about their window. typedef std::map<std::string, LLView*> default_widget_map_t; diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp index cf76202215..f39499e50c 100644 --- a/indra/llui/llwindowshade.cpp +++ b/indra/llui/llwindowshade.cpp @@ -37,10 +37,13 @@ const S32 MIN_NOTIFICATION_AREA_HEIGHT = 30; const S32 MAX_NOTIFICATION_AREA_HEIGHT = 100; +static LLDefaultChildRegistry::Register<LLWindowShade> r("window_shade"); + LLWindowShade::Params::Params() : bg_image("bg_image"), modal("modal", false), text_color("text_color"), + shade_color("shade_color"), can_close("can_close", true) { changeDefault(mouse_opaque, false); @@ -48,7 +51,6 @@ LLWindowShade::Params::Params() LLWindowShade::LLWindowShade(const LLWindowShade::Params& params) : LLUICtrl(params), - mNotification(params.notification), mModal(params.modal), mFormHeight(0), mTextColor(params.text_color) @@ -72,7 +74,7 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params) addChild(stackp); LLLayoutPanel::Params panel_p; - panel_p.rect = LLRect(0, 30, 800, 0); + panel_p.rect = LLRect(0, MIN_NOTIFICATION_AREA_HEIGHT, 800, 0); panel_p.name = "notification_area"; panel_p.visible = false; panel_p.user_resize = false; @@ -89,7 +91,7 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params) panel_p.name = "background_area"; panel_p.mouse_opaque = false; panel_p.background_visible = false; - panel_p.bg_alpha_color = LLColor4(0.f, 0.f, 0.f, 0.2f); + panel_p.bg_alpha_color = params.shade_color; LLLayoutPanel* dummy_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p); stackp->addChild(dummy_panel); @@ -107,11 +109,11 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params) LLIconCtrl::Params icon_p; icon_p.name = "notification_icon"; - icon_p.rect = LLRect(5, 23, 21, 8); + icon_p.rect = LLRect(5, 25, 21, 10); panel->addChild(LLUICtrlFactory::create<LLIconCtrl>(icon_p)); LLTextBox::Params text_p; - text_p.rect = LLRect(31, 20, panel->getRect().getWidth() - 5, 0); + text_p.rect = LLRect(31, 23, panel->getRect().getWidth() - 5, 3); text_p.follows.flags = FOLLOWS_ALL; text_p.text_color = mTextColor; text_p.font = LLFontGL::getFontSansSerifSmall(); @@ -125,41 +127,132 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params) panel_p.auto_resize = false; panel_p.user_resize = false; panel_p.name="form_elements"; - panel_p.rect = LLRect(0, 30, 130, 0); + panel_p.rect = LLRect(0, MIN_NOTIFICATION_AREA_HEIGHT, 130, 0); LLLayoutPanel* form_elements_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p); stackp->addChild(form_elements_panel); - if (params.can_close) + panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>(); + panel_p.auto_resize = false; + panel_p.user_resize = false; + panel_p.rect = LLRect(0, MIN_NOTIFICATION_AREA_HEIGHT, 25, 0); + panel_p.name = "close_panel"; + LLLayoutPanel* close_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p); + stackp->addChild(close_panel); + + LLButton::Params button_p; + button_p.name = "close_notification"; + button_p.rect = LLRect(5, 23, 21, 7); + button_p.image_color.control="DkGray_66"; + button_p.image_unselected.name="Icon_Close_Foreground"; + button_p.image_selected.name="Icon_Close_Press"; + button_p.click_callback.function = boost::bind(&LLWindowShade::onCloseNotification, this); + + close_panel->addChild(LLUICtrlFactory::create<LLButton>(button_p)); + + close_panel->setVisible(params.can_close); +} + +void LLWindowShade::draw() +{ + LLRect message_rect = getChild<LLTextBox>("notification_text")->getTextBoundingRect(); + + LLLayoutPanel* notification_area = getChild<LLLayoutPanel>("notification_area"); + + notification_area->reshape(notification_area->getRect().getWidth(), + llclamp(message_rect.getHeight() + 15, + llmin(mFormHeight, MAX_NOTIFICATION_AREA_HEIGHT), + MAX_NOTIFICATION_AREA_HEIGHT)); + + LLUICtrl::draw(); + + while(!mNotifications.empty() && !mNotifications.back()->isActive()) { - panel_p = LLUICtrlFactory::getDefaultParams<LLLayoutPanel>(); - panel_p.auto_resize = false; - panel_p.user_resize = false; - panel_p.rect = LLRect(0, 30, 25, 0); - LLLayoutPanel* close_panel = LLUICtrlFactory::create<LLLayoutPanel>(panel_p); - stackp->addChild(close_panel); - - LLButton::Params button_p; - button_p.name = "close_notification"; - button_p.rect = LLRect(5, 23, 21, 7); - button_p.image_color.control="DkGray_66"; - button_p.image_unselected.name="Icon_Close_Foreground"; - button_p.image_selected.name="Icon_Close_Press"; - button_p.click_callback.function = boost::bind(&LLWindowShade::onCloseNotification, this); - - close_panel->addChild(LLUICtrlFactory::create<LLButton>(button_p)); + mNotifications.pop_back(); + // go ahead and hide + hide(); } - LLSD payload = mNotification->getPayload(); + if (mNotifications.empty()) + { + hide(); + } + else if (notification_area->getCollapseFactor() < 0.01f) + { + displayLatestNotification(); + } + + if (!notification_area->getVisible() && (notification_area->getCollapseFactor() < 0.001f)) + { + getChildRef<LLLayoutPanel>("background_area").setBackgroundVisible(false); + setMouseOpaque(false); + } +} + +void LLWindowShade::hide() +{ + getChildRef<LLLayoutPanel>("notification_area").setVisible(false); +} + +void LLWindowShade::onCloseNotification() +{ + if (!mNotifications.empty()) + LLNotifications::instance().cancel(mNotifications.back()); +} + +void LLWindowShade::onClickIgnore(LLUICtrl* ctrl) +{ + LLNotificationPtr notify = getCurrentNotification(); + if (!notify) return; + + bool check = ctrl->getValue().asBoolean(); + if (notify->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN) + { + // question was "show again" so invert value to get "ignore" + check = !check; + } + notify->setIgnored(check); +} + +void LLWindowShade::onClickNotificationButton(const std::string& name) +{ + LLNotificationPtr notify = getCurrentNotification(); + if (!notify) return; + + mNotificationResponse[name] = true; + + notify->respond(mNotificationResponse); +} + +void LLWindowShade::onEnterNotificationText(LLUICtrl* ctrl, const std::string& name) +{ + mNotificationResponse[name] = ctrl->getValue().asString(); +} + +void LLWindowShade::show(LLNotificationPtr notification) +{ + mNotifications.push_back(notification); + + displayLatestNotification(); +} + +void LLWindowShade::displayLatestNotification() +{ + if (mNotifications.empty()) return; + + LLNotificationPtr notification = mNotifications.back(); - LLNotificationFormPtr formp = mNotification->getForm(); + LLSD payload = notification->getPayload(); + + LLNotificationFormPtr formp = notification->getForm(); LLLayoutPanel& notification_area = getChildRef<LLLayoutPanel>("notification_area"); - notification_area.getChild<LLUICtrl>("notification_icon")->setValue(mNotification->getIcon()); - notification_area.getChild<LLUICtrl>("notification_text")->setValue(mNotification->getMessage()); - notification_area.getChild<LLUICtrl>("notification_text")->setToolTip(mNotification->getMessage()); + notification_area.getChild<LLUICtrl>("notification_icon")->setValue(notification->getIcon()); + notification_area.getChild<LLUICtrl>("notification_text")->setValue(notification->getMessage()); + notification_area.getChild<LLUICtrl>("notification_text")->setToolTip(notification->getMessage()); LLNotificationForm::EIgnoreType ignore_type = formp->getIgnoreType(); LLLayoutPanel& form_elements = notification_area.getChildRef<LLLayoutPanel>("form_elements"); form_elements.deleteAllChildren(); + form_elements.reshape(form_elements.getRect().getWidth(), MIN_NOTIFICATION_AREA_HEIGHT); const S32 FORM_PADDING_HORIZONTAL = 10; const S32 FORM_PADDING_VERTICAL = 3; @@ -229,7 +322,7 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params) label_p.v_pad = 5; LLTextBox* textbox = LLUICtrlFactory::create<LLTextBox>(label_p); textbox->reshapeToFitText(); - textbox->reshape(textbox->getRect().getWidth(), form_elements.getRect().getHeight() - 2 * FORM_PADDING_VERTICAL); + textbox->reshape(textbox->getRect().getWidth(), MIN_NOTIFICATION_AREA_HEIGHT - 2 * FORM_PADDING_VERTICAL); form_elements.addChild(textbox); cur_x = textbox->getRect().mRight + FORM_PADDING_HORIZONTAL; @@ -249,7 +342,7 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params) } } - mFormHeight = form_elements.getRect().getHeight() - (cur_y - FORM_PADDING_VERTICAL) + WIDGET_HEIGHT; + mFormHeight = form_elements.getRect().getHeight() - (cur_y - WIDGET_HEIGHT - FORM_PADDING_VERTICAL); form_elements.reshape(form_width, mFormHeight); form_elements.setMinDim(form_width); @@ -261,68 +354,39 @@ void LLWindowShade::initFromParams(const LLWindowShade::Params& params) { (*it)->translate(0, delta_y); } -} -void LLWindowShade::show() -{ getChildRef<LLLayoutPanel>("notification_area").setVisible(true); getChildRef<LLLayoutPanel>("background_area").setBackgroundVisible(mModal); setMouseOpaque(mModal); } -void LLWindowShade::draw() +void LLWindowShade::setBackgroundImage(LLUIImage* image) { - LLRect message_rect = getChild<LLTextBox>("notification_text")->getTextBoundingRect(); - - LLLayoutPanel* notification_area = getChild<LLLayoutPanel>("notification_area"); - - notification_area->reshape(notification_area->getRect().getWidth(), - llclamp(message_rect.getHeight() + 10, - llmin(mFormHeight, MAX_NOTIFICATION_AREA_HEIGHT), - MAX_NOTIFICATION_AREA_HEIGHT)); - - LLUICtrl::draw(); - if (mNotification && !mNotification->isActive()) - { - hide(); - } + getChild<LLLayoutPanel>("notification_area")->setTransparentImage(image); } -void LLWindowShade::hide() +void LLWindowShade::setTextColor(LLColor4 color) { - getChildRef<LLLayoutPanel>("notification_area").setVisible(false); - getChildRef<LLLayoutPanel>("background_area").setBackgroundVisible(false); - - setMouseOpaque(false); + getChild<LLTextBox>("notification_text")->setColor(color); } -void LLWindowShade::onCloseNotification() +bool LLWindowShade::isShown() const { - LLNotifications::instance().cancel(mNotification); + return getChildRef<LLLayoutPanel>("notification_area").getVisible(); } -void LLWindowShade::onClickIgnore(LLUICtrl* ctrl) +void LLWindowShade::setCanClose(bool can_close) { - bool check = ctrl->getValue().asBoolean(); - if (mNotification && mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN) - { - // question was "show again" so invert value to get "ignore" - check = !check; - } - mNotification->setIgnored(check); + getChildView("close_panel")->setVisible(can_close); } -void LLWindowShade::onClickNotificationButton(const std::string& name) +LLNotificationPtr LLWindowShade::getCurrentNotification() { - if (!mNotification) return; - - mNotificationResponse[name] = true; - - mNotification->respond(mNotificationResponse); + if (mNotifications.empty()) + { + return LLNotificationPtr(); + } + return mNotifications.back(); } -void LLWindowShade::onEnterNotificationText(LLUICtrl* ctrl, const std::string& name) -{ - mNotificationResponse[name] = ctrl->getValue().asString(); -} diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h index 09ffc2cd54..6d753d1161 100644 --- a/indra/llui/llwindowshade.h +++ b/indra/llui/llwindowshade.h @@ -36,20 +36,28 @@ class LLWindowShade : public LLUICtrl public: struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> { - Mandatory<LLNotificationPtr> notification; Optional<LLUIImage*> bg_image; - Optional<LLUIColor> text_color; + Optional<LLUIColor> text_color, + shade_color; Optional<bool> modal, can_close; Params(); }; - void show(); + void show(LLNotificationPtr); /*virtual*/ void draw(); void hide(); + + bool isShown() const; + + void setBackgroundImage(LLUIImage* image); + void setTextColor(LLColor4 color); + void setCanClose(bool can_close); private: + void displayLatestNotification(); + LLNotificationPtr getCurrentNotification(); friend class LLUICtrlFactory; LLWindowShade(const Params& p); @@ -60,7 +68,7 @@ private: void onEnterNotificationText(LLUICtrl* ctrl, const std::string& name); void onClickIgnore(LLUICtrl* ctrl); - LLNotificationPtr mNotification; + std::vector<LLNotificationPtr> mNotifications; LLSD mNotificationResponse; bool mModal; S32 mFormHeight; diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 1351bed547..2e9e31bfea 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -186,8 +186,8 @@ BOOL LLWindow::setSize(LLCoordScreen size) { if (!getMaximized()) { - size.mX = llmin(size.mX, mMinWindowWidth); - size.mY = llmin(size.mY, mMinWindowHeight); + size.mX = llmax(size.mX, mMinWindowWidth); + size.mY = llmax(size.mY, mMinWindowHeight); } return setSizeImpl(size); } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 6b2fe1e45a..0a4874ae92 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -216,6 +216,7 @@ set(viewer_SOURCE_FILES llfloaternotificationsconsole.cpp llfloaterobjectweights.cpp llfloateropenobject.cpp + llfloateroutbox.cpp llfloaterpay.cpp llfloaterperms.cpp llfloaterpostprocess.cpp @@ -314,6 +315,7 @@ set(viewer_SOURCE_FILES llmaniprotate.cpp llmanipscale.cpp llmaniptranslate.cpp + llmarketplacefunctions.cpp llmediactrl.cpp llmediadataclient.cpp llmemoryview.cpp @@ -770,6 +772,7 @@ set(viewer_HEADER_FILES llfloaternotificationsconsole.h llfloaterobjectweights.h llfloateropenobject.h + llfloateroutbox.h llfloaterpay.h llfloaterperms.h llfloaterpostprocess.h @@ -868,6 +871,7 @@ set(viewer_HEADER_FILES llmaniprotate.h llmanipscale.h llmaniptranslate.h + llmarketplacefunctions.h llmediactrl.h llmediadataclient.h llmemoryview.h diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index a44b895f7b..1d1d39c786 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -135,6 +135,16 @@ is_running_function="Floater.IsOpen" is_running_parameters="moveview" /> + <command name="outbox" + available_in_toybox="false" + icon="Command_Outbox_Icon" + label_ref="Command_Outbox_Label" + tooltip_ref="Command_Outbox_Tooltip" + execute_function="Floater.ToggleOrBringToFront" + execute_parameters="outbox" + is_running_function="Floater.IsOpen" + is_running_parameters="outbox" + /> <command name="people" available_in_toybox="true" icon="Command_People_Icon" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index aa8ad53a3d..e5bb686123 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1150,6 +1150,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>EnableButtonFlashing</key> + <map> + <key>Comment</key> + <string>Allow UI to flash buttons to get your attention</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>ButtonHPad</key> <map> <key>Comment</key> @@ -4260,16 +4271,49 @@ <key>Value</key> <integer>0</integer> </map> - <key>InventoryMarketplaceUserStatus</key> + <key>InventoryOutboxLogging</key> + <map> + <key>Comment</key> + <string>Enable debug output associated with the Merchant Outbox.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>InventoryOutboxMaxFolderCount</key> <map> <key>Comment</key> - <string>Marketplace user status.</string> + <string>Maximum number of subfolders allowed in a listing in the merchant outbox.</string> <key>Persist</key> - <integer>1</integer> + <integer>0</integer> <key>Type</key> - <string>String</string> + <string>U32</string> <key>Value</key> - <string /> + <integer>20</integer> + </map> + <key>InventoryOutboxMaxFolderDepth</key> + <map> + <key>Comment</key> + <string>Maximum number of nested levels of subfolders allowed in a listing in the merchant outbox.</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>4</integer> + </map> + <key>InventoryOutboxMaxItemCount</key> + <map> + <key>Comment</key> + <string>Maximum number of items allowed in a listing in the merchant outbox.</string> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>200</integer> </map> <key>InventorySortOrder</key> <map> diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 0861fe85a8..637dd06651 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -45,6 +45,7 @@ #include "llwindow.h" #include "llviewerstats.h" #include "llviewerstatsrecorder.h" +#include "llmarketplacefunctions.h" #include "llmd5.h" #include "llmeshrepository.h" #include "llpumpio.h" @@ -1044,21 +1045,14 @@ bool LLAppViewer::init() LLTextUtil::TextHelpers::iconCallbackCreationFunction = create_text_segment_icon_from_url_match; - //EXT-7013 - On windows for some locale (Japanese) standard - //datetime formatting functions didn't support some parameters such as "weekday". - //Names for days and months localized in xml are also useful for Polish locale(STORM-107). - std::string language = gSavedSettings.getString("Language"); - if(language == "ja" || language == "pl") - { - LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames")); - LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames")); - LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames")); - LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames")); - LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat")); + LLStringOps::setupWeekDaysNames(LLTrans::getString("dateTimeWeekdaysNames")); + LLStringOps::setupWeekDaysShortNames(LLTrans::getString("dateTimeWeekdaysShortNames")); + LLStringOps::setupMonthNames(LLTrans::getString("dateTimeMonthNames")); + LLStringOps::setupMonthShortNames(LLTrans::getString("dateTimeMonthShortNames")); + LLStringOps::setupDayFormat(LLTrans::getString("dateTimeDayFormat")); - LLStringOps::sAM = LLTrans::getString("dateTimeAM"); - LLStringOps::sPM = LLTrans::getString("dateTimePM"); - } + LLStringOps::sAM = LLTrans::getString("dateTimeAM"); + LLStringOps::sPM = LLTrans::getString("dateTimePM"); LLAgentLanguage::init(); @@ -4402,6 +4396,9 @@ void LLAppViewer::idle() // update media focus LLViewerMediaFocus::getInstance()->update(); + + // Update marketplace importer + LLMarketplaceInventoryImporter::update(); // objects and camera should be in sync, do LOD calculations now { diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 8ca621538f..9a7cdcfa21 100755 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -680,12 +680,29 @@ namespace action_give_inventory std::string items; build_items_string(inventory_selected_uuids, items); + int folders_count = 0; + std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); + + //traverse through selected inventory items and count folders among them + for ( ; it != inventory_selected_uuids.end() && folders_count <=1 ; ++it) + { + LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it); + if (NULL != inv_cat) + { + folders_count++; + } + } + + // EXP-1599 + // In case of sharing multiple folders, make the confirmation + // dialog contain a warning that only one folder can be shared at a time. + std::string notification = (folders_count > 1) ? "ShareFolderConfirmation" : "ShareItemsConfirmation"; LLSD substitutions; substitutions["RESIDENTS"] = residents; substitutions["ITEMS"] = items; LLShareInfo::instance().mAvatarNames = avatar_names; LLShareInfo::instance().mAvatarUuids = avatar_uuids; - LLNotificationsUtil::add("ShareItemsConfirmation", substitutions, LLSD(), &give_inventory_cb); + LLNotificationsUtil::add(notification, substitutions, LLSD(), &give_inventory_cb); } } @@ -707,7 +724,7 @@ std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs() LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); if (sidepanel_inventory) { - inventory_selected_uuids = sidepanel_inventory->getInboxOrOutboxSelectionList(); + inventory_selected_uuids = sidepanel_inventory->getInboxSelectionList(); } } diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index 045c9017be..aabab0ccb9 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -302,6 +302,13 @@ void LLIMWellChiclet::createMenu() void LLIMWellChiclet::messageCountChanged(const LLSD& session_data) { + // The singleton class LLChicletBar instance might be already deleted + // so don't create a new one. + if (!LLChicletBar::instanceExists()) + { + return; + } + const LLUUID& session_id = session_data["session_id"]; const S32 counter = LLChicletBar::getInstance()->getTotalUnreadIMCount(); const bool im_not_visible = !LLFloaterReg::instanceVisible("im_container") diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp index 4f2fd47488..f4b6dc2c81 100644 --- a/indra/newview/llfavoritesbar.cpp +++ b/indra/newview/llfavoritesbar.cpp @@ -405,8 +405,8 @@ LLFavoritesBarCtrl::~LLFavoritesBarCtrl() { gInventory.removeObserver(this); - delete mOverflowMenuHandle.get(); - delete mContextMenuHandle.get(); + if (mOverflowMenuHandle.get()) mOverflowMenuHandle.get()->die(); + if (mContextMenuHandle.get()) mContextMenuHandle.get()->die(); } BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index 659e52271a..05d73c2416 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -271,7 +271,7 @@ void LLFloaterColorPicker::destroyUI () if ( mSwatchView ) { this->removeChild ( mSwatchView ); - delete mSwatchView; + mSwatchView->die();; mSwatchView = NULL; } } diff --git a/indra/newview/llfloateroutbox.cpp b/indra/newview/llfloateroutbox.cpp new file mode 100644 index 0000000000..8ccebb36dc --- /dev/null +++ b/indra/newview/llfloateroutbox.cpp @@ -0,0 +1,514 @@ +/** + * @file llfloateroutbox.cpp + * @brief Implementation of the merchant outbox window + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloateroutbox.h" + +#include "llfloaterreg.h" +#include "llfolderview.h" +#include "llinventorybridge.h" +#include "llinventorymodelbackgroundfetch.h" +#include "llinventoryobserver.h" +#include "llinventorypanel.h" +#include "llmarketplacefunctions.h" +#include "llnotificationhandler.h" +#include "llnotificationmanager.h" +#include "llnotificationsutil.h" +#include "lltextbox.h" +#include "lltransientfloatermgr.h" +#include "lltrans.h" +#include "llviewernetwork.h" +#include "llwindowshade.h" + +#define USE_WINDOWSHADE_DIALOGS 0 + + +///---------------------------------------------------------------------------- +/// LLOutboxNotification class +///---------------------------------------------------------------------------- + +bool LLNotificationsUI::LLOutboxNotification::processNotification(const LLSD& notify) +{ + LLFloaterOutbox* outbox_floater = LLFloaterReg::getTypedInstance<LLFloaterOutbox>("outbox"); + + outbox_floater->showNotification(notify); + + return false; +} + + +///---------------------------------------------------------------------------- +/// LLOutboxAddedObserver helper class +///---------------------------------------------------------------------------- + +class LLOutboxAddedObserver : public LLInventoryCategoryAddedObserver +{ +public: + LLOutboxAddedObserver(LLFloaterOutbox * outboxFloater) + : LLInventoryCategoryAddedObserver() + , mOutboxFloater(outboxFloater) + { + } + + void done() + { + for (cat_vec_t::iterator it = mAddedCategories.begin(); it != mAddedCategories.end(); ++it) + { + LLViewerInventoryCategory* added_category = *it; + + LLFolderType::EType added_category_type = added_category->getPreferredType(); + + if (added_category_type == LLFolderType::FT_OUTBOX) + { + mOutboxFloater->setupOutbox(added_category->getUUID()); + } + } + } + +private: + LLFloaterOutbox * mOutboxFloater; +}; + +///---------------------------------------------------------------------------- +/// LLFloaterOutbox +///---------------------------------------------------------------------------- + +LLFloaterOutbox::LLFloaterOutbox(const LLSD& key) + : LLFloater(key) + , mCategoriesObserver(NULL) + , mCategoryAddedObserver(NULL) + , mImportBusy(false) + , mImportButton(NULL) + , mInventoryFolderCountText(NULL) + , mInventoryImportInProgress(NULL) + , mInventoryPlaceholder(NULL) + , mInventoryText(NULL) + , mInventoryTitle(NULL) + , mOutboxId(LLUUID::null) + , mOutboxInventoryPanel(NULL) + , mOutboxItemCount(0) + , mWindowShade(NULL) +{ +} + +LLFloaterOutbox::~LLFloaterOutbox() +{ + if (mCategoriesObserver && gInventory.containsObserver(mCategoriesObserver)) + { + gInventory.removeObserver(mCategoriesObserver); + } + delete mCategoriesObserver; + + if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) + { + gInventory.removeObserver(mCategoryAddedObserver); + } + delete mCategoryAddedObserver; +} + +BOOL LLFloaterOutbox::postBuild() +{ + mInventoryFolderCountText = getChild<LLTextBox>("outbox_folder_count"); + mInventoryImportInProgress = getChild<LLView>("import_progress_indicator"); + mInventoryPlaceholder = getChild<LLView>("outbox_inventory_placeholder_panel"); + mInventoryText = mInventoryPlaceholder->getChild<LLTextBox>("outbox_inventory_placeholder_text"); + mInventoryTitle = mInventoryPlaceholder->getChild<LLTextBox>("outbox_inventory_placeholder_title"); + + mImportButton = getChild<LLButton>("outbox_import_btn"); + mImportButton->setCommitCallback(boost::bind(&LLFloaterOutbox::onImportButtonClicked, this)); + + LLFocusableElement::setFocusReceivedCallback(boost::bind(&LLFloaterOutbox::onFocusReceived, this)); + + return TRUE; +} + +void LLFloaterOutbox::onClose(bool app_quitting) +{ + if (mWindowShade) + { + delete mWindowShade; + + mWindowShade = NULL; + } +} + +void LLFloaterOutbox::onOpen(const LLSD& key) +{ + // + // Look for an outbox and set up the inventory API + // + + if (mOutboxId.isNull()) + { + const bool do_not_create_folder = false; + const bool do_not_find_in_library = false; + + const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library); + + if (outbox_id.isNull()) + { + // Observe category creation to catch outbox creation + mCategoryAddedObserver = new LLOutboxAddedObserver(this); + gInventory.addObserver(mCategoryAddedObserver); + } + else + { + setupOutbox(outbox_id); + } + } + + updateView(); + + // + // Trigger fetch of outbox contents + // + + fetchOutboxContents(); +} + +void LLFloaterOutbox::onFocusReceived() +{ + fetchOutboxContents(); +} + +void LLFloaterOutbox::fetchOutboxContents() +{ + if (mOutboxId.notNull()) + { + LLInventoryModelBackgroundFetch::instance().start(mOutboxId); + } +} + +void LLFloaterOutbox::setupOutbox(const LLUUID& outboxId) +{ + llassert(outboxId.notNull()); + llassert(mOutboxId.isNull()); + llassert(mCategoriesObserver == NULL); + + mOutboxId = outboxId; + + // No longer need to observe new category creation + if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) + { + gInventory.removeObserver(mCategoryAddedObserver); + delete mCategoryAddedObserver; + mCategoryAddedObserver = NULL; + } + + // Create observer for outbox modifications + mCategoriesObserver = new LLInventoryCategoriesObserver(); + gInventory.addObserver(mCategoriesObserver); + + mCategoriesObserver->addCategory(mOutboxId, boost::bind(&LLFloaterOutbox::onOutboxChanged, this)); + + // + // Set up the outbox inventory view + // + + mOutboxInventoryPanel = + LLUICtrlFactory::createFromFile<LLInventoryPanel>("panel_outbox_inventory.xml", + mInventoryPlaceholder->getParent(), + LLInventoryPanel::child_registry_t::instance()); + + llassert(mOutboxInventoryPanel); + + // Reshape the inventory to the proper size + LLRect inventory_placeholder_rect = mInventoryPlaceholder->getRect(); + mOutboxInventoryPanel->setShape(inventory_placeholder_rect); + + // Set the sort order newest to oldest + mOutboxInventoryPanel->setSortOrder(LLInventoryFilter::SO_FOLDERS_BY_NAME); + mOutboxInventoryPanel->getFilter()->markDefault(); + + fetchOutboxContents(); + + // + // Initialize the marketplace import API + // + + mImportBusy = true; + setStatusString(getString("OutboxInitializing")); + + LLMarketplaceInventoryImporter::getInstance()->initialize(); + LLMarketplaceInventoryImporter::getInstance()->setStatusChangedCallback(boost::bind(&LLFloaterOutbox::importStatusChanged, this, _1)); + LLMarketplaceInventoryImporter::getInstance()->setStatusReportCallback(boost::bind(&LLFloaterOutbox::importReportResults, this, _1, _2)); +} + +void LLFloaterOutbox::setStatusString(const std::string& statusString) +{ + llassert(mInventoryFolderCountText != NULL); + + mInventoryFolderCountText->setText(statusString); +} + +void LLFloaterOutbox::updateFolderCount() +{ + S32 item_count = 0; + + if (mOutboxId.notNull()) + { + LLInventoryModel::cat_array_t * cats; + LLInventoryModel::item_array_t * items; + gInventory.getDirectDescendentsOf(mOutboxId, cats, items); + + item_count = cats->count() + items->count(); + } + + mOutboxItemCount = item_count; + + if (mOutboxInventoryPanel) + { + switch (mOutboxItemCount) + { + case 0: setStatusString(getString("OutboxFolderCount0")); break; + case 1: setStatusString(getString("OutboxFolderCount1")); break; + default: + { + std::string item_count_str = llformat("%d", mOutboxItemCount); + + LLStringUtil::format_map_t args; + args["[NUM]"] = item_count_str; + + setStatusString(getString("OutboxFolderCountN", args)); + break; + } + } + } + + mImportButton->setEnabled(mOutboxItemCount > 0); +} + +void LLFloaterOutbox::updateView() +{ + if (!mImportBusy) + { + updateFolderCount(); + } + + if (mOutboxItemCount > 0) + { + mOutboxInventoryPanel->setVisible(TRUE); + mInventoryPlaceholder->setVisible(FALSE); + } + else + { + if (mOutboxInventoryPanel) + { + mOutboxInventoryPanel->setVisible(FALSE); + } + + mInventoryPlaceholder->setVisible(TRUE); + + std::string outbox_text; + std::string outbox_title; + std::string outbox_tooltip; + + LLStringUtil::format_map_t subs = getMarketplaceStringSubstitutions(); + + if (mOutboxId.notNull()) + { + outbox_text = LLTrans::getString("InventoryOutboxNoItems", subs); + outbox_title = LLTrans::getString("InventoryOutboxNoItemsTitle"); + outbox_tooltip = LLTrans::getString("InventoryOutboxNoItemsTooltip"); + } + else + { + outbox_text = LLTrans::getString("InventoryOutboxNotMerchant", subs); + outbox_title = LLTrans::getString("InventoryOutboxNotMerchantTitle"); + outbox_tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip"); + } + + mInventoryText->setValue(outbox_text); + mInventoryTitle->setValue(outbox_title); + mInventoryPlaceholder->getParent()->setToolTip(outbox_tooltip); + } +} + +BOOL LLFloaterOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + if ((mOutboxInventoryPanel == NULL) || + (mWindowShade && mWindowShade->isShown()) || + LLMarketplaceInventoryImporter::getInstance()->isImportInProgress()) + { + return FALSE; + } + + LLView * handled_view = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + BOOL handled = (handled_view != NULL); + + // Pass all drag and drop for this floater to the outbox inventory control + if (!handled || (*accept == ACCEPT_NO)) + { + // Always assume we are going to move the drag and drop operation to the outbox root folder + bool move_to_root = true; + + // If the inventory panel is visible, then only override it to the outbox root if we're outside the inventory panel + // (otherwise the inventory panel itself will handle the drag and drop operation, without any override) + if (mOutboxInventoryPanel->getVisible()) + { + S32 inv_x, inv_y; + localPointToOtherView(x, y, &inv_x, &inv_y, mOutboxInventoryPanel); + + const LLRect& inv_rect = mOutboxInventoryPanel->getRect(); + + move_to_root = !inv_rect.pointInRect(inv_x, inv_y); + } + + // Handle the drag and drop directly to the root of the outbox + if (move_to_root) + { + LLFolderView * root_folder = mOutboxInventoryPanel->getRootFolder(); + + handled = root_folder->handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } + } + + return handled; +} + +void LLFloaterOutbox::onImportButtonClicked() +{ + mOutboxInventoryPanel->clearSelection(); + + LLMarketplaceInventoryImporter::instance().triggerImport(); +} + +void LLFloaterOutbox::onOutboxChanged() +{ + llassert(!mOutboxId.isNull()); + + if (mOutboxInventoryPanel) + { + mOutboxInventoryPanel->requestSort(); + } + + fetchOutboxContents(); + + updateView(); +} + +void LLFloaterOutbox::importReportResults(U32 status, const LLSD& content) +{ + if (status == MarketplaceErrorCodes::IMPORT_DONE) + { + LLNotificationsUtil::add("OutboxImportComplete"); + } + else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS) + { + LLNotificationsUtil::add("OutboxImportHadErrors"); + } + else + { + char status_string[16]; + sprintf(status_string, "%d", status); + + LLSD subs; + subs["[ERROR_CODE]"] = status_string; + + //llassert(status == MarketplaceErrorCodes::IMPORT_JOB_FAILED); + LLNotificationsUtil::add("OutboxImportFailed", subs); + } + + updateView(); +} + +void LLFloaterOutbox::importStatusChanged(bool inProgress) +{ + if (inProgress) + { + if (!mImportBusy) + { + setStatusString(getString("OutboxImporting")); + } + + mImportBusy = true; + mImportButton->setEnabled(false); + mInventoryImportInProgress->setVisible(true); + } + else + { + mImportBusy = false; + mImportButton->setEnabled(mOutboxItemCount > 0); + mInventoryImportInProgress->setVisible(false); + + updateView(); + } +} + +void LLFloaterOutbox::showNotification(const LLSD& notify) +{ + LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); + + if (!notification) + { + llerrs << "Unable to find outbox notification!" << notify.asString() << llendl; + + return; + } + +#if USE_WINDOWSHADE_DIALOGS + + if (mWindowShade) + { + delete mWindowShade; + } + + LLRect floater_rect = getLocalRect(); + floater_rect.mTop -= getHeaderHeight(); + floater_rect.stretch(-5, 0); + + LLWindowShade::Params params; + params.name = "notification_shade"; + params.rect = floater_rect; + params.follows.flags = FOLLOWS_ALL; + params.modal = true; + params.can_close = false; + params.shade_color = LLColor4::white % 0.25f; + params.text_color = LLColor4::white; + + mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params); + + addChild(mWindowShade); + mWindowShade->show(notification); + +#else + + LLNotificationsUI::LLEventHandler * handler = + LLNotificationsUI::LLNotificationManager::instance().getHandlerForNotification("alertmodal"); + + LLNotificationsUI::LLSysHandler * sys_handler = dynamic_cast<LLNotificationsUI::LLSysHandler *>(handler); + llassert(sys_handler); + + sys_handler->processNotification(notify); + +#endif +} + diff --git a/indra/newview/llfloateroutbox.h b/indra/newview/llfloateroutbox.h new file mode 100644 index 0000000000..cc4a7207ca --- /dev/null +++ b/indra/newview/llfloateroutbox.h @@ -0,0 +1,108 @@ +/** + * @file llfloateroutbox.h + * @brief LLFloaterOutbox + * class definition + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * ABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLFLOATEROUTBOX_H +#define LL_LLFLOATEROUTBOX_H + +#include "llfloater.h" +#include "llfoldertype.h" +#include "llnotificationptr.h" + + +class LLButton; +class LLInventoryCategoriesObserver; +class LLInventoryCategoryAddedObserver; +class LLInventoryPanel; +class LLLoadingIndicator; +class LLNotification; +class LLTextBox; +class LLView; +class LLWindowShade; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFloaterOutbox +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLFloaterOutbox : public LLFloater +{ +public: + LLFloaterOutbox(const LLSD& key); + ~LLFloaterOutbox(); + + void setupOutbox(const LLUUID& outboxId); + + // virtuals + BOOL postBuild(); + BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); + + void showNotification(const LLSD& notify); + +protected: + void fetchOutboxContents(); + + void importReportResults(U32 status, const LLSD& content); + void importStatusChanged(bool inProgress); + + void onClose(bool app_quitting); + void onOpen(const LLSD& key); + + void onFocusReceived(); + + void onImportButtonClicked(); + void onOutboxChanged(); + + void setStatusString(const std::string& statusString); + + void updateFolderCount(); + void updateView(); + +private: + LLInventoryCategoriesObserver * mCategoriesObserver; + LLInventoryCategoryAddedObserver * mCategoryAddedObserver; + + bool mImportBusy; + LLButton * mImportButton; + + LLTextBox * mInventoryFolderCountText; + LLView * mInventoryImportInProgress; + LLView * mInventoryPlaceholder; + LLTextBox * mInventoryText; + LLTextBox * mInventoryTitle; + + LLUUID mOutboxId; + LLInventoryPanel * mOutboxInventoryPanel; + U32 mOutboxItemCount; + + LLWindowShade * mWindowShade; +}; + +#endif // LL_LLFLOATEROUTBOX_H diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index cc7a1b2368..d8d62e5bbb 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -1489,6 +1489,12 @@ void LLFloaterSnapshot::Impl::setNeedRefresh(LLFloaterSnapshot* floater, bool ne { if (!floater) return; + // Don't display the "Refresh to save" message if we're in auto-refresh mode. + if (gSavedSettings.getBOOL("AutoSnapshot")) + { + need = false; + } + floater->mRefreshLabel->setVisible(need); floater->impl.mNeedRefresh = need; } @@ -1984,7 +1990,7 @@ LLFloaterSnapshot::LLFloaterSnapshot(const LLSD& key) // Destroys the object LLFloaterSnapshot::~LLFloaterSnapshot() { - delete impl.mPreviewHandle.get(); + if (impl.mPreviewHandle.get()) impl.mPreviewHandle.get()->die(); //unfreeze everything else gSavedSettings.setBOOL("FreezeTime", FALSE); @@ -2053,6 +2059,13 @@ BOOL LLFloaterSnapshot::postBuild() gFloaterView->removeChild(this); gSnapshotFloaterView->addChild(this); + // Pre-select "Current Window" resolution. + getChild<LLComboBox>("profile_size_combo")->selectNthItem(0); + getChild<LLComboBox>("postcard_size_combo")->selectNthItem(0); + getChild<LLComboBox>("texture_size_combo")->selectNthItem(0); + getChild<LLComboBox>("local_size_combo")->selectNthItem(0); + getChild<LLComboBox>("local_format_combo")->selectNthItem(0); + impl.mPreviewHandle = previewp->getHandle(); impl.updateControls(this); impl.updateLayout(this); diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index 959edff713..428a02e9f0 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -29,6 +29,7 @@ #include "llfloatertranslationsettings.h" // Viewer includes +#include "llnearbychatbar.h" #include "lltranslate.h" #include "llviewercontrol.h" // for gSavedSettings @@ -292,5 +293,6 @@ void LLFloaterTranslationSettings::onBtnOK() gSavedSettings.setString("TranslationService", getSelectedService()); gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey()); gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); + LLNearbyChatBar::getInstance()->enableTranslationCheckbox(LLTranslate::isTranslationConfigured()); closeFloater(false); } diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index 6ec2598e44..0af20f5de5 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -299,7 +299,7 @@ LLFolderView::~LLFolderView( void ) mAutoOpenItems.removeAllNodes(); gIdleCallbacks.deleteFunction(idle, this); - delete mPopupMenuHandle.get(); + if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); mAutoOpenItems.removeAllNodes(); clearSelection(); @@ -1058,7 +1058,7 @@ void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LL for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { item = *item_it; - if(item->isRemovable()) + if (item && item->isRemovable()) { items.push_back(item); } @@ -1945,9 +1945,9 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, if (!handled) { if (getListener()->getUUID().notNull()) - { - handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); - } + { + handled = LLFolderViewFolder::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg); + } else { if (!mFolders.empty()) @@ -1969,7 +1969,7 @@ BOOL LLFolderView::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, void LLFolderView::deleteAllChildren() { closeRenamer(); - delete mPopupMenuHandle.get(); + if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); mPopupMenuHandle = LLHandle<LLView>(); mScrollContainer = NULL; mRenameItem = NULL; diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index f27fd035db..dc42bb148d 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -2276,33 +2276,16 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, EAcceptance* accept, std::string& tooltip_msg) { - LLFolderView* root_view = getRoot(); - BOOL handled = FALSE; - if(mIsOpen) + + if (mIsOpen) { - handled = childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, - cargo_data, accept, tooltip_msg) != NULL; + handled = (childrenHandleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) != NULL); } if (!handled) { - BOOL accepted = mListener && mListener->dragOrDrop(mask, drop,cargo_type,cargo_data, tooltip_msg); - - if (accepted) - { - mDragAndDropTarget = TRUE; - *accept = ACCEPT_YES_MULTI; - } - else - { - *accept = ACCEPT_NO; - } - - if (!drop && accepted) - { - root_view->autoOpenTest(this); - } + handleDragAndDropToThisFolder(mask, drop, cargo_type, cargo_data, accept, tooltip_msg); lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLFolderViewFolder" << llendl; } @@ -2310,6 +2293,33 @@ BOOL LLFolderViewFolder::handleDragAndDrop(S32 x, S32 y, MASK mask, return TRUE; } +BOOL LLFolderViewFolder::handleDragAndDropToThisFolder(MASK mask, + BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + BOOL accepted = mListener && mListener->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); + + if (accepted) + { + mDragAndDropTarget = TRUE; + *accept = ACCEPT_YES_MULTI; + } + else + { + *accept = ACCEPT_NO; + } + + if (!drop && accepted) + { + getRoot()->autoOpenTest(this); + } + + return TRUE; +} + BOOL LLFolderViewFolder::handleRightMouseDown( S32 x, S32 y, MASK mask ) { diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 3433e3f7f3..0f8c3edef8 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -547,6 +547,11 @@ public: void* cargo_data, EAcceptance* accept, std::string& tooltip_msg); + BOOL handleDragAndDropToThisFolder(MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg); virtual void draw(); time_t getCreationDate() const; diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index f7ed1116cb..bbf66ca750 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -95,7 +95,7 @@ LLGroupList::LLGroupList(const Params& p) LLGroupList::~LLGroupList() { gAgent.removeListener(this); - delete mContextMenuHandle.get(); + if (mContextMenuHandle.get()) mContextMenuHandle.get()->die(); } // virtual diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 0c092e9a56..c94deed5e2 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -53,6 +53,7 @@ #include "llinventorymodel.h" #include "llinventorymodelbackgroundfetch.h" #include "llinventorypanel.h" +#include "llmarketplacefunctions.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llpreviewanim.h" @@ -60,6 +61,7 @@ #include "llpreviewtexture.h" #include "llselectmgr.h" #include "llsidepanelappearance.h" +#include "lltooldraganddrop.h" #include "lltrans.h" #include "llviewerassettype.h" #include "llviewerfoldertype.h" @@ -71,7 +73,8 @@ #include "llwearablelist.h" // Marketplace outbox current disabled -#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 0 // keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_PANEL +#define ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU 1 +#define BLOCK_WORN_ITEMS_IN_OUTBOX 1 typedef std::pair<LLUUID, LLUUID> two_uuids_t; typedef std::list<two_uuids_t> two_uuids_list_t; @@ -616,7 +619,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, } } - // Don't allow items to be pasted directly into the COF or the inbox + // Don't allow items to be pasted directly into the COF or the inbox/outbox if (!isCOFFolder() && !isInboxFolder() && !isOutboxFolder()) { items.push_back(std::string("Paste")); @@ -1085,6 +1088,12 @@ BOOL LLInvFVBridge::canListOnMarketplace() const { return FALSE; } + + const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + if (outbox_id.isNull()) + { + return FALSE; + } LLViewerInventoryItem * item = model->getItem(mUUID); if (item && !item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID())) @@ -1100,23 +1109,42 @@ BOOL LLInvFVBridge::canListOnMarketplace() const BOOL LLInvFVBridge::canListOnMarketplaceNow() const { + BOOL can_list = FALSE; + #if ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU - if (get_is_item_worn(mUUID)) + + const LLInventoryObject* obj = getInventoryObject(); + + if (obj) { - return FALSE; + // Get outbox id + const LLUUID & outbox_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + LLFolderViewItem * outbox_itemp = mRoot->getItemByID(outbox_id); + + if (outbox_itemp) + { + MASK mask = 0x0; + BOOL drop = FALSE; + EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType()); + void * cargo_data = (void *) obj; + std::string tooltip_msg; + + can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); + } } - // Loop through all items worn by avatar and check to see if they are descendants - // of the item we are trying to list on the marketplace - if (get_is_parent_to_worn_item(mUUID)) + // Do not allow listing while import is in progress + if (LLMarketplaceInventoryImporter::instanceExists()) { - return FALSE; + if (LLMarketplaceInventoryImporter::instance().isImportInProgress()) + { + can_list = FALSE; + } } - return TRUE; -#else - return FALSE; #endif + + return can_list; } @@ -1787,30 +1815,35 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const static BOOL can_move_to_outbox(LLInventoryItem* inv_item, std::string& tooltip_msg) { - bool worn = get_is_item_worn(inv_item->getUUID()); + // Collapse links directly to items/folders + LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; + LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem(); + if (linked_item != NULL) + { + inv_item = linked_item; + } + bool allow_transfer = inv_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()); if (!allow_transfer) { tooltip_msg = LLTrans::getString("TooltipOutboxNoTransfer"); + return false; } - else if(worn) + +#if BLOCK_WORN_ITEMS_IN_OUTBOX + bool worn = get_is_item_worn(inv_item->getUUID()); + if (worn) { tooltip_msg = LLTrans::getString("TooltipOutboxWorn"); + return false; } +#endif - return !worn && allow_transfer; -} - - - -void LLFolderBridge::dropFolderToOutbox(LLInventoryCategory* inv_cat) -{ - copy_folder_to_outbox(inv_cat, getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false), inv_cat->getUUID()); + return true; } - int get_folder_levels(LLInventoryCategory* inv_cat) { LLInventoryModel::cat_array_t* cats; @@ -1865,54 +1898,78 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, if (!isAgentAvatarValid()) return FALSE; if (!isAgentInventory()) return FALSE; // cannot drag categories into library + const LLUUID &cat_id = inv_cat->getUUID(); + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); + const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + + const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); + const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); + const BOOL move_is_from_outbox = model->isObjectDescendentOf(cat_id, outbox_id); // check to make sure source is agent inventory, and is represented there. LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); - const BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL) + const BOOL is_agent_inventory = (model->getCategory(cat_id) != NULL) && (LLToolDragAndDrop::SOURCE_AGENT == source); - const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); - BOOL accept = FALSE; if (is_agent_inventory) { - const LLUUID &cat_id = inv_cat->getUUID(); const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); - const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); const BOOL move_is_into_outfit = getCategory() && (getCategory()->getPreferredType() == LLFolderType::FT_OUTFIT); const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); - const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); - const BOOL move_is_from_outbox = model->isObjectDescendentOf(inv_cat->getUUID(), outbox_id); //-------------------------------------------------------------------------------- // Determine if folder can be moved. // BOOL is_movable = TRUE; - if (LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())) + + if (is_movable && (mUUID == cat_id)) + { + is_movable = FALSE; + tooltip_msg = LLTrans::getString("TooltipDragOntoSelf"); + } + if (is_movable && (model->isObjectDescendentOf(mUUID, cat_id))) + { is_movable = FALSE; - if (move_is_into_outfit) + tooltip_msg = LLTrans::getString("TooltipDragOntoOwnChild"); + } + if (is_movable && LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType())) + { is_movable = FALSE; - if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)) + // tooltip? + } + if (is_movable && move_is_into_outfit) + { is_movable = FALSE; + // tooltip? + } + if (is_movable && (mUUID == model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE))) + { + is_movable = FALSE; + // tooltip? + } + LLInventoryModel::cat_array_t descendent_categories; LLInventoryModel::item_array_t descendent_items; - gInventory.collectDescendents(cat_id, descendent_categories, descendent_items, FALSE); - for (S32 i=0; i < descendent_categories.count(); ++i) + if (is_movable) { - LLInventoryCategory* category = descendent_categories[i]; - if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) + model->collectDescendents(cat_id, descendent_categories, descendent_items, FALSE); + for (S32 i=0; i < descendent_categories.count(); ++i) { - // Can't move "special folders" (e.g. Textures Folder). - is_movable = FALSE; - break; + LLInventoryCategory* category = descendent_categories[i]; + if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) + { + // Can't move "special folders" (e.g. Textures Folder). + is_movable = FALSE; + break; + } } } - if (move_is_into_trash) + if (is_movable && move_is_into_trash) { for (S32 i=0; i < descendent_items.count(); ++i) { @@ -1924,7 +1981,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } } } - if (move_is_into_landmarks) + if (is_movable && move_is_into_landmarks) { for (S32 i=0; i < descendent_items.count(); ++i) { @@ -1939,35 +1996,100 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } } } - if (move_is_into_outbox) + if (is_movable && move_is_into_outbox) { - for (S32 i=0; i < descendent_items.count(); ++i) + const int nested_folder_levels = get_folder_path_length(outbox_id, mUUID) + get_folder_levels(inv_cat); + + if (nested_folder_levels > gSavedSettings.getU32("InventoryOutboxMaxFolderDepth")) { - LLInventoryItem* item = descendent_items[i]; - if (!can_move_to_outbox(item, tooltip_msg)) - { - is_movable = FALSE; - break; - } + tooltip_msg = LLTrans::getString("TooltipOutboxFolderLevels"); + is_movable = FALSE; } + else + { + int dragged_folder_count = descendent_categories.count(); + int existing_item_count = 0; + int existing_folder_count = 0; + + const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID); + + if (master_folder != NULL) + { + if (model->isObjectDescendentOf(cat_id, master_folder->getUUID())) + { + // Don't use count because we're already inside the same category anyway + dragged_folder_count = 0; + } + else + { + existing_folder_count = 1; // Include the master folder in the count! + + // If we're in the drop operation as opposed to the drag without drop, we are doing a + // single category at a time so don't block based on the total amount of cargo data items + if (drop) + { + dragged_folder_count += 1; + } + else + { + // NOTE: The cargo id's count is a total of categories AND items but we err on the side of + // prevention rather than letting too many folders into the hierarchy of the outbox, + // when we're dragging the item to a new parent + dragged_folder_count += LLToolDragAndDrop::instance().getCargoIDsCount(); + } + } + + // Tally the total number of categories and items inside the master folder - int nested_folder_levels = get_folder_path_length(outbox_id, mUUID) + get_folder_levels(inv_cat); + LLInventoryModel::cat_array_t existing_categories; + LLInventoryModel::item_array_t existing_items; - if (nested_folder_levels > 4) - { - tooltip_msg = LLTrans::getString("TooltipOutboxFolderLevels"); - is_movable = FALSE; + model->collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE); + + existing_folder_count += existing_categories.count(); + existing_item_count += existing_items.count(); + } + else + { + // Assume a single category is being dragged to the outbox since we evaluate one at a time + // when not putting them under a parent item. + dragged_folder_count += 1; + } + + const int nested_folder_count = existing_folder_count + dragged_folder_count; + const int nested_item_count = existing_item_count + descendent_items.count(); + + if (nested_folder_count > gSavedSettings.getU32("InventoryOutboxMaxFolderCount")) + { + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyFolders"); + is_movable = FALSE; + } + else if (nested_item_count > gSavedSettings.getU32("InventoryOutboxMaxItemCount")) + { + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects"); + is_movable = FALSE; + } + + if (is_movable == TRUE) + { + for (S32 i=0; i < descendent_items.count(); ++i) + { + LLInventoryItem* item = descendent_items[i]; + if (!can_move_to_outbox(item, tooltip_msg)) + { + is_movable = FALSE; + break; + } + } + } } - } // //-------------------------------------------------------------------------------- - accept = is_movable - && (mUUID != cat_id) // Can't move a folder into itself - && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing - && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity + accept = is_movable; + if (accept && drop) { // Look for any gestures and deactivate them @@ -1999,7 +2121,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, // Recursively create links in target outfit. LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; - gInventory.collectDescendents(inv_cat->getUUID(), cats, items, LLInventoryModel::EXCLUDE_TRASH); + model->collectDescendents(cat_id, cats, items, LLInventoryModel::EXCLUDE_TRASH); LLAppearanceMgr::instance().linkAll(mUUID,items,NULL); } } @@ -2017,7 +2139,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, const std::string empty_description = ""; link_inventory_item( gAgent.getID(), - inv_cat->getUUID(), + cat_id, mUUID, inv_cat->getName(), empty_description, @@ -2029,13 +2151,13 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } else if (move_is_into_outbox && !move_is_from_outbox) { - dropFolderToOutbox(inv_cat); + copy_folder_to_outbox(inv_cat, mUUID, cat_id); } else { - if (gInventory.isObjectDescendentOf(inv_cat->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false))) + if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX, false, false))) { - set_dad_inbox_object(inv_cat->getUUID()); + set_dad_inbox_object(cat_id); } // Reparent the folder and restamp children if it's moving @@ -2050,15 +2172,28 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } else if (LLToolDragAndDrop::SOURCE_WORLD == source) { - // content category has same ID as object itself - LLUUID object_id = inv_cat->getUUID(); - LLUUID category_id = mUUID; - accept = move_inv_category_world_to_agent(object_id, category_id, drop); + if (move_is_into_outbox) + { + tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + else + { + accept = move_inv_category_world_to_agent(cat_id, mUUID, drop); + } } else if (LLToolDragAndDrop::SOURCE_LIBRARY == source) { - // Accept folders that contain complete outfits. - accept = move_is_into_current_outfit && LLAppearanceMgr::instance().getCanMakeFolderIntoOutfit(inv_cat->getUUID()); + if (move_is_into_outbox) + { + tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + else + { + // Accept folders that contain complete outfits. + accept = move_is_into_current_outfit && LLAppearanceMgr::instance().getCanMakeFolderIntoOutfit(cat_id); + } if (accept && drop) { @@ -2875,11 +3010,17 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) } else if(isOutboxFolder()) { + mItems.push_back(std::string("Rename")); mItems.push_back(std::string("Delete")); + + if ((flags & FIRST_SELECTED_ITEM) == 0) + { + mDisabledItems.push_back(std::string("Rename")); + } } else if(isAgentInventory()) // do not allow creating in library { - LLViewerInventoryCategory *cat = getCategory(); + LLViewerInventoryCategory *cat = getCategory(); // BAP removed protected check to re-enable standard ops in untyped folders. // Not sure what the right thing is to do here. if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT)) @@ -3307,8 +3448,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { LLInventoryModel* model = getInventoryModel(); - if(!model || !inv_item) return FALSE; - if(!isAgentInventory()) return FALSE; // cannot drag into library + if (!model || !inv_item) return FALSE; + if (!isAgentInventory()) return FALSE; // cannot drag into library if (!isAgentAvatarValid()) return FALSE; const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); @@ -3376,10 +3517,14 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, accept = TRUE; if (!is_movable) + { accept = FALSE; - if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites) + } + else if ((mUUID == inv_item->getParentUUID()) && !move_is_into_favorites) + { accept = FALSE; - if (move_is_into_current_outfit || move_is_into_outfit) + } + else if (move_is_into_current_outfit || move_is_into_outfit) { accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); } @@ -3390,9 +3535,32 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, else if (move_is_into_outbox) { accept = can_move_to_outbox(inv_item, tooltip_msg); + + if (accept) + { + const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID); + + int existing_item_count = LLToolDragAndDrop::instance().getCargoIDsCount(); + + if (master_folder != NULL) + { + LLInventoryModel::cat_array_t existing_categories; + LLInventoryModel::item_array_t existing_items; + + gInventory.collectDescendents(master_folder->getUUID(), existing_categories, existing_items, FALSE); + + existing_item_count += existing_items.count(); + } + + if (existing_item_count > gSavedSettings.getU32("InventoryOutboxMaxItemCount")) + { + tooltip_msg = LLTrans::getString("TooltipOutboxTooManyObjects"); + accept = FALSE; + } + } } - if(accept && drop) + if (accept && drop) { if (inv_item->getType() == LLAssetType::AT_GESTURE && LLGestureMgr::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash) @@ -3441,9 +3609,16 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { dropToOutfit(inv_item, move_is_into_current_outfit); } - else if (move_is_into_outbox && !move_is_from_outbox) + else if (move_is_into_outbox) { - copy_item_to_outbox(inv_item, outbox_id, LLUUID::null); + if (move_is_from_outbox) + { + move_item_within_outbox(inv_item, mUUID); + } + else + { + copy_item_to_outbox(inv_item, mUUID, LLUUID::null); + } } // NORMAL or TRASH folder // (move the item, restamp if into trash) @@ -3464,7 +3639,6 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // //-------------------------------------------------------------------------------- - } } else if (LLToolDragAndDrop::SOURCE_WORLD == source) @@ -3473,7 +3647,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // anonymous objects, it would be possible to bypass // permissions. object = gObjectList.findObject(inv_item->getParentUUID()); - if(!object) + if (!object) { llinfos << "Object not found for drop." << llendl; return FALSE; @@ -3483,10 +3657,9 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // move/copy this item. LLPermissions perm(inv_item->getPermissions()); BOOL is_move = FALSE; - if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) + if ((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()) && perm.allowTransferTo(gAgent.getID()))) // || gAgent.isGodlike()) - { accept = TRUE; } @@ -3502,7 +3675,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, // Don't allow placing an original item into Current Outfit or an outfit folder // because they must contain only links to wearable items. // *TODO: Probably we should create a link to an item if it was dragged to outfit or COF. - if(move_is_into_current_outfit || move_is_into_outfit) + if (move_is_into_current_outfit || move_is_into_outfit) { accept = FALSE; } @@ -3513,8 +3686,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { accept = FALSE; } - - if(drop && accept) + else if (move_is_into_outbox) + { + tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + + if (accept && drop) { LLMoveInv* move_inv = new LLMoveInv; move_inv->mObjectID = inv_item->getParentUUID(); @@ -3536,15 +3714,22 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLNotifications::instance().forceResponse(params, 0); } } - } else if(LLToolDragAndDrop::SOURCE_NOTECARD == source) { - // Don't allow placing an original item from a notecard to Current Outfit or an outfit folder - // because they must contain only links to wearable items. - accept = !(move_is_into_current_outfit || move_is_into_outfit); - - if(accept && drop) + if (move_is_into_outbox) + { + tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + else + { + // Don't allow placing an original item from a notecard to Current Outfit or an outfit folder + // because they must contain only links to wearable items. + accept = !(move_is_into_current_outfit || move_is_into_outfit); + } + + if (accept && drop) { copy_inventory_from_notecard(mUUID, // Drop to the chosen destination folder LLToolDragAndDrop::getInstance()->getObjectID(), @@ -3559,7 +3744,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, { accept = TRUE; - if (move_is_into_current_outfit || move_is_into_outfit) + if (move_is_into_outbox) + { + tooltip_msg = tooltip_msg = LLTrans::getString("TooltipOutboxNotInInventory"); + accept = FALSE; + } + else if (move_is_into_current_outfit || move_is_into_outfit) { accept = can_move_to_outfit(inv_item, move_is_into_current_outfit); } @@ -3724,29 +3914,29 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t items; menuentry_vec_t disabled_items; - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else if(isOutboxFolder()) + if (isOutboxFolder()) { items.push_back(std::string("Delete")); } else { - items.push_back(std::string("Share")); - if (!canShare()) + if (isItemInTrash()) { - disabled_items.push_back(std::string("Share")); - } - items.push_back(std::string("Sound Open")); - items.push_back(std::string("Properties")); + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + items.push_back(std::string("Sound Open")); + items.push_back(std::string("Properties")); - getClipboardEntries(true, items, disabled_items, flags); - } + getClipboardEntries(true, items, disabled_items, flags); + } - if (!isOutboxFolder()) - { items.push_back(std::string("Sound Separator")); items.push_back(std::string("Sound Play")); } @@ -3782,29 +3972,29 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t disabled_items; lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl; - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else if(isOutboxFolder()) + if(isOutboxFolder()) { items.push_back(std::string("Delete")); } else { - items.push_back(std::string("Share")); - if (!canShare()) + if(isItemInTrash()) { - disabled_items.push_back(std::string("Share")); - } - items.push_back(std::string("Landmark Open")); - items.push_back(std::string("Properties")); + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + items.push_back(std::string("Landmark Open")); + items.push_back(std::string("Properties")); - getClipboardEntries(true, items, disabled_items, flags); - } + getClipboardEntries(true, items, disabled_items, flags); + } - if (!isOutboxFolder()) - { items.push_back(std::string("Landmark Separator")); items.push_back(std::string("About Landmark")); } @@ -4337,36 +4527,35 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags) menuentry_vec_t disabled_items; lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl; - if(isItemInTrash()) - { - addTrashContextMenuOptions(items, disabled_items); - } - else if(isOutboxFolder()) + if(isOutboxFolder()) { items.push_back(std::string("Delete")); } else { - items.push_back(std::string("Share")); - if (!canShare()) + if(isItemInTrash()) { - disabled_items.push_back(std::string("Share")); - } - items.push_back(std::string("Animation Open")); - items.push_back(std::string("Properties")); + addTrashContextMenuOptions(items, disabled_items); + } + else + { + items.push_back(std::string("Share")); + if (!canShare()) + { + disabled_items.push_back(std::string("Share")); + } + items.push_back(std::string("Animation Open")); + items.push_back(std::string("Properties")); - getClipboardEntries(true, items, disabled_items, flags); - } + getClipboardEntries(true, items, disabled_items, flags); + } - if (!isOutboxFolder()) - { items.push_back(std::string("Animation Separator")); items.push_back(std::string("Animation Play")); items.push_back(std::string("Animation Audition")); } hide_context_entries(menu, items, disabled_items); - } // virtual @@ -5360,7 +5549,6 @@ void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags) getClipboardEntries(true, items, disabled_items, flags); } - hide_context_entries(menu, items, disabled_items); } diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 2d625befb4..126a28f74c 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -306,8 +306,6 @@ protected: void dropToFavorites(LLInventoryItem* inv_item); void dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); - void dropToOutbox(LLInventoryItem* inv_item); - void dropFolderToOutbox(LLInventoryCategory* inv_cat); //-------------------------------------------------------------------- // Messy hacks for handling folder options diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 5fb3f15cd5..6c5325620e 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -588,40 +588,72 @@ void move_to_outbox_cb(const LLSD& notification, const LLSD& response) parent = next_parent; } } - } } void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder) { - if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + // Collapse links directly to items/folders + LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; + LLViewerInventoryCategory * linked_category = viewer_inv_item->getLinkedCategory(); + if (linked_category != NULL) { - // when moving item directly into outbox create folder with that name - if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + copy_folder_to_outbox(linked_category, dest_folder, top_level_folder); + } + else + { + LLViewerInventoryItem * linked_item = viewer_inv_item->getLinkedItem(); + if (linked_item != NULL) { - dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_item->getName()); - gInventory.notifyObservers(); + inv_item = (LLInventoryItem *) linked_item; + } + + // Check for copy permissions + if (inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + // when moving item directly into outbox create folder with that name + if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + { + dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_item->getName()); + gInventory.notifyObservers(); + } + + copy_inventory_item(gAgent.getID(), + inv_item->getPermissions().getOwner(), + inv_item->getUUID(), + dest_folder, + inv_item->getName(), + LLPointer<LLInventoryCallback>(NULL)); + } + else + { + LLSD args; + args["ITEM_NAME"] = inv_item->getName(); + LLSD payload; + payload["item_id"] = inv_item->getUUID(); + payload["dest_folder_id"] = dest_folder; + payload["top_level_folder"] = top_level_folder; + LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&move_to_outbox_cb, _1, _2)); } - - copy_inventory_item( - gAgent.getID(), - inv_item->getPermissions().getOwner(), - inv_item->getUUID(), - dest_folder, - inv_item->getName(), - LLPointer<LLInventoryCallback>(NULL)); } - else - { - LLSD args; - args["ITEM_NAME"] = inv_item->getName(); - LLSD payload; - payload["item_id"] = inv_item->getUUID(); - payload["dest_folder_id"] = dest_folder; - payload["top_level_folder"] = top_level_folder; - LLNotificationsUtil::add("ConfirmNoCopyToOutbox", args, payload, boost::bind(&move_to_outbox_cb, _1, _2)); +} + +void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder) +{ + // when moving item directly into outbox create folder with that name + if (dest_folder == gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false)) + { + dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, inv_item->getName()); + gInventory.notifyObservers(); } + + LLViewerInventoryItem * viewer_inv_item = (LLViewerInventoryItem *) inv_item; + + change_item_parent(&gInventory, + viewer_inv_item, + dest_folder, + false); } void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder) diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 7b452537f8..9f0ee0571a 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -75,6 +75,7 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s void append_path(const LLUUID& id, std::string& path); void copy_item_to_outbox(LLInventoryItem* inv_item, LLUUID dest_folder, const LLUUID& top_level_folder); +void move_item_within_outbox(LLInventoryItem* inv_item, LLUUID dest_folder); void copy_folder_to_outbox(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, const LLUUID& top_level_folder); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index dc25689fa3..2fb9c53857 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -217,6 +217,38 @@ const LLViewerInventoryCategory *LLInventoryModel::getFirstNondefaultParent(cons return NULL; } +// +// Search up the parent chain until we get to the specified parent, then return the first child category under it +// +const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LLUUID& master_parent_id, const LLUUID& obj_id) const +{ + if (master_parent_id == obj_id) + { + return NULL; + } + + const LLViewerInventoryCategory* current_cat = getCategory(obj_id); + + if (current_cat == NULL) + { + current_cat = getCategory(getObject(obj_id)->getParentUUID()); + } + + while (current_cat != NULL) + { + const LLUUID& current_parent_id = current_cat->getParentUUID(); + + if (current_parent_id == master_parent_id) + { + return current_cat; + } + + current_cat = getCategory(current_parent_id); + } + + return NULL; +} + // Get the object by id. Returns NULL if not found. LLInventoryObject* LLInventoryModel::getObject(const LLUUID& id) const { diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 340c1b0c22..1740c4151d 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -238,6 +238,9 @@ public: // Get whatever special folder this object is a child of, if any. const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const; + + // Get first descendant of the child object under the specified parent + const LLViewerInventoryCategory *getFirstDescendantOf(const LLUUID& master_parent_id, const LLUUID& obj_id) const; // Get the object by id. Returns NULL if not found. // NOTE: Use the pointer returned for read operations - do diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index d06374d232..af1d2b8528 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -1105,30 +1105,23 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open) return FALSE; } - LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); - - // A. If the inventory side panel floater is open, use that preferably. - if (is_inventorysp_active()) - { - // Get the floater's z order to compare it to other inventory floaters' order later. - res = sidepanel_inventory->getActivePanel(); - z_min = gFloaterView->getZOrder(floater_inventory); - active_inv_floaterp = floater_inventory; - } + LLSidepanelInventory *inventory_panel = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); - // B. Iterate through the inventory floaters and return whichever is on top. + // Iterate through the inventory floaters and return whichever is on top. LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("inventory"); for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) { - LLFloaterInventory* iv = dynamic_cast<LLFloaterInventory*>(*iter); - if (iv && iv->getVisible()) + LLFloaterSidePanelContainer* inventory_floater = dynamic_cast<LLFloaterSidePanelContainer*>(*iter); + inventory_panel = inventory_floater->findChild<LLSidepanelInventory>("main_panel"); + + if (inventory_floater && inventory_panel && inventory_floater->getVisible()) { - S32 z_order = gFloaterView->getZOrder(iv); + S32 z_order = gFloaterView->getZOrder(inventory_floater); if (z_order < z_min) { - res = iv->getPanel(); + res = inventory_panel->getActivePanel(); z_min = z_order; - active_inv_floaterp = iv; + active_inv_floaterp = inventory_floater; } } } @@ -1145,7 +1138,7 @@ LLInventoryPanel* LLInventoryPanel::getActiveInventoryPanel(BOOL auto_open) { floater_inventory->openFloater(); - res = sidepanel_inventory->getActivePanel(); + res = inventory_panel->getActivePanel(); } return res; @@ -1164,7 +1157,6 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L LLViewerInventoryCategory * cat = gInventory.getCategory(obj_id); bool in_inbox = false; - bool in_outbox = false; LLViewerInventoryCategory * parent_cat = NULL; @@ -1180,10 +1172,9 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L if (parent_cat) { in_inbox = (LLFolderType::FT_INBOX == parent_cat->getPreferredType()); - in_outbox = (LLFolderType::FT_OUTBOX == parent_cat->getPreferredType()); } - if (in_inbox || in_outbox) + if (in_inbox) { LLSidepanelInventory * sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); LLInventoryPanel * inventory_panel = NULL; @@ -1193,11 +1184,6 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L sidepanel_inventory->openInbox(); inventory_panel = sidepanel_inventory->getInboxPanel(); } - else - { - sidepanel_inventory->openOutbox(); - inventory_panel = sidepanel_inventory->getOutboxPanel(); - } if (inventory_panel) { diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp new file mode 100644 index 0000000000..9a83c5fcb7 --- /dev/null +++ b/indra/newview/llmarketplacefunctions.cpp @@ -0,0 +1,407 @@ +/** + * @file llmarketplacefunctions.cpp + * @brief Implementation of assorted functions related to the marketplace + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llmarketplacefunctions.h" + +#include "llagent.h" +#include "llhttpclient.h" +#include "lltrans.h" +#include "llviewercontrol.h" +#include "llviewermedia.h" +#include "llviewernetwork.h" + + +// +// Helpers +// + +static std::string getMarketplaceDomain() +{ + std::string domain = "secondlife.com"; + + if (!LLGridManager::getInstance()->isInProductionGrid()) + { + const std::string& grid_label = LLGridManager::getInstance()->getGridLabel(); + const std::string& grid_label_lower = utf8str_tolower(grid_label); + + if (grid_label_lower == "damballah") + { + domain = "secondlife-staging.com"; + } + else + { + domain = llformat("%s.lindenlab.com", grid_label_lower.c_str()); + } + } + + return domain; +} + +static std::string getMarketplaceURL(const std::string& urlStringName) +{ + LLStringUtil::format_map_t domain_arg; + domain_arg["[MARKETPLACE_DOMAIN_NAME]"] = getMarketplaceDomain(); + + std::string marketplace_url = LLTrans::getString(urlStringName, domain_arg); + + return marketplace_url; +} + +LLStringUtil::format_map_t getMarketplaceStringSubstitutions() +{ + std::string marketplace_url = getMarketplaceURL("MarketplaceURL"); + std::string marketplace_url_create = getMarketplaceURL("MarketplaceURL_CreateStore"); + std::string marketplace_url_dashboard = getMarketplaceURL("MarketplaceURL_Dashboard"); + std::string marketplace_url_info = getMarketplaceURL("MarketplaceURL_LearnMore"); + + LLStringUtil::format_map_t agent_map; + agent_map["[AGENT_ID]"] = gAgent.getID().getString(); + + LLStringUtil::format(marketplace_url_dashboard, agent_map); + + LLStringUtil::format_map_t marketplace_sub_map; + marketplace_sub_map["[MARKETPLACE_URL]"] = marketplace_url; + marketplace_sub_map["[MARKETPLACE_CREATE_STORE_URL]"] = marketplace_url_create; + marketplace_sub_map["[MARKETPLACE_LEARN_MORE_URL]"] = marketplace_url_info; + marketplace_sub_map["[MARKETPLACE_DASHBOARD_URL]"] = marketplace_url_dashboard; + + return marketplace_sub_map; +} + +namespace LLMarketplaceImport +{ + // Basic interface for this namespace + + bool inProgress(); + bool resultPending(); + U32 getResultStatus(); + const LLSD& getResults(); + + void establishMarketplaceSessionCookie(); + void pollStatus(); + void triggerImport(); + + // Internal state variables + + static std::string sMarketplaceCookie = ""; + static LLSD sImportId = LLSD::emptyMap(); + static bool sImportInProgress = false; + static bool sImportPostPending = false; + static bool sImportGetPending = false; + static U32 sImportResultStatus = 0; + static LLSD sImportResults = LLSD::emptyMap(); + + + // Responders + + class LLImportPostResponder : public LLHTTPClient::Responder + { + public: + LLImportPostResponder() : LLCurl::Responder() {} + + void completed(U32 status, const std::string& reason, const LLSD& content) + { + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) + { + llinfos << " SLM POST status: " << status << llendl; + llinfos << " SLM POST reason: " << reason << llendl; + llinfos << " SLM POST content: " << content.asString() << llendl; + } + + sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_DONE); + sImportPostPending = false; + sImportResultStatus = status; + sImportId = content; + } + }; + + class LLImportGetResponder : public LLHTTPClient::Responder + { + public: + LLImportGetResponder() : LLCurl::Responder() {} + + void completedHeader(U32 status, const std::string& reason, const LLSD& content) + { + sMarketplaceCookie = content["set-cookie"].asString(); + } + + void completed(U32 status, const std::string& reason, const LLSD& content) + { + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) + { + llinfos << " SLM GET status: " << status << llendl; + llinfos << " SLM GET reason: " << reason << llendl; + llinfos << " SLM GET content: " << content.asString() << llendl; + } + + sImportInProgress = (status == MarketplaceErrorCodes::IMPORT_PROCESSING); + sImportGetPending = false; + sImportResultStatus = status; + sImportResults = content; + } + }; + + // Coroutine testing +/* + std::string gTimeDelayDebugFunc = ""; + + void timeDelay(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel) + { + waitForEventOn(self, "mainloop"); + + LLTimer delayTimer; + delayTimer.reset(); + delayTimer.setTimerExpirySec(5.0f); + + while (!delayTimer.hasExpired()) + { + waitForEventOn(self, "mainloop"); + } + + outboxPanel->onImportPostComplete(MarketplaceErrorCodes::IMPORT_DONE, LLSD::emptyMap()); + + gTimeDelayDebugFunc = ""; + } + + std::string gImportPollingFunc = ""; + + void importPoll(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel) + { + waitForEventOn(self, "mainloop"); + + while (outboxPanel->isImportInProgress()) + { + LLTimer delayTimer; + delayTimer.reset(); + delayTimer.setTimerExpirySec(5.0f); + + while (!delayTimer.hasExpired()) + { + waitForEventOn(self, "mainloop"); + } + + //outboxPanel-> + } + + gImportPollingFunc = ""; + } + +*/ + + // Basic API + + bool inProgress() + { + return sImportInProgress; + } + + bool resultPending() + { + return (sImportPostPending || sImportGetPending); + } + + U32 getResultStatus() + { + return sImportResultStatus; + } + + const LLSD& getResults() + { + return sImportResults; + } + + static std::string getInventoryImportURL() + { + std::string url = getMarketplaceURL("MarketplaceURL"); + + url += "api/1/"; + url += gAgent.getID().getString(); + url += "/inventory/import/"; + + return url; + } + + void establishMarketplaceSessionCookie() + { + sImportInProgress = true; + sImportGetPending = true; + + std::string url = getInventoryImportURL(); + + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) + { + llinfos << " SLM GET: " << url << llendl; + } + + LLHTTPClient::get(url, new LLImportGetResponder(), LLViewerMedia::getHeaders()); + } + + void pollStatus() + { + sImportGetPending = true; + + std::string url = getInventoryImportURL(); + + url += sImportId.asString(); + + // Make the headers for the post + LLSD headers = LLSD::emptyMap(); + headers["Accept"] = "*/*"; + headers["Cookie"] = sMarketplaceCookie; + headers["Content-Type"] = "application/llsd+xml"; + headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent(); + + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) + { + llinfos << " SLM GET: " << url << llendl; + } + + LLHTTPClient::get(url, new LLImportGetResponder(), headers); + } + + void triggerImport() + { + sImportId = LLSD::emptyMap(); + sImportInProgress = true; + sImportPostPending = true; + sImportResultStatus = MarketplaceErrorCodes::IMPORT_PROCESSING; + sImportResults = LLSD::emptyMap(); + + std::string url = getInventoryImportURL(); + + // Make the headers for the post + LLSD headers = LLSD::emptyMap(); + headers["Accept"] = "*/*"; + headers["Connection"] = "Keep-Alive"; + headers["Cookie"] = sMarketplaceCookie; + headers["Content-Type"] = "application/xml"; + headers["User-Agent"] = LLViewerMedia::getCurrentUserAgent(); + + if (gSavedSettings.getBOOL("InventoryOutboxLogging")) + { + llinfos << " SLM POST: " << url << llendl; + } + + LLHTTPClient::post(url, LLSD(), new LLImportPostResponder(), headers); + + // Set a timer (for testing only) + //gTimeDelayDebugFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox timeDelay", boost::bind(&timeDelay, _1, this)); + } +} + + +// +// Interface class +// + + +//static +void LLMarketplaceInventoryImporter::update() +{ + if (instanceExists()) + { + LLMarketplaceInventoryImporter::instance().updateImport(); + } +} + +LLMarketplaceInventoryImporter::LLMarketplaceInventoryImporter() + : mImportInProgress(false) + , mInitialized(false) + , mStatusChangedSignal(NULL) + , mStatusReportSignal(NULL) +{ +} + +void LLMarketplaceInventoryImporter::initialize() +{ + if (!mInitialized) + { + LLMarketplaceImport::establishMarketplaceSessionCookie(); + } +} + +boost::signals2::connection LLMarketplaceInventoryImporter::setStatusChangedCallback(const status_changed_signal_t::slot_type& cb) +{ + if (mStatusChangedSignal == NULL) + { + mStatusChangedSignal = new status_changed_signal_t(); + } + + return mStatusChangedSignal->connect(cb); +} + +boost::signals2::connection LLMarketplaceInventoryImporter::setStatusReportCallback(const status_report_signal_t::slot_type& cb) +{ + if (mStatusReportSignal == NULL) + { + mStatusReportSignal = new status_report_signal_t(); + } + + return mStatusReportSignal->connect(cb); +} + +bool LLMarketplaceInventoryImporter::triggerImport() +{ + LLMarketplaceImport::triggerImport(); + + return LLMarketplaceImport::inProgress(); +} + +void LLMarketplaceInventoryImporter::updateImport() +{ + const bool in_progress = LLMarketplaceImport::inProgress(); + + if (in_progress && !LLMarketplaceImport::resultPending()) + { + LLMarketplaceImport::pollStatus(); + } + + if (mImportInProgress != in_progress) + { + mImportInProgress = in_progress; + + if (mStatusChangedSignal) + { + (*mStatusChangedSignal)(mImportInProgress); + } + + // If we are no longer in progress, report results + if (!mImportInProgress && mStatusReportSignal) + { + if (mInitialized) + { + (*mStatusReportSignal)(LLMarketplaceImport::getResultStatus(), LLMarketplaceImport::getResults()); + } + else + { + mInitialized = true; + } + } + } +} + diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h new file mode 100644 index 0000000000..f501f1ee8b --- /dev/null +++ b/indra/newview/llmarketplacefunctions.h @@ -0,0 +1,88 @@ +/** + * @file llmarketplacefunctions.h + * @brief Miscellaneous marketplace-related functions and classes + * class definition + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLMARKETPLACEFUNCTIONS_H +#define LL_LLMARKETPLACEFUNCTIONS_H + + +#include <llsd.h> +#include <boost/function.hpp> +#include <boost/signals2.hpp> + +#include "llsingleton.h" +#include "llstring.h" + + +LLStringUtil::format_map_t getMarketplaceStringSubstitutions(); + + +namespace MarketplaceErrorCodes +{ + enum eCode + { + IMPORT_DONE = 200, + IMPORT_PROCESSING = 202, + IMPORT_DONE_WITH_ERRORS = 409, + IMPORT_JOB_FAILED = 410, + }; +} + + +class LLMarketplaceInventoryImporter + : public LLSingleton<LLMarketplaceInventoryImporter> +{ +public: + static void update(); + + LLMarketplaceInventoryImporter(); + + void initialize(); + + typedef boost::signals2::signal<void (bool)> status_changed_signal_t; + typedef boost::signals2::signal<void (U32, const LLSD&)> status_report_signal_t; + + boost::signals2::connection setStatusChangedCallback(const status_changed_signal_t::slot_type& cb); + boost::signals2::connection setStatusReportCallback(const status_report_signal_t::slot_type& cb); + + bool triggerImport(); + bool isImportInProgress() const { return mImportInProgress; } + +protected: + void updateImport(); + +private: + bool mImportInProgress; + bool mInitialized; + + status_changed_signal_t * mStatusChangedSignal; + status_report_signal_t * mStatusReportSignal; +}; + + + +#endif // LL_LLMARKETPLACEFUNCTIONS_H + diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 74fa5d350a..7650fe9229 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -133,10 +133,15 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : navigateHome(); } - // FIXME: How do we create a bevel now? -// LLRect border_rect( 0, getRect().getHeight() + 2, getRect().getWidth() + 2, 0 ); -// mBorder = new LLViewBorder( std::string("web control border"), border_rect, LLViewBorder::BEVEL_IN ); -// addChild( mBorder ); + LLWindowShade::Params params; + params.name = "notification_shade"; + params.rect = getLocalRect(); + params.follows.flags = FOLLOWS_ALL; + params.modal = true; + + mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params); + + addChild(mWindowShade); } LLMediaCtrl::~LLMediaCtrl() @@ -1092,39 +1097,28 @@ void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) void LLMediaCtrl::showNotification(LLNotificationPtr notify) { - delete mWindowShade; + LLWindowShade* shade = getChild<LLWindowShade>("notification_shade"); - LLWindowShade::Params params; - params.name = "notification_shade"; - params.rect = getLocalRect(); - params.follows.flags = FOLLOWS_ALL; - params.notification = notify; - params.modal = true; - //HACK: don't hardcode this if (notify->getIcon() == "Popup_Caution") { - params.bg_image.name = "Yellow_Gradient"; - params.text_color = LLColor4::black; + shade->setBackgroundImage(LLUI::getUIImage("Yellow_Gradient")); + shade->setTextColor(LLColor4::black); + shade->setCanClose(true); } - else - //HACK: another one since XUI doesn't support what we need right now - if (notify->getName() == "AuthRequest") + else if (notify->getName() == "AuthRequest") { - params.bg_image.name = "Yellow_Gradient"; - params.text_color = LLColor4::black; - params.can_close = false; + shade->setBackgroundImage(LLUI::getUIImage("Yellow_Gradient")); + shade->setTextColor(LLColor4::black); + shade->setCanClose(false); } else { //HACK: make this a property of the notification itself, "cancellable" - params.can_close = false; - params.text_color.control = "LabelTextColor"; + shade->setCanClose(false); + shade->setTextColor(LLUIColorTable::instance().getColor("LabelTextColor")); } - mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params); - - addChild(mWindowShade); - mWindowShade->show(); + mWindowShade->show(notify); } void LLMediaCtrl::hideNotification() diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 183063f1db..4512c14b7a 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -48,6 +48,7 @@ #include "llrootview.h" #include "llviewerchat.h" #include "llnearbychat.h" +#include "lltranslate.h" #include "llresizehandle.h" @@ -108,6 +109,10 @@ BOOL LLNearbyChatBar::postBuild() mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator"); mOutputMonitor->setVisible(FALSE); + gSavedSettings.declareBOOL("nearbychat_history_visibility", mNearbyChat->getVisible(), "Visibility state of nearby chat history", TRUE); + + mNearbyChat->setVisible(gSavedSettings.getBOOL("nearbychat_history_visibility")); + // Register for font change notifications LLViewerChat::setFontChangedCallback(boost::bind(&LLNearbyChatBar::onChatFontChange, this, _1)); @@ -116,6 +121,12 @@ BOOL LLNearbyChatBar::postBuild() return TRUE; } +// virtual +void LLNearbyChatBar::onOpen(const LLSD& key) +{ + enableTranslationCheckbox(LLTranslate::isTranslationConfigured()); +} + bool LLNearbyChatBar::applyRectControl() { bool rect_controlled = LLFloater::applyRectControl(); @@ -159,6 +170,11 @@ void LLNearbyChatBar::showHistory() } } +void LLNearbyChatBar::enableTranslationCheckbox(BOOL enable) +{ + getChild<LLUICtrl>("translate_chat_checkbox")->setEnabled(enable); +} + void LLNearbyChatBar::draw() { displaySpeakingIndicator(); @@ -401,6 +417,8 @@ void LLNearbyChatBar::onToggleNearbyChatPanel() enableResizeCtrls(true); storeRectControl(); } + + gSavedSettings.setBOOL("nearbychat_history_visibility", mNearbyChat->getVisible()); } void LLNearbyChatBar::setMinimized(BOOL b) diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index c2f57dc4ca..baf12a06ea 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -43,6 +43,7 @@ public: ~LLNearbyChatBar() {} virtual BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); static LLNearbyChatBar* getInstance(); @@ -60,6 +61,7 @@ public: static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate); void showHistory(); + void enableTranslationCheckbox(BOOL enable); /*virtual*/void setMinimized(BOOL b); protected: diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h index 28a69f2373..23dbb6b047 100644 --- a/indra/newview/llnotificationhandler.h +++ b/indra/newview/llnotificationhandler.h @@ -283,9 +283,17 @@ class LLBrowserNotification : public LLSingleton<LLBrowserNotification> { public: virtual bool processNotification(const LLSD& notify); +}; +/** + * Handler for outbox notifications + */ +class LLOutboxNotification : public LLSingleton<LLOutboxNotification> +{ +public: + virtual bool processNotification(const LLSD& notify); }; - + class LLHandlerUtil { public: diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index 6988227128..6105eff8ea 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -62,6 +62,7 @@ void LLNotificationManager::init() LLNotificationChannel::buildChannel("Offer", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "offer")); LLNotificationChannel::buildChannel("Hints", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "hint")); LLNotificationChannel::buildChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser")); + LLNotificationChannel::buildChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox")); LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); @@ -72,6 +73,7 @@ void LLNotificationManager::init() LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1)); LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1)); + LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1)); mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD())); mNotifyHandlers["notifytip"] = boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD())); diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp index e66dd5690c..b6c0c2ee24 100644 --- a/indra/newview/llpanelgrouplandmoney.cpp +++ b/indra/newview/llpanelgrouplandmoney.cpp @@ -1447,8 +1447,7 @@ void LLGroupMoneyPlanningTabEventHandler::processReply(LLMessageSystem* msg, text.append(time_str); text.append(".\n\n"); - text.append(llformat("%-23sL$%6d\n", LLTrans::getString("GroupMoneyBalance").c_str(), balance )); - text.append(1, '\n'); + text.append(llformat("%-24s %6d L$\n\n", LLTrans::getString("GroupMoneyBalance").c_str(), balance )); } // [DEV-29503] Hide the individual info since diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 9944b51902..374afb90be 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -28,6 +28,7 @@ #include "llpanelmaininventory.h" #include "llagent.h" +#include "llagentcamera.h" #include "llavataractions.h" #include "lldndbutton.h" #include "lleconomy.h" @@ -294,7 +295,13 @@ void LLPanelMainInventory::closeAllFolders() void LLPanelMainInventory::newWindow() { - LLFloaterInventory::showAgentInventory(); + static S32 instance_num = 0; + instance_num = (instance_num + 1) % S32_MAX; + + if (!gAgentCamera.cameraMouselook()) + { + LLFloaterReg::showTypedInstance<LLFloaterSidePanelContainer>("inventory", LLSD(instance_num)); + } } void LLPanelMainInventory::doCreate(const LLSD& userdata) @@ -586,7 +593,7 @@ void LLPanelMainInventory::onFocusReceived() return; } - sidepanel_inventory->clearSelections(false, true, true); + sidepanel_inventory->clearSelections(false, true); } void LLPanelMainInventory::setFilterTextFromFilter() diff --git a/indra/newview/llpanelmarketplaceinbox.cpp b/indra/newview/llpanelmarketplaceinbox.cpp index 7cb4bbf891..a5e964f563 100644 --- a/indra/newview/llpanelmarketplaceinbox.cpp +++ b/indra/newview/llpanelmarketplaceinbox.cpp @@ -109,7 +109,7 @@ void LLPanelMarketplaceInbox::onFocusReceived() LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); if (sidepanel_inventory) { - sidepanel_inventory->clearSelections(true, false, true); + sidepanel_inventory->clearSelections(true, false); } gSavedPerAccountSettings.setU32("LastInventoryInboxActivity", time_corrected()); diff --git a/indra/newview/llpanelmarketplaceoutbox.cpp b/indra/newview/llpanelmarketplaceoutbox.cpp index 12960fd0d6..6c2363eb7f 100644 --- a/indra/newview/llpanelmarketplaceoutbox.cpp +++ b/indra/newview/llpanelmarketplaceoutbox.cpp @@ -36,6 +36,7 @@ #include "llfloatersidepanelcontainer.h" #include "llinventorypanel.h" #include "llloadingindicator.h" +#include "llmarketplacefunctions.h" #include "llnotificationsutil.h" #include "llpanelmarketplaceinbox.h" #include "llsdutil.h" @@ -47,6 +48,11 @@ #include "llfolderview.h" #include "llinventoryfunctions.h" + +// Turn this on to get a bunch of console output for marketplace API calls, headers and status +#define DEBUG_MARKETPLACE_HTTP_API 0 + + static LLRegisterPanelClassWrapper<LLPanelMarketplaceOutbox> t_panel_marketplace_outbox("panel_marketplace_outbox"); const LLPanelMarketplaceOutbox::Params& LLPanelMarketplaceOutbox::getDefaultParams() @@ -58,9 +64,9 @@ const LLPanelMarketplaceOutbox::Params& LLPanelMarketplaceOutbox::getDefaultPara LLPanelMarketplaceOutbox::LLPanelMarketplaceOutbox(const Params& p) : LLPanel(p) , mInventoryPanel(NULL) - , mSyncButton(NULL) - , mSyncIndicator(NULL) - , mSyncInProgress(false) + , mImportButton(NULL) + , mImportIndicator(NULL) + , mOutboxButton(NULL) { } @@ -78,13 +84,17 @@ BOOL LLPanelMarketplaceOutbox::postBuild() return TRUE; } +// DO WE NEED THIS FILE AT ALL? + void LLPanelMarketplaceOutbox::handleLoginComplete() { - mSyncButton = getChild<LLButton>("outbox_sync_btn"); - mSyncButton->setCommitCallback(boost::bind(&LLPanelMarketplaceOutbox::onSyncButtonClicked, this)); - mSyncButton->setEnabled(!isOutboxEmpty()); + mImportButton = getChild<LLButton>("outbox_import_btn"); + mImportButton->setCommitCallback(boost::bind(&LLPanelMarketplaceOutbox::onImportButtonClicked, this)); + mImportButton->setEnabled(!isOutboxEmpty()); + + mImportIndicator = getChild<LLLoadingIndicator>("outbox_import_indicator"); - mSyncIndicator = getChild<LLLoadingIndicator>("outbox_sync_indicator"); + mOutboxButton = getChild<LLButton>("outbox_btn"); } void LLPanelMarketplaceOutbox::onFocusReceived() @@ -92,7 +102,7 @@ void LLPanelMarketplaceOutbox::onFocusReceived() LLSidepanelInventory * sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); if (sidepanel_inventory) { - sidepanel_inventory->clearSelections(true, true, false); + sidepanel_inventory->clearSelections(true, true); } } @@ -134,9 +144,44 @@ LLInventoryPanel * LLPanelMarketplaceOutbox::setupInventoryPanel() // Hide the placeholder text outbox_inventory_placeholder->setVisible(FALSE); + // Set up marketplace importer + LLMarketplaceInventoryImporter::getInstance()->initialize(); + LLMarketplaceInventoryImporter::getInstance()->setStatusChangedCallback(boost::bind(&LLPanelMarketplaceOutbox::importStatusChanged, this, _1)); + LLMarketplaceInventoryImporter::getInstance()->setStatusReportCallback(boost::bind(&LLPanelMarketplaceOutbox::importReportResults, this, _1, _2)); + + updateImportButtonStatus(); + return mInventoryPanel; } +void LLPanelMarketplaceOutbox::importReportResults(U32 status, const LLSD& content) +{ + if (status == MarketplaceErrorCodes::IMPORT_DONE) + { + LLNotificationsUtil::add("OutboxImportComplete", LLSD::emptyMap(), LLSD::emptyMap()); + } + else if (status == MarketplaceErrorCodes::IMPORT_DONE_WITH_ERRORS) + { + LLNotificationsUtil::add("OutboxImportHadErrors", LLSD::emptyMap(), LLSD::emptyMap()); + } + else + { + char status_string[16]; + sprintf(status_string, "%d", status); + + LLSD subs; + subs["ERROR_CODE"] = status_string; + + //llassert(status == MarketplaceErrorCodes::IMPORT_JOB_FAILED); + LLNotificationsUtil::add("OutboxImportFailed", LLSD::emptyMap(), LLSD::emptyMap()); + } +} + +void LLPanelMarketplaceOutbox::importStatusChanged(bool inProgress) +{ + updateImportButtonStatus(); +} + BOOL LLPanelMarketplaceOutbox::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, @@ -163,159 +208,23 @@ bool LLPanelMarketplaceOutbox::isOutboxEmpty() const return (getTotalItemCount() == 0); } -bool LLPanelMarketplaceOutbox::isSyncInProgress() const -{ - return mSyncInProgress; -} - - -std::string gTimeDelayDebugFunc = ""; - -void timeDelay(LLCoros::self& self, LLPanelMarketplaceOutbox* outboxPanel) -{ - waitForEventOn(self, "mainloop"); - - LLTimer delayTimer; - delayTimer.reset(); - delayTimer.setTimerExpirySec(5.0f); - - while (!delayTimer.hasExpired()) - { - waitForEventOn(self, "mainloop"); - } - - outboxPanel->onSyncComplete(true, LLSD::emptyMap()); - - gTimeDelayDebugFunc = ""; -} - - -class LLInventorySyncResponder : public LLHTTPClient::Responder -{ -public: - LLInventorySyncResponder(LLPanelMarketplaceOutbox * outboxPanel) - : LLCurl::Responder() - , mOutboxPanel(outboxPanel) - { - } - - void completed(U32 status, const std::string& reason, const LLSD& content) - { - llinfos << "inventory_import complete status: " << status << ", reason: " << reason << llendl; - - if (isGoodStatus(status)) - { - // Complete success - llinfos << "success" << llendl; - } - else - { - llwarns << "failed" << llendl; - } - - mOutboxPanel->onSyncComplete(isGoodStatus(status), content); - } - -private: - LLPanelMarketplaceOutbox * mOutboxPanel; -}; - -void LLPanelMarketplaceOutbox::onSyncButtonClicked() -{ - // Get the sync animation going - mSyncInProgress = true; - updateSyncButtonStatus(); - - // Make the url for the inventory import request - std::string url = "https://marketplace.secondlife.com/"; - - if (!LLGridManager::getInstance()->isInProductionGrid()) - { - std::string gridLabel = LLGridManager::getInstance()->getGridLabel(); - url = llformat("https://marketplace.%s.lindenlab.com/", utf8str_tolower(gridLabel).c_str()); - - // TEMP for Jim's pdp - //url = "http://pdp24.lindenlab.com:3000/"; - } - - url += "api/1/users/"; - url += gAgent.getID().getString(); - url += "/inventory_import"; - - llinfos << "http get: " << url << llendl; - LLHTTPClient::get(url, new LLInventorySyncResponder(this), LLViewerMedia::getHeaders()); - - // Set a timer (for testing only) - //gTimeDelayDebugFunc = LLCoros::instance().launch("LLPanelMarketplaceOutbox timeDelay", boost::bind(&timeDelay, _1, this)); -} - -void LLPanelMarketplaceOutbox::onSyncComplete(bool goodStatus, const LLSD& content) +void LLPanelMarketplaceOutbox::updateImportButtonStatus() { - mSyncInProgress = false; - updateSyncButtonStatus(); - - const LLSD& errors_list = content["errors"]; - - if (goodStatus && (errors_list.size() == 0)) + if (LLMarketplaceInventoryImporter::instance().isImportInProgress()) { - LLNotificationsUtil::add("OutboxUploadComplete", LLSD::emptyMap(), LLSD::emptyMap()); - } - else - { - LLNotificationsUtil::add("OutboxUploadHadErrors", LLSD::emptyMap(), LLSD::emptyMap()); - } - - llinfos << "Marketplace upload llsd:" << llendl; - llinfos << ll_pretty_print_sd(content) << llendl; - llinfos << llendl; + mImportButton->setVisible(false); - const LLSD& imported_list = content["imported"]; - LLSD::array_const_iterator it = imported_list.beginArray(); - for ( ; it != imported_list.endArray(); ++it) - { - LLUUID imported_folder = (*it).asUUID(); - llinfos << "Successfully uploaded folder " << imported_folder.asString() << " to marketplace." << llendl; - } - - for (it = errors_list.beginArray(); it != errors_list.endArray(); ++it) - { - const LLSD& item_error_map = (*it); - - LLUUID error_folder = item_error_map["folder_id"].asUUID(); - const std::string& error_string = item_error_map["identifier"].asString(); - LLUUID error_item = item_error_map["item_id"].asUUID(); - const std::string& error_item_name = item_error_map["item_name"].asString(); - const std::string& error_message = item_error_map["message"].asString(); - - llinfos << "Error item " << error_folder.asString() << ", " << error_string << ", " - << error_item.asString() << ", " << error_item_name << ", " << error_message << llendl; - - LLFolderViewFolder * item_folder = mInventoryPanel->getRootFolder()->getFolderByID(error_folder); - LLOutboxFolderViewFolder * outbox_item_folder = dynamic_cast<LLOutboxFolderViewFolder *>(item_folder); - - llassert(outbox_item_folder); - - outbox_item_folder->setErrorString(error_string); - } -} - -void LLPanelMarketplaceOutbox::updateSyncButtonStatus() -{ - if (isSyncInProgress()) - { - mSyncButton->setVisible(false); - - mSyncIndicator->setVisible(true); - mSyncIndicator->reset(); - mSyncIndicator->start(); + mImportIndicator->setVisible(true); + mImportIndicator->reset(); + mImportIndicator->start(); } else { - mSyncIndicator->stop(); - mSyncIndicator->setVisible(false); + mImportIndicator->stop(); + mImportIndicator->setVisible(false); - mSyncButton->setVisible(true); - mSyncButton->setEnabled(!isOutboxEmpty()); + mImportButton->setVisible(true); + mImportButton->setEnabled(!isOutboxEmpty()); } } @@ -330,12 +239,21 @@ U32 LLPanelMarketplaceOutbox::getTotalItemCount() const if (outbox_folder) { item_count += outbox_folder->getFoldersCount(); + item_count += outbox_folder->getItemsCount(); } } return item_count; } +void LLPanelMarketplaceOutbox::onImportButtonClicked() +{ + LLMarketplaceInventoryImporter::instance().triggerImport(); + + // Get the import animation going + updateImportButtonStatus(); +} + void LLPanelMarketplaceOutbox::draw() { const U32 item_count = getTotalItemCount(); @@ -347,16 +265,11 @@ void LLPanelMarketplaceOutbox::draw() LLStringUtil::format_map_t args; args["[NUM]"] = item_count_str; - getChild<LLButton>("outbox_btn")->setLabel(getString("OutboxLabelWithArg", args)); + mOutboxButton->setLabel(getString("OutboxLabelWithArg", args)); } else { - getChild<LLButton>("outbox_btn")->setLabel(getString("OutboxLabelNoArg")); - } - - if (!isSyncInProgress()) - { - mSyncButton->setEnabled(not_empty); + mOutboxButton->setLabel(getString("OutboxLabelNoArg")); } LLPanel::draw(); diff --git a/indra/newview/llpanelmarketplaceoutbox.h b/indra/newview/llpanelmarketplaceoutbox.h index c6b4a5abe2..6f038118b3 100644 --- a/indra/newview/llpanelmarketplaceoutbox.h +++ b/indra/newview/llpanelmarketplaceoutbox.h @@ -59,9 +59,6 @@ public: U32 getTotalItemCount() const; bool isOutboxEmpty() const; - bool isSyncInProgress() const; - - void onSyncComplete(bool goodStatus, const LLSD& content); /*virtual*/ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, @@ -70,19 +67,23 @@ public: std::string& tooltip_msg); protected: - void onSyncButtonClicked(); - void updateSyncButtonStatus(); + void onImportButtonClicked(); + void updateImportButtonStatus(); void handleLoginComplete(); void onFocusReceived(); void onSelectionChange(); - + + void importReportResults(U32 status, const LLSD& content); + void importStatusChanged(bool inProgress); + private: LLInventoryPanel * mInventoryPanel; - LLButton * mSyncButton; - LLLoadingIndicator * mSyncIndicator; - bool mSyncInProgress; + LLButton * mImportButton; + LLLoadingIndicator * mImportIndicator; + + LLButton * mOutboxButton; }; diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index d5e289e6e6..9c46f04abf 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -526,11 +526,11 @@ LLPanelPeople::~LLPanelPeople() LLVoiceClient::getInstance()->removeObserver(this); } - delete mGroupPlusMenuHandle.get(); - delete mNearbyViewSortMenuHandle.get(); - delete mFriendsViewSortMenuHandle.get(); - delete mGroupsViewSortMenuHandle.get(); - delete mRecentViewSortMenuHandle.get(); + if (mGroupPlusMenuHandle.get()) mGroupPlusMenuHandle.get()->die(); + if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die(); + if (mNearbyViewSortMenuHandle.get()) mNearbyViewSortMenuHandle.get()->die(); + if (mGroupsViewSortMenuHandle.get()) mGroupsViewSortMenuHandle.get()->die(); + if (mRecentViewSortMenuHandle.get()) mRecentViewSortMenuHandle.get()->die(); } diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 933b40ec79..39c0628cbe 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -1351,7 +1351,6 @@ void LLPanelPrimMediaControls::showNotification(LLNotificationPtr notify) LLWindowShade::Params params; params.rect = mMediaRegion->getLocalRect(); params.follows.flags = FOLLOWS_ALL; - params.notification = notify; //HACK: don't hardcode this if (notify->getIcon() == "Popup_Caution") @@ -1369,7 +1368,7 @@ void LLPanelPrimMediaControls::showNotification(LLNotificationPtr notify) mWindowShade = LLUICtrlFactory::create<LLWindowShade>(params); mMediaRegion->addChild(mWindowShade); - mWindowShade->show(); + mWindowShade->show(notify); } void LLPanelPrimMediaControls::hideNotification() diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index b1eeabb028..e2e7006773 100755 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -177,7 +177,7 @@ LLPanelProfile::ChildStack::~ChildStack() LLView* viewp = *it; if (viewp) { - delete viewp; + viewp->die(); } } mStack.pop_back(); diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index d3543daff0..1f1cccad85 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -388,7 +388,7 @@ LLTeleportHistoryPanel::LLTeleportHistoryPanel() LLTeleportHistoryPanel::~LLTeleportHistoryPanel() { LLTeleportHistoryFlatItemStorage::instance().purge(); - delete mGearMenuHandle.get(); + if (mGearMenuHandle.get()) mGearMenuHandle.get()->die(); mTeleportHistoryChangedConnection.disconnect(); } diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 9d069c3996..5cda381d10 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -47,7 +47,6 @@ #include "lloutfitobserver.h" #include "llpanelmaininventory.h" #include "llpanelmarketplaceinbox.h" -#include "llpanelmarketplaceoutbox.h" #include "llselectmgr.h" #include "llsidepaneliteminfo.h" #include "llsidepaneltaskinfo.h" @@ -68,35 +67,24 @@ static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_ // No longer want the inbox panel to auto-expand since it creates issues with the "new" tag time stamp #define AUTO_EXPAND_INBOX 0 -// Temporarily disabling the outbox until we straighten out the API -#define ENABLE_MERCHANT_OUTBOX_PANEL 0 // keep in sync with ENABLE_INVENTORY_DISPLAY_OUTBOX, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU - static const char * const INBOX_BUTTON_NAME = "inbox_btn"; -static const char * const OUTBOX_BUTTON_NAME = "outbox_btn"; - static const char * const INBOX_LAYOUT_PANEL_NAME = "inbox_layout_panel"; -static const char * const OUTBOX_LAYOUT_PANEL_NAME = "outbox_layout_panel"; - -static const char * const INBOX_OUTBOX_LAYOUT_PANEL_NAME = "inbox_outbox_layout_panel"; static const char * const MAIN_INVENTORY_LAYOUT_PANEL_NAME = "main_inventory_layout_panel"; static const char * const INBOX_INVENTORY_PANEL = "inventory_inbox"; -static const char * const OUTBOX_INVENTORY_PANEL = "inventory_outbox"; -static const char * const INBOX_OUTBOX_LAYOUT_STACK_NAME = "inbox_outbox_layout_stack"; static const char * const INVENTORY_LAYOUT_STACK_NAME = "inventory_layout_stack"; static const char * const MARKETPLACE_INBOX_PANEL = "marketplace_inbox"; -static const char * const MARKETPLACE_OUTBOX_PANEL = "marketplace_outbox"; // // Helpers // -class LLInboxOutboxAddedObserver : public LLInventoryCategoryAddedObserver +class LLInboxAddedObserver : public LLInventoryCategoryAddedObserver { public: - LLInboxOutboxAddedObserver(LLSidepanelInventory * sidepanelInventory) + LLInboxAddedObserver(LLSidepanelInventory * sidepanelInventory) : LLInventoryCategoryAddedObserver() , mSidepanelInventory(sidepanelInventory) { @@ -116,10 +104,6 @@ public: mSidepanelInventory->enableInbox(true); mSidepanelInventory->observeInboxModifications(added_category->getUUID()); break; - case LLFolderType::FT_OUTBOX: - mSidepanelInventory->enableOutbox(true); - mSidepanelInventory->observeOutboxModifications(added_category->getUUID()); - break; default: break; } @@ -138,12 +122,10 @@ LLSidepanelInventory::LLSidepanelInventory() : LLPanel() , mItemPanel(NULL) , mInventoryPanelInbox(NULL) - , mInventoryPanelOutbox(NULL) , mPanelMainInventory(NULL) , mInboxEnabled(false) - , mOutboxEnabled(false) , mCategoriesObserver(NULL) - , mInboxOutboxAddedObserver(NULL) + , mInboxAddedObserver(NULL) { //buildFromFile( "panel_inventory.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder() } @@ -156,11 +138,11 @@ LLSidepanelInventory::~LLSidepanelInventory() } delete mCategoriesObserver; - if (mInboxOutboxAddedObserver && gInventory.containsObserver(mInboxOutboxAddedObserver)) + if (mInboxAddedObserver && gInventory.containsObserver(mInboxAddedObserver)) { - gInventory.removeObserver(mInboxOutboxAddedObserver); + gInventory.removeObserver(mInboxAddedObserver); } - delete mInboxOutboxAddedObserver; + delete mInboxAddedObserver; } void handleInventoryDisplayInboxChanged() @@ -172,15 +154,6 @@ void handleInventoryDisplayInboxChanged() } } -void handleInventoryDisplayOutboxChanged() -{ - LLSidepanelInventory* sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory"); - if (sidepanel_inventory) - { - sidepanel_inventory->enableOutbox(gSavedSettings.getBOOL("InventoryDisplayOutbox")); - } -} - BOOL LLSidepanelInventory::postBuild() { // UI elements from inventory panel @@ -242,43 +215,31 @@ BOOL LLSidepanelInventory::postBuild() } } - // Marketplace inbox/outbox setup + // Received items inbox setup { LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME); // Disable user_resize on main inventory panel by default inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, false); - inv_stack->setPanelUserResize(INBOX_OUTBOX_LAYOUT_PANEL_NAME, false); - - // Collapse marketplace panel by default - inv_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME), true); - - LLLayoutStack* inout_stack = getChild<LLLayoutStack>(INBOX_OUTBOX_LAYOUT_STACK_NAME); + inv_stack->setPanelUserResize(INBOX_LAYOUT_PANEL_NAME, false); - // Collapse both inbox and outbox panels - inout_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true); - inout_stack->collapsePanel(getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME), true); + // Collapse inbox panel + inv_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true); // Set up button states and callbacks LLButton * inbox_button = getChild<LLButton>(INBOX_BUTTON_NAME); - LLButton * outbox_button = getChild<LLButton>(OUTBOX_BUTTON_NAME); inbox_button->setToggleState(false); - outbox_button->setToggleState(false); - inbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleInboxBtn, this)); - outbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleOutboxBtn, this)); - // Set the inbox and outbox visible based on debug settings (final setting comes from http request below) + // Set the inbox visible based on debug settings (final setting comes from http request below) enableInbox(gSavedSettings.getBOOL("InventoryDisplayInbox")); - enableOutbox(gSavedSettings.getBOOL("InventoryDisplayOutbox")); - // Trigger callback for after login so we can setup to track inbox and outbox changes after initial inventory load - LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLSidepanelInventory::updateInboxOutbox, this)); + // Trigger callback for after login so we can setup to track inbox changes after initial inventory load + LLAppViewer::instance()->setOnLoginCompletedCallback(boost::bind(&LLSidepanelInventory::updateInbox, this)); } gSavedSettings.getControl("InventoryDisplayInbox")->getCommitSignal()->connect(boost::bind(&handleInventoryDisplayInboxChanged)); - gSavedSettings.getControl("InventoryDisplayOutbox")->getCommitSignal()->connect(boost::bind(&handleInventoryDisplayOutboxChanged)); // Update the verbs buttons state. updateVerbs(); @@ -286,63 +247,50 @@ BOOL LLSidepanelInventory::postBuild() return TRUE; } -void LLSidepanelInventory::updateInboxOutbox() +void LLSidepanelInventory::updateInbox() { // - // Track inbox and outbox folder changes + // Track inbox folder changes // const bool do_not_create_folder = false; const bool do_not_find_in_library = false; const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, do_not_create_folder, do_not_find_in_library); - const LLUUID outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, do_not_create_folder, do_not_find_in_library); - // Set up observer to listen for creation of inbox and outbox if at least one of them doesn't exist - if (inbox_id.isNull() || outbox_id.isNull()) + // Set up observer to listen for creation of inbox if at least one of them doesn't exist + if (inbox_id.isNull()) { - observeInboxOutboxCreation(); + observeInboxCreation(); } - // Set up observer for inbox changes, if we have an inbox already - if (!inbox_id.isNull()) + else { // Enable the display of the inbox if it exists enableInbox(true); observeInboxModifications(inbox_id); } - -#if ENABLE_MERCHANT_OUTBOX_PANEL - // Set up observer for outbox changes, if we have an outbox already - if (!outbox_id.isNull()) - { - // Enable the display of the outbox if it exists - enableOutbox(true); - - observeOutboxModifications(outbox_id); - } -#endif } -void LLSidepanelInventory::observeInboxOutboxCreation() +void LLSidepanelInventory::observeInboxCreation() { // - // Set up observer to track inbox and outbox folder creation + // Set up observer to track inbox folder creation // - if (mInboxOutboxAddedObserver == NULL) + if (mInboxAddedObserver == NULL) { - mInboxOutboxAddedObserver = new LLInboxOutboxAddedObserver(this); + mInboxAddedObserver = new LLInboxAddedObserver(this); - gInventory.addObserver(mInboxOutboxAddedObserver); + gInventory.addObserver(mInboxAddedObserver); } } void LLSidepanelInventory::observeInboxModifications(const LLUUID& inboxID) { // - // Track inbox and outbox folder changes + // Track inbox folder changes // if (inboxID.isNull()) @@ -373,81 +321,12 @@ void LLSidepanelInventory::observeInboxModifications(const LLUUID& inboxID) mInventoryPanelInbox = inbox->setupInventoryPanel(); } - -void LLSidepanelInventory::observeOutboxModifications(const LLUUID& outboxID) -{ - // - // Track outbox folder changes - // - - if (outboxID.isNull()) - { - llwarns << "Attempting to track modifications to non-existant outbox" << llendl; - return; - } - - if (mCategoriesObserver == NULL) - { - mCategoriesObserver = new LLInventoryCategoriesObserver(); - gInventory.addObserver(mCategoriesObserver); - } - - mCategoriesObserver->addCategory(outboxID, boost::bind(&LLSidepanelInventory::onOutboxChanged, this, outboxID)); - - // - // Set up the outbox inventory view - // - - LLPanelMarketplaceOutbox * outbox = getChild<LLPanelMarketplaceOutbox>(MARKETPLACE_OUTBOX_PANEL); - mInventoryPanelOutbox = outbox->setupInventoryPanel(); -} - void LLSidepanelInventory::enableInbox(bool enabled) { mInboxEnabled = enabled; LLLayoutPanel * inbox_layout_panel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME); inbox_layout_panel->setVisible(enabled); - - if (mInboxEnabled) - { - LLLayoutPanel * inout_layout_panel = getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME); - - inout_layout_panel->setVisible(TRUE); - - if (mOutboxEnabled) - { - S32 inbox_min_dim = inbox_layout_panel->getMinDim(); - S32 outbox_min_dim = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME)->getMinDim(); - - inout_layout_panel->setMinDim(inbox_min_dim + outbox_min_dim); - } - } -} - -void LLSidepanelInventory::enableOutbox(bool enabled) -{ - mOutboxEnabled = enabled; - - LLLayoutPanel * outbox_layout_panel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME); - outbox_layout_panel->setVisible(enabled); - - if (mOutboxEnabled) - { - LLLayoutPanel * inout_layout_panel = getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME); - - inout_layout_panel->setVisible(TRUE); - - if (mInboxEnabled) - { - S32 inbox_min_dim = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME)->getMinDim(); - S32 outbox_min_dim = outbox_layout_panel->getMinDim(); - - inout_layout_panel->setMinDim(inbox_min_dim + outbox_min_dim); - } - - updateOutboxUserStatus(); - } } void LLSidepanelInventory::openInbox() @@ -459,31 +338,13 @@ void LLSidepanelInventory::openInbox() } } -void LLSidepanelInventory::openOutbox() -{ - if (mOutboxEnabled) - { - getChild<LLButton>(OUTBOX_BUTTON_NAME)->setToggleState(true); - onToggleOutboxBtn(); - } -} - void LLSidepanelInventory::onInboxChanged(const LLUUID& inbox_id) { // Trigger a load of the entire inbox so we always know the contents and their creation dates for sorting LLInventoryModelBackgroundFetch::instance().start(inbox_id); #if AUTO_EXPAND_INBOX - // If the outbox is expanded, don't auto-expand the inbox - if (mOutboxEnabled) - { - if (getChild<LLButton>(OUTBOX_BUTTON_NAME)->getToggleState()) - { - return; - } - } - - // Expand the inbox since we have fresh items and the outbox is not expanded + // Expand the inbox since we have fresh items if (mInboxEnabled) { getChild<LLButton>(INBOX_BUTTON_NAME)->setToggleState(true); @@ -492,68 +353,19 @@ void LLSidepanelInventory::onInboxChanged(const LLUUID& inbox_id) #endif } -void LLSidepanelInventory::onOutboxChanged(const LLUUID& outbox_id) -{ - // Expand the outbox since we have new items in it - if (mOutboxEnabled) - { - getChild<LLButton>(OUTBOX_BUTTON_NAME)->setToggleState(true); - onToggleOutboxBtn(); - } -} - -bool LLSidepanelInventory::manageInboxOutboxPanels(LLButton * pressedButton, LLLayoutPanel * pressedPanel, - LLButton * otherButton, LLLayoutPanel * otherPanel) -{ - bool expand = pressedButton->getToggleState(); - bool otherExpanded = otherButton->getToggleState(); - - LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME); - LLLayoutStack* inout_stack = getChild<LLLayoutStack>(INBOX_OUTBOX_LAYOUT_STACK_NAME); - LLLayoutPanel* inout_panel = getChild<LLLayoutPanel>(INBOX_OUTBOX_LAYOUT_PANEL_NAME); - - // Enable user_resize on main inventory panel only when a marketplace box is expanded - inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, expand); - inv_stack->collapsePanel(inout_panel, !expand); - - // Collapse other marketplace panel if it is expanded - if (expand && otherExpanded) - { - // Reshape pressedPanel to the otherPanel's height so we preserve the marketplace panel size - pressedPanel->reshape(pressedPanel->getRect().getWidth(), otherPanel->getRect().getHeight()); - - inout_stack->collapsePanel(otherPanel, true); - otherButton->setToggleState(false); - } - else - { - // NOTE: This is an attempt to reshape the inventory panel to the proper size but it doesn't seem to propagate - // properly to the child panels. - - S32 new_height = inout_panel->getRect().getHeight(); - - if (otherPanel->getVisible()) - { - new_height -= otherPanel->getMinDim(); - } - - pressedPanel->reshape(pressedPanel->getRect().getWidth(), new_height); - } - - // Expand/collapse the indicated panel - inout_stack->collapsePanel(pressedPanel, !expand); - - return expand; -} - void LLSidepanelInventory::onToggleInboxBtn() { LLButton* inboxButton = getChild<LLButton>(INBOX_BUTTON_NAME); LLLayoutPanel* inboxPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME); - LLButton* outboxButton = getChild<LLButton>(OUTBOX_BUTTON_NAME); - LLLayoutPanel* outboxPanel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME); - - const bool inbox_expanded = manageInboxOutboxPanels(inboxButton, inboxPanel, outboxButton, outboxPanel); + LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME); + + const bool inbox_expanded = inboxButton->getToggleState(); + + // Enable user_resize on main inventory panel only when inbox is expanded + inv_stack->setPanelUserResize(MAIN_INVENTORY_LAYOUT_PANEL_NAME, inbox_expanded); + + // Expand/collapse the indicated panel + inv_stack->collapsePanel(inboxPanel, !inbox_expanded); if (inbox_expanded && inboxPanel->isInVisibleChain()) { @@ -561,16 +373,6 @@ void LLSidepanelInventory::onToggleInboxBtn() } } -void LLSidepanelInventory::onToggleOutboxBtn() -{ - LLButton* inboxButton = getChild<LLButton>(INBOX_BUTTON_NAME); - LLLayoutPanel* inboxPanel = getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME); - LLButton* outboxButton = getChild<LLButton>(OUTBOX_BUTTON_NAME); - LLLayoutPanel* outboxPanel = getChild<LLLayoutPanel>(OUTBOX_LAYOUT_PANEL_NAME); - - manageInboxOutboxPanels(outboxButton, outboxPanel, inboxButton, inboxPanel); -} - void LLSidepanelInventory::onOpen(const LLSD& key) { LLFirstUse::newInventory(false); @@ -740,77 +542,6 @@ void LLSidepanelInventory::showInventoryPanel() updateVerbs(); } -void LLSidepanelInventory::updateOutboxUserStatus() -{ - const bool isMerchant = (gSavedSettings.getString("InventoryMarketplaceUserStatus") == "merchant"); - const bool hasOutbox = !gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false, false).isNull(); - - LLView * outbox_placeholder = getChild<LLView>("outbox_inventory_placeholder_panel"); - LLView * outbox_placeholder_parent = outbox_placeholder->getParent(); - - LLTextBox * outbox_title_box = outbox_placeholder->getChild<LLTextBox>("outbox_inventory_placeholder_title"); - LLTextBox * outbox_text_box = outbox_placeholder->getChild<LLTextBox>("outbox_inventory_placeholder_text"); - - std::string outbox_text; - std::string outbox_title; - std::string outbox_tooltip; - - if (isMerchant) - { - if (hasOutbox) - { - outbox_text = LLTrans::getString("InventoryOutboxNoItems"); - outbox_title = LLTrans::getString("InventoryOutboxNoItemsTitle"); - outbox_tooltip = LLTrans::getString("InventoryOutboxNoItemsTooltip"); - } - else - { - outbox_text = LLTrans::getString("InventoryOutboxCreationError"); - outbox_title = LLTrans::getString("InventoryOutboxCreationErrorTitle"); - outbox_tooltip = LLTrans::getString("InventoryOutboxCreationErrorTooltip"); - } - } - else - { - // - // The string to become a merchant contains 3 URL's which need the domain name patched in. - // - - std::string domain = "secondlife.com"; - - if (!LLGridManager::getInstance()->isInProductionGrid()) - { - std::string gridLabel = LLGridManager::getInstance()->getGridLabel(); - domain = llformat("%s.lindenlab.com", utf8str_tolower(gridLabel).c_str()); - } - - LLStringUtil::format_map_t domain_arg; - domain_arg["[DOMAIN_NAME]"] = domain; - - std::string marketplace_url = LLTrans::getString("MarketplaceURL", domain_arg); - std::string marketplace_url_create = LLTrans::getString("MarketplaceURL_CreateStore", domain_arg); - std::string marketplace_url_info = LLTrans::getString("MarketplaceURL_LearnMore", domain_arg); - - LLStringUtil::format_map_t args1, args2, args3; - args1["[MARKETPLACE_URL]"] = marketplace_url; - args2["[LEARN_MORE_URL]"] = marketplace_url_info; - args3["[CREATE_STORE_URL]"] = marketplace_url_create; - - // NOTE: This is dumb, ridiculous and very finicky. The order of these is very important - // to have these three string substitutions work properly. - outbox_text = LLTrans::getString("InventoryOutboxNotMerchant", args1); - LLStringUtil::format(outbox_text, args2); - LLStringUtil::format(outbox_text, args3); - - outbox_title = LLTrans::getString("InventoryOutboxNotMerchantTitle"); - outbox_tooltip = LLTrans::getString("InventoryOutboxNotMerchantTooltip"); - } - - outbox_text_box->setValue(outbox_text); - outbox_title_box->setValue(outbox_title); - outbox_placeholder_parent->setToolTip(outbox_tooltip); -} - void LLSidepanelInventory::updateVerbs() { mInfoBtn->setEnabled(FALSE); @@ -926,13 +657,6 @@ U32 LLSidepanelInventory::getSelectedCount() { selection_list = mInventoryPanelInbox->getRootFolder()->getSelectionList(); - count += selection_list.size(); - } - - if ((count == 0) && mOutboxEnabled && (mInventoryPanelOutbox != NULL)) - { - selection_list = mInventoryPanelOutbox->getRootFolder()->getSelectionList(); - count += selection_list.size(); } @@ -957,7 +681,7 @@ BOOL LLSidepanelInventory::isMainInventoryPanelActive() const return mInventoryPanel->getVisible(); } -void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox, bool clearOutbox) +void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox) { if (clearMain) { @@ -974,15 +698,10 @@ void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox, bool mInventoryPanelInbox->clearSelection(); } - if (clearOutbox && mOutboxEnabled && (mInventoryPanelOutbox != NULL)) - { - mInventoryPanelOutbox->clearSelection(); - } - updateVerbs(); } -std::set<LLUUID> LLSidepanelInventory::getInboxOrOutboxSelectionList() +std::set<LLUUID> LLSidepanelInventory::getInboxSelectionList() { std::set<LLUUID> inventory_selected_uuids; @@ -991,10 +710,5 @@ std::set<LLUUID> LLSidepanelInventory::getInboxOrOutboxSelectionList() inventory_selected_uuids = mInventoryPanelInbox->getRootFolder()->getSelectionList(); } - if (inventory_selected_uuids.empty() && mOutboxEnabled && (mInventoryPanelOutbox != NULL)) - { - inventory_selected_uuids = mInventoryPanelOutbox->getRootFolder()->getSelectionList(); - } - return inventory_selected_uuids; } diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h index 2c6f807013..a33607f50d 100644 --- a/indra/newview/llsidepanelinventory.h +++ b/indra/newview/llsidepanelinventory.h @@ -31,7 +31,7 @@ class LLButton; class LLFolderViewItem; -class LLInboxOutboxAddedObserver; +class LLInboxAddedObserver; class LLInventoryCategoriesObserver; class LLInventoryItem; class LLInventoryPanel; @@ -47,25 +47,23 @@ public: virtual ~LLSidepanelInventory(); private: - void updateInboxOutbox(); + void updateInbox(); public: - void observeInboxOutboxCreation(); + void observeInboxCreation(); void observeInboxModifications(const LLUUID& inboxID); - void observeOutboxModifications(const LLUUID& outboxID); /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); LLInventoryPanel* getActivePanel(); // Returns an active inventory panel, if any. LLInventoryPanel* getInboxPanel() const { return mInventoryPanelInbox; } - LLInventoryPanel* getOutboxPanel() const { return mInventoryPanelOutbox; } LLPanelMainInventory* getMainInventoryPanel() const { return mPanelMainInventory; } BOOL isMainInventoryPanelActive() const; - void clearSelections(bool clearMain, bool clearInbox, bool clearOutbox); - std::set<LLUUID> getInboxOrOutboxSelectionList(); + void clearSelections(bool clearMain, bool clearInbox); + std::set<LLUUID> getInboxSelectionList(); void showItemInfoPanel(); void showTaskInfoPanel(); @@ -75,18 +73,13 @@ public: bool canShare(); void onToggleInboxBtn(); - void onToggleOutboxBtn(); void enableInbox(bool enabled); - void enableOutbox(bool enabled); void openInbox(); - void openOutbox(); bool isInboxEnabled() const { return mInboxEnabled; } - bool isOutboxEnabled() const { return mOutboxEnabled; } - void updateOutboxUserStatus(); void updateVerbs(); protected: @@ -100,9 +93,6 @@ protected: bool canWearSelected(); // check whether selected items can be worn void onInboxChanged(const LLUUID& inbox_id); - void onOutboxChanged(const LLUUID& outbox_id); - - bool manageInboxOutboxPanels(LLButton * pressedButton, LLLayoutPanel * pressedPanel, LLButton * otherButton, LLLayoutPanel * otherPanel); // // UI Elements @@ -110,7 +100,6 @@ protected: private: LLPanel* mInventoryPanel; // Main inventory view LLInventoryPanel* mInventoryPanelInbox; - LLInventoryPanel* mInventoryPanelOutbox; LLSidepanelItemInfo* mItemPanel; // Individual item view LLSidepanelTaskInfo* mTaskPanel; // Individual in-world object view LLPanelMainInventory* mPanelMainInventory; @@ -135,10 +124,9 @@ private: LLButton* mShopBtn; bool mInboxEnabled; - bool mOutboxEnabled; - LLInventoryCategoriesObserver* mCategoriesObserver; - LLInboxOutboxAddedObserver* mInboxOutboxAddedObserver; + LLInventoryCategoriesObserver* mCategoriesObserver; + LLInboxAddedObserver* mInboxAddedObserver; }; #endif //LL_LLSIDEPANELINVENTORY_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 36d6ff3ef2..7e02a41e7e 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2026,7 +2026,7 @@ bool idle_startup() const F32 wearables_time = wearables_timer.getElapsedTimeF32(); const F32 MAX_WEARABLES_TIME = 10.f; - if (!gAgent.isGenderChosen()) + if (!gAgent.isGenderChosen() && isAgentAvatarValid()) { // No point in waiting for clothing, we don't even // know what gender we are. Pop a dialog to ask and @@ -2541,6 +2541,12 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, gender = SEX_FEMALE; } + if (!isAgentAvatarValid()) + { + llwarns << "Trying to load an initial outfit for an invalid agent avatar" << llendl; + return; + } + gAgentAvatarp->setSex(gender); // try to find the outfit - if not there, create some default diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 6910b8eced..6338ea477c 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -626,6 +626,8 @@ BOOL LLToolDragAndDrop::handleToolTip(S32 x, S32 y, MASK mask) void LLToolDragAndDrop::handleDeselect() { mToolTipMsg.clear(); + + LLToolTipMgr::instance().blockToolTips(); } // protected diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 92f007a251..273d23d1a0 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -86,6 +86,8 @@ public: EAcceptance getLastAccept() { return mLastAccept; } boost::signals2::connection setEndDragCallback( const enddrag_signal_t::slot_type& cb ) { return mEndDragSignal.connect(cb); } + + uuid_vec_t::size_type getCargoIDsCount() const { return mCargoIDs.size(); } protected: enum EDropTarget diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index 7eb54271f4..c1cc9c7bc4 100755 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -95,6 +95,12 @@ bool LLGoogleTranslationHandler::parseResponse( return parseTranslation(root, translation, detected_lang); } +// virtual +bool LLGoogleTranslationHandler::isConfigured() const +{ + return !getAPIKey().empty(); +} + // static void LLGoogleTranslationHandler::parseErrorResponse( const Json::Value& root, @@ -218,6 +224,12 @@ bool LLBingTranslationHandler::parseResponse( return true; } +// virtual +bool LLBingTranslationHandler::isConfigured() const +{ + return !getAPIKey().empty(); +} + // static std::string LLBingTranslationHandler::getAPIKey() { @@ -332,6 +344,12 @@ std::string LLTranslate::getTranslateLanguage() } // static +bool LLTranslate::isTranslationConfigured() +{ + return getPreferredHandler().isConfigured(); +} + +// static const LLTranslationAPIHandler& LLTranslate::getPreferredHandler() { EService service = SERVICE_BING; diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h index c2330daa81..424bc14587 100755 --- a/indra/newview/lltranslate.h +++ b/indra/newview/lltranslate.h @@ -89,6 +89,11 @@ public: std::string& detected_lang, std::string& err_msg) const = 0; + /** + * @return if the handler is configured to function properly + */ + virtual bool isConfigured() const = 0; + virtual ~LLTranslationAPIHandler() {} protected: @@ -115,6 +120,7 @@ public: std::string& translation, std::string& detected_lang, std::string& err_msg) const; + /*virtual*/ bool isConfigured() const; private: static void parseErrorResponse( @@ -148,6 +154,7 @@ public: std::string& translation, std::string& detected_lang, std::string& err_msg) const; + /*virtual*/ bool isConfigured() const; private: static std::string getAPIKey(); }; @@ -275,8 +282,17 @@ public : * @param key Key to verify. */ static void verifyKey(KeyVerificationReceiverPtr& receiver, const std::string& key); + + /** + * @return translation target language + */ static std::string getTranslateLanguage(); + /** + * @return true if translation is configured properly. + */ + static bool isTranslationConfigured(); + private: static const LLTranslationAPIHandler& getPreferredHandler(); static const LLTranslationAPIHandler& getHandler(EService service); diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 8406f639df..01650881f9 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -83,6 +83,7 @@ #include "llfloaternotificationsconsole.h" #include "llfloaterobjectweights.h" #include "llfloateropenobject.h" +#include "llfloateroutbox.h" #include "llfloaterpay.h" #include "llfloaterperms.h" #include "llfloaterpostprocess.h" @@ -238,6 +239,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("object_weights", "floater_object_weights.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterObjectWeights>); LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>); + LLFloaterReg::add("outbox", "floater_merchant_outbox.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOutbox>); LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>); LLFloaterPayUtil::registerFloater(); diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 42dabdec0d..046360e9e9 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -26,46 +26,48 @@ #include "llviewerprecompiledheaders.h" +#include "llviewermedia.h" + #include "llagent.h" #include "llagentcamera.h" -#include "llviewermedia.h" -#include "llviewermediafocus.h" -#include "llmimetypes.h" +#include "llappviewer.h" +#include "llaudioengine.h" // for gAudiop +#include "llcallbacklist.h" +#include "lldir.h" +#include "lldiriterator.h" +#include "llevent.h" // LLSimpleListener +#include "llfilepicker.h" +#include "llfloaterwebcontent.h" // for handling window close requests and geometry change requests in media browser windows. +#include "llfocusmgr.h" +#include "llkeyboard.h" +#include "lllogininstance.h" +#include "llmarketplacefunctions.h" #include "llmediaentry.h" +#include "llmimetypes.h" +#include "llmutelist.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" +#include "llpanelprofile.h" +#include "llparcel.h" +#include "llpluginclassmedia.h" +#include "llplugincookiestore.h" +#include "llurldispatcher.h" +#include "lluuid.h" #include "llversioninfo.h" +#include "llviewermediafocus.h" #include "llviewercontrol.h" -#include "llviewertexture.h" +#include "llviewernetwork.h" #include "llviewerparcelmedia.h" #include "llviewerparcelmgr.h" +#include "llviewerregion.h" +#include "llviewertexture.h" #include "llviewertexturelist.h" -#include "llvovolume.h" -#include "llpluginclassmedia.h" -#include "llplugincookiestore.h" #include "llviewerwindow.h" -#include "llfocusmgr.h" -#include "llcallbacklist.h" -#include "llparcel.h" -#include "llaudioengine.h" // for gAudiop -#include "llurldispatcher.h" #include "llvoavatar.h" #include "llvoavatarself.h" -#include "llviewerregion.h" +#include "llvovolume.h" #include "llwebprofile.h" #include "llwebsharing.h" // For LLWebSharing::setOpenIDCookie(), *TODO: find a better way to do this! -#include "llfilepicker.h" -#include "llnotifications.h" -#include "lldir.h" -#include "lldiriterator.h" -#include "llevent.h" // LLSimpleListener -#include "llnotificationsutil.h" -#include "lluuid.h" -#include "llkeyboard.h" -#include "llmutelist.h" -#include "llpanelprofile.h" -#include "llappviewer.h" -#include "lllogininstance.h" -//#include "llfirstuse.h" -#include "llviewernetwork.h" #include "llwindow.h" #include "llvieweraudio.h" @@ -1398,75 +1400,11 @@ void LLViewerMedia::removeCookie(const std::string &name, const std::string &dom } -// This is defined in two files but I don't want to create a dependence between this and llsidepanelinventory -// just to be able to temporarily disable the outbox. -#define ENABLE_INVENTORY_DISPLAY_OUTBOX 0 // keep in sync with ENABLE_MERCHANT_OUTBOX_PANEL, ENABLE_MERCHANT_OUTBOX_CONTEXT_MENU - -class LLInventoryUserStatusResponder : public LLHTTPClient::Responder -{ -public: - LLInventoryUserStatusResponder() - : LLCurl::Responder() - { - } - - void completed(U32 status, const std::string& reason, const LLSD& content) - { - if (isGoodStatus(status)) - { - std::string merchantStatus = content[gAgent.getID().getString()].asString(); - llinfos << "Marketplace merchant status: " << merchantStatus << llendl; - - // Save the merchant status before turning on the display - gSavedSettings.setString("InventoryMarketplaceUserStatus", merchantStatus); - - // Complete success - gSavedSettings.setBOOL("InventoryDisplayInbox", true); - -#if ENABLE_INVENTORY_DISPLAY_OUTBOX - gSavedSettings.setBOOL("InventoryDisplayOutbox", true); -#endif - } - else if (status == 401) - { - // API is available for use but OpenID authorization failed - gSavedSettings.setBOOL("InventoryDisplayInbox", true); - } - else - { - // API in unavailable - llinfos << "Marketplace API is unavailable -- Inbox may be disabled, status = " << status << ", reason = " << reason << llendl; - } - } -}; - - -void doOnetimeEarlyHTTPRequests() -{ - std::string url = "https://marketplace.secondlife.com/"; - - if (!LLGridManager::getInstance()->isInProductionGrid()) - { - std::string gridLabel = LLGridManager::getInstance()->getGridLabel(); - url = llformat("https://marketplace.%s.lindenlab.com/", utf8str_tolower(gridLabel).c_str()); - - // TEMP for Jim's pdp - //url = "http://pdp24.lindenlab.com:3000/"; - } - - url += "api/1/users/"; - url += gAgent.getID().getString(); - url += "/user_status"; - - llinfos << "http get: " << url << llendl; - LLHTTPClient::get(url, new LLInventoryUserStatusResponder(), LLViewerMedia::getHeaders()); -} - - LLSD LLViewerMedia::getHeaders() { LLSD headers = LLSD::emptyMap(); headers["Accept"] = "*/*"; + headers["Content-Type"] = "application/xml"; headers["Cookie"] = sOpenIDCookie; headers["User-Agent"] = getCurrentUserAgent(); @@ -1521,9 +1459,6 @@ void LLViewerMedia::setOpenIDCookie() LLHTTPClient::get(profile_url, new LLViewerMediaWebProfileResponder(raw_profile_url.getAuthority()), headers); - - // FUI: No longer perform the user_status query - //doOnetimeEarlyHTTPRequests(); } } @@ -1966,7 +1901,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ } } - LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL; + LL_WARNS_ONCE("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL; LLSD args; args["MIME_TYPE"] = media_type; LLNotificationsUtil::add("NoPlugin", args); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 31dfa1923c..b73be4ed43 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -130,6 +130,7 @@ #include "llmorphview.h" #include "llmoveview.h" #include "llnavigationbar.h" +#include "llpaneltopinfobar.h" #include "llpopupview.h" #include "llpreviewtexture.h" #include "llprogressview.h" @@ -5001,8 +5002,8 @@ void LLViewerWindow::setUIVisibility(bool visible) gToolBarView->setToolBarsVisible(visible); } - mRootView->getChildView("topinfo_bar_container")->setVisible(visible); - mRootView->getChildView("nav_bar_container")->setVisible(visible); + LLNavigationBar::getInstance()->setVisible(visible ? gSavedSettings.getBOOL("ShowNavbarNavigationPanel") : FALSE); + LLPanelTopInfoBar::getInstance()->setVisible(visible? gSavedSettings.getBOOL("ShowMiniLocationPanel") : FALSE); mRootView->getChildView("status_bar_container")->setVisible(visible); } diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 8702ebde2a..e4a8622a4b 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -137,6 +137,7 @@ with the same filename but different name <texture name="Command_MiniCart_Icon" file_name="toolbar_icons/mini_cart.png" preload="true" /> <texture name="Command_MiniMap_Icon" file_name="toolbar_icons/mini_map.png" preload="true" /> <texture name="Command_Move_Icon" file_name="toolbar_icons/move.png" preload="true" /> + <texture name="Command_Outbox_Icon" file_name="toolbar_icons/outbox.png" preload="true" /> <texture name="Command_People_Icon" file_name="toolbar_icons/people.png" preload="true" /> <texture name="Command_Picks_Icon" file_name="toolbar_icons/picks.png" preload="true" /> <texture name="Command_Places_Icon" file_name="toolbar_icons/places.png" preload="true" /> @@ -386,22 +387,9 @@ with the same filename but different name <texture name="OptionsMenu_Off" file_name="icons/OptionsMenu_Off.png" preload="false" /> <texture name="OptionsMenu_Press" file_name="icons/OptionsMenu_Press.png" preload="false" /> - <texture name="OutboxPush_Disabled" file_name="icons/OutboxPush_Disabled.png" preload="true" /> - <texture name="OutboxPush_Off" file_name="icons/OutboxPush_Off.png" preload="true" /> - <texture name="OutboxPush_On" file_name="icons/OutboxPush_On.png" preload="true" /> - <texture name="OutboxPush_On_Over" file_name="icons/OutboxPush_On_Over.png" preload="true" /> - <texture name="OutboxPush_Over" file_name="icons/OutboxPush_Over.png" preload="true" /> - <texture name="OutboxPush_Press" file_name="icons/OutboxPush_Press.png" preload="true" /> - <texture name="OutboxPush_Progress_1" file_name="icons/OutboxPush_Progress_1.png" preload="true" /> - <texture name="OutboxPush_Progress_2" file_name="icons/OutboxPush_Progress_2.png" preload="true" /> - <texture name="OutboxPush_Progress_3" file_name="icons/OutboxPush_Progress_3.png" preload="true" /> - <texture name="OutboxPush_Progress_4" file_name="icons/OutboxPush_Progress_4.png" preload="true" /> - <texture name="OutboxPush_Progress_5" file_name="icons/OutboxPush_Progress_5.png" preload="true" /> - <texture name="OutboxPush_Progress_6" file_name="icons/OutboxPush_Progress_6.png" preload="true" /> - <texture name="OutboxPush_Selected" file_name="icons/OutboxPush_Selected.png" preload="true" /> - <texture name="OutboxPush_Selected_Disabled" file_name="icons/OutboxPush_Selected_Disabled.png" preload="true" /> - <texture name="OutboxPush_Selected_Over" file_name="icons/OutboxPush_Selected_Over.png" preload="true" /> - <texture name="OutboxPush_Selected_Press" file_name="icons/OutboxPush_Selected_Press.png" preload="true" /> + <texture name="OutboxStatus_Success" file_name="green_checkmark.png" preload="false" /> + <texture name="OutboxStatus_Warning" file_name="icons/pop_up_caution.png" preload="false" /> + <texture name="OutboxStatus_Error" file_name="red_x.png" preload="false" /> <texture name="PanOrbit_Off" file_name="bottomtray/PanOrbit_Off.png" preload="false" /> diff --git a/indra/newview/skins/default/textures/toolbar_icons/outbox.png b/indra/newview/skins/default/textures/toolbar_icons/outbox.png Binary files differnew file mode 100644 index 0000000000..0f3db1c47c --- /dev/null +++ b/indra/newview/skins/default/textures/toolbar_icons/outbox.png diff --git a/indra/newview/skins/default/xui/de/floater_chat_bar.xml b/indra/newview/skins/default/xui/de/floater_chat_bar.xml index dc5a7cd681..2464a55665 100644 --- a/indra/newview/skins/default/xui/de/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/de/floater_chat_bar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="chat_bar" title="CHAT IN DER NÄHE"> - <panel> + <panel name="bottom_panel"> <line_editor label="Zum Chatten hier klicken." name="chat_box" tool_tip="Eingabetaste zum Sprechen, Strg+Eingabe zum Rufen"/> <button name="show_nearby_chat" tool_tip="Chatprotokoll in der Nähe ein-/ausblenden"/> </panel> diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml index 72e7ec8eb4..a5fcd3e0b4 100644 --- a/indra/newview/skins/default/xui/de/notifications.xml +++ b/indra/newview/skins/default/xui/de/notifications.xml @@ -1443,7 +1443,7 @@ Zur Installation des Updates muss [APP_NAME] neu gestartet werden. <usetemplate ignoretext="Bestätigen, bevor Objekte an Ihre Eigentümer zurückgegeben werden" name="okcancelignore" notext="Abbrechen" yestext="OK"/> </notification> <notification name="GroupLeaveConfirmMember"> - Sie sind Mitglied der Gruppe [GROUP]. + Sie sind Mitglied der Gruppe <nolink>[GROUP]</nolink>. Diese Gruppe verlassen? <usetemplate name="okcancelbuttons" notext="Abbrechen" yestext="OK"/> </notification> diff --git a/indra/newview/skins/default/xui/de/panel_status_bar.xml b/indra/newview/skins/default/xui/de/panel_status_bar.xml index d34fcf70bc..2493d60df6 100644 --- a/indra/newview/skins/default/xui/de/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/de/panel_status_bar.xml @@ -18,7 +18,7 @@ <panel name="balance_bg"> <text name="balance" tool_tip="Klicken, um L$-Guthaben zu aktualisieren" value="20 L$"/> <button label="L$ kaufen" name="buyL" tool_tip="Hier klicken, um mehr L$ zu kaufen"/> - <button label="Einkaufen" name="goShop" tool_tip="Second Life-Marktplatz öffnen"/> + <button label="Einkaufen" name="goShop" tool_tip="Second Life-Marktplatz öffnen" width="85"/> </panel> <text name="TimeText" tool_tip="Aktuelle Zeit (Pazifik)"> 24:00 H PST diff --git a/indra/newview/skins/default/xui/en/floater_chat_bar.xml b/indra/newview/skins/default/xui/en/floater_chat_bar.xml index 8d0cecdac3..63992462b3 100644 --- a/indra/newview/skins/default/xui/en/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/en/floater_chat_bar.xml @@ -9,6 +9,7 @@ single_instance="true" title="NEARBY CHAT" save_rect="true" + save_visibility="true" can_close="true" can_minimize="true" help_topic="chat_bar" @@ -30,6 +31,7 @@ <panel width="300" height="31" left="0" + name="bottom_panel" bottom="-1" follows="left|right|bottom" tab_group="1"> diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml new file mode 100644 index 0000000000..02394e8ac3 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<floater + open_positioning="cascading" + can_close="true" + can_resize="true" + height="440" + help_topic="floater_merchant_outbox" + min_width="300" + min_height="200" + name="floater_merchant_outbox" + save_rect="true" + save_visibility="true" + reuse_instance="true" + title="MERCHANT OUTBOX" + width="333" > + <string name="OutboxFolderCount0">0 folders</string> + <string name="OutboxFolderCount1">1 folder</string> + <string name="OutboxFolderCountN">[NUM] folders</string> + <string name="OutboxImporting">Sending folders...</string> + <string name="OutboxInitializing">Initializing...</string> + <panel + follows="all" + layout="topleft" + left="0" + top="0" + label="" + height="440" + width="333"> + <panel + follows="all" + left="10" + bottom="400" + width="313" + top="0" + bg_opaque_color="InventoryBackgroundColor" + > + <panel + name="outbox_inventory_placeholder_panel" + follows="all" + layout="topleft" + top="0" + left="0" + width="308" + height="400" + bg_opaque_color="InventoryBackgroundColor" + > + <text + name="outbox_inventory_placeholder_title" + type="string" + follows="top|left|right" + layout="topleft" + top="10" + left="0" + width="308" + height="25" + wrap="true" + halign="center" + font="SansSerifBold"> + Loading... + </text> + <text + name="outbox_inventory_placeholder_text" + type="string" + follows="top|left|right" + layout="topleft" + top="35" + left="0" + width="308" + height="130" + wrap="true" + halign="left" /> + </panel> + </panel> + <panel + follows="bottom|left|right" + left="10" + bottom="435" + width="313" + top="405" + bg_opaque_color="InventoryBackgroundColor" + > + <text + name="outbox_folder_count" + type="string" + follows="all" + layout="topleft" + top="10" + left="5" + width="150" + height="20" + wrap="true" + halign="left" + valign="bottom" + font="SansSerif" /> + <button + label="Send to Marketplace" + tool_tip="Push to my Marketplace Storefront" + is_toggle="false" + name="outbox_import_btn" + follows="bottom|right" + tab_stop="false" + halign="center" + top="3" + left="160" + height="25" + width="150" + enabled="false" /> + </panel> + <layout_stack name="import_progress_indicator" orientation="vertical" left="0" height="440" top="0" width="333" follows="all" visible="false"> + <layout_panel /> + <layout_panel height="45" auto_resize="false"> + <layout_stack orientation="horizontal" left="0" height="45" top="0" width="333" follows="all"> + <layout_panel width="0" /> + <layout_panel width="45" auto_resize="false"> + <loading_indicator + height="45" + layout="topleft" + left="0" + top="0" + width="45" + /> + </layout_panel> + <layout_panel width="0" /> + </layout_stack> + </layout_panel> + <layout_panel /> + </layout_stack> + </panel> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_toybox.xml b/indra/newview/skins/default/xui/en/floater_toybox.xml index 493d44a9cf..72e6187a14 100644 --- a/indra/newview/skins/default/xui/en/floater_toybox.xml +++ b/indra/newview/skins/default/xui/en/floater_toybox.xml @@ -5,7 +5,7 @@ can_minimize="false" can_resize="false" default_tab_group="1" - height="330" + height="375" help_topic="toybox" layout="topleft" legacy_header_height="18" @@ -46,7 +46,7 @@ Buttons will appear as shown or as icon-only depending on each toolbar's settings. </text> <toolbar - bottom="265" + bottom="310" button_display_mode="icons_with_text" follows="all" left="20" @@ -82,11 +82,11 @@ <panel bevel_style="none" border="true" - bottom="266" + bottom="311" follows="left|bottom|right" left="20" right="-20" - top="266" /> + top="311" /> <button follows="left|bottom|right" height="23" @@ -95,7 +95,7 @@ layout="topleft" left="185" name="btn_clear_all" - top="285" + top="330" width="130"> <button.commit_callback function="Toybox.ClearAll" /> </button> @@ -107,7 +107,7 @@ layout="topleft" left="335" name="btn_restore_defaults" - top="285" + top="330" width="130"> <button.commit_callback function="Toybox.RestoreDefaults" /> </button> diff --git a/indra/newview/skins/default/xui/en/menu_edit.xml b/indra/newview/skins/default/xui/en/menu_edit.xml index fab76c497c..99061e089a 100644 --- a/indra/newview/skins/default/xui/en/menu_edit.xml +++ b/indra/newview/skins/default/xui/en/menu_edit.xml @@ -6,6 +6,7 @@ <menu_item_call label="Undo" name="Undo" + allow_key_repeat="true" shortcut="control|Z"> <menu_item_call.on_click function="Edit.Undo" /> @@ -15,6 +16,7 @@ <menu_item_call label="Redo" name="Redo" + allow_key_repeat="true" shortcut="control|Y"> <menu_item_call.on_click function="Edit.Redo" /> @@ -43,6 +45,7 @@ <menu_item_call label="Paste" name="Paste" + allow_key_repeat="true" shortcut="control|V"> <menu_item_call.on_click function="Edit.Paste" /> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 0aa5c72f2a..bdd2c8cb62 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -164,12 +164,19 @@ <menu_item_separator/> <menu_item_call - label="Buy L$" + label="Buy L$..." name="Buy and Sell L$"> <menu_item_call.on_click function="BuyCurrency" /> </menu_item_call> <menu_item_call + label="Merchant Outbox..." + name="MerchantOutbox"> + <menu_item_call.on_click + function="Floater.ToggleOrBringToFront" + parameter="outbox" /> + </menu_item_call> + <menu_item_call label="Account dashboard..." name="Manage My Account"> <menu_item_call.on_click @@ -1154,6 +1161,7 @@ enabled="false" label="Undo" name="Undo" + allow_key_repeat="true" shortcut="control|Z"> <on_click function="Edit.Undo" @@ -1165,6 +1173,7 @@ enabled="false" label="Redo" name="Redo" + allow_key_repeat="true" shortcut="control|Y"> <on_click function="Edit.Redo" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index a7705c8bac..bcb3a105ea 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -203,8 +203,8 @@ Save changes to current clothing/body part? icon="alertmodal.tga" name="ConfirmNoCopyToOutbox" type="alertmodal"> - You don't have permission to copy this item to the Marketplace Outbox. Are you sure you want to move the following item? - [ITEM_NAME] +You don't have permission to copy this item to the Marketplace Outbox. Are you sure you want to move the following item? +[ITEM_NAME] <usetemplate name="okcancelbuttons" notext="No" @@ -212,23 +212,44 @@ Save changes to current clothing/body part? </notification> <notification - icon="alertmodal.tga" - name="OutboxUploadComplete" - type="alertmodal"> -Marketplace upload complete. + icon="OutboxStatus_Success" + name="OutboxImportComplete" + type="outbox"> +Success + +All folders were successfully sent to the Marketplace. + <usetemplate name="okbutton" - yestext="Hooray!"/> + yestext="OK"/> </notification> <notification - icon="alertmodal.tga" - name="OutboxUploadHadErrors" - type="alertmodal"> -Marketplace upload completed with errors! Please correct the problems in your outbox and retry. Thanks. + icon="OutboxStatus_Warning" + name="OutboxImportHadErrors" + type="outbox"> +Some folders did not transfer + +Errors occurred when some folders were sent to the Marketplace. Those folders are still in your Merchant Outbox. See the error log for more information. + + <usetemplate + name="okbutton" + yestext="OK"/> + </notification> + + <notification + icon="OutboxStatus_Error" + name="OutboxImportFailed" + type="outbox"> +Transfer failed + +No folders were sent to the Marketplace because of a system or network error. Try again later. + +Error [ERROR_CODE] + <usetemplate name="okbutton" - yestext="Boo!"/> + yestext="OK"/> </notification> @@ -3409,7 +3430,7 @@ Are you sure you want to return the selected objects to their owners? Transferab icon="alert.tga" name="GroupLeaveConfirmMember" type="alert"> -You are currently a member of the group [GROUP]. +You are currently a member of the group <nolink>[GROUP]</nolink>. Leave Group? <tag>group</tag> <tag>confirm</tag> @@ -6953,6 +6974,26 @@ With the following Residents: <notification icon="notifytip.tga" + name="ShareFolderConfirmation" + type="alertmodal"> +Only one folder at a time can be shared. + +Are you sure you want to share the following items: + +<nolink>[ITEMS]</nolink> + +With the following Residents: + +[RESIDENTS] + <tag>confirm</tag> + <usetemplate + name="okcancelbuttons" + notext="Cancel" + yestext="Ok"/> + </notification> + + <notification + icon="notifytip.tga" name="ItemsShared" type="notifytip"> Items successfully shared. diff --git a/indra/newview/skins/default/xui/en/panel_group_general.xml b/indra/newview/skins/default/xui/en/panel_group_general.xml index 38b680ba86..adde982c60 100644 --- a/indra/newview/skins/default/xui/en/panel_group_general.xml +++ b/indra/newview/skins/default/xui/en/panel_group_general.xml @@ -225,13 +225,22 @@ Hover your mouse over the options for more help. height="23" increment="1" label_width="15" - label="L$" layout="topleft" max_val="99999" left="30" name="spin_enrollment_fee" tool_tip="New members must pay this fee to join the group when Enrollment Fee is checked." - width="170" /> + width="150" /> + <text + follows="left|top" + type="string" + height="16" + left_pad="2" + name="currency_label" + top_delta="5" + width="18"> + L$ + </text> <combo_box follows="left|top" height="23" diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index e6c5110999..3007be7d5e 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel - background_visible="true" default_tab_group="1" follows="all" height="423" @@ -51,10 +50,6 @@ top="18" width="303" /> <tab_container - bg_alpha_color="DkGray" - bg_opaque_color="DkGray" - background_visible="true" - background_opaque="true" follows="all" halign="center" height="339" @@ -71,7 +66,6 @@ bg_opaque_color="DkGray2" bg_alpha_color="DkGray2" background_visible="true" - background_opaque="true" border="false" bevel_style="none" follows="all" @@ -90,7 +84,6 @@ bg_opaque_color="DkGray2" bg_alpha_color="DkGray2" background_visible="true" - background_opaque="true" border="false" bevel_style="none" follows="all" diff --git a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml index 66117615e4..a3d39e55af 100644 --- a/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_outbox_inventory.xml @@ -8,7 +8,6 @@ bg_opaque_color="DkGray2" bg_alpha_color="DkGray2" background_visible="true" - background_opaque="true" border="false" bevel_style="none" show_item_link_overlays="true" diff --git a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml index d8ff043444..ebba292a93 100644 --- a/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml +++ b/indra/newview/skins/default/xui/en/panel_snapshot_postcard.xml @@ -16,14 +16,6 @@ name="upload_message"> Sending... </string> - <string - name="default_subject"> - Postcard from [SECOND_LIFE]. - </string> - <string - name="default_message"> - Check this out! - </string> <icon follows="top|left" height="18" diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml index 3239c4e531..d453a970e7 100644 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -70,7 +70,7 @@ pad_bottom="2" tool_tip="Click to buy more L$" top="0" - width="55" /> + width="80" /> <button halign="left" font="SansSerifSmall" @@ -87,7 +87,6 @@ left_pad="0" label_shadow="true" name="goShop" - pad_right="0" pad_bottom="2" tool_tip="Open Second Life Marketplace" top="0" diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml index b52784d6bc..a26eb23a5d 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml @@ -1,6 +1,5 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <panel - background_visible="true" follows="all" height="570" label="Things" @@ -30,7 +29,7 @@ width="330"> <layout_panel name="main_inventory_layout_panel" - layout="topleft" + layout="topleft" min_dim="150" width="330" follows="bottom|left|right" @@ -48,41 +47,18 @@ height="300" width="330" /> </layout_panel> - <layout_panel - width="330" - layout="topleft" - auto_resize="true" - user_resize="false" - follows="bottom|left|right" - name="inbox_outbox_layout_panel" - visible="false" - min_dim="35" - max_dim="235" - expanded_min_dim="125" - height="235"> - <layout_stack - follows="left|right|top|bottom" - layout="topleft" - left="0" - top="0" - orientation="vertical" - name="inbox_outbox_layout_stack" - open_time_constant="0.02" - close_time_constant="0.02" - height="235" - width="330"> - <layout_panel + <layout_panel width="330" - layout="topleft" + layout="topleft" auto_resize="true" user_resize="false" follows="left|right|top" name="inbox_layout_panel" visible="false" min_dim="35" - max_dim="200" + max_dim="235" expanded_min_dim="90" - height="200"> + height="235"> <panel follows="all" layout="topleft" @@ -91,13 +67,13 @@ class="panel_marketplace_inbox" top="0" label="" - height="200" + height="235" width="330"> <string name="InboxLabelWithArg">Received items ([NUM])</string> <string name="InboxLabelNoArg">Received items</string> <button label="Received items" - font="SansSerifMedium" + font="SansSerifMedium" name="inbox_btn" height="35" width="308" @@ -129,7 +105,7 @@ <panel follows="all" left="10" - bottom="200" + bottom="235" width="308" top="35" bg_opaque_color="InventoryBackgroundColor" @@ -145,7 +121,7 @@ top="0" left="0" width="308" - height="165" + height="200" wrap="true" halign="center"> Purchases from the marketplace will be delivered here. @@ -153,139 +129,6 @@ </panel> </panel> </layout_panel> - <layout_panel - width="330" - layout="topleft" - auto_resize="true" - user_resize="false" - follows="all" - name="outbox_layout_panel" - visible="false" - min_dim="35" - max_dim="200" - expanded_min_dim="90" - height="200"> - <panel - follows="all" - layout="topleft" - left="0" - name="marketplace_outbox" - class="panel_marketplace_outbox" - top="0" - label="" - height="200" - width="330"> - <string name="OutboxLabelWithArg">Merchant outbox ([NUM])</string> - <string name="OutboxLabelNoArg">Merchant outbox</string> - <button - label="Merchant outbox" - font="SansSerifMedium" - name="outbox_btn" - height="35" - width="308" - image_unselected="MarketplaceBtn_Off" - image_selected="MarketplaceBtn_Selected" - halign="left" - handle_right_mouse="false" - follows="top|left|right" - is_toggle="true" - tab_stop="false" - pad_left="35" - top="0" - left="10" /> - <button - image_unselected="OutboxPush_Off" - image_selected="OutboxPush_Selected" - image_hover_selected="OutboxPush_Selected_Over" - image_hover_unselected="OutboxPush_Over" - image_disabled_selected="OutboxPush_Selected_Disabled" - image_disabled="OutboxPush_Disabled" - image_pressed="OutboxPush_Press" - image_pressed_selected="OutboxPush_Selected_Press" - label="" - tool_tip="Push to my Marketplace Storefront" - is_toggle="false" - name="outbox_sync_btn" - follows="top|right" - tab_stop="false" - halign="center" - top="6" - left="-50" - height="23" - width="32" - enabled="false" /> - <loading_indicator - follows="top|right" - name="outbox_sync_indicator" - top="6" - left="-50" - height="23" - width="32" - images_per_sec="1.15" - tab_stop="false" - visible="false"> - <images> - <image name="OutboxPush_Progress_1"/> - <image name="OutboxPush_Progress_2"/> - <image name="OutboxPush_Progress_3"/> - <image name="OutboxPush_Progress_4"/> - <image name="OutboxPush_Progress_5"/> - <image name="OutboxPush_Progress_6"/> - </images> - </loading_indicator> - <panel - follows="all" - left="10" - bottom="200" - width="308" - top="35" - bg_opaque_color="InventoryBackgroundColor" - background_visible="true" - background_opaque="true" - > - <panel - name="outbox_inventory_placeholder_panel" - follows="all" - layout="topleft" - top="0" - left="0" - width="308" - height="165" - bg_opaque_color="InventoryBackgroundColor" - background_visible="true" - background_opaque="true" - > - <text - name="outbox_inventory_placeholder_title" - type="string" - follows="all" - layout="topleft" - top="10" - left="0" - width="308" - height="25" - wrap="true" - halign="center" - font="SansSerifBold"> - Loading... - </text> - <text - name="outbox_inventory_placeholder_text" - type="string" - follows="all" - layout="topleft" - top="35" - left="0" - width="308" - height="130" - wrap="true" - halign="left" /> - </panel> - </panel> - </panel> - </layout_panel> - </layout_stack> - </layout_panel> </layout_stack> <panel follows="bottom|left|right" @@ -406,8 +249,7 @@ </layout_stack> </panel> </panel> - -<panel + <panel follows="all" layout="topleft" left="0" @@ -420,8 +262,7 @@ visible="false" width="330"> </panel> - -<panel + <panel follows="all" layout="topleft" left="0" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 9752a07b66..7041cb8e22 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -164,10 +164,16 @@ Please try logging in again in a minute.</string> <string name="TooltipLand">Land:</string> <string name="TooltipMustSingleDrop">Only a single item can be dragged here</string> <string name="TooltipPrice" value="L$[AMOUNT]: "/> - <string name="TooltipOutboxNoTransfer">One or more of these objects cannot be sold or transferred to another user.</string> - <string name="TooltipOutboxWorn">You are wearing one or more of these objects. Remove them from your avatar and try moving them again.</string> - <string name="TooltipOutboxFolderLevels">This folder has too many levels of subfolders. Rearrange the interior folders to a maximum of 4 levels deep (Root Folder contains A contains B contains C).</string> - <string name="TooltipOutboxTooManyObjects">This folder contains more than 200 objects. Box some of the items to reduce the object count.</string> + + <string name="TooltipOutboxNoTransfer">One or more of these objects cannot be sold or transferred.</string> + <string name="TooltipOutboxNotInInventory">Your merchant outbox can only accept items directly from your inventory</string> + <string name="TooltipOutboxWorn">You can not put items you are wearing into your merchant outbox</string> + <string name="TooltipOutboxFolderLevels">Depth of nested folders exceeds 3</string> + <string name="TooltipOutboxTooManyFolders">Subfolder count in top-level folder exceeds 20</string> + <string name="TooltipOutboxTooManyObjects">Item count in top-level folder exceeds 200</string> + + <string name="TooltipDragOntoOwnChild">You can't move a folder into its child</string> + <string name="TooltipDragOntoSelf">You can't move a folder into itself</string> <!-- tooltips for Urls --> <string name="TooltipHttpUrl">Click to view this web page</string> @@ -2029,23 +2035,26 @@ Returns a string with the requested data about the region <string name="FavoritesNoMatchingItems">Drag a landmark here to add it to your favorites.</string> <string name="InventoryNoTexture">You do not have a copy of this texture in your inventory</string> <string name="InventoryInboxNoItems">When you purchase or otherwise receive an item, it will appear here so you can drag it to a folder in your inventory, or delete it if you do not wish to keep it.</string> - <string name="MarketplaceURL">http://marketplace.[DOMAIN_NAME]</string> - <string name="MarketplaceURL_CreateStore">http://marketplace.[DOMAIN_NAME]/create_store</string> - <string name="MarketplaceURL_LearnMore">http://marketplace.[DOMAIN_NAME]/learn_more</string> - <string name="InventoryOutboxCreationErrorTitle">Your Merchant Outbox is not properly configured</string> - <string name="InventoryOutboxCreationErrorTooltip">Merchant Outbox configuration error</string> - <string name="InventoryOutboxCreationError">Please contact Customer Service to correct the problem.</string> - <string name="InventoryOutboxNotMerchantTitle">Anyone can sell items on the Marketplace</string> - <string name="InventoryOutboxNotMerchantTooltip">Become a merchant!</string> - <string name="InventoryOutboxNotMerchant">[[MARKETPLACE_URL] The Second Life Marketplace] offers more than one million virtual products for sale, all of them created by Residents. You, too, can sell items you create, as well as some of the items you have purchased. It’s easy and setup is free. [[LEARN_MORE_URL] Learn more] or [[CREATE_STORE_URL] create a store] on the Marketplace to get started.</string> - <string name="InventoryOutboxNoItemsTitle">A new way to send items to the Marketplace</string> - <string name="InventoryOutboxNoItemsTooltip">Drag and drop items here to prepare them for sale on the Marketplace</string> - <string name="InventoryOutboxNoItems">Drag items or folders that you wish to sell into this area. A copy of the item will appear, leaving your inventory unchanged, unless you have dragged a no-copy item. When you are ready to send the items to the Marketplace, click the Upload button. Once your items have been moved to your Marketplace Inventory, they will disappear from this folder.</string> + <string name="MarketplaceURL">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/</string> + <string name="MarketplaceURL_CreateStore">http://community.secondlife.com/t5/English-Knowledge-Base/Selling-in-the-Marketplace/ta-p/700193#Section_.4</string> + <string name="MarketplaceURL_Dashboard">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/merchants/store/dashboard</string> + <string name="MarketplaceURL_LearnMore">https://marketplace.[MARKETPLACE_DOMAIN_NAME]/learn_more</string> + <string name="InventoryOutboxNotMerchantTitle">Anyone can sell items on the Marketplace.</string> + <string name="InventoryOutboxNotMerchantTooltip"></string> + <string name="InventoryOutboxNotMerchant"> +If you'd like to become a merchant, you'll need to [[MARKETPLACE_CREATE_STORE_URL] create a Marketplace store]. + </string> + <string name="InventoryOutboxNoItemsTitle">Your outbox is empty.</string> + <string name="InventoryOutboxNoItemsTooltip"></string> + <string name="InventoryOutboxNoItems"> +Drag folders to this area and click "Send to Marketplace" to list them for sale on the [[MARKETPLACE_DASHBOARD_URL] Marketplace]. + </string> <string name="Marketplace Error None">No errors</string> <string name="Marketplace Error Not Merchant">Error: Before sending items to the Marketplace you will need to set yourself up as a merchant (free of charge).</string> <string name="Marketplace Error Empty Folder">Error: This folder has no contents.</string> - <string name="Marketplace Error Unassociated Products">Error: This item failed to upload because your merchant account has too many items unassociated with products. To fix this error, login to the marketplace website and reduce your unassociated item count.</string> + <string name="Marketplace Error Unassociated Products">Error: This item failed to upload because your merchant account has too many items unassociated with products. To fix this error, log in to the marketplace website and reduce your unassociated item count.</string> + <string name="Marketplace Error Object Limit">Error: This item contains too many objects. Fix this error by placing objects together in boxes to reduce the total count to less than 200.</string> <string name="Marketplace Error Folder Depth">Error: This item contains too many levels of nested folders. Reorganize it to a maximum of 3 levels of nested folders.</string> <string name="Marketplace Error Unsellable Item">Error: This item can not be sold on the marketplace.</string> @@ -2272,7 +2281,7 @@ Returns a string with the requested data about the region <string name="NextStipendDay" value="The next stipend day is " /> <string name="GroupPlanningDate">[mthnum,datetime,utc]/[day,datetime,utc]/[year,datetime,utc]</string> <string name="GroupIndividualShare" value=" Group Individual Share" /> - <string name="GroupColumn" value=" Group" /> + <string name="GroupColumn" value="Group" /> <string name="Balance">Balance</string> <string name="Credits">Credits</string> <string name="Debits">Debits</string> @@ -3503,6 +3512,9 @@ Abuse Report</string> <string name="dateTimeDayFormat">[MDAY]</string> <string name="dateTimeAM">AM</string> <string name="dateTimePM">PM</string> + + <!-- Format string for displaying a localized date in a scroll list cell of type "date" --> + <string name="ScrollListCellDateFormat">[wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local]</string> <!-- currency formatting --> <string name="LocalEstimateUSD">US$ [AMOUNT]</string> @@ -3680,6 +3692,7 @@ Try enclosing path to the editor with double quotes. <string name="Command_Marketplace_Label">Marketplace</string> <string name="Command_MiniMap_Label">Mini-map</string> <string name="Command_Move_Label">Walk / run / fly</string> + <string name="Command_Outbox_Label">Merchant outbox</string> <string name="Command_People_Label">People</string> <string name="Command_Picks_Label">Picks</string> <string name="Command_Places_Label">Places</string> @@ -3705,6 +3718,7 @@ Try enclosing path to the editor with double quotes. <string name="Command_Marketplace_Tooltip">Go shopping</string> <string name="Command_MiniMap_Tooltip">Show nearby people</string> <string name="Command_Move_Tooltip">Moving your avatar</string> + <string name="Command_Outbox_Tooltip">Transfer items to your marketplace for sale</string> <string name="Command_People_Tooltip">Friends, groups, and nearby people</string> <string name="Command_Picks_Tooltip">Places to show as favorites in your profile</string> <string name="Command_Places_Tooltip">Places you've saved</string> diff --git a/indra/newview/skins/default/xui/en/widgets/window_shade.xml b/indra/newview/skins/default/xui/en/widgets/window_shade.xml new file mode 100644 index 0000000000..23eb2f13fb --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/window_shade.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<window_shade shade_color="0 0 0 0.5"/> diff --git a/indra/newview/skins/default/xui/es/floater_chat_bar.xml b/indra/newview/skins/default/xui/es/floater_chat_bar.xml index 5e5ef616b8..2e94805057 100644 --- a/indra/newview/skins/default/xui/es/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/es/floater_chat_bar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="chat_bar" title="CHAT"> - <panel> + <panel name="bottom_panel"> <line_editor label="Pulsa aquí para chatear." name="chat_box" tool_tip="Pulsa Enter para decirlo o Ctrl+Enter para gritarlo"/> <button name="show_nearby_chat" tool_tip="Muestra o esconde el registro del chat"/> </panel> diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml index 9591b424fc..0de56f9b6d 100644 --- a/indra/newview/skins/default/xui/es/notifications.xml +++ b/indra/newview/skins/default/xui/es/notifications.xml @@ -1437,7 +1437,7 @@ Debemos reiniciar [APP_NAME] para instalar la actualización. <usetemplate ignoretext="Confirmar antes de devolver objetos a sus propietarios." name="okcancelignore" notext="Cancelar" yestext="OK"/> </notification> <notification name="GroupLeaveConfirmMember"> - Actualmente, eres miembro del grupo [GROUP]. + Actualmente, eres miembro del grupo <nolink>[GROUP]</nolink>. ¿Dejar el grupo? <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="OK"/> </notification> diff --git a/indra/newview/skins/default/xui/es/panel_status_bar.xml b/indra/newview/skins/default/xui/es/panel_status_bar.xml index d43790c8c6..79b2c32b23 100644 --- a/indra/newview/skins/default/xui/es/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/es/panel_status_bar.xml @@ -18,7 +18,7 @@ <panel name="balance_bg"> <text name="balance" tool_tip="Haz clic para actualizar tu saldo en L$" value="20 L$"/> <button label="Comprar L$" name="buyL" tool_tip="Pulsa para comprar más L$"/> - <button label="Comprar" name="goShop" tool_tip="Abrir el mercado de Second Life"/> + <button label="Comprar" name="goShop" tool_tip="Abrir el mercado de Second Life" width="80"/> </panel> <text name="TimeText" tool_tip="Hora actual (Pacífico)"> 24:00 AM PST diff --git a/indra/newview/skins/default/xui/fr/floater_chat_bar.xml b/indra/newview/skins/default/xui/fr/floater_chat_bar.xml index 88a2fb669b..c7d27c0589 100644 --- a/indra/newview/skins/default/xui/fr/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/fr/floater_chat_bar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="chat_bar" title="CHAT PRÈS DE MOI"> - <panel> + <panel name="bottom_panel"> <line_editor label="Cliquer ici pour chatter." name="chat_box" tool_tip="Appuyer sur Entrée pour dire, Ctrl-Entrée pour crier"/> <button name="show_nearby_chat" tool_tip="Affiche/Masque le journal de chats près de vous"/> </panel> diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml index d8d79d8dde..be6f1f8c31 100644 --- a/indra/newview/skins/default/xui/fr/notifications.xml +++ b/indra/newview/skins/default/xui/fr/notifications.xml @@ -1428,7 +1428,7 @@ Version [VERSION] <usetemplate ignoretext="Confirmer avant de rendre les objets à leurs propriétaires" name="okcancelignore" notext="Annuler" yestext="OK"/> </notification> <notification name="GroupLeaveConfirmMember"> - Vous êtes actuellement membre du groupe [GROUP]. + Vous êtes actuellement membre du groupe <nolink>[GROUP]</nolink>. Quitter le groupe ? <usetemplate name="okcancelbuttons" notext="Annuler" yestext="OK"/> </notification> diff --git a/indra/newview/skins/default/xui/fr/panel_status_bar.xml b/indra/newview/skins/default/xui/fr/panel_status_bar.xml index ac61eb7e52..c0d59a3182 100644 --- a/indra/newview/skins/default/xui/fr/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/fr/panel_status_bar.xml @@ -18,7 +18,7 @@ <panel name="balance_bg"> <text name="balance" tool_tip="Cliquer sur ce bouton pour actualiser votre solde en L$." value="20 L$"/> <button label="Acheter L$" name="buyL" tool_tip="Cliquer pour acheter plus de L$."/> - <button label="Achats" name="goShop" tool_tip="Ouvrir la Place du marché Second Life."/> + <button label="Achats" name="goShop" tool_tip="Ouvrir la Place du marché Second Life." width="75"/> </panel> <text name="TimeText" tool_tip="Heure actuelle (Pacifique)"> 00h00 PST diff --git a/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml b/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml index 95649d3934..0b5333fc80 100644 --- a/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml +++ b/indra/newview/skins/default/xui/fr/sidepanel_item_info.xml @@ -13,7 +13,7 @@ Le propriétaire peut : </panel.string> <panel.string name="acquiredDate"> - [wkday,datetime,local] [mth,datetime,local] [day,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] [year,datetime,local] + [wkday,datetime,local] [day,datetime,local] [mth,datetime,local] [year,datetime,local] [hour,datetime,local]:[min,datetime,local]:[second,datetime,local] </panel.string> <panel.string name="origin_inventory"> (inventaire) diff --git a/indra/newview/skins/default/xui/it/floater_chat_bar.xml b/indra/newview/skins/default/xui/it/floater_chat_bar.xml index 6c5c8fbea0..94c85b50c8 100644 --- a/indra/newview/skins/default/xui/it/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/it/floater_chat_bar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="chat_bar" title="CHAT NEI DINTORNI"> - <panel> + <panel name="bottom_panel"> <line_editor label="Clicca qui per la chat." name="chat_box" tool_tip="Premi Invio per parlare, Ctrl+Invio per gridare"/> <button name="show_nearby_chat" tool_tip="Mostra/Nasconde il registro della chat nei dintorni"/> </panel> diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml index 2db0892cd6..fce027da0c 100644 --- a/indra/newview/skins/default/xui/it/notifications.xml +++ b/indra/newview/skins/default/xui/it/notifications.xml @@ -1432,7 +1432,7 @@ Per installare l'aggiornamento è necessario riavviare [APP_NAME]. <usetemplate ignoretext="Conferma prima di restituire gli oggetti ai relativi proprietari" name="okcancelignore" notext="Annulla" yestext="OK"/> </notification> <notification name="GroupLeaveConfirmMember"> - Sei attualmente un membro del gruppo [GROUP]. + Sei attualmente un membro del gruppo <nolink>[GROUP]</nolink>. Vuoi lasciare il gruppo? <usetemplate name="okcancelbuttons" notext="Annulla" yestext="OK"/> </notification> diff --git a/indra/newview/skins/default/xui/it/panel_status_bar.xml b/indra/newview/skins/default/xui/it/panel_status_bar.xml index fadaa575ea..4abc90113f 100644 --- a/indra/newview/skins/default/xui/it/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/it/panel_status_bar.xml @@ -18,7 +18,7 @@ <panel name="balance_bg"> <text name="balance" tool_tip="Clicca per aggiornare il tuo saldo in L$" value="L$ 20"/> <button label="Acquista L$" name="buyL" tool_tip="Clicca per acquistare più L$"/> - <button label="Acquisti" name="goShop" tool_tip="Apri Mercato Second Life"/> + <button label="Acquisti" name="goShop" tool_tip="Apri Mercato Second Life" width="75"/> </panel> <text name="TimeText" tool_tip="Orario attuale (Pacifico)"> 24:00, ora del Pacifico diff --git a/indra/newview/skins/default/xui/ja/floater_chat_bar.xml b/indra/newview/skins/default/xui/ja/floater_chat_bar.xml index 9735afb101..504cea5931 100644 --- a/indra/newview/skins/default/xui/ja/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/ja/floater_chat_bar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="chat_bar" title="近くのチャット"> - <panel> + <panel name="bottom_panel"> <line_editor label="ここをクリックしてチャットを開始します。" name="chat_box" tool_tip="Enter キーを押して話し、Ctrl + Enter キーで叫びます。"/> <button name="show_nearby_chat" tool_tip="近くのチャットログを表示・非表示"/> </panel> diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml index 7dfa6d2f7a..141f2c8071 100644 --- a/indra/newview/skins/default/xui/ja/notifications.xml +++ b/indra/newview/skins/default/xui/ja/notifications.xml @@ -1467,7 +1467,7 @@ http://secondlife.com/download から最新バージョンをダウンロード <usetemplate ignoretext="オブジェクトを所有者に返却する前の確認" name="okcancelignore" notext="取り消し" yestext="OK"/> </notification> <notification name="GroupLeaveConfirmMember"> - 現在あなたは [GROUP] のメンバーです。 + 現在あなたは <nolink>[GROUP]</nolink> のメンバーです。 このグループを抜けますか? <usetemplate name="okcancelbuttons" notext="取り消し" yestext="OK"/> </notification> diff --git a/indra/newview/skins/default/xui/ja/panel_status_bar.xml b/indra/newview/skins/default/xui/ja/panel_status_bar.xml index 93689b81af..4fb876f690 100644 --- a/indra/newview/skins/default/xui/ja/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/ja/panel_status_bar.xml @@ -18,7 +18,7 @@ <panel name="balance_bg"> <text name="balance" tool_tip="クリックして L$ 残高を更新" value="L$20"/> <button label="L$ の購入" name="buyL" tool_tip="クリックして L$ を購入します"/> - <button label="店" name="goShop" tool_tip="Second Life マーケットプレイスを開く"/> + <button label="店" name="goShop" tool_tip="Second Life マーケットプレイスを開く" width="40"/> </panel> <text name="TimeText" tool_tip="現在時刻(太平洋)"> 24:00 AM PST diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml index e1fb6dd3f1..0194293642 100644 --- a/indra/newview/skins/default/xui/pl/notifications.xml +++ b/indra/newview/skins/default/xui/pl/notifications.xml @@ -1385,7 +1385,7 @@ W celu instalacji aktualizacji musi zostać wykonany restart [APP_NAME]. <usetemplate ignoretext="Potwierdź zanim zwrócisz obiekty do ich właścicieli" name="okcancelignore" notext="Anuluj" yestext="OK"/> </notification> <notification name="GroupLeaveConfirmMember"> - Jesteś członkiem grupy [GROUP]. + Jesteś członkiem grupy <nolink>[GROUP]</nolink>. Chcesz opuścić grupę? <usetemplate name="okcancelbuttons" notext="Anuluj" yestext="OK"/> </notification> diff --git a/indra/newview/skins/default/xui/pt/floater_chat_bar.xml b/indra/newview/skins/default/xui/pt/floater_chat_bar.xml index c089ab93f2..72016c6b40 100644 --- a/indra/newview/skins/default/xui/pt/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/pt/floater_chat_bar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="chat_bar" title="BATE-PAPO LOCAL"> - <panel> + <panel name="bottom_panel"> <line_editor label="Clique aqui para bater papo." name="chat_box" tool_tip="Tecle Enter para falar, Ctrl+Enter para gritar"/> <button name="show_nearby_chat" tool_tip="Mostra/oculta o histórico do bate-papo local"/> </panel> diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml index d3547beeb3..b53ebeb136 100644 --- a/indra/newview/skins/default/xui/pt/notifications.xml +++ b/indra/newview/skins/default/xui/pt/notifications.xml @@ -1419,7 +1419,7 @@ Para instalar a atualização, será preciso reiniciar o [APP_NAME]. <usetemplate ignoretext="Confirmar antes de devolver objetos a seus donos" name="okcancelignore" notext="Cancelar" yestext="Retornar"/> </notification> <notification name="GroupLeaveConfirmMember"> - Você é atualmente um membro do grupo [GROUP]. + Você é atualmente um membro do grupo <nolink>[GROUP]</nolink>. Sair do grupo? <usetemplate name="okcancelbuttons" notext="Cancelar" yestext="Sair"/> </notification> diff --git a/indra/newview/skins/default/xui/pt/panel_status_bar.xml b/indra/newview/skins/default/xui/pt/panel_status_bar.xml index d5a3258ddc..22853f0643 100644 --- a/indra/newview/skins/default/xui/pt/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/pt/panel_status_bar.xml @@ -18,7 +18,7 @@ <panel name="balance_bg"> <text name="balance" tool_tip="Atualizar saldo de L$" value="L$20"/> <button label="Comprar L$" name="buyL" tool_tip="Comprar mais L$"/> - <button label="Comprar" name="goShop" tool_tip="Abrir Mercado do Second Life"/> + <button label="Comprar" name="goShop" tool_tip="Abrir Mercado do Second Life" width="80"/> </panel> <text name="TimeText" tool_tip="Hora atual (Pacífico)"> 24:00 AM PST diff --git a/indra/newview/skins/default/xui/ru/floater_chat_bar.xml b/indra/newview/skins/default/xui/ru/floater_chat_bar.xml index eceab1775a..79b7b033fb 100644 --- a/indra/newview/skins/default/xui/ru/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/ru/floater_chat_bar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="chat_bar" title="ЛОКАЛЬНЫЙ ЧАТ"> - <panel> + <panel name="bottom_panel"> <line_editor label="Щелкните здесь для общения." name="chat_box" tool_tip="Нажмите Enter, чтобы сказать, Ctrl+Enter, чтобы прокричать"/> <button name="show_nearby_chat" tool_tip="Показать/скрыть лог локального чата"/> </panel> diff --git a/indra/newview/skins/default/xui/ru/notifications.xml b/indra/newview/skins/default/xui/ru/notifications.xml index 1be14160ed..f121743fe9 100644 --- a/indra/newview/skins/default/xui/ru/notifications.xml +++ b/indra/newview/skins/default/xui/ru/notifications.xml @@ -1431,7 +1431,7 @@ http://secondlife.com/download. <usetemplate ignoretext="Подтверждать перед возвратом объектов владельцам" name="okcancelignore" notext="Отмена" yestext="OK"/> </notification> <notification name="GroupLeaveConfirmMember"> - Вы являетесь участником группы [GROUP]. + Вы являетесь участником группы <nolink>[GROUP]</nolink>. Хотите покинуть группу? <usetemplate name="okcancelbuttons" notext="Отмена" yestext="OK"/> </notification> diff --git a/indra/newview/skins/default/xui/ru/panel_status_bar.xml b/indra/newview/skins/default/xui/ru/panel_status_bar.xml index 6822244196..babe5811ac 100644 --- a/indra/newview/skins/default/xui/ru/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/ru/panel_status_bar.xml @@ -18,7 +18,7 @@ <panel name="balance_bg"> <text name="balance" tool_tip="Щелкните для обновления вашего баланса L$" value="L$20"/> <button label="Купить L$" name="buyL" tool_tip="Щелкните для покупки L$"/> - <button label="Торговый центр" name="goShop" tool_tip="Открыть торговый центр Second Life"/> + <button label="Торговый центр" name="goShop" tool_tip="Открыть торговый центр Second Life" width="121"/> </panel> <text name="TimeText" tool_tip="Текущее время (тихоокеанское)"> 00:00 (тихоокеанское время) diff --git a/indra/newview/skins/default/xui/tr/floater_chat_bar.xml b/indra/newview/skins/default/xui/tr/floater_chat_bar.xml index d2385e6be3..dee17b7bc4 100644 --- a/indra/newview/skins/default/xui/tr/floater_chat_bar.xml +++ b/indra/newview/skins/default/xui/tr/floater_chat_bar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8" standalone="yes"?> <floater name="chat_bar" title="YAKINDAKİ SOHBET"> - <panel> + <panel name="bottom_panel"> <line_editor label="Sohbet etmek için buraya tıklayın." name="chat_box" tool_tip="Söylemek için Enter, bağırmak için Ctrl+Enter yapın"/> <button name="show_nearby_chat" tool_tip="yakın sohbet günlüğünü gösterir/gizler"/> </panel> diff --git a/indra/newview/skins/default/xui/tr/notifications.xml b/indra/newview/skins/default/xui/tr/notifications.xml index 6908f6867f..c0dc67ed34 100644 --- a/indra/newview/skins/default/xui/tr/notifications.xml +++ b/indra/newview/skins/default/xui/tr/notifications.xml @@ -1431,7 +1431,7 @@ Güncellemeyi kurmak için [APP_NAME] uygulamasını yeniden başlatmalısınız <usetemplate ignoretext="Nesneleri sahiplerine iade etmeden önce doğrulama iste" name="okcancelignore" notext="İptal" yestext="Tamam"/> </notification> <notification name="GroupLeaveConfirmMember"> - Şu anda [GROUP] grubunun bir üyesisiniz. + Şu anda <nolink>[GROUP]</nolink> grubunun bir üyesisiniz. Gruptan ayrılmak istiyor musunuz? <usetemplate name="okcancelbuttons" notext="İptal" yestext="Tamam"/> </notification> diff --git a/indra/newview/skins/default/xui/tr/panel_status_bar.xml b/indra/newview/skins/default/xui/tr/panel_status_bar.xml index 63726b94e2..81c304a5d8 100644 --- a/indra/newview/skins/default/xui/tr/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/tr/panel_status_bar.xml @@ -18,7 +18,7 @@ <panel name="balance_bg"> <text name="balance" tool_tip="L$ bakiyenizi yenilemek için buraya tıklayın" value="L$20"/> <button label="L$ Satın Al" name="buyL" tool_tip="Daha fazla L$ satın almak için tıklayın"/> - <button label="Alışveriş yap" name="goShop" tool_tip="Second Life Pazaryeri Aç"/> + <button label="Alışveriş yap" name="goShop" tool_tip="Second Life Pazaryeri Aç" width="95"/> </panel> <text name="TimeText" tool_tip="Geçerli zaman (Pasifik)"> 24:00 AM PST diff --git a/indra/newview/skins/default/xui/zh/notifications.xml b/indra/newview/skins/default/xui/zh/notifications.xml index 17ff6288a5..3fa8ff3f78 100644 --- a/indra/newview/skins/default/xui/zh/notifications.xml +++ b/indra/newview/skins/default/xui/zh/notifications.xml @@ -1418,7 +1418,7 @@ We must restart [APP_NAME] to install the update. <usetemplate ignoretext="在我退回物件給它們的擁有者前確認" name="okcancelignore" notext="取消" yestext="確定"/> </notification> <notification name="GroupLeaveConfirmMember"> - 你目前是 [GROUP] 群組的成員。 + 你目前是 <nolink>[GROUP]</nolink> 群組的成員。 是否要離開群組? <usetemplate name="okcancelbuttons" notext="取消" yestext="確定"/> </notification> diff --git a/indra/newview/skins/paths.xml b/indra/newview/skins/paths.xml index e6d68488ea..3c0da041c7 100644 --- a/indra/newview/skins/paths.xml +++ b/indra/newview/skins/paths.xml @@ -1,4 +1,4 @@ -<paths> +<paths> <directory> <subdir>xui</subdir> <subdir>en</subdir> |