summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorVadim ProductEngine <vsavchuk@productengine.com>2011-08-19 19:58:00 +0300
committerVadim ProductEngine <vsavchuk@productengine.com>2011-08-19 19:58:00 +0300
commit1ed945b5a08a40399ff63ed657c66416c3baf7cf (patch)
tree3e113d9af224bfcd450bf013cddda23236ca7e29 /indra/newview
parent51c837dda7661ad7b9d90d96e35117eacc7a113a (diff)
STORM-1543 WIP Fixed auto-moving offered inventory items to trash.
It turned out impossible to properly remove an inventory item from within LLDiscardAgentOffer::done(), because that would lead to nested LLInventoryModel::notifyObservers() calls. Fixed that by deferring removal until the next LLAppViewer::idle() iteration. Also elimiteed duplicated code.
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llappviewer.cpp48
-rw-r--r--indra/newview/llappviewer.h2
-rw-r--r--indra/newview/llviewermessage.cpp32
3 files changed, 52 insertions, 30 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index d12b971bde..16c2b2d55a 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -321,6 +321,47 @@ static std::string gLaunchFileOnQuit;
// Used on Win32 for other apps to identify our window (eg, win_setup)
const char* const VIEWER_WINDOW_CLASSNAME = "Second Life";
+//-- LLDeferredTaskList ------------------------------------------------------
+
+/**
+ * A list of deferred tasks.
+ *
+ * We sometimes need to defer execution of some code until the viewer gets idle,
+ * e.g. removing an inventory item from within notifyObservers() may not work out.
+ *
+ * Tasks added to this list will be executed in the next LLAppViewer::idle() iteration.
+ * All tasks are executed only once.
+ */
+class LLDeferredTaskList:
+ public LLSingleton<LLDeferredTaskList>,
+ private LLDestroyClass<LLDeferredTaskList>
+{
+ LOG_CLASS(LLDeferredTaskList);
+ friend class LLAppViewer;
+ friend class LLDestroyClass<LLDeferredTaskList>;
+ typedef boost::signals2::signal<void()> signal_t;
+
+ void addTask(const signal_t::slot_type& cb)
+ {
+ mSignal.connect(cb);
+ }
+
+ void run()
+ {
+ if (mSignal.empty()) return;
+
+ mSignal();
+ mSignal.disconnect_all_slots();
+ }
+
+ static void destroyClass()
+ {
+ instance().mSignal.disconnect_all_slots();
+ }
+
+ signal_t mSignal;
+};
+
//----------------------------------------------------------------------------
// List of entries from strings.xml to always replace
@@ -3820,6 +3861,11 @@ bool LLAppViewer::initCache()
}
}
+void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb)
+{
+ LLDeferredTaskList::instance().addTask(cb);
+}
+
void LLAppViewer::purgeCache()
{
LL_INFOS("AppCache") << "Purging Cache and Texture Cache..." << LL_ENDL;
@@ -4413,6 +4459,8 @@ void LLAppViewer::idle()
gAudiop->idle(max_audio_decode_time);
}
}
+
+ LLDeferredTaskList::instance().run();
// Handle shutdown process, for example,
// wait for floaters to close, send quit message,
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 61ee6a7cf1..32115e0e7b 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -164,6 +164,8 @@ public:
login_completed_signal_t mOnLoginCompleted;
boost::signals2::connection setOnLoginCompletedCallback( const login_completed_signal_t::slot_type& cb ) { return mOnLoginCompleted.connect(cb); }
+ void addOnIdleCallback(const boost::function<void()>& cb); // add a callback to fire (once) when idle
+
void purgeCache(); // Clear the local cache.
// mute/unmute the system's master audio
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 8177446778..2c783cd4b6 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -1058,37 +1058,9 @@ public:
virtual void done()
{
LL_DEBUGS("Messaging") << "LLDiscardAgentOffer::done()" << LL_ENDL;
- const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
- bool notify = false;
- if(trash_id.notNull() && mObjectID.notNull())
- {
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate old_folder(mFolderID, -1);
- update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1);
- update.push_back(new_folder);
- gInventory.accountForUpdate(update);
- gInventory.moveObject(mObjectID, trash_id);
- LLInventoryObject* obj = gInventory.getObject(mObjectID);
- if(obj)
- {
- // no need to restamp since this is already a freshly
- // stamped item.
- obj->updateParentOnServer(FALSE);
- notify = true;
- }
- }
- else
- {
- LL_WARNS("Messaging") << "DiscardAgentOffer unable to find: "
- << (trash_id.isNull() ? "trash " : "")
- << (mObjectID.isNull() ? "object" : "") << LL_ENDL;
- }
+
+ LLAppViewer::instance()->addOnIdleCallback(boost::bind(&LLInventoryModel::removeItem, &gInventory, mObjectID));
gInventory.removeObserver(this);
- if(notify)
- {
- gInventory.notifyObservers();
- }
delete this;
}
protected: