Move AIAlert* into namespace AIAlert and rename classes.

Instead of having several AI* classes, it turned out to be easier to
have a namespace: this allows me to define the classes in llcommon but
add (new) 'add' and 'add_modal' functions to 'AIAlert' in llui.
This is needed to avoid a collision with the 'add' functions in
LLNotificationsUtil.

The new add/add_modal makes it a lot easier to just show a caught
alert, prepending or appending new text: it turns out that that is
way more common then a re-throw.

Adjusted code as appropriate.
This commit is contained in:
Aleric Inglewood
2013-11-05 22:30:02 +01:00
parent 8ab9039ff6
commit c516a71804
14 changed files with 300 additions and 230 deletions

View File

@@ -25,43 +25,51 @@
* *
* 02/11/2013 * 02/11/2013
* - Initial version, written by Aleric Inglewood @ SL * - Initial version, written by Aleric Inglewood @ SL
*
* 05/11/2013
* Moved everything in namespace AIAlert, except AIArgs.
*/ */
#include "aialert.h" #include "aialert.h"
AIAlert::AIAlert(AIAlertPrefix const& prefix, modal_nt type, namespace AIAlert
std::string const& xml_desc, AIArgs const& args) : mModal(type)
{ {
if (prefix) mLines.push_back(AIAlertLine(prefix));
mLines.push_back(AIAlertLine(xml_desc, args)); Error::Error(Prefix const& prefix, modal_nt type,
std::string const& xml_desc, AIArgs const& args) : mModal(type)
{
if (prefix) mLines.push_back(Line(prefix));
mLines.push_back(Line(xml_desc, args));
} }
AIAlert::AIAlert(AIAlertPrefix const& prefix, modal_nt type, Error::Error(Prefix const& prefix, modal_nt type,
AIAlert const& alert, Error const& alert,
std::string const& xml_desc, AIArgs const& args) : mLines(alert.mLines), mModal(type) std::string const& xml_desc, AIArgs const& args) : mLines(alert.mLines), mModal(type)
{ {
if (alert.mModal == modal) mModal = modal; if (alert.mModal == modal) mModal = modal;
if (prefix) mLines.push_back(AIAlertLine(prefix, !mLines.empty())); if (prefix) mLines.push_back(Line(prefix, !mLines.empty()));
mLines.push_back(AIAlertLine(xml_desc, args)); mLines.push_back(Line(xml_desc, args));
} }
AIAlert::AIAlert(AIAlertPrefix const& prefix, modal_nt type, Error::Error(Prefix const& prefix, modal_nt type,
std::string const& xml_desc, std::string const& xml_desc,
AIAlert const& alert) : mLines(alert.mLines), mModal(type) Error const& alert) : mLines(alert.mLines), mModal(type)
{ {
if (alert.mModal == modal) mModal = modal; if (alert.mModal == modal) mModal = modal;
if (!mLines.empty()) { mLines.front().set_newline(); } if (!mLines.empty()) { mLines.front().set_newline(); }
mLines.push_front(AIAlertLine(xml_desc)); mLines.push_front(Line(xml_desc));
if (prefix) mLines.push_front(AIAlertLine(prefix)); if (prefix) mLines.push_front(Line(prefix));
} }
AIAlert::AIAlert(AIAlertPrefix const& prefix, modal_nt type, Error::Error(Prefix const& prefix, modal_nt type,
std::string const& xml_desc, AIArgs const& args, std::string const& xml_desc, AIArgs const& args,
AIAlert const& alert) : mLines(alert.mLines), mModal(type) Error const& alert) : mLines(alert.mLines), mModal(type)
{ {
if (alert.mModal == modal) mModal = modal; if (alert.mModal == modal) mModal = modal;
if (!mLines.empty()) { mLines.front().set_newline(); } if (!mLines.empty()) { mLines.front().set_newline(); }
mLines.push_front(AIAlertLine(xml_desc, args)); mLines.push_front(Line(xml_desc, args));
if (prefix) mLines.push_front(AIAlertLine(prefix)); if (prefix) mLines.push_front(Line(prefix));
} }
} // namespace AIAlert

View File

