Merge branch 'master' into devtools_papago_translate
This commit is contained in:
commit
918c877e04
@ -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
|
||||
|
48
GUI/attachprocessdialog.cpp
Normal file
48
GUI/attachprocessdialog.cpp
Normal 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
17
GUI/attachprocessdialog.h
Normal 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;
|
||||
};
|
41
GUI/attachprocessdialog.ui
Normal file
41
GUI/attachprocessdialog.ui
Normal 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>
|
@ -2,11 +2,6 @@
|
||||
|
||||
#include "qtcommon.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ExtenWindow;
|
||||
}
|
||||
|
||||
struct InfoForExtension
|
||||
{
|
||||
const char* name;
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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()
|
||||
|
63
extensions/devtoolssystrantranslate.cpp
Normal file
63
extensions/devtoolssystrantranslate.cpp
Normal 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 };
|
||||
}
|
Loading…
Reference in New Issue
Block a user