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)
msvc_registry_search()
find_qt5(Core Widgets)
find_qt5(Core Widgets WinExtras)
add_executable(Textractor WIN32
main.cpp
mainwindow.cpp
extenwindow.cpp
attachprocessdialog.cpp
host/exception.cpp
host/host.cpp
host/textthread.cpp
@ -14,7 +15,7 @@ add_executable(Textractor WIN32
Textractor.ico
)
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)
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"
namespace Ui
{
class ExtenWindow;
}
struct InfoForExtension
{
const char* name;

View File

@ -5,6 +5,7 @@
#include "extenwindow.h"
#include "host/host.h"
#include "host/hookcode.h"
#include "attachprocessdialog.h"
#include <shellapi.h>
#include <process.h>
#include <QRegularExpression>
@ -14,6 +15,7 @@
#include <QDialogButtonBox>
#include <QFileDialog>
#include <QFontDialog>
#include <QHash>
extern const char* ATTACH;
extern const char* LAUNCH;
@ -28,7 +30,6 @@ extern const char* SETTINGS;
extern const char* EXTENSIONS;
extern const char* FONT;
extern const char* SELECT_PROCESS;
extern const char* ATTACH_INFO;
extern const char* SELECT_PROCESS_INFO;
extern const char* FROM_COMPUTER;
extern const char* PROCESSES;
@ -153,16 +154,31 @@ namespace
void AttachProcess()
{
QMultiHash<QString, DWORD> allProcesses;
QMultiHash<QString, DWORD> processesMap;
std::vector<std::pair<QString, HICON>> processIcons;
for (auto [processId, processName] : GetAllProcesses())
{
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());
processList.sort(Qt::CaseInsensitive);
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));
else for (auto processId : allProcesses.values(process)) Host::InjectProcess(processId);
AttachProcessDialog attachProcessDialog(This, processIcons);
if (attachProcessDialog.exec())
{
QString process = attachProcessDialog.SelectedProcess();
if (int processId = process.toInt(nullptr, 0)) Host::InjectProcess(processId);
else for (int processId : processesMap.values(process)) Host::InjectProcess(processId);
}
}
void LaunchProcess()

View File

@ -10,9 +10,9 @@ Watch the [tutorial video](https://tinyurl.com/textractor-tutorial) for a quick
## Download
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>
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

View File

@ -46,6 +46,7 @@ foreach ($language in @{
"DeepL Translate",
"DevTools DeepL Translate",
"DevTools Papago Translate",
"DevTools Systran Translate",
"Extra Newlines",
"Extra Window",
"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\**\*");
}
rm -Force -Recurse -Verbose "Runtime";
mkdir -Force -Verbose "Runtime";
foreach ($arch in @("x86", "x64"))
@ -79,6 +79,7 @@ foreach ($arch in @("x86", "x64"))
"Qt5Gui.dll",
"Qt5Network.dll",
"Qt5WebSockets.dll",
"Qt5WinExtras.dll"
"Qt5Widgets.dll",
"platforms",
"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(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\ 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\ Window MODULE extrawindow.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(DevTools\ DeepL\ 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\ Window 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(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\ Systran\ Translate shell32 winhttp Qt5::Widgets Qt5::WebSockets)
target_link_libraries(Extra\ Window Qt5::Widgets)
target_link_libraries(Google\ Translate winhttp 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 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()

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 };
}