FIRE-6094 Import 'script recovery' (through changeset 26dd79c2b49d)

Kitty Barnett 2012-11-26 23:04:24 +01:00
parent ff18e33738
commit f168b2db27
11 changed files with 660 additions and 2 deletions

View File

@ -295,6 +295,7 @@ set(viewer_SOURCE_FILES
llfloaterreporter.cpp
llfloaterscriptdebug.cpp
llfloaterscriptlimits.cpp
llfloaterscriptrecover.cpp
llfloatersearch.cpp
llfloatersearchreplace.cpp
llfloatersellland.cpp
@ -946,6 +947,7 @@ set(viewer_HEADER_FILES
llfloaterreporter.h
llfloaterscriptdebug.h
llfloaterscriptlimits.h
llfloaterscriptrecover.h
llfloatersearch.h
llfloatersearchreplace.h
llfloatersellland.h

View File

@ -95,6 +95,9 @@
#include "llupdaterservice.h"
#include "llcallfloater.h"
#include "llfloatertexturefetchdebugger.h"
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-24 (Catznip-3.2.0)
#include "llfloaterscriptrecover.h"
// [/SL:KB]
#include "llspellcheck.h"
// Linden library includes
@ -5486,6 +5489,10 @@ void LLAppViewer::handleLoginComplete()
}
// </FS:TT>
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-24 (Catznip-3.2.0) | Added: Catznip-3.2.0
LLScriptRecoverQueue::recoverIfNeeded();
// [/SL:KB]
writeDebugInfo();
// <FS:AO> Warn users cache purge will affect usability

View File

@ -516,6 +516,18 @@ LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(
{
}
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2012-04-29 (Catznip-3.3.0) | Modified: Catznip-3.3.0
LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(
const LLSD& post_data,
const std::string& file_name,
LLAssetType::EType asset_type,
upload_callback_t upload_cb,
error_callback_t error_cb)
: LLAssetUploadResponder(post_data, file_name, asset_type), mUploadCallback(upload_cb), mErrorCallback(error_cb)
{
}
// [/SL:KB]
//virtual
void LLUpdateAgentInventoryResponder::uploadComplete(const LLSD& content)
{
@ -527,6 +539,12 @@ void LLUpdateAgentInventoryResponder::uploadComplete(const LLSD& content)
{
llwarns << "Inventory item for " << mVFileID
<< " is no longer in agent inventory." << llendl;
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2012-02-06 (Catznip-3.2.1) | Added: Catznip-3.2.1
if (!mUploadCallback.empty())
{
mUploadCallback(item_id, content, false /*failure*/);
}
// [/SL:KB]
return;
}
@ -539,6 +557,14 @@ void LLUpdateAgentInventoryResponder::uploadComplete(const LLSD& content)
llinfos << "Inventory item " << item->getName() << " saved into "
<< content["new_asset"].asString() << llendl;
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-24 (Catznip-3.2.0) | Added: Catznip-3.2.0
if (!mUploadCallback.empty())
{
mUploadCallback(item_id, content, true /*success*/);
return;
}
// [/SL:KB]
LLInventoryType::EType inventory_type = new_item->getInventoryType();
switch(inventory_type)
{
@ -611,6 +637,26 @@ void LLUpdateAgentInventoryResponder::uploadComplete(const LLSD& content)
}
}
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-24 (Catznip-3.2.0) | Added: Catznip-3.2.0
void LLUpdateAgentInventoryResponder::uploadFailure(const LLSD& content)
{
if (!mUploadCallback.empty())
mUploadCallback(mPostData["item_id"].asUUID(), content, false /*failure*/);
else
LLAssetUploadResponder::uploadFailure(content);
}
void LLUpdateAgentInventoryResponder::error(U32 statusNum, const std::string& reason)
{
LLAssetUploadResponder::error(statusNum, reason);
if (!mErrorCallback.empty())
{
// Clear the filename if the error callback returns false (prevents parent's destructor from deleting the file)
if (!mErrorCallback(mFileName, statusNum, reason))
mFileName.clear();
}
}
// [/SL:KB]
LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data,
const LLUUID& vfile_id,

View File

@ -136,7 +136,26 @@ public:
LLUpdateAgentInventoryResponder(const LLSD& post_data,
const std::string& file_name,
LLAssetType::EType asset_type);
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2012-04-29 (Catznip-3.3.0) | Modified: Catznip-3.3.0
typedef boost::function<void(const LLUUID&, const LLSD&, bool)> upload_callback_t;
typedef boost::function<bool(const std::string& filename, U32 statusNum, const std::string reason)> error_callback_t;
LLUpdateAgentInventoryResponder(const LLSD& post_data,
const std::string& file_name,
LLAssetType::EType asset_type,
upload_callback_t upload_cb,
error_callback_t error_cb = error_callback_t());
// [/SL:KB]
virtual void uploadComplete(const LLSD& content);
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2012-04-29 (Catznip-3.3.0) | Modified: Catznip-3.3.0
virtual void uploadFailure(const LLSD& content);
virtual void error(U32 statusNum, const std::string& reason);
// [/SL:KB]
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2012-04-29 (Catznip-3.3.0) | Modified: Catznip-3.3.0
upload_callback_t mUploadCallback;
error_callback_t mErrorCallback;
// [/SL:KB]
};
class LLUpdateTaskInventoryResponder : public LLAssetUploadResponder

View File

@ -0,0 +1,278 @@
/**
*
* Copyright (c) 2011-2012, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt
* in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt
*
* 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.
*
*/
#include "llviewerprecompiledheaders.h"
#include "llagent.h"
#include "llassetuploadresponders.h"
#include "llcheckboxctrl.h"
#include "lldiriterator.h"
#include "llfloaterreg.h"
#include "llfolderview.h"
#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
#include "llinventorypanel.h"
#include "llscrolllistctrl.h"
#include "llviewerassettype.h"
#include "llviewerinventory.h"
#include "llviewerregion.h"
#include "llfloaterscriptrecover.h"
// ============================================================================
// LLFloaterScriptRecover
//
LLFloaterScriptRecover::LLFloaterScriptRecover(const LLSD& sdKey)
: LLFloater(sdKey)
{
}
void LLFloaterScriptRecover::onOpen(const LLSD& sdKey)
{
LLScrollListCtrl* pListCtrl = findChild<LLScrollListCtrl>("script_list");
LLSD sdBhvrRow; LLSD& sdBhvrColumns = sdBhvrRow["columns"];
sdBhvrColumns[0] = LLSD().with("column", "script_check").with("type", "checkbox");
sdBhvrColumns[1] = LLSD().with("column", "script_name").with("type", "text");
pListCtrl->clearRows();
for (LLSD::array_const_iterator itFile = sdKey["files"].beginArray(), endFile = sdKey["files"].endArray();
itFile != endFile; ++itFile)
{
const LLSD& sdFile = *itFile;
sdBhvrRow["value"] = sdFile;
sdBhvrColumns[0]["value"] = true;
sdBhvrColumns[1]["value"] = sdFile["name"];
pListCtrl->addElement(sdBhvrRow, ADD_BOTTOM);
}
}
BOOL LLFloaterScriptRecover::postBuild()
{
findChild<LLUICtrl>("recover_btn")->setCommitCallback(boost::bind(&LLFloaterScriptRecover::onBtnRecover, this));
findChild<LLUICtrl>("cancel_btn")->setCommitCallback(boost::bind(&LLFloaterScriptRecover::onBtnCancel, this));
return TRUE;
}
void LLFloaterScriptRecover::onBtnCancel()
{
LLScrollListCtrl* pListCtrl = findChild<LLScrollListCtrl>("script_list");
// Delete all listed files
std::vector<LLScrollListItem*> items = pListCtrl->getAllData();
for (std::vector<LLScrollListItem*>::const_iterator itItem = items.begin(); itItem != items.end(); ++itItem)
{
LLFile::remove((*itItem)->getValue().asString());
}
closeFloater();
}
void LLFloaterScriptRecover::onBtnRecover()
{
LLScrollListCtrl* pListCtrl = findChild<LLScrollListCtrl>("script_list");
// Recover all selected, delete any unselected
std::vector<LLScrollListItem*> items = pListCtrl->getAllData(); LLSD sdFiles;
for (std::vector<LLScrollListItem*>::const_iterator itItem = items.begin(); itItem != items.end(); ++itItem)
{
LLScrollListCheck* pCheckColumn = dynamic_cast<LLScrollListCheck*>((*itItem)->getColumn(0));
if (!pCheckColumn)
continue;
const LLSD sdFile = (*itItem)->getValue();
if (pCheckColumn->getCheckBox()->getValue().asBoolean())
sdFiles.append(sdFile);
else
LLFile::remove(sdFile["path"]);
}
if (!sdFiles.emptyArray())
new LLScriptRecoverQueue(sdFiles);
closeFloater();
}
// ============================================================================
// LLCreateRecoverScriptCallback
//
class LLCreateRecoverScriptCallback : public LLInventoryCallback
{
public:
LLCreateRecoverScriptCallback(LLScriptRecoverQueue* pRecoverQueue)
: LLInventoryCallback(), mRecoverQueue(pRecoverQueue)
{
}
void fire(const LLUUID& idItem)
{
mRecoverQueue->onCreateScript(idItem);
}
protected:
LLScriptRecoverQueue* mRecoverQueue;
};
// ============================================================================
// LLScriptRecoverQueue
//
// static
void LLScriptRecoverQueue::recoverIfNeeded()
{
const std::string strTempPath = LLFile::tmpdir();
LLSD sdData, &sdFiles = sdData["files"];
LLDirIterator itFiles(strTempPath, "*.lslbackup"); std::string strFilename;
while (itFiles.next(strFilename))
{
// Build a friendly name for the file
std::string strName = gDirUtilp->getBaseFileName(strFilename, true);
std::string::size_type offset = strName.find_last_of("-");
if ( (std::string::npos != offset) && (offset != 0) && (offset == strName.length() - 9))
strName.erase(strName.length() - 9);
LLStringUtil::trim(strName);
if (0 == strName.length())
strName = "(Unknown script)";
sdFiles.append(LLSD().with("path", strTempPath + strFilename).with("name", strName));
}
if (sdFiles.size())
LLFloaterReg::showInstance("script_recover", sdData);
}
LLScriptRecoverQueue::LLScriptRecoverQueue(const LLSD& sdFiles)
{
for (LLSD::array_const_iterator itFile = sdFiles.beginArray(), endFile = sdFiles.endArray(); itFile != endFile; ++itFile)
{
const LLSD& sdFile = *itFile;
if (LLFile::isfile(sdFile["path"]))
m_FileQueue.insert(std::pair<std::string, LLSD>(sdFile["path"], sdFile));
}
recoverNext();
}
bool LLScriptRecoverQueue::recoverNext()
{
/**
* Steps:
* (1) create a script inventory item under Lost and Found
* (2) once we have the item's UUID we can upload the script
* (3) once the script is uploaded we move on to the next item
*/
const LLUUID idFNF = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
// Sanity check - if the associated UUID is non-null then this file is already being processed
filename_queue_t::const_iterator itFile = m_FileQueue.begin();
while ( (itFile != m_FileQueue.end()) && (itFile->second.has("item")) && (itFile->second["item"].asUUID().notNull()) )
++itFile;
if (m_FileQueue.end() == itFile)
{
LLInventoryPanel* pInvPanel = LLInventoryPanel::getActiveInventoryPanel(TRUE);
if (pInvPanel)
{
LLFolderViewFolder* pFVF = dynamic_cast<LLFolderViewFolder*>(pInvPanel->getRootFolder()->getItemByID(idFNF));
if (pFVF)
{
pFVF->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
pInvPanel->setSelection(idFNF, TRUE);
}
}
delete this;
return false;
}
std::string strItemDescr;
LLViewerAssetType::generateDescriptionFor(LLAssetType::AT_LSL_TEXT, strItemDescr);
create_inventory_item(gAgent.getID(), gAgent.getSessionID(), idFNF, LLTransactionID::tnull,
itFile->second["name"].asString(), strItemDescr, LLAssetType::AT_LSL_TEXT, LLInventoryType::IT_LSL,
NOT_WEARABLE, PERM_MOVE | PERM_TRANSFER, new LLCreateRecoverScriptCallback(this));
return true;
}
void LLScriptRecoverQueue::onCreateScript(const LLUUID& idItem)
{
const LLViewerInventoryItem* pItem = gInventory.getItem(idItem);
if (!pItem)
{
// TODO: error handling
return;
}
std::string strFileName;
for (filename_queue_t::iterator itFile = m_FileQueue.begin(); itFile != m_FileQueue.end(); ++itFile)
{
if (itFile->second["name"].asString() != pItem->getName())
continue;
strFileName = itFile->second["path"];
itFile->second["item"] = idItem;
break;
}
LLSD sdBody;
sdBody["item_id"] = idItem;
sdBody["target"] = "lsl2";
std::string strCapsUrl = gAgent.getRegion()->getCapability("UpdateScriptAgent");
LLHTTPClient::post(strCapsUrl, sdBody,
new LLUpdateAgentInventoryResponder(sdBody, strFileName, LLAssetType::AT_LSL_TEXT,
boost::bind(&LLScriptRecoverQueue::onSavedScript, this, _1, _2, _3),
boost::bind(&LLScriptRecoverQueue::onUploadError, this, _1)));
}
void LLScriptRecoverQueue::onSavedScript(const LLUUID& idItem, const LLSD&, bool fSuccess)
{
const LLViewerInventoryItem* pItem = gInventory.getItem(idItem);
if (pItem)
{
filename_queue_t::iterator itFile = m_FileQueue.begin();
while ( (itFile != m_FileQueue.end()) && ((!itFile->second.has("item")) || (itFile->second["item"].asUUID() != idItem)) )
++itFile;
if (itFile != m_FileQueue.end())
{
LLFile::remove(itFile->first);
m_FileQueue.erase(itFile);
}
}
recoverNext();
}
bool LLScriptRecoverQueue::onUploadError(const std::string& strFilename)
{
// Skip over the file when there's an error, we can try again on the next relog
filename_queue_t::iterator itFile = m_FileQueue.find(strFilename);
if (itFile != m_FileQueue.end())
{
LLViewerInventoryItem* pItem = gInventory.getItem(itFile->second["item"]);
if (pItem)
gInventory.changeItemParent(pItem, gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH), FALSE);
m_FileQueue.erase(itFile);
}
recoverNext();
return false;
}
// ============================================================================