@@ -1,6 +1,6 @@
/** /**
* @file aialert.h * @file aialert.h
* @brief Declaration of AIArgs, AIAlertPrefix, AIAlertLine, AIAlert and AIAlertCode * @brief Declaration of AIArgs and AIAlert classes.
* *
* Copyright (c) 2013, Aleric Inglewood. * Copyright (c) 2013, Aleric Inglewood.
* *
@@ -26,6 +26,9 @@
* *
* 02/11/2013 * 02/11/2013
* Initial version, written by Aleric Inglewood @ SL * Initial version, written by Aleric Inglewood @ SL
*
* 05/11/2013
* Moved everything in namespace AIAlert, except AIArgs.
*/ */
#ifndef AI_ALERT #ifndef AI_ALERT
@@ -40,28 +43,28 @@
// Facility to throw errors that can easily be converted to an informative pop-up floater for the user. // Facility to throw errors that can easily be converted to an informative pop-up floater for the user.
// Throw arbitrary class. // Throw arbitrary class.
#define THROW_ALERT_CLASS(Alert, ...) throw Alert(AIAlertPrefix(), AIAlert::not_modal, __VA_ARGS__) #define THROW_ALERT_CLASS(Alert, ...) throw Alert(AIAlert::Prefix(), AIAlert::not_modal, __VA_ARGS__)
#define THROW_MALERT_CLASS(Alert, ...) throw Alert(AIAlertPrefix(), AIAlert::modal, __VA_ARGS__) #define THROW_MALERT_CLASS(Alert, ...) throw Alert(AIAlert::Prefix(), AIAlert::modal, __VA_ARGS__)
#define THROW_FALERT_CLASS(Alert, ...) throw Alert(AIAlertPrefix(__PRETTY_FUNCTION__, alert_line_pretty_function_prefix), AIAlert::not_modal, __VA_ARGS__) #define THROW_FALERT_CLASS(Alert, ...) throw Alert(AIAlert::Prefix(__PRETTY_FUNCTION__, AIAlert::pretty_function_prefix), AIAlert::not_modal, __VA_ARGS__)
#define THROW_FMALERT_CLASS(Alert, ...) throw Alert(AIAlertPrefix(__PRETTY_FUNCTION__, alert_line_pretty_function_prefix), AIAlert::modal, __VA_ARGS__) #define THROW_FMALERT_CLASS(Alert, ...) throw Alert(AIAlert::Prefix(__PRETTY_FUNCTION__, AIAlert::pretty_function_prefix), AIAlert::modal, __VA_ARGS__)
// Shortcut to throw AIAlert. // Shortcut to throw AIAlert::Error.
#define THROW_ALERT(...) THROW_ALERT_CLASS(AIAlert, __VA_ARGS__) #define THROW_ALERT(...) THROW_ALERT_CLASS(AIAlert::Error, __VA_ARGS__)
#define THROW_MALERT(...) THROW_MALERT_CLASS(AIAlert, __VA_ARGS__) #define THROW_MALERT(...) THROW_MALERT_CLASS(AIAlert::Error, __VA_ARGS__)
#define THROW_FALERT(...) THROW_FALERT_CLASS(AIAlert, __VA_ARGS__) #define THROW_FALERT(...) THROW_FALERT_CLASS(AIAlert::Error, __VA_ARGS__)
#define THROW_FMALERT(...) THROW_FMALERT_CLASS(AIAlert, __VA_ARGS__) #define THROW_FMALERT(...) THROW_FMALERT_CLASS(AIAlert::Error, __VA_ARGS__)
// Shortcut to throw AIAlertCode. // Shortcut to throw AIAlert::ErrorCode.
#define THROW_ALERTC(...) THROW_ALERT_CLASS(AIAlertCode, __VA_ARGS__) #define THROW_ALERTC(...) THROW_ALERT_CLASS(AIAlert::ErrorCode, __VA_ARGS__)
#define THROW_MALERTC(...) THROW_MALERT_CLASS(AIAlertCode, __VA_ARGS__) #define THROW_MALERTC(...) THROW_MALERT_CLASS(AIAlert::ErrorCode, __VA_ARGS__)
#define THROW_FALERTC(...) THROW_FALERT_CLASS(AIAlertCode, __VA_ARGS__) #define THROW_FALERTC(...) THROW_FALERT_CLASS(AIAlert::ErrorCode, __VA_ARGS__)
#define THROW_FMALERTC(...) THROW_FMALERT_CLASS(AIAlertCode, __VA_ARGS__) #define THROW_FMALERTC(...) THROW_FMALERT_CLASS(AIAlert::ErrorCode, __VA_ARGS__)
// Shortcut to throw AIAlertCode with errno as code. // Shortcut to throw AIAlert::ErrorCode with errno as code.
#define THROW_ALERTE(...) do { int errn = errno; THROW_ALERT_CLASS(AIAlertCode, errn, __VA_ARGS__); } while(0) #define THROW_ALERTE(...) do { int errn = errno; THROW_ALERT_CLASS(AIAlert::ErrorCode, errn, __VA_ARGS__); } while(0)
#define THROW_MALERTE(...) do { int errn = errno; THROW_MALERT_CLASS(AIAlertCode, errn, __VA_ARGS__); } while(0) #define THROW_MALERTE(...) do { int errn = errno; THROW_MALERT_CLASS(AIAlert::ErrorCode, errn, __VA_ARGS__); } while(0)
#define THROW_FALERTE(...) do { int errn = errno; THROW_FALERT_CLASS(AIAlertCode, errn, __VA_ARGS__); } while(0) #define THROW_FALERTE(...) do { int errn = errno; THROW_FALERT_CLASS(AIAlert::ErrorCode, errn, __VA_ARGS__); } while(0)
#define THROW_FMALERTE(...) do { int errn = errno; THROW_FMALERT_CLASS(AIAlertCode, errn, __VA_ARGS__); } while(0) #define THROW_FMALERTE(...) do { int errn = errno; THROW_FMALERT_CLASS(AIAlert::ErrorCode, errn, __VA_ARGS__); } while(0)
// Examples // Examples
@@ -70,18 +73,18 @@
//---------------------------------------------------------- //----------------------------------------------------------
// To show the alert box: // To show the alert box:
catch (AIAlert const& alert) catch (AIAlert::Error const& error)
{ {
LLNotificationsUtil::add(alert); // Optionally pass alert_line_pretty_function_prefix as second parameter to *suppress* that output. AIAlert::add(error); // Optionally pass pretty_function_prefix as second parameter to *suppress* that output.
} }
// or, for example // or, for example
catch (AIAlertCode const& alert) catch (AIAlert::ErrorCode const& error)
{ {
if (alert.getCode() != EEXIST) if (error.getCode() != EEXIST)
{ {
LLNotificationsUtil::add(alert, alert_line_pretty_function_prefix); AIAlert::add(alert, AIAlert::pretty_function_prefix);
} }
} }
//---------------------------------------------------------- //----------------------------------------------------------
@@ -89,15 +92,15 @@
THROW_ALERT("ExampleKey"); // A) Lookup "ExampleKey" in strings.xml and show translation. THROW_ALERT("ExampleKey"); // A) Lookup "ExampleKey" in strings.xml and show translation.
THROW_ALERT("ExampleKey", AIArgs("[FIRST]", first)("[SECOND]", second)(...etc...)); // B) Same as A, but replace [FIRST] with first, [SECOND] with second, etc. THROW_ALERT("ExampleKey", AIArgs("[FIRST]", first)("[SECOND]", second)(...etc...)); // B) Same as A, but replace [FIRST] with first, [SECOND] with second, etc.
THROW_ALERT("ExampleKey", alert); // C) As A, but followed by a colon and a newline, and then the text of 'alert'. THROW_ALERT("ExampleKey", error); // C) As A, but followed by a colon and a newline, and then the text of 'error'.
THROW_ALERT(alert, "ExampleKey"); // D) The text of 'alert', followed by a colon and a newline and then as A. THROW_ALERT(error, "ExampleKey"); // D) The text of 'error', followed by a colon and a newline and then as A.
THROW_ALERT("ExampleKey", AIArgs("[FIRST]", first)("[SECOND]", second), alert); // E) As B, but followed by a colon and a newline, and then the text of 'alert'. THROW_ALERT("ExampleKey", AIArgs("[FIRST]", first)("[SECOND]", second), error); // E) As B, but followed by a colon and a newline, and then the text of 'error'.
THROW_ALERT(alert, "ExampleKey", AIArgs("[FIRST]", first)("[SECOND]", second)); // F) The text of 'alert', followed by a colon and a newline and then as B. THROW_ALERT(error, "ExampleKey", AIArgs("[FIRST]", first)("[SECOND]", second)); // F) The text of 'error', followed by a colon and a newline and then as B.
// where 'alert' is a caught AIAlert object (as above) in a rethrow. // where 'error' is a caught Error object (as above) in a rethrow.
// Prepend ALERT with M and/or F to make the alert box Modal and/or prepend the text with the current function name. // Prepend ALERT with M and/or F to make the alert box Modal and/or prepend the text with the current function name.
// For example, // For example,
THROW_MFALERT("ExampleKey", AIArgs("[FIRST]", first)); // Throw a Modal alert box that is prefixed with the current Function name. THROW_MFALERT("ExampleKey", AIArgs("[FIRST]", first)); // Throw a Modal alert box that is prefixed with the current Function name.
// Append E after ALERT to throw an AIAlertCode class that contains the current errno. // Append E after ALERT to throw an ErrorCode class that contains the current errno.
// For example, // For example,
THROW_FALERTE("ExampleKey", AIArgs("[FIRST]", first)); // Throw an alert box that is prefixed with the current Function name and pass errno to the catcher. THROW_FALERTE("ExampleKey", AIArgs("[FIRST]", first)); // Throw an alert box that is prefixed with the current Function name and pass errno to the catcher.
@@ -106,34 +109,6 @@
// //
//=================================================================================================================================== //===================================================================================================================================
enum alert_line_type_nt
{
alert_line_normal = 0,
alert_line_empty_prefix = 1,
alert_line_pretty_function_prefix = 2
// These must exist of single bits (a mask).
};
// An AIAlertPrefix currently comes only in two flavors:
//
// alert_line_empty_prefix : An empty prefix.
// alert_line_pretty_function_prefix : A function name prefix, this is the function from which the alert was thrown.
class LL_COMMON_API AIAlertPrefix
{
public:
AIAlertPrefix(void) : mType(alert_line_empty_prefix) { }
AIAlertPrefix(char const* str, alert_line_type_nt type) : mStr(str), mType(type) { }
operator bool(void) const { return mType != alert_line_empty_prefix; }
alert_line_type_nt type(void) const { return mType; }
std::string const& str(void) const { return mStr; }
private:
std::string mStr; // Literal text. For example a C++ function name.
alert_line_type_nt mType; // The type of this prefix.
};
// A wrapper around LLStringUtil::format_map_t to allow constructing a dictionary // A wrapper around LLStringUtil::format_map_t to allow constructing a dictionary
// on one line by doing: // on one line by doing:
// //
@@ -158,25 +133,62 @@ class LL_COMMON_API AIArgs
LLStringUtil::format_map_t const& operator*() const { return mArgs; } LLStringUtil::format_map_t const& operator*() const { return mArgs; }
}; };
namespace AIAlert
{
enum modal_nt
{
not_modal,
modal
};
enum alert_line_type_nt
{
normal = 0,
empty_prefix = 1,
pretty_function_prefix = 2
// These must exist of single bits (a mask).
};
// An Prefix currently comes only in two flavors:
//
// empty_prefix : An empty prefix.
// pretty_function_prefix : A function name prefix, this is the function from which the alert was thrown.
class LL_COMMON_API Prefix
{
public:
Prefix(void) : mType(empty_prefix) { }
Prefix(char const* str, alert_line_type_nt type) : mStr(str), mType(type) { }
operator bool(void) const { return mType != empty_prefix; }
alert_line_type_nt type(void) const { return mType; }
std::string const& str(void) const { return mStr; }
private:
std::string mStr; // Literal text. For example a C++ function name.
alert_line_type_nt mType; // The type of this prefix.
};
// A class that represents one line with its replacements. // A class that represents one line with its replacements.
// The string mXmlDesc shall be looked up in strings.xml. // The string mXmlDesc shall be looked up in strings.xml.
// This is not done as part of this class because LLTrans::getString // This is not done as part of this class because LLTrans::getString
// is not part of llcommon. // is not part of llcommon.
class LL_COMMON_API AIAlertLine class LL_COMMON_API Line
{ {
private: private:
bool mNewline; // Prepend this line with a newline if set. bool mNewline; // Prepend this line with a newline if set.
std::string mXmlDesc; // The keyword to look up in string.xml. std::string mXmlDesc; // The keyword to look up in string.xml.
AIArgs mArgs; // Replacement map. AIArgs mArgs; // Replacement map.
alert_line_type_nt mType; // The type of this line: alert_line_normal for normal lines, other for prefixes. alert_line_type_nt mType; // The type of this line: normal for normal lines, other for prefixes.
public: public:
AIAlertLine(std::string const& xml_desc, bool newline = false) : mNewline(newline), mXmlDesc(xml_desc), mType(alert_line_normal) { } Line(std::string const& xml_desc, bool newline = false) : mNewline(newline), mXmlDesc(xml_desc), mType(normal) { }
AIAlertLine(std::string const& xml_desc, AIArgs const& args, bool newline = false) : mNewline(newline), mXmlDesc(xml_desc), mArgs(args), mType(alert_line_normal) { } Line(std::string const& xml_desc, AIArgs const& args, bool newline = false) : mNewline(newline), mXmlDesc(xml_desc), mArgs(args), mType(normal) { }
AIAlertLine(AIAlertPrefix const& prefix, bool newline = false) : mNewline(newline), mXmlDesc("AIPrefix"), mArgs("[PREFIX]", prefix.str()), mType(prefix.type()) { } Line(Prefix const& prefix, bool newline = false) : mNewline(newline), mXmlDesc("AIPrefix"), mArgs("[PREFIX]", prefix.str()), mType(prefix.type()) { }
// The destructor may not throw. // The destructor may not throw.
~AIAlertLine() throw() { } ~Line() throw() { }
// Prepend a newline before this line. // Prepend a newline before this line.
void set_newline(void) { mNewline = true; } void set_newline(void) { mNewline = true; }
@@ -188,7 +200,7 @@ class LL_COMMON_API AIAlertLine
// Accessors. // Accessors.
bool suppressed(unsigned int suppress_mask) const { return (suppress_mask & mType) != 0; } bool suppressed(unsigned int suppress_mask) const { return (suppress_mask & mType) != 0; }
bool is_prefix(void) const { return mType != alert_line_normal; } bool is_prefix(void) const { return mType != normal; }
}; };
// This class is used to throw an error that will cause // This class is used to throw an error that will cause
@@ -200,82 +212,82 @@ class LL_COMMON_API AIAlertLine
// The class represents multiple lines, each line is to be translated and catenated, // The class represents multiple lines, each line is to be translated and catenated,
// separated by newlines, and then written to an alert box. This is not done as part // separated by newlines, and then written to an alert box. This is not done as part
// of this class because LLTrans::getString and LLNotification is not part of llcommon. // of this class because LLTrans::getString and LLNotification is not part of llcommon.
// Instead call LLNotificationUtil::add(AIAlert const&). // Instead call LLNotificationUtil::add(Error const&).
class LL_COMMON_API AIAlert : public std::exception class LL_COMMON_API Error : public std::exception
{ {
public: public:
typedef std::deque<AIAlertLine> lines_type; typedef std::deque<Line> lines_type;
enum modal_nt { not_modal, modal };
// The destructor may not throw. // The destructor may not throw.
~AIAlert() throw() { } ~Error() throw() { }
// Accessors. // Accessors.
lines_type const& lines(void) const { return mLines; } lines_type const& lines(void) const { return mLines; }
bool is_modal(void) const { return mModal == modal; } bool is_modal(void) const { return mModal == modal; }
// A string with zero or more replacements. // A string with zero or more replacements.
AIAlert(AIAlertPrefix const& prefix, modal_nt modal, Error(Prefix const& prefix, modal_nt type,
std::string const& xml_desc, AIArgs const& args = AIArgs()); std::string const& xml_desc, AIArgs const& args = AIArgs());
// Same as above bit prepending the message with the text of another alert. // Same as above bit prepending the message with the text of another alert.
AIAlert(AIAlertPrefix const& prefix, modal_nt modal, Error(Prefix const& prefix, modal_nt type,
AIAlert const& alert, Error const& alert,
std::string const& xml_desc, AIArgs const& args = AIArgs()); std::string const& xml_desc, AIArgs const& args = AIArgs());
// Same as above but appending the message with the text of another alert. // Same as above but appending the message with the text of another alert.
// (no args) // (no args)
AIAlert(AIAlertPrefix const& prefix, modal_nt modal, Error(Prefix const& prefix, modal_nt type,
std::string const& xml_desc, std::string const& xml_desc,
AIAlert const& alert); Error const& alert);
// (with args) // (with args)
AIAlert(AIAlertPrefix const& prefix, modal_nt modal, Error(Prefix const& prefix, modal_nt type,
std::string const& xml_desc, AIArgs const& args, std::string const& xml_desc, AIArgs const& args,
AIAlert const& alert); Error const& alert);
private: private:
lines_type mLines; // The lines (or prefixes) of text to be displayed, each consisting on a keyword (to be looked up in strings.xml) and a replacement map. lines_type mLines; // The lines (or prefixes) of text to be displayed, each consisting on a keyword (to be looked up in strings.xml) and a replacement map.
modal_nt mModal; // If true, make the alert box a modal floater. modal_nt mModal; // If true, make the alert box a modal floater.
}; };
// Same as AIAlert but allows to pass an additional error code. // Same as Error but allows to pass an additional error code.
class LL_COMMON_API AIAlertCode : public AIAlert class LL_COMMON_API ErrorCode : public Error
{ {
private: private:
int mCode; int mCode;
public: public:
// The destructor may not throw. // The destructor may not throw.
~AIAlertCode() throw() { } ~ErrorCode() throw() { }
// Accessor. // Accessor.
int getCode(void) const { return mCode; } int getCode(void) const { return mCode; }
// A string with zero or more replacements. // A string with zero or more replacements.
AIAlertCode(AIAlertPrefix const& prefix, modal_nt modal, int code, ErrorCode(Prefix const& prefix, modal_nt type, int code,
std::string const& xml_desc, AIArgs const& args = AIArgs()) : std::string const& xml_desc, AIArgs const& args = AIArgs()) :
AIAlert(prefix, modal, xml_desc, args) { } Error(prefix, modal, xml_desc, args) { }
// Same as above bit prepending the message with the text of another alert. // Same as above bit prepending the message with the text of another alert.
AIAlertCode(AIAlertPrefix const& prefix, modal_nt modal, int code, ErrorCode(Prefix const& prefix, modal_nt type, int code,
AIAlert const& alert, Error const& alert,
std::string const& xml_desc, AIArgs const& args = AIArgs()) : std::string const& xml_desc, AIArgs const& args = AIArgs()) :
AIAlert(prefix, modal, alert, xml_desc, args) { } Error(prefix, modal, alert, xml_desc, args) { }
// Same as above but appending the message with the text of another alert. // Same as above but appending the message with the text of another alert.
// (no args) // (no args)
AIAlertCode(AIAlertPrefix const& prefix, modal_nt modal, int code, ErrorCode(Prefix const& prefix, modal_nt type, int code,
std::string const& xml_desc, std::string const& xml_desc,
AIAlert const& alert) : Error const& alert) :
AIAlert(prefix, modal, xml_desc, alert) { } Error(prefix, modal, xml_desc, alert) { }
// (with args) // (with args)
AIAlertCode(AIAlertPrefix const& prefix, modal_nt modal, int code, ErrorCode(Prefix const& prefix, modal_nt type, int code,
std::string const& xml_desc, AIArgs const& args, std::string const& xml_desc, AIArgs const& args,
AIAlert const& alert) : Error const& alert) :
AIAlert(prefix, modal, xml_desc, args, alert) { } Error(prefix, modal, xml_desc, args, alert) { }
}; };
} // namespace AIAlert
#endif // AI_ALERT #endif // AI_ALERT

