forked from Public-Mirror/Textractor
add source language selection and rename variables
Added source language selection since autodetect fails sometimes Refactored names of variables
This commit is contained in:
parent
4b46057800
commit
9bb7fbff06
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
};
|
@ -3,21 +3,21 @@
|
||||
#include "devtools.h"
|
||||
|
||||
extern const wchar_t* TRANSLATION_ERROR;
|
||||
extern Synchronized<std::wstring> translateTo;
|
||||
extern Synchronized<std::wstring> 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<long> 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<bool, std::wstring> 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<long> callQueue;
|
||||
|
||||
std::pair<bool, std::wstring> 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<bool, std::wstring> 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<bool, std::wstring> 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<bool, std::wstring> 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<bool, std::wstring> 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) };
|
||||
}
|
@ -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<bool, std::wstring> Translate(const std::wstring& text, DevTools* devtools);
|
||||
std::pair<bool, std::wstring> 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<std::wstring> translateTo = L"en";
|
||||
Settings settings;
|
||||
Synchronized<std::wstring> translateTo = L"en", translateFrom = L"ja";
|
||||
Synchronized<std::map<std::wstring, std::wstring>> 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<bool&, const char*>{
|
||||
{ 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<int&, const char*>{
|
||||
{ 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<std::wstring>{
|
||||
for (auto defaultPath : Array<std::wstring>{
|
||||
{ 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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user