diff --git a/extensions/devtools.cpp b/extensions/devtools.cpp index 1b5f1b4..8fa4d83 100644 --- a/extensions/devtools.cpp +++ b/extensions/devtools.cpp @@ -2,8 +2,8 @@ DevTools::DevTools(QObject* parent) : QObject(parent), - idcounter(0), - idmethod(0), + idCounter(0), + idMethod(0), status("Stopped"), session(0) { @@ -29,19 +29,19 @@ void DevTools::startDevTools(QString path, bool headless, int port) { if (GetJsonfromHTTP(doc, "/json/version", port)) { - useragent = doc.object().value("User-Agent").toString(); + userAgent = doc.object().value("User-Agent").toString(); } webSocket.open(webSocketDebuggerUrl); session += 1; return; } } - status = "Failed to find chrome debug port!"; + status = "Failed to find Chrome debug port!"; emit statusChanged(status); } else { - status = "Failed to start chrome!"; + status = "Failed to start Chrome!"; emit statusChanged(status); } } @@ -58,7 +58,7 @@ QString DevTools::getStatus() QString DevTools::getUserAgent() { - return useragent; + return userAgent; } DevTools::~DevTools() @@ -136,7 +136,7 @@ bool DevTools::SendRequest(QString method, QJsonObject params, QJsonObject& root QJsonDocument doc(json); QString message(doc.toJson(QJsonDocument::Compact)); mutex.lock(); - mapqueue.insert(std::make_pair(id, response)); + mapQueue.insert(std::make_pair(id, response)); mutex.unlock(); webSocket.sendTextMessage(message); webSocket.flush(); @@ -171,19 +171,19 @@ long DevTools::methodToReceive(QString method, QJsonObject params) json.insert("method", method); json.insert("params", params); mutex.lock(); - mapmethod.insert(std::make_pair(id, json)); + mapMethod.insert(std::make_pair(id, json)); mutex.unlock(); return id; } long DevTools::idIncrement() { - return ++idcounter; + return ++idCounter; } long DevTools::idmIncrement() { - return ++idmethod; + return ++idMethod; } bool DevTools::isConnected() @@ -194,25 +194,30 @@ bool DevTools::isConnected() return false; } -bool DevTools::compareJson(QJsonValue storedparams, QJsonValue params) +bool DevTools::compareJson(QJsonValue stored, QJsonValue params) { - if (storedparams.isObject()) + if (stored.isObject()) { - foreach(const QString & key, storedparams.toObject().keys()) + foreach(const QString & key, stored.toObject().keys()) { - QJsonValue storedvalue = storedparams.toObject().value(key); + QJsonValue storedvalue = stored.toObject().value(key); QJsonValue value = params.toObject().value(key); if (!compareJson(storedvalue, value)) return false; } } - else if (storedparams.isArray()) + else if (stored.isArray()) { - for (int i = 0; i < storedparams.toArray().size(); i++) - if (!compareJson(storedparams.toArray()[i], params.toArray()[i])) + for (int i = 0; i < stored.toArray().size(); i++) + if (!compareJson(stored.toArray()[i], params.toArray()[i])) return false; } - else if (storedparams.toVariant() != params.toVariant()) + else if (stored.isString()) + { + if (!stored.toString().contains(params.toString())) + return false; + } + else if (stored.toVariant() != params.toVariant()) return false; return true; @@ -220,8 +225,8 @@ bool DevTools::compareJson(QJsonValue storedparams, QJsonValue params) bool DevTools::checkMethod(long id) { - MapMethod::iterator iter = mapmethod.find(id); - if (iter == mapmethod.end()) + MapMethod::iterator iter = mapMethod.find(id); + if (iter == mapMethod.end()) return true; else return false; @@ -235,13 +240,13 @@ void DevTools::onTextMessageReceived(QString message) QJsonObject root = doc.object(); if (root.contains("method")) { - for (auto iter = mapmethod.cbegin(); iter != mapmethod.cend();) + for (auto iter = mapMethod.cbegin(); iter != mapMethod.cend();) { if (iter->second.value("method") == root.value("method") && compareJson(iter->second.value("params"), root.value("params"))) { mutex.lock(); - mapmethod.erase(iter++); + mapMethod.erase(iter++); mutex.unlock(); } ++iter; @@ -251,12 +256,12 @@ void DevTools::onTextMessageReceived(QString message) if (root.contains("id")) { long id = root.value("id").toInt(); - MapResponse::iterator request = mapqueue.find(id); - if (request != mapqueue.end()) + MapResponse::iterator request = mapQueue.find(id); + if (request != mapQueue.end()) { request->second.set(root); mutex.lock(); - mapqueue.erase(request); + mapQueue.erase(request); mutex.unlock(); } return; @@ -266,20 +271,20 @@ void DevTools::onTextMessageReceived(QString message) void DevTools::closeDevTools() { - if (this->mapqueue.size() > 0) + if (this->mapQueue.size() > 0) { - MapResponse::iterator iter = mapqueue.begin(); - MapResponse::iterator iend = mapqueue.end(); + MapResponse::iterator iter = mapQueue.begin(); + MapResponse::iterator iend = mapQueue.end(); for (; iter != iend; iter++) { iter->second.set_exception("exception"); } } webSocket.close(); - mapmethod.clear(); - mapqueue.clear(); - idcounter = 0; - idmethod = 0; + mapMethod.clear(); + mapQueue.clear(); + idCounter = 0; + idMethod = 0; DWORD exitCode = 0; if (GetExitCodeProcess(processInfo.hProcess, &exitCode) != FALSE) { diff --git a/extensions/devtools.h b/extensions/devtools.h index 82641d1..c13b610 100644 --- a/extensions/devtools.h +++ b/extensions/devtools.h @@ -37,15 +37,15 @@ private: bool GetJsonfromHTTP(QJsonDocument& doc, QString object, int port = 9222); long idIncrement(); long idmIncrement(); - bool compareJson(QJsonValue storedparams, QJsonValue params); + bool compareJson(QJsonValue stored, QJsonValue params); int session; QWebSocket webSocket; std::mutex mutex; - MapResponse mapqueue; - MapMethod mapmethod; - long idcounter; - long idmethod; + MapResponse mapQueue; + MapMethod mapMethod; + long idCounter; + long idMethod; PROCESS_INFORMATION processInfo; QString status; - QString useragent; + QString userAgent; }; \ No newline at end of file diff --git a/extensions/devtoolsdeepltranslate.cpp b/extensions/devtoolsdeepltranslate.cpp index 7b20d29..3efcf84 100644 --- a/extensions/devtoolsdeepltranslate.cpp +++ b/extensions/devtoolsdeepltranslate.cpp @@ -3,21 +3,21 @@ #include "devtools.h" extern const wchar_t* TRANSLATION_ERROR; -extern Synchronized translateTo; +extern Synchronized translateTo, translateFrom; -bool useCache = true, autostartchrome = false, headlesschrome = true; -int maxSentenceSize = 500, chromeport = 9222; +bool useCache = true, autoStartChrome = false, headlessChrome = true; +int maxSentenceSize = 500, chromePort = 9222; const char* TRANSLATION_PROVIDER = "DevTools DeepL Translate"; -const wchar_t* ERROR_CHROME = L"Error: chrome not started"; -const wchar_t* ERROR_START_CHROME = L"Error: failed to start chrome or to connect to it"; +const wchar_t* ERROR_CHROME = L"Error: Chrome not started"; +const wchar_t* ERROR_START_CHROME = L"Error: failed to start Chrome or to connect to it"; const wchar_t* ERROR_GOT_TIMEOUT = L"Error: timeout (s)"; const wchar_t* ERROR_COMMAND_FAIL = L"Error: command failed"; const wchar_t* ERROR_LANGUAGE = L"Error: target languages do not match"; const wchar_t* ERROR_NOTE = L"Error: notification"; QString URL = "https://www.deepl.com/en/translator"; -QStringList languages +QStringList languagesTo { "Chinese (simplified): zh", "Dutch: nl", @@ -32,21 +32,37 @@ QStringList languages "Spanish: es", }; -int docfound = -1, targetNodeId = -1, session = -1, pageenabled = -1, useragentflag = -1, backup = -1; -long update = -1, callnumber = 0; -std::vector callqueue; +QStringList languagesFrom +{ + "Any language: ", + "Chinese: zh", + "Dutch: nl", + "English: en", + "French: fr", + "German: de", + "Italian: it", + "Japanese: ja", + "Polish: pl", + "Portuguese: pt", + "Russian: ru", + "Spanish: es", +}; -std::pair Translate(const std::wstring& text, DevTools* devtools) +int docFound = -1, targetNodeId = -1, session = -1, pageEnabled = -1, userAgentFlag = -1, backup = -1, sourceLangId = -1; +long update = -1, callNumber = 0; +std::vector callQueue; + +std::pair Translate(const std::wstring& text, DevTools* devTools) { QString qtext = S(text); qtext.remove(QString(12288)); // japanese space (no need for translator) // Remove quotes - bool checkquote = false; + bool checkQuote = false; if ((qtext.front() == QString(12300) && qtext.back() == QString(12301)) // japanese quotation marks || (qtext.front() == "\"" && qtext.back() == "\"")) { - checkquote = true; + checkQuote = true; qtext.remove(0, 1); qtext.chop(1); } @@ -65,29 +81,30 @@ std::pair Translate(const std::wstring& text, DevTools* devt } // Put quotes back - if (checkquote) + if (checkQuote) { qtext = "\"" + qtext + "\""; } // Check status - if (devtools->getStatus() == "Stopped") + if (devTools->getStatus() == "Stopped") { return { false, FormatString(L"%s", ERROR_CHROME) }; } - if (devtools->getStatus().startsWith("Fail") || devtools->getStatus().startsWith("Unconnected")) + if (devTools->getStatus().startsWith("Fail") || devTools->getStatus().startsWith("Unconnected")) { return { false, FormatString(L"%s", ERROR_START_CHROME) }; } - if (session != devtools->getSession()) + if (session != devTools->getSession()) { - session = devtools->getSession(); - docfound = -1; + session = devTools->getSession(); + docFound = -1; targetNodeId = -1; - pageenabled = -1; - useragentflag = -1; + sourceLangId = -1; + pageEnabled = -1; + userAgentFlag = -1; update = -1; - callnumber = 0; + callNumber = 0; backup = -1; } @@ -97,98 +114,112 @@ std::pair Translate(const std::wstring& text, DevTools* devt // Enable page feedback QJsonObject root; - int errorcode = 0; - if (pageenabled == -1) + int errorCode = 0; + if (pageEnabled == -1) { - if (!devtools->SendRequest("Page.enable", {}, root)) - errorcode = 1; + if (!devTools->SendRequest("Page.enable", {}, root)) + errorCode = 1; else - pageenabled = 1; + pageEnabled = 1; } // Change user-agent if in headless mode - if (useragentflag == -1 && errorcode == 0) + if (userAgentFlag == -1 && errorCode == 0) { - QString useragent = devtools->getUserAgent(); - if (!useragent.isEmpty()) + QString userAgent = devTools->getUserAgent(); + if (!userAgent.isEmpty()) { - useragent.replace("HeadlessChrome", "Chrome"); - if (!devtools->SendRequest("Network.setUserAgentOverride", { {"userAgent", useragent} }, root)) - errorcode = 1; + userAgent.replace("HeadlessChrome", "Chrome"); + if (!devTools->SendRequest("Network.setUserAgentOverride", { {"userAgent", userAgent} }, root)) + errorCode = 1; else - useragentflag = 1; + userAgentFlag = 1; } } // Increase queue counter and wait until previous calls are done float timer = 0; - int timer_stop = 10; - long calltag = ++callnumber; - callqueue.insert(callqueue.begin(), calltag); - while (errorcode == 0 && callqueue.back() != calltag && timer < 2 * timer_stop) + int timerStop = 10; + long callTag = ++callNumber; + callQueue.insert(callQueue.begin(), callTag); + while (errorCode == 0 && callQueue.back() != callTag && timer < 2 * timerStop) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); timer += 0.1; } - if (timer >= timer_stop) - errorcode = 5; + if (timer >= timerStop) + errorCode = 5; // Set methods to receive - long navigate = devtools->methodToReceive("Page.navigatedWithinDocument"); + long navigate = devTools->methodToReceive("Page.navigatedWithinDocument"); long target; if (backup == -1) - target = devtools->methodToReceive("DOM.attributeModified", { { "value" , "lmt__mobile_share_container lmt--mobile-hidden" } }); + target = devTools->methodToReceive("DOM.attributeModified", { { "value" , "lmt__mobile_share_container lmt--mobile-hidden" } }); else - target = devtools->methodToReceive("DOM.childNodeCountUpdated"); + target = devTools->methodToReceive("DOM.childNodeCountUpdated"); if (update == -1) - update = devtools->methodToReceive("DOM.documentUpdated"); + update = devTools->methodToReceive("DOM.documentUpdated"); // Navigate to site and wait until it is loaded - QString fullurl = URL + "#ja/" + S(translateTo.Copy()) + "/" + qtext; - if (errorcode == 0 && !devtools->SendRequest("Page.navigate", { {"url", fullurl} }, root)) - errorcode = 1; + QString checkFrom = translateFrom.Copy().empty() ? "ja" : S(translateFrom.Copy()); + QString fullUrl = URL + "#" + checkFrom + "/" + S(translateTo.Copy()) + "/" + qtext; + if (errorCode == 0 && !devTools->SendRequest("Page.navigate", { {"url", fullUrl} }, root)) + errorCode = 1; timer = 0; - while (errorcode == 0 && !devtools->checkMethod(navigate) && timer < timer_stop) + while (errorCode == 0 && !devTools->checkMethod(navigate) && timer < timerStop) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); timer += 0.1; } - if (timer >= timer_stop) - errorcode = 2; + if (timer >= timerStop) + errorCode = 2; // Check if document is outdated - if (devtools->checkMethod(update)) + if (devTools->checkMethod(update)) { - docfound = -1; + docFound = -1; targetNodeId = -1; update = -1; } // Get document - if (docfound == -1 && errorcode == 0) + if (docFound == -1 && errorCode == 0) { - if (!devtools->SendRequest("DOM.getDocument", {}, root)) - errorcode = 1; + if (!devTools->SendRequest("DOM.getDocument", {}, root)) + errorCode = 1; else - docfound = root.value("result").toObject().value("root").toObject().value("nodeId").toInt(); + docFound = root.value("result").toObject().value("root").toObject().value("nodeId").toInt(); } // Get target selector - if (targetNodeId == -1 && errorcode == 0) + if (targetNodeId == -1 && errorCode == 0) { - if (!devtools->SendRequest("DOM.querySelector", { {"nodeId", docfound}, {"selector", "textarea.lmt__target_textarea"} }, root) + if (!devTools->SendRequest("DOM.querySelector", { {"nodeId", docFound}, {"selector", "textarea.lmt__target_textarea"} }, root) || root.value("result").toObject().value("nodeId").toInt() == 0) { - docfound = -1; - errorcode = 1; + docFound = -1; + errorCode = 1; } else targetNodeId = root.value("result").toObject().value("nodeId").toInt(); } + // Get source language selector + if (sourceLangId == -1 && errorCode == 0) + { + if (!devTools->SendRequest("DOM.querySelector", { {"nodeId", docFound}, {"selector", "div.lmt__language_select--source"} }, root) + || root.value("result").toObject().value("nodeId").toInt() == 0) + { + docFound = -1; + errorCode = 1; + } + else + sourceLangId = root.value("result").toObject().value("nodeId").toInt(); + } + // Wait for the translation to appear on the web page timer = 0; - while (errorcode == 0 && !devtools->checkMethod(target) && timer < timer_stop) + while (errorCode == 0 && !devTools->checkMethod(target) && timer < timerStop) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); timer += 0.1; @@ -196,10 +227,10 @@ std::pair Translate(const std::wstring& text, DevTools* devt // Catch the translation QString OuterHTML; - if (errorcode == 0 && !devtools->SendRequest("DOM.getOuterHTML", { {"nodeId", targetNodeId + 1} }, root)) + if (errorCode == 0 && !devTools->SendRequest("DOM.getOuterHTML", { {"nodeId", targetNodeId + 1} }, root)) { targetNodeId = -1; - errorcode = 1; + errorCode = 1; } else { @@ -209,57 +240,90 @@ std::pair Translate(const std::wstring& text, DevTools* devt { // Try to catch the notification int noteNodeId = -1; - if (errorcode == 0 && (!devtools->SendRequest("DOM.querySelector", { {"nodeId", docfound}, {"selector", "div.lmt__system_notification"} }, root) - || root.value("result").toObject().value("nodeId").toInt() == 0) && timer >= timer_stop) + if (errorCode == 0 && (!devTools->SendRequest("DOM.querySelector", { {"nodeId", docFound}, {"selector", "div.lmt__system_notification"} }, root) + || root.value("result").toObject().value("nodeId").toInt() == 0) && timer >= timerStop) { - errorcode = 2; + errorCode = 2; } else { noteNodeId = root.value("result").toObject().value("nodeId").toInt(); - if (errorcode == 0 && devtools->SendRequest("DOM.getOuterHTML", { {"nodeId", noteNodeId} }, root)) + if (errorCode == 0 && devTools->SendRequest("DOM.getOuterHTML", { {"nodeId", noteNodeId} }, root)) { OuterHTML = root.value("result").toObject().value("outerHTML").toString(); } - errorcode = 3; + errorCode = 3; } } OuterHTML.remove(QRegExp("<[^>]*>")); OuterHTML = OuterHTML.trimmed(); - if (backup == -1 && errorcode == 0 && timer >= timer_stop) + if (backup == -1 && errorCode == 0 && timer >= timerStop) backup = 1; // Check if the translator output language does not match the selected language - QString targetlang; - if (errorcode == 0 && devtools->SendRequest("DOM.getAttributes", { {"nodeId", targetNodeId} }, root)) + QString targetLang; + if (errorCode == 0 && devTools->SendRequest("DOM.getAttributes", { {"nodeId", targetNodeId} }, root)) { QJsonArray attributes = root.value("result").toObject().value("attributes").toArray(); for (size_t i = 0; i < attributes.size(); i++) { if (attributes[i].toString() == "lang") { - targetlang = attributes[i + 1].toString().mid(0, 2); - if (targetlang != S(translateTo.Copy())) + targetLang = attributes[i + 1].toString().mid(0, 2); + if (targetLang != S(translateTo.Copy())) { - errorcode = 4; + errorCode = 4; } } + break; + } + } + + // Check selected source language + if (errorCode == 0 && devTools->SendRequest("DOM.getAttributes", { {"nodeId", sourceLangId} }, root)) + { + QJsonArray attributes = root.value("result").toObject().value("attributes").toArray(); + for (size_t i = 0; i < attributes.size(); i++) + { + if (attributes[i].toString() == "dl-selected-lang" + && attributes[i + 1].toString().mid(0, 2) != S(translateFrom.Copy())) + { + QStringList::const_iterator constIter; + for (constIter = languagesFrom.constBegin(); constIter != languagesFrom.constEnd(); ++constIter) + { + if (constIter->contains(": " + S(translateFrom.Copy()))) + break; + } + devTools->SendRequest("Runtime.evaluate", { {"expression", + "document\ + .querySelector('div.lmt__language_select--source')\ + .querySelector('button.lmt__language_select__active')\ + .click();\ + document\ + .evaluate(\"//button[contains(text(), '" + + constIter->split(": ")[0] + "')]\", \ + document.querySelector('div.lmt__language_select__menu'),\ + null, XPathResult.FIRST_ORDERED_NODE_TYPE, null)\ + .singleNodeValue\ + .click();" + } }, root); + } } } - callqueue.pop_back(); - if (errorcode == 0) + callQueue.pop_back(); + if (errorCode == 0) return { true, S(OuterHTML) }; - else if (errorcode == 1) + else if (errorCode == 1) return { false, FormatString(L"%s", ERROR_COMMAND_FAIL) }; - else if (errorcode == 2) - return { false, FormatString(L"%s: %d", ERROR_GOT_TIMEOUT, timer_stop) }; - else if (errorcode == 3) + else if (errorCode == 2) + return { false, FormatString(L"%s: %d", ERROR_GOT_TIMEOUT, timerStop) }; + else if (errorCode == 3) return { false, FormatString(L"%s: %s", ERROR_NOTE, S(OuterHTML)) }; - else if (errorcode == 4) - return { false, FormatString(L"%s (%s): %s", ERROR_LANGUAGE, S(targetlang), S(OuterHTML)) }; - else if (errorcode == 5) - return { false, FormatString(L"%s: %d", ERROR_GOT_TIMEOUT, 2*timer_stop) }; + else if (errorCode == 4) + return { false, FormatString(L"%s (%s): %s", ERROR_LANGUAGE, S(targetLang), S(OuterHTML)) }; + else if (errorCode == 5) + return { false, FormatString(L"%s: %d", ERROR_GOT_TIMEOUT, 2*timerStop) }; else return { false, FormatString(L"%s", TRANSLATION_ERROR) }; } \ No newline at end of file diff --git a/extensions/devtoolswrapper.cpp b/extensions/devtoolswrapper.cpp index a319c78..546d5a2 100644 --- a/extensions/devtoolswrapper.cpp +++ b/extensions/devtoolswrapper.cpp @@ -13,33 +13,37 @@ extern const char* TRANSLATE_SELECTED_THREAD_ONLY; extern const char* USE_TRANS_CACHE; extern const char* MAX_SENTENCE_SIZE; extern const char* TRANSLATION_PROVIDER; -extern QStringList languages; -const char* PATH_TO_CHROME = u8"Path to chrome"; -const char* AUTO_START_CHROME = u8"Start chrome automatically"; +extern QStringList languagesTo; +extern QStringList languagesFrom; +const char* TRANSLATE_FROM = u8"Translate from"; +const char* NATIVE_LANGUAGE_FROM = u8"Japanese"; +const char* PATH_TO_CHROME = u8"Path to Chrome"; +const char* AUTO_START_CHROME = u8"Start Chrome automatically"; const char* HEADLESS_CHROME = u8"Start in headless mode"; const char* CHROME_DEBUG_PORT = u8"Chrome debug port"; const char* DEV_TOOLS_STATUS = u8"Status: "; const char* START_DEV_TOOLS_BUTTON = u8"Start"; -const char* START_DEV_TOOLS = u8"Start chrome"; +const char* START_DEV_TOOLS = u8"Start Chrome"; const char* STOP_DEV_TOOLS_BUTTON = u8"Stop"; -const char* STOP_DEV_TOOLS = u8"Stop chrome"; +const char* STOP_DEV_TOOLS = u8"Stop Chrome"; -extern bool useCache, autostartchrome, headlesschrome; -extern int maxSentenceSize, chromeport; +extern bool useCache, autoStartChrome, headlessChrome; +extern int maxSentenceSize, chromePort; -std::pair Translate(const std::wstring& text, DevTools* devtools); +std::pair Translate(const std::wstring& text, DevTools* devTools); -const char* LANGUAGE = u8"Language"; +const char* LANGUAGE_TO = u8"Language"; +const char* LANGUAGE_FROM = u8"Language from"; const std::string TRANSLATION_CACHE_FILE = FormatString("%s Cache.txt", TRANSLATION_PROVIDER); QFormLayout* display; -QSettings settings = openSettings(); -Synchronized translateTo = L"en"; +Settings settings; +Synchronized translateTo = L"en", translateFrom = L"ja"; Synchronized> translationCache; int savedSize; -DevTools* devtools = nullptr; -std::wstring pathtochrome = L""; +DevTools* devTools = nullptr; +std::wstring pathToChrome = L""; void SaveCache() { @@ -67,23 +71,35 @@ public: Window() : QDialog(nullptr, Qt::WindowMinMaxButtonsHint) { + localize(); display = new QFormLayout(this); settings.beginGroup(TRANSLATION_PROVIDER); - auto languageBox = new QComboBox(this); - languageBox->addItems(languages); - int language = -1; - if (settings.contains(LANGUAGE)) language = languageBox->findText(settings.value(LANGUAGE).toString(), Qt::MatchEndsWith); - if (language < 0) language = languageBox->findText(NATIVE_LANGUAGE, Qt::MatchStartsWith); - if (language < 0) language = languageBox->findText("English", Qt::MatchStartsWith); - languageBox->setCurrentIndex(language); - saveLanguage(languageBox->currentText()); - display->addRow(TRANSLATE_TO, languageBox); - connect(languageBox, &QComboBox::currentTextChanged, this, &Window::saveLanguage); + auto languageBoxTo = new QComboBox(this); + languageBoxTo->addItems(languagesTo); + int languageTo = -1; + if (settings.contains(LANGUAGE_TO)) languageTo = languageBoxTo->findText(settings.value(LANGUAGE_TO).toString(), Qt::MatchEndsWith); + if (languageTo < 0) languageTo = languageBoxTo->findText(NATIVE_LANGUAGE, Qt::MatchStartsWith); + if (languageTo < 0) languageTo = languageBoxTo->findText("English", Qt::MatchStartsWith); + languageBoxTo->setCurrentIndex(languageTo); + saveLanguage(languageBoxTo->currentText()); + display->addRow(TRANSLATE_TO, languageBoxTo); + connect(languageBoxTo, &QComboBox::currentTextChanged, this, &Window::saveLanguage); + + auto languageBoxFrom = new QComboBox(this); + languageBoxFrom->addItems(languagesFrom); + int languageFrom = -1; + if (settings.contains(LANGUAGE_FROM)) languageFrom = languageBoxFrom->findText(settings.value(LANGUAGE_FROM).toString(), Qt::MatchEndsWith); + if (languageFrom < 0) languageFrom = languageBoxFrom->findText(NATIVE_LANGUAGE_FROM, Qt::MatchStartsWith); + if (languageFrom < 0) languageFrom = languageBoxFrom->findText("Japanese", Qt::MatchStartsWith); + languageBoxFrom->setCurrentIndex(languageFrom); + saveLanguageFrom(languageBoxFrom->currentText()); + display->addRow(TRANSLATE_FROM, languageBoxFrom); + connect(languageBoxFrom, &QComboBox::currentTextChanged, this, &Window::saveLanguageFrom); for (auto [value, label] : Array{ { useCache, USE_TRANS_CACHE }, - { autostartchrome, AUTO_START_CHROME }, - //{ headlesschrome, HEADLESS_CHROME } + { autoStartChrome, AUTO_START_CHROME }, + //{ headlessChrome, HEADLESS_CHROME } }) { value = settings.value(label, value).toBool(); @@ -94,7 +110,7 @@ public: } for (auto [value, label] : Array{ { maxSentenceSize, MAX_SENTENCE_SIZE }, - { chromeport, CHROME_DEBUG_PORT }, + { chromePort, CHROME_DEBUG_PORT }, }) { value = settings.value(label, value).toInt(); @@ -106,24 +122,24 @@ public: } auto keyInput = new QLineEdit(settings.value(PATH_TO_CHROME).toString()); - pathtochrome = (S(keyInput->text())); - if (pathtochrome.empty()) + pathToChrome = (S(keyInput->text())); + if (pathToChrome.empty()) { - for (auto defaultpath : Array{ + for (auto defaultPath : Array{ { L"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe" }, { L"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe" }, }) - if (std::filesystem::exists(defaultpath)) + if (std::filesystem::exists(defaultPath)) { - pathtochrome = defaultpath; - keyInput->setText(S(pathtochrome)); + pathToChrome = defaultPath; + keyInput->setText(S(pathToChrome)); } } - connect(keyInput, &QLineEdit::textChanged, [keyInput](QString key) { settings.setValue(PATH_TO_CHROME, S(pathtochrome = (S(key)))); }); + connect(keyInput, &QLineEdit::textChanged, [keyInput](QString key) { settings.setValue(PATH_TO_CHROME, S(pathToChrome = (S(key)))); }); display->addRow(PATH_TO_CHROME, keyInput); - connect(&startButton, &QPushButton::clicked, this, &Window::start); - connect(&stopButton, &QPushButton::clicked, this, &Window::stop); + connect(&startButton, &QPushButton::clicked, this, &Window::Start); + connect(&stopButton, &QPushButton::clicked, this, &Window::Stop); display->addRow(START_DEV_TOOLS, &startButton); display->addRow(STOP_DEV_TOOLS, &stopButton); @@ -144,39 +160,42 @@ public: } savedSize = translationCache->size(); - devtools = new DevTools(this); - connect(devtools, &DevTools::statusChanged, [this](QString text) + devTools = new DevTools(this); + connect(devTools, &DevTools::statusChanged, [this](QString text) { status.setText(text); }); - if (autostartchrome) - QMetaObject::invokeMethod(this, &Window::start, Qt::QueuedConnection); + if (autoStartChrome) + QMetaObject::invokeMethod(this, &Window::Start, Qt::QueuedConnection); } ~Window() { - stop(); - if (devtools != nullptr) - delete devtools; + Stop(); + if (devTools != nullptr) + delete devTools; SaveCache(); } private: - void start() + void Start() { - if (devtools->getStatus() == "Stopped") - devtools->startDevTools(S(pathtochrome), headlesschrome, chromeport); + if (devTools->getStatus() == "Stopped") + devTools->startDevTools(S(pathToChrome), headlessChrome, chromePort); } - void stop() + void Stop() { - devtools->closeDevTools(); + devTools->closeDevTools(); } - void saveLanguage(QString language) { - settings.setValue(LANGUAGE, S(translateTo->assign(S(language.split(": ")[1])))); + settings.setValue(LANGUAGE_TO, S(translateTo->assign(S(language.split(": ")[1])))); + } + void saveLanguageFrom(QString language) + { + settings.setValue(LANGUAGE_FROM, S(translateFrom->assign(S(language.split(": ")[1])))); } QPushButton startButton{ START_DEV_TOOLS_BUTTON, this }; QPushButton stopButton{ STOP_DEV_TOOLS_BUTTON, this }; @@ -197,7 +216,7 @@ bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo) if (translation.empty() && (sentenceInfo["current select"])) { EraseControlCharacters(sentence); - std::tie(cache, translation) = Translate(sentence, devtools); + std::tie(cache, translation) = Translate(sentence, devTools); } if (cache) translationCache->try_emplace(sentence, translation);