View File

@@ -55,7 +55,7 @@ AIFile::~AIFile()
int errn = errno; \ int errn = errno; \
std::ostringstream error; \ std::ostringstream error; \
error << LLFile::strerr(errn) << " (" << errn << ')'; \ error << LLFile::strerr(errn) << " (" << errn << ')'; \
THROW_MALERT_CLASS(AIAlertCode, errn, __VA_ARGS__ ("[ERROR]", error.str())); \ THROW_MALERT_CLASS(AIAlert::ErrorCode, errn, __VA_ARGS__ ("[ERROR]", error.str())); \
} while(0) } while(0)
//static //static

View File

@@ -1480,12 +1480,12 @@ LLNotificationPtr LLNotifications::add(const LLNotification::Params& p)
return pNotif; return pNotif;
} }
LLNotificationPtr LLNotifications::add(AIAlert const& alert, unsigned int suppress_mask) LLNotificationPtr LLNotifications::add(AIAlert::Error const& error, int type, unsigned int suppress_mask)
{ {
std::string alert_text; std::string alert_text;
bool suppress_newlines = false; bool suppress_newlines = false;
bool last_was_prefix = false; bool last_was_prefix = false;
for (AIAlert::lines_type::const_iterator line = alert.lines().begin(); line != alert.lines().end(); ++line) for (AIAlert::Error::lines_type::const_iterator line = error.lines().begin(); line != error.lines().end(); ++line)
{ {
// Even if a line is suppressed, we print its leading newline if requested, but never more than one. // Even if a line is suppressed, we print its leading newline if requested, but never more than one.
if (!suppress_newlines && line->prepend_newline()) if (!suppress_newlines && line->prepend_newline())
@@ -1503,7 +1503,7 @@ LLNotificationPtr LLNotifications::add(AIAlert const& alert, unsigned int suppre
} }
LLSD substitutions = LLSD::emptyMap(); LLSD substitutions = LLSD::emptyMap();
substitutions["[PAYLOAD]"] = alert_text; substitutions["[PAYLOAD]"] = alert_text;
return add(LLNotification::Params(alert.is_modal() ? "AIAlertModal" : "AIAlert").substitutions(substitutions)); return add(LLNotification::Params((type == AIAlert::modal || error.is_modal()) ? "AIAlertModal" : "AIAlert").substitutions(substitutions));
} }

View File

@@ -108,7 +108,7 @@
#include "llnotificationptr.h" #include "llnotificationptr.h"
#include "llnotificationcontext.h" #include "llnotificationcontext.h"
class AIAlert; namespace AIAlert { class Error; }
typedef enum e_notification_priority typedef enum e_notification_priority
{ {
@@ -739,7 +739,7 @@ public:
const LLSD& substitutions, const LLSD& substitutions,
const LLSD& payload, const LLSD& payload,
LLNotificationFunctorRegistry::ResponseFunctor functor); LLNotificationFunctorRegistry::ResponseFunctor functor);
LLNotificationPtr add(AIAlert const& alert, unsigned int suppress_mask); LLNotificationPtr add(AIAlert::Error const& error, int type, unsigned int suppress_mask);
LLNotificationPtr add(const LLNotification::Params& p); LLNotificationPtr add(const LLNotification::Params& p);
void forceResponse(const LLNotification::Params& params, S32 option); void forceResponse(const LLNotification::Params& params, S32 option);

View File

@@ -30,11 +30,46 @@
#include "llsd.h" #include "llsd.h"
#include "llxmlnode.h" // apparently needed to call LLNotifications::instance() #include "llxmlnode.h" // apparently needed to call LLNotifications::instance()
LLNotificationPtr LLNotificationsUtil::add(AIAlert const& alert, unsigned int suppress_mask) namespace AIAlert
{ {
return LLNotifications::instance().add(alert, suppress_mask);
LLNotificationPtr add(Error const& error, modal_nt type, unsigned int suppress_mask)
{
return LLNotifications::instance().add(error, type, suppress_mask);
} }
LLNotificationPtr add(std::string const& xml_desc, modal_nt type)
{
return LLNotifications::instance().add(Error(Prefix(), type, xml_desc, AIArgs()), type, 0);
}
LLNotificationPtr add(std::string const& xml_desc, AIArgs const& args, modal_nt type)
{
return LLNotifications::instance().add(Error(Prefix(), type, xml_desc, args), type, 0);
}
LLNotificationPtr add(Error const& error, std::string const& xml_desc, unsigned int suppress_mask, modal_nt type)
{
return LLNotifications::instance().add(Error(Prefix(), type, error, xml_desc, AIArgs()), type, suppress_mask);
}
LLNotificationPtr add(Error const& error, std::string const& xml_desc, AIArgs const& args, unsigned int suppress_mask, modal_nt type)
{
return LLNotifications::instance().add(Error(Prefix(), type, error, xml_desc, args), type, suppress_mask);
}
LLNotificationPtr add(std::string const& xml_desc, Error const& error, unsigned int suppress_mask, modal_nt type)
{
return LLNotifications::instance().add(Error(Prefix(), type, xml_desc, AIArgs(), error), type, suppress_mask);
}
LLNotificationPtr add(std::string const& xml_desc, AIArgs const& args, Error const& error, unsigned int suppress_mask, modal_nt type)
{
return LLNotifications::instance().add(Error(Prefix(), type, xml_desc, args, error), type, suppress_mask);
}
} // namespace AIAlert
LLNotificationPtr LLNotificationsUtil::add(const std::string& name) LLNotificationPtr LLNotificationsUtil::add(const std::string& name)
{ {
return LLNotifications::instance().add( return LLNotifications::instance().add(

View File

@@ -30,16 +30,53 @@
// to avoid including the heavyweight llnotifications.h // to avoid including the heavyweight llnotifications.h
#include "llnotificationptr.h" #include "llnotificationptr.h"
#include "aialert.h"
#include <boost/function.hpp> #include <boost/function.hpp>
class LLSD; class LLSD;
class AIAlert;
namespace AIAlert
{
// Add an alert directly to LLNotifications.
// Look up xml_desc in strings.xml.
LLNotificationPtr add(std::string const& xml_desc,
modal_nt type = not_modal);
// ... with replacement args.
LLNotificationPtr add(std::string const& xml_desc, AIArgs const& args,
modal_nt type = not_modal);
// Append it to an existing alert error.
LLNotificationPtr add(Error const& error,
std::string const& xml_desc,
unsigned int suppress_mask = 0, modal_nt type = not_modal);
LLNotificationPtr add(Error const& error,
std::string const& xml_desc, AIArgs const& args,
unsigned int suppress_mask = 0, modal_nt type = not_modal);
// Prepend it to an existing alert error.
LLNotificationPtr add(std::string const& xml_desc,
Error const& error,
unsigned int suppress_mask = 0, modal_nt type = not_modal);
LLNotificationPtr add(std::string const& xml_desc, AIArgs const& args,
Error const& error,
unsigned int suppress_mask = 0, modal_nt type = not_modal);
// Just show the caught alert error.
LLNotificationPtr add(Error const& error,
modal_nt type = not_modal, unsigned int suppress_mask = 0);
// Short cuts for enforcing modal alerts.
inline LLNotificationPtr add_modal(std::string const& xml_desc) { return add(xml_desc, modal); }
inline LLNotificationPtr add_modal(std::string const& xml_desc, AIArgs const& args) { return add(xml_desc, args, modal); }
inline LLNotificationPtr add_modal(Error const& error, std::string const& xml_desc, unsigned int suppress_mask = 0) { return add(error, xml_desc, suppress_mask, modal); }
inline LLNotificationPtr add_modal(Error const& error, std::string const& xml_desc, AIArgs const& args, unsigned int suppress_mask = 0) { return add(error, xml_desc, args, suppress_mask, modal); }
inline LLNotificationPtr add_modal(std::string const& xml_desc, Error const& error, unsigned int suppress_mask = 0) { return add(xml_desc, error, suppress_mask, modal); }
inline LLNotificationPtr add_modal(std::string const& xml_desc, AIArgs const& args, Error const& error, unsigned int suppress_mask = 0) { return add(xml_desc, args, error, suppress_mask, modal); }
}
namespace LLNotificationsUtil namespace LLNotificationsUtil
{ {
LLNotificationPtr add(AIAlert const& alert, unsigned int suppress_mask = 0); // Singu extension.
LLNotificationPtr add(const std::string& name); LLNotificationPtr add(const std::string& name);
LLNotificationPtr add(const std::string& name, LLNotificationPtr add(const std::string& name,

View File

@@ -336,8 +336,7 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker)
std::string const filename = filepicker->getFilename(); std::string const filename = filepicker->getFilename();
LLSD args(LLSD::emptyMap()); AIArgs args("[FILE]", gDirUtilp->getBaseFileName(filename));
args["FILE"] = gDirUtilp->getBaseFileName(filename);
bool found_param = false; bool found_param = false;
bool found_texture = false; bool found_texture = false;
@@ -362,11 +361,7 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker)
if (!LLStringUtil::convertToU32(metaversion, metaversion_major) || metaversion_major > 1) if (!LLStringUtil::convertToU32(metaversion, metaversion_major) || metaversion_major > 1)
{ {
llwarns << "Invalid or incompatible linden_genepool metaversion: " << metaversion << " in file: " << filename << llendl; THROW_MALERT("AIXMLImportRootVersionError", args("[TAG]", "metaversion")("[VERSIONMAJOR]", "1"));
args["TAG"] = "metaversion";
args["VERSIONMAJOR"] = "1";
LLNotificationsUtil::add("AIXMLImportRootVersionError", args);
return;
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@@ -436,9 +431,9 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker)
} }
} }
} }
catch (AIAlert const& alert) catch (AIAlert::Error const& error)
{ {
LLNotificationsUtil::add(AIAlert(AIAlertPrefix(), AIAlert::modal, "AIXMLImportError", AIArgs("[TYPE]", label), alert)); AIAlert::add_modal("AIXMLImportError", AIArgs("[TYPE]", label), error);
return; return;
} }
@@ -449,28 +444,25 @@ void LLFloaterCustomize::onBtnImport_continued(AIFilePicker* filepicker)
panel_edit_wearable->updateScrollingPanelUI(); panel_edit_wearable->updateScrollingPanelUI();
if (found_texture && different_grid) if (found_texture && different_grid)
{ {
args["EXPORTGRID"] = gridnick; args("[EXPORTGRID]", gridnick);
args["CURRENTGRID"] = gHippoGridManager->getConnectedGrid()->getGridNick(); args("[CURRENTGRID]", gHippoGridManager->getConnectedGrid()->getGridNick());
if (mixed_grids) if (mixed_grids)
{ {
LLNotificationsUtil::add("AIXMLImportMixedGrid", args); AIAlert::add_modal("AIXMLImportMixedGrid", args);
} }
else else
{ {
LLNotificationsUtil::add("AIXMLImportDifferentGrid", args); AIAlert::add_modal("AIXMLImportDifferentGrid", args);
} }
} }
} }
else if (found_type) else if (found_type)
{ {
args["TYPE"] = label; AIAlert::add("AIXMLImportEmptyArchetype", args("[TYPE]", label));
LLNotificationsUtil::add("AIXMLImportEmptyArchetype", args);
} }
else if (!wearable_types.empty()) else if (!wearable_types.empty())
{ {
args["TYPE"] = label; AIAlert::add("AIXMLImportWearableTypeMismatch", args("[TYPE]", label)("[ARCHETYPENAME]", wearable_types));
args["ARCHETYPENAME"] = wearable_types;
LLNotificationsUtil::add("AIXMLImportWearableTypeMismatch", args);
} }
} }
@@ -527,24 +519,21 @@ void LLFloaterCustomize::onBtnExport_continued(LLViewerWearable* edit_wearable,
bool success = false; bool success = false;
try try
{ {
LLFILE* outfile = AIFile::fopen(filename, "wb"); AIFile outfile(filename, "wb");
AIXMLLindenGenepool linden_genepool(outfile); AIXMLLindenGenepool linden_genepool(outfile);
linden_genepool.child(edit_wearable->getArchetype()); linden_genepool.child(edit_wearable->getArchetype());
AIFile::close(outfile);
success = true; success = true;
} }
catch (AIAlert const& alert) catch (AIAlert::Error const& error)
{ {
LLNotificationsUtil::add(AIAlert(AIAlertPrefix(), AIAlert::modal, "AIXMLExportWriteError", AIArgs("[FILE]", filename), alert)); AIAlert::add_modal("AIXMLExportWriteError", AIArgs("[FILE]", filename), error);
} }
if (success) if (success)
{ {
LLSD args(LLSD::emptyMap()); AIAlert::add_modal("AIXMLExportSuccess", AIArgs("[FILE]", filename));
args["FILE"] = filename;
LLNotificationsUtil::add("AIXMLExportSuccess", args);
} }
} }

