forked from Public-Mirror/Textractor
allow replacement in regex filter and make names consistent
This commit is contained in:
parent
4219115a40
commit
084f26a72d
@ -303,8 +303,8 @@ namespace
|
||||
|
||||
QDialog dialog(This, Qt::WindowCloseButtonHint);
|
||||
QFormLayout layout(&dialog);
|
||||
QCheckBox cjkCheckBox(&dialog);
|
||||
layout.addRow(SEARCH_CJK, &cjkCheckBox);
|
||||
QCheckBox CJKCheck(&dialog);
|
||||
layout.addRow(SEARCH_CJK, &CJKCheck);
|
||||
QDialogButtonBox confirm(QDialogButtonBox::Ok | QDialogButtonBox::Help | QDialogButtonBox::Retry, &dialog);
|
||||
layout.addRow(&confirm);
|
||||
confirm.button(QDialogButtonBox::Ok)->setText(START_HOOK_SEARCH);
|
||||
@ -323,29 +323,29 @@ namespace
|
||||
{
|
||||
QDialog dialog(This, Qt::WindowCloseButtonHint);
|
||||
QFormLayout layout(&dialog);
|
||||
QLineEdit textInput(&dialog);
|
||||
layout.addRow(TEXT, &textInput);
|
||||
QSpinBox codepageInput(&dialog);
|
||||
codepageInput.setMaximum(INT_MAX);
|
||||
codepageInput.setValue(sp.codepage);
|
||||
layout.addRow(CODEPAGE, &codepageInput);
|
||||
QLineEdit textEdit(&dialog);
|
||||
layout.addRow(TEXT, &textEdit);
|
||||
QSpinBox codepageSpin(&dialog);
|
||||
codepageSpin.setMaximum(INT_MAX);
|
||||
codepageSpin.setValue(sp.codepage);
|
||||
layout.addRow(CODEPAGE, &codepageSpin);
|
||||
QDialogButtonBox confirm(QDialogButtonBox::Ok);
|
||||
QObject::connect(&confirm, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
||||
layout.addRow(&confirm);
|
||||
if (!dialog.exec()) return;
|
||||
wcsncpy_s(sp.text, S(textInput.text()).c_str(), PATTERN_SIZE - 1);
|
||||
wcsncpy_s(sp.text, S(textEdit.text()).c_str(), PATTERN_SIZE - 1);
|
||||
try { Host::FindHooks(selectedProcessId, sp); } catch (std::out_of_range) {}
|
||||
return;
|
||||
}
|
||||
|
||||
filter.setPattern(cjkCheckBox.isChecked() ? "[\\x{3000}-\\x{a000}]{4,}" : "[\\x{0020}-\\x{1000}]{4,}");
|
||||
filter.setPattern(CJKCheck.isChecked() ? "[\\x{3000}-\\x{a000}]{4,}" : "[\\x{0020}-\\x{1000}]{4,}");
|
||||
if (customSettings)
|
||||
{
|
||||
QDialog dialog(This, Qt::WindowCloseButtonHint);
|
||||
QFormLayout layout(&dialog);
|
||||
QLineEdit patternInput(x64 ? "CC CC 48 89" : "55 8B EC", &dialog);
|
||||
assert(QByteArray::fromHex(patternInput.text().toUtf8()) == QByteArray((const char*)sp.pattern, sp.length));
|
||||
layout.addRow(SEARCH_PATTERN, &patternInput);
|
||||
QLineEdit patternEdit(x64 ? "CC CC 48 89" : "55 8B EC", &dialog);
|
||||
assert(QByteArray::fromHex(patternEdit.text().toUtf8()) == QByteArray((const char*)sp.pattern, sp.length));
|
||||
layout.addRow(SEARCH_PATTERN, &patternEdit);
|
||||
for (auto [value, label] : Array<int&, const char*>{
|
||||
{ sp.searchTime, SEARCH_DURATION },
|
||||
{ sp.offset, PATTERN_OFFSET },
|
||||
@ -359,36 +359,36 @@ namespace
|
||||
layout.addRow(label, spinBox);
|
||||
QObject::connect(spinBox, qOverload<int>(&QSpinBox::valueChanged), [&value](int newValue) { value = newValue; });
|
||||
}
|
||||
QLineEdit boundInput(QFileInfo(S(GetModuleFilename(selectedProcessId).value_or(L""))).fileName(), &dialog);
|
||||
layout.addRow(SEARCH_MODULE, &boundInput);
|
||||
QLineEdit boundEdit(QFileInfo(S(GetModuleFilename(selectedProcessId).value_or(L""))).fileName(), &dialog);
|
||||
layout.addRow(SEARCH_MODULE, &boundEdit);
|
||||
for (auto [value, label] : Array<uintptr_t&, const char*>{
|
||||
{ sp.minAddress, MIN_ADDRESS },
|
||||
{ sp.maxAddress, MAX_ADDRESS },
|
||||
{ sp.padding, STRING_OFFSET },
|
||||
})
|
||||
{
|
||||
auto input = new QLineEdit(QString::number(value, 16), &dialog);
|
||||
layout.addRow(label, input);
|
||||
QObject::connect(input, &QLineEdit::textEdited, [&value](QString text) { if (uintptr_t newValue = text.toULongLong(&ok, 16); ok) value = newValue; });
|
||||
auto edit = new QLineEdit(QString::number(value, 16), &dialog);
|
||||
layout.addRow(label, edit);
|
||||
QObject::connect(edit, &QLineEdit::textEdited, [&value](QString text) { if (uintptr_t newValue = text.toULongLong(&ok, 16); ok) value = newValue; });
|
||||
}
|
||||
QLineEdit filterInput(filter.pattern(), &dialog);
|
||||
layout.addRow(HOOK_SEARCH_FILTER, &filterInput);
|
||||
QLineEdit filterEdit(filter.pattern(), &dialog);
|
||||
layout.addRow(HOOK_SEARCH_FILTER, &filterEdit);
|
||||
QPushButton startButton(START_HOOK_SEARCH, &dialog);
|
||||
layout.addWidget(&startButton);
|
||||
QObject::connect(&startButton, &QPushButton::clicked, &dialog, &QDialog::accept);
|
||||
if (!dialog.exec()) return;
|
||||
if (patternInput.text().contains('.'))
|
||||
if (patternEdit.text().contains('.'))
|
||||
{
|
||||
wcsncpy_s(sp.exportModule, S(patternInput.text()).c_str(), MAX_MODULE_SIZE - 1);
|
||||
wcsncpy_s(sp.exportModule, S(patternEdit.text()).c_str(), MAX_MODULE_SIZE - 1);
|
||||
sp.length = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
QByteArray pattern = QByteArray::fromHex(patternInput.text().replace("??", QString::number(XX, 16)).toUtf8());
|
||||
QByteArray pattern = QByteArray::fromHex(patternEdit.text().replace("??", QString::number(XX, 16)).toUtf8());
|
||||
memcpy(sp.pattern, pattern.data(), sp.length = min(pattern.size(), PATTERN_SIZE));
|
||||
}
|
||||
wcsncpy_s(sp.boundaryModule, S(boundInput.text()).c_str(), MAX_MODULE_SIZE - 1);
|
||||
filter.setPattern(filterInput.text());
|
||||
wcsncpy_s(sp.boundaryModule, S(boundEdit.text()).c_str(), MAX_MODULE_SIZE - 1);
|
||||
filter.setPattern(filterEdit.text());
|
||||
if (!filter.isValid()) filter.setPattern(".");
|
||||
}
|
||||
else
|
||||
@ -467,12 +467,12 @@ namespace
|
||||
layout.addRow(label, spinBox);
|
||||
QObject::connect(&saveButton, &QPushButton::clicked, [spinBox, label, &settings, &value] { settings.setValue(label, value = spinBox->value()); });
|
||||
}
|
||||
QComboBox localeComboBox(&dialog);
|
||||
QComboBox localeCombo(&dialog);
|
||||
assert(PROMPT == 0 && ALWAYS == 1 && NEVER == 2);
|
||||
localeComboBox.addItems({ { "Prompt", "Always", "Never" } });
|
||||
localeComboBox.setCurrentIndex(settings.value(CONFIG_JP_LOCALE, PROMPT).toInt());
|
||||
layout.addRow(CONFIG_JP_LOCALE, &localeComboBox);
|
||||
QObject::connect(&localeComboBox, qOverload<int>(&QComboBox::activated), [&settings](int i) { settings.setValue(CONFIG_JP_LOCALE, i); });
|
||||
localeCombo.addItems({ { "Prompt", "Always", "Never" } });
|
||||
localeCombo.setCurrentIndex(settings.value(CONFIG_JP_LOCALE, PROMPT).toInt());
|
||||
layout.addRow(CONFIG_JP_LOCALE, &localeCombo);
|
||||
QObject::connect(&localeCombo, qOverload<int>(&QComboBox::activated), [&settings](int i) { settings.setValue(CONFIG_JP_LOCALE, i); });
|
||||
layout.addWidget(&saveButton);
|
||||
QObject::connect(&saveButton, &QPushButton::clicked, &dialog, &QDialog::accept);
|
||||
dialog.setWindowTitle(SETTINGS);
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
extern const wchar_t* TRANSLATION_ERROR;
|
||||
|
||||
extern Synchronized<std::wstring> translateTo, apiKey;
|
||||
extern Synchronized<std::wstring> translateTo, authKey;
|
||||
|
||||
const char* TRANSLATION_PROVIDER = "Bing Translate";
|
||||
const char* GET_API_KEY_FROM = "https://www.microsoft.com/en-us/translator/business/trial/#get-started";
|
||||
@ -84,14 +84,14 @@ int tokenCount = 30, tokenRestoreDelay = 60000, maxSentenceSize = 1000;
|
||||
|
||||
std::pair<bool, std::wstring> Translate(const std::wstring& text)
|
||||
{
|
||||
if (!apiKey->empty())
|
||||
if (!authKey->empty())
|
||||
if (HttpRequest httpRequest{
|
||||
L"Mozilla/5.0 Textractor",
|
||||
L"api.cognitive.microsofttranslator.com",
|
||||
L"POST",
|
||||
FormatString(L"/translate?api-version=3.0&to=%s", translateTo.Copy()).c_str(),
|
||||
FormatString(R"([{"text":"%s"}])", JSON::Escape(WideStringToString(text))),
|
||||
FormatString(L"Content-Type: application/json; charset=UTF-8\r\nOcp-Apim-Subscription-Key:%s", apiKey.Copy()).c_str()
|
||||
FormatString(L"Content-Type: application/json; charset=UTF-8\r\nOcp-Apim-Subscription-Key:%s", authKey.Copy()).c_str()
|
||||
})
|
||||
if (auto translation = Copy(JSON::Parse(httpRequest.response)[0][L"translations"][0][L"text"].String())) return { true, translation.value() };
|
||||
else return { false, FormatString(L"%s: %s", TRANSLATION_ERROR, httpRequest.response) };
|
||||
|
@ -5,7 +5,7 @@
|
||||
extern const wchar_t* TRANSLATION_ERROR;
|
||||
extern const char* USE_PREV_SENTENCE_CONTEXT;
|
||||
|
||||
extern Synchronized<std::wstring> translateTo, apiKey;
|
||||
extern Synchronized<std::wstring> translateTo, authKey;
|
||||
|
||||
const char* TRANSLATION_PROVIDER = "DeepL Translate";
|
||||
const char* GET_API_KEY_FROM = "https://www.deepl.com/pro.html";
|
||||
@ -32,20 +32,20 @@ int keyType = CAT;
|
||||
|
||||
std::pair<bool, std::wstring> Translate(const std::wstring& text)
|
||||
{
|
||||
if (!apiKey->empty())
|
||||
if (!authKey->empty())
|
||||
if (HttpRequest httpRequest{
|
||||
L"Mozilla/5.0 Textractor",
|
||||
L"api.deepl.com",
|
||||
L"POST",
|
||||
keyType == CAT ? L"/v1/translate" : L"/v2/translate",
|
||||
FormatString("text=%S&auth_key=%S&target_lang=%S", Escape(text), apiKey.Copy(), translateTo.Copy()),
|
||||
FormatString("text=%S&auth_key=%S&target_lang=%S", Escape(text), authKey.Copy(), translateTo.Copy()),
|
||||
L"Content-Type: application/x-www-form-urlencoded"
|
||||
}; httpRequest && (!httpRequest.response.empty() || (httpRequest = HttpRequest{
|
||||
L"Mozilla/5.0 Textractor",
|
||||
L"api.deepl.com",
|
||||
L"POST",
|
||||
(keyType = !keyType) == CAT ? L"/v1/translate" : L"/v2/translate",
|
||||
FormatString("text=%S&auth_key=%S&target_lang=%S", Escape(text), apiKey.Copy(), translateTo.Copy()),
|
||||
FormatString("text=%S&auth_key=%S&target_lang=%S", Escape(text), authKey.Copy(), translateTo.Copy()),
|
||||
L"Content-Type: application/x-www-form-urlencoded"
|
||||
})))
|
||||
// Response formatted as JSON: translation starts with text":" and ends with "}]
|
||||
|
@ -54,10 +54,10 @@ BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved
|
||||
display->addRow(CHROME_LOCATION, chromePathEdit);
|
||||
auto statusLabel = new QLabel("Stopped");
|
||||
auto startButton = new QPushButton(START_DEVTOOLS), stopButton = new QPushButton(STOP_DEVTOOLS);
|
||||
auto headlessCheckBox = new QCheckBox();
|
||||
headlessCheckBox->setChecked(settings.value(HEADLESS_MODE, true).toBool());
|
||||
QObject::connect(headlessCheckBox, &QCheckBox::clicked, [](bool headless) { settings.setValue(HEADLESS_MODE, headless); });
|
||||
QObject::connect(startButton, &QPushButton::clicked, [statusLabel, chromePathEdit, headlessCheckBox] {
|
||||
auto headlessCheck = new QCheckBox();
|
||||
headlessCheck->setChecked(settings.value(HEADLESS_MODE, true).toBool());
|
||||
QObject::connect(headlessCheck, &QCheckBox::clicked, [](bool headless) { settings.setValue(HEADLESS_MODE, headless); });
|
||||
QObject::connect(startButton, &QPushButton::clicked, [statusLabel, chromePathEdit, headlessCheck] {
|
||||
DevTools::Start(
|
||||
S(chromePathEdit->text()),
|
||||
[statusLabel](QString status)
|
||||
@ -82,14 +82,14 @@ BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved
|
||||
FormatString(LR"({"userAgent":"%s"})", userAgent->replace(userAgent->find(L"Headless"), 8, L"")));
|
||||
}).detach();
|
||||
},
|
||||
headlessCheckBox->isChecked()
|
||||
headlessCheck->isChecked()
|
||||
);
|
||||
});
|
||||
QObject::connect(stopButton, &QPushButton::clicked, &DevTools::Close);
|
||||
auto buttons = new QHBoxLayout();
|
||||
buttons->addWidget(startButton);
|
||||
buttons->addWidget(stopButton);
|
||||
display->addRow(HEADLESS_MODE, headlessCheckBox);
|
||||
display->addRow(HEADLESS_MODE, headlessCheck);
|
||||
auto autoStartButton = new QCheckBox();
|
||||
autoStartButton->setChecked(settings.value(AUTO_START, false).toBool());
|
||||
QObject::connect(autoStartButton, &QCheckBox::clicked, [](bool autoStart) { settings.setValue(AUTO_START, autoStart); });
|
||||
|
@ -55,14 +55,14 @@ struct PrettyWindow : QDialog
|
||||
settings.beginGroup(name);
|
||||
QFont font = ui.display->font();
|
||||
if (font.fromString(settings.value(FONT, font.toString()).toString())) ui.display->setFont(font);
|
||||
setBgColor(settings.value(BG_COLOR, bgColor).value<QColor>());
|
||||
setTextColor(settings.value(TEXT_COLOR, textColor()).value<QColor>());
|
||||
SetBackgroundColor(settings.value(BG_COLOR, backgroundColor).value<QColor>());
|
||||
SetTextColor(settings.value(TEXT_COLOR, TextColor()).value<QColor>());
|
||||
outliner.color = settings.value(OUTLINE_COLOR, outliner.color).value<QColor>();
|
||||
outliner.size = settings.value(OUTLINE_SIZE, outliner.size).toDouble();
|
||||
menu.addAction(FONT, this, &PrettyWindow::RequestFont);
|
||||
menu.addAction(BG_COLOR, [this] { setBgColor(colorPrompt(this, bgColor, BG_COLOR)); });
|
||||
menu.addAction(TEXT_COLOR, [this] { setTextColor(colorPrompt(this, textColor(), TEXT_COLOR)); });
|
||||
QAction* outlineAction = menu.addAction(TEXT_OUTLINE, this, &PrettyWindow::setOutline);
|
||||
menu.addAction(BG_COLOR, [this] { SetBackgroundColor(colorPrompt(this, backgroundColor, BG_COLOR)); });
|
||||
menu.addAction(TEXT_COLOR, [this] { SetTextColor(colorPrompt(this, TextColor(), TEXT_COLOR)); });
|
||||
QAction* outlineAction = menu.addAction(TEXT_OUTLINE, this, &PrettyWindow::SetOutline);
|
||||
outlineAction->setCheckable(true);
|
||||
outlineAction->setChecked(outliner.size >= 0);
|
||||
connect(ui.display, &QLabel::customContextMenuRequested, [this](QPoint point) { menu.exec(mapToGlobal(point)); });
|
||||
@ -89,28 +89,28 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
void setBgColor(QColor color)
|
||||
void SetBackgroundColor(QColor color)
|
||||
{
|
||||
if (!color.isValid()) return;
|
||||
if (color.alpha() == 0) color.setAlpha(1);
|
||||
bgColor = color;
|
||||
backgroundColor = color;
|
||||
repaint();
|
||||
settings.setValue(BG_COLOR, color.name(QColor::HexArgb));
|
||||
};
|
||||
|
||||
QColor textColor()
|
||||
QColor TextColor()
|
||||
{
|
||||
return ui.display->palette().color(QPalette::WindowText);
|
||||
}
|
||||
|
||||
void setTextColor(QColor color)
|
||||
void SetTextColor(QColor color)
|
||||
{
|
||||
if (!color.isValid()) return;
|
||||
ui.display->setPalette(QPalette(color, {}, {}, {}, {}, {}, {}));
|
||||
settings.setValue(TEXT_COLOR, color.name(QColor::HexArgb));
|
||||
};
|
||||
|
||||
void setOutline(bool enable)
|
||||
void SetOutline(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
@ -125,10 +125,10 @@ private:
|
||||
|
||||
void paintEvent(QPaintEvent*) override
|
||||
{
|
||||
QPainter(this).fillRect(rect(), bgColor);
|
||||
QPainter(this).fillRect(rect(), backgroundColor);
|
||||
}
|
||||
|
||||
QColor bgColor{ palette().window().color() };
|
||||
QColor backgroundColor{ palette().window().color() };
|
||||
struct : QGraphicsEffect
|
||||
{
|
||||
void draw(QPainter* painter) override
|
||||
@ -163,10 +163,10 @@ public:
|
||||
maxSentenceSize = settings.value(MAX_SENTENCE_SIZE, maxSentenceSize).toInt();
|
||||
|
||||
for (auto [name, default, slot] : Array<const char*, bool, void(ExtraWindow::*)(bool)>{
|
||||
{ TOPMOST, false, &ExtraWindow::setTopmost },
|
||||
{ SIZE_LOCK, false, &ExtraWindow::setLock },
|
||||
{ SHOW_ORIGINAL, true, &ExtraWindow::setShowOriginal },
|
||||
{ DICTIONARY, false, &ExtraWindow::setUseDictionary },
|
||||
{ TOPMOST, false, &ExtraWindow::SetTopmost },
|
||||
{ SIZE_LOCK, false, &ExtraWindow::SetLock },
|
||||
{ SHOW_ORIGINAL, true, &ExtraWindow::SetShowOriginal },
|
||||
{ DICTIONARY, false, &ExtraWindow::SetUseDictionary },
|
||||
})
|
||||
{
|
||||
// delay processing anything until Textractor has finished initializing
|
||||
@ -206,26 +206,26 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void setTopmost(bool topmost)
|
||||
void SetTopmost(bool topmost)
|
||||
{
|
||||
for (auto window : { winId(), dictionaryWindow.winId() })
|
||||
SetWindowPos((HWND)window, topmost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||
settings.setValue(TOPMOST, topmost);
|
||||
};
|
||||
|
||||
void setLock(bool locked)
|
||||
void SetLock(bool locked)
|
||||
{
|
||||
setSizeGripEnabled(!locked);
|
||||
settings.setValue(SIZE_LOCK, this->locked = locked);
|
||||
};
|
||||
|
||||
void setShowOriginal(bool showOriginal)
|
||||
void SetShowOriginal(bool showOriginal)
|
||||
{
|
||||
if (!showOriginal && settings.value(SHOW_ORIGINAL, false).toBool()) QMessageBox::information(this, SHOW_ORIGINAL, SHOW_ORIGINAL_INFO);
|
||||
settings.setValue(SHOW_ORIGINAL, this->showOriginal = showOriginal);
|
||||
};
|
||||
|
||||
void setUseDictionary(bool useDictionary)
|
||||
void SetUseDictionary(bool useDictionary)
|
||||
{
|
||||
if (useDictionary)
|
||||
{
|
||||
@ -239,11 +239,11 @@ private:
|
||||
settings.setValue(DICTIONARY, this->useDictionary = useDictionary);
|
||||
}
|
||||
|
||||
void computeDictionaryPosition(QPoint mouse)
|
||||
void ComputeDictionaryPosition(QPoint mouse)
|
||||
{
|
||||
QString sentence = ui.display->text();
|
||||
const QFont& font = ui.display->font();
|
||||
if (cachedDisplayInfo.compareExchange(ui.display))
|
||||
if (cachedDisplayInfo.CompareExchange(ui.display))
|
||||
{
|
||||
QFontMetrics fontMetrics(font, ui.display);
|
||||
textPositionMap.clear();
|
||||
@ -269,7 +269,7 @@ private:
|
||||
if (i == textPositionMap.size() || (mouse - textPositionMap[i]).manhattanLength() > font.pointSize() * 3) return dictionaryWindow.hide();
|
||||
if (sentence.mid(i) == dictionaryWindow.term) return dictionaryWindow.ShowDefinition();
|
||||
dictionaryWindow.ui.display->setFixedWidth(ui.display->width() * 3 / 4);
|
||||
dictionaryWindow.setTerm(sentence.mid(i));
|
||||
dictionaryWindow.SetTerm(sentence.mid(i));
|
||||
int left = i == 0 ? 0 : textPositionMap[i - 1].x(), right = textPositionMap[i].x(),
|
||||
x = textPositionMap[i].x() > ui.display->width() / 2 ? -dictionaryWindow.width() + (right * 3 + left) / 4 : (left * 3 + right) / 4, y = 0;
|
||||
for (auto point : textPositionMap) if (point.y() > y && point.y() < textPositionMap[i].y()) y = point.y();
|
||||
@ -278,7 +278,7 @@ private:
|
||||
|
||||
bool eventFilter(QObject*, QEvent* event) override
|
||||
{
|
||||
if (useDictionary && event->type() == QEvent::MouseMove) computeDictionaryPosition(((QMouseEvent*)event)->localPos().toPoint());
|
||||
if (useDictionary && event->type() == QEvent::MouseMove) ComputeDictionaryPosition(((QMouseEvent*)event)->localPos().toPoint());
|
||||
if (event->type() == QEvent::MouseButtonPress) dictionaryWindow.hide();
|
||||
return false;
|
||||
}
|
||||
@ -309,7 +309,7 @@ private:
|
||||
class
|
||||
{
|
||||
public:
|
||||
bool compareExchange(QLabel* display)
|
||||
bool CompareExchange(QLabel* display)
|
||||
{
|
||||
if (display->text() == text && display->font() == font && display->width() == width) return false;
|
||||
text = display->text();
|
||||
@ -389,7 +389,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void setTerm(QString term)
|
||||
void SetTerm(QString term)
|
||||
{
|
||||
this->term = term;
|
||||
UpdateDictionary();
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
extern const wchar_t* TRANSLATION_ERROR;
|
||||
|
||||
extern Synchronized<std::wstring> translateTo, apiKey;
|
||||
extern Synchronized<std::wstring> translateTo, authKey;
|
||||
|
||||
const char* TRANSLATION_PROVIDER = "Google Translate";
|
||||
const char* GET_API_KEY_FROM = "https://codelabs.developers.google.com/codelabs/cloud-translation-intro";
|
||||
@ -126,12 +126,12 @@ int tokenCount = 30, tokenRestoreDelay = 60000, maxSentenceSize = 1000;
|
||||
|
||||
std::pair<bool, std::wstring> Translate(const std::wstring& text)
|
||||
{
|
||||
if (!apiKey->empty())
|
||||
if (!authKey->empty())
|
||||
if (HttpRequest httpRequest{
|
||||
L"Mozilla/5.0 Textractor",
|
||||
L"translation.googleapis.com",
|
||||
L"POST",
|
||||
FormatString(L"/language/translate/v2?format=text&target=%s&key=%s", translateTo.Copy(), apiKey.Copy()).c_str(),
|
||||
FormatString(L"/language/translate/v2?format=text&target=%s&key=%s", translateTo.Copy(), authKey.Copy()).c_str(),
|
||||
FormatString(R"({"q":["%s"]})", JSON::Escape(WideStringToString(text)))
|
||||
})
|
||||
if (auto translation = Copy(JSON::Parse(httpRequest.response)[L"data"][L"translations"][0][L"translatedText"].String())) return { true, translation.value() };
|
||||
|
@ -12,6 +12,7 @@ extern const char* CURRENT_FILTER;
|
||||
const char* REGEX_SAVE_FILE = "SavedRegexFilters.txt";
|
||||
|
||||
std::optional<std::wregex> regex;
|
||||
std::wstring replace;
|
||||
std::shared_mutex m;
|
||||
DWORD (*GetSelectedProcessId)() = nullptr;
|
||||
|
||||
@ -24,16 +25,17 @@ public:
|
||||
Localize();
|
||||
ui.setupUi(this);
|
||||
|
||||
connect(ui.input, &QLineEdit::textEdited, this, &Window::setRegex);
|
||||
connect(ui.save, &QPushButton::clicked, this, &Window::saveRegex);
|
||||
connect(ui.regexEdit, &QLineEdit::textEdited, this, &Window::SetRegex);
|
||||
connect(ui.replaceEdit, &QLineEdit::textEdited, this, &Window::SetReplace);
|
||||
connect(ui.saveButton, &QPushButton::clicked, this, &Window::Save);
|
||||
|
||||
setWindowTitle(REGEX_FILTER);
|
||||
QMetaObject::invokeMethod(this, &QWidget::show, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void setRegex(QString regex)
|
||||
void SetRegex(QString regex)
|
||||
{
|
||||
ui.input->setText(regex);
|
||||
ui.regexEdit->setText(regex);
|
||||
std::scoped_lock lock(m);
|
||||
if (!regex.isEmpty()) try { ::regex = S(regex); }
|
||||
catch (std::regex_error) { return ui.output->setText(INVALID_REGEX); }
|
||||
@ -41,13 +43,21 @@ public:
|
||||
ui.output->setText(QString(CURRENT_FILTER).arg(regex));
|
||||
}
|
||||
|
||||
void SetReplace(QString replace)
|
||||
{
|
||||
ui.replaceEdit->setText(replace);
|
||||
std::scoped_lock lock(m);
|
||||
::replace = S(replace);
|
||||
}
|
||||
|
||||
private:
|
||||
void saveRegex()
|
||||
void Save()
|
||||
{
|
||||
auto formatted = FormatString(
|
||||
L"\xfeff|PROCESS|%s|FILTER|%s|END|\r\n",
|
||||
L"\xfeff|PROCESS|%s|FILTER|%s|REPLACE|%s|END|\r\n",
|
||||
GetModuleFilename(GetSelectedProcessId()).value_or(FormatString(L"Error getting name of process 0x%X", GetSelectedProcessId())),
|
||||
S(ui.input->text())
|
||||
S(ui.regexEdit->text()),
|
||||
S(ui.replaceEdit->text())
|
||||
);
|
||||
std::ofstream(REGEX_SAVE_FILE, std::ios::binary | std::ios::app).write((const char*)formatted.c_str(), formatted.size() * sizeof(wchar_t));
|
||||
}
|
||||
@ -62,12 +72,16 @@ bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
||||
if (sentenceInfo["current select"] && !regex) if (auto processName = GetModuleFilename(sentenceInfo["process id"]))
|
||||
{
|
||||
std::ifstream stream(REGEX_SAVE_FILE, std::ios::binary);
|
||||
BlockMarkupIterator savedFilters(stream, Array<std::wstring_view>{ L"|PROCESS|", L"|FILTER|" });
|
||||
std::vector<std::wstring> regexes;
|
||||
while (auto read = savedFilters.Next()) if (read->at(0) == processName) regexes.push_back(std::move(read->at(1)));
|
||||
if (!regexes.empty()) QMetaObject::invokeMethod(&window, [regex = S(regexes.back())] { window.setRegex(regex); }, Qt::BlockingQueuedConnection);
|
||||
BlockMarkupIterator savedFilters(stream, Array<std::wstring_view>{ L"|PROCESS|", L"|FILTER|", L"|REPLACE|" });
|
||||
std::vector<std::array<std::wstring, 3>> regexes;
|
||||
while (auto read = savedFilters.Next()) if (read->at(0) == processName) regexes.push_back(std::move(read.value()));
|
||||
if (!regexes.empty()) QMetaObject::invokeMethod(&window, [regex = S(regexes.back()[1]), replace = S(regexes.back()[2])]
|
||||
{
|
||||
window.SetRegex(regex);
|
||||
window.SetReplace(replace);
|
||||
}, Qt::BlockingQueuedConnection);
|
||||
}
|
||||
std::shared_lock l(m);
|
||||
if (regex) sentence = std::regex_replace(sentence, regex.value(), L"");
|
||||
if (regex) sentence = std::regex_replace(sentence, regex.value(), replace);
|
||||
return true;
|
||||
}
|
||||
|
@ -6,13 +6,27 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>350</width>
|
||||
<height>105</height>
|
||||
<width>500</width>
|
||||
<height>107</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="input"/>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="regexEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel">
|
||||
<property name="text">
|
||||
<string>=></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="replaceEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="output">
|
||||
@ -25,7 +39,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="save">
|
||||
<widget class="QPushButton" name="saveButton">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
|
@ -30,7 +30,7 @@ const std::string TRANSLATION_CACHE_FILE = FormatString("%s Translation Cache.tx
|
||||
|
||||
QFormLayout* display;
|
||||
Settings settings;
|
||||
Synchronized<std::wstring> translateTo = L"en", apiKey;
|
||||
Synchronized<std::wstring> translateTo = L"en", authKey;
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -57,16 +57,16 @@ public:
|
||||
|
||||
settings.beginGroup(TRANSLATION_PROVIDER);
|
||||
|
||||
auto languageBox = new QComboBox(this);
|
||||
languageBox->addItems(languages);
|
||||
auto languageCombo = new QComboBox(this);
|
||||
languageCombo->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);
|
||||
if (settings.contains(LANGUAGE)) language = languageCombo->findText(settings.value(LANGUAGE).toString(), Qt::MatchEndsWith);
|
||||
if (language < 0) language = languageCombo->findText(NATIVE_LANGUAGE, Qt::MatchStartsWith);
|
||||
if (language < 0) language = languageCombo->findText("English", Qt::MatchStartsWith);
|
||||
languageCombo->setCurrentIndex(language);
|
||||
saveLanguage(languageCombo->currentText());
|
||||
display->addRow(TRANSLATE_TO, languageCombo);
|
||||
connect(languageCombo, &QComboBox::currentTextChanged, this, &Window::saveLanguage);
|
||||
for (auto [value, label] : Array<bool&, const char*>{
|
||||
{ translateSelectedOnly, TRANSLATE_SELECTED_THREAD_ONLY },
|
||||
{ rateLimitAll, RATE_LIMIT_ALL_THREADS },
|
||||
@ -95,12 +95,12 @@ public:
|
||||
}
|
||||
if (GET_API_KEY_FROM)
|
||||
{
|
||||
auto keyInput = new QLineEdit(settings.value(API_KEY).toString(), this);
|
||||
apiKey->assign(S(keyInput->text()));
|
||||
QObject::connect(keyInput, &QLineEdit::textChanged, [](QString key) { settings.setValue(API_KEY, S(apiKey->assign(S(key)))); });
|
||||
auto keyEdit = new QLineEdit(settings.value(API_KEY).toString(), this);
|
||||
authKey->assign(S(keyEdit->text()));
|
||||
QObject::connect(keyEdit, &QLineEdit::textChanged, [](QString key) { settings.setValue(API_KEY, S(authKey->assign(S(key)))); });
|
||||
auto keyLabel = new QLabel(QString("<a href=\"%1\">%2</a>").arg(GET_API_KEY_FROM, API_KEY), this);
|
||||
keyLabel->setOpenExternalLinks(true);
|
||||
display->addRow(keyLabel, keyInput);
|
||||
display->addRow(keyLabel, keyEdit);
|
||||
}
|
||||
|
||||
setWindowTitle(TRANSLATION_PROVIDER);
|
||||
|
Loading…
x
Reference in New Issue
Block a user