Merge branch 'master' into devtools_papago_translate

This commit is contained in:
Akash Mozumdar 2021-06-06 03:15:33 -06:00 committed by GitHub
commit 918c877e04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 203 additions and 24 deletions

View File

@ -1,11 +1,12 @@
include(QtUtils) include(QtUtils)
msvc_registry_search() msvc_registry_search()
find_qt5(Core Widgets) find_qt5(Core Widgets WinExtras)
add_executable(Textractor WIN32 add_executable(Textractor WIN32
main.cpp main.cpp
mainwindow.cpp mainwindow.cpp
extenwindow.cpp extenwindow.cpp
attachprocessdialog.cpp
host/exception.cpp host/exception.cpp
host/host.cpp host/host.cpp
host/textthread.cpp host/textthread.cpp
@ -14,7 +15,7 @@ add_executable(Textractor WIN32
Textractor.ico Textractor.ico
) )
target_precompile_headers(Textractor REUSE_FROM pch) target_precompile_headers(Textractor REUSE_FROM pch)
target_link_libraries(Textractor Qt5::Widgets shell32 winhttp) target_link_libraries(Textractor Qt5::Widgets Qt5::WinExtras shell32 winhttp)
if (NOT EXISTS ${CMAKE_FINAL_OUTPUT_DIRECTORY}/Qt5Core.dll AND NOT EXISTS ${CMAKE_FINAL_OUTPUT_DIRECTORY}/Qt5Cored.dll) if (NOT EXISTS ${CMAKE_FINAL_OUTPUT_DIRECTORY}/Qt5Core.dll AND NOT EXISTS ${CMAKE_FINAL_OUTPUT_DIRECTORY}/Qt5Cored.dll)
add_custom_command(TARGET Textractor add_custom_command(TARGET Textractor

View File

@ -0,0 +1,48 @@
#include "attachprocessdialog.h"
#include <QtWinExtras/QtWin>
extern const char* SELECT_PROCESS;
extern const char* ATTACH_INFO;
AttachProcessDialog::AttachProcessDialog(QWidget *parent, std::vector<std::pair<QString, HICON>> processIcons) :
QDialog(parent, Qt::WindowCloseButtonHint),
model(this)
{
ui.setupUi(this);
setWindowTitle(SELECT_PROCESS);
ui.label->setText(ATTACH_INFO);
ui.processIdEdit->setValidator(new QIntValidator(0, INT_MAX, this));
ui.processList->setModel(&model);
QPixmap transparent(100, 100);
transparent.fill(QColor::fromRgba(0));
for (const auto& [process, icon] : processIcons)
{
auto item = new QStandardItem(icon ? QIcon(QtWin::fromHICON(icon)) : transparent, process);
item->setEditable(false);
model.appendRow(item);
}
connect(ui.buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(ui.buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(ui.processList, &QListView::clicked, [this](QModelIndex index)
{
selectedProcess = model.item(index.row())->text();
});
connect(ui.processList, &QListView::doubleClicked, [this](QModelIndex index)
{
selectedProcess = model.item(index.row())->text();
accept();
});
connect(ui.processIdEdit, &QLineEdit::returnPressed, [this]
{
selectedProcess = ui.processIdEdit->text();
accept();
});
}
QString AttachProcessDialog::SelectedProcess()
{
return selectedProcess.isEmpty() ? ui.processIdEdit->text() : selectedProcess;
}

17
GUI/attachprocessdialog.h Normal file
View File

@ -0,0 +1,17 @@
#pragma once
#include "qtcommon.h"
#include "ui_attachprocessdialog.h"
#include <QStandardItemModel>
class AttachProcessDialog : public QDialog
{
public:
explicit AttachProcessDialog(QWidget *parent, std::vector<std::pair<QString, HICON>> processIcons);
QString SelectedProcess();
private:
Ui::AttachProcessDialog ui;
QStandardItemModel model;
QString selectedProcess;
};

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AttachProcessDialog</class>
<widget class="QWidget" name="AttachProcessDialog">
<property name="windowModality">
<enum>Qt::WindowModal</enum>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>400</height>
</rect>
</property>
<layout class="QVBoxLayout">
<item>
<widget class="QLabel" name="label"/>
</item>
<item>
<widget class="QLineEdit" name="processIdEdit">
<property name="placeholderText">
<string>Process id</string>
</property>
</widget>
</item>
<item>
<widget class="QListView" name="processList"/>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -2,11 +2,6 @@
#include "qtcommon.h" #include "qtcommon.h"
namespace Ui
{
class ExtenWindow;
}
struct InfoForExtension struct InfoForExtension
{ {
const char* name; const char* name;

View File

@ -5,6 +5,7 @@
#include "extenwindow.h" #include "extenwindow.h"
#include "host/host.h" #include "host/host.h"
#include "host/hookcode.h" #include "host/hookcode.h"
#include "attachprocessdialog.h"
#include <shellapi.h> #include <shellapi.h>
#include <process.h> #include <process.h>
#include <QRegularExpression> #include <QRegularExpression>
@ -14,6 +15,7 @@
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QFileDialog> #include <QFileDialog>
#include <QFontDialog> #include <QFontDialog>
#include <QHash>
extern const char* ATTACH; extern const char* ATTACH;
extern const char* LAUNCH; extern const char* LAUNCH;
@ -28,7 +30,6 @@ extern const char* SETTINGS;
extern const char* EXTENSIONS; extern const char* EXTENSIONS;
extern const char* FONT; extern const char* FONT;
extern const char* SELECT_PROCESS; extern const char* SELECT_PROCESS;
extern const char* ATTACH_INFO;
extern const char* SELECT_PROCESS_INFO; extern const char* SELECT_PROCESS_INFO;
extern const char* FROM_COMPUTER; extern const char* FROM_COMPUTER;
extern const char* PROCESSES; extern const char* PROCESSES;
@ -153,16 +154,31 @@ namespace
void AttachProcess() void AttachProcess()
{ {
QMultiHash<QString, DWORD> allProcesses; QMultiHash<QString, DWORD> processesMap;
std::vector<std::pair<QString, HICON>> processIcons;
for (auto [processId, processName] : GetAllProcesses()) for (auto [processId, processName] : GetAllProcesses())
{
if (processName && (showSystemProcesses || processName->find(L":\\Windows\\") == std::string::npos)) if (processName && (showSystemProcesses || processName->find(L":\\Windows\\") == std::string::npos))
allProcesses.insert(QFileInfo(S(processName.value())).fileName(), processId); {
QString fileName = QFileInfo(S(processName.value())).fileName();
if (!processesMap.contains(fileName))
{
HICON bigIcon, smallIcon;
ExtractIconExW(processName->c_str(), 0, &bigIcon, &smallIcon, 1);
processIcons.push_back({ fileName, bigIcon ? bigIcon : smallIcon });
}
processesMap.insert(fileName, processId);
}
}
std::sort(processIcons.begin(), processIcons.end());
QStringList processList(allProcesses.uniqueKeys()); AttachProcessDialog attachProcessDialog(This, processIcons);
processList.sort(Qt::CaseInsensitive); if (attachProcessDialog.exec())
if (QString process = QInputDialog::getItem(This, SELECT_PROCESS, ATTACH_INFO, processList, 0, true, &ok, Qt::WindowCloseButtonHint); ok) {
if (process.toInt(nullptr, 0)) Host::InjectProcess(process.toInt(nullptr, 0)); QString process = attachProcessDialog.SelectedProcess();
else for (auto processId : allProcesses.values(process)) Host::InjectProcess(processId); if (int processId = process.toInt(nullptr, 0)) Host::InjectProcess(processId);
else for (int processId : processesMap.values(process)) Host::InjectProcess(processId);
}
} }
void LaunchProcess() void LaunchProcess()

View File

@ -10,9 +10,9 @@ Watch the [tutorial video](https://tinyurl.com/textractor-tutorial) for a quick
## Download ## Download
Official stable releases of Textractor can be found [here](https://github.com/Artikash/Textractor/releases).<br> Official stable releases of Textractor can be found [here](https://github.com/Artikash/Textractor/releases).<br>
Experimental builds of Textractor from the latest source can be found [here](https://ci.appveyor.com/project/Artikash/textractor/history) (in the 'Artifacts' section of a job).<br>
The last release of ITHVNR can be found [here](https://drive.google.com/open?id=13aHF4uIXWn-3YML_k2YCDWhtGgn5-tnO).<br> The last release of ITHVNR can be found [here](https://drive.google.com/open?id=13aHF4uIXWn-3YML_k2YCDWhtGgn5-tnO).<br>
Try running vcredist if you get an error when starting Textractor. Experimental builds of Textractor (with debug info) from the latest source can be found [here](https://ci.appveyor.com/project/Artikash/textractor/history) in the 'Artifacts' section of each job.<br>
Try running vcredist if you get an error when starting Textractor or if nothing happens when you try attaching to a game.
## Features ## Features

View File

@ -46,6 +46,7 @@ foreach ($language in @{
"DeepL Translate", "DeepL Translate",
"DevTools DeepL Translate", "DevTools DeepL Translate",
"DevTools Papago Translate", "DevTools Papago Translate",
"DevTools Systran Translate",
"Extra Newlines", "Extra Newlines",
"Extra Window", "Extra Window",
"Google Translate", "Google Translate",
@ -66,7 +67,6 @@ foreach ($language in @{
&"C:\Program Files (x86)\Windows Kits\10\App Certification Kit\signtool.exe" sign /a /v /t "http://timestamp.digicert.com" /fd SHA256 @(dir "$folder\**\*"); &"C:\Program Files (x86)\Windows Kits\10\App Certification Kit\signtool.exe" sign /a /v /t "http://timestamp.digicert.com" /fd SHA256 @(dir "$folder\**\*");
} }
rm -Force -Recurse -Verbose "Runtime"; rm -Force -Recurse -Verbose "Runtime";
mkdir -Force -Verbose "Runtime"; mkdir -Force -Verbose "Runtime";
foreach ($arch in @("x86", "x64")) foreach ($arch in @("x86", "x64"))
@ -79,6 +79,7 @@ foreach ($arch in @("x86", "x64"))
"Qt5Gui.dll", "Qt5Gui.dll",
"Qt5Network.dll", "Qt5Network.dll",
"Qt5WebSockets.dll", "Qt5WebSockets.dll",
"Qt5WinExtras.dll"
"Qt5Widgets.dll", "Qt5Widgets.dll",
"platforms", "platforms",
"styles" "styles"

View File

@ -8,6 +8,7 @@ add_library(Copy\ to\ Clipboard MODULE copyclipboard.cpp extensionimpl.cpp)
add_library(DeepL\ Translate MODULE deepltranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp) add_library(DeepL\ Translate MODULE deepltranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
add_library(DevTools\ DeepL\ Translate MODULE devtoolsdeepltranslate.cpp devtools.cpp translatewrapper.cpp network.cpp extensionimpl.cpp) add_library(DevTools\ DeepL\ Translate MODULE devtoolsdeepltranslate.cpp devtools.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
add_library(DevTools\ Papago\ Translate MODULE devtoolspapagotranslate.cpp devtools.cpp translatewrapper.cpp network.cpp extensionimpl.cpp) add_library(DevTools\ Papago\ Translate MODULE devtoolspapagotranslate.cpp devtools.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
add_library(DevTools\ Systran\ Translate MODULE devtoolssystrantranslate.cpp devtools.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
add_library(Extra\ Newlines MODULE extranewlines.cpp extensionimpl.cpp) add_library(Extra\ Newlines MODULE extranewlines.cpp extensionimpl.cpp)
add_library(Extra\ Window MODULE extrawindow.cpp extensionimpl.cpp) add_library(Extra\ Window MODULE extrawindow.cpp extensionimpl.cpp)
add_library(Google\ Translate MODULE googletranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp) add_library(Google\ Translate MODULE googletranslate.cpp translatewrapper.cpp network.cpp extensionimpl.cpp)
@ -26,6 +27,7 @@ target_precompile_headers(Copy\ to\ Clipboard REUSE_FROM pch)
target_precompile_headers(DeepL\ Translate REUSE_FROM pch) target_precompile_headers(DeepL\ Translate REUSE_FROM pch)
target_precompile_headers(DevTools\ DeepL\ Translate REUSE_FROM pch) target_precompile_headers(DevTools\ DeepL\ Translate REUSE_FROM pch)
target_precompile_headers(DevTools\ Papago\ Translate REUSE_FROM pch) target_precompile_headers(DevTools\ Papago\ Translate REUSE_FROM pch)
target_precompile_headers(DevTools\ Systran\ Translate REUSE_FROM pch)
target_precompile_headers(Extra\ Newlines REUSE_FROM pch) target_precompile_headers(Extra\ Newlines REUSE_FROM pch)
target_precompile_headers(Extra\ Window REUSE_FROM pch) target_precompile_headers(Extra\ Window REUSE_FROM pch)
target_precompile_headers(Google\ Translate REUSE_FROM pch) target_precompile_headers(Google\ Translate REUSE_FROM pch)
@ -43,6 +45,7 @@ target_link_libraries(Bing\ Translate winhttp Qt5::Widgets)
target_link_libraries(DeepL\ Translate winhttp Qt5::Widgets) target_link_libraries(DeepL\ Translate winhttp Qt5::Widgets)
target_link_libraries(DevTools\ DeepL\ Translate shell32 winhttp Qt5::Widgets Qt5::WebSockets) target_link_libraries(DevTools\ DeepL\ Translate shell32 winhttp Qt5::Widgets Qt5::WebSockets)
target_link_libraries(DevTools\ Papago\ Translate shell32 winhttp Qt5::Widgets Qt5::WebSockets) target_link_libraries(DevTools\ Papago\ Translate shell32 winhttp Qt5::Widgets Qt5::WebSockets)
target_link_libraries(DevTools\ Systran\ Translate shell32 winhttp Qt5::Widgets Qt5::WebSockets)
target_link_libraries(Extra\ Window Qt5::Widgets) target_link_libraries(Extra\ Window Qt5::Widgets)
target_link_libraries(Google\ Translate winhttp Qt5::Widgets) target_link_libraries(Google\ Translate winhttp Qt5::Widgets)
target_link_libraries(Lua lua53 Qt5::Widgets) target_link_libraries(Lua lua53 Qt5::Widgets)
@ -59,10 +62,4 @@ if (NOT EXISTS ${CMAKE_FINAL_OUTPUT_DIRECTORY}/Qt5WebSockets.dll AND NOT EXISTS
COMMAND set PATH=%PATH%$<SEMICOLON>${qt5_install_prefix}/bin COMMAND set PATH=%PATH%$<SEMICOLON>${qt5_install_prefix}/bin
COMMAND Qt5::windeployqt --dir ${CMAKE_FINAL_OUTPUT_DIRECTORY} "${CMAKE_FINAL_OUTPUT_DIRECTORY}/DevTools\ DeepL\ Translate.dll" COMMAND Qt5::windeployqt --dir ${CMAKE_FINAL_OUTPUT_DIRECTORY} "${CMAKE_FINAL_OUTPUT_DIRECTORY}/DevTools\ DeepL\ Translate.dll"
) )
add_custom_command(TARGET DevTools\ Papago\ Translate
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/windeployqt"
COMMAND set PATH=%PATH%$<SEMICOLON>${qt5_install_prefix}/bin
COMMAND Qt5::windeployqt --dir ${CMAKE_FINAL_OUTPUT_DIRECTORY} "${CMAKE_FINAL_OUTPUT_DIRECTORY}/DevTools\ Papago\ Translate.dll"
)
endif() endif()

View File

@ -0,0 +1,63 @@
#include "qtcommon.h"
#include "devtools.h"
extern const wchar_t* ERROR_START_CHROME;
extern const wchar_t* TRANSLATION_ERROR;
extern Synchronized<std::wstring> translateTo, translateFrom;
extern QFormLayout* display;
extern Settings settings;
const char* TRANSLATION_PROVIDER = "DevTools Systran Translate";
const char* GET_API_KEY_FROM = nullptr;
bool translateSelectedOnly = true, rateLimitAll = false, rateLimitSelected = false, useCache = true, useFilter = true;
int tokenCount = 30, tokenRestoreDelay = 60000, maxSentenceSize = 2500;
QStringList languages
{
"Chinese: zh",
"Chinese (traditional): zt",
"English: en",
"French: fr",
"German: de",
"Italian: it",
"Japanese: ja",
"Korean: ko",
"Portuguese: pt",
"Spanish: es",
"Thai: th",
};
std::wstring autoDetectLanguage = L"auto";
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
DevTools::Start();
}
break;
case DLL_PROCESS_DETACH:
{
DevTools::Close();
}
break;
}
return TRUE;
}
std::pair<bool, std::wstring> Translate(const std::wstring& text)
{
if (!DevTools::Connected()) return { false, FormatString(L"%s: %s", TRANSLATION_ERROR, ERROR_START_CHROME) };
// DevTools can't handle concurrent translations yet
static std::mutex translationMutex;
std::scoped_lock lock(translationMutex);
DevTools::SendRequest("Page.navigate", FormatString(LR"({"url":"https://translate.systran.net/?&source=%s&target=%s&input=%s"})", translateFrom.Copy(), translateTo.Copy(), Escape(text)));
for (int retry = 0; ++retry < 100; Sleep(100))
if (auto translation = Copy(DevTools::SendRequest("Runtime.evaluate",
LR"({"expression":"document.querySelector('#outputEditor').textContent.trim() ","returnByValue":true})"
)[L"result"][L"value"].String())) if (!translation->empty()) return { true, translation.value() };
return { false, TRANSLATION_ERROR };
}