View File

@@ -8412,9 +8412,9 @@ void LLVOAvatar::dumpArchetypeXML_cont(std::string const& fullpath, bool group_b
} }
#endif #endif
} }
catch(AIAlert const& alert) catch (AIAlert::Error const& error)
{ {
LLNotificationsUtil::add(AIAlert(AIAlertPrefix(), AIAlert::modal, "AIXMLdumpArchetypeXMLError", AIArgs("[FILENAME]", fullpath), alert)); AIAlert::add_modal("AIXMLdumpArchetypeXMLError", AIArgs("[FILE]", fullpath), error);
} }
} }

View File

@@ -69,15 +69,6 @@
</form> </form>
</template> </template>
<notification name="AIXMLImportRootVersionError">Import Failure: the file "[FILE]" contains linden_genepool XML data with the wrong [TAG]. Version "[VERSIONMAJOR].0" or less is required.</notification>
<notification name="AIXMLImportDifferentGrid">Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have NOT been applied!</notification>
<notification name="AIXMLImportMixedGrid">Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have been applied but might not exist here!</notification>
<notification name="AIXMLImportWearableTypeMismatch">Import Warning: the file "[FILE]" does not contain a wearable of type [TYPE].
It contains an archetype of type [ARCHETYPENAME]. Please select the correct type before importing.</notification>
<notification name="MediaAlert">Der Besitzer der Parzelle m&#xF6;chte Ihren Viewer anweisen die folgende [TYPE] URL zu laden:[URL]Sie k&#xF6;nnen die korrespondierende Dom&#xE4;ne oder In-Welt Objekt-Skript-Server erlauben oder ablehnen."Erlauben" und "Verweigern" gelten nur f&#xFC;r die aktuelle Sitzung, w&#xE4;hrend "Immer sperren" bzw. "Immer erlauben" dann immer gelten.<form name="form"> <notification name="MediaAlert">Der Besitzer der Parzelle m&#xF6;chte Ihren Viewer anweisen die folgende [TYPE] URL zu laden:[URL]Sie k&#xF6;nnen die korrespondierende Dom&#xE4;ne oder In-Welt Objekt-Skript-Server erlauben oder ablehnen."Erlauben" und "Verweigern" gelten nur f&#xFC;r die aktuelle Sitzung, w&#xE4;hrend "Immer sperren" bzw. "Immer erlauben" dann immer gelten.<form name="form">
<button name="Allow" text="erlauben"/> <button name="Allow" text="erlauben"/>
<button name="Deny" text="verbieten"/> <button name="Deny" text="verbieten"/>

