summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/llclipboard.cpp148
-rw-r--r--indra/llui/llclipboard.h72
-rw-r--r--indra/llui/lllineeditor.cpp19
-rw-r--r--indra/llui/llscrolllistctrl.cpp2
-rw-r--r--indra/llui/lltexteditor.cpp20
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/llfavoritesbar.cpp12
-rw-r--r--indra/newview/llfloatergesture.cpp21
-rw-r--r--indra/newview/llfolderview.cpp44
-rw-r--r--indra/newview/llfolderview.h1
-rw-r--r--indra/newview/llfoldervieweventlistener.h2
-rw-r--r--indra/newview/llfolderviewitem.cpp32
-rw-r--r--indra/newview/llinventorybridge.cpp187
-rw-r--r--indra/newview/llinventorybridge.h6
-rw-r--r--indra/newview/llinventoryclipboard.cpp110
-rw-r--r--indra/newview/llinventoryclipboard.h86
-rw-r--r--indra/newview/llinventoryfilter.cpp37
-rw-r--r--indra/newview/llinventoryfilter.h1
-rw-r--r--indra/newview/llinventoryfunctions.cpp69
-rw-r--r--indra/newview/llinventoryfunctions.h4
-rw-r--r--indra/newview/llinventorypanel.cpp12
-rw-r--r--indra/newview/llinventorypanel.h1
-rw-r--r--indra/newview/llpanellandmarks.cpp5
-rw-r--r--indra/newview/llpanelobjectinventory.cpp5
-rw-r--r--indra/newview/llpanelteleporthistory.cpp2
-rw-r--r--indra/newview/llpaneltopinfobar.cpp2
-rw-r--r--indra/newview/llpanelwearing.cpp2
-rw-r--r--indra/newview/lltoolbarview.cpp14
-rw-r--r--indra/newview/lltoolbarview.h3
-rw-r--r--indra/newview/lltooldraganddrop.cpp3
-rw-r--r--indra/newview/llurllineeditorctrl.cpp2
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory.xml8
32 files changed, 515 insertions, 419 deletions
diff --git a/indra/llui/llclipboard.cpp b/indra/llui/llclipboard.cpp
index 6910b962a1..e0729366cc 100644
--- a/indra/llui/llclipboard.cpp
+++ b/indra/llui/llclipboard.cpp
@@ -34,109 +34,133 @@
#include "llview.h"
#include "llwindow.h"
-// Global singleton
-LLClipboard gClipboard;
-
-
-LLClipboard::LLClipboard()
+LLClipboard::LLClipboard() :
+ mState(0)
{
- mSourceItem = NULL;
+ reset();
}
-
LLClipboard::~LLClipboard()
{
+ reset();
}
-
-void LLClipboard::copyFromSubstring(const LLWString &src, S32 pos, S32 len, const LLUUID& source_id )
+void LLClipboard::reset()
{
- mSourceID = source_id;
- mString = src.substr(pos, len);
- LLView::getWindow()->copyTextToClipboard( mString );
+ // Increment the clipboard state
+ mState++;
+ // Call the cleanup function (if any) before releasing the object list
+ if (mCutMode && mCleanupCallback)
+ {
+ mCleanupCallback();
+ }
+ // Clear the clipboard
+ mObjects.reset();
+ mCutMode = false;
+ mCleanupCallback = NULL;
+ mString = LLWString();
}
-void LLClipboard::copyFromString(const LLWString &src, const LLUUID& source_id )
+// Copy the input uuid to the LL clipboard
+bool LLClipboard::copyToClipboard(const LLUUID& src, const LLAssetType::EType type)
{
- mSourceID = source_id;
- mString = src;
- LLView::getWindow()->copyTextToClipboard( mString );
+ reset();
+ return addToClipboard(src, type);
}
-const LLWString& LLClipboard::getPasteWString( LLUUID* source_id )
+// Add the input uuid to the LL clipboard
+// Convert the uuid to string and concatenate that string to the system clipboard if legit
+bool LLClipboard::addToClipboard(const LLUUID& src, const LLAssetType::EType type)
{
- if( mSourceID.notNull() )
+ bool res = false;
+ if (src.notNull())
{
- LLWString temp_string;
- LLView::getWindow()->pasteTextFromClipboard(temp_string);
-
- if( temp_string != mString )
+ res = true;
+ if (LLAssetType::lookupIsAssetIDKnowable(type))
{
- mSourceID.setNull();
- mString = temp_string;
+ LLWString source = utf8str_to_wstring(src.asString());
+ res = addToClipboard(source, 0, source.size());
+ }
+ if (res)
+ {
+ mObjects.put(src);
+ mState++;
}
}
- else
- {
- LLView::getWindow()->pasteTextFromClipboard(mString);
- }
+ return res;
+}
- if( source_id )
+bool LLClipboard::pasteFromClipboard(LLDynamicArray<LLUUID>& inv_objects) const
+{
+ bool res = false;
+ S32 count = mObjects.count();
+ if (count > 0)
{
- *source_id = mSourceID;
+ res = true;
+ inv_objects.reset();
+ for (S32 i = 0; i < count; i++)
+ {
+ inv_objects.put(mObjects[i]);
+ }
}
-
- return mString;
+ return res;
}
-
-BOOL LLClipboard::canPasteString() const
+// Returns true if the LL Clipboard has pasteable items in it
+bool LLClipboard::hasContents() const
{
- return LLView::getWindow()->isClipboardTextAvailable();
+ return (mObjects.count() > 0);
}
-
-void LLClipboard::copyFromPrimarySubstring(const LLWString &src, S32 pos, S32 len, const LLUUID& source_id )
+// Returns true if the input uuid is in the list of clipboard objects
+bool LLClipboard::isOnClipboard(const LLUUID& object) const
{
- mSourceID = source_id;
- mString = src.substr(pos, len);
- LLView::getWindow()->copyTextToPrimary( mString );
+ return (mObjects.find(object) != LLDynamicArray<LLUUID>::FAIL);
}
+// Copy the input string to the LL and the system clipboard
+bool LLClipboard::copyToClipboard(const LLWString &src, S32 pos, S32 len, bool use_primary)
+{
+ reset();
+ return addToClipboard(src, pos, len, use_primary);
+}
-const LLWString& LLClipboard::getPastePrimaryWString( LLUUID* source_id )
+// Concatenate the input string to the LL and the system clipboard
+bool LLClipboard::addToClipboard(const LLWString &src, S32 pos, S32 len, bool use_primary)
{
- if( mSourceID.notNull() )
+ const LLWString sep(utf8str_to_wstring(std::string(", ")));
+ if (mString.length() == 0)
{
- LLWString temp_string;
- LLView::getWindow()->pasteTextFromPrimary(temp_string);
-
- if( temp_string != mString )
- {
- mSourceID.setNull();
- mString = temp_string;
- }
+ mString = src.substr(pos, len);
}
else
{
- LLView::getWindow()->pasteTextFromPrimary(mString);
+ mString = mString + sep + src.substr(pos, len);
}
+ mState++;
+ return (use_primary ? LLView::getWindow()->copyTextToPrimary(mString) : LLView::getWindow()->copyTextToClipboard(mString));
+}
- if( source_id )
+// Copy the System clipboard to the output string.
+// Manage the LL Clipboard / System clipboard consistency
+bool LLClipboard::pasteFromClipboard(LLWString &dst, bool use_primary)
+{
+ bool res = (use_primary ? LLView::getWindow()->pasteTextFromPrimary(dst) : LLView::getWindow()->pasteTextFromClipboard(dst));
+ if (res)
{
- *source_id = mSourceID;
+ if (dst != mString)
+ {
+ // Invalidate the LL clipboard if the System had a different string in it (i.e. some copy/cut was done in some other app)
+ reset();
+ }
+ mString = dst;
}
-
- return mString;
+ return res;
}
-
-BOOL LLClipboard::canPastePrimaryString() const
+// Return true if there's something on the System clipboard
+bool LLClipboard::isTextAvailable(bool use_primary) const
{
- return LLView::getWindow()->isPrimaryTextAvailable();
+ return (use_primary ? LLView::getWindow()->isPrimaryTextAvailable() : LLView::getWindow()->isClipboardTextAvailable());
}
-void LLClipboard::setSourceObject(const LLUUID& source_id, LLAssetType::EType type)
-{
- mSourceItem = new LLInventoryObject (source_id, LLUUID::null, type, "");
-}
diff --git a/indra/llui/llclipboard.h b/indra/llui/llclipboard.h
index 9371b94284..3947fa0229 100644
--- a/indra/llui/llclipboard.h
+++ b/indra/llui/llclipboard.h
@@ -27,46 +27,68 @@
#ifndef LL_LLCLIPBOARD_H
#define LL_LLCLIPBOARD_H
+#include <boost/function.hpp>
#include "llstring.h"
#include "lluuid.h"
#include "stdenums.h"
+#include "llsingleton.h"
+#include "llassettype.h"
#include "llinventory.h"
+typedef boost::function<void ()> cleanup_callback_t;
-class LLClipboard
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLClipboard
+//
+// This class is used to cut/copy/paste text strings and inventory items around
+// the world. Use LLClipboard::getInstance()->method() to use its methods.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLClipboard : public LLSingleton<LLClipboard>
{
public:
LLClipboard();
~LLClipboard();
+
+ // Clears the clipboard
+ void reset();
+ // Returns the state of the clipboard so client can know if it has been modified (comparing with tracked state)
+ int getState() const { return mState; }
- /* We support two flavors of clipboard. The default is the explicitly
- copy-and-pasted clipboard. The second is the so-called 'primary' clipboard
- which is implicitly copied upon selection on platforms which expect this
- (i.e. X11/Linux). */
-
- void copyFromSubstring(const LLWString &copy_from, S32 pos, S32 len, const LLUUID& source_id = LLUUID::null );
- void copyFromString(const LLWString &copy_from, const LLUUID& source_id = LLUUID::null );
- BOOL canPasteString() const;
- const LLWString& getPasteWString(LLUUID* source_id = NULL);
+ // Text strings management:
+ // ------------------------
+ // We support two flavors of text clipboards. The default is the explicitly
+ // copy-and-pasted clipboard. The second is the so-called 'primary' clipboard
+ // which is implicitly copied upon selection on platforms which expect this
+ // (i.e. X11/Linux, Mac).
+ bool copyToClipboard(const LLWString& src, S32 pos, S32 len, bool use_primary = false);
+ bool addToClipboard(const LLWString& src, S32 pos, S32 len, bool use_primary = false);
+ bool pasteFromClipboard(LLWString& dst, bool use_primary = false);
+ bool isTextAvailable(bool use_primary = false) const;
+
+ // Object list management:
+ // -----------------------
+ // Clears and adds one single object to the clipboard
+ bool copyToClipboard(const LLUUID& src, const LLAssetType::EType type = LLAssetType::AT_NONE);
+ // Adds one object to the current list of objects on the clipboard
+ bool addToClipboard(const LLUUID& src, const LLAssetType::EType type = LLAssetType::AT_NONE);
+ // Gets a copy of the objects on the clipboard
+ bool pasteFromClipboard(LLDynamicArray<LLUUID>& inventory_objects) const;
+
+ bool hasContents() const; // True if the clipboard has pasteable objects
+ bool isOnClipboard(const LLUUID& object) const; // True if the input object uuid is on the clipboard
- void copyFromPrimarySubstring(const LLWString &copy_from, S32 pos, S32 len, const LLUUID& source_id = LLUUID::null );
- BOOL canPastePrimaryString() const;
- const LLWString& getPastePrimaryWString(LLUUID* source_id = NULL);
+ bool isCutMode() const { return mCutMode; }
+ void setCutMode(bool mode, cleanup_callback_t cb = NULL) { mCutMode = mode; mCleanupCallback = cb; mState++; }
- // Support clipboard for object known only by their uuid and asset type
- void setSourceObject(const LLUUID& source_id, LLAssetType::EType type);
- const LLInventoryObject* getSourceObject() { return mSourceItem; }
-
private:
- LLUUID mSourceID;
- LLWString mString;
- LLInventoryObject* mSourceItem;
+ LLDynamicArray<LLUUID> mObjects; // Objects on the clipboard. Can be empty while mString contains something licit (e.g. text from chat)
+ LLWString mString; // The text string. If mObjects is not empty, this string is reflecting them (UUIDs for the moment).
+ bool mCutMode; // This is a convenience flag for the viewer. Will determine if mCleanupCallback() needs to be called.
+ cleanup_callback_t mCleanupCallback;// Function to call when the cut clipboard is being wiped out. Can be set to NULL (nothing done then).
+ int mState; // Incremented when the clipboard change so that interested parties can check its state.
+
};
-
-// Global singleton
-extern LLClipboard gClipboard;
-
-
#endif // LL_LLCLIPBOARD_H
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 7e84814c51..ff85afdf25 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -1047,7 +1047,7 @@ void LLLineEditor::cut()
// Prepare for possible rollback
LLLineEditorRollback rollback( this );
- gClipboard.copyFromSubstring( mText.getWString(), left_pos, length );
+ LLClipboard::getInstance()->copyToClipboard( mText.getWString(), left_pos, length );
deleteSelection();
// Validate new string and rollback the if needed.
@@ -1078,13 +1078,13 @@ void LLLineEditor::copy()
{
S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
S32 length = llabs( mSelectionStart - mSelectionEnd );
- gClipboard.copyFromSubstring( mText.getWString(), left_pos, length );
+ LLClipboard::getInstance()->copyToClipboard( mText.getWString(), left_pos, length );
}
}
BOOL LLLineEditor::canPaste() const
{
- return !mReadOnly && gClipboard.canPasteString();
+ return !mReadOnly && LLClipboard::getInstance()->isTextAvailable();
}
void LLLineEditor::paste()
@@ -1115,14 +1115,7 @@ void LLLineEditor::pasteHelper(bool is_primary)
if (can_paste_it)
{
LLWString paste;
- if (is_primary)
- {
- paste = gClipboard.getPastePrimaryWString();
- }
- else
- {
- paste = gClipboard.getPasteWString();
- }
+ LLClipboard::getInstance()->pasteFromClipboard(paste, is_primary);
if (!paste.empty())
{
@@ -1209,13 +1202,13 @@ void LLLineEditor::copyPrimary()
{
S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
S32 length = llabs( mSelectionStart - mSelectionEnd );
- gClipboard.copyFromPrimarySubstring( mText.getWString(), left_pos, length );
+ LLClipboard::getInstance()->copyToClipboard( mText.getWString(), left_pos, length, true);
}
}
BOOL LLLineEditor::canPastePrimary() const
{
- return !mReadOnly && gClipboard.canPastePrimaryString();
+ return !mReadOnly && LLClipboard::getInstance()->isTextAvailable(true);
}
void LLLineEditor::updatePrimary()
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index 466fac33ea..0a9d862b66 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -2504,7 +2504,7 @@ void LLScrollListCtrl::copy()
{
buffer += (*itor)->getContentsCSV() + "\n";
}
- gClipboard.copyFromSubstring(utf8str_to_wstring(buffer), 0, buffer.length());
+ LLClipboard::getInstance()->copyToClipboard(utf8str_to_wstring(buffer), 0, buffer.length());
}
// virtual
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 3409b6817d..141602ad2e 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -1332,7 +1332,7 @@ void LLTextEditor::cut()
}
S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
S32 length = llabs( mSelectionStart - mSelectionEnd );
- gClipboard.copyFromSubstring( getWText(), left_pos, length, mSourceID );
+ LLClipboard::getInstance()->copyToClipboard( getWText(), left_pos, length);
deleteSelection( FALSE );
onKeyStroke();
@@ -1352,12 +1352,12 @@ void LLTextEditor::copy()
}
S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
S32 length = llabs( mSelectionStart - mSelectionEnd );
- gClipboard.copyFromSubstring(getWText(), left_pos, length, mSourceID);
+ LLClipboard::getInstance()->copyToClipboard(getWText(), left_pos, length);
}
BOOL LLTextEditor::canPaste() const
{
- return !mReadOnly && gClipboard.canPasteString();
+ return !mReadOnly && LLClipboard::getInstance()->isTextAvailable();
}
// paste from clipboard
@@ -1393,16 +1393,8 @@ void LLTextEditor::pasteHelper(bool is_primary)
return;
}
- LLUUID source_id;
LLWString paste;
- if (is_primary)
- {
- paste = gClipboard.getPastePrimaryWString(&source_id);
- }
- else
- {
- paste = gClipboard.getPasteWString(&source_id);
- }
+ LLClipboard::getInstance()->pasteFromClipboard(paste, is_primary);
if (paste.empty())
{
@@ -1475,12 +1467,12 @@ void LLTextEditor::copyPrimary()
}
S32 left_pos = llmin( mSelectionStart, mSelectionEnd );
S32 length = llabs( mSelectionStart - mSelectionEnd );
- gClipboard.copyFromPrimarySubstring(getWText(), left_pos, length, mSourceID);
+ LLClipboard::getInstance()->copyToClipboard(getWText(), left_pos, length, true);
}
BOOL LLTextEditor::canPastePrimary() const
{
- return !mReadOnly && gClipboard.canPastePrimaryString();
+ return !mReadOnly && LLClipboard::getInstance()->isTextAvailable(true);
}
void LLTextEditor::updatePrimary()
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 66361c8fbf..0593475c54 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -288,7 +288,6 @@ set(viewer_SOURCE_FILES
llinspectremoteobject.cpp
llinspecttoast.cpp
llinventorybridge.cpp
- llinventoryclipboard.cpp
llinventoryfilter.cpp
llinventoryfunctions.cpp
llinventoryicon.cpp
@@ -843,7 +842,6 @@ set(viewer_HEADER_FILES
llinspectremoteobject.h
llinspecttoast.h
llinventorybridge.h
- llinventoryclipboard.h
llinventoryfilter.h
llinventoryfunctions.h
llinventoryicon.h
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index f4b6dc2c81..d4bce1e3a1 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -39,7 +39,7 @@
#include "llagent.h"
#include "llclipboard.h"
-#include "llinventoryclipboard.h"
+#include "llclipboard.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llfloatersidepanelcontainer.h"
@@ -1118,7 +1118,7 @@ BOOL LLFavoritesBarCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask)
}
void copy_slurl_to_clipboard_cb(std::string& slurl)
{
- gClipboard.copyFromString(utf8str_to_wstring(slurl));
+ LLClipboard::getInstance()->copyToClipboard(utf8str_to_wstring(slurl),0,slurl.size());
LLSD args;
args["SLURL"] = slurl;
@@ -1187,7 +1187,7 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata)
}
else if (action == "copy")
{
- LLInventoryClipboard::instance().store(mSelectedItemID);
+ LLClipboard::getInstance()->copyToClipboard(mSelectedItemID, LLAssetType::AT_LANDMARK);
}
else if (action == "paste")
{
@@ -1211,13 +1211,13 @@ void LLFavoritesBarCtrl::doToSelected(const LLSD& userdata)
BOOL LLFavoritesBarCtrl::isClipboardPasteable() const
{
- if (!LLInventoryClipboard::instance().hasContents())
+ if (!LLClipboard::getInstance()->hasContents())
{
return FALSE;
}
LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
+ LLClipboard::getInstance()->pasteFromClipboard(objects);
S32 count = objects.count();
for(S32 i = 0; i < count; i++)
{
@@ -1246,7 +1246,7 @@ void LLFavoritesBarCtrl::pastFromClipboard() const
{
LLInventoryItem* item = NULL;
LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
+ LLClipboard::getInstance()->pasteFromClipboard(objects);
S32 count = objects.count();
LLUUID parent_id(mFavoriteFolderId);
for(S32 i = 0; i < count; i++)
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index 9ed9d10c75..7791d4688b 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -32,7 +32,7 @@
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
-#include "llinventoryclipboard.h"
+#include "llclipboard.h"
#include "llagent.h"
#include "llappearancemgr.h"
@@ -397,11 +397,11 @@ bool LLFloaterGesture::isActionEnabled(const LLSD& command)
std::string command_name = command.asString();
if("paste" == command_name)
{
- if(!LLInventoryClipboard::instance().hasContents())
+ if(!LLClipboard::getInstance()->hasContents())
return false;
LLDynamicArray<LLUUID> ids;
- LLInventoryClipboard::instance().retrieve(ids);
+ LLClipboard::getInstance()->pasteFromClipboard(ids);
for(LLDynamicArray<LLUUID>::iterator it = ids.begin(); it != ids.end(); it++)
{
LLInventoryItem* item = gInventory.getItem(*it);
@@ -496,27 +496,26 @@ void LLFloaterGesture::onActivateBtnClick()
void LLFloaterGesture::onCopyPasteAction(const LLSD& command)
{
std::string command_name = command.asString();
- // since we select this comman inventory item had already arrived .
+ // Since we select this command, the inventory items must have already arrived
if("copy_gesture" == command_name)
{
uuid_vec_t ids;
getSelectedIds(ids);
- // make sure that clopboard is empty
- LLInventoryClipboard::instance().reset();
+ // Make sure the clipboard is empty
+ LLClipboard::getInstance()->reset();
for(uuid_vec_t::iterator it = ids.begin(); it != ids.end(); it++)
{
LLInventoryItem* item = gInventory.getItem(*it);
if(item && item->getInventoryType() == LLInventoryType::IT_GESTURE)
{
- LLInventoryClipboard::instance().add(item->getUUID());
+ LLClipboard::getInstance()->addToClipboard(item->getUUID(),LLAssetType::AT_GESTURE);
}
}
}
else if ("paste" == command_name)
{
- LLInventoryClipboard& clipbord = LLInventoryClipboard::instance();
LLDynamicArray<LLUUID> ids;
- clipbord.retrieve(ids);
+ LLClipboard::getInstance()->pasteFromClipboard(ids);
if(ids.empty() || !gInventory.isCategoryComplete(mGestureFolderID))
return;
LLInventoryCategory* gesture_dir = gInventory.getCategory(mGestureFolderID);
@@ -536,11 +535,11 @@ void LLFloaterGesture::onCopyPasteAction(const LLSD& command)
gesture_dir->getUUID(), getString("copy_name", string_args), cb);
}
}
- clipbord.reset();
+ LLClipboard::getInstance()->reset();
}
else if ("copy_uuid" == command_name)
{
- gClipboard.copyFromString(utf8str_to_wstring(mGestureList->getCurrentID().asString()), mGestureList->getCurrentID());
+ LLClipboard::getInstance()->copyToClipboard(mGestureList->getCurrentID(),LLAssetType::AT_GESTURE);
}
}
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 86001e4146..c0db2e366c 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -30,7 +30,7 @@
#include "llcallbacklist.h"
#include "llinventorybridge.h"
-#include "llinventoryclipboard.h" // *TODO: remove this once hack below gone.
+#include "llclipboard.h" // *TODO: remove this once hack below gone.
#include "llinventoryfilter.h"
#include "llinventoryfunctions.h"
#include "llinventorymodelbackgroundfetch.h"
@@ -1014,6 +1014,36 @@ bool isDescendantOfASelectedItem(LLFolderViewItem* item, const std::vector<LLFol
return false;
}
+// static
+void LLFolderView::removeCutItems()
+{
+ // There's no item in "cut" mode on the clipboard -> exit
+ if (!LLClipboard::getInstance()->isCutMode())
+ return;
+
+ // Get the list of clipboard item uuids and iterate through them
+ LLDynamicArray<LLUUID> objects;
+ LLClipboard::getInstance()->pasteFromClipboard(objects);
+ for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin();
+ iter != objects.end();
+ ++iter)
+ {
+ const LLUUID& item_id = (*iter);
+ LLInventoryObject *obj = gInventory.getObject(item_id);
+ if (obj)
+ {
+ if (LLAssetType::AT_CATEGORY == obj->getType())
+ {
+ remove_category(&gInventory, item_id);
+ }
+ else
+ {
+ remove_item(&gInventory, item_id);
+ }
+ }
+ }
+}
+
void LLFolderView::onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
@@ -1293,7 +1323,7 @@ BOOL LLFolderView::canCopy() const
void LLFolderView::copy()
{
// *NOTE: total hack to clear the inventory clipboard
- LLInventoryClipboard::instance().reset();
+ LLClipboard::getInstance()->reset();
S32 count = mSelectedItems.size();
if(getVisible() && getEnabled() && (count > 0))
{
@@ -1334,7 +1364,7 @@ BOOL LLFolderView::canCut() const
void LLFolderView::cut()
{
// clear the inventory clipboard
- LLInventoryClipboard::instance().reset();
+ LLClipboard::getInstance()->reset();
S32 count = mSelectedItems.size();
if(getVisible() && getEnabled() && (count > 0))
{
@@ -2108,10 +2138,10 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata)
removeSelectedItems();
return true;
}
-
- if ("copy" == action)
- {
- LLInventoryClipboard::instance().reset();
+ if (("copy" == action) || ("cut" == action))
+ {
+ // Clear the clipboard before we start adding things on it
+ LLClipboard::getInstance()->reset();
}
static const std::string change_folder_string = "change_folder_type_";
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index 1d018b5e6a..9a1df5a142 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -159,6 +159,7 @@ public:
// deletion functionality
void removeSelectedItems();
+ static void removeCutItems();
// open the selected item.
void openSelectedItems( void );
diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h
index aee31ca033..06682dcbf1 100644
--- a/indra/newview/llfoldervieweventlistener.h
+++ b/indra/newview/llfoldervieweventlistener.h
@@ -75,7 +75,7 @@ public:
virtual void move( LLFolderViewEventListener* parent_listener ) = 0;
virtual BOOL isItemCopyable() const = 0;
virtual BOOL copyToClipboard() const = 0;
- virtual void cutToClipboard() = 0;
+ virtual BOOL cutToClipboard() const = 0;
virtual BOOL isClipboardPasteable() const = 0;
virtual void pasteFromClipboard() = 0;
virtual void pasteLinkFromClipboard() = 0;
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index afad27b4e0..712d3e4583 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -40,6 +40,7 @@
#include "llviewerwindow.h" // Argh, only for setCursor()
// linden library includes
+#include "llclipboard.h"
#include "llfocusmgr.h" // gFocusMgr
#include "lltrans.h"
@@ -1002,7 +1003,7 @@ void LLFolderViewItem::draw()
LLColor4 color = (mIsSelected && filled) ? sHighlightFgColor : sFgColor;
if (highlight_link) color = sLinkColor;
if (in_library) color = sLibraryColor;
-
+
F32 right_x = 0;
F32 y = (F32)getRect().getHeight() - font->getLineHeight() - (F32)TEXT_PAD - (F32)TOP_PAD;
F32 text_left = (F32)(ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + mIndentation);
@@ -1158,7 +1159,36 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height, S32 filter_generation)
mNeedsSort = false;
}
+ // evaluate mHasVisibleChildren
mHasVisibleChildren = hasFilteredDescendants(filter_generation);
+ if (mHasVisibleChildren)
+ {
+ // We have to verify that there's at least one child that's not filtered out
+ bool found = false;
+ // Try the items first
+ for (items_t::iterator iit = mItems.begin(); iit != mItems.end(); ++iit)
+ {
+ LLFolderViewItem* itemp = (*iit);
+ found = (itemp->getFiltered(filter_generation));
+ if (found)
+ break;
+ }
+ if (!found)
+ {
+ // If no item found, try the folders
+ for (folders_t::iterator fit = mFolders.begin(); fit != mFolders.end(); ++fit)
+ {
+ LLFolderViewFolder* folderp = (*fit);
+ found = ( folderp->getListener()
+ && (folderp->getFiltered(filter_generation)
+ || (folderp->getFilteredFolder(filter_generation)
+ && folderp->hasFilteredDescendants(filter_generation))));
+ if (found)
+ break;
+ }
+ }
+ mHasVisibleChildren = found;
+ }
// calculate height as a single item (without any children), and reshapes rectangle to match
LLFolderViewItem::arrange( width, height, filter_generation );
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index ef58e4fa21..d55fb6a089 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -47,7 +47,7 @@
#include "llgiveinventory.h"
#include "llimfloater.h"
#include "llimview.h"
-#include "llinventoryclipboard.h"
+#include "llclipboard.h"
#include "llinventorydefines.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
@@ -215,13 +215,27 @@ BOOL LLInvFVBridge::isLink() const
/**
* @brief Adds this item into clipboard storage
*/
-void LLInvFVBridge::cutToClipboard()
+BOOL LLInvFVBridge::cutToClipboard() const
{
- if(isItemMovable())
+ const LLInventoryObject* obj = gInventory.getObject(mUUID);
+ if (obj && isItemMovable() && isItemRemovable())
{
- LLInventoryClipboard::instance().cut(mUUID);
+ LLClipboard::getInstance()->setCutMode(true, boost::bind(LLFolderView::removeCutItems));
+ return LLClipboard::getInstance()->addToClipboard(mUUID);
}
+ return FALSE;
}
+
+BOOL LLInvFVBridge::copyToClipboard() const
+{
+ const LLInventoryObject* obj = gInventory.getObject(mUUID);
+ if (obj && isItemCopyable())
+ {
+ return LLClipboard::getInstance()->addToClipboard(mUUID);
+ }
+ return FALSE;
+}
+
// *TODO: make sure this does the right thing
void LLInvFVBridge::showProperties()
{
@@ -405,7 +419,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*
BOOL LLInvFVBridge::isClipboardPasteable() const
{
- if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+ if (!LLClipboard::getInstance()->hasContents() || !isAgentInventory())
{
return FALSE;
}
@@ -415,37 +429,35 @@ BOOL LLInvFVBridge::isClipboardPasteable() const
return FALSE;
}
- const LLUUID &agent_id = gAgent.getID();
-
LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
+ LLClipboard::getInstance()->pasteFromClipboard(objects);
S32 count = objects.count();
for(S32 i = 0; i < count; i++)
{
const LLUUID &item_id = objects.get(i);
- // Can't paste folders
+ // Folders are pastable if all items in there are copyable
const LLInventoryCategory *cat = model->getCategory(item_id);
- if (cat)
- {
- return FALSE;
- }
-
- const LLInventoryItem *item = model->getItem(item_id);
- if (item)
+ if (cat)
{
- if (!item->getPermissions().allowCopyBy(agent_id))
- {
+ LLFolderBridge cat_br(mInventoryPanel.get(), mRoot, item_id);
+ if (!cat_br.isItemCopyable())
return FALSE;
- }
+ // Skip to the next item in the clipboard
+ continue;
}
+
+ // Each item must be copyable to be pastable
+ LLItemBridge item_br(mInventoryPanel.get(), mRoot, item_id);
+ if (!item_br.isItemCopyable())
+ return FALSE;
}
return TRUE;
}
BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
{
- if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+ if (!LLClipboard::getInstance()->hasContents() || !isAgentInventory())
{
return FALSE;
}
@@ -456,7 +468,7 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
}
LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
+ LLClipboard::getInstance()->pasteFromClipboard(objects);
S32 count = objects.count();
for(S32 i = 0; i < count; i++)
{
@@ -607,6 +619,12 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
disabled_items.push_back(std::string("Copy"));
}
+ items.push_back(std::string("Cut"));
+ if (!isItemMovable() || !isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Cut"));
+ }
+
if (canListOnMarketplace())
{
items.push_back(std::string("Marketplace Separator"));
@@ -625,7 +643,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
{
items.push_back(std::string("Paste"));
}
- if (!isClipboardPasteable() || ((flags & FIRST_SELECTED_ITEM) == 0))
+ if ((!LLClipboard::getInstance()->isCutMode() && !isClipboardPasteable()) || ((flags & FIRST_SELECTED_ITEM) == 0))
{
disabled_items.push_back(std::string("Paste"));
}
@@ -1286,6 +1304,11 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
gViewerWindow->getWindow()->copyTextToClipboard(utf8str_to_wstring(buffer));
return;
}
+ else if ("cut" == action)
+ {
+ cutToClipboard();
+ return;
+ }
else if ("copy" == action)
{
copyToClipboard();
@@ -1293,7 +1316,6 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action)
}
else if ("paste" == action)
{
- // Single item only
LLInventoryItem* itemp = model->getItem(mUUID);
if (!itemp) return;
@@ -1668,16 +1690,6 @@ BOOL LLItemBridge::isItemCopyable() const
return FALSE;
}
-BOOL LLItemBridge::copyToClipboard() const
-{
- if(isItemCopyable())
- {
- LLInventoryClipboard::instance().add(mUUID);
- return TRUE;
- }
- return FALSE;
-}
-
LLViewerInventoryItem* LLItemBridge::getItem() const
{
LLViewerInventoryItem* item = NULL;
@@ -1776,18 +1788,34 @@ BOOL LLFolderBridge::isUpToDate() const
BOOL LLFolderBridge::isItemCopyable() const
{
- // Can copy folders to paste-as-link, but not for straight paste.
- return gSavedSettings.getBOOL("InventoryLinking");
-}
+ // Folders are copyable if items in them are, recursively, copyable.
-BOOL LLFolderBridge::copyToClipboard() const
-{
- if(isItemCopyable())
+ // Get the content of the folder
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(mUUID,cat_array,item_array);
+
+ // Check the items
+ LLInventoryModel::item_array_t item_array_copy = *item_array;
+ for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
{
- LLInventoryClipboard::instance().add(mUUID);
- return TRUE;
+ LLInventoryItem* item = *iter;
+ LLItemBridge item_br(mInventoryPanel.get(), mRoot, item->getUUID());
+ if (!item_br.isItemCopyable())
+ return FALSE;
}
- return FALSE;
+
+ // Check the folders
+ LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
+ for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
+ {
+ LLViewerInventoryCategory* category = *iter;
+ LLFolderBridge cat_br(mInventoryPanel.get(), mRoot, category->getUUID());
+ if (!cat_br.isItemCopyable())
+ return FALSE;
+ }
+
+ return TRUE;
}
BOOL LLFolderBridge::isClipboardPasteable() const
@@ -1805,7 +1833,7 @@ BOOL LLFolderBridge::isClipboardPasteable() const
}
LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
+ LLClipboard::getInstance()->pasteFromClipboard(objects);
const LLViewerInventoryCategory *current_cat = getCategory();
// Search for the direct descendent of current Friends subfolder among all pasted items,
@@ -1843,7 +1871,7 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat );
const LLUUID &current_cat_id = current_cat->getUUID();
LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
+ LLClipboard::getInstance()->pasteFromClipboard(objects);
S32 count = objects.count();
for(S32 i = 0; i < count; i++)
{
@@ -2666,6 +2694,11 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
modifyOutfit(TRUE);
return;
}
+ else if ("cut" == action)
+ {
+ cutToClipboard();
+ return;
+ }
else if ("copy" == action)
{
copyToClipboard();
@@ -2877,7 +2910,7 @@ bool LLFolderBridge::removeItemResponse(const LLSD& notification, const LLSD& re
void LLFolderBridge::pasteFromClipboard()
{
LLInventoryModel* model = getInventoryModel();
- if(model && isClipboardPasteable())
+ if (model && (isClipboardPasteable() || LLClipboard::getInstance()->isCutMode()))
{
const LLUUID &current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);
const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false);
@@ -2887,7 +2920,7 @@ void LLFolderBridge::pasteFromClipboard()
const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);
LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
+ LLClipboard::getInstance()->pasteFromClipboard(objects);
if (move_is_into_outbox)
{
@@ -2937,7 +2970,8 @@ void LLFolderBridge::pasteFromClipboard()
const LLUUID& item_id = (*iter);
LLInventoryItem *item = model->getItem(item_id);
- if (item)
+ LLInventoryObject *obj = model->getObject(item_id);
+ if (obj)
{
if (move_is_into_current_outfit || move_is_into_outfit)
{
@@ -2946,29 +2980,56 @@ void LLFolderBridge::pasteFromClipboard()
dropToOutfit(item, move_is_into_current_outfit);
}
}
- else if(LLInventoryClipboard::instance().isCutMode())
+ else if (LLClipboard::getInstance()->isCutMode())
{
- // move_inventory_item() is not enough,
- //we have to update inventory locally too
- LLViewerInventoryItem* viitem = dynamic_cast<LLViewerInventoryItem*>(item);
- llassert(viitem);
- if (viitem)
+ // Do a move to "paste" a "cut"
+ // move_inventory_item() is not enough, as we have to update inventory locally too
+ if (LLAssetType::AT_CATEGORY == obj->getType())
+ {
+ LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id);
+ llassert(vicat);
+ if (vicat)
+ {
+ changeCategoryParent(model, vicat, parent_id, FALSE);
+ }
+ }
+ else
{
- changeItemParent(model, viitem, parent_id, FALSE);
+ LLViewerInventoryItem* viitem = dynamic_cast<LLViewerInventoryItem*>(item);
+ llassert(viitem);
+ if (viitem)
+ {
+ changeItemParent(model, viitem, parent_id, FALSE);
+ }
}
}
else
{
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- parent_id,
- std::string(),
- LLPointer<LLInventoryCallback>(NULL));
+ // Do a "copy" to "paste" a regular copy clipboard
+ if (LLAssetType::AT_CATEGORY == obj->getType())
+ {
+ LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id);
+ llassert(vicat);
+ if (vicat)
+ {
+ copy_inventory_category(model, vicat, parent_id);
+ }
+ }
+ else
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ parent_id,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
}
}
}
+ // Change mode to paste for next paste
+ LLClipboard::getInstance()->setCutMode(false);
}
}
@@ -2993,7 +3054,7 @@ void LLFolderBridge::pasteLinkFromClipboard()
const LLUUID parent_id(mUUID);
LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
+ LLClipboard::getInstance()->pasteFromClipboard(objects);
for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin();
iter != objects.end();
++iter)
@@ -3031,6 +3092,8 @@ void LLFolderBridge::pasteLinkFromClipboard()
LLPointer<LLInventoryCallback>(NULL));
}
}
+ // Change mode to paste for next paste
+ LLClipboard::getInstance()->setCutMode(false);
}
}
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 3b4f845f54..dc9e88d54d 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -106,8 +106,8 @@ public:
virtual void removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch);
virtual void move(LLFolderViewEventListener* new_parent_bridge) {}
virtual BOOL isItemCopyable() const { return FALSE; }
- virtual BOOL copyToClipboard() const { return FALSE; }
- virtual void cutToClipboard();
+ virtual BOOL copyToClipboard() const;
+ virtual BOOL cutToClipboard() const;
virtual BOOL isClipboardPasteable() const;
virtual BOOL isClipboardPasteableAsLink() const;
virtual void pasteFromClipboard() {}
@@ -212,7 +212,6 @@ public:
virtual BOOL renameItem(const std::string& new_name);
virtual BOOL removeItem();
virtual BOOL isItemCopyable() const;
- virtual BOOL copyToClipboard() const;
virtual BOOL hasChildren() const { return FALSE; }
virtual BOOL isUpToDate() const { return TRUE; }
@@ -275,7 +274,6 @@ public:
virtual BOOL isItemCopyable() const;
virtual BOOL isClipboardPasteable() const;
virtual BOOL isClipboardPasteableAsLink() const;
- virtual BOOL copyToClipboard() const;
static void createWearable(LLFolderBridge* bridge, LLWearableType::EType type);
diff --git a/indra/newview/llinventoryclipboard.cpp b/indra/newview/llinventoryclipboard.cpp
deleted file mode 100644
index 53da34f448..0000000000
--- a/indra/newview/llinventoryclipboard.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- * @file llinventoryclipboard.cpp
- * @brief LLInventoryClipboard class implementation
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include "llinventoryclipboard.h"
-
-
-LLInventoryClipboard LLInventoryClipboard::sInstance;
-
-///----------------------------------------------------------------------------
-/// Local function declarations, constants, enums, and typedefs
-///----------------------------------------------------------------------------
-
-
-///----------------------------------------------------------------------------
-/// Class LLInventoryClipboard
-///----------------------------------------------------------------------------
-
-LLInventoryClipboard::LLInventoryClipboard()
-: mCutMode(false)
-{
-}
-
-LLInventoryClipboard::~LLInventoryClipboard()
-{
- reset();
-}
-
-void LLInventoryClipboard::add(const LLUUID& object)
-{
- mObjects.put(object);
-}
-
-// this stores a single inventory object
-void LLInventoryClipboard::store(const LLUUID& object)
-{
- reset();
- mObjects.put(object);
-}
-
-void LLInventoryClipboard::store(const LLDynamicArray<LLUUID>& inv_objects)
-{
- reset();
- S32 count = inv_objects.count();
- for(S32 i = 0; i < count; i++)
- {
- mObjects.put(inv_objects[i]);
- }
-}
-
-void LLInventoryClipboard::cut(const LLUUID& object)
-{
- if(!mCutMode && !mObjects.empty())
- {
- //looks like there are some stored items, reset clipboard state
- reset();
- }
- mCutMode = true;
- add(object);
-}
-void LLInventoryClipboard::retrieve(LLDynamicArray<LLUUID>& inv_objects) const
-{
- inv_objects.reset();
- S32 count = mObjects.count();
- for(S32 i = 0; i < count; i++)
- {
- inv_objects.put(mObjects[i]);
- }
-}
-
-void LLInventoryClipboard::reset()
-{
- mObjects.reset();
- mCutMode = false;
-}
-
-// returns true if the clipboard has something pasteable in it.
-BOOL LLInventoryClipboard::hasContents() const
-{
- return (mObjects.count() > 0);
-}
-
-
-///----------------------------------------------------------------------------
-/// Local function definitions
-///----------------------------------------------------------------------------
diff --git a/indra/newview/llinventoryclipboard.h b/indra/newview/llinventoryclipboard.h
deleted file mode 100644
index b9f1451e5c..0000000000
--- a/indra/newview/llinventoryclipboard.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/**
- * @file llinventoryclipboard.h
- * @brief LLInventoryClipboard class header file
- *
- * $LicenseInfo:firstyear=2002&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLINVENTORYCLIPBOARD_H
-#define LL_LLINVENTORYCLIPBOARD_H
-
-#include "lldarray.h"
-#include "lluuid.h"
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryClipboard
-//
-// This class is used to cut/copy/paste inventory items around the
-// world. This class is accessed through a singleton (only one
-// inventory clipboard for now) which can be referenced using the
-// instance() method.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLInventoryClipboard
-{
-public:
- // calling this before main() is undefined
- static LLInventoryClipboard& instance() { return sInstance; }
-
- // this method adds to the current list.
- void add(const LLUUID& object);
-
- // this stores a single inventory object
- void store(const LLUUID& object);
-
- // this method stores an array of objects
- void store(const LLDynamicArray<LLUUID>& inventory_objects);
-
- void cut(const LLUUID& object);
- // this method gets the objects in the clipboard by copying them
- // into the array provided.
- void retrieve(LLDynamicArray<LLUUID>& inventory_objects) const;
-
- // this method empties out the clipboard
- void reset();
-
- // returns true if the clipboard has something pasteable in it.
- BOOL hasContents() const;
- bool isCutMode() const { return mCutMode; }
-
-protected:
- static LLInventoryClipboard sInstance;
-
- LLDynamicArray<LLUUID> mObjects;
- bool mCutMode;
-
-public:
- // please don't actually call these
- LLInventoryClipboard();
- ~LLInventoryClipboard();
-private:
- // please don't implement these
- LLInventoryClipboard(const LLInventoryClipboard&);
- LLInventoryClipboard& operator=(const LLInventoryClipboard&);
-};
-
-
-#endif // LL_LLINVENTORYCLIPBOARD_H
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 947f74315c..c127d7ac88 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -39,6 +39,7 @@
#include "llviewerfoldertype.h"
// linden library includes
+#include "llclipboard.h"
#include "lltrans.h"
LLInventoryFilter::FilterOps::FilterOps() :
@@ -96,13 +97,16 @@ BOOL LLInventoryFilter::check(const LLFolderViewItem* item)
}
mSubStringMatchOffset = mFilterSubString.size() ? item->getSearchableLabel().find(mFilterSubString) : std::string::npos;
+ const LLFolderViewEventListener* listener = item->getListener();
const BOOL passed_filtertype = checkAgainstFilterType(item);
const BOOL passed_permissions = checkAgainstPermissions(item);
const BOOL passed_filterlink = checkAgainstFilterLinks(item);
+ const BOOL passed_clipboard = (listener ? checkAgainstClipboard(listener->getUUID()) : TRUE);
const BOOL passed = (passed_filtertype &&
passed_permissions &&
passed_filterlink &&
+ passed_clipboard &&
(mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos));
return passed;
@@ -114,8 +118,10 @@ bool LLInventoryFilter::check(const LLInventoryItem* item)
const bool passed_filtertype = checkAgainstFilterType(item);
const bool passed_permissions = checkAgainstPermissions(item);
+ const BOOL passed_clipboard = checkAgainstClipboard(item->getUUID());
const bool passed = (passed_filtertype &&
passed_permissions &&
+ passed_clipboard &&
(mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos));
return passed;
@@ -163,7 +169,10 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const
return false;
}
- return true;
+ // Always check against the clipboard
+ const BOOL passed_clipboard = checkAgainstClipboard(folder_id);
+
+ return passed_clipboard;
}
BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) const
@@ -255,7 +264,7 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con
}
}
}
-
+
return TRUE;
}
@@ -309,6 +318,30 @@ bool LLInventoryFilter::checkAgainstFilterType(const LLInventoryItem* item) cons
return true;
}
+// Items and folders that are on the clipboard or, recursively, in a folder which
+// is on the clipboard must be filtered out if the clipboard is in the "cut" mode.
+bool LLInventoryFilter::checkAgainstClipboard(const LLUUID& object_id) const
+{
+ if (LLClipboard::getInstance()->isCutMode())
+ {
+ LLUUID current_id = object_id;
+ LLInventoryObject *current_object = gInventory.getObject(object_id);
+ while (current_id.notNull() && current_object)
+ {
+ if (LLClipboard::getInstance()->isOnClipboard(current_id))
+ {
+ return false;
+ }
+ current_id = current_object->getParentUUID();
+ if (current_id.notNull())
+ {
+ current_object = gInventory.getObject(current_id);
+ }
+ }
+ }
+ return true;
+}
+
BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const
{
const LLFolderViewEventListener* listener = item->getListener();
diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h
index 6be2acfaa3..1804637a04 100644
--- a/indra/newview/llinventoryfilter.h
+++ b/indra/newview/llinventoryfilter.h
@@ -124,6 +124,7 @@ public:
BOOL checkAgainstPermissions(const LLFolderViewItem* item) const;
bool checkAgainstPermissions(const LLInventoryItem* item) const;
BOOL checkAgainstFilterLinks(const LLFolderViewItem* item) const;
+ bool checkAgainstClipboard(const LLUUID& object_id) const;
std::string::size_type getStringMatchOffset() const;
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index dd92188e9d..236c997ef6 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -54,7 +54,6 @@
#include "lliconctrl.h"
#include "llimview.h"
#include "llinventorybridge.h"
-#include "llinventoryclipboard.h"
#include "llinventorymodel.h"
#include "llinventorypanel.h"
#include "lllineeditor.h"
@@ -161,6 +160,31 @@ void change_category_parent(LLInventoryModel* model,
model->notifyObservers();
}
+// Move the item to the trash. Works for folders and objects.
+// Caution: This method assumes that the item is removable!
+void remove_item(LLInventoryModel* model, const LLUUID& id)
+{
+ LLViewerInventoryItem* item = model->getItem(id);
+ if (!item)
+ return;
+
+ if (item->getType() == LLAssetType::AT_CATEGORY)
+ {
+ // Call the general helper function to delete a folder
+ remove_category(model, id);
+ }
+ else
+ {
+ // Get the trash UUID
+ LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false);
+ if (trash_id.notNull())
+ {
+ // Finally, move the item to the trash
+ change_item_parent(model, item, trash_id, true);
+ }
+ }
+}
+
void remove_category(LLInventoryModel* model, const LLUUID& cat_id)
{
if (!model || !get_is_category_removable(model, cat_id))
@@ -214,6 +238,49 @@ void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::s
model->notifyObservers();
}
+void copy_inventory_category(LLInventoryModel* model,
+ LLViewerInventoryCategory* cat,
+ const LLUUID& parent_id,
+ const LLUUID& root_copy_id)
+{
+ // Create the initial folder
+ LLUUID new_cat_uuid = gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName());
+ model->notifyObservers();
+
+ // We need to exclude the initial root of the copy to avoid recursively copying the copy, etc...
+ LLUUID root_id = (root_copy_id.isNull() ? new_cat_uuid : root_copy_id);
+
+ // Get the content of the folder
+ LLInventoryModel::cat_array_t* cat_array;
+ LLInventoryModel::item_array_t* item_array;
+ gInventory.getDirectDescendentsOf(cat->getUUID(),cat_array,item_array);
+
+ // Copy all the items
+ LLInventoryModel::item_array_t item_array_copy = *item_array;
+ for (LLInventoryModel::item_array_t::iterator iter = item_array_copy.begin(); iter != item_array_copy.end(); iter++)
+ {
+ LLInventoryItem* item = *iter;
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ new_cat_uuid,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+
+ // Copy all the folders
+ LLInventoryModel::cat_array_t cat_array_copy = *cat_array;
+ for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
+ {
+ LLViewerInventoryCategory* category = *iter;
+ if (category->getUUID() != root_id)
+ {
+ copy_inventory_category(model, category, new_cat_uuid, root_id);
+ }
+ }
+}
+
class LLInventoryCollectAllItems : public LLInventoryCollectFunctor
{
public:
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index ce2b89b22e..b3d9f4b966 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -62,6 +62,8 @@ void change_item_parent(LLInventoryModel* model,
const LLUUID& new_parent_id,
BOOL restamp);
+void remove_item(LLInventoryModel* model, const LLUUID& id);
+
void change_category_parent(LLInventoryModel* model,
LLViewerInventoryCategory* cat,
const LLUUID& new_parent_id,
@@ -71,6 +73,8 @@ void remove_category(LLInventoryModel* model, const LLUUID& cat_id);
void rename_category(LLInventoryModel* model, const LLUUID& cat_id, const std::string& new_name);
+void copy_inventory_category(LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& parent_id, const LLUUID& root_copy_id = LLUUID::null);
+
// Generates a string containing the path to the item specified by item_id.
void append_path(const LLUUID& id, std::string& path);
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 01a8ecfb5d..a1e17ffbf2 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -33,6 +33,7 @@
#include "llagentwearables.h"
#include "llappearancemgr.h"
#include "llavataractions.h"
+#include "llclipboard.h"
#include "llfloaterinventory.h"
#include "llfloaterreg.h"
#include "llfloatersidepanelcontainer.h"
@@ -247,6 +248,9 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params)
getFilter()->setFilterEmptySystemFolders();
}
+ // keep track of the clipboard state so that we avoid filtering too much
+ mClipboardState = LLClipboard::getInstance()->getState();
+
// Initialize base class params.
LLPanel::initFromParams(params);
}
@@ -277,6 +281,14 @@ void LLInventoryPanel::draw()
{
// Select the desired item (in case it wasn't loaded when the selection was requested)
mFolderRoot->updateSelection();
+
+ // Nudge the filter if the clipboard state changed
+ if (mClipboardState != LLClipboard::getInstance()->getState())
+ {
+ mClipboardState = LLClipboard::getInstance()->getState();
+ getFilter()->setModified(LLClipboard::getInstance()->isCutMode() ? LLInventoryFilter::FILTER_MORE_RESTRICTIVE : LLInventoryFilter::FILTER_LESS_RESTRICTIVE);
+ }
+
LLPanel::draw();
}
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 7d805f6862..6db59afb9b 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -222,6 +222,7 @@ public:
private:
std::string mSortOrderSetting;
+ int mClipboardState;
//--------------------------------------------------------------------
// Hidden folders
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index c7454e85a9..68a3b6d1cd 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -1149,7 +1149,7 @@ Rules:
- cut/rename/delete in any other accordions
- paste - only in Favorites, Landmarks accordions
3. For Folders we can: perform any action in Landmarks accordion, except Received folder
- 4. We can not paste folders from Clipboard (processed by LLFolderView::canPaste())
+ 4. We can paste folders from Clipboard (processed by LLFolderView::canPaste())
5. Check LLFolderView/Inventory Bridges rules
*/
bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFolderViewItem* item) const
@@ -1206,8 +1206,7 @@ bool LLLandmarksPanel::canItemBeModified(const std::string& command_name, LLFold
if ("cut" == command_name)
{
- // "Cut" disabled for folders. See EXT-8697.
- can_be_modified = root_folder->canCut() && listenerp->getInventoryType() != LLInventoryType::IT_CATEGORY;
+ can_be_modified = root_folder->canCut();
}
else if ("rename" == command_name)
{
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index 98ea680504..eb0a257def 100644
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -124,7 +124,7 @@ public:
virtual void move(LLFolderViewEventListener* parent_listener);
virtual BOOL isItemCopyable() const;
virtual BOOL copyToClipboard() const;
- virtual void cutToClipboard();
+ virtual BOOL cutToClipboard() const;
virtual BOOL isClipboardPasteable() const;
virtual void pasteFromClipboard();
virtual void pasteLinkFromClipboard();
@@ -524,8 +524,9 @@ BOOL LLTaskInvFVBridge::copyToClipboard() const
return FALSE;
}
-void LLTaskInvFVBridge::cutToClipboard()
+BOOL LLTaskInvFVBridge::cutToClipboard() const
{
+ return FALSE;
}
BOOL LLTaskInvFVBridge::isClipboardPasteable() const
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index 1f1cccad85..f92fbf3220 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -358,7 +358,7 @@ void LLTeleportHistoryPanel::ContextMenu::onInfo()
//static
void LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback(const std::string& slurl)
{
- gClipboard.copyFromString(utf8str_to_wstring(slurl));
+ LLClipboard::getInstance()->copyToClipboard(utf8str_to_wstring(slurl),0,slurl.size());
}
void LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard()
diff --git a/indra/newview/llpaneltopinfobar.cpp b/indra/newview/llpaneltopinfobar.cpp
index eb4c7572d4..0ad207ef00 100644
--- a/indra/newview/llpaneltopinfobar.cpp
+++ b/indra/newview/llpaneltopinfobar.cpp
@@ -467,7 +467,7 @@ void LLPanelTopInfoBar::onContextMenuItemClicked(const LLSD::String& item)
LLAgentUI::buildSLURL(slurl, false);
LLUIString location_str(slurl.getSLURLString());
- gClipboard.copyFromString(location_str);
+ LLClipboard::getInstance()->copyToClipboard(location_str,0,location_str.length());
}
}
diff --git a/indra/newview/llpanelwearing.cpp b/indra/newview/llpanelwearing.cpp
index e2801c09bd..5199bcb6b1 100644
--- a/indra/newview/llpanelwearing.cpp
+++ b/indra/newview/llpanelwearing.cpp
@@ -302,6 +302,6 @@ void LLPanelWearing::copyToClipboard()
}
}
- gClipboard.copyFromString(utf8str_to_wstring(text));
+ LLClipboard::getInstance()->copyToClipboard(utf8str_to_wstring(text),0,text.size());
}
// EOF
diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp
index eccb2cf2f1..81ad96f39e 100644
--- a/indra/newview/lltoolbarview.cpp
+++ b/indra/newview/lltoolbarview.cpp
@@ -75,6 +75,7 @@ LLToolBarView::LLToolBarView(const LLToolBarView::Params& p)
mDragStarted(false),
mShowToolbars(true),
mDragToolbarButton(NULL),
+ mDragItem(NULL),
mToolbarsLoaded(false)
{
for (S32 i = 0; i < TOOLBAR_COUNT; i++)
@@ -579,7 +580,6 @@ BOOL LLToolBarView::handleDragTool( S32 x, S32 y, const LLUUID& uuid, LLAssetTyp
uuid_vec_t cargo_ids;
types.push_back(DAD_WIDGET);
cargo_ids.push_back(uuid);
- gClipboard.setSourceObject(uuid,LLAssetType::AT_WIDGET);
LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_VIEWER;
LLUUID srcID;
LLToolDragAndDrop::getInstance()->beginMultiDrag(types, cargo_ids, src, srcID);
@@ -662,6 +662,18 @@ void LLToolBarView::resetDragTool(LLToolBarButton* toolbarButton)
gToolBarView->mDragToolbarButton = toolbarButton;
}
+// Provide a handle on a free standing inventory item containing references to the tool.
+// This might be used by Drag and Drop to move around references to tool items.
+LLInventoryObject* LLToolBarView::getDragItem()
+{
+ if (mDragToolbarButton)
+ {
+ LLUUID item_uuid = mDragToolbarButton->getCommandId().uuid();
+ mDragItem = new LLInventoryObject (item_uuid, LLUUID::null, LLAssetType::AT_WIDGET, "");
+ }
+ return mDragItem;
+}
+
void LLToolBarView::setToolBarsVisible(bool visible)
{
mShowToolbars = visible;
diff --git a/indra/newview/lltoolbarview.h b/indra/newview/lltoolbarview.h
index be66bcae36..9c4194ebed 100644
--- a/indra/newview/lltoolbarview.h
+++ b/indra/newview/lltoolbarview.h
@@ -31,6 +31,7 @@
#include "lluictrl.h"
#include "lltoolbar.h"
#include "llcommandmanager.h"
+#include "llinventory.h"
class LLUICtrlFactory;
@@ -106,6 +107,7 @@ public:
static BOOL handleDragTool(S32 x, S32 y, const LLUUID& uuid, LLAssetType::EType type);
static BOOL handleDropTool(void* cargo_data, S32 x, S32 y, LLToolBar* toolbar);
static void resetDragTool(LLToolBarButton* toolbarButton);
+ LLInventoryObject* getDragItem();
bool isModified() const;
@@ -129,6 +131,7 @@ private:
bool mDragStarted;
LLToolBarButton* mDragToolbarButton;
+ LLInventoryObject* mDragItem;
bool mShowToolbars;
};
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index c7ab934f9e..4f4eef0f3d 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -48,6 +48,7 @@
#include "llpreviewnotecard.h"
#include "llrootview.h"
#include "llselectmgr.h"
+#include "lltoolbarview.h"
#include "lltoolmgr.h"
#include "lltooltip.h"
#include "lltrans.h"
@@ -2528,7 +2529,7 @@ LLInventoryObject* LLToolDragAndDrop::locateInventory(
}
else if(mSource == SOURCE_VIEWER)
{
- item = (LLViewerInventoryItem*)gClipboard.getSourceObject();
+ item = (LLViewerInventoryItem*)gToolBarView->getDragItem();
}
if(item) return item;
if(cat) return cat;
diff --git a/indra/newview/llurllineeditorctrl.cpp b/indra/newview/llurllineeditorctrl.cpp
index 56b5bbf942..3efebcade9 100644
--- a/indra/newview/llurllineeditorctrl.cpp
+++ b/indra/newview/llurllineeditorctrl.cpp
@@ -89,5 +89,5 @@ void LLURLLineEditor::copyEscapedURLToClipboard()
else // human-readable location
text_to_copy = utf8str_to_wstring(unescaped_text);
- gClipboard.copyFromString( text_to_copy );
+ LLClipboard::getInstance()->copyToClipboard(text_to_copy, 0, text_to_copy.size());
}
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index ef4a1bc061..b13bf5b508 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -453,6 +453,14 @@
layout="topleft"
name="Copy Separator" />
<menu_item_call
+ label="Cut"
+ layout="topleft"
+ name="Cut">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="cut" />
+ </menu_item_call>
+ <menu_item_call
label="Copy"
layout="topleft"
name="Copy">