Merge branch 'DRTVWR-580-maint-T' of https://github.com/secondlife/viewer
# Conflicts: # indra/llcharacter/llkeyframemotion.cpp # indra/llcommon/llerrorthread.cpp # indra/llui/lllayoutstack.cpp # indra/newview/app_settings/settings.xml # indra/newview/llfilepicker.cppmaster
commit
e900da3597
|
|
@ -2057,7 +2057,7 @@ BOOL LLKeyframeMotion::serialize(LLDataPacker& dp) const
|
|||
LL_DEBUGS("BVH") << " rot: t " << rot_key.mTime << " angles " << rot_angles.mV[VX] <<","<< rot_angles.mV[VY] <<","<< rot_angles.mV[VZ] << LL_ENDL;
|
||||
}
|
||||
|
||||
success &= dp.packS32(joint_motionp->mPositionCurve.mKeys.size(), "num_pos_keys"); // <FS:Ansariel> Fix LL merge bug
|
||||
success &= dp.packS32(joint_motionp->mPositionCurve.mKeys.size(), "num_pos_keys");
|
||||
for (PositionCurve::key_map_t::value_type& pos_pair : joint_motionp->mPositionCurve.mKeys)
|
||||
{
|
||||
PositionKey& pos_key = pos_pair.second;
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ set(llcommon_SOURCE_FILES
|
|||
lldependencies.cpp
|
||||
lldictionary.cpp
|
||||
llerror.cpp
|
||||
llerrorthread.cpp
|
||||
llevent.cpp
|
||||
lleventapi.cpp
|
||||
lleventcoro.cpp
|
||||
|
|
@ -151,7 +150,6 @@ set(llcommon_HEADER_FILES
|
|||
llendianswizzle.h
|
||||
llerror.h
|
||||
llerrorcontrol.h
|
||||
llerrorthread.h
|
||||
llevent.h
|
||||
lleventapi.h
|
||||
lleventcoro.h
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@
|
|||
#include "llcommon.h"
|
||||
#include "llapr.h"
|
||||
#include "llerrorcontrol.h"
|
||||
#include "llerrorthread.h"
|
||||
#include "llframetimer.h"
|
||||
#include "lllivefile.h"
|
||||
#include "llmemory.h"
|
||||
|
|
@ -108,12 +107,7 @@ LLAppErrorHandler LLApp::sErrorHandler = NULL;
|
|||
BOOL LLApp::sErrorThreadRunning = FALSE;
|
||||
|
||||
|
||||
LLApp::LLApp() : mThreadErrorp(NULL)
|
||||
{
|
||||
commonCtor();
|
||||
}
|
||||
|
||||
void LLApp::commonCtor()
|
||||
LLApp::LLApp()
|
||||
{
|
||||
// Set our status to running
|
||||
setStatus(APP_STATUS_RUNNING);
|
||||
|
|
@ -143,12 +137,6 @@ void LLApp::commonCtor()
|
|||
mCrashReportPipeStr = L"\\\\.\\pipe\\LLCrashReporterPipe";
|
||||
}
|
||||
|
||||
LLApp::LLApp(LLErrorThread *error_thread) :
|
||||
mThreadErrorp(error_thread)
|
||||
{
|
||||
commonCtor();
|
||||
}
|
||||
|
||||
|
||||
LLApp::~LLApp()
|
||||
{
|
||||
|
|
@ -158,13 +146,6 @@ LLApp::~LLApp()
|
|||
mLiveFiles.clear();
|
||||
|
||||
setStopped();
|
||||
// HACK: wait for the error thread to clean itself
|
||||
ms_sleep(20);
|
||||
if (mThreadErrorp)
|
||||
{
|
||||
delete mThreadErrorp;
|
||||
mThreadErrorp = NULL;
|
||||
}
|
||||
|
||||
SUBSYSTEM_CLEANUP_DBG(LLCommon);
|
||||
}
|
||||
|
|
@ -393,27 +374,6 @@ void LLApp::setupErrorHandling(bool second_instance)
|
|||
#endif // ! LL_BUGSPLAT
|
||||
|
||||
#endif // ! LL_WINDOWS
|
||||
|
||||
#ifdef LL_BUGSPLAT
|
||||
// do not start our own error thread
|
||||
#else // ! LL_BUGSPLAT
|
||||
startErrorThread();
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLApp::startErrorThread()
|
||||
{
|
||||
//
|
||||
// Start the error handling thread, which is responsible for taking action
|
||||
// when the app goes into the APP_STATUS_ERROR state
|
||||
//
|
||||
if(!mThreadErrorp)
|
||||
{
|
||||
LL_INFOS() << "Starting error thread" << LL_ENDL;
|
||||
mThreadErrorp = new LLErrorThread();
|
||||
mThreadErrorp->setUserData((void *) this);
|
||||
mThreadErrorp->start();
|
||||
}
|
||||
}
|
||||
|
||||
void LLApp::setErrorHandler(LLAppErrorHandler handler)
|
||||
|
|
@ -476,7 +436,7 @@ void LLApp::setStatus(EAppStatus status)
|
|||
// static
|
||||
void LLApp::setError()
|
||||
{
|
||||
// set app status to ERROR so that the LLErrorThread notices
|
||||
// set app status to ERROR
|
||||
setStatus(APP_STATUS_ERROR);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include <atomic>
|
||||
#include <chrono>
|
||||
// Forward declarations
|
||||
class LLErrorThread;
|
||||
class LLLiveFile;
|
||||
#if LL_LINUX
|
||||
#include <signal.h>
|
||||
|
|
@ -53,7 +52,6 @@ void clear_signals();
|
|||
|
||||
class LL_COMMON_API LLApp
|
||||
{
|
||||
friend class LLErrorThread;
|
||||
public:
|
||||
typedef enum e_app_status
|
||||
{
|
||||
|
|
@ -67,11 +65,6 @@ public:
|
|||
LLApp();
|
||||
virtual ~LLApp();
|
||||
|
||||
protected:
|
||||
LLApp(LLErrorThread* error_thread);
|
||||
void commonCtor();
|
||||
public:
|
||||
|
||||
/**
|
||||
* @brief Return the static app instance if one was created.
|
||||
*/
|
||||
|
|
@ -257,14 +250,14 @@ public:
|
|||
void setupErrorHandling(bool mSecondInstance=false);
|
||||
|
||||
void setErrorHandler(LLAppErrorHandler handler);
|
||||
static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred.
|
||||
static void runErrorHandler(); // run shortly after we detect an error
|
||||
//@}
|
||||
|
||||
|
||||
// the maximum length of the minidump filename returned by getMiniDumpFilename()
|
||||
static const U32 MAX_MINDUMP_PATH_LENGTH = 256;
|
||||
|
||||
// change the directory where Breakpad minidump files are written to
|
||||
void setDebugFileNames(const std::string &path);
|
||||
void setDebugFileNames(const std::string &path);
|
||||
|
||||
// Return the Google Breakpad minidump filename after a crash.
|
||||
char *getMiniDumpFilename() { return mMinidumpPath; }
|
||||
|
|
@ -310,13 +303,11 @@ protected:
|
|||
void stepFrame();
|
||||
|
||||
private:
|
||||
void startErrorThread();
|
||||
|
||||
// Contains the filename of the minidump file after a crash.
|
||||
char mMinidumpPath[MAX_MINDUMP_PATH_LENGTH];
|
||||
|
||||
std::string mStaticDebugFileName;
|
||||
std::string mDynamicDebugFileName;
|
||||
std::string mStaticDebugFileName;
|
||||
std::string mDynamicDebugFileName;
|
||||
|
||||
// *NOTE: On Windows, we need a routine to reset the structured
|
||||
// exception handler when some evil driver has taken it over for
|
||||
|
|
@ -324,9 +315,6 @@ private:
|
|||
typedef int(*signal_handler_func)(int signum);
|
||||
static LLAppErrorHandler sErrorHandler;
|
||||
|
||||
// Default application threads
|
||||
LLErrorThread* mThreadErrorp; // Waits for app to go to status ERROR, then runs the error callback
|
||||
|
||||
// This is the application level runnable scheduler.
|
||||
LLRunner mRunner;
|
||||
|
||||
|
|
|
|||
|
|
@ -286,7 +286,6 @@ namespace LLError
|
|||
// used to indicate no class info known for logging
|
||||
|
||||
//LLCallStacks keeps track of call stacks and output the call stacks to log file
|
||||
//when LLAppViewer::handleViewerCrash() is triggered.
|
||||
//
|
||||
//Note: to be simple, efficient and necessary to keep track of correct call stacks,
|
||||
//LLCallStacks is designed not to be thread-safe.
|
||||
|
|
|
|||
|
|
@ -1,135 +0,0 @@
|
|||
/**
|
||||
* @file llerrorthread.cpp
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&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 "linden_common.h"
|
||||
#include "llerrorthread.h"
|
||||
|
||||
#include "llapp.h"
|
||||
#include "lltimer.h" // ms_sleep()
|
||||
|
||||
LLErrorThread::LLErrorThread()
|
||||
: LLThread("Error"),
|
||||
mUserDatap(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LLErrorThread::~LLErrorThread()
|
||||
{
|
||||
}
|
||||
|
||||
void LLErrorThread::setUserData(void* user_data)
|
||||
{
|
||||
mUserDatap = user_data;
|
||||
}
|
||||
|
||||
|
||||
void* LLErrorThread::getUserData() const
|
||||
{
|
||||
return mUserDatap;
|
||||
}
|
||||
|
||||
#if !LL_WINDOWS
|
||||
//
|
||||
// Various signal/error handling functions that can't be put into the class
|
||||
//
|
||||
void get_child_status(const int waitpid_status, int &process_status, bool &exited, bool do_logging)
|
||||
{
|
||||
exited = false;
|
||||
process_status = -1;
|
||||
// The child process exited. Call its callback, and then clean it up
|
||||
if (WIFEXITED(waitpid_status))
|
||||
{
|
||||
process_status = WEXITSTATUS(waitpid_status);
|
||||
exited = true;
|
||||
if (do_logging)
|
||||
{
|
||||
LL_INFOS() << "get_child_status - Child exited cleanly with return of " << process_status << LL_ENDL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (WIFSIGNALED(waitpid_status))
|
||||
{
|
||||
process_status = WTERMSIG(waitpid_status);
|
||||
exited = true;
|
||||
if (do_logging)
|
||||
{
|
||||
LL_INFOS() << "get_child_status - Child died because of uncaught signal " << process_status << LL_ENDL;
|
||||
#ifdef WCOREDUMP
|
||||
if (WCOREDUMP(waitpid_status))
|
||||
{
|
||||
LL_INFOS() << "get_child_status - Child dumped core" << LL_ENDL;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "get_child_status - Child didn't dump core" << LL_ENDL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (do_logging)
|
||||
{
|
||||
// This is weird. I just dump the waitpid status into the status code,
|
||||
// not that there's any way of telling what it is...
|
||||
LL_INFOS() << "get_child_status - Got SIGCHILD but child didn't exit" << LL_ENDL;
|
||||
process_status = waitpid_status;
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void LLErrorThread::run()
|
||||
{
|
||||
LLApp::sErrorThreadRunning = TRUE;
|
||||
// This thread sits and waits for the sole purpose
|
||||
// of waiting for the signal/exception handlers to flag the
|
||||
// application state as APP_STATUS_ERROR.
|
||||
|
||||
// <FS:ND/> Do not log as this can lead to deadlocks during startup.
|
||||
// LL_INFOS() << "thread_error - Waiting for an error" << LL_ENDL;
|
||||
|
||||
S32 counter = 0;
|
||||
while (! (LLApp::isError() || LLApp::isStopped()))
|
||||
{
|
||||
ms_sleep(10);
|
||||
counter++;
|
||||
}
|
||||
if (LLApp::isError())
|
||||
{
|
||||
// The app is in an error state, run the application's error handler.
|
||||
//LL_INFOS() << "thread_error - An error has occurred, running error callback!" << LL_ENDL;
|
||||
// Run the error handling callback
|
||||
LLApp::runErrorHandler();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Everything is okay, a clean exit.
|
||||
//LL_INFOS() << "thread_error - Application exited cleanly" << LL_ENDL;
|
||||
}
|
||||
|
||||
//LL_INFOS() << "thread_error - Exiting" << LL_ENDL;
|
||||
LLApp::sErrorThreadRunning = FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/**
|
||||
* @file llerrorthread.h
|
||||
* @brief Specialized thread to handle runtime errors.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&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_LLERRORTHREAD_H
|
||||
#define LL_LLERRORTHREAD_H
|
||||
|
||||
#include "llthread.h"
|
||||
|
||||
class LL_COMMON_API LLErrorThread : public LLThread
|
||||
{
|
||||
public:
|
||||
LLErrorThread();
|
||||
~LLErrorThread();
|
||||
|
||||
/*virtual*/ void run(void);
|
||||
void setUserData(void *user_data);
|
||||
void *getUserData() const;
|
||||
|
||||
protected:
|
||||
void* mUserDatap; // User data associated with this thread
|
||||
};
|
||||
|
||||
#endif // LL_LLERRORTHREAD_H
|
||||
|
|
@ -320,6 +320,17 @@ void LLLayoutStack::draw()
|
|||
}
|
||||
}
|
||||
|
||||
void LLLayoutStack::deleteAllChildren()
|
||||
{
|
||||
mPanels.clear();
|
||||
LLView::deleteAllChildren();
|
||||
|
||||
// Not really needed since nothing is left to
|
||||
// display, but for the sake of consistency
|
||||
updateFractionalSizes();
|
||||
mNeedsLayout = true;
|
||||
}
|
||||
|
||||
void LLLayoutStack::removeChild(LLView* view)
|
||||
{
|
||||
LLLayoutPanel* embedded_panelp = findEmbeddedPanel(dynamic_cast<LLPanel*>(view));
|
||||
|
|
@ -327,21 +338,14 @@ void LLLayoutStack::removeChild(LLView* view)
|
|||
if (embedded_panelp)
|
||||
{
|
||||
mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp));
|
||||
// delete embedded_panelp; // <FS:Zi> Fix crash when removing layout panels from a stack
|
||||
LLView::removeChild(view);
|
||||
updateFractionalSizes();
|
||||
mNeedsLayout = true;
|
||||
}
|
||||
|
||||
LLView::removeChild(view);
|
||||
|
||||
// <FS:Zi> Fix crash when removing layout panels from a stack
|
||||
if (embedded_panelp)
|
||||
{
|
||||
// only delete the panel after it was removed from LLView to prevent
|
||||
// LLView::removeChild() to run into an already deleted pointer
|
||||
delete embedded_panelp;
|
||||
}
|
||||
// </FS:Zi>
|
||||
else
|
||||
{
|
||||
LLView::removeChild(view);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL LLLayoutStack::postBuild()
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ public:
|
|||
virtual ~LLLayoutStack();
|
||||
|
||||
/*virtual*/ void draw();
|
||||
/*virtual*/ void deleteAllChildren();
|
||||
/*virtual*/ void removeChild(LLView*);
|
||||
/*virtual*/ BOOL postBuild();
|
||||
/*virtual*/ bool addChild(LLView* child, S32 tab_group = 0);
|
||||
|
|
|
|||
|
|
@ -1905,6 +1905,13 @@ bool LLMenuGL::addContextChild(LLView* view, S32 tab_group)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
void LLMenuGL::deleteAllChildren()
|
||||
{
|
||||
mItems.clear();
|
||||
LLUICtrl::deleteAllChildren();
|
||||
}
|
||||
|
||||
void LLMenuGL::removeChild( LLView* ctrl)
|
||||
{
|
||||
// previously a dynamic_cast with if statement to check validity
|
||||
|
|
|
|||
|
|
@ -443,6 +443,7 @@ public:
|
|||
/*virtual*/ void drawBackground(LLMenuItemGL* itemp, F32 alpha);
|
||||
/*virtual*/ void setVisible(BOOL visible);
|
||||
/*virtual*/ bool addChild(LLView* view, S32 tab_group = 0);
|
||||
/*virtual*/ void deleteAllChildren();
|
||||
/*virtual*/ void removeChild( LLView* ctrl);
|
||||
/*virtual*/ BOOL postBuild();
|
||||
|
||||
|
|
|
|||
|
|
@ -626,8 +626,10 @@ void LLView::deleteAllChildren()
|
|||
|
||||
while (!mChildList.empty())
|
||||
{
|
||||
LLView* viewp = mChildList.front();
|
||||
delete viewp; // will remove the child from mChildList
|
||||
LLView* viewp = mChildList.front();
|
||||
viewp->mParentView = NULL;
|
||||
delete viewp;
|
||||
mChildList.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16246,6 +16246,17 @@ Change of this parameter will affect the layout of buttons in notification toast
|
|||
<key>Value</key>
|
||||
<string></string>
|
||||
</map>
|
||||
<key>DeepLTranslateAPIKey</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>DeepL Translation service data to use with the DeepL Translator API</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>LLSD</string>
|
||||
<key>Value</key>
|
||||
<string></string>
|
||||
</map>
|
||||
<key>TutorialURL</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -4335,8 +4335,6 @@ void LLAppViewer::writeSystemInfo()
|
|||
// "CrashNotHandled" is set here, while things are running well,
|
||||
// in case of a freeze. If there is a freeze, the crash logger will be launched
|
||||
// and can read this value from the debug_info.log.
|
||||
// If the crash is handled by LLAppViewer::handleViewerCrash, ie not a freeze,
|
||||
// then the value of "CrashNotHandled" will be set to true.
|
||||
gDebugInfo["CrashNotHandled"] = LLSD::Boolean(true);
|
||||
#else // LL_BUGSPLAT
|
||||
// "CrashNotHandled" is obsolete; it used (not very successsfully)
|
||||
|
|
@ -4437,163 +4435,6 @@ void getFileList()
|
|||
}
|
||||
#endif
|
||||
|
||||
void LLAppViewer::handleViewerCrash()
|
||||
{
|
||||
LL_INFOS("CRASHREPORT") << "Handle viewer crash entry." << LL_ENDL;
|
||||
|
||||
LL_INFOS("CRASHREPORT") << "Last render pool type: " << LLPipeline::sCurRenderPoolType << LL_ENDL ;
|
||||
|
||||
LLMemory::logMemoryInfo(true) ;
|
||||
|
||||
//print out recorded call stacks if there are any.
|
||||
LLError::LLCallStacks::print();
|
||||
|
||||
LLAppViewer* pApp = LLAppViewer::instance();
|
||||
if (pApp->beingDebugged())
|
||||
{
|
||||
// This will drop us into the debugger.
|
||||
abort();
|
||||
}
|
||||
|
||||
if (LLApp::isCrashloggerDisabled())
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
// Returns whether a dialog was shown.
|
||||
// Only do the logic in here once
|
||||
if (pApp->mReportedCrash)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pApp->mReportedCrash = TRUE;
|
||||
|
||||
// Insert crash host url (url to post crash log to) if configured.
|
||||
std::string crashHostUrl = gSavedSettings.get<std::string>("CrashHostUrl");
|
||||
if(crashHostUrl != "")
|
||||
{
|
||||
gDebugInfo["Dynamic"]["CrashHostUrl"] = crashHostUrl;
|
||||
}
|
||||
|
||||
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
|
||||
if ( parcel && parcel->getMusicURL()[0])
|
||||
{
|
||||
gDebugInfo["Dynamic"]["ParcelMusicURL"] = parcel->getMusicURL();
|
||||
}
|
||||
if ( parcel && parcel->getMediaURL()[0])
|
||||
{
|
||||
gDebugInfo["Dynamic"]["ParcelMediaURL"] = parcel->getMediaURL();
|
||||
}
|
||||
|
||||
gDebugInfo["Dynamic"]["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds());
|
||||
gDebugInfo["Dynamic"]["RAMInfo"]["Allocated"] = LLSD::Integer(LLMemory::getCurrentRSS() / 1024);
|
||||
|
||||
if(gLogoutInProgress)
|
||||
{
|
||||
gDebugInfo["Dynamic"]["LastExecEvent"] = LAST_EXEC_LOGOUT_CRASH;
|
||||
}
|
||||
else
|
||||
{
|
||||
gDebugInfo["Dynamic"]["LastExecEvent"] = gLLErrorActivated ? LAST_EXEC_LLERROR_CRASH : LAST_EXEC_OTHER_CRASH;
|
||||
}
|
||||
|
||||
if(gAgent.getRegion())
|
||||
{
|
||||
gDebugInfo["Dynamic"]["CurrentSimHost"] = gAgent.getRegion()->getSimHostName();
|
||||
gDebugInfo["Dynamic"]["CurrentRegion"] = gAgent.getRegion()->getName();
|
||||
|
||||
const LLVector3& loc = gAgent.getPositionAgent();
|
||||
gDebugInfo["Dynamic"]["CurrentLocationX"] = loc.mV[0];
|
||||
gDebugInfo["Dynamic"]["CurrentLocationY"] = loc.mV[1];
|
||||
gDebugInfo["Dynamic"]["CurrentLocationZ"] = loc.mV[2];
|
||||
}
|
||||
|
||||
if(LLAppViewer::instance()->mMainloopTimeout)
|
||||
{
|
||||
gDebugInfo["Dynamic"]["MainloopTimeoutState"] = LLAppViewer::instance()->mMainloopTimeout->getState();
|
||||
}
|
||||
|
||||
// The crash is being handled here so set this value to false.
|
||||
// Otherwise the crash logger will think this crash was a freeze.
|
||||
gDebugInfo["Dynamic"]["CrashNotHandled"] = LLSD::Boolean(false);
|
||||
|
||||
//Write out the crash status file
|
||||
//Use marker file style setup, as that's the simplest, especially since
|
||||
//we're already in a crash situation
|
||||
if (gDirUtilp)
|
||||
{
|
||||
std::string crash_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
|
||||
gLLErrorActivated
|
||||
? LLERROR_MARKER_FILE_NAME
|
||||
: ERROR_MARKER_FILE_NAME);
|
||||
LLAPRFile crash_marker_file ;
|
||||
crash_marker_file.open(crash_marker_file_name, LL_APR_WB);
|
||||
if (crash_marker_file.getFileHandle())
|
||||
{
|
||||
LL_INFOS("MarkerFile") << "Created crash marker file " << crash_marker_file_name << LL_ENDL;
|
||||
recordMarkerVersion(crash_marker_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("MarkerFile") << "Cannot create error marker file " << crash_marker_file_name << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("MarkerFile") << "No gDirUtilp with which to create error marker file name" << LL_ENDL;
|
||||
}
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
Sleep(200);
|
||||
#endif
|
||||
|
||||
char *minidump_file = pApp->getMiniDumpFilename();
|
||||
LL_DEBUGS("CRASHREPORT") << "minidump file name " << minidump_file << LL_ENDL;
|
||||
if(minidump_file && minidump_file[0] != 0)
|
||||
{
|
||||
gDebugInfo["Dynamic"]["MinidumpPath"] = minidump_file;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef LL_WINDOWS
|
||||
getFileList();
|
||||
#else
|
||||
LL_WARNS("CRASHREPORT") << "no minidump file?" << LL_ENDL;
|
||||
#endif
|
||||
}
|
||||
gDebugInfo["Dynamic"]["CrashType"]="crash";
|
||||
|
||||
if (gMessageSystem && gDirUtilp)
|
||||
{
|
||||
std::string filename;
|
||||
filename = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "stats.log");
|
||||
LL_DEBUGS("CRASHREPORT") << "recording stats " << filename << LL_ENDL;
|
||||
llofstream file(filename.c_str(), std::ios_base::binary);
|
||||
if(file.good())
|
||||
{
|
||||
gMessageSystem->summarizeLogs(file);
|
||||
file.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("CRASHREPORT") << "problem recording stats" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
if (gMessageSystem)
|
||||
{
|
||||
gMessageSystem->getCircuitInfo(gDebugInfo["CircuitInfo"]);
|
||||
gMessageSystem->stopLogging();
|
||||
}
|
||||
|
||||
if (LLWorld::instanceExists()) LLWorld::getInstance()->getInfo(gDebugInfo["Dynamic"]);
|
||||
|
||||
gDebugInfo["FatalMessage"] = LLError::getFatalMessage();
|
||||
|
||||
// Close the debug file
|
||||
pApp->writeDebugInfo(false); //false answers the isStatic question with the least overhead.
|
||||
}
|
||||
|
||||
// static
|
||||
void LLAppViewer::recordMarkerVersion(LLAPRFile& marker_file)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -119,7 +119,6 @@ public:
|
|||
|
||||
virtual bool restoreErrorTrap() = 0; // Require platform specific override to reset error handling mechanism.
|
||||
// return false if the error trap needed restoration.
|
||||
static void handleViewerCrash(); // Hey! The viewer crashed. Do this, soon.
|
||||
void checkForCrash();
|
||||
|
||||
// Thread accessors
|
||||
|
|
|
|||
|
|
@ -128,8 +128,6 @@ int main( int argc, char **argv )
|
|||
|
||||
// install unexpected exception handler
|
||||
gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler);
|
||||
// install crash handlers
|
||||
viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
|
||||
|
||||
unsetenv( "LD_PRELOAD" ); // <FS:ND/> Get rid of any preloading, we do not want this to happen during startup of plugins.
|
||||
|
||||
|
|
|
|||
|
|
@ -83,8 +83,6 @@ void constructViewer()
|
|||
}
|
||||
|
||||
gViewerAppPtr = new LLAppViewerMacOSX();
|
||||
|
||||
gViewerAppPtr->setErrorHandler(LLAppViewer::handleViewerCrash);
|
||||
}
|
||||
|
||||
bool initViewer()
|
||||
|
|
|
|||
|
|
@ -472,8 +472,6 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
|
|||
|
||||
gOldTerminateHandler = std::set_terminate(exceptionTerminateHandler);
|
||||
|
||||
viewer_app_ptr->setErrorHandler(LLAppViewer::handleViewerCrash);
|
||||
|
||||
// Set a debug info flag to indicate if multiple instances are running.
|
||||
bool found_other_instance = !create_app_mutex();
|
||||
gDebugInfo["FoundOtherInstanceAtStartup"] = LLSD::Boolean(found_other_instance);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ LLFloaterTranslationSettings::LLFloaterTranslationSettings(const LLSD& key)
|
|||
, mMachineTranslationCB(NULL)
|
||||
, mAzureKeyVerified(false)
|
||||
, mGoogleKeyVerified(false)
|
||||
, mDeepLKeyVerified(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -63,8 +64,11 @@ BOOL LLFloaterTranslationSettings::postBuild()
|
|||
mAzureAPIKeyEditor = getChild<LLLineEditor>("azure_api_key");
|
||||
mAzureAPIRegionEditor = getChild<LLLineEditor>("azure_api_region");
|
||||
mGoogleAPIKeyEditor = getChild<LLLineEditor>("google_api_key");
|
||||
mDeepLAPIDomainCombo = getChild<LLComboBox>("deepl_api_domain_combo");
|
||||
mDeepLAPIKeyEditor = getChild<LLLineEditor>("deepl_api_key");
|
||||
mAzureVerifyBtn = getChild<LLButton>("verify_azure_api_key_btn");
|
||||
mGoogleVerifyBtn = getChild<LLButton>("verify_google_api_key_btn");
|
||||
mDeepLVerifyBtn = getChild<LLButton>("verify_deepl_api_key_btn");
|
||||
mOKBtn = getChild<LLButton>("ok_btn");
|
||||
|
||||
mMachineTranslationCB->setCommitCallback(boost::bind(&LLFloaterTranslationSettings::updateControlsEnabledState, this));
|
||||
|
|
@ -73,18 +77,37 @@ BOOL LLFloaterTranslationSettings::postBuild()
|
|||
getChild<LLButton>("cancel_btn")->setClickedCallback(boost::bind(&LLFloater::closeFloater, this, false));
|
||||
mAzureVerifyBtn->setClickedCallback(boost::bind(&LLFloaterTranslationSettings::onBtnAzureVerify, this));
|
||||
mGoogleVerifyBtn->setClickedCallback(boost::bind(&LLFloaterTranslationSettings::onBtnGoogleVerify, this));
|
||||
mDeepLVerifyBtn->setClickedCallback(boost::bind(&LLFloaterTranslationSettings::onBtnDeepLVerify, this));
|
||||
|
||||
mAzureAPIKeyEditor->setFocusReceivedCallback(boost::bind(&LLFloaterTranslationSettings::onEditorFocused, this, _1));
|
||||
mAzureAPIKeyEditor->setKeystrokeCallback(boost::bind(&LLFloaterTranslationSettings::onAzureKeyEdited, this), NULL);
|
||||
mAzureAPIRegionEditor->setFocusReceivedCallback(boost::bind(&LLFloaterTranslationSettings::onEditorFocused, this, _1));
|
||||
mAzureAPIRegionEditor->setKeystrokeCallback(boost::bind(&LLFloaterTranslationSettings::onAzureKeyEdited, this), NULL);
|
||||
|
||||
mAzureAPIEndpointEditor->setFocusLostCallback(boost::bind(&LLFloaterTranslationSettings::onAzureKeyEdited, this));
|
||||
mAzureAPIEndpointEditor->setCommitCallback(boost::bind(&LLFloaterTranslationSettings::onAzureKeyEdited, this));
|
||||
mAzureAPIEndpointEditor->setFocusLostCallback([this](LLFocusableElement*)
|
||||
{
|
||||
setAzureVerified(false, false, 0);
|
||||
});
|
||||
mAzureAPIEndpointEditor->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param)
|
||||
{
|
||||
setAzureVerified(false, false, 0);
|
||||
});
|
||||
|
||||
mGoogleAPIKeyEditor->setFocusReceivedCallback(boost::bind(&LLFloaterTranslationSettings::onEditorFocused, this, _1));
|
||||
mGoogleAPIKeyEditor->setKeystrokeCallback(boost::bind(&LLFloaterTranslationSettings::onGoogleKeyEdited, this), NULL);
|
||||
|
||||
mDeepLAPIKeyEditor->setFocusReceivedCallback(boost::bind(&LLFloaterTranslationSettings::onEditorFocused, this, _1));
|
||||
mDeepLAPIKeyEditor->setKeystrokeCallback(boost::bind(&LLFloaterTranslationSettings::onDeepLKeyEdited, this), NULL);
|
||||
|
||||
mDeepLAPIDomainCombo->setFocusLostCallback([this](LLFocusableElement*)
|
||||
{
|
||||
setDeepLVerified(false, false, 0);
|
||||
});
|
||||
mDeepLAPIDomainCombo->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param)
|
||||
{
|
||||
setDeepLVerified(false, false, 0);
|
||||
});
|
||||
|
||||
center();
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -133,6 +156,20 @@ void LLFloaterTranslationSettings::onOpen(const LLSD& key)
|
|||
mGoogleKeyVerified = FALSE;
|
||||
}
|
||||
|
||||
LLSD deepl_key = gSavedSettings.getLLSD("DeepLTranslateAPIKey");
|
||||
if (deepl_key.isMap() && !deepl_key["id"].asString().empty())
|
||||
{
|
||||
mDeepLAPIKeyEditor->setText(deepl_key["id"].asString());
|
||||
mDeepLAPIKeyEditor->setTentative(false);
|
||||
mDeepLAPIDomainCombo->setValue(deepl_key["domain"]);
|
||||
verifyKey(LLTranslate::SERVICE_DEEPL, deepl_key, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
mDeepLAPIKeyEditor->setTentative(TRUE);
|
||||
mDeepLKeyVerified = FALSE;
|
||||
}
|
||||
|
||||
updateControlsEnabledState();
|
||||
}
|
||||
|
||||
|
|
@ -158,6 +195,17 @@ void LLFloaterTranslationSettings::setGoogleVerified(bool ok, bool alert, S32 st
|
|||
updateControlsEnabledState();
|
||||
}
|
||||
|
||||
void LLFloaterTranslationSettings::setDeepLVerified(bool ok, bool alert, S32 status)
|
||||
{
|
||||
if (alert)
|
||||
{
|
||||
showAlert(ok ? "deepl_api_key_verified" : "deepl_api_key_not_verified", status);
|
||||
}
|
||||
|
||||
mDeepLKeyVerified = ok;
|
||||
updateControlsEnabledState();
|
||||
}
|
||||
|
||||
std::string LLFloaterTranslationSettings::getSelectedService() const
|
||||
{
|
||||
return mTranslationServiceRadioGroup->getSelectedValue().asString();
|
||||
|
|
@ -183,6 +231,17 @@ std::string LLFloaterTranslationSettings::getEnteredGoogleKey() const
|
|||
return mGoogleAPIKeyEditor->getTentative() ? LLStringUtil::null : mGoogleAPIKeyEditor->getText();
|
||||
}
|
||||
|
||||
LLSD LLFloaterTranslationSettings::getEnteredDeepLKey() const
|
||||
{
|
||||
LLSD key;
|
||||
if (!mDeepLAPIKeyEditor->getTentative())
|
||||
{
|
||||
key["domain"] = mDeepLAPIDomainCombo->getValue();
|
||||
key["id"] = mDeepLAPIKeyEditor->getText();
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
void LLFloaterTranslationSettings::showAlert(const std::string& msg_name, S32 status) const
|
||||
{
|
||||
LLStringUtil::format_map_t string_args;
|
||||
|
|
@ -202,29 +261,42 @@ void LLFloaterTranslationSettings::updateControlsEnabledState()
|
|||
std::string service = getSelectedService();
|
||||
bool azure_selected = service == "azure";
|
||||
bool google_selected = service == "google";
|
||||
bool deepl_selected = service == "deepl";
|
||||
|
||||
mTranslationServiceRadioGroup->setEnabled(on);
|
||||
mLanguageCombo->setEnabled(on);
|
||||
|
||||
getChild<LLTextBox>("azure_api_endoint_label")->setEnabled(on);
|
||||
mAzureAPIEndpointEditor->setEnabled(on);
|
||||
// MS Azure
|
||||
getChild<LLTextBox>("azure_api_endoint_label")->setEnabled(on);
|
||||
mAzureAPIEndpointEditor->setEnabled(on && azure_selected);
|
||||
getChild<LLTextBox>("azure_api_key_label")->setEnabled(on);
|
||||
mAzureAPIKeyEditor->setEnabled(on);
|
||||
mAzureAPIKeyEditor->setEnabled(on && azure_selected);
|
||||
getChild<LLTextBox>("azure_api_region_label")->setEnabled(on);
|
||||
mAzureAPIRegionEditor->setEnabled(on);
|
||||
mAzureAPIRegionEditor->setEnabled(on && azure_selected);
|
||||
|
||||
getChild<LLTextBox>("google_api_key_label")->setEnabled(on);
|
||||
mGoogleAPIKeyEditor->setEnabled(on);
|
||||
mAzureVerifyBtn->setEnabled(on && azure_selected &&
|
||||
!mAzureKeyVerified && getEnteredAzureKey().isMap());
|
||||
|
||||
mAzureAPIKeyEditor->setEnabled(on && azure_selected);
|
||||
mGoogleAPIKeyEditor->setEnabled(on && google_selected);
|
||||
// Google
|
||||
getChild<LLTextBox>("google_api_key_label")->setEnabled(on);
|
||||
mGoogleAPIKeyEditor->setEnabled(on && google_selected);
|
||||
|
||||
mAzureVerifyBtn->setEnabled(on && azure_selected &&
|
||||
!mAzureKeyVerified && getEnteredAzureKey().isMap());
|
||||
mGoogleVerifyBtn->setEnabled(on && google_selected &&
|
||||
!mGoogleKeyVerified && !getEnteredGoogleKey().empty());
|
||||
|
||||
bool service_verified = (azure_selected && mAzureKeyVerified) || (google_selected && mGoogleKeyVerified);
|
||||
// DeepL
|
||||
getChild<LLTextBox>("deepl_api_domain_label")->setEnabled(on);
|
||||
mDeepLAPIDomainCombo->setEnabled(on && deepl_selected);
|
||||
getChild<LLTextBox>("deepl_api_key_label")->setEnabled(on);
|
||||
mDeepLAPIKeyEditor->setEnabled(on && deepl_selected);
|
||||
|
||||
mDeepLVerifyBtn->setEnabled(on && deepl_selected &&
|
||||
!mDeepLKeyVerified && getEnteredDeepLKey().isMap());
|
||||
|
||||
bool service_verified =
|
||||
(azure_selected && mAzureKeyVerified)
|
||||
|| (google_selected && mGoogleKeyVerified)
|
||||
|| (deepl_selected && mDeepLKeyVerified);
|
||||
gSavedPerAccountSettings.setBOOL("TranslatingEnabled", service_verified);
|
||||
|
||||
mOKBtn->setEnabled(!on || service_verified);
|
||||
|
|
@ -250,6 +322,9 @@ void LLFloaterTranslationSettings::setVerificationStatus(int service, bool ok, b
|
|||
case LLTranslate::SERVICE_GOOGLE:
|
||||
floater->setGoogleVerified(ok, alert, status);
|
||||
break;
|
||||
case LLTranslate::SERVICE_DEEPL:
|
||||
floater->setDeepLVerified(ok, alert, status);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -276,8 +351,7 @@ void LLFloaterTranslationSettings::onEditorFocused(LLFocusableElement* control)
|
|||
void LLFloaterTranslationSettings::onAzureKeyEdited()
|
||||
{
|
||||
if (mAzureAPIKeyEditor->isDirty()
|
||||
|| mAzureAPIRegionEditor->isDirty()
|
||||
|| mAzureAPIEndpointEditor->getValue().isString())
|
||||
|| mAzureAPIRegionEditor->isDirty())
|
||||
{
|
||||
// todo: verify mAzureAPIEndpointEditor url
|
||||
setAzureVerified(false, false, 0);
|
||||
|
|
@ -292,6 +366,14 @@ void LLFloaterTranslationSettings::onGoogleKeyEdited()
|
|||
}
|
||||
}
|
||||
|
||||
void LLFloaterTranslationSettings::onDeepLKeyEdited()
|
||||
{
|
||||
if (mDeepLAPIKeyEditor->isDirty())
|
||||
{
|
||||
setDeepLVerified(false, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterTranslationSettings::onBtnAzureVerify()
|
||||
{
|
||||
LLSD key = getEnteredAzureKey();
|
||||
|
|
@ -309,15 +391,28 @@ void LLFloaterTranslationSettings::onBtnGoogleVerify()
|
|||
verifyKey(LLTranslate::SERVICE_GOOGLE, LLSD(key));
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterTranslationSettings::onBtnDeepLVerify()
|
||||
{
|
||||
LLSD key = getEnteredDeepLKey();
|
||||
if (key.isMap())
|
||||
{
|
||||
verifyKey(LLTranslate::SERVICE_DEEPL, key);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFloaterTranslationSettings::onClose(bool app_quitting)
|
||||
{
|
||||
std::string service = gSavedSettings.getString("TranslationService");
|
||||
bool azure_selected = service == "azure";
|
||||
bool google_selected = service == "google";
|
||||
bool deepl_selected = service == "deepl";
|
||||
|
||||
bool service_verified = (azure_selected && mAzureKeyVerified) || (google_selected && mGoogleKeyVerified);
|
||||
gSavedPerAccountSettings.setBOOL("TranslatingEnabled", service_verified);
|
||||
|
||||
bool service_verified =
|
||||
(azure_selected && mAzureKeyVerified)
|
||||
|| (google_selected && mGoogleKeyVerified)
|
||||
|| (deepl_selected && mDeepLKeyVerified);
|
||||
gSavedPerAccountSettings.setBOOL("TranslatingEnabled", service_verified);
|
||||
}
|
||||
void LLFloaterTranslationSettings::onBtnOK()
|
||||
{
|
||||
|
|
@ -326,6 +421,7 @@ void LLFloaterTranslationSettings::onBtnOK()
|
|||
gSavedSettings.setString("TranslationService", getSelectedService());
|
||||
gSavedSettings.setLLSD("AzureTranslateAPIKey", getEnteredAzureKey());
|
||||
gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey());
|
||||
gSavedSettings.setLLSD("DeepLTranslateAPIKey", getEnteredDeepLKey());
|
||||
|
||||
closeFloater(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,12 +44,14 @@ public:
|
|||
|
||||
void setAzureVerified(bool ok, bool alert, S32 status);
|
||||
void setGoogleVerified(bool ok, bool alert, S32 status);
|
||||
void setDeepLVerified(bool ok, bool alert, S32 status);
|
||||
void onClose(bool app_quitting);
|
||||
|
||||
private:
|
||||
std::string getSelectedService() const;
|
||||
LLSD getEnteredAzureKey() const;
|
||||
std::string getEnteredGoogleKey() const;
|
||||
LLSD getEnteredDeepLKey() const;
|
||||
void showAlert(const std::string& msg_name, S32 status) const;
|
||||
void updateControlsEnabledState();
|
||||
void verifyKey(int service, const LLSD& key, bool alert = true);
|
||||
|
|
@ -57,25 +59,31 @@ private:
|
|||
void onEditorFocused(LLFocusableElement* control);
|
||||
void onAzureKeyEdited();
|
||||
void onGoogleKeyEdited();
|
||||
void onDeepLKeyEdited();
|
||||
void onBtnAzureVerify();
|
||||
void onBtnGoogleVerify();
|
||||
void onBtnDeepLVerify();
|
||||
void onBtnOK();
|
||||
|
||||
static void setVerificationStatus(int service, bool alert, bool ok, S32 status);
|
||||
|
||||
LLCheckBoxCtrl* mMachineTranslationCB;
|
||||
LLComboBox* mLanguageCombo;
|
||||
LLComboBox* mAzureAPIEndpointEditor;;
|
||||
LLComboBox* mAzureAPIEndpointEditor;
|
||||
LLLineEditor* mAzureAPIKeyEditor;
|
||||
LLLineEditor* mAzureAPIRegionEditor;
|
||||
LLLineEditor* mGoogleAPIKeyEditor;
|
||||
LLComboBox* mDeepLAPIDomainCombo;
|
||||
LLLineEditor* mDeepLAPIKeyEditor;
|
||||
LLRadioGroup* mTranslationServiceRadioGroup;
|
||||
LLButton* mAzureVerifyBtn;
|
||||
LLButton* mGoogleVerifyBtn;
|
||||
LLButton* mDeepLVerifyBtn;
|
||||
LLButton* mOKBtn;
|
||||
|
||||
bool mAzureKeyVerified;
|
||||
bool mGoogleKeyVerified;
|
||||
bool mDeepLKeyVerified;
|
||||
};
|
||||
|
||||
#endif // LL_LLFLOATERTRANSLATIONSETTINGS_H
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ public:
|
|||
|
||||
/*virtual*/ void onOpen(const LLSD& notification_id);
|
||||
/*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask);
|
||||
/*virtual*/ void deleteAllChildren();
|
||||
/*virtual*/ void removeChild(LLView* child);
|
||||
private:
|
||||
void onToastDestroy(LLToast * toast);
|
||||
|
|
@ -122,6 +123,12 @@ BOOL LLInspectToast::handleToolTip(S32 x, S32 y, MASK mask)
|
|||
return LLFloater::handleToolTip(x, y, mask);
|
||||
}
|
||||
|
||||
void LLInspectToast::deleteAllChildren()
|
||||
{
|
||||
mPanel = NULL;
|
||||
LLInspect::deleteAllChildren();
|
||||
}
|
||||
|
||||
// virtual
|
||||
void LLInspectToast::removeChild(LLView* child)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -662,7 +662,11 @@ const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(
|
|||
}
|
||||
}
|
||||
|
||||
if(rv.isNull() && create_folder && root_id.notNull())
|
||||
if(rv.isNull()
|
||||
&& root_id.notNull()
|
||||
&& create_folder
|
||||
&& preferred_type != LLFolderType::FT_MARKETPLACE_LISTINGS
|
||||
&& preferred_type != LLFolderType::FT_OUTBOX)
|
||||
{
|
||||
|
||||
if (isInventoryUsable())
|
||||
|
|
|
|||
|
|
@ -133,7 +133,9 @@ public:
|
|||
LLCore::HttpOptions::ptr_t options,
|
||||
LLCore::HttpHeaders::ptr_t headers,
|
||||
const std::string & url,
|
||||
const std::string & msg) const = 0;
|
||||
const std::string & msg,
|
||||
const std::string& from_lang,
|
||||
const std::string& to_lang) const = 0;
|
||||
virtual LLSD verifyAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter,
|
||||
LLCore::HttpRequest::ptr_t request,
|
||||
LLCore::HttpOptions::ptr_t options,
|
||||
|
|
@ -230,7 +232,7 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s
|
|||
return;
|
||||
}
|
||||
|
||||
LLSD result = sendMessageAndSuspend(httpAdapter, httpRequest, httpOpts, httpHeaders, url, msg);
|
||||
LLSD result = sendMessageAndSuspend(httpAdapter, httpRequest, httpOpts, httpHeaders, url, msg, fromTo.first, fromTo.second);
|
||||
|
||||
if (LLApp::isQuitting())
|
||||
{
|
||||
|
|
@ -331,7 +333,9 @@ public:
|
|||
LLCore::HttpOptions::ptr_t options,
|
||||
LLCore::HttpHeaders::ptr_t headers,
|
||||
const std::string & url,
|
||||
const std::string & msg) const override;
|
||||
const std::string & msg,
|
||||
const std::string& from_lang,
|
||||
const std::string& to_lang) const override;
|
||||
|
||||
LLSD verifyAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter,
|
||||
LLCore::HttpRequest::ptr_t request,
|
||||
|
|
@ -508,7 +512,9 @@ LLSD LLGoogleTranslationHandler::sendMessageAndSuspend(LLCoreHttpUtil::HttpCorou
|
|||
LLCore::HttpOptions::ptr_t options,
|
||||
LLCore::HttpHeaders::ptr_t headers,
|
||||
const std::string & url,
|
||||
const std::string & msg) const
|
||||
const std::string & msg,
|
||||
const std::string& from_lang,
|
||||
const std::string& to_lang) const
|
||||
{
|
||||
return adapter->getRawAndSuspend(request, url, options, headers);
|
||||
}
|
||||
|
|
@ -558,7 +564,9 @@ public:
|
|||
LLCore::HttpOptions::ptr_t options,
|
||||
LLCore::HttpHeaders::ptr_t headers,
|
||||
const std::string & url,
|
||||
const std::string & msg) const override;
|
||||
const std::string & msg,
|
||||
const std::string& from_lang,
|
||||
const std::string& to_lang) const override;
|
||||
|
||||
LLSD verifyAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter,
|
||||
LLCore::HttpRequest::ptr_t request,
|
||||
|
|
@ -728,7 +736,7 @@ bool LLAzureTranslationHandler::parseResponse(
|
|||
// virtual
|
||||
bool LLAzureTranslationHandler::isConfigured() const
|
||||
{
|
||||
return !getAPIKey().isMap();
|
||||
return getAPIKey().isMap();
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
@ -814,7 +822,9 @@ LLSD LLAzureTranslationHandler::sendMessageAndSuspend(LLCoreHttpUtil::HttpCorout
|
|||
LLCore::HttpOptions::ptr_t options,
|
||||
LLCore::HttpHeaders::ptr_t headers,
|
||||
const std::string & url,
|
||||
const std::string & msg) const
|
||||
const std::string & msg,
|
||||
const std::string& from_lang,
|
||||
const std::string& to_lang) const
|
||||
{
|
||||
LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray);
|
||||
LLCore::BufferArrayStream outs(rawbody.get());
|
||||
|
|
@ -838,6 +848,259 @@ LLSD LLAzureTranslationHandler::verifyAndSuspend(LLCoreHttpUtil::HttpCoroutineAd
|
|||
return adapter->postRawAndSuspend(request, url, rawbody, options, headers);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
/// DeepL Translator API handler.
|
||||
class LLDeepLTranslationHandler: public LLTranslationAPIHandler
|
||||
{
|
||||
LOG_CLASS(LLDeepLTranslationHandler);
|
||||
|
||||
public:
|
||||
std::string getTranslateURL(
|
||||
const std::string& from_lang,
|
||||
const std::string& to_lang,
|
||||
const std::string& text) const override;
|
||||
std::string getKeyVerificationURL(
|
||||
const LLSD& key) const override;
|
||||
bool checkVerificationResponse(
|
||||
const LLSD& response,
|
||||
int status) const override;
|
||||
bool parseResponse(
|
||||
const LLSD& http_response,
|
||||
int& status,
|
||||
const std::string& body,
|
||||
std::string& translation,
|
||||
std::string& detected_lang,
|
||||
std::string& err_msg) const override;
|
||||
bool isConfigured() const override;
|
||||
|
||||
LLTranslate::EService getCurrentService() override
|
||||
{
|
||||
return LLTranslate::EService::SERVICE_DEEPL;
|
||||
}
|
||||
|
||||
void verifyKey(const LLSD& key, LLTranslate::KeyVerificationResult_fn fnc) override;
|
||||
|
||||
void initHttpHeader(LLCore::HttpHeaders::ptr_t headers, const std::string& user_agent) const override;
|
||||
void initHttpHeader(LLCore::HttpHeaders::ptr_t headers, const std::string& user_agent, const LLSD& key) const override;
|
||||
LLSD sendMessageAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter,
|
||||
LLCore::HttpRequest::ptr_t request,
|
||||
LLCore::HttpOptions::ptr_t options,
|
||||
LLCore::HttpHeaders::ptr_t headers,
|
||||
const std::string& url,
|
||||
const std::string& msg,
|
||||
const std::string& from_lang,
|
||||
const std::string& to_lang) const override;
|
||||
|
||||
LLSD verifyAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter,
|
||||
LLCore::HttpRequest::ptr_t request,
|
||||
LLCore::HttpOptions::ptr_t options,
|
||||
LLCore::HttpHeaders::ptr_t headers,
|
||||
const std::string& url) const override;
|
||||
private:
|
||||
static std::string parseErrorResponse(
|
||||
const std::string& body);
|
||||
static LLSD getAPIKey();
|
||||
static std::string getAPILanguageCode(const std::string& lang);
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// virtual
|
||||
std::string LLDeepLTranslationHandler::getTranslateURL(
|
||||
const std::string& from_lang,
|
||||
const std::string& to_lang,
|
||||
const std::string& text) const
|
||||
{
|
||||
std::string url;
|
||||
LLSD key = getAPIKey();
|
||||
if (key.isMap())
|
||||
{
|
||||
url = key["domain"].asString();
|
||||
|
||||
if (*url.rbegin() != '/')
|
||||
{
|
||||
url += "/";
|
||||
}
|
||||
url += std::string("v2/translate");
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
|
||||
// virtual
|
||||
std::string LLDeepLTranslationHandler::getKeyVerificationURL(
|
||||
const LLSD& key) const
|
||||
{
|
||||
std::string url;
|
||||
if (key.isMap())
|
||||
{
|
||||
url = key["domain"].asString();
|
||||
|
||||
if (*url.rbegin() != '/')
|
||||
{
|
||||
url += "/";
|
||||
}
|
||||
url += std::string("v2/translate");
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
//virtual
|
||||
bool LLDeepLTranslationHandler::checkVerificationResponse(
|
||||
const LLSD& response,
|
||||
int status) const
|
||||
{
|
||||
return status == HTTP_OK;
|
||||
}
|
||||
|
||||
// virtual
|
||||
bool LLDeepLTranslationHandler::parseResponse(
|
||||
const LLSD& http_response,
|
||||
int& status,
|
||||
const std::string& body,
|
||||
std::string& translation,
|
||||
std::string& detected_lang,
|
||||
std::string& err_msg) const
|
||||
{
|
||||
if (status != HTTP_OK)
|
||||
{
|
||||
if (http_response.has("error_body"))
|
||||
err_msg = parseErrorResponse(http_response["error_body"].asString());
|
||||
return false;
|
||||
}
|
||||
|
||||
//Example:
|
||||
// "{\"translations\":[{\"detected_source_language\":\"EN\",\"text\":\"test\"}]}"
|
||||
|
||||
Json::Value root;
|
||||
Json::Reader reader;
|
||||
|
||||
if (!reader.parse(body, root))
|
||||
{
|
||||
err_msg = reader.getFormatedErrorMessages();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!root.isObject()
|
||||
|| !root.isMember("translations")) // empty response? should not happen
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Request succeeded, extract translation from the response.
|
||||
const Json::Value& translations = root["translations"];
|
||||
if (!translations.isArray() || translations.size() == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const Json::Value& data= translations[0U];
|
||||
if (!data.isObject()
|
||||
|| !data.isMember("detected_source_language")
|
||||
|| !data.isMember("text"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
detected_lang = data["detected_source_language"].asString();
|
||||
LLStringUtil::toLower(detected_lang);
|
||||
translation = data["text"].asString();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// virtual
|
||||
bool LLDeepLTranslationHandler::isConfigured() const
|
||||
{
|
||||
return getAPIKey().isMap();
|
||||
}
|
||||
|
||||
//static
|
||||
std::string LLDeepLTranslationHandler::parseErrorResponse(
|
||||
const std::string& body)
|
||||
{
|
||||
// DeepL doesn't seem to have any error handling beyoun http codes
|
||||
return std::string();
|
||||
}
|
||||
|
||||
// static
|
||||
LLSD LLDeepLTranslationHandler::getAPIKey()
|
||||
{
|
||||
static LLCachedControl<LLSD> deepl_key(gSavedSettings, "DeepLTranslateAPIKey");
|
||||
return deepl_key;
|
||||
}
|
||||
|
||||
// static
|
||||
std::string LLDeepLTranslationHandler::getAPILanguageCode(const std::string& lang)
|
||||
{
|
||||
return lang == "zh" ? "zh-CHT" : lang; // treat Chinese as Traditional Chinese
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
void LLDeepLTranslationHandler::verifyKey(const LLSD& key, LLTranslate::KeyVerificationResult_fn fnc)
|
||||
{
|
||||
LLCoros::instance().launch("DeepL /Verify Key", boost::bind(&LLTranslationAPIHandler::verifyKeyCoro,
|
||||
this, LLTranslate::SERVICE_DEEPL, key, fnc));
|
||||
}
|
||||
/*virtual*/
|
||||
void LLDeepLTranslationHandler::initHttpHeader(
|
||||
LLCore::HttpHeaders::ptr_t headers,
|
||||
const std::string& user_agent) const
|
||||
{
|
||||
initHttpHeader(headers, user_agent, getAPIKey());
|
||||
}
|
||||
|
||||
/*virtual*/
|
||||
void LLDeepLTranslationHandler::initHttpHeader(
|
||||
LLCore::HttpHeaders::ptr_t headers,
|
||||
const std::string& user_agent,
|
||||
const LLSD& key) const
|
||||
{
|
||||
headers->append(HTTP_OUT_HEADER_CONTENT_TYPE, "application/x-www-form-urlencoded");
|
||||
headers->append(HTTP_OUT_HEADER_USER_AGENT, user_agent);
|
||||
|
||||
if (key.has("id"))
|
||||
{
|
||||
std::string authkey = "DeepL-Auth-Key " + key["id"].asString();
|
||||
headers->append(HTTP_OUT_HEADER_AUTHORIZATION, authkey);
|
||||
}
|
||||
}
|
||||
|
||||
LLSD LLDeepLTranslationHandler::sendMessageAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter,
|
||||
LLCore::HttpRequest::ptr_t request,
|
||||
LLCore::HttpOptions::ptr_t options,
|
||||
LLCore::HttpHeaders::ptr_t headers,
|
||||
const std::string& url,
|
||||
const std::string& msg,
|
||||
const std::string& from_lang,
|
||||
const std::string& to_lang) const
|
||||
{
|
||||
LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray);
|
||||
LLCore::BufferArrayStream outs(rawbody.get());
|
||||
outs << "text=";
|
||||
std::string escaped_string = LLURI::escape(msg);
|
||||
outs << escaped_string;
|
||||
outs << "&target_lang=";
|
||||
std::string lang = to_lang;
|
||||
LLStringUtil::toUpper(lang);
|
||||
outs << lang;
|
||||
|
||||
return adapter->postRawAndSuspend(request, url, rawbody, options, headers);
|
||||
}
|
||||
|
||||
LLSD LLDeepLTranslationHandler::verifyAndSuspend(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter,
|
||||
LLCore::HttpRequest::ptr_t request,
|
||||
LLCore::HttpOptions::ptr_t options,
|
||||
LLCore::HttpHeaders::ptr_t headers,
|
||||
const std::string& url) const
|
||||
{
|
||||
LLCore::BufferArray::ptr_t rawbody(new LLCore::BufferArray);
|
||||
LLCore::BufferArrayStream outs(rawbody.get());
|
||||
outs << "text=&target_lang=EN";
|
||||
|
||||
return adapter->postRawAndSuspend(request, url, rawbody, options, headers);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
LLTranslate::LLTranslate():
|
||||
mCharsSeen(0),
|
||||
|
|
@ -867,6 +1130,11 @@ std::string LLTranslate::addNoTranslateTags(std::string mesg)
|
|||
return mesg;
|
||||
}
|
||||
|
||||
if (getPreferredHandler().getCurrentService() == SERVICE_DEEPL)
|
||||
{
|
||||
return mesg;
|
||||
}
|
||||
|
||||
if (getPreferredHandler().getCurrentService() == SERVICE_AZURE)
|
||||
{
|
||||
// https://learn.microsoft.com/en-us/azure/cognitive-services/translator/prevent-translation
|
||||
|
|
@ -892,6 +1160,10 @@ std::string LLTranslate::removeNoTranslateTags(std::string mesg)
|
|||
{
|
||||
return mesg;
|
||||
}
|
||||
if (getPreferredHandler().getCurrentService() == SERVICE_DEEPL)
|
||||
{
|
||||
return mesg;
|
||||
}
|
||||
|
||||
if (getPreferredHandler().getCurrentService() == SERVICE_AZURE)
|
||||
{
|
||||
|
|
@ -997,6 +1269,14 @@ LLTranslationAPIHandler& LLTranslate::getPreferredHandler()
|
|||
{
|
||||
service = SERVICE_GOOGLE;
|
||||
}
|
||||
if (service_str == "azure")
|
||||
{
|
||||
service = SERVICE_AZURE;
|
||||
}
|
||||
if (service_str == "deepl")
|
||||
{
|
||||
service = SERVICE_DEEPL;
|
||||
}
|
||||
|
||||
return getHandler(service);
|
||||
}
|
||||
|
|
@ -1006,11 +1286,18 @@ LLTranslationAPIHandler& LLTranslate::getHandler(EService service)
|
|||
{
|
||||
static LLGoogleTranslationHandler google;
|
||||
static LLAzureTranslationHandler azure;
|
||||
static LLDeepLTranslationHandler deepl;
|
||||
|
||||
if (service == SERVICE_GOOGLE)
|
||||
{
|
||||
return google;
|
||||
}
|
||||
switch (service)
|
||||
{
|
||||
case SERVICE_AZURE:
|
||||
return azure;
|
||||
case SERVICE_GOOGLE:
|
||||
return google;
|
||||
case SERVICE_DEEPL:
|
||||
return deepl;
|
||||
}
|
||||
|
||||
return azure;
|
||||
|
||||
return azure;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ public :
|
|||
typedef enum e_service {
|
||||
SERVICE_AZURE,
|
||||
SERVICE_GOOGLE,
|
||||
SERVICE_DEEPL,
|
||||
} EService;
|
||||
|
||||
typedef boost::function<void(EService, bool, S32)> KeyVerificationResult_fn;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||
<floater
|
||||
legacy_header_height="18"
|
||||
height="370"
|
||||
height="470"
|
||||
layout="topleft"
|
||||
name="floater_translation_settings"
|
||||
help_topic="translation_settings"
|
||||
|
|
@ -11,9 +11,11 @@
|
|||
|
||||
<string name="azure_api_key_not_verified">Azure service identifier not verified. Status: [STATUS]. Please check your settings and try again.</string>
|
||||
<string name="google_api_key_not_verified">Google API key not verified. Status: [STATUS]. Please check your key and try again.</string>
|
||||
<string name="deepl_api_key_not_verified">DeepL Auth Key key not verified. Status: [STATUS]. Please check your key and try again.</string>
|
||||
|
||||
<string name="azure_api_key_verified">Azure service identifier verified.</string>
|
||||
<string name="google_api_key_verified">Google API key verified.</string>
|
||||
<string name="deepl_api_key_verified">DeepL API key verified.</string>
|
||||
|
||||
<check_box
|
||||
height="16"
|
||||
|
|
@ -128,7 +130,7 @@
|
|||
|
||||
<radio_group
|
||||
follows="top|left"
|
||||
height="140"
|
||||
height="260"
|
||||
layout="topleft"
|
||||
left_delta="10"
|
||||
name="translation_service_rg"
|
||||
|
|
@ -145,6 +147,12 @@
|
|||
layout="topleft"
|
||||
name="google"
|
||||
top_pad="115" />
|
||||
<radio_item
|
||||
initial_value="deepl"
|
||||
label="DeepL Translator"
|
||||
layout="topleft"
|
||||
name="deepl"
|
||||
top_pad="61" />
|
||||
</radio_group>
|
||||
|
||||
<text
|
||||
|
|
@ -154,7 +162,7 @@
|
|||
left="185"
|
||||
length="1"
|
||||
name="google_links_text"
|
||||
top_pad="-142"
|
||||
top_pad="-262"
|
||||
type="string"
|
||||
width="100">
|
||||
[https://learn.microsoft.com/en-us/azure/cognitive-services/translator/create-translator-resource Setup]
|
||||
|
|
@ -286,7 +294,7 @@
|
|||
left_pad="10"
|
||||
name="verify_google_api_key_btn"
|
||||
top_delta="-2"
|
||||
width="90" />
|
||||
width="90" />
|
||||
|
||||
<text
|
||||
follows="top|right"
|
||||
|
|
@ -301,6 +309,87 @@
|
|||
[http://code.google.com/apis/language/translate/v2/pricing.html Pricing] | [https://code.google.com/apis/console Stats]
|
||||
</text>
|
||||
|
||||
<text
|
||||
type="string"
|
||||
length="1"
|
||||
follows="top|right"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
left="70"
|
||||
name="deepl_api_domain_label"
|
||||
top_pad="80"
|
||||
width="85">
|
||||
Domain:
|
||||
</text>
|
||||
|
||||
<combo_box
|
||||
allow_text_entry="false"
|
||||
follows="left|top"
|
||||
name="deepl_api_domain_combo"
|
||||
height="23"
|
||||
left_pad="10"
|
||||
width="140"
|
||||
top_delta="-4"
|
||||
max_chars="512"
|
||||
value="https://api-free.deepl.com"
|
||||
combo_button.scale_image="true">
|
||||
<combo_box.item
|
||||
label="DeepL Free"
|
||||
name="global"
|
||||
value="https://api-free.deepl.com" />
|
||||
<combo_box.item
|
||||
label="DeepL Pro"
|
||||
name="api-apc"
|
||||
value="https://api.deepl.com" />
|
||||
</combo_box>
|
||||
|
||||
<text
|
||||
follows="top|right"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
left="70"
|
||||
length="1"
|
||||
name="deepl_api_key_label"
|
||||
top_pad="11"
|
||||
type="string"
|
||||
width="85">
|
||||
DeepL API key:
|
||||
</text>
|
||||
|
||||
<line_editor
|
||||
default_text="Enter DeepL API key and click "Verify""
|
||||
follows="top|left"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
left_pad="10"
|
||||
max_length_chars="50"
|
||||
top_delta="-4"
|
||||
name="deepl_api_key"
|
||||
width="210" />
|
||||
|
||||
<button
|
||||
follows="left|top"
|
||||
height="23"
|
||||
label="Verify"
|
||||
layout="topleft"
|
||||
left_pad="10"
|
||||
name="verify_deepl_api_key_btn"
|
||||
top_delta="-2"
|
||||
width="90" />
|
||||
|
||||
<text
|
||||
follows="top|right"
|
||||
height="20"
|
||||
layout="topleft"
|
||||
left="185"
|
||||
length="1"
|
||||
name="deepl_links_text"
|
||||
top_delta="-53"
|
||||
type="string"
|
||||
width="100">
|
||||
[https://www.deepl.com/pro/select-country?cta=header-prices Pricing]
|
||||
</text>
|
||||
|
||||
<button
|
||||
follows="left|top"
|
||||
height="23"
|
||||
|
|
|
|||
Loading…
Reference in New Issue