View File

@@ -147,50 +147,6 @@
[PAYLOAD] [PAYLOAD]
</notification> </notification>
<notification
icon="alertmodal.tga"
name="AIXMLExportSuccess"
type="alertmodal">
Successfully exported wearable to &quot;[FILE]&quot;.
</notification>
<notification
icon="alertmodal.tga"
name="AIXMLImportRootVersionError"
type="alertmodal">
Import Failure: the file &quot;[FILE]&quot; contains linden_genepool XML data with the wrong [TAG]. Version &quot;[VERSIONMAJOR].0&quot; or less is required.
</notification>
<notification
icon="alertmodal.tga"
name="AIXMLImportDifferentGrid"
type="alertmodal">
Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have NOT been applied!
</notification>
<notification
icon="alertmodal.tga"
name="AIXMLImportMixedGrid"
type="alertmodal">
Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have been applied but might not exist here!
</notification>
<notification
icon="alert.tga"
name="AIXMLImportEmptyArchetype"
type="alert">
Import warning: the file &quot;[FILE]&quot; contains a wearable of the selected type ([TYPE]),
but contains no parameters or textures for that type. Nothing was imported.
</notification>
<notification
icon="alert.tga"
name="AIXMLImportWearableTypeMismatch"
type="alert">
Import warning: the file &quot;[FILE]&quot; does not contain a wearable of type [TYPE].
It contains an archetype of type [ARCHETYPENAME]. Please select the correct type before importing.
</notification>
<notification <notification
icon="alert.tga" icon="alert.tga"
name="MediaAlert" name="MediaAlert"

