diff options
-rw-r--r-- | indra/newview/llfloatertranslationsettings.cpp | 214 | ||||
-rw-r--r-- | indra/newview/llfloatertranslationsettings.h | 22 | ||||
-rw-r--r-- | indra/newview/lltranslate.cpp | 107 | ||||
-rw-r--r-- | indra/newview/lltranslate.h | 37 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_translation_settings.xml | 52 |
5 files changed, 363 insertions, 69 deletions
diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index 4079fdf482..ac3e7ac8fa 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -29,6 +29,7 @@ #include "llfloatertranslationsettings.h" // Viewer includes +#include "lltranslate.h" #include "llviewercontrol.h" // for gSavedSettings // Linden library includes @@ -40,6 +41,41 @@ #include "llnotificationsutil.h" #include "llradiogroup.h" +class EnteredKeyVerifier : public LLTranslate::KeyVerificationReceiver +{ +public: + EnteredKeyVerifier(LLTranslate::EService service, bool alert) + : LLTranslate::KeyVerificationReceiver(service) + , mAlert(alert) + { + } + +private: + /*virtual*/ void setVerificationStatus(bool ok) + { + LLFloaterTranslationSettings* floater = + LLFloaterReg::getTypedInstance<LLFloaterTranslationSettings>("prefs_translation"); + + if (!floater) + { + llwarns << "Cannot find translation settings floater" << llendl; + return; + } + + switch (getService()) + { + case LLTranslate::SERVICE_BING: + floater->setBingVerified(ok, mAlert); + break; + case LLTranslate::SERVICE_GOOGLE: + floater->setGoogleVerified(ok, mAlert); + break; + } + } + + bool mAlert; +}; + LLFloaterTranslationSettings::LLFloaterTranslationSettings(const LLSD& key) : LLFloater(key) , mMachineTranslationCB(NULL) @@ -47,6 +83,11 @@ LLFloaterTranslationSettings::LLFloaterTranslationSettings(const LLSD& key) , mTranslationServiceRadioGroup(NULL) , mBingAPIKeyEditor(NULL) , mGoogleAPIKeyEditor(NULL) +, mBingVerifyBtn(NULL) +, mGoogleVerifyBtn(NULL) +, mOKBtn(NULL) +, mBingKeyVerified(false) +, mGoogleKeyVerified(false) { } @@ -58,11 +99,21 @@ BOOL LLFloaterTranslationSettings::postBuild() mTranslationServiceRadioGroup = getChild<LLRadioGroup>("translation_service_rg"); mBingAPIKeyEditor = getChild<LLLineEditor>("bing_api_key"); mGoogleAPIKeyEditor = getChild<LLLineEditor>("google_api_key"); + mBingVerifyBtn = getChild<LLButton>("verify_bing_api_key_btn"); + mGoogleVerifyBtn = getChild<LLButton>("verify_google_api_key_btn"); + mOKBtn = getChild<LLButton>("ok_btn"); mMachineTranslationCB->setCommitCallback(boost::bind(&LLFloaterTranslationSettings::updateControlsEnabledState, this)); mTranslationServiceRadioGroup->setCommitCallback(boost::bind(&LLFloaterTranslationSettings::updateControlsEnabledState, this)); - getChild<LLButton>("ok_btn")->setClickedCallback(boost::bind(&LLFloaterTranslationSettings::onBtnOK, this)); + mOKBtn->setClickedCallback(boost::bind(&LLFloaterTranslationSettings::onBtnOK, this)); getChild<LLButton>("cancel_btn")->setClickedCallback(boost::bind(&LLFloater::closeFloater, this, false)); + mBingVerifyBtn->setClickedCallback(boost::bind(&LLFloaterTranslationSettings::onBtnBingVerify, this)); + mGoogleVerifyBtn->setClickedCallback(boost::bind(&LLFloaterTranslationSettings::onBtnGoogleVerify, this)); + + mBingAPIKeyEditor->setFocusReceivedCallback(boost::bind(&LLFloaterTranslationSettings::onEditorFocused, this, _1)); + mBingAPIKeyEditor->setKeystrokeCallback(boost::bind(&LLFloaterTranslationSettings::onBingKeyEdited, this), NULL); + mGoogleAPIKeyEditor->setFocusReceivedCallback(boost::bind(&LLFloaterTranslationSettings::onEditorFocused, this, _1)); + mGoogleAPIKeyEditor->setKeystrokeCallback(boost::bind(&LLFloaterTranslationSettings::onGoogleKeyEdited, this), NULL); center(); return TRUE; @@ -74,43 +125,78 @@ void LLFloaterTranslationSettings::onOpen(const LLSD& key) mMachineTranslationCB->setValue(gSavedSettings.getBOOL("TranslateChat")); mLanguageCombo->setSelectedByValue(gSavedSettings.getString("TranslateLanguage"), TRUE); mTranslationServiceRadioGroup->setSelectedByValue(gSavedSettings.getString("TranslationService"), TRUE); - mBingAPIKeyEditor->setText(gSavedSettings.getString("BingTranslateAPIKey")); - mGoogleAPIKeyEditor->setText(gSavedSettings.getString("GoogleTranslateAPIKey")); + + std::string bing_key = gSavedSettings.getString("BingTranslateAPIKey"); + if (!bing_key.empty()) + { + mBingAPIKeyEditor->setText(bing_key); + mBingAPIKeyEditor->setTentative(FALSE); + verifyKey(LLTranslate::SERVICE_BING, bing_key, false); + } + else + { + mBingAPIKeyEditor->setTentative(TRUE); + mBingKeyVerified = FALSE; + } + + std::string google_key = gSavedSettings.getString("GoogleTranslateAPIKey"); + if (!google_key.empty()) + { + mGoogleAPIKeyEditor->setText(google_key); + mGoogleAPIKeyEditor->setTentative(FALSE); + verifyKey(LLTranslate::SERVICE_GOOGLE, google_key, false); + } + else + { + mGoogleAPIKeyEditor->setTentative(TRUE); + mGoogleKeyVerified = FALSE; + } updateControlsEnabledState(); } -std::string LLFloaterTranslationSettings::getSelectedService() const +void LLFloaterTranslationSettings::setBingVerified(bool ok, bool alert) { - return mTranslationServiceRadioGroup->getSelectedValue().asString(); + if (alert) + { + showAlert(ok ? "bing_api_key_verified" : "bing_api_key_not_verified"); + } + + mBingKeyVerified = ok; + updateControlsEnabledState(); } -void LLFloaterTranslationSettings::showError(const std::string& err_name) const +void LLFloaterTranslationSettings::setGoogleVerified(bool ok, bool alert) { - LLSD args; - args["MESSAGE"] = getString(err_name); - LLNotificationsUtil::add("GenericAlert", args); + if (alert) + { + showAlert(ok ? "google_api_key_verified" : "google_api_key_not_verified"); + } + + mGoogleKeyVerified = ok; + updateControlsEnabledState(); } -bool LLFloaterTranslationSettings::validate() const +std::string LLFloaterTranslationSettings::getSelectedService() const { - bool translate_chat = mMachineTranslationCB->getValue().asBoolean(); - if (!translate_chat) return true; + return mTranslationServiceRadioGroup->getSelectedValue().asString(); +} - std::string service = getSelectedService(); - if (service == "bing" && mBingAPIKeyEditor->getText().empty()) - { - showError("no_bing_api_key"); - return false; - } +std::string LLFloaterTranslationSettings::getEnteredBingKey() const +{ + return mBingAPIKeyEditor->getTentative() ? LLStringUtil::null : mBingAPIKeyEditor->getText(); +} - if (service == "google" && mGoogleAPIKeyEditor->getText().empty()) - { - showError("no_google_api_key"); - return false; - } +std::string LLFloaterTranslationSettings::getEnteredGoogleKey() const +{ + return mGoogleAPIKeyEditor->getTentative() ? LLStringUtil::null : mGoogleAPIKeyEditor->getText(); +} - return true; +void LLFloaterTranslationSettings::showAlert(const std::string& msg_name) const +{ + LLSD args; + args["MESSAGE"] = getString(msg_name); + LLNotificationsUtil::add("GenericAlert", args); } void LLFloaterTranslationSettings::updateControlsEnabledState() @@ -118,6 +204,8 @@ void LLFloaterTranslationSettings::updateControlsEnabledState() // Enable/disable controls based on the checkbox value. bool on = mMachineTranslationCB->getValue().asBoolean(); std::string service = getSelectedService(); + bool bing_selected = service == "bing"; + bool google_selected = service == "google"; mTranslationServiceRadioGroup->setEnabled(on); mLanguageCombo->setEnabled(on); @@ -128,19 +216,77 @@ void LLFloaterTranslationSettings::updateControlsEnabledState() getChild<LLTextBox>("google_api_key_label")->setEnabled(on); mGoogleAPIKeyEditor->setEnabled(on); - mBingAPIKeyEditor->setEnabled(on && service == "bing"); - mGoogleAPIKeyEditor->setEnabled(on && service == "google"); + mBingAPIKeyEditor->setEnabled(on && bing_selected); + mGoogleAPIKeyEditor->setEnabled(on && google_selected); + + mBingVerifyBtn->setEnabled(on && bing_selected && + !mBingKeyVerified && !getEnteredBingKey().empty()); + mGoogleVerifyBtn->setEnabled(on && google_selected && + !mGoogleKeyVerified && !getEnteredGoogleKey().empty()); + + mOKBtn->setEnabled( + !on || ( + (bing_selected && mBingKeyVerified) || + (google_selected && mGoogleKeyVerified) + )); } -void LLFloaterTranslationSettings::onBtnOK() +void LLFloaterTranslationSettings::verifyKey(int service, const std::string& key, bool alert) { - if (validate()) + LLTranslate::KeyVerificationReceiverPtr receiver = + new EnteredKeyVerifier((LLTranslate::EService) service, alert); + LLTranslate::verifyKey(receiver, key); +} + +void LLFloaterTranslationSettings::onEditorFocused(LLFocusableElement* control) +{ + LLLineEditor* editor = dynamic_cast<LLLineEditor*>(control); + if (editor) { - gSavedSettings.setBOOL("TranslateChat", mMachineTranslationCB->getValue().asBoolean()); - gSavedSettings.setString("TranslateLanguage", mLanguageCombo->getSelectedValue().asString()); - gSavedSettings.setString("TranslationService", getSelectedService()); - gSavedSettings.setString("BingTranslateAPIKey", mBingAPIKeyEditor->getText()); - gSavedSettings.setString("GoogleTranslateAPIKey", mGoogleAPIKeyEditor->getText()); - closeFloater(false); + if (editor->getTentative()) + { + editor->setText(LLStringUtil::null); + editor->setTentative(FALSE); + } } } + +void LLFloaterTranslationSettings::onBingKeyEdited() +{ + mBingAPIKeyEditor->setTentative(FALSE); + setBingVerified(false, false); +} + +void LLFloaterTranslationSettings::onGoogleKeyEdited() +{ + mGoogleAPIKeyEditor->setTentative(FALSE); + setGoogleVerified(false, false); +} + +void LLFloaterTranslationSettings::onBtnBingVerify() +{ + std::string key = getEnteredBingKey(); + if (!key.empty()) + { + verifyKey(LLTranslate::SERVICE_BING, key); + } +} + +void LLFloaterTranslationSettings::onBtnGoogleVerify() +{ + std::string key = getEnteredGoogleKey(); + if (!key.empty()) + { + verifyKey(LLTranslate::SERVICE_GOOGLE, key); + } +} + +void LLFloaterTranslationSettings::onBtnOK() +{ + gSavedSettings.setBOOL("TranslateChat", mMachineTranslationCB->getValue().asBoolean()); + gSavedSettings.setString("TranslateLanguage", mLanguageCombo->getSelectedValue().asString()); + gSavedSettings.setString("TranslationService", getSelectedService()); + gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey()); + gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); + closeFloater(false); +} diff --git a/indra/newview/llfloatertranslationsettings.h b/indra/newview/llfloatertranslationsettings.h index 47e2fc80e6..9b47ad72ed 100644 --- a/indra/newview/llfloatertranslationsettings.h +++ b/indra/newview/llfloatertranslationsettings.h @@ -29,6 +29,7 @@ #include "llfloater.h" +class LLButton; class LLCheckBoxCtrl; class LLComboBox; class LLLineEditor; @@ -41,11 +42,22 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); + void setBingVerified(bool ok, bool alert); + void setGoogleVerified(bool ok, bool alert); + private: std::string getSelectedService() const; - void showError(const std::string& err_name) const; - bool validate() const; + std::string getEnteredBingKey() const; + std::string getEnteredGoogleKey() const; + void showAlert(const std::string& msg_name) const; void updateControlsEnabledState(); + void verifyKey(int service, const std::string& key, bool alert = true); + + void onEditorFocused(LLFocusableElement* control); + void onBingKeyEdited(); + void onGoogleKeyEdited(); + void onBtnBingVerify(); + void onBtnGoogleVerify(); void onBtnOK(); LLCheckBoxCtrl* mMachineTranslationCB; @@ -53,6 +65,12 @@ private: LLLineEditor* mBingAPIKeyEditor; LLLineEditor* mGoogleAPIKeyEditor; LLRadioGroup* mTranslationServiceRadioGroup; + LLButton* mBingVerifyBtn; + LLButton* mGoogleVerifyBtn; + LLButton* mOKBtn; + + bool mBingKeyVerified; + bool mGoogleKeyVerified; }; #endif // LL_LLFLOATERTRANSLATIONSETTINGS_H diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index a74b252c68..7b99c20a58 100644 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -54,6 +54,15 @@ void LLGoogleTranslationHandler::getTranslateURL( } // virtual +void LLGoogleTranslationHandler::getKeyVerificationURL( + std::string& url, + const std::string& key) const +{ + url = std::string("https://www.googleapis.com/language/translate/v2/languages?key=") + + key + "&target=en"; +} + +// virtual bool LLGoogleTranslationHandler::parseResponse( int& status, const std::string& body, @@ -153,6 +162,15 @@ void LLBingTranslarionHandler::getTranslateURL( } // virtual +void LLBingTranslarionHandler::getKeyVerificationURL( + std::string& url, + const std::string& key) const +{ + url = std::string("http://api.microsofttranslator.com/v2/Http.svc/GetLanguagesForTranslate?appId=") + + key; +} + +// virtual bool LLBingTranslarionHandler::parseResponse( int& status, const std::string& body, @@ -251,6 +269,27 @@ void LLTranslate::TranslationReceiver::completedRaw( } } +LLTranslate::KeyVerificationReceiver::KeyVerificationReceiver(EService service) +: mService(service) +{ +} + +LLTranslate::EService LLTranslate::KeyVerificationReceiver::getService() const +{ + return mService; +} + +// virtual +void LLTranslate::KeyVerificationReceiver::completedRaw( + U32 http_status, + const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) +{ + bool ok = (http_status == 200); + setVerificationStatus(ok); +} + //static void LLTranslate::translateMessage( TranslationReceiverPtr &receiver, @@ -261,24 +300,21 @@ void LLTranslate::translateMessage( std::string url; receiver->mHandler.getTranslateURL(url, from_lang, to_lang, mesg); - static const float REQUEST_TIMEOUT = 5; - static LLSD sHeader; - - if (!sHeader.size()) - { - std::string user_agent = llformat("%s %d.%d.%d (%d)", - LLVersionInfo::getChannel().c_str(), - LLVersionInfo::getMajor(), - LLVersionInfo::getMinor(), - LLVersionInfo::getPatch(), - LLVersionInfo::getBuild()); + LL_DEBUGS("Translate") << "Sending translation request: " << url << LL_ENDL; + sendRequest(url, receiver); +} - sHeader.insert("Accept", "text/plain"); - sHeader.insert("User-Agent", user_agent); - } +// static +void LLTranslate::verifyKey( + KeyVerificationReceiverPtr& receiver, + const std::string& key) +{ + std::string url; + const LLTranslationAPIHandler& handler = getHandler(receiver->getService()); + handler.getKeyVerificationURL(url, key); - LL_DEBUGS("Translate") << "Sending translation request: " << url << LL_ENDL; - LLHTTPClient::get(url, receiver, sHeader, REQUEST_TIMEOUT); + LL_DEBUGS("Translate") << "Sending key verification request: " << url << LL_ENDL; + sendRequest(url, receiver); } //static @@ -296,14 +332,49 @@ std::string LLTranslate::getTranslateLanguage() // static const LLTranslationAPIHandler& LLTranslate::getPreferredHandler() { + EService service = SERVICE_BING; + + std::string service_str = gSavedSettings.getString("TranslationService"); + if (service_str == "google") + { + service = SERVICE_GOOGLE; + } + + return getHandler(service); +} + +// static +const LLTranslationAPIHandler& LLTranslate::getHandler(EService service) +{ static LLGoogleTranslationHandler google; static LLBingTranslarionHandler bing; - std::string service = gSavedSettings.getString("TranslationService"); - if (service == "google") + if (service == SERVICE_GOOGLE) { return google; } return bing; } + +// static +void LLTranslate::sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder) +{ + static const float REQUEST_TIMEOUT = 5; + static LLSD sHeader; + + if (!sHeader.size()) + { + std::string user_agent = llformat("%s %d.%d.%d (%d)", + LLVersionInfo::getChannel().c_str(), + LLVersionInfo::getMajor(), + LLVersionInfo::getMinor(), + LLVersionInfo::getPatch(), + LLVersionInfo::getBuild()); + + sHeader.insert("Accept", "text/plain"); + sHeader.insert("User-Agent", user_agent); + } + + LLHTTPClient::get(url, responder, sHeader, REQUEST_TIMEOUT); +} diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h index 1bf6965fd4..672a56af8b 100644 --- a/indra/newview/lltranslate.h +++ b/indra/newview/lltranslate.h @@ -44,6 +44,10 @@ public: const std::string &to_lang, const std::string &text) const = 0; + virtual void getKeyVerificationURL( + std::string &url, + const std::string &key) const = 0; + virtual bool parseResponse( int& status, const std::string& body, @@ -67,6 +71,9 @@ public: const std::string &from_lang, const std::string &to_lang, const std::string &text) const; + /*virtual*/ void getKeyVerificationURL( + std::string &url, + const std::string &key) const; /*virtual*/ bool parseResponse( int& status, const std::string& body, @@ -96,6 +103,9 @@ public: const std::string &from_lang, const std::string &to_lang, const std::string &text) const; + /*virtual*/ void getKeyVerificationURL( + std::string &url, + const std::string &key) const; /*virtual*/ bool parseResponse( int& status, const std::string& body, @@ -112,6 +122,12 @@ class LLTranslate LOG_CLASS(LLTranslate); public : + + typedef enum e_service { + SERVICE_BING, + SERVICE_GOOGLE, + } EService; + class TranslationReceiver: public LLHTTPClient::Responder { public: @@ -134,13 +150,34 @@ public : const LLTranslationAPIHandler& mHandler; }; + class KeyVerificationReceiver: public LLHTTPClient::Responder + { + public: + EService getService() const; + + protected: + KeyVerificationReceiver(EService service); + /*virtual*/ void completedRaw( + U32 http_status, + const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + virtual void setVerificationStatus(bool ok) = 0; + + EService mService; + }; + typedef boost::intrusive_ptr<TranslationReceiver> TranslationReceiverPtr; + typedef boost::intrusive_ptr<KeyVerificationReceiver> KeyVerificationReceiverPtr; static void translateMessage(TranslationReceiverPtr &receiver, const std::string &from_lang, const std::string &to_lang, const std::string &mesg); + static void verifyKey(KeyVerificationReceiverPtr& receiver, const std::string& key); static std::string getTranslateLanguage(); private: static const LLTranslationAPIHandler& getPreferredHandler(); + static const LLTranslationAPIHandler& getHandler(EService service); + static void sendRequest(const std::string& url, LLHTTPClient::ResponderPtr responder); }; #endif diff --git a/indra/newview/skins/default/xui/en/floater_translation_settings.xml b/indra/newview/skins/default/xui/en/floater_translation_settings.xml index f21f64fcf6..e13c810820 100644 --- a/indra/newview/skins/default/xui/en/floater_translation_settings.xml +++ b/indra/newview/skins/default/xui/en/floater_translation_settings.xml @@ -1,16 +1,19 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <floater legacy_header_height="18" - height="320" + height="310" layout="topleft" name="floater_translation_settings" help_topic="environment_editor_floater" save_rect="true" title="TRANSLATION SETTINGS" - width="350"> + width="480"> - <string name="no_bing_api_key">Bing Translator requires and appID to function.</string> - <string name="no_google_api_key">Google Translate requires an API key to function.</string> + <string name="bing_api_key_not_verified">Bing appID not verified. Please try again.</string> + <string name="google_api_key_not_verified">Google API key not verified. Please try again.</string> + + <string name="bing_api_key_verified">Bing appID verified.</string> + <string name="google_api_key_verified">Google API key verified.</string> <check_box height="16" @@ -125,7 +128,7 @@ <radio_group follows="top|left" - height="55" + height="70" layout="topleft" left_delta="10" name="translation_service_rg" @@ -141,7 +144,7 @@ label="Google Translate" layout="topleft" name="google" - top_pad="20" /> + top_pad="55" /> </radio_group> <text @@ -150,13 +153,14 @@ follows="top|right" height="20" layout="topleft" - left="10" + left="40" name="bing_api_key_label" - top_pad="20" + top_pad="-45" width="100"> Bing [http://www.bing.com/developers/createapp.aspx AppID]: </text> <line_editor + default_text="Enter Bing AppID and click "Verify"" follows="top|left" height="20" layout="topleft" @@ -164,22 +168,31 @@ max_length_chars="50" top_delta="-4" name="bing_api_key" - value="" width="220" /> + <button + follows="left|top" + height="23" + label="Verify" + layout="topleft" + left_pad="10" + name="verify_bing_api_key_btn" + top_delta="-2" + width="90" /> <text follows="top|right" height="20" layout="topleft" - left="10" + left="40" length="1" name="google_api_key_label" - top_pad="20" + top_pad="50" type="string" width="100"> - Google [http://code.google.com/apis/language/translate/v2/pricing.html API key]: + Google [http://code.google.com/apis/language/translate/v2/getting_started.html#auth API key]: </text> <line_editor + default_text="Enter Google API key and click "Verify"" follows="top|left" height="20" layout="topleft" @@ -188,6 +201,15 @@ top_delta="-4" name="google_api_key" width="220" /> + <button + follows="left|top" + height="23" + label="Verify" + layout="topleft" + left_pad="10" + name="verify_google_api_key_btn" + top_delta="-2" + width="90" /> <text follows="top|right" @@ -195,11 +217,11 @@ layout="topleft" left="155" length="1" - name="google_pricing_link" - top_delta="-80" + name="google_links_text" + top_delta="-23" type="string" width="100"> - ([http://code.google.com/apis/language/translate/v2/pricing.html pricing]) + [http://code.google.com/apis/language/translate/v2/pricing.html Pricing] | [https://code.google.com/apis/console Stats] </text> <button |