View File

@ -0,0 +1,75 @@
/**
*
* Copyright (c) 2011-2012, Kitty Barnett
*
* The source code in this file is provided to you under the terms of the
* GNU Lesser General Public License, version 2.1, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. Terms of the LGPL can be found in doc/LGPL-licence.txt
* in this distribution, or online at http://www.gnu.org/licenses/lgpl-2.1.txt
*
* 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.
*
*/
#ifndef LL_FLOATERSCRIPTRECOVER_H
#define LL_FLOATERSCRIPTRECOVER_H
#include "llfloater.h"
// ============================================================================
// LLFloaterScriptRecover
//
class LLFloaterScriptRecover : public LLFloater
{
friend class LLFloaterReg;
private:
LLFloaterScriptRecover(const LLSD& sdKey);
/*
* LLFloater overrides
*/
public:
/*virtual*/ void onOpen(const LLSD& sdKey);
/*virtual*/ BOOL postBuild();
/*
* Member functions
*/
protected:
void onBtnCancel();
void onBtnRecover();
};
// ============================================================================
// LLScriptRecoverQueue
//
class LLScriptRecoverQueue
{
friend class LLCreateRecoverScriptCallback;
friend class LLFloaterScriptRecover;
protected:
LLScriptRecoverQueue(const LLSD& sdFiles);
public:
static void recoverIfNeeded();
protected:
bool recoverNext();
void onCreateScript(const LLUUID& idItem);
void onSavedScript(const LLUUID& idItem, const LLSD& sdContent, bool fSuccess);
bool onUploadError(const std::string& strFilename);
protected:
typedef std::map<std::string, LLSD> filename_queue_t;
filename_queue_t m_FileQueue;
};
// ============================================================================
#endif // LL_FLOATERSCRIPTRECOVER_H