View File

@@ -4404,8 +4404,14 @@ Try enclosing path to the editor with double quotes.
<string name="AIArchetype_archetype_has_no_meta">archetype has no &lt;meta&gt; element.</string> <string name="AIArchetype_archetype_has_no_meta">archetype has no &lt;meta&gt; element.</string>
<string name="AIArchetype_MetaData_archetype_meta_has_no_ATTRIBUTE">archetype &lt;meta&gt; element has no '[ATTRIBUTE]' attribute.</string> <string name="AIArchetype_MetaData_archetype_meta_has_no_ATTRIBUTE">archetype &lt;meta&gt; element has no '[ATTRIBUTE]' attribute.</string>
<string name="AIXMLdumpArchetypeXMLError">Failure dumping archetype to "[FILENAME]":</string> <string name="AIXMLdumpArchetypeXMLError">Failure dumping archetype to "[FILE]":</string>
<string name="AIXMLExportSuccess">Successfully exported wearable to "[FILE]".</string>
<string name="AIXMLExportWriteError">The export to file "[FILE]" failed:</string> <string name="AIXMLExportWriteError">The export to file "[FILE]" failed:</string>
<string name="AIXMLImportRootVersionError">Import Failure: the file "[FILE]" contains linden_genepool XML data with the wrong [TAG]. Version "[VERSIONMAJOR].0" or less is required.</string>
<string name="AIXMLImportDifferentGrid">Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have NOT been applied!</string>
<string name="AIXMLImportMixedGrid">Import was successful but note that the wearable was exported on grid [EXPORTGRID] (and the current grid is [CURRENTGRID]). Texture UUIDs have been applied but might not exist here!</string>
<string name="AIXMLImportEmptyArchetype">Import warning: the file "[FILE]" contains a wearable of the selected type ([TYPE]), but contains no parameters or textures for that type. Nothing was imported.</string>
<string name="AIXMLImportWearableTypeMismatch">Import warning: the file "[FILE]" does not contain a wearable of type [TYPE]. It contains an archetype of type [ARCHETYPENAME]. Please select the correct type before importing.</string>
<string name="AIXMLImportError">Failed to import the [TYPE] wearable:</string> <string name="AIXMLImportError">Failed to import the [TYPE] wearable:</string>
<string name="AIXMLImportNoArchetypeError">No archetype found in wearable import file "[FILE]".</string> <string name="AIXMLImportNoArchetypeError">No archetype found in wearable import file "[FILE]".</string>

