Branch merge
commit
b1e83df9ba
|
|
@ -170,6 +170,7 @@ Boroondas Gupte
|
|||
SNOW-610
|
||||
SNOW-624
|
||||
SNOW-737
|
||||
STORM-318
|
||||
VWR-233
|
||||
VWR-20583
|
||||
VWR-20891
|
||||
|
|
@ -750,6 +751,8 @@ WolfPup Lowenhar
|
|||
STORM-102
|
||||
STORM-103
|
||||
STORM-143
|
||||
STORM-535
|
||||
STORM-544
|
||||
VWR-20741
|
||||
VWR-20933
|
||||
Zai Lynch
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@ macro (check_message_template _target)
|
|||
TARGET ${_target}
|
||||
POST_BUILD
|
||||
COMMAND ${PYTHON_EXECUTABLE}
|
||||
ARGS ${SCRIPTS_DIR}/template_verifier.py
|
||||
--mode=development --cache_master
|
||||
COMMENT "Verifying message template"
|
||||
ARGS ${SCRIPTS_DIR}/md5check.py
|
||||
3f19d130400c547de36278a6b6f9b028
|
||||
${SCRIPTS_DIR}/messages/message_template.msg
|
||||
COMMENT "Verifying message template - See http://wiki.secondlife.com/wiki/Template_verifier.py"
|
||||
)
|
||||
endmacro (check_message_template)
|
||||
|
|
|
|||
|
|
@ -58,6 +58,11 @@ void LLProcessLauncher::setWorkingDirectory(const std::string &dir)
|
|||
mWorkingDir = dir;
|
||||
}
|
||||
|
||||
const std::string& LLProcessLauncher::getExecutable() const
|
||||
{
|
||||
return mExecutable;
|
||||
}
|
||||
|
||||
void LLProcessLauncher::clearArguments()
|
||||
{
|
||||
mLaunchArguments.clear();
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ public:
|
|||
void setExecutable(const std::string &executable);
|
||||
void setWorkingDirectory(const std::string &dir);
|
||||
|
||||
const std::string& getExecutable() const;
|
||||
|
||||
void clearArguments();
|
||||
void addArgument(const std::string &arg);
|
||||
void addArgument(const char *arg);
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ set(viewer_SOURCE_FILES
|
|||
lleventnotifier.cpp
|
||||
lleventpoll.cpp
|
||||
llexpandabletextbox.cpp
|
||||
llexternaleditor.cpp
|
||||
llface.cpp
|
||||
llfasttimerview.cpp
|
||||
llfavoritesbar.cpp
|
||||
|
|
@ -682,6 +683,7 @@ set(viewer_HEADER_FILES
|
|||
lleventnotifier.h
|
||||
lleventpoll.h
|
||||
llexpandabletextbox.h
|
||||
llexternaleditor.h
|
||||
llface.h
|
||||
llfasttimerview.h
|
||||
llfavoritesbar.h
|
||||
|
|
|
|||
|
|
@ -12059,10 +12059,10 @@
|
|||
<key>Value</key>
|
||||
<real>150000.0</real>
|
||||
</map>
|
||||
<key>XUIEditor</key>
|
||||
<key>ExternalEditor</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Path to program used to edit XUI files</string>
|
||||
<string>Path to program used to edit LSL scripts and XUI files, e.g.: /usr/bin/gedit --new-window "%s"</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
|
|||
|
|
@ -825,9 +825,14 @@ void LLChatHistory::appendMessage(const LLChat& chat, const LLSD &args, const LL
|
|||
// [/RLVa:KB]
|
||||
{
|
||||
LLStyle::Params link_params(style_params);
|
||||
link_params.overwriteFrom(LLStyleMap::instance().lookupAgent(chat.mFromID));
|
||||
|
||||
// Setting is_link = true for agent SLURL to avoid applying default style to it.
|
||||
// See LLTextBase::appendTextImpl().
|
||||
link_params.is_link = true;
|
||||
link_params.link_href = LLSLURL("agent", chat.mFromID, "inspect").getSLURLString();
|
||||
|
||||
// Add link to avatar's inspector and delimiter to message.
|
||||
mEditor->appendText(link_params.link_href, false, style_params);
|
||||
mEditor->appendText(chat.mFromName, false, link_params);
|
||||
mEditor->appendText(delimiter, false, style_params);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "llchatmsgbox.h"
|
||||
#include "llavatariconctrl.h"
|
||||
#include "llcommandhandler.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "lllocalcliprect.h"
|
||||
#include "lltrans.h"
|
||||
|
|
@ -40,14 +41,44 @@
|
|||
|
||||
#include "llslurl.h"
|
||||
|
||||
// [RLVa:KB] - Checked: 2010-04-21 (RLVa-1.2.0f)
|
||||
#include "rlvhandler.h"
|
||||
// [/RLVa:KB]
|
||||
|
||||
static const S32 msg_left_offset = 10;
|
||||
static const S32 msg_right_offset = 10;
|
||||
static const S32 msg_height_pad = 5;
|
||||
|
||||
//*******************************************************************************************************************
|
||||
// LLObjectHandler
|
||||
//*******************************************************************************************************************
|
||||
|
||||
// handle secondlife:///app/object/<ID>/inspect SLURLs
|
||||
class LLObjectHandler : public LLCommandHandler
|
||||
{
|
||||
public:
|
||||
LLObjectHandler() : LLCommandHandler("object", UNTRUSTED_BLOCK) { }
|
||||
|
||||
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
|
||||
{
|
||||
if (params.size() < 2) return false;
|
||||
|
||||
LLUUID object_id;
|
||||
if (!object_id.set(params[0], FALSE))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string verb = params[1].asString();
|
||||
|
||||
if (verb == "inspect")
|
||||
{
|
||||
LLFloaterReg::showInstance("inspect_object", LLSD().with("object_id", object_id));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
LLObjectHandler gObjectHandler;
|
||||
|
||||
//*******************************************************************************************************************
|
||||
//LLNearbyChatToastPanel
|
||||
//*******************************************************************************************************************
|
||||
|
|
@ -145,11 +176,7 @@ void LLNearbyChatToastPanel::init(LLSD& notification)
|
|||
std::string fromName = notification["from"].asString(); // agent or object name
|
||||
mFromID = notification["from_id"].asUUID(); // agent id or object id
|
||||
mFromName = fromName;
|
||||
|
||||
// [RLVa:KB] - Checked: 2010-04-22 (RLVa-1.2.0f) | Added: RLVa-1.2.0f
|
||||
mShowIconTooltip = notification.has("show_icon_tooltip") ? notification["show_icon_tooltip"].asBoolean() : true;
|
||||
// [/RLVa:KB]
|
||||
|
||||
|
||||
int sType = notification["source"].asInteger();
|
||||
mSourceType = (EChatSourceType)sType;
|
||||
|
||||
|
|
@ -177,17 +204,26 @@ void LLNearbyChatToastPanel::init(LLSD& notification)
|
|||
{
|
||||
std::string str_sender;
|
||||
|
||||
str_sender = "<nolink>"; // disable parsing URLs in object names (STORM-358)
|
||||
str_sender += fromName;
|
||||
str_sender += "</nolink>";
|
||||
str_sender = fromName;
|
||||
|
||||
str_sender+=" ";
|
||||
|
||||
//append user name
|
||||
//append sender name
|
||||
if (mSourceType == CHAT_SOURCE_AGENT || mSourceType == CHAT_SOURCE_OBJECT)
|
||||
{
|
||||
LLStyle::Params style_params_name;
|
||||
|
||||
LLColor4 userNameColor = LLUIColorTable::instance().getColor("ChatToastAgentNameColor");
|
||||
std::string href;
|
||||
|
||||
if (mSourceType == CHAT_SOURCE_AGENT)
|
||||
{
|
||||
href = LLSLURL("agent", mFromID, "about").getSLURLString();
|
||||
}
|
||||
else
|
||||
{
|
||||
href = LLSLURL("object", mFromID, "inspect").getSLURLString();
|
||||
}
|
||||
|
||||
style_params_name.color(userNameColor);
|
||||
|
||||
|
|
@ -196,11 +232,16 @@ void LLNearbyChatToastPanel::init(LLSD& notification)
|
|||
style_params_name.font.name(font_name);
|
||||
style_params_name.font.size(font_style_size);
|
||||
|
||||
style_params_name.link_href = LLSLURL("agent",mFromID,"about").getSLURLString();
|
||||
style_params_name.link_href = href;
|
||||
style_params_name.is_link = true;
|
||||
|
||||
msg_text->appendText(str_sender, FALSE, style_params_name);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
msg_text->appendText(str_sender, false);
|
||||
}
|
||||
}
|
||||
|
||||
//append text
|
||||
|
|
@ -329,10 +370,7 @@ void LLNearbyChatToastPanel::draw()
|
|||
LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon", false);
|
||||
if(icon)
|
||||
{
|
||||
// icon->setDrawTooltip(mSourceType == CHAT_SOURCE_AGENT);
|
||||
// [RLVa:KB] - Checked: 2010-04-200 (RLVa-1.2.0f) | Added: RLVa-1.2.0f
|
||||
icon->setDrawTooltip( (mShowIconTooltip) && (mSourceType == CHAT_SOURCE_AGENT) );
|
||||
// [/RLVa:KB]
|
||||
icon->setDrawTooltip(mSourceType == CHAT_SOURCE_AGENT);
|
||||
if(mSourceType == CHAT_SOURCE_OBJECT)
|
||||
icon->setValue(LLSD("OBJECT_Icon"));
|
||||
else if(mSourceType == CHAT_SOURCE_SYSTEM)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,192 @@
|
|||
/**
|
||||
* @file llexternaleditor.cpp
|
||||
* @brief A convenient class to run external editor.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&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 "llexternaleditor.h"
|
||||
|
||||
#include "llui.h"
|
||||
|
||||
// static
|
||||
const std::string LLExternalEditor::sFilenameMarker = "%s";
|
||||
|
||||
// static
|
||||
const std::string LLExternalEditor::sSetting = "ExternalEditor";
|
||||
|
||||
bool LLExternalEditor::setCommand(const std::string& env_var, const std::string& override)
|
||||
{
|
||||
std::string cmd = findCommand(env_var, override);
|
||||
if (cmd.empty())
|
||||
{
|
||||
llwarns << "Empty editor command" << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add the filename marker if missing.
|
||||
if (cmd.find(sFilenameMarker) == std::string::npos)
|
||||
{
|
||||
cmd += " \"" + sFilenameMarker + "\"";
|
||||
llinfos << "Adding the filename marker (" << sFilenameMarker << ")" << llendl;
|
||||
}
|
||||
|
||||
string_vec_t tokens;
|
||||
if (tokenize(tokens, cmd) < 2) // 2 = bin + at least one arg (%s)
|
||||
{
|
||||
llwarns << "Error parsing editor command" << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check executable for existence.
|
||||
std::string bin_path = tokens[0];
|
||||
if (!LLFile::isfile(bin_path))
|
||||
{
|
||||
llwarns << "Editor binary [" << bin_path << "] not found" << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save command.
|
||||
mProcess.setExecutable(bin_path);
|
||||
mArgs.clear();
|
||||
for (size_t i = 1; i < tokens.size(); ++i)
|
||||
{
|
||||
if (i > 1) mArgs += " ";
|
||||
mArgs += "\"" + tokens[i] + "\"";
|
||||
}
|
||||
llinfos << "Setting command [" << bin_path << " " << mArgs << "]" << llendl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLExternalEditor::run(const std::string& file_path)
|
||||
{
|
||||
std::string args = mArgs;
|
||||
if (mProcess.getExecutable().empty() || args.empty())
|
||||
{
|
||||
llwarns << "Editor command not set" << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Substitute the filename marker in the command with the actual passed file name.
|
||||
LLStringUtil::replaceString(args, sFilenameMarker, file_path);
|
||||
|
||||
// Split command into separate tokens.
|
||||
string_vec_t tokens;
|
||||
tokenize(tokens, args);
|
||||
|
||||
// Set process arguments taken from the command.
|
||||
mProcess.clearArguments();
|
||||
for (string_vec_t::const_iterator arg_it = tokens.begin(); arg_it != tokens.end(); ++arg_it)
|
||||
{
|
||||
mProcess.addArgument(*arg_it);
|
||||
}
|
||||
|
||||
// Run the editor.
|
||||
llinfos << "Running editor command [" << mProcess.getExecutable() + " " + args << "]" << llendl;
|
||||
int result = mProcess.launch();
|
||||
if (result == 0)
|
||||
{
|
||||
// Prevent killing the process in destructor (will add it to the zombies list).
|
||||
mProcess.orphan();
|
||||
}
|
||||
|
||||
return result == 0;
|
||||
}
|
||||
|
||||
// static
|
||||
size_t LLExternalEditor::tokenize(string_vec_t& tokens, const std::string& str)
|
||||
{
|
||||
tokens.clear();
|
||||
|
||||
// Split the argument string into separate strings for each argument
|
||||
typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
|
||||
boost::char_separator<char> sep("", "\" ", boost::drop_empty_tokens);
|
||||
|
||||
tokenizer tokens_list(str, sep);
|
||||
tokenizer::iterator token_iter;
|
||||
BOOL inside_quotes = FALSE;
|
||||
BOOL last_was_space = FALSE;
|
||||
for (token_iter = tokens_list.begin(); token_iter != tokens_list.end(); ++token_iter)
|
||||
{
|
||||
if (!strncmp("\"",(*token_iter).c_str(),2))
|
||||
{
|
||||
inside_quotes = !inside_quotes;
|
||||
}
|
||||
else if (!strncmp(" ",(*token_iter).c_str(),2))
|
||||
{
|
||||
if(inside_quotes)
|
||||
{
|
||||
tokens.back().append(std::string(" "));
|
||||
last_was_space = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string to_push = *token_iter;
|
||||
if (last_was_space)
|
||||
{
|
||||
tokens.back().append(to_push);
|
||||
last_was_space = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
tokens.push_back(to_push);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tokens.size();
|
||||
}
|
||||
|
||||
// static
|
||||
std::string LLExternalEditor::findCommand(
|
||||
const std::string& env_var,
|
||||
const std::string& override)
|
||||
{
|
||||
std::string cmd;
|
||||
|
||||
// Get executable path.
|
||||
if (!override.empty()) // try the supplied override first
|
||||
{
|
||||
cmd = override;
|
||||
llinfos << "Using override" << llendl;
|
||||
}
|
||||
else if (!LLUI::sSettingGroups["config"]->getString(sSetting).empty())
|
||||
{
|
||||
cmd = LLUI::sSettingGroups["config"]->getString(sSetting);
|
||||
llinfos << "Using setting" << llendl;
|
||||
}
|
||||
else // otherwise use the path specified by the environment variable
|
||||
{
|
||||
char* env_var_val = getenv(env_var.c_str());
|
||||
if (env_var_val)
|
||||
{
|
||||
cmd = env_var_val;
|
||||
llinfos << "Using env var " << env_var << llendl;
|
||||
}
|
||||
}
|
||||
|
||||
llinfos << "Found command [" << cmd << "]" << llendl;
|
||||
return cmd;
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* @file llexternaleditor.h
|
||||
* @brief A convenient class to run external editor.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&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_LLEXTERNALEDITOR_H
|
||||
#define LL_LLEXTERNALEDITOR_H
|
||||
|
||||
#include <llprocesslauncher.h>
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
* LLExternalEditor ed;
|
||||
* ed.setCommand("MY_EXTERNAL_EDITOR_VAR");
|
||||
* ed.run("/path/to/file1");
|
||||
* ed.run("/other/path/to/file2");
|
||||
*/
|
||||
class LLExternalEditor
|
||||
{
|
||||
typedef std::vector<std::string> string_vec_t;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Set editor command.
|
||||
*
|
||||
* @param env_var Environment variable of the same purpose.
|
||||
* @param override Optional override.
|
||||
*
|
||||
* First tries the override, then a predefined setting (sSetting),
|
||||
* then the environment variable.
|
||||
*
|
||||
* @return Command if found, empty string otherwise.
|
||||
*
|
||||
* @see sSetting
|
||||
*/
|
||||
bool setCommand(const std::string& env_var, const std::string& override = LLStringUtil::null);
|
||||
|
||||
/**
|
||||
* Run the editor with the given file.
|
||||
*
|
||||
* @param file_path File to edit.
|
||||
* @return true on success, false on error.
|
||||
*/
|
||||
bool run(const std::string& file_path);
|
||||
|
||||
private:
|
||||
|
||||
static std::string findCommand(
|
||||
const std::string& env_var,
|
||||
const std::string& override);
|
||||
|
||||
static size_t tokenize(string_vec_t& tokens, const std::string& str);
|
||||
|
||||
/**
|
||||
* Filename placeholder that gets replaced with an actual file name.
|
||||
*/
|
||||
static const std::string sFilenameMarker;
|
||||
|
||||
/**
|
||||
* Setting that can specify the editor command.
|
||||
*/
|
||||
static const std::string sSetting;
|
||||
|
||||
|
||||
std::string mArgs;
|
||||
LLProcessLauncher mProcess;
|
||||
};
|
||||
|
||||
#endif // LL_LLEXTERNALEDITOR_H
|
||||
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
// Internal utility
|
||||
#include "lleventtimer.h"
|
||||
#include "llexternaleditor.h"
|
||||
#include "llrender.h"
|
||||
#include "llsdutil.h"
|
||||
#include "llxmltree.h"
|
||||
|
|
@ -160,6 +161,8 @@ public:
|
|||
DiffMap mDiffsMap; // map, of filename to pair of list of changed element paths and list of errors
|
||||
|
||||
private:
|
||||
LLExternalEditor mExternalEditor;
|
||||
|
||||
// XUI elements for this floater
|
||||
LLScrollListCtrl* mFileList; // scroll list control for file list
|
||||
LLLineEditor* mEditorPathTextBox; // text field for path to editor executable
|
||||
|
|
@ -185,7 +188,7 @@ private:
|
|||
std::string mSavedDiffPath; // stored diff file path so closing this floater doesn't reset it
|
||||
|
||||
// Internal functionality
|
||||
static void popupAndPrintWarning(std::string& warning); // pop up a warning
|
||||
static void popupAndPrintWarning(const std::string& warning); // pop up a warning
|
||||
std::string getLocalizedDirectory(); // build and return the path to the XUI directory for the currently-selected localization
|
||||
void scanDiffFile(LLXmlTreeNode* file_node); // scan a given XML node for diff entries and highlight them in its associated file
|
||||
void highlightChangedElements(); // look up the list of elements to highlight and highlight them in the current floater
|
||||
|
|
@ -597,7 +600,7 @@ void LLFloaterUIPreview::onClose(bool app_quitting)
|
|||
|
||||
// Error handling (to avoid code repetition)
|
||||
// *TODO: this is currently unlocalized. Add to alerts/notifications.xml, someday, maybe.
|
||||
void LLFloaterUIPreview::popupAndPrintWarning(std::string& warning)
|
||||
void LLFloaterUIPreview::popupAndPrintWarning(const std::string& warning)
|
||||
{
|
||||
llwarns << warning << llendl;
|
||||
LLSD args;
|
||||
|
|
@ -998,190 +1001,55 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save)
|
|||
// Respond to button click to edit currently-selected floater
|
||||
void LLFloaterUIPreview::onClickEditFloater()
|
||||
{
|
||||
std::string file_name = mFileList->getSelectedItemLabel(1); // get the file name of the currently-selected floater
|
||||
if(std::string("") == file_name) // if no item is selected
|
||||
// Determine file to edit.
|
||||
std::string file_path;
|
||||
{
|
||||
return; // ignore click
|
||||
}
|
||||
std::string path = getLocalizedDirectory() + file_name;
|
||||
std::string file_name = mFileList->getSelectedItemLabel(1); // get the file name of the currently-selected floater
|
||||
if (file_name.empty()) // if no item is selected
|
||||
{
|
||||
llwarns << "No file selected" << llendl;
|
||||
return; // ignore click
|
||||
}
|
||||
file_path = getLocalizedDirectory() + file_name;
|
||||
|
||||
// stat file to see if it exists (some localized versions may not have it there are no diffs, and then we try to open an nonexistent file)
|
||||
llstat dummy;
|
||||
if(LLFile::stat(path.c_str(), &dummy)) // if the file does not exist
|
||||
{
|
||||
std::string warning = "No file for this floater exists in the selected localization. Opening the EN version instead.";
|
||||
popupAndPrintWarning(warning);
|
||||
|
||||
path = get_xui_dir() + mDelim + "en" + mDelim + file_name; // open the en version instead, by default
|
||||
// stat file to see if it exists (some localized versions may not have it there are no diffs, and then we try to open an nonexistent file)
|
||||
llstat dummy;
|
||||
if(LLFile::stat(file_path.c_str(), &dummy)) // if the file does not exist
|
||||
{
|
||||
popupAndPrintWarning("No file for this floater exists in the selected localization. Opening the EN version instead.");
|
||||
file_path = get_xui_dir() + mDelim + "en" + mDelim + file_name; // open the en version instead, by default
|
||||
}
|
||||
}
|
||||
|
||||
// get executable path
|
||||
const char* exe_path_char;
|
||||
std::string path_in_textfield = mEditorPathTextBox->getText();
|
||||
if(std::string("") != path_in_textfield) // if the text field is not emtpy, use its path
|
||||
// Set the editor command.
|
||||
std::string cmd_override;
|
||||
{
|
||||
exe_path_char = path_in_textfield.c_str();
|
||||
}
|
||||
else if (!LLUI::sSettingGroups["config"]->getString("XUIEditor").empty())
|
||||
{
|
||||
exe_path_char = LLUI::sSettingGroups["config"]->getString("XUIEditor").c_str();
|
||||
}
|
||||
else // otherwise use the path specified by the environment variable
|
||||
{
|
||||
exe_path_char = getenv("LL_XUI_EDITOR");
|
||||
}
|
||||
std::string bin = mEditorPathTextBox->getText();
|
||||
if (!bin.empty())
|
||||
{
|
||||
// surround command with double quotes for the case if the path contains spaces
|
||||
if (bin.find("\"") == std::string::npos)
|
||||
{
|
||||
bin = "\"" + bin + "\"";
|
||||
}
|
||||
|
||||
// error check executable path
|
||||
if(NULL == exe_path_char)
|
||||
std::string args = mEditorArgsTextBox->getText();
|
||||
cmd_override = bin + " " + args;
|
||||
}
|
||||
}
|
||||
if (!mExternalEditor.setCommand("LL_XUI_EDITOR", cmd_override))
|
||||
{
|
||||
std::string warning = "Select an editor by setting the environment variable LL_XUI_EDITOR or specifying its path in the \"Editor Path\" field.";
|
||||
std::string warning = "Select an editor by setting the environment variable LL_XUI_EDITOR "
|
||||
"or the ExternalEditor setting or specifying its path in the \"Editor Path\" field.";
|
||||
popupAndPrintWarning(warning);
|
||||
return;
|
||||
}
|
||||
std::string exe_path = exe_path_char; // do this after error check, otherwise internal strlen call fails on bad char*
|
||||
|
||||
// remove any quotes; they're added back in later where necessary
|
||||
int found_at;
|
||||
while((found_at = exe_path.find("\"")) != -1 || (found_at = exe_path.find("'")) != -1)
|
||||
// Run the editor.
|
||||
if (!mExternalEditor.run(file_path))
|
||||
{
|
||||
exe_path.erase(found_at,1);
|
||||
}
|
||||
|
||||
llstat s;
|
||||
if(!LLFile::stat(exe_path.c_str(), &s)) // If the executable exists
|
||||
{
|
||||
// build paths and arguments
|
||||
std::string quote = std::string("\"");
|
||||
std::string args;
|
||||
std::string custom_args = mEditorArgsTextBox->getText();
|
||||
int position_of_file = custom_args.find(std::string("%FILE%"), 0); // prepare to replace %FILE% with actual file path
|
||||
std::string first_part_of_args = "";
|
||||
std::string second_part_of_args = "";
|
||||
if(-1 == position_of_file) // default: Executable.exe File.xml
|
||||
{
|
||||
args = quote + path + quote; // execute the command Program.exe "File.xml"
|
||||
}
|
||||
else // use advanced command-line arguments, e.g. "Program.exe -safe File.xml" -windowed for "-safe %FILE% -windowed"
|
||||
{
|
||||
first_part_of_args = custom_args.substr(0,position_of_file); // get part of args before file name
|
||||
second_part_of_args = custom_args.substr(position_of_file+6,custom_args.length()); // get part of args after file name
|
||||
custom_args = first_part_of_args + std::string("\"") + path + std::string("\"") + second_part_of_args; // replace %FILE% with "<file path>" and put back together
|
||||
args = custom_args; // and save in the variable that is actually used
|
||||
}
|
||||
|
||||
// find directory in which executable resides by taking everything after last slash
|
||||
int last_slash_position = exe_path.find_last_of(mDelim);
|
||||
if(-1 == last_slash_position)
|
||||
{
|
||||
std::string warning = std::string("Unable to find a valid path to the specified executable for XUI XML editing: ") + exe_path;
|
||||
popupAndPrintWarning(warning);
|
||||
return;
|
||||
}
|
||||
std::string exe_dir = exe_path.substr(0,last_slash_position); // strip executable off, e.g. get "C:\Program Files\TextPad 5" (with or without trailing slash)
|
||||
|
||||
#if LL_WINDOWS
|
||||
PROCESS_INFORMATION pinfo;
|
||||
STARTUPINFOA sinfo;
|
||||
memset(&sinfo, 0, sizeof(sinfo));
|
||||
memset(&pinfo, 0, sizeof(pinfo));
|
||||
|
||||
std::string exe_name = exe_path.substr(last_slash_position+1);
|
||||
args = quote + exe_name + quote + std::string(" ") + args; // and prepend the executable name, so we get 'Program.exe "Arg1"'
|
||||
|
||||
char *args2 = new char[args.size() + 1]; // Windows requires that the second parameter to CreateProcessA be a writable (non-const) string...
|
||||
strcpy(args2, args.c_str());
|
||||
|
||||
// we don't want the current directory to be the executable directory, since the file path is now relative. By using
|
||||
// NULL for the current directory instead of exe_dir.c_str(), the path to the target file will work.
|
||||
if(!CreateProcessA(exe_path.c_str(), args2, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo))
|
||||
{
|
||||
// DWORD dwErr = GetLastError();
|
||||
std::string warning = "Creating editor process failed!";
|
||||
popupAndPrintWarning(warning);
|
||||
}
|
||||
else
|
||||
{
|
||||
// foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
|
||||
// sGatewayHandle = pinfo.hProcess;
|
||||
CloseHandle(pinfo.hThread); // stops leaks - nothing else
|
||||
}
|
||||
|
||||
delete[] args2;
|
||||
#else // if !LL_WINDOWS
|
||||
// This code was copied from the code to run SLVoice, with some modification; should work in UNIX (Mac/Darwin or Linux)
|
||||
{
|
||||
std::vector<std::string> arglist;
|
||||
arglist.push_back(exe_path.c_str());
|
||||
|
||||
// Split the argument string into separate strings for each argument
|
||||
typedef boost::tokenizer< boost::char_separator<char> > tokenizer;
|
||||
boost::char_separator<char> sep("","\" ", boost::drop_empty_tokens);
|
||||
|
||||
tokenizer tokens(args, sep);
|
||||
tokenizer::iterator token_iter;
|
||||
BOOL inside_quotes = FALSE;
|
||||
BOOL last_was_space = FALSE;
|
||||
for(token_iter = tokens.begin(); token_iter != tokens.end(); ++token_iter)
|
||||
{
|
||||
if(!strncmp("\"",(*token_iter).c_str(),2))
|
||||
{
|
||||
inside_quotes = !inside_quotes;
|
||||
}
|
||||
else if(!strncmp(" ",(*token_iter).c_str(),2))
|
||||
{
|
||||
if(inside_quotes)
|
||||
{
|
||||
arglist.back().append(std::string(" "));
|
||||
last_was_space = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string to_push = *token_iter;
|
||||
if(last_was_space)
|
||||
{
|
||||
arglist.back().append(to_push);
|
||||
last_was_space = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
arglist.push_back(to_push);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create an argv vector for the child process
|
||||
char **fakeargv = new char*[arglist.size() + 1];
|
||||
int i;
|
||||
for(i=0; i < arglist.size(); i++)
|
||||
fakeargv[i] = const_cast<char*>(arglist[i].c_str());
|
||||
|
||||
fakeargv[i] = NULL;
|
||||
|
||||
fflush(NULL); // flush all buffers before the child inherits them
|
||||
pid_t id = vfork();
|
||||
if(id == 0)
|
||||
{
|
||||
// child
|
||||
execv(exe_path.c_str(), fakeargv);
|
||||
|
||||
// If we reach this point, the exec failed.
|
||||
// Use _exit() instead of exit() per the vfork man page.
|
||||
std::string warning = "Creating editor process failed (vfork/execv)!";
|
||||
popupAndPrintWarning(warning);
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
// parent
|
||||
delete[] fakeargv;
|
||||
// sGatewayPID = id;
|
||||
}
|
||||
#endif // LL_WINDOWS
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string warning = "Unable to find path to external XML editor for XUI preview tool";
|
||||
popupAndPrintWarning(warning);
|
||||
popupAndPrintWarning("Failed to run editor");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -733,8 +733,6 @@ void LLIMFloater::updateMessages()
|
|||
|
||||
if (messages.size())
|
||||
{
|
||||
// LLUIColor chat_color = LLUIColorTable::instance().getColor("IMChatColor");
|
||||
|
||||
LLSD chat_args;
|
||||
chat_args["use_plain_text_chat_history"] = use_plain_text_chat_history;
|
||||
|
||||
|
|
|
|||
|
|
@ -34,11 +34,13 @@
|
|||
#include "llcheckboxctrl.h"
|
||||
#include "llcombobox.h"
|
||||
#include "lldir.h"
|
||||
#include "llexternaleditor.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llinventorydefines.h"
|
||||
#include "llinventorymodel.h"
|
||||
#include "llkeyboard.h"
|
||||
#include "lllineeditor.h"
|
||||
#include "lllivefile.h"
|
||||
#include "llhelp.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llresmgr.h"
|
||||
|
|
@ -118,6 +120,54 @@ static bool have_script_upload_cap(LLUUID& object_id)
|
|||
return object && (! object->getRegion()->getCapability("UpdateScriptTask").empty());
|
||||
}
|
||||
|
||||
/// ---------------------------------------------------------------------------
|
||||
/// LLLiveLSLFile
|
||||
/// ---------------------------------------------------------------------------
|
||||
class LLLiveLSLFile : public LLLiveFile
|
||||
{
|
||||
public:
|
||||
LLLiveLSLFile(std::string file_path, LLLiveLSLEditor* parent);
|
||||
~LLLiveLSLFile();
|
||||
|
||||
void ignoreNextUpdate() { mIgnoreNextUpdate = true; }
|
||||
|
||||
protected:
|
||||
/*virtual*/ bool loadFile();
|
||||
|
||||
LLLiveLSLEditor* mParent;
|
||||
bool mIgnoreNextUpdate;
|
||||
};
|
||||
|
||||
LLLiveLSLFile::LLLiveLSLFile(std::string file_path, LLLiveLSLEditor* parent)
|
||||
: mParent(parent)
|
||||
, mIgnoreNextUpdate(false)
|
||||
, LLLiveFile(file_path, 1.0)
|
||||
{
|
||||
}
|
||||
|
||||
LLLiveLSLFile::~LLLiveLSLFile()
|
||||
{
|
||||
LLFile::remove(filename());
|
||||
}
|
||||
|
||||
bool LLLiveLSLFile::loadFile()
|
||||
{
|
||||
if (mIgnoreNextUpdate)
|
||||
{
|
||||
mIgnoreNextUpdate = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!mParent->loadScriptText(filename()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Disable sync to avoid recursive load->save->load calls.
|
||||
mParent->saveIfNeeded(false);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// ---------------------------------------------------------------------------
|
||||
/// LLFloaterScriptSearch
|
||||
/// ---------------------------------------------------------------------------
|
||||
|
|
@ -284,6 +334,7 @@ LLScriptEdCore::LLScriptEdCore(
|
|||
const LLHandle<LLFloater>& floater_handle,
|
||||
void (*load_callback)(void*),
|
||||
void (*save_callback)(void*, BOOL),
|
||||
void (*edit_callback)(void*),
|
||||
void (*search_replace_callback) (void* userdata),
|
||||
void* userdata,
|
||||
S32 bottom_pad)
|
||||
|
|
@ -293,6 +344,7 @@ LLScriptEdCore::LLScriptEdCore(
|
|||
mEditor( NULL ),
|
||||
mLoadCallback( load_callback ),
|
||||
mSaveCallback( save_callback ),
|
||||
mEditCallback( edit_callback ),
|
||||
mSearchReplaceCallback( search_replace_callback ),
|
||||
mUserdata( userdata ),
|
||||
mForceClose( FALSE ),
|
||||
|
|
@ -332,6 +384,7 @@ BOOL LLScriptEdCore::postBuild()
|
|||
|
||||
childSetCommitCallback("lsl errors", &LLScriptEdCore::onErrorList, this);
|
||||
childSetAction("Save_btn", boost::bind(&LLScriptEdCore::doSave,this,FALSE));
|
||||
childSetAction("Edit_btn", boost::bind(&LLScriptEdCore::onEditButtonClick, this));
|
||||
|
||||
initMenu();
|
||||
|
||||
|
|
@ -812,6 +865,13 @@ void LLScriptEdCore::doSave( BOOL close_after_save )
|
|||
}
|
||||
}
|
||||
|
||||
void LLScriptEdCore::onEditButtonClick()
|
||||
{
|
||||
if (mEditCallback)
|
||||
{
|
||||
mEditCallback(mUserdata);
|
||||
}
|
||||
}
|
||||
|
||||
void LLScriptEdCore::onBtnUndoChanges()
|
||||
{
|
||||
|
|
@ -952,6 +1012,7 @@ void* LLPreviewLSL::createScriptEdPanel(void* userdata)
|
|||
self->getHandle(),
|
||||
LLPreviewLSL::onLoad,
|
||||
LLPreviewLSL::onSave,
|
||||
NULL, // no edit callback
|
||||
LLPreviewLSL::onSearchReplace,
|
||||
self,
|
||||
0);
|
||||
|
|
@ -1420,6 +1481,7 @@ void* LLLiveLSLEditor::createScriptEdPanel(void* userdata)
|
|||
self->getHandle(),
|
||||
&LLLiveLSLEditor::onLoad,
|
||||
&LLLiveLSLEditor::onSave,
|
||||
&LLLiveLSLEditor::onEdit,
|
||||
&LLLiveLSLEditor::onSearchReplace,
|
||||
self,
|
||||
0);
|
||||
|
|
@ -1436,6 +1498,7 @@ LLLiveLSLEditor::LLLiveLSLEditor(const LLSD& key) :
|
|||
mCloseAfterSave(FALSE),
|
||||
mPendingUploads(0),
|
||||
mIsModifiable(FALSE),
|
||||
mLiveFile(NULL),
|
||||
mIsNew(false)
|
||||
{
|
||||
mFactoryMap["script ed panel"] = LLCallbackMap(LLLiveLSLEditor::createScriptEdPanel, this);
|
||||
|
|
@ -1461,6 +1524,7 @@ BOOL LLLiveLSLEditor::postBuild()
|
|||
|
||||
LLLiveLSLEditor::~LLLiveLSLEditor()
|
||||
{
|
||||
delete mLiveFile;
|
||||
}
|
||||
|
||||
// virtual
|
||||
|
|
@ -1642,38 +1706,39 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id,
|
|||
delete xored_id;
|
||||
}
|
||||
|
||||
// unused
|
||||
// void LLLiveLSLEditor::loadScriptText(const std::string& filename)
|
||||
// {
|
||||
// if(!filename)
|
||||
// {
|
||||
// llerrs << "Filename is Empty!" << llendl;
|
||||
// return;
|
||||
// }
|
||||
// LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
|
||||
// if(file)
|
||||
// {
|
||||
// // read in the whole file
|
||||
// fseek(file, 0L, SEEK_END);
|
||||
// long file_length = ftell(file);
|
||||
// fseek(file, 0L, SEEK_SET);
|
||||
// char* buffer = new char[file_length+1];
|
||||
// size_t nread = fread(buffer, 1, file_length, file);
|
||||
// if (nread < (size_t) file_length)
|
||||
// {
|
||||
// llwarns << "Short read" << llendl;
|
||||
// }
|
||||
// buffer[nread] = '\0';
|
||||
// fclose(file);
|
||||
// mScriptEd->mEditor->setText(LLStringExplicit(buffer));
|
||||
// mScriptEd->mEditor->makePristine();
|
||||
// delete[] buffer;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// llwarns << "Error opening " << filename << llendl;
|
||||
// }
|
||||
// }
|
||||
bool LLLiveLSLEditor::loadScriptText(const std::string& filename)
|
||||
{
|
||||
if (filename.empty())
|
||||
{
|
||||
llwarns << "Empty file name" << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
LLFILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/
|
||||
if (!file)
|
||||
{
|
||||
llwarns << "Error opening " << filename << llendl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// read in the whole file
|
||||
fseek(file, 0L, SEEK_END);
|
||||
size_t file_length = (size_t) ftell(file);
|
||||
fseek(file, 0L, SEEK_SET);
|
||||
char* buffer = new char[file_length+1];
|
||||
size_t nread = fread(buffer, 1, file_length, file);
|
||||
if (nread < file_length)
|
||||
{
|
||||
llwarns << "Short read" << llendl;
|
||||
}
|
||||
buffer[nread] = '\0';
|
||||
fclose(file);
|
||||
mScriptEd->mEditor->setText(LLStringExplicit(buffer));
|
||||
//mScriptEd->mEditor->makePristine();
|
||||
delete[] buffer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLLiveLSLEditor::loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
|
||||
{
|
||||
|
|
@ -1842,9 +1907,8 @@ LLLiveLSLSaveData::LLLiveLSLSaveData(const LLUUID& id,
|
|||
mItem = new LLViewerInventoryItem(item);
|
||||
}
|
||||
|
||||
void LLLiveLSLEditor::saveIfNeeded()
|
||||
void LLLiveLSLEditor::saveIfNeeded(bool sync)
|
||||
{
|
||||
llinfos << "LLLiveLSLEditor::saveIfNeeded()" << llendl;
|
||||
LLViewerObject* object = gObjectList.findObject(mObjectUUID);
|
||||
if(!object)
|
||||
{
|
||||
|
|
@ -1894,29 +1958,19 @@ void LLLiveLSLEditor::saveIfNeeded()
|
|||
mItem->setAssetUUID(asset_id);
|
||||
mItem->setTransactionID(tid);
|
||||
|
||||
// write out the data, and store it in the asset database
|
||||
LLFILE* fp = LLFile::fopen(filename, "wb");
|
||||
if(!fp)
|
||||
writeToFile(filename);
|
||||
|
||||
if (sync)
|
||||
{
|
||||
llwarns << "Unable to write to " << filename << llendl;
|
||||
|
||||
LLSD row;
|
||||
row["columns"][0]["value"] = "Error writing to local file. Is your hard drive full?";
|
||||
row["columns"][0]["font"] = "SANSSERIF_SMALL";
|
||||
mScriptEd->mErrorList->addElement(row);
|
||||
return;
|
||||
// Sync with external ed2itor.
|
||||
std::string tmp_file = getTmpFileName();
|
||||
llstat s;
|
||||
if (LLFile::stat(tmp_file, &s) == 0) // file exists
|
||||
{
|
||||
if (mLiveFile) mLiveFile->ignoreNextUpdate();
|
||||
writeToFile(tmp_file);
|
||||
}
|
||||
}
|
||||
std::string utf8text = mScriptEd->mEditor->getText();
|
||||
|
||||
// Special case for a completely empty script - stuff in one space so it can store properly. See SL-46889
|
||||
if ( utf8text.size() == 0 )
|
||||
{
|
||||
utf8text = " ";
|
||||
}
|
||||
|
||||
fputs(utf8text.c_str(), fp);
|
||||
fclose(fp);
|
||||
fp = NULL;
|
||||
|
||||
// save it out to asset server
|
||||
std::string url = object->getRegion()->getCapability("UpdateScriptTask");
|
||||
|
|
@ -1933,6 +1987,73 @@ void LLLiveLSLEditor::saveIfNeeded()
|
|||
}
|
||||
}
|
||||
|
||||
void LLLiveLSLEditor::openExternalEditor()
|
||||
{
|
||||
LLViewerObject* object = gObjectList.findObject(mObjectUUID);
|
||||
if(!object)
|
||||
{
|
||||
LLNotificationsUtil::add("SaveScriptFailObjectNotFound");
|
||||
return;
|
||||
}
|
||||
|
||||
delete mLiveFile; // deletes file
|
||||
|
||||
// Save the script to a temporary file.
|
||||
std::string filename = getTmpFileName();
|
||||
writeToFile(filename);
|
||||
|
||||
// Start watching file changes.
|
||||
mLiveFile = new LLLiveLSLFile(filename, this);
|
||||
mLiveFile->addToEventTimer();
|
||||
|
||||
// Open it in external editor.
|
||||
{
|
||||
LLExternalEditor ed;
|
||||
|
||||
if (!ed.setCommand("LL_SCRIPT_EDITOR"))
|
||||
{
|
||||
std::string msg = "Select an editor by setting the environment variable LL_SCRIPT_EDITOR "
|
||||
"or the ExternalEditor setting"; // *TODO: localize
|
||||
LLNotificationsUtil::add("GenericAlert", LLSD().with("MESSAGE", msg));
|
||||
return;
|
||||
}
|
||||
|
||||
ed.run(filename);
|
||||
}
|
||||
}
|
||||
|
||||
bool LLLiveLSLEditor::writeToFile(const std::string& filename)
|
||||
{
|
||||
LLFILE* fp = LLFile::fopen(filename, "wb");
|
||||
if (!fp)
|
||||
{
|
||||
llwarns << "Unable to write to " << filename << llendl;
|
||||
|
||||
LLSD row;
|
||||
row["columns"][0]["value"] = "Error writing to local file. Is your hard drive full?";
|
||||
row["columns"][0]["font"] = "SANSSERIF_SMALL";
|
||||
mScriptEd->mErrorList->addElement(row);
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string utf8text = mScriptEd->mEditor->getText();
|
||||
|
||||
// Special case for a completely empty script - stuff in one space so it can store properly. See SL-46889
|
||||
if (utf8text.size() == 0)
|
||||
{
|
||||
utf8text = " ";
|
||||
}
|
||||
|
||||
fputs(utf8text.c_str(), fp);
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string LLLiveLSLEditor::getTmpFileName()
|
||||
{
|
||||
return std::string(LLFile::tmpdir()) + "sl_script_" + mObjectUUID.asString() + ".lsl";
|
||||
}
|
||||
|
||||
void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url,
|
||||
const std::string& filename,
|
||||
const LLUUID& task_id,
|
||||
|
|
@ -2164,6 +2285,14 @@ void LLLiveLSLEditor::onSave(void* userdata, BOOL close_after_save)
|
|||
self->saveIfNeeded();
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void LLLiveLSLEditor::onEdit(void* userdata)
|
||||
{
|
||||
LLLiveLSLEditor* self = (LLLiveLSLEditor*)userdata;
|
||||
self->openExternalEditor();
|
||||
}
|
||||
|
||||
// static
|
||||
void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include "lliconctrl.h"
|
||||
#include "llframetimer.h"
|
||||
|
||||
class LLLiveLSLFile;
|
||||
class LLMessageSystem;
|
||||
class LLTextEditor;
|
||||
class LLButton;
|
||||
|
|
@ -62,6 +63,7 @@ public:
|
|||
const LLHandle<LLFloater>& floater_handle,
|
||||
void (*load_callback)(void* userdata),
|
||||
void (*save_callback)(void* userdata, BOOL close_after_save),
|
||||
void (*edit_callback)(void*),
|
||||
void (*search_replace_callback)(void* userdata),
|
||||
void* userdata,
|
||||
S32 bottom_pad = 0); // pad below bottom row of buttons
|
||||
|
|
@ -80,6 +82,8 @@ public:
|
|||
bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response);
|
||||
bool handleReloadFromServerDialog(const LLSD& notification, const LLSD& response);
|
||||
|
||||
void onEditButtonClick();
|
||||
|
||||
static void onCheckLock(LLUICtrl*, void*);
|
||||
static void onHelpComboCommit(LLUICtrl* ctrl, void* userdata);
|
||||
static void onClickBack(void* userdata);
|
||||
|
|
@ -114,6 +118,7 @@ private:
|
|||
LLTextEditor* mEditor;
|
||||
void (*mLoadCallback)(void* userdata);
|
||||
void (*mSaveCallback)(void* userdata, BOOL close_after_save);
|
||||
void (*mEditCallback)(void* userdata);
|
||||
void (*mSearchReplaceCallback) (void* userdata);
|
||||
void* mUserdata;
|
||||
LLComboBox *mFunctions;
|
||||
|
|
@ -179,6 +184,7 @@ protected:
|
|||
// Used to view and edit an LSL that is attached to an object.
|
||||
class LLLiveLSLEditor : public LLPreview
|
||||
{
|
||||
friend class LLLiveLSLFile;
|
||||
public:
|
||||
LLLiveLSLEditor(const LLSD& key);
|
||||
~LLLiveLSLEditor();
|
||||
|
|
@ -202,7 +208,10 @@ private:
|
|||
|
||||
virtual void loadAsset();
|
||||
void loadAsset(BOOL is_new);
|
||||
void saveIfNeeded();
|
||||
void saveIfNeeded(bool sync = true);
|
||||
void openExternalEditor();
|
||||
std::string getTmpFileName();
|
||||
bool writeToFile(const std::string& filename);
|
||||
void uploadAssetViaCaps(const std::string& url,
|
||||
const std::string& filename,
|
||||
const LLUUID& task_id,
|
||||
|
|
@ -218,6 +227,7 @@ private:
|
|||
static void onSearchReplace(void* userdata);
|
||||
static void onLoad(void* userdata);
|
||||
static void onSave(void* userdata, BOOL close_after_save);
|
||||
static void onEdit(void* userdata);
|
||||
|
||||
static void onLoadComplete(LLVFS *vfs, const LLUUID& asset_uuid,
|
||||
LLAssetType::EType type,
|
||||
|
|
@ -227,7 +237,7 @@ private:
|
|||
static void onRunningCheckboxClicked(LLUICtrl*, void* userdata);
|
||||
static void onReset(void* userdata);
|
||||
|
||||
// void loadScriptText(const std::string& filename); // unused
|
||||
bool loadScriptText(const std::string& filename);
|
||||
void loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type);
|
||||
|
||||
static void onErrorList(LLUICtrl*, void* user_data);
|
||||
|
|
@ -253,6 +263,7 @@ private:
|
|||
|
||||
LLCheckBoxCtrl* mMonoCheckbox;
|
||||
BOOL mIsModifiable;
|
||||
LLLiveLSLFile* mLiveFile;
|
||||
};
|
||||
|
||||
#endif // LL_LLPREVIEWSCRIPT_H
|
||||
|
|
|
|||
|
|
@ -399,9 +399,6 @@
|
|||
<color
|
||||
name="HighlightParentColor"
|
||||
value="0.67 0.83 0.96 1" />
|
||||
<color
|
||||
name="IMChatColor"
|
||||
reference="LtGray" />
|
||||
<color
|
||||
name="IMHistoryBgColor"
|
||||
reference="Unused?" />
|
||||
|
|
@ -766,9 +763,6 @@
|
|||
<color
|
||||
name="SysWellItemSelected"
|
||||
value="0.3 0.3 0.3 1.0" />
|
||||
<color
|
||||
name="ChatToastAgentNameColor"
|
||||
reference="EmphasisColor" />
|
||||
<color
|
||||
name="ColorSwatchBorderColor"
|
||||
value="0.45098 0.517647 0.607843 1"/>
|
||||
|
|
|
|||
|
|
@ -359,6 +359,18 @@
|
|||
<menu_item_check.on_check
|
||||
control="NavBarShowParcelProperties" />
|
||||
</menu_item_check>
|
||||
<menu_item_separator />
|
||||
<menu_item_check
|
||||
label="Advanced Menu"
|
||||
name="Show Advanced Menu"
|
||||
shortcut="control|alt|shift|D">
|
||||
<on_check
|
||||
function="CheckControl"
|
||||
parameter="UseDebugMenus" />
|
||||
<on_click
|
||||
function="ToggleControl"
|
||||
parameter="UseDebugMenus" />
|
||||
</menu_item_check>
|
||||
</menu>
|
||||
|
||||
<menu_item_separator/>
|
||||
|
|
@ -1642,6 +1654,18 @@
|
|||
<menu_item_call.on_click
|
||||
function="View.DefaultUISize" />
|
||||
</menu_item_call>
|
||||
<!-- This second, alternative shortcut for Show Advanced Menu is for backward compatibility. The main shortcut has been changed so it's Linux-friendly, where the old shortcut is typically eaten by the window manager. -->
|
||||
<menu_item_check
|
||||
label="Show Advanced Menu - legacy shortcut"
|
||||
name="Show Advanced Menu - legacy shortcut"
|
||||
shortcut="control|alt|D">
|
||||
<on_check
|
||||
function="CheckControl"
|
||||
parameter="UseDebugMenus" />
|
||||
<on_click
|
||||
function="ToggleControl"
|
||||
parameter="UseDebugMenus" />
|
||||
</menu_item_check>
|
||||
|
||||
<menu_item_separator/>
|
||||
|
||||
|
|
@ -1809,23 +1833,6 @@
|
|||
<menu_item_call.on_click
|
||||
function="View.ZoomOut" />
|
||||
</menu_item_call>
|
||||
<menu_item_separator
|
||||
visible="false"/>
|
||||
<!-- Made invisible to avoid a dissonance: menu item toggles the menu where it is located. EXT-8069.
|
||||
Can't be removed, to keep shortcut workable.
|
||||
-->
|
||||
<menu_item_check
|
||||
label="Show Advanced Menu"
|
||||
name="Show Advanced Menu"
|
||||
shortcut="control|alt|D"
|
||||
visible="false">
|
||||
<on_check
|
||||
function="CheckControl"
|
||||
parameter="UseDebugMenus" />
|
||||
<on_click
|
||||
function="ToggleControl"
|
||||
parameter="UseDebugMenus" />
|
||||
</menu_item_check>
|
||||
</menu> <!--Shortcuts-->
|
||||
|
||||
<menu_item_separator/>
|
||||
|
|
@ -1855,7 +1862,6 @@
|
|||
function="ToggleControl"
|
||||
parameter="QAMode" />
|
||||
</menu_item_check>
|
||||
|
||||
</menu>
|
||||
<menu
|
||||
create_jump_keys="true"
|
||||
|
|
|
|||
|
|
@ -113,22 +113,22 @@
|
|||
</text>
|
||||
<color_swatch
|
||||
can_apply_immediately="true"
|
||||
color="LtGray"
|
||||
color="EmphasisColor_35"
|
||||
follows="left|top"
|
||||
height="24"
|
||||
label_height="0"
|
||||
label_width="60"
|
||||
layout="topleft"
|
||||
left="360"
|
||||
name="im"
|
||||
name="objects"
|
||||
top_pad="-15"
|
||||
width="44">
|
||||
<color_swatch.init_callback
|
||||
function="Pref.getUIColor"
|
||||
parameter="IMChatColor" />
|
||||
parameter="ObjectChatColor" />
|
||||
<color_swatch.commit_callback
|
||||
function="Pref.applyUIColor"
|
||||
parameter="IMChatColor" />
|
||||
parameter="ObjectChatColor" />
|
||||
</color_swatch>
|
||||
<text
|
||||
type="string"
|
||||
|
|
@ -141,7 +141,7 @@
|
|||
name="text_box3"
|
||||
top_delta="5"
|
||||
width="95">
|
||||
IM
|
||||
Objects
|
||||
</text>
|
||||
<color_swatch
|
||||
can_apply_immediately="true"
|
||||
|
|
@ -206,37 +206,6 @@
|
|||
width="95">
|
||||
Errors
|
||||
</text>
|
||||
<color_swatch
|
||||
can_apply_immediately="true"
|
||||
color="EmphasisColor_35"
|
||||
follows="left|top"
|
||||
height="24"
|
||||
label_height="0"
|
||||
layout="topleft"
|
||||
left="360"
|
||||
name="objects"
|
||||
top_pad="-15"
|
||||
width="44" >
|
||||
<color_swatch.init_callback
|
||||
function="Pref.getUIColor"
|
||||
parameter="ObjectChatColor" />
|
||||
<color_swatch.commit_callback
|
||||
function="Pref.applyUIColor"
|
||||
parameter="ObjectChatColor" />
|
||||
</color_swatch>
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="left|top"
|
||||
height="10"
|
||||
layout="topleft"
|
||||
left_pad="5"
|
||||
mouse_opaque="false"
|
||||
name="text_box6"
|
||||
top_delta="5"
|
||||
width="95">
|
||||
Objects
|
||||
</text>
|
||||
<color_swatch
|
||||
can_apply_immediately="true"
|
||||
color="LtYellow"
|
||||
|
|
@ -305,7 +274,7 @@
|
|||
left="30"
|
||||
height="12"
|
||||
name="bubble_chat"
|
||||
top_pad="28"
|
||||
top_pad="20"
|
||||
width="120"
|
||||
>
|
||||
Bubble chat:
|
||||
|
|
@ -336,11 +305,58 @@
|
|||
height="16"
|
||||
increment="0.05"
|
||||
initial_value="1"
|
||||
label="Opacity"
|
||||
label="Opacity:"
|
||||
layout="topleft"
|
||||
left_pad="15"
|
||||
label_width="56"
|
||||
left_pad="10"
|
||||
label_width="70"
|
||||
name="bubble_chat_opacity"
|
||||
top_delta = "6"
|
||||
width="347" />
|
||||
width="378" />
|
||||
<text
|
||||
follows="left|top"
|
||||
layout="topleft"
|
||||
left="30"
|
||||
height="12"
|
||||
name="bubble_chat"
|
||||
top_pad="15"
|
||||
width="120"
|
||||
>
|
||||
Floater Opacity:
|
||||
</text>
|
||||
<slider
|
||||
can_edit_text="false"
|
||||
control_name="ActiveFloaterTransparency"
|
||||
decimal_digits="2"
|
||||
follows="left|top"
|
||||
height="16"
|
||||
increment="0.01"
|
||||
initial_value="0.8"
|
||||
layout="topleft"
|
||||
label_width="115"
|
||||
label="Active :"
|
||||
left="50"
|
||||
max_val="1.00"
|
||||
min_val="0.00"
|
||||
name="active"
|
||||
show_text="true"
|
||||
top_pad="5"
|
||||
width="415" />
|
||||
<slider
|
||||
can_edit_text="false"
|
||||
control_name="InactiveFloaterTransparency"
|
||||
decimal_digits="2"
|
||||
follows="left|top"
|
||||
height="16"
|
||||
increment="0.01"
|
||||
initial_value="0.5"
|
||||
layout="topleft"
|
||||
label_width="115"
|
||||
label="Inctive :"
|
||||
left="50"
|
||||
max_val="1.00"
|
||||
min_val="0.00"
|
||||
name="active"
|
||||
show_text="true"
|
||||
top_pad="5"
|
||||
width="415" />
|
||||
</panel>
|
||||
|
|
|
|||
|
|
@ -179,4 +179,13 @@
|
|||
right="487"
|
||||
name="Save_btn"
|
||||
width="81" />
|
||||
<button
|
||||
follows="right|bottom"
|
||||
height="23"
|
||||
label="Edit..."
|
||||
layout="topleft"
|
||||
top_pad="-23"
|
||||
right="400"
|
||||
name="Edit_btn"
|
||||
width="81" />
|
||||
</panel>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
#!/usr/bin/python
|
||||
"""\
|
||||
@file md5check.py
|
||||
@brief Replacement for message template compatibility verifier.
|
||||
|
||||
$LicenseInfo:firstyear=20i10&license=viewergpl$
|
||||
Copyright (c) 2010, Linden Research, Inc.
|
||||
|
||||
Second Life Viewer Source Code
|
||||
The source code in this file ("Source Code") is provided by Linden Lab
|
||||
to you under the terms of the GNU General Public License, version 2.0
|
||||
("GPL"), unless you have obtained a separate licensing agreement
|
||||
("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
|
||||
There are special exceptions to the terms and conditions of the GPL as
|
||||
it is applied to this Source Code. View the full text of the exception
|
||||
in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
online at
|
||||
http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
|
||||
By copying, modifying or distributing this software, you acknowledge
|
||||
that you have read and understood your obligations described above,
|
||||
and agree to abide by those obligations.
|
||||
|
||||
ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
COMPLETENESS OR PERFORMANCE.
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
import sys
|
||||
import hashlib
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
print """Usage: %s --create|<hash-digest> <file>
|
||||
|
||||
Creates an md5sum hash digest of the specified file content
|
||||
and compares it with the given hash digest.
|
||||
|
||||
If --create is used instead of a hash digest, it will simply
|
||||
print out the hash digest of specified file content.
|
||||
""" % sys.argv[0]
|
||||
sys.exit(1)
|
||||
|
||||
if sys.argv[2] == '-':
|
||||
fh = sys.stdin
|
||||
filename = "<stdin>"
|
||||
else:
|
||||
filename = sys.argv[2]
|
||||
fh = open(filename)
|
||||
|
||||
hexdigest = hashlib.md5(fh.read()).hexdigest()
|
||||
if sys.argv[1] == '--create':
|
||||
print hexdigest
|
||||
elif hexdigest == sys.argv[1]:
|
||||
print "md5sum check passed:", filename
|
||||
else:
|
||||
print "md5sum check FAILED:", filename
|
||||
sys.exit(1)
|
||||
Loading…
Reference in New Issue