View File

@ -104,7 +104,10 @@ public:
// llview
/*virtual*/ void draw();
void refreshFromItem();
// void refreshFromItem();
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2012-02-06 (Catznip-3.2.1) | Added: Catznip-3.2.1
virtual void refreshFromItem();
// [/SL:KB]
protected:
virtual void onCommit();

View File

@ -127,6 +127,29 @@ static bool have_script_upload_cap(LLUUID& object_id)
return object && (! object->getRegion()->getCapability("UpdateScriptTask").empty());
}
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0) | Added: Catznip-3.2.0
#include "lleventtimer.h"
/// ---------------------------------------------------------------------------
/// Timer helper class
/// ---------------------------------------------------------------------------
class LLCallbackTimer : public LLEventTimer
{
public:
typedef boost::function<bool()> bool_func_t;
public:
LLCallbackTimer(F32 nPeriod, bool_func_t cb) : LLEventTimer(nPeriod), m_Callback(cb) {}
/*virtual*/ BOOL tick() { return m_Callback(); }
protected:
bool_func_t m_Callback;
};
inline LLEventTimer* setupCallbackTimer(F32 nPeriod, LLCallbackTimer::bool_func_t cb)
{
return new LLCallbackTimer(nPeriod, cb);
}
// [/SL:KB]
/// ---------------------------------------------------------------------------
/// LLLiveLSLFile
/// ---------------------------------------------------------------------------
@ -1252,9 +1275,71 @@ bool LLScriptEdCore::enableLoadFromFileMenu(void* userdata)
LLScriptEdContainer::LLScriptEdContainer(const LLSD& key)
: LLPreview(key)
, mScriptEd(NULL)
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0) | Added: Catznip-3.2.0
, mBackupTimer(NULL)
// [/SL:KB]
{
}
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0) | Added: Catznip-3.2.0
LLScriptEdContainer::~LLScriptEdContainer()
{
// Clean up the backup file (unless we've gotten disconnected)
if ( (!mBackupFilename.empty()) && (gAgent.getRegion()) )
LLFile::remove(mBackupFilename);
delete mBackupTimer;
}
void LLScriptEdContainer::refreshFromItem()
{
LLPreview::refreshFromItem();
if (!mBackupFilename.empty())
{
const std::string strFilename = getBackupFileName();
if (strFilename != mBackupFilename)
{
LLFile::rename(mBackupFilename, strFilename);
mBackupFilename = strFilename;
}
}
}
bool LLScriptEdContainer::onBackupTimer()
{
if ( (mScriptEd) && (mScriptEd->hasChanged()) )
{
if (mBackupFilename.empty())
mBackupFilename = getBackupFileName();
mScriptEd->writeToFile(mBackupFilename);
}
return false;
}
std::string LLScriptEdContainer::getBackupFileName() const
{
// NOTE: this function is not guaranteed to return the same filename every time (i.e. the item name may have changed)
std::string strFile = LLFile::tmpdir();
// Find the inventory item for this script
const LLInventoryItem* pItem = getItem();
if (pItem)
{
strFile += gDirUtilp->getScrubbedFileName(pItem->getName().substr(0, 32));
strFile += "-";
}
// Append a CRC of the item UUID to make the filename (hopefully) unique
LLCRC crcUUID;
crcUUID.update((U8*)(&mItemUUID.mData), UUID_BYTES);
strFile += llformat("%X", crcUUID.getCRC());
strFile += ".lslbackup";
return strFile;
}
// [/SL:KB]
std::string LLScriptEdContainer::getTmpFileName()
{
// Take script inventory item id (within the object inventory)
@ -1350,6 +1435,16 @@ void LLPreviewLSL::callbackLSLCompileSucceeded()
// successful message here, since it's meaningless anyway.
// mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful"));
mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete"));
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0) | Added: Catznip-3.2.0
// Script was successfully saved so delete our backup copy if we have one and the editor is still pristine
if ( (!mBackupFilename.empty()) && (!mScriptEd->hasChanged()) )
{
LLFile::remove(mBackupFilename);
mBackupFilename.clear();
}
// [/SL:KB]
closeIfNeeded();
}
@ -1370,6 +1465,16 @@ void LLPreviewLSL::callbackLSLCompileFailed(const LLSD& compile_errors)
mScriptEd->mErrorList->addElement(row);
}
mScriptEd->selectFirstError();
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0) | Added: Catznip-3.2.0
// Script was successfully saved so delete our backup copy if we have one and the editor is still pristine
if ( (!mBackupFilename.empty()) && (!mScriptEd->hasChanged()) )
{
LLFile::remove(mBackupFilename);
mBackupFilename.clear();
}
// [/SL:KB]
closeIfNeeded();
}
@ -1475,7 +1580,10 @@ void LLPreviewLSL::onSave(void* userdata, BOOL close_after_save)
void LLPreviewLSL::saveIfNeeded(bool sync /*= true*/)
{
// llinfos << "LLPreviewLSL::saveIfNeeded()" << llendl;
if(!mScriptEd->hasChanged())
// if(!mScriptEd->hasChanged())
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2012-02-10 (Catznip-3.2.1) | Added: Catznip-3.2.1
if ( (!mScriptEd->hasChanged()) || (!gAgent.getRegion()) )
// [/SL:KB]
{
return;
}
@ -1764,6 +1872,11 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset
}
preview->mScriptEd->setEnableEditing(is_modifiable);
preview->mAssetStatus = PREVIEW_ASSET_LOADED;
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0) | Added: Catznip-3.2.0
// Start the timer which will perform regular backup saves
preview->mBackupTimer = setupCallbackTimer(60.0f, boost::bind(&LLPreviewLSL::onBackupTimer, preview));
// [/SL:KB]
}
else
{
@ -1854,6 +1967,16 @@ void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id,
lldebugs << "LSL Bytecode saved" << llendl;
mScriptEd->mErrorList->setCommentText(LLTrans::getString("CompileSuccessful"));
mScriptEd->mErrorList->setCommentText(LLTrans::getString("SaveComplete"));
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0) | Added: Catznip-3.2.0
// Script was successfully saved so delete our backup copy if we have one and the editor is still pristine
if ( (!mBackupFilename.empty()) && (!mScriptEd->hasChanged()) )
{
LLFile::remove(mBackupFilename);
mBackupFilename.clear();
}
// [/SL:KB]
closeIfNeeded();
}
@ -1874,6 +1997,16 @@ void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors)
mScriptEd->mErrorList->addElement(row);
}
mScriptEd->selectFirstError();
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0) | Added: Catznip-3.2.0
// Script was successfully saved so delete our backup copy if we have one and the editor is still pristine
if ( (!mBackupFilename.empty()) && (!mScriptEd->hasChanged()) )
{
LLFile::remove(mBackupFilename);
mBackupFilename.clear();
}
// [/SL:KB]
closeIfNeeded();
}
@ -1996,6 +2129,11 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id,
instance->loadScriptText(vfs, asset_id, type);
instance->mScriptEd->setEnableEditing(TRUE);
instance->mAssetStatus = PREVIEW_ASSET_LOADED;
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0) | Added: Catznip-3.2.0
// Start the timer which will perform regular backup saves
instance->mBackupTimer = setupCallbackTimer(60.0f, boost::bind(&LLLiveLSLEditor::onBackupTimer, instance));
// [/SL:KB]
}
else
{

View File

@ -49,6 +49,9 @@ class LLKeywordToken;
class LLVFS;
class LLViewerInventoryItem;
class LLScriptEdContainer;
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0)
class LLEventTimer;
// [/SL:KB]
// NaCl - LSL Preprocessor
class FSLSLPreprocessor;
// NaCl End
@ -176,13 +179,27 @@ class LLScriptEdContainer : public LLPreview
public:
LLScriptEdContainer(const LLSD& key);
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0) | Added: Catznip-3.2.0
/*virtual*/ ~LLScriptEdContainer();
/*virtual*/ void refreshFromItem();
// [/SL:KB]
protected:
std::string getTmpFileName();
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0) | Added: Catznip-3.2.0
virtual std::string getBackupFileName() const;
bool onBackupTimer();
// [/SL:KB]
bool onExternalChange(const std::string& filename);
virtual void saveIfNeeded(bool sync = true) = 0;
LLScriptEdCore* mScriptEd;
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-23 (Catznip-3.2.0) | Added: Catznip-3.2.0
std::string mBackupFilename;
LLEventTimer* mBackupTimer;
// [/SL:KB]
};
// Used to view and edit a LSL from your inventory.