View File

@@ -73,24 +73,7 @@
</form> </form>
</template> </template>
<notification name="AIXMLImportRootVersionError">
Fallo de Importación: el archivo &quot;[FILE]&quot; contiene datos linden_genepool XML con [TAG] erróneo. Se requiere Versión &quot;[VERSIONMAJOR].0&quot; o inferior.
</notification>
<notification name="AIXMLImportDifferentGrid">
La importación se ha realizado con exito, pero ten presente que el objeto vestible fue exportado desde el grid [EXPORTGRID] (y el grid actual es [CURRENTGRID]). ¡No se aplicaron las UUIDs de las Texturas!
</notification>
<notification name="AIXMLImportMixedGrid">
La importación se ha realizado con exito, pero ten presente que el objeto vestible fue exportado desde el grid [EXPORTGRID] (y el grid actual es [CURRENTGRID]).¡Se aplicaron las UUIDs de la Texturas pero quizás no existan aquí!
</notification>
<notification name="AIXMLImportWearableTypeMismatch">
Aviso de Importación: el archivo &quot;[FILE]&quot; no contiene un objeto vestible de tipo [TYPE].
Éste contiene un arquetipo de tipo [ARCHETYPENAME]. Por favor, selecciona el tipo correcto antes de comenzar la importación.
</notification>
<notification name="MediaAlert"> <notification name="MediaAlert">
El propietario de esta parcela ha solicitado que el siguiente URL de [TYPE] sea cargado en tu visor: El propietario de esta parcela ha solicitado que el siguiente URL de [TYPE] sea cargado en tu visor:

