summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/cmake/DragDrop.cmake23
-rw-r--r--indra/llui/lltextbase.cpp13
-rw-r--r--indra/llui/lltextbase.h2
-rw-r--r--indra/llui/llviewmodel.h3
-rw-r--r--indra/llwindow/CMakeLists.txt3
-rw-r--r--indra/llwindow/lldragdropwin32.cpp370
-rw-r--r--indra/llwindow/lldragdropwin32.h80
-rw-r--r--indra/llwindow/llwindowcallbacks.cpp5
-rw-r--r--indra/llwindow/llwindowcallbacks.h15
-rw-r--r--indra/llwindow/llwindowmacosx.cpp195
-rw-r--r--indra/llwindow/llwindowmacosx.h16
-rw-r--r--indra/llwindow/llwindowwin32.cpp33
-rw-r--r--indra/llwindow/llwindowwin32.h6
-rw-r--r--indra/newview/CMakeLists.txt1
-rw-r--r--indra/newview/app_settings/settings.xml22
-rw-r--r--indra/newview/llfloaterland.cpp22
-rw-r--r--indra/newview/llfloaterscriptlimits.cpp987
-rw-r--r--indra/newview/llfloaterscriptlimits.h76
-rw-r--r--indra/newview/llpanellogin.cpp17
-rw-r--r--indra/newview/llpanellogin.h3
-rw-r--r--indra/newview/llpreviewscript.cpp2
-rw-r--r--indra/newview/llviewermessage.cpp3
-rw-r--r--indra/newview/llviewerwindow.cpp135
-rw-r--r--indra/newview/llviewerwindow.h7
-rw-r--r--indra/newview/llvoiceclient.cpp8
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_limits.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml45
-rw-r--r--indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml38
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml1
29 files changed, 1612 insertions, 520 deletions
diff --git a/indra/cmake/DragDrop.cmake b/indra/cmake/DragDrop.cmake
new file mode 100644
index 0000000000..c0424396e5
--- /dev/null
+++ b/indra/cmake/DragDrop.cmake
@@ -0,0 +1,23 @@
+# -*- cmake -*-
+
+if (VIEWER)
+
+ set(OS_DRAG_DROP ON CACHE BOOL "Build the viewer with OS level drag and drop turned on or off")
+
+ if (OS_DRAG_DROP)
+
+ if (WINDOWS)
+ add_definitions(-DLL_OS_DRAGDROP_ENABLED=1)
+ endif (WINDOWS)
+
+ if (DARWIN)
+ add_definitions(-DLL_OS_DRAGDROP_ENABLED=1)
+ endif (DARWIN)
+
+ if (LINUX)
+ add_definitions(-DLL_OS_DRAGDROP_ENABLED=0)
+ endif (LINUX)
+
+ endif (OS_DRAG_DROP)
+
+endif (VIEWER)
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index a12b7793f7..259522a932 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -312,7 +312,6 @@ void LLTextBase::drawSelectionBackground()
// Draw selection even if we don't have keyboard focus for search/replace
if( hasSelection() && !mLineInfoList.empty())
{
- LLWString text = getWText();
std::vector<LLRect> selection_rects;
S32 selection_left = llmin( mSelectionStart, mSelectionEnd );
@@ -411,7 +410,7 @@ void LLTextBase::drawCursor()
&& gFocusMgr.getAppHasFocus()
&& !mReadOnly)
{
- LLWString wtext = getWText();
+ const LLWString &wtext = getWText();
const llwchar* text = wtext.c_str();
LLRect cursor_rect = getLocalRectFromDocIndex(mCursorPos);
@@ -497,7 +496,6 @@ void LLTextBase::drawCursor()
void LLTextBase::drawText()
{
- LLWString text = getWText();
const S32 text_len = getLength();
if( text_len <= 0 )
{
@@ -1116,7 +1114,6 @@ void LLTextBase::reflow(S32 start_index)
S32 line_start_index = 0;
const S32 text_available_width = mVisibleTextRect.getWidth() - mHPad; // reserve room for margin
S32 remaining_pixels = text_available_width;
- LLWString text(getWText());
S32 line_count = 0;
// find and erase line info structs starting at start_index and going to end of document
@@ -1759,7 +1756,7 @@ void LLTextBase::setWText(const LLWString& text)
setText(wstring_to_utf8str(text));
}
-LLWString LLTextBase::getWText() const
+const LLWString& LLTextBase::getWText() const
{
return getViewModel()->getDisplay();
}
@@ -2454,7 +2451,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
if (num_chars > 0)
{
height = mFontHeight;
- LLWString text = mEditor.getWText();
+ const LLWString &text = mEditor.getWText();
// if last character is a newline, then return true, forcing line break
llwchar last_char = text[mStart + first_char + num_chars - 1];
if (last_char == '\n')
@@ -2481,7 +2478,7 @@ bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& widt
S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const
{
- LLWString text = mEditor.getWText();
+ const LLWString &text = mEditor.getWText();
return mStyle->getFont()->charFromPixelOffset(text.c_str(), mStart + start_offset,
(F32)segment_local_x_coord,
F32_MAX,
@@ -2491,7 +2488,7 @@ S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset,
S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
{
- LLWString text = mEditor.getWText();
+ const LLWString &text = mEditor.getWText();
LLUIImagePtr image = mStyle->getImage();
if( image.notNull())
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 48d5478088..b5c7fab67a 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -145,7 +145,7 @@ public:
// wide-char versions
void setWText(const LLWString& text);
- LLWString getWText() const;
+ const LLWString& getWText() const;
void appendText(const std::string &new_text, bool prepend_newline, const LLStyle::Params& input_params = LLStyle::Params());
// force reflow of text
diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h
index c8a9b52cca..992365d44d 100644
--- a/indra/llui/llviewmodel.h
+++ b/indra/llui/llviewmodel.h
@@ -107,7 +107,8 @@ public:
// New functions
/// Get the stored value in string form
- LLWString getDisplay() const { return mDisplay; }
+ const LLWString& getDisplay() const { return mDisplay; }
+
/**
* Set the display string directly (see LLTextEditor). What the user is
* editing is actually the LLWString value rather than the underlying
diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt
index 7b1cab696f..77c6fa57b6 100644
--- a/indra/llwindow/CMakeLists.txt
+++ b/indra/llwindow/CMakeLists.txt
@@ -12,6 +12,7 @@ project(llwindow)
include(00-Common)
include(DirectX)
+include(DragDrop)
include(LLCommon)
include(LLImage)
include(LLMath)
@@ -102,11 +103,13 @@ if (WINDOWS)
llwindowwin32.cpp
lldxhardware.cpp
llkeyboardwin32.cpp
+ lldragdropwin32.cpp
)
list(APPEND llwindow_HEADER_FILES
llwindowwin32.h
lldxhardware.h
llkeyboardwin32.h
+ lldragdropwin32.h
)
list(APPEND llwindow_LINK_LIBRARIES
comdlg32 # Common Dialogs for ChooseColor
diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp
new file mode 100644
index 0000000000..9b80fe0a84
--- /dev/null
+++ b/indra/llwindow/lldragdropwin32.cpp
@@ -0,0 +1,370 @@
+/**
+ * @file lldragdrop32.cpp
+ * @brief Handler for Windows specific drag and drop (OS to client) code
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#if LL_WINDOWS
+
+#if LL_OS_DRAGDROP_ENABLED
+
+#include "linden_common.h"
+
+#include "llwindowwin32.h"
+#include "llkeyboardwin32.h"
+#include "llwindowcallbacks.h"
+#include "lldragdropwin32.h"
+
+class LLDragDropWin32Target:
+ public IDropTarget
+{
+ public:
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ LLDragDropWin32Target( HWND hWnd ) :
+ mRefCount( 1 ),
+ mAppWindowHandle( hWnd ),
+ mAllowDrop( false)
+ {
+ };
+
+ virtual ~LLDragDropWin32Target()
+ {
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ ULONG __stdcall AddRef( void )
+ {
+ return InterlockedIncrement( &mRefCount );
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ ULONG __stdcall Release( void )
+ {
+ LONG count = InterlockedDecrement( &mRefCount );
+
+ if ( count == 0 )
+ {
+ delete this;
+ return 0;
+ }
+ else
+ {
+ return count;
+ };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ HRESULT __stdcall QueryInterface( REFIID iid, void** ppvObject )
+ {
+ if ( iid == IID_IUnknown || iid == IID_IDropTarget )
+ {
+ AddRef();
+ *ppvObject = this;
+ return S_OK;
+ }
+ else
+ {
+ *ppvObject = 0;
+ return E_NOINTERFACE;
+ };
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ HRESULT __stdcall DragEnter( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
+ {
+ FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+
+ // support CF_TEXT using a HGLOBAL?
+ if ( S_OK == pDataObject->QueryGetData( &fmtetc ) )
+ {
+ mAllowDrop = true;
+ mDropUrl = std::string();
+ mIsSlurl = false;
+
+ STGMEDIUM stgmed;
+ if( S_OK == pDataObject->GetData( &fmtetc, &stgmed ) )
+ {
+ PVOID data = GlobalLock( stgmed.hGlobal );
+ mDropUrl = std::string( (char*)data );
+ // XXX MAJOR MAJOR HACK!
+ LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
+ if (NULL != window_imp)
+ {
+ LLCoordGL gl_coord( 0, 0 );
+
+ POINT pt2;
+ pt2.x = pt.x;
+ pt2.y = pt.y;
+ ScreenToClient( mAppWindowHandle, &pt2 );
+
+ LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
+ window_imp->convertCoords(cursor_coord_window, &gl_coord);
+ MASK mask = gKeyboard->currentMask(TRUE);
+
+ LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
+ LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl );
+
+ switch (result)
+ {
+ case LLWindowCallbacks::DND_COPY:
+ *pdwEffect = DROPEFFECT_COPY;
+ break;
+ case LLWindowCallbacks::DND_LINK:
+ *pdwEffect = DROPEFFECT_LINK;
+ break;
+ case LLWindowCallbacks::DND_MOVE:
+ *pdwEffect = DROPEFFECT_MOVE;
+ break;
+ case LLWindowCallbacks::DND_NONE:
+ default:
+ *pdwEffect = DROPEFFECT_NONE;
+ break;
+ }
+ };
+
+ GlobalUnlock( stgmed.hGlobal );
+ ReleaseStgMedium( &stgmed );
+ };
+ SetFocus( mAppWindowHandle );
+ }
+ else
+ {
+ mAllowDrop = false;
+ *pdwEffect = DROPEFFECT_NONE;
+ };
+
+ return S_OK;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ HRESULT __stdcall DragOver( DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
+ {
+ if ( mAllowDrop )
+ {
+ // XXX MAJOR MAJOR HACK!
+ LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
+ if (NULL != window_imp)
+ {
+ LLCoordGL gl_coord( 0, 0 );
+
+ POINT pt2;
+ pt2.x = pt.x;
+ pt2.y = pt.y;
+ ScreenToClient( mAppWindowHandle, &pt2 );
+
+ LLCoordWindow cursor_coord_window( pt2.x, pt2.y );
+ window_imp->convertCoords(cursor_coord_window, &gl_coord);
+ MASK mask = gKeyboard->currentMask(TRUE);
+
+ LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
+ LLWindowCallbacks::DNDA_TRACK, mDropUrl );
+
+ switch (result)
+ {
+ case LLWindowCallbacks::DND_COPY:
+ *pdwEffect = DROPEFFECT_COPY;
+ break;
+ case LLWindowCallbacks::DND_LINK:
+ *pdwEffect = DROPEFFECT_LINK;
+ break;
+ case LLWindowCallbacks::DND_MOVE:
+ *pdwEffect = DROPEFFECT_MOVE;
+ break;
+ case LLWindowCallbacks::DND_NONE:
+ default:
+ *pdwEffect = DROPEFFECT_NONE;
+ break;
+ }
+ };
+ }
+ else
+ {
+ *pdwEffect = DROPEFFECT_NONE;
+ };
+
+ return S_OK;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ HRESULT __stdcall DragLeave( void )
+ {
+ // XXX MAJOR MAJOR HACK!
+ LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA);
+ if (NULL != window_imp)
+ {
+ LLCoordGL gl_coord( 0, 0 );
+ MASK mask = gKeyboard->currentMask(TRUE);
+ window_imp->completeDragNDropRequest( gl_coord, mask, LLWindowCallbacks::DNDA_STOP_TRACKING, mDropUrl );
+ };
+ return S_OK;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ HRESULT __stdcall Drop( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
+ {
+ if ( mAllowDrop )
+ {
+ // window impl stored in Window data (neat!)
+ LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA );
+ if ( NULL != window_imp )
+ {
+ LLCoordGL gl_coord( 0, 0 );
+
+ POINT pt_client;
+ pt_client.x = pt.x;
+ pt_client.y = pt.y;
+ ScreenToClient( mAppWindowHandle, &pt_client );
+
+ LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y );
+ window_imp->convertCoords(cursor_coord_window, &gl_coord);
+ llinfos << "### (Drop) URL is: " << mDropUrl << llendl;
+ llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl;
+ llinfos << "### client coords are: " << pt_client.x << " x " << pt_client.y << llendl;
+ llinfos << "### GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl;
+ llinfos << llendl;
+
+ // no keyboard modifier option yet but we could one day
+ MASK mask = gKeyboard->currentMask( TRUE );
+
+ // actually do the drop
+ LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,
+ LLWindowCallbacks::DNDA_DROPPED, mDropUrl );
+
+ switch (result)
+ {
+ case LLWindowCallbacks::DND_COPY:
+ *pdwEffect = DROPEFFECT_COPY;
+ break;
+ case LLWindowCallbacks::DND_LINK:
+ *pdwEffect = DROPEFFECT_LINK;
+ break;
+ case LLWindowCallbacks::DND_MOVE:
+ *pdwEffect = DROPEFFECT_MOVE;
+ break;
+ case LLWindowCallbacks::DND_NONE:
+ default:
+ *pdwEffect = DROPEFFECT_NONE;
+ break;
+ }
+ };
+ }
+ else
+ {
+ *pdwEffect = DROPEFFECT_NONE;
+ };
+
+ return S_OK;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////
+ //
+ private:
+ LONG mRefCount;
+ HWND mAppWindowHandle;
+ bool mAllowDrop;
+ std::string mDropUrl;
+ bool mIsSlurl;
+ friend class LLWindowWin32;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLDragDropWin32::LLDragDropWin32() :
+ mDropTarget( NULL ),
+ mDropWindowHandle( NULL )
+
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+LLDragDropWin32::~LLDragDropWin32()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool LLDragDropWin32::init( HWND hWnd )
+{
+ if ( NOERROR != OleInitialize( NULL ) )
+ return FALSE;
+
+ mDropTarget = new LLDragDropWin32Target( hWnd );
+ if ( mDropTarget )
+ {
+ HRESULT result = CoLockObjectExternal( mDropTarget, TRUE, FALSE );
+ if ( S_OK == result )
+ {
+ result = RegisterDragDrop( hWnd, mDropTarget );
+ if ( S_OK != result )
+ {
+ // RegisterDragDrop failed
+ return false;
+ };
+
+ // all ok
+ mDropWindowHandle = hWnd;
+ }
+ else
+ {
+ // Unable to lock OLE object
+ return false;
+ };
+ };
+
+ // success
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLDragDropWin32::reset()
+{
+ if ( mDropTarget )
+ {
+ RevokeDragDrop( mDropWindowHandle );
+ CoLockObjectExternal( mDropTarget, FALSE, TRUE );
+ mDropTarget->Release();
+ };
+
+ OleUninitialize();
+}
+
+#endif // LL_OS_DRAGDROP_ENABLED
+
+#endif // LL_WINDOWS
+
diff --git a/indra/llwindow/lldragdropwin32.h b/indra/llwindow/lldragdropwin32.h
new file mode 100644
index 0000000000..9686626d7c
--- /dev/null
+++ b/indra/llwindow/lldragdropwin32.h
@@ -0,0 +1,80 @@
+/**
+ * @file lldragdrop32.cpp
+ * @brief Handler for Windows specific drag and drop (OS to client) code
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#if LL_WINDOWS
+
+#if LL_OS_DRAGDROP_ENABLED
+
+#ifndef LL_LLDRAGDROP32_H
+#define LL_LLDRAGDROP32_H
+
+#include <windows.h>
+#include <ole2.h>
+
+class LLDragDropWin32
+{
+ public:
+ LLDragDropWin32();
+ ~LLDragDropWin32();
+
+ bool init( HWND hWnd );
+ void reset();
+
+ private:
+ IDropTarget* mDropTarget;
+ HWND mDropWindowHandle;
+};
+#endif // LL_LLDRAGDROP32_H
+
+#else // LL_OS_DRAGDROP_ENABLED
+
+#ifndef LL_LLDRAGDROP32_H
+#define LL_LLDRAGDROP32_H
+
+#include <windows.h>
+#include <ole2.h>
+
+// imposter class that does nothing
+class LLDragDropWin32
+{
+ public:
+ LLDragDropWin32() {};
+ ~LLDragDropWin32() {};
+
+ bool init( HWND hWnd ) { return false; };
+ void reset() { };
+};
+#endif // LL_LLDRAGDROP32_H
+
+#endif // LL_OS_DRAGDROP_ENABLED
+
+#endif // LL_WINDOWS
diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp
index 72f9997149..6d9f012cc3 100644
--- a/indra/llwindow/llwindowcallbacks.cpp
+++ b/indra/llwindow/llwindowcallbacks.cpp
@@ -163,6 +163,11 @@ void LLWindowCallbacks::handleDataCopy(LLWindow *window, S32 data_type, void *da
{
}
+LLWindowCallbacks::DragNDropResult LLWindowCallbacks::handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, DragNDropAction action, std::string data )
+{
+ return LLWindowCallbacks::DND_NONE;
+}
+
BOOL LLWindowCallbacks::handleTimerEvent(LLWindow *window)
{
return FALSE;
diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h
index abc66c42a2..42add8dde0 100644
--- a/indra/llwindow/llwindowcallbacks.h
+++ b/indra/llwindow/llwindowcallbacks.h
@@ -71,6 +71,21 @@ public:
virtual BOOL handleTimerEvent(LLWindow *window);
virtual BOOL handleDeviceChange(LLWindow *window);
+ enum DragNDropAction {
+ DNDA_START_TRACKING = 0,// Start tracking an incoming drag
+ DNDA_TRACK, // User is dragging an incoming drag around the window
+ DNDA_STOP_TRACKING, // User is no longer dragging an incoming drag around the window (may have either cancelled or dropped on the window)
+ DNDA_DROPPED // User dropped an incoming drag on the window (this is the "commit" event)
+ };
+
+ enum DragNDropResult {
+ DND_NONE = 0, // No drop allowed
+ DND_MOVE, // Drop accepted would result in a "move" operation
+ DND_COPY, // Drop accepted would result in a "copy" operation
+ DND_LINK // Drop accepted would result in a "link" operation
+ };
+ virtual DragNDropResult handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, DragNDropAction action, std::string data);
+
virtual void handlePingWatchdog(LLWindow *window, const char * msg);
virtual void handlePauseWatchdog(LLWindow *window);
virtual void handleResumeWatchdog(LLWindow *window);
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index ed62faece6..9ccd4c7f97 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -278,6 +278,8 @@ LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks,
mMoveEventCampartorUPP = NewEventComparatorUPP(staticMoveEventComparator);
mGlobalHandlerRef = NULL;
mWindowHandlerRef = NULL;
+
+ mDragOverrideCursor = -1;
// We're not clipping yet
SetRect( &mOldMouseClip, 0, 0, 0, 0 );
@@ -499,8 +501,11 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
// Set up window event handlers (some window-related events ONLY go to window handlers.)
InstallStandardEventHandler(GetWindowEventTarget(mWindow));
- InstallWindowEventHandler (mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef); // add event handler
-
+ InstallWindowEventHandler(mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef); // add event handler
+#if LL_OS_DRAGDROP_ENABLED
+ InstallTrackingHandler( dragTrackingHandler, mWindow, (void*)this );
+ InstallReceiveHandler( dragReceiveHandler, mWindow, (void*)this );
+#endif // LL_OS_DRAGDROP_ENABLED
}
{
@@ -2174,11 +2179,8 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e
}
else
{
- MASK mask = 0;
- if(modifiers & shiftKey) { mask |= MASK_SHIFT; }
- if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; }
- if(modifiers & optionKey) { mask |= MASK_ALT; }
-
+ MASK mask = LLWindowMacOSX::modifiersToMask(modifiers);
+
llassert( actualType == typeUnicodeText );
// The result is a UTF16 buffer. Pass the characters in turn to handleUnicodeChar.
@@ -2795,6 +2797,14 @@ void LLWindowMacOSX::setCursor(ECursorType cursor)
{
OSStatus result = noErr;
+ if (mDragOverrideCursor != -1)
+ {
+ // A drag is in progress...remember the requested cursor and we'll
+ // restore it when it is done
+ mCurrentCursor = cursor;
+ return;
+ }
+
if (cursor == UI_CURSOR_ARROW
&& mBusyCount > 0)
{
@@ -3379,3 +3389,174 @@ std::vector<std::string> LLWindowMacOSX::getDynamicFallbackFontList()
return std::vector<std::string>();
}
+// static
+MASK LLWindowMacOSX::modifiersToMask(SInt16 modifiers)
+{
+ MASK mask = 0;
+ if(modifiers & shiftKey) { mask |= MASK_SHIFT; }
+ if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; }
+ if(modifiers & optionKey) { mask |= MASK_ALT; }
+ return mask;
+}
+
+#if LL_OS_DRAGDROP_ENABLED
+
+OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow,
+ void * handlerRefCon, DragRef drag)
+{
+ OSErr result = noErr;
+ LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon;
+
+ lldebugs << "drag tracking handler, message = " << message << llendl;
+
+ switch(message)
+ {
+ case kDragTrackingInWindow:
+ result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_TRACK);
+ break;
+
+ case kDragTrackingEnterHandler:
+ result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_START_TRACKING);
+ break;
+
+ case kDragTrackingLeaveHandler:
+ result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_STOP_TRACKING);
+ break;
+
+ default:
+ break;
+ }
+
+ return result;
+}
+
+OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefCon,
+ DragRef drag)
+{
+ LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon;
+ return self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_DROPPED);
+
+}
+
+OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDropAction action)
+{
+ OSErr result = dragNotAcceptedErr; // overall function result
+ OSErr err = noErr; // for local error handling
+
+ // Get the mouse position and modifiers of this drag.
+ SInt16 modifiers, mouseDownModifiers, mouseUpModifiers;
+ ::GetDragModifiers(drag, &modifiers, &mouseDownModifiers, &mouseUpModifiers);
+ MASK mask = LLWindowMacOSX::modifiersToMask(modifiers);
+
+ Point mouse_point;
+ // This will return the mouse point in global screen coords
+ ::GetDragMouse(drag, &mouse_point, NULL);
+ LLCoordScreen screen_coords(mouse_point.h, mouse_point.v);
+ LLCoordGL gl_pos;
+ convertCoords(screen_coords, &gl_pos);
+
+ // Look at the pasteboard and try to extract an URL from it
+ PasteboardRef pasteboard;
+ if(GetDragPasteboard(drag, &pasteboard) == noErr)
+ {
+ ItemCount num_items = 0;
+ // Treat an error here as an item count of 0
+ (void)PasteboardGetItemCount(pasteboard, &num_items);
+
+ // Only deal with single-item drags.
+ if(num_items == 1)
+ {
+ PasteboardItemID item_id = NULL;
+ CFArrayRef flavors = NULL;
+ CFDataRef data = NULL;
+
+ err = PasteboardGetItemIdentifier(pasteboard, 1, &item_id); // Yes, this really is 1-based.
+
+ // Try to extract an URL from the pasteboard
+ if(err == noErr)
+ {
+ err = PasteboardCopyItemFlavors( pasteboard, item_id, &flavors);
+ }
+
+ if(err == noErr)
+ {
+ if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeURL))
+ {
+ // This is an URL.
+ err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeURL, &data);
+ }
+ else if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeUTF8PlainText))
+ {
+ // This is a string that might be an URL.
+ err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeUTF8PlainText, &data);
+ }
+
+ }
+
+ if(flavors != NULL)
+ {
+ CFRelease(flavors);
+ }
+
+ if(data != NULL)
+ {
+ std::string url;
+ url.assign((char*)CFDataGetBytePtr(data), CFDataGetLength(data));
+ CFRelease(data);
+
+ if(!url.empty())
+ {
+ LLWindowCallbacks::DragNDropResult res =
+ mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url);
+
+ switch (res) {
+ case LLWindowCallbacks::DND_NONE: // No drop allowed
+ if (action == LLWindowCallbacks::DNDA_TRACK)
+ {
+ mDragOverrideCursor = kThemeNotAllowedCursor;
+ }
+ else {
+ mDragOverrideCursor = -1;
+ }
+ break;
+ case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation
+ mDragOverrideCursor = kThemePointingHandCursor;
+ result = noErr;
+ break;
+ case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation
+ mDragOverrideCursor = kThemeCopyArrowCursor;
+ result = noErr;
+ break;
+ case LLWindowCallbacks::DND_LINK: // Drop accepted would result in a "link" operation:
+ mDragOverrideCursor = kThemeAliasArrowCursor;
+ result = noErr;
+ break;
+ default:
+ mDragOverrideCursor = -1;
+ break;
+ }
+ // This overrides the cursor being set by setCursor.
+ // This is a bit of a hack workaround because lots of areas
+ // within the viewer just blindly set the cursor.
+ if (mDragOverrideCursor == -1)
+ {
+ // Restore the cursor
+ ECursorType temp_cursor = mCurrentCursor;
+ // get around the "setting the same cursor" code in setCursor()
+ mCurrentCursor = UI_CURSOR_COUNT;
+ setCursor(temp_cursor);
+ }
+ else {
+ // Override the cursor
+ SetThemeCursor(mDragOverrideCursor);
+ }
+
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+#endif // LL_OS_DRAGDROP_ENABLED
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index fbfa07fab4..377f10b6d4 100644
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -34,6 +34,7 @@
#define LL_LLWINDOWMACOSX_H
#include "llwindow.h"
+#include "llwindowcallbacks.h"
#include "lltimer.h"
@@ -159,8 +160,15 @@ protected:
void adjustCursorDecouple(bool warpingMouse = false);
void fixWindowSize(void);
void stopDockTileBounce();
-
-
+ static MASK modifiersToMask(SInt16 modifiers);
+
+#if LL_OS_DRAGDROP_ENABLED
+ static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow,
+ void * handlerRefCon, DragRef theDrag);
+ static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag);
+ OSErr handleDragNDrop(DragRef theDrag, LLWindowCallbacks::DragNDropAction action);
+#endif // LL_OS_DRAGDROP_ENABLED
+
//
// Platform specific variables
//
@@ -193,11 +201,13 @@ protected:
U32 mFSAASamples;
BOOL mForceRebuild;
+ S32 mDragOverrideCursor;
+
F32 mBounceTime;
NMRec mBounceRec;
LLTimer mBounceTimer;
- // Imput method management through Text Service Manager.
+ // Input method management through Text Service Manager.
TSMDocumentID mTSMDocument;
BOOL mLanguageTextInputAllowed;
ScriptCode mTSMScriptCode;
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index b591111b75..57a4921d92 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -38,6 +38,7 @@
// LLWindow library includes
#include "llkeyboardwin32.h"
+#include "lldragdropwin32.h"
#include "llpreeditor.h"
#include "llwindowcallbacks.h"
@@ -52,6 +53,7 @@
#include <mapi.h>
#include <process.h> // for _spawn
#include <shellapi.h>
+#include <fstream>
#include <Imm.h>
// Require DirectInput version 8
@@ -383,6 +385,9 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
gKeyboard = new LLKeyboardWin32();
gKeyboard->setCallbacks(callbacks);
+ // Initialize the Drag and Drop functionality
+ mDragDrop = new LLDragDropWin32;
+
// Initialize (boot strap) the Language text input management,
// based on the system's (user's) default settings.
allowLanguageTextInput(mPreeditor, FALSE);
@@ -620,6 +625,8 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
LLWindowWin32::~LLWindowWin32()
{
+ delete mDragDrop;
+
delete [] mWindowTitle;
mWindowTitle = NULL;
@@ -671,6 +678,8 @@ void LLWindowWin32::close()
return;
}
+ mDragDrop->reset();
+
// Make sure cursor is visible and we haven't mangled the clipping state.
setMouseClipping(FALSE);
showCursor();
@@ -1349,6 +1358,11 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
}
SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this);
+
+ // register this window as handling drag/drop events from the OS
+ DragAcceptFiles( mWindowHandle, TRUE );
+
+ mDragDrop->init( mWindowHandle );
//register joystick timer callback
SetTimer( mWindowHandle, 0, 1000 / 30, NULL ); // 30 fps timer
@@ -2354,11 +2368,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
return 0;
case WM_COPYDATA:
- window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COPYDATA");
- // received a URL
- PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param;
- window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData);
+ {
+ window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COPYDATA");
+ // received a URL
+ PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param;
+ window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData);
+ };
return 0;
+
+ break;
}
window_imp->mCallbacks->handlePauseWatchdog(window_imp);
@@ -3528,6 +3546,13 @@ static LLWString find_context(const LLWString & wtext, S32 focus, S32 focus_leng
return wtext.substr(start, end - start);
}
+// final stage of handling drop requests - both from WM_DROPFILES message
+// for files and via IDropTarget interface requests.
+LLWindowCallbacks::DragNDropResult LLWindowWin32::completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url )
+{
+ return mCallbacks->handleDragNDrop( this, gl_coord, mask, action, url );
+}
+
// Handle WM_IME_REQUEST message.
// If it handled the message, returns TRUE. Otherwise, FALSE.
// When it handled the message, the value to be returned from
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index e4e9179db7..6aca31b63e 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -39,6 +39,8 @@
#include <windows.h>
#include "llwindow.h"
+#include "llwindowcallbacks.h"
+#include "lldragdropwin32.h"
// Hack for async host by name
#define LL_WM_HOST_RESOLVED (WM_APP + 1)
@@ -114,6 +116,8 @@ public:
/*virtual*/ void interruptLanguageTextInput();
/*virtual*/ void spawnWebBrowser(const std::string& escaped_url);
+ LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url );
+
static std::vector<std::string> getDynamicFallbackFontList();
protected:
@@ -205,6 +209,8 @@ protected:
LLPreeditor *mPreeditor;
+ LLDragDropWin32* mDragDrop;
+
friend class LLWindowManager;
};
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 1c32c690a8..cd7c002096 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -7,6 +7,7 @@ include(Boost)
include(BuildVersion)
include(DBusGlib)
include(DirectX)
+include(DragDrop)
include(ELFIO)
include(FMOD)
include(OPENAL)
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 2a7c3b0f74..62197406b6 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -5527,6 +5527,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>PrimMediaDragNDrop</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable drag and drop of URLs onto prim faces</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>PrimMediaMaxRetries</key>
<map>
<key>Comment</key>
@@ -10820,6 +10831,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>SLURLDragNDrop</key>
+ <map>
+ <key>Comment</key>
+ <string>Enable drag and drop of SLURLs onto the viewer</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>soundsbeacon</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 0ad283d7c6..8cd63deebe 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -427,8 +427,26 @@ BOOL LLPanelLandGeneral::postBuild()
mBtnBuyLand = getChild<LLButton>("Buy Land...");
mBtnBuyLand->setClickedCallback(onClickBuyLand, (void*)&BUY_PERSONAL_LAND);
- mBtnScriptLimits = getChild<LLButton>("Scripts...");
- mBtnScriptLimits->setClickedCallback(onClickScriptLimits, this);
+ // note: on region change this will not be re checked, should not matter on Agni as
+ // 99% of the time all regions will return the same caps. In case of an erroneous setting
+ // to enabled the floater will just throw an error when trying to get it's cap
+ std::string url = gAgent.getRegion()->getCapability("LandResources");
+ if (!url.empty())
+ {
+ mBtnScriptLimits = getChild<LLButton>("Scripts...");
+ if(mBtnScriptLimits)
+ {
+ mBtnScriptLimits->setClickedCallback(onClickScriptLimits, this);
+ }
+ }
+ else
+ {
+ mBtnScriptLimits = getChild<LLButton>("Scripts...");
+ if(mBtnScriptLimits)
+ {
+ mBtnScriptLimits->setVisible(false);
+ }
+ }
mBtnBuyGroupLand = getChild<LLButton>("Buy For Group...");
mBtnBuyGroupLand->setClickedCallback(onClickBuyLand, (void*)&BUY_GROUP_LAND);
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
index 8875e35821..4194416a01 100644
--- a/indra/newview/llfloaterscriptlimits.cpp
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -59,10 +59,30 @@
/// LLFloaterScriptLimits
///----------------------------------------------------------------------------
-// due to server side bugs the full summary display is not possible
-// until they are fixed this define creates a simple version of the
-// summary which only shows available & correct information
-#define USE_SIMPLE_SUMMARY
+// debug switches, won't work in release
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+
+// dump responder replies to llinfos for debugging
+//#define DUMP_REPLIES_TO_LLINFOS
+
+#ifdef DUMP_REPLIES_TO_LLINFOS
+#include "llsdserialize.h"
+#include "llwindow.h"
+#endif
+
+// use fake LLSD responses to check the viewer side is working correctly
+// I'm syncing this with the server side efforts so hopfully we can keep
+// the to-ing and fro-ing between the two teams to a minimum
+//#define USE_FAKE_RESPONSES
+
+#ifdef USE_FAKE_RESPONSES
+const S32 FAKE_NUMBER_OF_URLS = 329;
+const S32 FAKE_AVAILABLE_URLS = 731;
+const S32 FAKE_AMOUNT_OF_MEMORY = 66741;
+const S32 FAKE_AVAILABLE_MEMORY = 895577;
+#endif
+
+#endif
const S32 SIZE_OF_ONE_KB = 1024;
@@ -87,32 +107,41 @@ BOOL LLFloaterScriptLimits::postBuild()
}
mTab = getChild<LLTabContainer>("scriptlimits_panels");
+
+ if(!mTab)
+ {
+ llinfos << "Error! couldn't get scriptlimits_panels, aborting Script Information setup" << llendl;
+ return FALSE;
+ }
// contruct the panels
- LLPanelScriptLimitsRegionMemory* panel_memory;
- panel_memory = new LLPanelScriptLimitsRegionMemory;
- mInfoPanels.push_back(panel_memory);
+ std::string land_url = gAgent.getRegion()->getCapability("LandResources");
+ if (!land_url.empty())
+ {
+ LLPanelScriptLimitsRegionMemory* panel_memory;
+ panel_memory = new LLPanelScriptLimitsRegionMemory;
+ mInfoPanels.push_back(panel_memory);
+ LLUICtrlFactory::getInstance()->buildPanel(panel_memory, "panel_script_limits_region_memory.xml");
+ mTab->addTabPanel(panel_memory);
+ }
- LLUICtrlFactory::getInstance()->buildPanel(panel_memory, "panel_script_limits_region_memory.xml");
- mTab->addTabPanel(panel_memory);
-
- LLPanelScriptLimitsRegionURLs* panel_urls = new LLPanelScriptLimitsRegionURLs;
- mInfoPanels.push_back(panel_urls);
- LLUICtrlFactory::getInstance()->buildPanel(panel_urls, "panel_script_limits_region_urls.xml");
- mTab->addTabPanel(panel_urls);
-
- LLPanelScriptLimitsAttachment* panel_attachments = new LLPanelScriptLimitsAttachment;
- mInfoPanels.push_back(panel_attachments);
- LLUICtrlFactory::getInstance()->buildPanel(panel_attachments, "panel_script_limits_my_avatar.xml");
- mTab->addTabPanel(panel_attachments);
-
- if(selectParcelPanel)
+ std::string attachment_url = gAgent.getRegion()->getCapability("AttachmentResources");
+ if (!attachment_url.empty())
+ {
+ LLPanelScriptLimitsAttachment* panel_attachments = new LLPanelScriptLimitsAttachment;
+ mInfoPanels.push_back(panel_attachments);
+ LLUICtrlFactory::getInstance()->buildPanel(panel_attachments, "panel_script_limits_my_avatar.xml");
+ mTab->addTabPanel(panel_attachments);
+ }
+
+ if(mInfoPanels.size() > 0)
{
mTab->selectTab(0);
}
- else
+
+ if(!selectParcelPanel && (mInfoPanels.size() > 1))
{
- mTab->selectTab(2);
+ mTab->selectTab(1);
}
return TRUE;
@@ -160,6 +189,20 @@ void LLPanelScriptLimitsInfo::updateChild(LLUICtrl* child_ctr)
void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content)
{
+ //we don't need to test with a fake respose here (shouldn't anyway)
+
+#ifdef DUMP_REPLIES_TO_LLINFOS
+
+ LLSDNotationStreamer notation_streamer(content);
+ std::ostringstream nice_llsd;
+ nice_llsd << notation_streamer;
+
+ OSMessageBox(nice_llsd.str(), "main cap response:", 0);
+
+ llinfos << "main cap response:" << content << llendl;
+
+#endif
+
// at this point we have an llsd which should contain ether one or two urls to the services we want.
// first we look for the details service:
if(content.has("ScriptResourceDetails"))
@@ -173,24 +216,6 @@ void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content)
{
llinfos << "Failed to get llfloaterscriptlimits instance" << llendl;
}
- else
- {
-
-// temp - only show info if we get details - there's nothing to show if not until the sim gets fixed
-#ifdef USE_SIMPLE_SUMMARY
-
- LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
- LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
- std::string msg = LLTrans::getString("ScriptLimitsRequestDontOwnParcel");
- panel_memory->childSetValue("loading_text", LLSD(msg));
- LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
- panel_urls->childSetValue("loading_text", LLSD(msg));
-
- // intentional early out as we dont want the resource summary if we are using the "simple summary"
- // and the details are missing
- return;
-#endif
- }
}
// then the summary service:
@@ -205,8 +230,61 @@ void fetchScriptLimitsRegionInfoResponder::error(U32 status, const std::string&
llinfos << "Error from responder " << reason << llendl;
}
-void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content)
+void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content_ref)
{
+#ifdef USE_FAKE_RESPONSES
+
+ LLSD fake_content;
+ LLSD summary = LLSD::emptyMap();
+ LLSD available = LLSD::emptyArray();
+ LLSD available_urls = LLSD::emptyMap();
+ LLSD available_memory = LLSD::emptyMap();
+ LLSD used = LLSD::emptyArray();
+ LLSD used_urls = LLSD::emptyMap();
+ LLSD used_memory = LLSD::emptyMap();
+
+ used_urls["type"] = "urls";
+ used_urls["amount"] = FAKE_NUMBER_OF_URLS;
+ available_urls["type"] = "urls";
+ available_urls["amount"] = FAKE_AVAILABLE_URLS;
+ used_memory["type"] = "memory";
+ used_memory["amount"] = FAKE_AMOUNT_OF_MEMORY;
+ available_memory["type"] = "memory";
+ available_memory["amount"] = FAKE_AVAILABLE_MEMORY;
+
+//summary response:{'summary':{'available':[{'amount':i731,'type':'urls'},{'amount':i895577,'type':'memory'},{'amount':i731,'type':'urls'},{'amount':i895577,'type':'memory'}],'used':[{'amount':i329,'type':'urls'},{'amount':i66741,'type':'memory'}]}}
+
+ used.append(used_urls);
+ used.append(used_memory);
+ available.append(available_urls);
+ available.append(available_memory);
+
+ summary["available"] = available;
+ summary["used"] = used;
+
+ fake_content["summary"] = summary;
+
+ const LLSD& content = fake_content;
+
+#else
+
+ const LLSD& content = content_ref;
+
+#endif
+
+
+#ifdef DUMP_REPLIES_TO_LLINFOS
+
+ LLSDNotationStreamer notation_streamer(content);
+ std::ostringstream nice_llsd;
+ nice_llsd << notation_streamer;
+
+ OSMessageBox(nice_llsd.str(), "summary response:", 0);
+
+ llinfos << "summary response:" << *content << llendl;
+
+#endif
+
LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
if(!instance)
{
@@ -217,8 +295,6 @@ void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content)
LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
panel_memory->setRegionSummary(content);
- LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
- panel_urls->setRegionSummary(content);
}
}
@@ -227,8 +303,82 @@ void fetchScriptLimitsRegionSummaryResponder::error(U32 status, const std::strin
llinfos << "Error from responder " << reason << llendl;
}
-void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content)
+void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content_ref)
{
+#ifdef USE_FAKE_RESPONSES
+/*
+Updated detail service, ** denotes field added:
+
+result (map)
++-parcels (array of maps)
+ +-id (uuid)
+ +-local_id (S32)**
+ +-name (string)
+ +-owner_id (uuid) (in ERS as owner, but owner_id in code)
+ +-objects (array of maps)
+ +-id (uuid)
+ +-name (string)
+ +-owner_id (uuid) (in ERS as owner, in code as owner_id)
+ +-owner_name (sting)**
+ +-location (map)**
+ +-x (float)
+ +-y (float)
+ +-z (float)
+ +-resources (map) (this is wrong in the ERS but right in code)
+ +-type (string)
+ +-amount (int)
+*/
+ LLSD fake_content;
+ LLSD resource = LLSD::emptyMap();
+ LLSD location = LLSD::emptyMap();
+ LLSD object = LLSD::emptyMap();
+ LLSD objects = LLSD::emptyArray();
+ LLSD parcel = LLSD::emptyMap();
+ LLSD parcels = LLSD::emptyArray();
+
+ resource["urls"] = FAKE_NUMBER_OF_URLS;
+ resource["memory"] = FAKE_AMOUNT_OF_MEMORY;
+
+ location["x"] = 128.0f;
+ location["y"] = 128.0f;
+ location["z"] = 0.0f;
+
+ object["id"] = LLUUID("d574a375-0c6c-fe3d-5733-da669465afc7");
+ object["name"] = "Gabs fake Object!";
+ object["owner_id"] = LLUUID("8dbf2d41-69a0-4e5e-9787-0c9d297bc570");
+ object["owner_name"] = "Gabs Linden";
+ object["location"] = location;
+ object["resources"] = resource;
+
+ objects.append(object);
+
+ parcel["id"] = LLUUID("da05fb28-0d20-e593-2728-bddb42dd0160");
+ parcel["local_id"] = 42;
+ parcel["name"] = "Gabriel Linden\'s Sub Plot";
+ parcel["objects"] = objects;
+ parcels.append(parcel);
+
+ fake_content["parcels"] = parcels;
+ const LLSD& content = fake_content;
+
+#else
+
+ const LLSD& content = content_ref;
+
+#endif
+
+#ifdef DUMP_REPLIES_TO_LLINFOS
+
+ LLSDNotationStreamer notation_streamer(content);
+ std::ostringstream nice_llsd;
+ nice_llsd << notation_streamer;
+
+ OSMessageBox(nice_llsd.str(), "details response:", 0);
+
+ llinfos << "details response:" << content << llendl;
+
+#endif
+
LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
if(!instance)
@@ -238,11 +388,22 @@ void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content)
else
{
LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
- LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
- panel_memory->setRegionDetails(content);
-
- LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
- panel_urls->setRegionDetails(content);
+ if(tab)
+ {
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ if(panel_memory)
+ {
+ panel_memory->setRegionDetails(content);
+ }
+ else
+ {
+ llinfos << "Failed to get scriptlimits memory panel" << llendl;
+ }
+ }
+ else
+ {
+ llinfos << "Failed to get scriptlimits_panels" << llendl;
+ }
}
}
@@ -251,8 +412,61 @@ void fetchScriptLimitsRegionDetailsResponder::error(U32 status, const std::strin
llinfos << "Error from responder " << reason << llendl;
}
-void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content)
+void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content_ref)
{
+
+#ifdef USE_FAKE_RESPONSES
+
+ // just add the summary, as that's all I'm testing currently!
+ LLSD fake_content = LLSD::emptyMap();
+ LLSD summary = LLSD::emptyMap();
+ LLSD available = LLSD::emptyArray();
+ LLSD available_urls = LLSD::emptyMap();
+ LLSD available_memory = LLSD::emptyMap();
+ LLSD used = LLSD::emptyArray();
+ LLSD used_urls = LLSD::emptyMap();
+ LLSD used_memory = LLSD::emptyMap();
+
+ used_urls["type"] = "urls";
+ used_urls["amount"] = FAKE_NUMBER_OF_URLS;
+ available_urls["type"] = "urls";
+ available_urls["amount"] = FAKE_AVAILABLE_URLS;
+ used_memory["type"] = "memory";
+ used_memory["amount"] = FAKE_AMOUNT_OF_MEMORY;
+ available_memory["type"] = "memory";
+ available_memory["amount"] = FAKE_AVAILABLE_MEMORY;
+
+ used.append(used_urls);
+ used.append(used_memory);
+ available.append(available_urls);
+ available.append(available_memory);
+
+ summary["available"] = available;
+ summary["used"] = used;
+
+ fake_content["summary"] = summary;
+ fake_content["attachments"] = content_ref["attachments"];
+
+ const LLSD& content = fake_content;
+
+#else
+
+ const LLSD& content = content_ref;
+
+#endif
+
+#ifdef DUMP_REPLIES_TO_LLINFOS
+
+ LLSDNotationStreamer notation_streamer(content);
+ std::ostringstream nice_llsd;
+ nice_llsd << notation_streamer;
+
+ OSMessageBox(nice_llsd.str(), "attachment response:", 0);
+
+ llinfos << "attachment response:" << content << llendl;
+
+#endif
+
LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
if(!instance)
@@ -262,8 +476,22 @@ void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content)
else
{
LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
- LLPanelScriptLimitsAttachment* panel = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel");
- panel->setAttachmentDetails(content);
+ if(tab)
+ {
+ LLPanelScriptLimitsAttachment* panel = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel");
+ if(panel)
+ {
+ panel->setAttachmentDetails(content);
+ }
+ else
+ {
+ llinfos << "Failed to get script_limits_my_avatar_panel" << llendl;
+ }
+ }
+ else
+ {
+ llinfos << "Failed to get scriptlimits_panels" << llendl;
+ }
}
}
@@ -309,7 +537,7 @@ void LLPanelScriptLimitsRegionMemory::processParcelInfo(const LLParcelData& parc
{
std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
childSetValue("loading_text", LLSD(msg_waiting));
- }
+ }
}
void LLPanelScriptLimitsRegionMemory::setParcelID(const LLUUID& parcel_id)
@@ -341,6 +569,11 @@ void LLPanelScriptLimitsRegionMemory::onNameCache(
std::string name = first_name + " " + last_name;
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
+ if(!list)
+ {
+ return;
+ }
+
std::vector<LLSD>::iterator id_itor;
for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor)
{
@@ -351,33 +584,8 @@ void LLPanelScriptLimitsRegionMemory::onNameCache(
if(item)
{
- item->getColumn(2)->setValue(LLSD(name));
- element["columns"][2]["value"] = name;
- }
- }
- }
-
- // fill in the url's tab if needed, all urls must have memory so we can do it all here
- LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
- if(instance)
- {
- LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
- LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
-
- LLScrollListCtrl *list = panel->getChild<LLScrollListCtrl>("scripts_list");
- std::vector<LLSD>::iterator id_itor;
- for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor)
- {
- LLSD element = *id_itor;
- if(element["owner_id"].asUUID() == id)
- {
- LLScrollListItem* item = list->getItem(element["id"].asUUID());
-
- if(item)
- {
- item->getColumn(2)->setValue(LLSD(name));
- element["columns"][2]["value"] = name;
- }
+ item->getColumn(3)->setValue(LLSD(name));
+ element["columns"][3]["value"] = name;
}
}
}
@@ -386,6 +594,12 @@ void LLPanelScriptLimitsRegionMemory::onNameCache(
void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
{
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
+
+ if(!list)
+ {
+ llinfos << "Error getting the scripts_list control" << llendl;
+ return;
+ }
S32 number_parcels = content["parcels"].size();
@@ -394,130 +608,197 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
std::string msg_parcels = LLTrans::getString("ScriptLimitsParcelsOwned", args_parcels);
childSetValue("parcels_listed", LLSD(msg_parcels));
- S32 total_objects = 0;
- S32 total_size = 0;
-
std::vector<LLUUID> names_requested;
+ // This makes the assumption that all objects will have the same set
+ // of attributes, ie they will all have, or none will have locations
+ // This is a pretty safe assumption as it's reliant on server version.
+ bool has_locations = false;
+ bool has_local_ids = false;
+
for(S32 i = 0; i < number_parcels; i++)
{
std::string parcel_name = content["parcels"][i]["name"].asString();
LLUUID parcel_id = content["parcels"][i]["id"].asUUID();
S32 number_objects = content["parcels"][i]["objects"].size();
+
+ S32 local_id = 0;
+ if(content["parcels"][i].has("local_id"))
+ {
+ // if any locations are found flag that we can use them and turn on the highlight button
+ has_local_ids = true;
+ local_id = content["parcels"][i]["local_id"].asInteger();
+ }
+
for(S32 j = 0; j < number_objects; j++)
{
S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / SIZE_OF_ONE_KB;
- total_size += size;
+
+ S32 urls = content["parcels"][i]["objects"][j]["resources"]["urls"].asInteger();
std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString();
LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID();
LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID();
-
+
+ F32 location_x = 0.0f;
+ F32 location_y = 0.0f;
+ F32 location_z = 0.0f;
+
+ if(content["parcels"][i]["objects"][j].has("location"))
+ {
+ // if any locations are found flag that we can use them and turn on the highlight button
+ LLVector3 vec = ll_vector3_from_sd(content["parcels"][i]["objects"][j]["location"]);
+ has_locations = true;
+ location_x = vec.mV[0];
+ location_y = vec.mV[1];
+ location_z = vec.mV[2];
+ }
+
std::string owner_buf;
-
- BOOL name_is_cached = gCacheName->getFullName(owner_id, owner_buf);
- if(!name_is_cached)
+
+ // in the future the server will give us owner names, so see if we're there yet:
+ if(content["parcels"][i]["objects"][j].has("owner_name"))
+ {
+ owner_buf = content["parcels"][i]["objects"][j]["owner_name"].asString();
+ }
+ // ...and if not use the slightly more painful method of disovery:
+ else
{
- if(std::find(names_requested.begin(), names_requested.end(), owner_id) == names_requested.end())
+ BOOL name_is_cached = gCacheName->getFullName(owner_id, owner_buf);
+ if(!name_is_cached)
{
- names_requested.push_back(owner_id);
- gCacheName->get(owner_id, TRUE,
- boost::bind(&LLPanelScriptLimitsRegionMemory::onNameCache,
- this, _1, _2, _3));
+ if(std::find(names_requested.begin(), names_requested.end(), owner_id) == names_requested.end())
+ {
+ names_requested.push_back(owner_id);
+ gCacheName->get(owner_id, TRUE,
+ boost::bind(&LLPanelScriptLimitsRegionMemory::onNameCache,
+ this, _1, _2, _3));
+ }
}
}
LLSD element;
element["id"] = task_id;
- element["owner_id"] = owner_id;
element["columns"][0]["column"] = "size";
element["columns"][0]["value"] = llformat("%d", size);
element["columns"][0]["font"] = "SANSSERIF";
- element["columns"][1]["column"] = "name";
- element["columns"][1]["value"] = name_buf;
+ element["columns"][1]["column"] = "urls";
+ element["columns"][1]["value"] = llformat("%d", urls);
element["columns"][1]["font"] = "SANSSERIF";
- element["columns"][2]["column"] = "owner";
- element["columns"][2]["value"] = owner_buf;
+ element["columns"][2]["column"] = "name";
+ element["columns"][2]["value"] = name_buf;
element["columns"][2]["font"] = "SANSSERIF";
- element["columns"][3]["column"] = "location";
- element["columns"][3]["value"] = parcel_name;
+ element["columns"][3]["column"] = "owner";
+ element["columns"][3]["value"] = owner_buf;
element["columns"][3]["font"] = "SANSSERIF";
+ element["columns"][4]["column"] = "parcel";
+ element["columns"][4]["value"] = parcel_name;
+ element["columns"][4]["font"] = "SANSSERIF";
+ element["columns"][5]["column"] = "location";
+ if(has_locations)
+ {
+ element["columns"][5]["value"] = llformat("<%0.1f,%0.1f,%0.1f>", location_x, location_y, location_z);
+ }
+ else
+ {
+ element["columns"][5]["value"] = "";
+ }
+ element["columns"][5]["font"] = "SANSSERIF";
list->addElement(element, ADD_SORTED);
+
+ element["owner_id"] = owner_id;
+ element["local_id"] = local_id;
mObjectListItems.push_back(element);
- total_objects++;
}
}
- mParcelMemoryUsed =total_size;
- mGotParcelMemoryUsed = TRUE;
- populateParcelMemoryText();
-}
+ if (has_locations)
+ {
+ LLButton* btn = getChild<LLButton>("highlight_btn");
+ if(btn)
+ {
+ btn->setVisible(true);
+ }
+ }
-void LLPanelScriptLimitsRegionMemory::populateParcelMemoryText()
-{
- if(mGotParcelMemoryUsed && mGotParcelMemoryMax)
+ if (has_local_ids)
{
-#ifdef USE_SIMPLE_SUMMARY
- LLStringUtil::format_map_t args_parcel_memory;
- args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed);
- std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsedSimple", args_parcel_memory);
- childSetValue("memory_used", LLSD(msg_parcel_memory));
-#else
- S32 parcel_memory_available = mParcelMemoryMax - mParcelMemoryUsed;
+ LLButton* btn = getChild<LLButton>("return_btn");
+ if(btn)
+ {
+ btn->setVisible(true);
+ }
+ }
- LLStringUtil::format_map_t args_parcel_memory;
- args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed);
- args_parcel_memory["[MAX]"] = llformat ("%d", mParcelMemoryMax);
- args_parcel_memory["[AVAILABLE]"] = llformat ("%d", parcel_memory_available);
- std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsed", args_parcel_memory);
- childSetValue("memory_used", LLSD(msg_parcel_memory));
-#endif
+ // save the structure to make object return easier
+ mContent = content;
- childSetValue("loading_text", LLSD(std::string("")));
- }
+ childSetValue("loading_text", LLSD(std::string("")));
}
void LLPanelScriptLimitsRegionMemory::setRegionSummary(LLSD content)
{
- if(content["summary"]["available"][0]["type"].asString() == std::string("memory"))
+ if(content["summary"]["used"][0]["type"].asString() == std::string("memory"))
{
- mParcelMemoryMax = content["summary"]["available"][0]["amount"].asInteger();
- mGotParcelMemoryMax = TRUE;
+ mParcelMemoryUsed = content["summary"]["used"][0]["amount"].asInteger() / SIZE_OF_ONE_KB;
+ mParcelMemoryMax = content["summary"]["available"][0]["amount"].asInteger() / SIZE_OF_ONE_KB;
+ mGotParcelMemoryUsed = TRUE;
}
- else if(content["summary"]["available"][1]["type"].asString() == std::string("memory"))
+ else if(content["summary"]["used"][1]["type"].asString() == std::string("memory"))
{
- mParcelMemoryMax = content["summary"]["available"][1]["amount"].asInteger();
- mGotParcelMemoryMax = TRUE;
+ mParcelMemoryUsed = content["summary"]["used"][1]["amount"].asInteger() / SIZE_OF_ONE_KB;
+ mParcelMemoryMax = content["summary"]["available"][1]["amount"].asInteger() / SIZE_OF_ONE_KB;
+ mGotParcelMemoryUsed = TRUE;
}
else
{
llinfos << "summary doesn't contain memory info" << llendl;
return;
}
-/*
- currently this is broken on the server, so we get this value from the details section
- and update via populateParcelMemoryText() when both sets of information have been returned
-
- when the sim is fixed this should be used instead:
- if(content["summary"]["used"][0]["type"].asString() == std::string("memory"))
+
+ if(content["summary"]["used"][0]["type"].asString() == std::string("urls"))
{
- mParcelMemoryUsed = content["summary"]["used"][0]["amount"].asInteger();
- mGotParcelMemoryUsed = TRUE;
+ mParcelURLsUsed = content["summary"]["used"][0]["amount"].asInteger();
+ mParcelURLsMax = content["summary"]["available"][0]["amount"].asInteger();
+ mGotParcelURLsUsed = TRUE;
}
- else if(content["summary"]["used"][1]["type"].asString() == std::string("memory"))
+ else if(content["summary"]["used"][1]["type"].asString() == std::string("urls"))
{
- mParcelMemoryUsed = content["summary"]["used"][1]["amount"].asInteger();
- mGotParcelMemoryUsed = TRUE;
+ mParcelURLsUsed = content["summary"]["used"][1]["amount"].asInteger();
+ mParcelURLsMax = content["summary"]["available"][1]["amount"].asInteger();
+ mGotParcelURLsUsed = TRUE;
}
else
{
- //ERROR!!!
+ llinfos << "summary doesn't contain urls info" << llendl;
return;
- }*/
+ }
- populateParcelMemoryText();
+ if((mParcelMemoryUsed >= 0) && (mParcelMemoryMax >= 0))
+ {
+ S32 parcel_memory_available = mParcelMemoryMax - mParcelMemoryUsed;
+
+ LLStringUtil::format_map_t args_parcel_memory;
+ args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed);
+ args_parcel_memory["[MAX]"] = llformat ("%d", mParcelMemoryMax);
+ args_parcel_memory["[AVAILABLE]"] = llformat ("%d", parcel_memory_available);
+ std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsed", args_parcel_memory);
+ childSetValue("memory_used", LLSD(msg_parcel_memory));
+ }
+
+ if((mParcelURLsUsed >= 0) && (mParcelURLsMax >= 0))
+ {
+ S32 parcel_urls_available = mParcelURLsMax - mParcelURLsUsed;
+
+ LLStringUtil::format_map_t args_parcel_urls;
+ args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed);
+ args_parcel_urls["[MAX]"] = llformat ("%d", mParcelURLsMax);
+ args_parcel_urls["[AVAILABLE]"] = llformat ("%d", parcel_urls_available);
+ std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsed", args_parcel_urls);
+ childSetValue("urls_used", LLSD(msg_parcel_urls));
+ }
}
BOOL LLPanelScriptLimitsRegionMemory::postBuild()
@@ -530,6 +811,10 @@ BOOL LLPanelScriptLimitsRegionMemory::postBuild()
childSetValue("loading_text", LLSD(msg_waiting));
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
+ if(!list)
+ {
+ return FALSE;
+ }
//set all columns to resizable mode even if some columns will be empty
for(S32 column = 0; column < list->getNumColumns(); column++)
@@ -548,18 +833,11 @@ BOOL LLPanelScriptLimitsRegionMemory::StartRequestChain()
LLFloaterLand* instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land");
if(!instance)
{
- //this isnt really an error...
-// llinfos << "Failed to get about land instance" << llendl;
-// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
childSetValue("loading_text", LLSD(std::string("")));
//might have to do parent post build here
//if not logic below could use early outs
return FALSE;
}
-
- LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
- LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
-
LLParcel* parcel = instance->getCurrentSelectedParcel();
LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
@@ -575,7 +853,6 @@ BOOL LLPanelScriptLimitsRegionMemory::StartRequestChain()
{
std::string msg_wrong_region = LLTrans::getString("ScriptLimitsRequestWrongRegion");
childSetValue("loading_text", LLSD(msg_wrong_region));
- panel_urls->childSetValue("loading_text", LLSD(msg_wrong_region));
return FALSE;
}
@@ -605,14 +882,12 @@ BOOL LLPanelScriptLimitsRegionMemory::StartRequestChain()
std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
childSetValue("loading_text", LLSD(msg_waiting));
- panel_urls->childSetValue("loading_text", LLSD(msg_waiting));
}
}
else
{
- std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestNoParcelSelected");
childSetValue("loading_text", LLSD(msg_waiting));
- panel_urls->childSetValue("loading_text", LLSD(msg_waiting));
}
return LLPanelScriptLimitsInfo::postBuild();
@@ -629,10 +904,13 @@ void LLPanelScriptLimitsRegionMemory::clearList()
mGotParcelMemoryUsed = FALSE;
mGotParcelMemoryMax = FALSE;
+ mGotParcelURLsUsed = FALSE;
+ mGotParcelURLsMax = FALSE;
LLStringUtil::format_map_t args_parcel_memory;
std::string msg_empty_string("");
childSetValue("memory_used", LLSD(msg_empty_string));
+ childSetValue("urls_used", LLSD(msg_empty_string));
childSetValue("parcels_listed", LLSD(msg_empty_string));
mObjectListItems.clear();
@@ -647,13 +925,16 @@ void LLPanelScriptLimitsRegionMemory::onClickRefresh(void* userdata)
if(instance)
{
LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
- LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
- panel_memory->clearList();
-
- LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
- panel_urls->clearList();
+ if(tab)
+ {
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ if(panel_memory)
+ {
+ panel_memory->clearList();
- panel_memory->StartRequestChain();
+ panel_memory->StartRequestChain();
+ }
+ }
return;
}
else
@@ -665,78 +946,80 @@ void LLPanelScriptLimitsRegionMemory::onClickRefresh(void* userdata)
void LLPanelScriptLimitsRegionMemory::showBeacon()
{
-/* LLScrollListCtrl* list = getChild<LLScrollListCtrl>("scripts_list");
+ LLScrollListCtrl* list = getChild<LLScrollListCtrl>("scripts_list");
if (!list) return;
LLScrollListItem* first_selected = list->getFirstSelected();
if (!first_selected) return;
- std::string name = first_selected->getColumn(1)->getValue().asString();
- std::string pos_string = first_selected->getColumn(3)->getValue().asString();
+ std::string name = first_selected->getColumn(2)->getValue().asString();
+ std::string pos_string = first_selected->getColumn(5)->getValue().asString();
- llinfos << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" <<llendl;
- llinfos << "name = " << name << " pos = " << pos_string << llendl;
-
F32 x, y, z;
S32 matched = sscanf(pos_string.c_str(), "<%g,%g,%g>", &x, &y, &z);
if (matched != 3) return;
LLVector3 pos_agent(x, y, z);
LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
- llinfos << "name = " << name << " pos = " << pos_string << llendl;
+
std::string tooltip("");
- LLTracker::trackLocation(pos_global, name, tooltip, LLTracker::LOCATION_ITEM);*/
+ LLTracker::trackLocation(pos_global, name, tooltip, LLTracker::LOCATION_ITEM);
}
// static
void LLPanelScriptLimitsRegionMemory::onClickHighlight(void* userdata)
{
-/* llinfos << "LLPanelRegionGeneralInfo::onClickHighlight" << llendl;
+ llinfos << "LLPanelRegionGeneralInfo::onClickHighlight" << llendl;
LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
if(instance)
{
LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
- LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
- panel->showBeacon();
+ if(tab)
+ {
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ if(panel)
+ {
+ panel->showBeacon();
+ }
+ }
return;
}
else
{
llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
-// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
-// panel->childSetValue("loading_text", LLSD(msg_waiting));
return;
- }*/
+ }
}
-void LLPanelScriptLimitsRegionMemory::returnObjects()
+void LLPanelScriptLimitsRegionMemory::returnObjectsFromParcel(S32 local_id)
{
-/* llinfos << "started" << llendl;
LLMessageSystem *msg = gMessageSystem;
LLViewerRegion* region = gAgent.getRegion();
if (!region) return;
- llinfos << "got region" << llendl;
LLCtrlListInterface *list = childGetListInterface("scripts_list");
if (!list || list->getItemCount() == 0) return;
- llinfos << "got list" << llendl;
- std::vector<LLUUID>::iterator id_itor;
+ std::vector<LLSD>::iterator id_itor;
bool start_message = true;
- for (id_itor = mObjectListIDs.begin(); id_itor != mObjectListIDs.end(); ++id_itor)
+ for (id_itor = mObjectListItems.begin(); id_itor != mObjectListItems.end(); ++id_itor)
{
- LLUUID task_id = *id_itor;
- llinfos << task_id << llendl;
- if (!list->isSelected(task_id))
+ LLSD element = *id_itor;
+ if (!list->isSelected(element["id"].asUUID()))
{
- llinfos << "not selected" << llendl;
// Selected only
continue;
}
- llinfos << "selected" << llendl;
+
+ if(element["local_id"].asInteger() != local_id)
+ {
+ // Not the parcel we are looking for
+ continue;
+ }
+
if (start_message)
{
msg->newMessageFast(_PREHASH_ParcelReturnObjects);
@@ -744,285 +1027,74 @@ void LLPanelScriptLimitsRegionMemory::returnObjects()
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_ParcelData);
- msg->addS32Fast(_PREHASH_LocalID, -1); // Whole region
- msg->addS32Fast(_PREHASH_ReturnType, RT_LIST);
+ msg->addS32Fast(_PREHASH_LocalID, element["local_id"].asInteger());
+ msg->addU32Fast(_PREHASH_ReturnType, RT_LIST);
start_message = false;
- llinfos << "start message" << llendl;
}
msg->nextBlockFast(_PREHASH_TaskIDs);
- msg->addUUIDFast(_PREHASH_TaskID, task_id);
- llinfos << "added id" << llendl;
+ msg->addUUIDFast(_PREHASH_TaskID, element["id"].asUUID());
if (msg->isSendFullFast(_PREHASH_TaskIDs))
{
msg->sendReliable(region->getHost());
start_message = true;
- llinfos << "sent 1" << llendl;
}
}
if (!start_message)
{
msg->sendReliable(region->getHost());
- llinfos << "sent 2" << llendl;
- }*/
+ }
}
-// static
-void LLPanelScriptLimitsRegionMemory::onClickReturn(void* userdata)
+void LLPanelScriptLimitsRegionMemory::returnObjects()
{
-/* llinfos << "LLPanelRegionGeneralInfo::onClickReturn" << llendl;
- LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
- if(instance)
+ if(!mContent.has("parcels"))
{
- LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
- LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
- panel->returnObjects();
return;
}
- else
- {
- llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
-// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
-// panel->childSetValue("loading_text", LLSD(msg_waiting));
- return;
- }*/
-}
-
-///----------------------------------------------------------------------------
-// URLs Panel
-///----------------------------------------------------------------------------
-
-void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content)
-{
- LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
-
- S32 number_parcels = content["parcels"].size();
-
- LLStringUtil::format_map_t args_parcels;
- args_parcels["[PARCELS]"] = llformat ("%d", number_parcels);
- std::string msg_parcels = LLTrans::getString("ScriptLimitsParcelsOwned", args_parcels);
- childSetValue("parcels_listed", LLSD(msg_parcels));
-
- S32 total_objects = 0;
- S32 total_size = 0;
+ S32 number_parcels = mContent["parcels"].size();
+
+ // a message per parcel containing all objects to be returned from that parcel
for(S32 i = 0; i < number_parcels; i++)
{
- std::string parcel_name = content["parcels"][i]["name"].asString();
- llinfos << parcel_name << llendl;
-
- S32 number_objects = content["parcels"][i]["objects"].size();
- for(S32 j = 0; j < number_objects; j++)
+ S32 local_id = 0;
+ if(mContent["parcels"][i].has("local_id"))
{
- if(content["parcels"][i]["objects"][j]["resources"].has("urls"))
- {
- S32 size = content["parcels"][i]["objects"][j]["resources"]["urls"].asInteger();
- total_size += size;
-
- std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString();
- LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID();
- LLUUID owner_id = content["parcels"][i]["objects"][j]["owner_id"].asUUID();
-
- std::string owner_buf;
- gCacheName->getFullName(owner_id, owner_buf); //dont care if this fails as the memory tab will request and fill the field
-
- LLSD element;
-
- element["id"] = task_id;
- element["columns"][0]["column"] = "urls";
- element["columns"][0]["value"] = llformat("%d", size);
- element["columns"][0]["font"] = "SANSSERIF";
- element["columns"][1]["column"] = "name";
- element["columns"][1]["value"] = name_buf;
- element["columns"][1]["font"] = "SANSSERIF";
- element["columns"][2]["column"] = "owner";
- element["columns"][2]["value"] = owner_buf;
- element["columns"][2]["font"] = "SANSSERIF";
- element["columns"][3]["column"] = "location";
- element["columns"][3]["value"] = parcel_name;
- element["columns"][3]["font"] = "SANSSERIF";
-
- list->addElement(element);
- mObjectListItems.push_back(element);
- total_objects++;
- }
+ local_id = mContent["parcels"][i]["local_id"].asInteger();
+ returnObjectsFromParcel(local_id);
}
}
-
- mParcelURLsUsed =total_size;
- mGotParcelURLsUsed = TRUE;
- populateParcelURLsText();
-}
-
-void LLPanelScriptLimitsRegionURLs::populateParcelURLsText()
-{
- if(mGotParcelURLsUsed && mGotParcelURLsMax)
- {
-
-#ifdef USE_SIMPLE_SUMMARY
- LLStringUtil::format_map_t args_parcel_urls;
- args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed);
- std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsedSimple", args_parcel_urls);
- childSetValue("urls_used", LLSD(msg_parcel_urls));
-#else
- S32 parcel_urls_available = mParcelURLsMax - mParcelURLsUsed;
- LLStringUtil::format_map_t args_parcel_urls;
- args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed);
- args_parcel_urls["[MAX]"] = llformat ("%d", mParcelURLsMax);
- args_parcel_urls["[AVAILABLE]"] = llformat ("%d", parcel_urls_available);
- std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsed", args_parcel_urls);
- childSetValue("urls_used", LLSD(msg_parcel_urls));
-#endif
-
- childSetValue("loading_text", LLSD(std::string("")));
-
- }
+ onClickRefresh(NULL);
}
-void LLPanelScriptLimitsRegionURLs::setRegionSummary(LLSD content)
-{
- if(content["summary"]["available"][0]["type"].asString() == std::string("urls"))
- {
- mParcelURLsMax = content["summary"]["available"][0]["amount"].asInteger();
- mGotParcelURLsMax = TRUE;
- }
- else if(content["summary"]["available"][1]["type"].asString() == std::string("urls"))
- {
- mParcelURLsMax = content["summary"]["available"][1]["amount"].asInteger();
- mGotParcelURLsMax = TRUE;
- }
- else
- {
- llinfos << "summary contains no url info" << llendl;
- return;
- }
-/*
- currently this is broken on the server, so we get this value from the details section
- and update via populateParcelMemoryText() when both sets of information have been returned
-
- when the sim is fixed this should be used instead:
- if(content["summary"]["used"][0]["type"].asString() == std::string("urls"))
- {
- mParcelURLsUsed = content["summary"]["used"][0]["amount"].asInteger();
- mGotParcelURLsUsed = TRUE;
- }
- else if(content["summary"]["used"][1]["type"].asString() == std::string("urls"))
- {
- mParcelURLsUsed = content["summary"]["used"][1]["amount"].asInteger();
- mGotParcelURLsUsed = TRUE;
- }
- else
- {
- //ERROR!!!
- return;
- }*/
-
- populateParcelURLsText();
-}
-
-BOOL LLPanelScriptLimitsRegionURLs::postBuild()
-{
- childSetAction("refresh_list_btn", onClickRefresh, this);
- childSetAction("highlight_btn", onClickHighlight, this);
- childSetAction("return_btn", onClickReturn, this);
-
- std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
- childSetValue("loading_text", LLSD(msg_waiting));
- return FALSE;
-}
-
-void LLPanelScriptLimitsRegionURLs::clearList()
-{
- LLCtrlListInterface *list = childGetListInterface("scripts_list");
-
- if (list)
- {
- list->operateOnAll(LLCtrlListInterface::OP_DELETE);
- }
-
- mGotParcelURLsUsed = FALSE;
- mGotParcelURLsMax = FALSE;
-
- LLStringUtil::format_map_t args_parcel_urls;
- std::string msg_empty_string("");
- childSetValue("urls_used", LLSD(msg_empty_string));
- childSetValue("parcels_listed", LLSD(msg_empty_string));
-
- mObjectListItems.clear();
-}
-
-// static
-void LLPanelScriptLimitsRegionURLs::onClickRefresh(void* userdata)
-{
- llinfos << "Refresh clicked" << llendl;
-
- LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
- if(instance)
- {
- LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
- LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
- // use the memory panel to re-request all the info
- panel_memory->clearList();
-
- LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
- // but the urls panel to clear itself
- panel_urls->clearList();
-
- panel_memory->StartRequestChain();
- return;
- }
- else
- {
- llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl;
- return;
- }
-}
// static
-void LLPanelScriptLimitsRegionURLs::onClickHighlight(void* userdata)
+void LLPanelScriptLimitsRegionMemory::onClickReturn(void* userdata)
{
-/* llinfos << "Highlight clicked" << llendl;
+ llinfos << "LLPanelRegionGeneralInfo::onClickReturn" << llendl;
LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
if(instance)
{
LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
- LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
- // use the beacon function from the memory panel
- panel->showBeacon();
+ if(tab)
+ {
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ if(panel)
+ {
+ panel->returnObjects();
+ }
+ }
return;
}
else
{
llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
-// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
-// panel->childSetValue("loading_text", LLSD(msg_waiting));
- return;
- }*/
-}
-
-// static
-void LLPanelScriptLimitsRegionURLs::onClickReturn(void* userdata)
-{
-/* llinfos << "Return clicked" << llendl;
- LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
- if(instance)
- {
- LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
- LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
- // use the return function from the memory panel
- panel->returnObjects();
return;
}
- else
- {
- llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
-// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
-// panel->childSetValue("loading_text", LLSD(msg_waiting));
- return;
- }*/
}
///----------------------------------------------------------------------------
@@ -1047,6 +1119,12 @@ BOOL LLPanelScriptLimitsAttachment::requestAttachmentDetails()
void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content)
{
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
+
+ if(!list)
+ {
+ return;
+ }
+
S32 number_attachments = content["attachments"].size();
for(int i = 0; i < number_attachments; i++)
@@ -1096,6 +1174,8 @@ void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content)
list->addElement(element);
}
}
+
+ setAttachmentSummary(content);
childSetValue("loading_text", LLSD(std::string("")));
}
@@ -1122,6 +1202,69 @@ void LLPanelScriptLimitsAttachment::clearList()
childSetValue("loading_text", LLSD(msg_waiting));
}
+void LLPanelScriptLimitsAttachment::setAttachmentSummary(LLSD content)
+{
+ if(content["summary"]["used"][0]["type"].asString() == std::string("memory"))
+ {
+ mAttachmentMemoryUsed = content["summary"]["used"][0]["amount"].asInteger() / SIZE_OF_ONE_KB;
+ mAttachmentMemoryMax = content["summary"]["available"][0]["amount"].asInteger() / SIZE_OF_ONE_KB;
+ mGotAttachmentMemoryUsed = TRUE;
+ }
+ else if(content["summary"]["used"][1]["type"].asString() == std::string("memory"))
+ {
+ mAttachmentMemoryUsed = content["summary"]["used"][1]["amount"].asInteger() / SIZE_OF_ONE_KB;
+ mAttachmentMemoryMax = content["summary"]["available"][1]["amount"].asInteger() / SIZE_OF_ONE_KB;
+ mGotAttachmentMemoryUsed = TRUE;
+ }
+ else
+ {
+ llinfos << "attachment details don't contain memory summary info" << llendl;
+ return;
+ }
+
+ if(content["summary"]["used"][0]["type"].asString() == std::string("urls"))
+ {
+ mAttachmentURLsUsed = content["summary"]["used"][0]["amount"].asInteger();
+ mAttachmentURLsMax = content["summary"]["available"][0]["amount"].asInteger();
+ mGotAttachmentURLsUsed = TRUE;
+ }
+ else if(content["summary"]["used"][1]["type"].asString() == std::string("urls"))
+ {
+ mAttachmentURLsUsed = content["summary"]["used"][1]["amount"].asInteger();
+ mAttachmentURLsMax = content["summary"]["available"][1]["amount"].asInteger();
+ mGotAttachmentURLsUsed = TRUE;
+ }
+ else
+ {
+ llinfos << "attachment details don't contain urls summary info" << llendl;
+ return;
+ }
+
+ if((mAttachmentMemoryUsed >= 0) && (mAttachmentMemoryMax >= 0))
+ {
+ S32 attachment_memory_available = mAttachmentMemoryMax - mAttachmentMemoryUsed;
+
+ LLStringUtil::format_map_t args_attachment_memory;
+ args_attachment_memory["[COUNT]"] = llformat ("%d", mAttachmentMemoryUsed);
+ args_attachment_memory["[MAX]"] = llformat ("%d", mAttachmentMemoryMax);
+ args_attachment_memory["[AVAILABLE]"] = llformat ("%d", attachment_memory_available);
+ std::string msg_attachment_memory = LLTrans::getString("ScriptLimitsMemoryUsed", args_attachment_memory);
+ childSetValue("memory_used", LLSD(msg_attachment_memory));
+ }
+
+ if((mAttachmentURLsUsed >= 0) && (mAttachmentURLsMax >= 0))
+ {
+ S32 attachment_urls_available = mAttachmentURLsMax - mAttachmentURLsUsed;
+
+ LLStringUtil::format_map_t args_attachment_urls;
+ args_attachment_urls["[COUNT]"] = llformat ("%d", mAttachmentURLsUsed);
+ args_attachment_urls["[MAX]"] = llformat ("%d", mAttachmentURLsMax);
+ args_attachment_urls["[AVAILABLE]"] = llformat ("%d", attachment_urls_available);
+ std::string msg_attachment_urls = LLTrans::getString("ScriptLimitsURLsUsed", args_attachment_urls);
+ childSetValue("urls_used", LLSD(msg_attachment_urls));
+ }
+}
+
// static
void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata)
{
diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h
index e675d14515..4c1ecc1019 100644
--- a/indra/newview/llfloaterscriptlimits.h
+++ b/indra/newview/llfloaterscriptlimits.h
@@ -166,10 +166,10 @@ public:
BOOL StartRequestChain();
- void populateParcelMemoryText();
BOOL getLandScriptResources();
void clearList();
void showBeacon();
+ void returnObjectsFromParcel(S32 local_id);
void returnObjects();
private:
@@ -178,69 +178,30 @@ private:
const std::string& first_name,
const std::string& last_name);
+ LLSD mContent;
LLUUID mParcelId;
BOOL mGotParcelMemoryUsed;
+ BOOL mGotParcelMemoryUsedDetails;
BOOL mGotParcelMemoryMax;
S32 mParcelMemoryMax;
S32 mParcelMemoryUsed;
+ S32 mParcelMemoryUsedDetails;
- std::vector<LLSD> mObjectListItems;
-
-protected:
-
-// LLRemoteParcelInfoObserver interface:
-/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
-/*virtual*/ void setParcelID(const LLUUID& parcel_id);
-/*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
-
- static void onClickRefresh(void* userdata);
- static void onClickHighlight(void* userdata);
- static void onClickReturn(void* userdata);
-};
-
-/////////////////////////////////////////////////////////////////////////////
-// URLs panel
-/////////////////////////////////////////////////////////////////////////////
-
-class LLPanelScriptLimitsRegionURLs : public LLPanelScriptLimitsInfo
-{
-
-public:
- LLPanelScriptLimitsRegionURLs()
- : LLPanelScriptLimitsInfo(),
-
- mParcelId(LLUUID()),
- mGotParcelURLsUsed(FALSE),
- mGotParcelURLsMax(FALSE),
- mParcelURLsMax(0),
- mParcelURLsUsed(0)
- {
- };
-
- ~LLPanelScriptLimitsRegionURLs()
- {
- };
-
- // LLPanel
- virtual BOOL postBuild();
-
- void setRegionDetails(LLSD content);
- void setRegionSummary(LLSD content);
-
- void populateParcelURLsText();
- void clearList();
-
-private:
-
- LLUUID mParcelId;
BOOL mGotParcelURLsUsed;
+ BOOL mGotParcelURLsUsedDetails;
BOOL mGotParcelURLsMax;
S32 mParcelURLsMax;
S32 mParcelURLsUsed;
+ S32 mParcelURLsUsedDetails;
std::vector<LLSD> mObjectListItems;
protected:
+
+// LLRemoteParcelInfoObserver interface:
+/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
+/*virtual*/ void setParcelID(const LLUUID& parcel_id);
+/*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
static void onClickRefresh(void* userdata);
static void onClickHighlight(void* userdata);
@@ -266,11 +227,26 @@ public:
void setAttachmentDetails(LLSD content);
+ void setAttachmentSummary(LLSD content);
BOOL requestAttachmentDetails();
void clearList();
private:
+ BOOL mGotAttachmentMemoryUsed;
+ BOOL mGotAttachmentMemoryUsedDetails;
+ BOOL mGotAttachmentMemoryMax;
+ S32 mAttachmentMemoryMax;
+ S32 mAttachmentMemoryUsed;
+ S32 mAttachmentMemoryUsedDetails;
+
+ BOOL mGotAttachmentURLsUsed;
+ BOOL mGotAttachmentURLsUsedDetails;
+ BOOL mGotAttachmentURLsMax;
+ S32 mAttachmentURLsMax;
+ S32 mAttachmentURLsUsed;
+ S32 mAttachmentURLsUsedDetails;
+
protected:
static void onClickRefresh(void* userdata);
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 87d101b00f..af9e791223 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -689,6 +689,23 @@ void LLPanelLogin::refreshLocation( bool force_visible )
}
// static
+void LLPanelLogin::updateLocationUI()
+{
+ if (!sInstance) return;
+
+ std::string sim_string = LLURLSimString::sInstance.mSimString;
+ if (!sim_string.empty())
+ {
+ // Replace "<Type region name>" with this region name
+ LLComboBox* combo = sInstance->getChild<LLComboBox>("start_location_combo");
+ combo->remove(2);
+ combo->add( sim_string );
+ combo->setTextEntry(sim_string);
+ combo->setCurrentByIndex( 2 );
+ }
+}
+
+// static
void LLPanelLogin::closePanel()
{
if (sInstance)
diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h
index 97350ce5c7..1fdc3a9361 100644
--- a/indra/newview/llpanellogin.h
+++ b/indra/newview/llpanellogin.h
@@ -71,6 +71,7 @@ public:
static void addServer(const std::string& server, S32 domain_name);
static void refreshLocation( bool force_visible );
+ static void updateLocationUI();
static void getFields(std::string *firstname, std::string *lastname,
std::string *password);
@@ -102,7 +103,7 @@ private:
static void onPassKey(LLLineEditor* caller, void* user_data);
static void onSelectServer(LLUICtrl*, void*);
static void onServerComboLostFocus(LLFocusableElement*);
-
+
private:
LLPointer<LLUIImage> mLogoImage;
boost::scoped_ptr<LLPanelLoginListener> mListener;
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index fccf71f3cb..7bcbe334ff 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -1904,7 +1904,7 @@ void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url,
const LLUUID& item_id,
BOOL is_running)
{
- llinfos << "Update Task Inventory via capability" << llendl;
+ llinfos << "Update Task Inventory via capability " << url << llendl;
LLSD body;
body["task_id"] = task_id;
body["item_id"] = item_id;
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 9240833632..b0952dd698 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -870,8 +870,7 @@ void open_inventory_offer(const std::vector<LLUUID>& items, const std::string& f
////////////////////////////////////////////////////////////////////////////////
// Don't highlight if it's in certain "quiet" folders which don't need UI
// notification (e.g. trash, cof, lost-and-found).
- const BOOL user_is_away = gAwayTimer.getStarted();
- if(!user_is_away)
+ if(!gAgent.getAFK())
{
const LLViewerInventoryCategory *parent = gInventory.getFirstNondefaultParent(item_id);
if (parent)
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index cd6b9e2c50..fdc6675db1 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -51,6 +51,7 @@
#include "llviewquery.h"
#include "llxmltree.h"
+#include "llslurl.h"
//#include "llviewercamera.h"
#include "llrender.h"
@@ -80,6 +81,9 @@
#include "timing.h"
#include "llviewermenu.h"
#include "lltooltip.h"
+#include "llmediaentry.h"
+#include "llurldispatcher.h"
+#include "llurlsimstring.h"
// newview includes
#include "llagent.h"
@@ -795,6 +799,137 @@ BOOL LLViewerWindow::handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MAS
// Always handled as far as the OS is concerned.
return TRUE;
}
+
+LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data)
+{
+ LLWindowCallbacks::DragNDropResult result = LLWindowCallbacks::DND_NONE;
+
+ const bool prim_media_dnd_enabled = gSavedSettings.getBOOL("PrimMediaDragNDrop");
+ const bool slurl_dnd_enabled = gSavedSettings.getBOOL("SLURLDragNDrop");
+
+ if ( prim_media_dnd_enabled || slurl_dnd_enabled )
+ {
+ switch(action)
+ {
+ // Much of the handling for these two cases is the same.
+ case LLWindowCallbacks::DNDA_TRACK:
+ case LLWindowCallbacks::DNDA_DROPPED:
+ case LLWindowCallbacks::DNDA_START_TRACKING:
+ {
+ bool drop = (LLWindowCallbacks::DNDA_DROPPED == action);
+
+ if (slurl_dnd_enabled)
+ {
+ // special case SLURLs
+ if ( LLSLURL::isSLURL( data ) )
+ {
+ if (drop)
+ {
+ LLURLDispatcher::dispatch( data, NULL, true );
+ LLURLSimString::setStringRaw( LLSLURL::stripProtocol( data ) );
+ LLPanelLogin::refreshLocation( true );
+ LLPanelLogin::updateLocationUI();
+ }
+ return LLWindowCallbacks::DND_MOVE;
+ };
+ }
+
+ if (prim_media_dnd_enabled)
+ {
+ LLPickInfo pick_info = pickImmediate( pos.mX, pos.mY, TRUE /*BOOL pick_transparent*/ );
+
+ LLUUID object_id = pick_info.getObjectID();
+ S32 object_face = pick_info.mObjectFace;
+ std::string url = data;
+
+ lldebugs << "Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << llendl;
+
+ LLVOVolume *obj = dynamic_cast<LLVOVolume*>(static_cast<LLViewerObject*>(pick_info.getObject()));
+
+ if (obj && obj->permModify() && !obj->getRegion()->getCapability("ObjectMedia").empty())
+ {
+ LLTextureEntry *te = obj->getTE(object_face);
+ if (te)
+ {
+ if (drop)
+ {
+ if (! te->hasMedia())
+ {
+ // Create new media entry
+ LLSD media_data;
+ // XXX Should we really do Home URL too?
+ media_data[LLMediaEntry::HOME_URL_KEY] = url;
+ media_data[LLMediaEntry::CURRENT_URL_KEY] = url;
+ media_data[LLMediaEntry::AUTO_PLAY_KEY] = true;
+ obj->syncMediaData(object_face, media_data, true, true);
+ // XXX This shouldn't be necessary, should it ?!?
+ if (obj->getMediaImpl(object_face))
+ obj->getMediaImpl(object_face)->navigateReload();
+ obj->sendMediaDataUpdate();
+
+ result = LLWindowCallbacks::DND_COPY;
+ }
+ else {
+ // Check the whitelist
+ if (te->getMediaData()->checkCandidateUrl(url))
+ {
+ // just navigate to the URL
+ if (obj->getMediaImpl(object_face))
+ {
+ obj->getMediaImpl(object_face)->navigateTo(url);
+ }
+ else {
+ // This is very strange. Navigation should
+ // happen via the Impl, but we don't have one.
+ // This sends it to the server, which /should/
+ // trigger us getting it. Hopefully.
+ LLSD media_data;
+ media_data[LLMediaEntry::CURRENT_URL_KEY] = url;
+ obj->syncMediaData(object_face, media_data, true, true);
+ obj->sendMediaDataUpdate();
+ }
+ result = LLWindowCallbacks::DND_LINK;
+ }
+ }
+ LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
+ mDragHoveredObject = NULL;
+
+ }
+ else {
+ // Check the whitelist, if there's media (otherwise just show it)
+ if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url))
+ {
+ if ( obj != mDragHoveredObject)
+ {
+ // Highlight the dragged object
+ LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
+ mDragHoveredObject = obj;
+ LLSelectMgr::getInstance()->highlightObjectOnly(mDragHoveredObject);
+ }
+ result = (! te->hasMedia()) ? LLWindowCallbacks::DND_COPY : LLWindowCallbacks::DND_LINK;
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case LLWindowCallbacks::DNDA_STOP_TRACKING:
+ // The cleanup case below will make sure things are unhilighted if necessary.
+ break;
+ }
+
+ if (prim_media_dnd_enabled &&
+ result == LLWindowCallbacks::DND_NONE && !mDragHoveredObject.isNull())
+ {
+ LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
+ mDragHoveredObject = NULL;
+ }
+ }
+
+ return result;
+}
BOOL LLViewerWindow::handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask)
{
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index c0a9180b53..98d2958d9a 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -166,7 +166,8 @@ public:
/*virtual*/ BOOL handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ BOOL handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask);
- /*virtual*/ void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask);
+ /*virtual*/ LLWindowCallbacks::DragNDropResult handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, LLWindowCallbacks::DragNDropAction action, std::string data);
+ void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask);
/*virtual*/ void handleMouseLeave(LLWindow *window);
/*virtual*/ void handleResize(LLWindow *window, S32 x, S32 y);
/*virtual*/ void handleFocus(LLWindow *window);
@@ -472,6 +473,10 @@ protected:
static std::string sSnapshotDir;
static std::string sMovieBaseName;
+
+private:
+ // Object temporarily hovered over while dragging
+ LLPointer<LLViewerObject> mDragHoveredObject;
};
void toggle_flying(void*);
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index c062dd1732..3914064d72 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -1258,7 +1258,6 @@ LLVoiceClient::LLVoiceClient() :
mEarLocation(0),
mSpeakerVolumeDirty(true),
mSpeakerMuteDirty(true),
- mSpeakerVolume(0),
mMicVolume(0),
mMicVolumeDirty(true),
@@ -1271,6 +1270,8 @@ LLVoiceClient::LLVoiceClient() :
mAPIVersion = LLTrans::getString("NotConnected");
+ mSpeakerVolume = scale_speaker_volume(0);
+
#if LL_DARWIN || LL_LINUX || LL_SOLARIS
// HACK: THIS DOES NOT BELONG HERE
// When the vivox daemon dies, the next write attempt on our socket generates a SIGPIPE, which kills us.
@@ -3525,7 +3526,7 @@ void LLVoiceClient::buildLocalAudioUpdates(std::ostringstream &stream)
if(mSpeakerMuteDirty)
{
- const char *muteval = ((mSpeakerVolume == 0)?"true":"false");
+ const char *muteval = ((mSpeakerVolume <= scale_speaker_volume(0))?"true":"false");
mSpeakerMuteDirty = false;
@@ -6062,7 +6063,8 @@ void LLVoiceClient::setVoiceVolume(F32 volume)
if(scaled_volume != mSpeakerVolume)
{
- if((scaled_volume == 0) || (mSpeakerVolume == 0))
+ int min_volume = scale_speaker_volume(0);
+ if((scaled_volume == min_volume) || (mSpeakerVolume == min_volume))
{
mSpeakerMuteDirty = true;
}
diff --git a/indra/newview/skins/default/xui/en/floater_script_limits.xml b/indra/newview/skins/default/xui/en/floater_script_limits.xml
index 98c44ad1b3..6b36cdfcc5 100644
--- a/indra/newview/skins/default/xui/en/floater_script_limits.xml
+++ b/indra/newview/skins/default/xui/en/floater_script_limits.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
legacy_header_height="18"
+ can_resize="true"
height="570"
help_topic="scriptlimits"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml b/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml
index d98f690339..629d8567d1 100644
--- a/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml
+++ b/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml
@@ -9,7 +9,44 @@
name="script_limits_my_avatar_panel"
top="0"
width="480">
- <text
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="script_memory"
+ top_pad="24"
+ text_color="White"
+ width="480">
+ Avatar Script Usage
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="30"
+ name="memory_used"
+ top_delta="18"
+ width="480">
+
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="30"
+ name="urls_used"
+ top_delta="18"
+ width="480">
+
+ </text>
+ <text
type="string"
length="1"
follows="left|top"
@@ -17,7 +54,7 @@
layout="topleft"
left="10"
name="loading_text"
- top="10"
+ top="80"
text_color="EmphasisColor"
width="480">
Loading...
@@ -25,12 +62,12 @@
<scroll_list
draw_heading="true"
follows="all"
- height="500"
+ height="415"
layout="topleft"
left_delta="0"
multi_select="true"
name="scripts_list"
- top_delta="17"
+ top="100"
width="460">
<scroll_list.columns
label="Size (kb)"
diff --git a/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml
index 0fa3c1cf2e..9dff00fa0b 100644
--- a/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml
+++ b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml
@@ -33,7 +33,7 @@
top_delta="18"
visible="true"
width="480">
- Parcels Owned:
+
</text>
<text
type="string"
@@ -45,7 +45,19 @@
name="memory_used"
top_delta="18"
width="480">
- Memory used:
+ </text>
+
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="30"
+ name="urls_used"
+ top_delta="18"
+ width="480">
+
</text>
<text
type="string"
@@ -55,7 +67,7 @@
layout="topleft"
left="10"
name="loading_text"
- top_delta="32"
+ top_delta="12"
text_color="EmphasisColor"
width="480">
Loading...
@@ -73,7 +85,11 @@
<scroll_list.columns
label="Size (kb)"
name="size"
- width="70" />
+ width="72" />
+ <scroll_list.columns
+ label="URLs"
+ name="urls"
+ width="48" />
<scroll_list.columns
label="Object Name"
name="name"
@@ -83,11 +99,13 @@
name="owner"
width="100" />
<scroll_list.columns
- label="Parcel / Location"
- name="location"
+ label="Parcel"
+ name="parcel"
width="130" />
-<!-- <scroll_list.commit_callback
- function="TopObjects.CommitObjectsList" />-->
+ <scroll_list.columns
+ label="Location"
+ name="location"
+ width="80" />
</scroll_list>
<button
follows="bottom|left"
@@ -102,8 +120,8 @@
<button
follows="bottom|right"
height="19"
- visible="false"
label="Highlight"
+ visible="false"
layout="bottomright"
left="370"
name="highlight_btn"
@@ -112,8 +130,8 @@
<button
follows="bottom|right"
height="19"
- visible="false"
label="Return"
+ visible="false"
layout="bottomright"
name="return_btn"
top="34"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index b378944e48..b4a12cfb32 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2051,6 +2051,7 @@ this texture in your inventory
<string name="ScriptLimitsURLsUsed">URLs used: [COUNT] out of [MAX]; [AVAILABLE] available</string>
<string name="ScriptLimitsURLsUsedSimple">URLs used: [COUNT]</string>
<string name="ScriptLimitsRequestError">Error requesting information</string>
+ <string name="ScriptLimitsRequestNoParcelSelected">No Parcel Selected</string>
<string name="ScriptLimitsRequestWrongRegion">Error: script information is only available in your current region</string>
<string name="ScriptLimitsRequestWaiting">Retrieving information...</string>
<string name="ScriptLimitsRequestDontOwnParcel">You do not have permission to examine this parcel</string>