View File

@ -96,6 +96,9 @@
#include "llfloaterreporter.h"
#include "llfloaterscriptdebug.h"
#include "llfloaterscriptlimits.h"
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-24 (Catznip-3.2.0)
#include "llfloaterscriptrecover.h"
// [/SL:KB]
#include "llfloatersearch.h"
#include "llfloatersellland.h"
#include "llfloatersettingsdebug.h"
@ -345,6 +348,9 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("script_debug_output", "floater_script_debug_panel.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebugOutput>);
LLFloaterReg::add("script_floater", "floater_script.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLScriptFloater>);
LLFloaterReg::add("script_limits", "floater_script_limits.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptLimits>);
// [SL:KB] - Patch: Build-ScriptRecover | Checked: 2011-11-24 (Catznip-3.2.0) | Added: Catznip-3.2.0
LLFloaterReg::add("script_recover", "floater_script_recover.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptRecover>);
// [/SL:KB]
LLFloaterReg::add("sell_land", "floater_sell_land.xml", &LLFloaterSellLand::buildFloater);
LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>);
LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundDevices>);

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
can_close="false"
can_minimize="false"
can_resize="false"
height="275"
open_positioning="centered"
name="script_recover"
single_instance="true"
title="Script Recovery"
width="350">
<text
follows="top|left|right"
height="48"
layout="topleft"
left="15"
length="1"
name="txt2"
top="10"
type="string"
word_wrap="true"
width="330">
[APP_NAME] has detected recoverable scripts that may have been left over from a recent viewer crash.
If you choose to recover these scripts they will be placed in the 'Lost and Found' folder of your inventory.
</text>
<scroll_list
draw_border="false"
draw_heading="true"
draw_stripes="true"
follows="all"
height="150"
layout="topleft"
left="10"
multi_select="false"
name="script_list"
top_pad="20"
width="330">
<scroll_list.columns
label=""
name="script_check"
width="20" />
<scroll_list.columns
label="Script Name"
name="script_name"
width="170" />
</scroll_list>
<button
follows="bottom|left"
height="25"
label="Recover"
left="65"
name="recover_btn"
top_pad="10"
width="100" />
<button
follows="bottom|left"
height="25"
label="Cancel"
left_pad="20"
name="cancel_btn"
width="100" />
</floater>