View File

@@ -4836,5 +4836,58 @@ Intenta entrecomillando el camino al editor.
<!-- teleport_strings.xml's strings we need --> <!-- teleport_strings.xml's strings we need -->
<string name="completed_from">Teleporte completado desde</string> <string name="completed_from">Teleporte completado desde</string>
<!-- ************ EVERYTHING BELOW STILL NEEDS TRANSLATION! ************** -->
<!-- AIAlert messages -->
<string name="AIPrefix">"[PREFIX]: "</string>
<!-- AIFile exception alerts -->
<string name="AIFile_mkdir_Failed_to_create_DIRNAME">Failed to create folder [DIRNAME]: [ERROR]</string>
<string name="AIFile_rmdir_Failed_to_remove_DIRNAME">Failed to remove folder [DIRNAME]: [ERROR]</string>
<string name="AIFile_fopen_Failed_to_open_FILENAME">Failed to open file "[FILENAME]": [ERROR]</string>
<string name="AIFile_close_Failed_to_close_file">Failed to close file: [ERROR]</string>
<string name="AIFile_remove_Failed_to_remove_FILENAME">Failed to remove file [FILENAME]: [ERROR]</string>
<string name="AIFile_rename_Failed_to_rename_FILE_to_NEWFILE">Failed to rename file [FILE] to [NEWFILE]: [ERROR]</string>
<!-- AIXMLElement exception alerts -->
<string name="AIXMLElement_attribute_Failed_to_write_DATA">Failed to write '[DATA]', writing attribute data.</string>
<string name="AIXMLElement_child_Bad_ostream">ostream not good after calling child.toXML</string>
<string name="AIXMLElement_write_child_Failed_to_write_DATA">Failed to write '[DATA]', writing child data.</string>
<string name="AIXMLElement_Failed_to_write_DATA">Failed to write '[DATA]', opening new child.</string>
<string name="AIXMLElement_closing_child_Failed_to_write_DATA">Failed to write '[DATA]', closing previous child.</string>
<!-- AIXMLStream exception alerts -->
<string name="AIXMLStream_fprintf_failed_to_write_xml_header">Failed to write XML header.</string>
<!-- AIXMLParser exception alerts -->
<string name="AIXMLParser_Cannot_parse_FILEDESC_FILENAME">Cannot parse [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLParser_No_root_node_found_in_FILEDESC_FILENAME">No root node found in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLParser_Missing_header_NAME_invalid_FILEDESC_FILENAME">Missing header '[NAME]' ; invalid [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLParser_Invalid_or_missing_NAME_version_attribute_in_FILEDESC_FILENAME">Invalid or missing [NAME] 'version' attribute in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLParser_Incompatible_NAME_version_MAJOR_MINOR_in">Incompatible '[NAME]' version, [MAJOR].[MINOR], in [FILEDESC] "[FILENAME]".</string>
<!-- AIXMLElementParser exception alerts -->
<string name="AIXMLElementParser_read_string_Invalid_MD5_VALUE_in_FILEDESC_FILENAME">Invalid MD5 ([VALUE]) in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLElementParser_read_string_Invalid_boolean_VALUE_in_FILEDESC_FILENAME">Invalid boolean ([VALUE]) in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLElementParser_attribute_Missing_NAME_attribute_in_NODENAME_of_FILEDESC_FILENAME">Missing '[NAME]' attribute in [NODENAME] of [FILEDESC] "[FILENAME]".</string>"
<string name="AIXMLElementParser_attribute_Invalid_NAME_attribute_should_be_REQUIRED_in_NODENAME_of_FILEDESC_FILENAME">Invalid '[NAME]' attribute (should be '[REQUIRED]') in [NODENAME] of [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLElementParser_read_child_Invalid_uuid_in_FILEDESC_FILENAME">Invalid UUID in [FILEDESC] "[FILENAME]".</string>
<string name="AIXMLElementParser_read_child_Invalid_date_DATE_in_FILEDESC_FILENAME">Invalid DATE ([DATE]) in [FILEDESC] "[FILENAME]".</string>
<!-- AIArchetype exception alerts -->
<string name="AIArchetype_archetype_has_no_meta">archetype has no &lt;meta&gt; element.</string>
<string name="AIArchetype_MetaData_archetype_meta_has_no_ATTRIBUTE">archetype &lt;meta&gt; element has no '[ATTRIBUTE]' attribute.</string>
<string name="AIXMLdumpArchetypeXMLError">Failure dumping archetype to "[FILE]":</string>
<string name="AIXMLExportSuccess">Successfully exported wearable to "[FILE]".</string>
<string name="AIXMLExportWriteError">The export to file "[FILE]" failed:</string>
<string name="AIXMLImportRootVersionError">Fallo de Importación: el archivo "[FILE]" contiene datos linden_genepool XML con [TAG] erróneo. Se requiere Versión "[VERSIONMAJOR].0" o inferior.</string>
<string name="AIXMLImportDifferentGrid">La importación se ha realizado con exito, pero ten presente que el objeto vestible fue exportado desde el grid [EXPORTGRID] (y el grid actual es [CURRENTGRID]). ¡No se aplicaron las UUIDs de las Texturas!</string>
<string name="AIXMLImportMixedGrid">La importación se ha realizado con exito, pero ten presente que el objeto vestible fue exportado desde el grid [EXPORTGRID] (y el grid actual es [CURRENTGRID]).¡Se aplicaron las UUIDs de la Texturas pero quizás no existan aquí!</string>
<string name="AIXMLImportEmptyArchetype">Import warning: the file "[FILE]" contains a wearable of the selected type ([TYPE]), but contains no parameters or textures for that type. Nothing was imported.</string>
<string name="AIXMLImportWearableTypeMismatch">Aviso de Importación: el archivo "[FILE]" no contiene un objeto vestible de tipo [TYPE]. Éste contiene un arquetipo de tipo [ARCHETYPENAME]. Por favor, selecciona el tipo correcto antes de comenzar la importación.</string>
<string name="AIXMLImportError">Failed to import the [TYPE] wearable:</string>
<string name="AIXMLImportNoArchetypeError">No archetype found in wearable import file "[FILE]".</string>
</strings> </strings>