refactor and perf improvements
This commit is contained in:
parent
6bac544c89
commit
f1d46e9f73
@ -70,6 +70,14 @@ bool DispatchSentenceToExtensions(std::wstring& sentence, const InfoForExtension
|
|||||||
return !sentence.empty();
|
return !sentence.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CleanupExtensions()
|
||||||
|
{
|
||||||
|
std::scoped_lock writeLock(extenMutex);
|
||||||
|
for (auto extension : extensions)
|
||||||
|
FreeLibrary(GetModuleHandleW(extension.name.c_str()));
|
||||||
|
extensions.clear();
|
||||||
|
}
|
||||||
|
|
||||||
ExtenWindow::ExtenWindow(QWidget* parent) :
|
ExtenWindow::ExtenWindow(QWidget* parent) :
|
||||||
QMainWindow(parent, Qt::WindowCloseButtonHint),
|
QMainWindow(parent, Qt::WindowCloseButtonHint),
|
||||||
ui(new Ui::ExtenWindow)
|
ui(new Ui::ExtenWindow)
|
||||||
|
@ -14,6 +14,7 @@ struct InfoForExtension
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool DispatchSentenceToExtensions(std::wstring& sentence, const InfoForExtension* miscInfo);
|
bool DispatchSentenceToExtensions(std::wstring& sentence, const InfoForExtension* miscInfo);
|
||||||
|
void CleanupExtensions(); // must call this before exiting the program, only way to uphold guarantee that DllMain and OnNewSentence won't be called concurrently
|
||||||
|
|
||||||
class ExtenWindow : public QMainWindow
|
class ExtenWindow : public QMainWindow
|
||||||
{
|
{
|
||||||
|
@ -134,6 +134,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
{
|
{
|
||||||
QSettings(CONFIG_FILE, QSettings::IniFormat).setValue(WINDOW, geometry());
|
QSettings(CONFIG_FILE, QSettings::IniFormat).setValue(WINDOW, geometry());
|
||||||
|
CleanupExtensions();
|
||||||
SetErrorMode(SEM_NOGPFAULTERRORBOX);
|
SetErrorMode(SEM_NOGPFAULTERRORBOX);
|
||||||
ExitProcess(0);
|
ExitProcess(0);
|
||||||
}
|
}
|
||||||
@ -177,7 +178,7 @@ void MainWindow::ThreadAdded(TextThread& thread)
|
|||||||
{
|
{
|
||||||
std::wstring threadCode = Util::GenerateCode(thread.hp, thread.tp.processId);
|
std::wstring threadCode = Util::GenerateCode(thread.hp, thread.tp.processId);
|
||||||
QString ttString = TextThreadString(thread) + S(thread.name) + " (" + S(threadCode) + ")";
|
QString ttString = TextThreadString(thread) + S(thread.name) + " (" + S(threadCode) + ")";
|
||||||
bool savedMatch = savedThreadCtx.first == thread.tp.ctx && savedThreadCtx.second == thread.tp.ctx2 && savedThreadCode == threadCode;
|
bool savedMatch = savedThreadCtx == std::pair(thread.tp.ctx, thread.tp.ctx2) && savedThreadCode == threadCode;
|
||||||
if (savedMatch) savedThreadCtx.first = savedThreadCtx.second = savedThreadCode[0] = 0;
|
if (savedMatch) savedThreadCtx.first = savedThreadCtx.second = savedThreadCode[0] = 0;
|
||||||
QMetaObject::invokeMethod(this, [this, ttString, savedMatch]
|
QMetaObject::invokeMethod(this, [this, ttString, savedMatch]
|
||||||
{
|
{
|
||||||
@ -236,9 +237,9 @@ std::array<InfoForExtension, 10> MainWindow::GetMiscInfo(TextThread& thread)
|
|||||||
{
|
{
|
||||||
void(*AddSentence)(MainWindow*, int64_t, const wchar_t*) = [](MainWindow* This, int64_t number, const wchar_t* sentence)
|
void(*AddSentence)(MainWindow*, int64_t, const wchar_t*) = [](MainWindow* This, int64_t number, const wchar_t* sentence)
|
||||||
{
|
{
|
||||||
std::wstring sentenceStr = sentence;
|
std::wstring copy = sentence;
|
||||||
// pointer from Host::GetThread may not stay valid unless on main thread
|
// pointer from Host::GetThread may not stay valid unless on main thread
|
||||||
QMetaObject::invokeMethod(This, [=]() mutable { if (TextThread* thread = Host::GetThread(number)) thread->AddSentence(std::move(sentenceStr)); });
|
QMetaObject::invokeMethod(This, [=]() mutable { if (TextThread* thread = Host::GetThread(number)) thread->AddSentence(std::move(copy)); });
|
||||||
};
|
};
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -394,7 +395,7 @@ void MainWindow::FindHooks()
|
|||||||
connect(&confirm, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
connect(&confirm, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
||||||
connect(&confirm, &QDialogButtonBox::helpRequested, &dialog, &QDialog::accept);
|
connect(&confirm, &QDialogButtonBox::helpRequested, &dialog, &QDialog::accept);
|
||||||
dialog.setWindowTitle(SEARCH_FOR_HOOKS);
|
dialog.setWindowTitle(SEARCH_FOR_HOOKS);
|
||||||
if (dialog.exec() == QDialog::Rejected) return;
|
if (!dialog.exec()) return;
|
||||||
|
|
||||||
if (customSettings)
|
if (customSettings)
|
||||||
{
|
{
|
||||||
@ -432,7 +433,7 @@ void MainWindow::FindHooks()
|
|||||||
QPushButton startButton(START_HOOK_SEARCH, &dialog);
|
QPushButton startButton(START_HOOK_SEARCH, &dialog);
|
||||||
layout.addWidget(&startButton);
|
layout.addWidget(&startButton);
|
||||||
connect(&startButton, &QPushButton::clicked, &dialog, &QDialog::accept);
|
connect(&startButton, &QPushButton::clicked, &dialog, &QDialog::accept);
|
||||||
if (dialog.exec() == QDialog::Rejected) return;
|
if (!dialog.exec()) return;
|
||||||
QByteArray pattern = QByteArray::fromHex(patternInput.text().replace("??", QString::number(XX, 16)).toUtf8());
|
QByteArray pattern = QByteArray::fromHex(patternInput.text().replace("??", QString::number(XX, 16)).toUtf8());
|
||||||
memcpy(sp.pattern, pattern.data(), sp.length = min(pattern.size(), 25));
|
memcpy(sp.pattern, pattern.data(), sp.length = min(pattern.size(), 25));
|
||||||
try { filter = std::wregex(S(filterInput.text())); } catch (std::regex_error) {};
|
try { filter = std::wregex(S(filterInput.text())); } catch (std::regex_error) {};
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
#include "extension.h"
|
#include "extension.h"
|
||||||
|
#include "ui_extrawindow.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include <QDialog>
|
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QColorDialog>
|
#include <QColorDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
@ -14,7 +12,6 @@
|
|||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
extern const char* EXTRA_WINDOW_INFO;
|
extern const char* EXTRA_WINDOW_INFO;
|
||||||
extern const char* TOPMOST;
|
extern const char* TOPMOST;
|
||||||
@ -29,117 +26,117 @@ extern const char* FONT_FAMILY;
|
|||||||
extern const char* FONT_WEIGHT;
|
extern const char* FONT_WEIGHT;
|
||||||
extern const char* SAVE_SETTINGS;
|
extern const char* SAVE_SETTINGS;
|
||||||
|
|
||||||
std::mutex m;
|
struct Window : QDialog
|
||||||
|
|
||||||
struct : QDialog
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void launch()
|
Window()
|
||||||
{
|
{
|
||||||
settings->beginGroup("Extra Window");
|
ui.setupUi(this);
|
||||||
(new QHBoxLayout(this))->addWidget(display = new QLabel(EXTRA_WINDOW_INFO, this));
|
|
||||||
display->setTextFormat(Qt::PlainText);
|
settings.beginGroup("Extra Window");
|
||||||
display->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
|
||||||
display->setAlignment(Qt::AlignTop);
|
|
||||||
display->setWordWrap(true);
|
|
||||||
display->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
|
|
||||||
setWindowFlags(Qt::FramelessWindowHint);
|
setWindowFlags(Qt::FramelessWindowHint);
|
||||||
setAttribute(Qt::WA_TranslucentBackground);
|
setAttribute(Qt::WA_TranslucentBackground);
|
||||||
setSizeGripEnabled(true);
|
QMetaObject::invokeMethod(this, [this]
|
||||||
resize(400, 300);
|
{
|
||||||
show();
|
show();
|
||||||
|
|
||||||
auto setBackgroundColor = [=](QColor color)
|
QFont font = ui.display->font();
|
||||||
{
|
if (font.fromString(settings.value(FONT, font.toString()).toString())) ui.display->setFont(font);
|
||||||
if (!color.isValid()) return;
|
setBackgroundColor(settings.value(BG_COLOR, palette().window().color()).value<QColor>());
|
||||||
if (color.alpha() == 0) color.setAlpha(1);
|
setTextColor(settings.value(TEXT_COLOR, ui.display->palette().windowText().color()).value<QColor>());
|
||||||
bgColor = color;
|
setLock(settings.value(SIZE_LOCK, false).toBool());
|
||||||
repaint();
|
setTopmost(settings.value(TOPMOST, false).toBool());
|
||||||
settings->setValue(BG_COLOR, color);
|
setGeometry(settings.value(WINDOW, geometry()).toRect());
|
||||||
};
|
|
||||||
auto setTextColor = [=](QColor color)
|
menu.addAction(FONT, this, &Window::RequestFont);
|
||||||
{
|
menu.addAction(BG_COLOR, [this] { setBackgroundColor(QColorDialog::getColor(bgColor, this, BG_COLOR, QColorDialog::ShowAlphaChannel)); });
|
||||||
if (!color.isValid()) return;
|
menu.addAction(TEXT_COLOR, [this] { setTextColor(QColorDialog::getColor(ui.display->palette().windowText().color(), this, TEXT_COLOR, QColorDialog::ShowAlphaChannel)); });
|
||||||
auto newPalette = display->palette();
|
for (auto [name, default, slot] : Array<std::tuple<const char*, bool, void(Window::*)(bool)>>{
|
||||||
newPalette.setColor(QPalette::WindowText, color);
|
{ TOPMOST, false, &Window::setTopmost },
|
||||||
display->setPalette(newPalette);
|
{ SIZE_LOCK, false, &Window::setLock },
|
||||||
settings->setValue(TEXT_COLOR, color);
|
{ SHOW_ORIGINAL, true, &Window::setShowOriginal }
|
||||||
};
|
})
|
||||||
auto requestFont = [=]
|
|
||||||
{
|
|
||||||
QFont font = display->font();
|
|
||||||
auto fontDialog = new QDialog(this, Qt::WindowCloseButtonHint);
|
|
||||||
fontDialog->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
fontDialog->setWindowTitle(FONT);
|
|
||||||
auto layout = new QFormLayout(fontDialog);
|
|
||||||
fontDialog->setLayout(layout);
|
|
||||||
auto fontFamily = new QLineEdit(font.family(), fontDialog);
|
|
||||||
layout->addRow(FONT_FAMILY, fontFamily);
|
|
||||||
auto fontSize = new QSpinBox(fontDialog);
|
|
||||||
fontSize->setValue(font.pointSize());
|
|
||||||
layout->addRow(FONT_SIZE, fontSize);
|
|
||||||
auto fontWeight = new QSpinBox(fontDialog);
|
|
||||||
fontWeight->setValue(font.weight());
|
|
||||||
layout->addRow(FONT_WEIGHT, fontWeight);
|
|
||||||
auto save = new QPushButton(SAVE_SETTINGS, fontDialog);
|
|
||||||
layout->addWidget(save);
|
|
||||||
connect(save, &QPushButton::clicked, fontDialog, &QDialog::accept);
|
|
||||||
fontDialog->open();
|
|
||||||
connect(fontDialog, &QDialog::accepted, [=]
|
|
||||||
{
|
{
|
||||||
QFont font(fontFamily->text(), fontSize->value(), fontWeight->value());
|
auto action = menu.addAction(name, this, slot);
|
||||||
settings->setValue(FONT, font.toString());
|
action->setCheckable(true);
|
||||||
display->setFont(font);
|
action->setChecked(settings.value(name, default).toBool());
|
||||||
});
|
}
|
||||||
};
|
connect(ui.display, &QLabel::customContextMenuRequested, [this](QPoint point) { menu.exec(mapToGlobal(point)); });
|
||||||
auto setTopmost = [=](bool topmost)
|
|
||||||
{
|
|
||||||
SetWindowPos((HWND)winId(), topmost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
|
||||||
settings->setValue(TOPMOST, topmost);
|
|
||||||
};
|
|
||||||
auto setLock = [=](bool lock)
|
|
||||||
{
|
|
||||||
locked = lock;
|
|
||||||
setSizeGripEnabled(!lock);
|
|
||||||
settings->setValue(SIZE_LOCK, lock);
|
|
||||||
};
|
|
||||||
auto setShowOriginal = [=](bool showOriginal)
|
|
||||||
{
|
|
||||||
if (!showOriginal) QMessageBox::information(this, SHOW_ORIGINAL, SHOW_ORIGINAL_INFO);
|
|
||||||
settings->setValue(SHOW_ORIGINAL, showOriginal);
|
|
||||||
};
|
|
||||||
setGeometry(settings->value(WINDOW, geometry()).toRect());
|
|
||||||
setLock(settings->value(SIZE_LOCK, false).toBool());
|
|
||||||
setTopmost(settings->value(TOPMOST, false).toBool());
|
|
||||||
QFont font = display->font();
|
|
||||||
font.setPointSize(16);
|
|
||||||
font.fromString(settings->value(FONT, font.toString()).toString());
|
|
||||||
display->setFont(font);
|
|
||||||
setBackgroundColor(settings->value(BG_COLOR, palette().window().color()).value<QColor>());
|
|
||||||
setTextColor(settings->value(TEXT_COLOR, display->palette().windowText().color()).value<QColor>());
|
|
||||||
|
|
||||||
auto menu = new QMenu(display);
|
QMetaObject::invokeMethod(this, [this] { ui.display->setText(EXTRA_WINDOW_INFO); }, Qt::QueuedConnection);
|
||||||
auto topmost = menu->addAction(TOPMOST, setTopmost);
|
}, Qt::QueuedConnection);
|
||||||
topmost->setCheckable(true);
|
|
||||||
topmost->setChecked(settings->value(TOPMOST, false).toBool());
|
|
||||||
auto lock = menu->addAction(SIZE_LOCK, setLock);
|
|
||||||
lock->setCheckable(true);
|
|
||||||
lock->setChecked(settings->value(SIZE_LOCK, false).toBool());
|
|
||||||
auto showOriginal = menu->addAction(SHOW_ORIGINAL, setShowOriginal);
|
|
||||||
showOriginal->setCheckable(true);
|
|
||||||
showOriginal->setChecked(settings->value(SHOW_ORIGINAL, true).toBool());
|
|
||||||
menu->addAction(BG_COLOR, [=] { setBackgroundColor(QColorDialog::getColor(bgColor, this, BG_COLOR, QColorDialog::ShowAlphaChannel)); });
|
|
||||||
menu->addAction(TEXT_COLOR, [=] { setTextColor(QColorDialog::getColor(display->palette().windowText().color(), this, TEXT_COLOR, QColorDialog::ShowAlphaChannel)); });
|
|
||||||
menu->addAction(FONT, requestFont);
|
|
||||||
display->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
||||||
connect(display, &QLabel::customContextMenuRequested, [=](QPoint point) { menu->exec(mapToGlobal(point)); });
|
|
||||||
connect(this, &QDialog::destroyed, [=] { settings->setValue(WINDOW, geometry()); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QSettings* settings = new QSettings(CONFIG_FILE, QSettings::IniFormat, this);
|
~Window()
|
||||||
QLabel* display;
|
{
|
||||||
|
settings.setValue(WINDOW, geometry());
|
||||||
|
settings.sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ui::ExtraWindow ui;
|
||||||
|
QSettings settings{ CONFIG_FILE, QSettings::IniFormat, this };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void RequestFont()
|
||||||
|
{
|
||||||
|
QFont font = ui.display->font();
|
||||||
|
QDialog fontDialog(this, Qt::WindowCloseButtonHint);
|
||||||
|
fontDialog.setWindowTitle(FONT);
|
||||||
|
QFormLayout layout(&fontDialog);
|
||||||
|
QLineEdit fontFamily(font.family(), &fontDialog);
|
||||||
|
layout.addRow(FONT_FAMILY, &fontFamily);
|
||||||
|
QSpinBox fontSize(&fontDialog);
|
||||||
|
fontSize.setValue(font.pointSize());
|
||||||
|
layout.addRow(FONT_SIZE, &fontSize);
|
||||||
|
QSpinBox fontWeight(&fontDialog);
|
||||||
|
fontWeight.setValue(font.weight());
|
||||||
|
layout.addRow(FONT_WEIGHT, &fontWeight);
|
||||||
|
QPushButton save(SAVE_SETTINGS, &fontDialog);
|
||||||
|
layout.addWidget(&save);
|
||||||
|
connect(&save, &QPushButton::clicked, &fontDialog, &QDialog::accept);
|
||||||
|
if (!fontDialog.exec()) return;
|
||||||
|
font = QFont(fontFamily.text(), fontSize.value(), fontWeight.value());
|
||||||
|
settings.setValue(FONT, font.toString());
|
||||||
|
ui.display->setFont(font);
|
||||||
|
};
|
||||||
|
|
||||||
|
void setBackgroundColor(QColor color)
|
||||||
|
{
|
||||||
|
if (!color.isValid()) return;
|
||||||
|
if (color.alpha() == 0) color.setAlpha(1);
|
||||||
|
bgColor = color;
|
||||||
|
repaint();
|
||||||
|
settings.setValue(BG_COLOR, color);
|
||||||
|
};
|
||||||
|
|
||||||
|
void setTextColor(QColor color)
|
||||||
|
{
|
||||||
|
if (!color.isValid()) return;
|
||||||
|
auto newPalette = ui.display->palette();
|
||||||
|
newPalette.setColor(QPalette::WindowText, color);
|
||||||
|
ui.display->setPalette(newPalette);
|
||||||
|
settings.setValue(TEXT_COLOR, color);
|
||||||
|
};
|
||||||
|
|
||||||
|
void setTopmost(bool topmost)
|
||||||
|
{
|
||||||
|
SetWindowPos((HWND)winId(), topmost ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||||
|
settings.setValue(TOPMOST, topmost);
|
||||||
|
};
|
||||||
|
|
||||||
|
void setLock(bool lock)
|
||||||
|
{
|
||||||
|
locked = lock;
|
||||||
|
setSizeGripEnabled(!lock);
|
||||||
|
settings.setValue(SIZE_LOCK, lock);
|
||||||
|
};
|
||||||
|
|
||||||
|
void setShowOriginal(bool showOriginal)
|
||||||
|
{
|
||||||
|
if (!showOriginal) QMessageBox::information(this, SHOW_ORIGINAL, SHOW_ORIGINAL_INFO);
|
||||||
|
settings.setValue(SHOW_ORIGINAL, showOriginal);
|
||||||
|
};
|
||||||
|
|
||||||
void paintEvent(QPaintEvent*) override
|
void paintEvent(QPaintEvent*) override
|
||||||
{
|
{
|
||||||
QPainter(this).fillRect(rect(), bgColor);
|
QPainter(this).fillRect(rect(), bgColor);
|
||||||
@ -157,51 +154,19 @@ private:
|
|||||||
oldPos = event->globalPos();
|
oldPos = event->globalPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool locked;
|
QMenu menu{ ui.display };
|
||||||
|
bool locked = true;
|
||||||
QColor bgColor;
|
QColor bgColor;
|
||||||
QPoint oldPos;
|
QPoint oldPos;
|
||||||
}*window = nullptr;
|
} window;
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
|
||||||
{
|
|
||||||
switch (ul_reason_for_call)
|
|
||||||
{
|
|
||||||
case DLL_PROCESS_ATTACH:
|
|
||||||
{
|
|
||||||
QTimer::singleShot(0, []
|
|
||||||
{
|
|
||||||
std::lock_guard l(m);
|
|
||||||
(window = new std::remove_pointer_t<decltype(window)>)->launch();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DLL_PROCESS_DETACH:
|
|
||||||
{
|
|
||||||
std::lock_guard l(m);
|
|
||||||
if (window)
|
|
||||||
{
|
|
||||||
window->settings->setValue(WINDOW, window->geometry());
|
|
||||||
window->settings->sync();
|
|
||||||
}
|
|
||||||
if (lpReserved == NULL) // https://blogs.msdn.microsoft.com/oldnewthing/20120105-00/?p=8683
|
|
||||||
{
|
|
||||||
delete window;
|
|
||||||
window = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
||||||
{
|
{
|
||||||
std::lock_guard l(m);
|
if (!sentenceInfo["current select"]) return false;
|
||||||
if (window == nullptr || !sentenceInfo["current select"]) return false;
|
|
||||||
|
|
||||||
QString qSentence = QString::fromStdWString(sentence);
|
QString qSentence = QString::fromStdWString(sentence);
|
||||||
if (!window->settings->value(SHOW_ORIGINAL).toBool()) qSentence = qSentence.section('\n', qSentence.count('\n') / 2 + 1);
|
if (!window.settings.value(SHOW_ORIGINAL).toBool()) qSentence = qSentence.section('\n', qSentence.count('\n') / 2 + 1);
|
||||||
|
|
||||||
QMetaObject::invokeMethod(window, [=] { window->display->setText(qSentence); });
|
QMetaObject::invokeMethod(&window, [=] { window.ui.display->setText(qSentence); });
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
48
extensions/extrawindow.ui
Normal file
48
extensions/extrawindow.ui
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>ExtraWindow</class>
|
||||||
|
<widget class="QDialog" name="ExtraWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizeGripEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="display">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Ignored" vsizetype="Ignored">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>16</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::CustomContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignTop</set>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@ -5,7 +5,6 @@
|
|||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
extern const char* LUA_INTRO;
|
extern const char* LUA_INTRO;
|
||||||
extern const char* LOAD_LUA_SCRIPT;
|
extern const char* LOAD_LUA_SCRIPT;
|
||||||
@ -45,61 +44,47 @@ bool logErrors = true;
|
|||||||
Synchronized<std::string> script;
|
Synchronized<std::string> script;
|
||||||
std::atomic<int> revCount = 0;
|
std::atomic<int> revCount = 0;
|
||||||
|
|
||||||
struct : QMainWindow
|
class Window : public QMainWindow
|
||||||
{
|
{
|
||||||
void launch()
|
public:
|
||||||
|
Window()
|
||||||
{
|
{
|
||||||
auto centralWidget = new QWidget(this);
|
connect(&loadButton, &QPushButton::clicked, this, &Window::LoadScript);
|
||||||
auto layout = new QHBoxLayout(centralWidget);
|
|
||||||
auto scriptEditor = new QPlainTextEdit(std::string(std::istreambuf_iterator<char>(std::ifstream(LUA_SAVE_FILE, std::ios::in)), {}).c_str(), centralWidget);
|
if (scriptEditor.toPlainText().isEmpty()) scriptEditor.setPlainText(LUA_INTRO);
|
||||||
auto loadButton = new QPushButton(LOAD_LUA_SCRIPT, centralWidget);
|
layout.addWidget(&scriptEditor);
|
||||||
if (scriptEditor->toPlainText().isEmpty()) scriptEditor->setPlainText(LUA_INTRO);
|
layout.addWidget(&loadButton);
|
||||||
layout->addWidget(scriptEditor);
|
|
||||||
layout->addWidget(loadButton);
|
|
||||||
save = [=]
|
|
||||||
{
|
|
||||||
auto script = scriptEditor->toPlainText().toUtf8();
|
|
||||||
std::ofstream(LUA_SAVE_FILE, std::ios::out | std::ios::trunc).write(script, strlen(script));
|
|
||||||
};
|
|
||||||
connect(loadButton, &QPushButton::clicked, [=](bool)
|
|
||||||
{
|
|
||||||
revCount += 1;
|
|
||||||
script->assign(scriptEditor->toPlainText().toUtf8());
|
|
||||||
save();
|
|
||||||
});
|
|
||||||
resize(800, 600);
|
resize(800, 600);
|
||||||
setCentralWidget(centralWidget);
|
setCentralWidget(¢ralWidget);
|
||||||
setWindowTitle("Lua");
|
setWindowTitle("Lua");
|
||||||
show();
|
QMetaObject::invokeMethod(this, &QWidget::show, Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::function<void()> save;
|
~Window()
|
||||||
}*window = nullptr;
|
{
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
private:
|
||||||
{
|
void LoadScript()
|
||||||
switch (ul_reason_for_call)
|
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
revCount += 1;
|
||||||
|
script->assign(scriptEditor.toPlainText().toUtf8());
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Save()
|
||||||
{
|
{
|
||||||
QTimer::singleShot(0, []
|
auto script = scriptEditor.toPlainText().toUtf8();
|
||||||
{
|
std::ofstream(LUA_SAVE_FILE, std::ios::out | std::ios::trunc).write(script, script.size());
|
||||||
(window = new std::remove_pointer_t<decltype(window)>)->launch();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case DLL_PROCESS_DETACH:
|
QWidget centralWidget{ this };
|
||||||
{
|
QHBoxLayout layout{ ¢ralWidget };
|
||||||
if (window) window->save();
|
QPlainTextEdit scriptEditor{ std::string(std::istreambuf_iterator<char>(std::ifstream(LUA_SAVE_FILE, std::ios::in)), {}).c_str(), ¢ralWidget };
|
||||||
if (lpReserved == NULL) // https://blogs.msdn.microsoft.com/oldnewthing/20120105-00/?p=8683
|
QPushButton loadButton{ LOAD_LUA_SCRIPT, ¢ralWidget };
|
||||||
{
|
} window;
|
||||||
delete window;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "extension.h"
|
#include "extension.h"
|
||||||
#include "ui_regexfilter.h"
|
#include "ui_regexfilter.h"
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
extern const char* REGEX_FILTER;
|
extern const char* REGEX_FILTER;
|
||||||
extern const char* INVALID_REGEX;
|
extern const char* INVALID_REGEX;
|
||||||
@ -9,56 +8,35 @@ extern const char* CURRENT_FILTER;
|
|||||||
std::wregex regex;
|
std::wregex regex;
|
||||||
std::shared_mutex m;
|
std::shared_mutex m;
|
||||||
|
|
||||||
struct : QMainWindow
|
class Window : public QMainWindow
|
||||||
{
|
{
|
||||||
void launch()
|
public:
|
||||||
|
Window()
|
||||||
{
|
{
|
||||||
ui.setupUi(this);
|
ui.setupUi(this);
|
||||||
connect(ui.input, &QLineEdit::textEdited, [=](QString newRegex)
|
|
||||||
{
|
connect(ui.input, &QLineEdit::textEdited, this, &Window::setRegex);
|
||||||
std::lock_guard l(m);
|
|
||||||
try { regex = newRegex.toStdWString(); }
|
|
||||||
catch (std::regex_error) { return ui.output->setText(INVALID_REGEX); }
|
|
||||||
ui.output->setText(QString(CURRENT_FILTER).arg(newRegex));
|
|
||||||
});
|
|
||||||
setWindowTitle(REGEX_FILTER);
|
setWindowTitle(REGEX_FILTER);
|
||||||
show();
|
QMetaObject::invokeMethod(this, &QWidget::show, Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setRegex(QString newRegex)
|
||||||
|
{
|
||||||
|
std::lock_guard l(m);
|
||||||
|
try { regex = newRegex.toStdWString(); }
|
||||||
|
catch (std::regex_error) { return ui.output->setText(INVALID_REGEX); }
|
||||||
|
ui.output->setText(QString(CURRENT_FILTER).arg(newRegex));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ui::FilterWindow ui;
|
Ui::FilterWindow ui;
|
||||||
}*window = nullptr;
|
} window;
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
|
||||||
{
|
|
||||||
switch (ul_reason_for_call)
|
|
||||||
{
|
|
||||||
case DLL_PROCESS_ATTACH:
|
|
||||||
{
|
|
||||||
QTimer::singleShot(0, []
|
|
||||||
{
|
|
||||||
std::lock_guard l(m);
|
|
||||||
(window = new std::remove_pointer_t<decltype(window)>)->launch();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DLL_PROCESS_DETACH:
|
|
||||||
{
|
|
||||||
if (lpReserved == NULL) // https://blogs.msdn.microsoft.com/oldnewthing/20120105-00/?p=8683
|
|
||||||
{
|
|
||||||
std::lock_guard l(m);
|
|
||||||
delete window;
|
|
||||||
window = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
||||||
{
|
{
|
||||||
std::shared_lock l(m);
|
|
||||||
if (sentenceInfo["text number"] == 0) return false;
|
if (sentenceInfo["text number"] == 0) return false;
|
||||||
|
std::shared_lock l(m);
|
||||||
sentence = std::regex_replace(sentence, regex, L"");
|
sentence = std::regex_replace(sentence, regex, L"");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -93,12 +93,12 @@ bool Replace(std::wstring& sentence)
|
|||||||
|
|
||||||
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||||
{
|
{
|
||||||
static HANDLE replacementFile; // not actually used to read/write, just to ensure it exists
|
// not actually used to read/write, just to ensure it exists
|
||||||
|
static AutoHandle<> replacementFile = CreateFileA(REPLACE_SAVE_FILE, FILE_GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||||
switch (ul_reason_for_call)
|
switch (ul_reason_for_call)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
{
|
{
|
||||||
replacementFile = CreateFileA(REPLACE_SAVE_FILE, FILE_GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
||||||
std::vector<BYTE> file(std::istreambuf_iterator<char>(std::ifstream(REPLACE_SAVE_FILE, std::ios::in | std::ios::binary)), {});
|
std::vector<BYTE> file(std::istreambuf_iterator<char>(std::ifstream(REPLACE_SAVE_FILE, std::ios::in | std::ios::binary)), {});
|
||||||
if (Parse(std::wstring((wchar_t*)file.data(), file.size() / sizeof(wchar_t))) == 0)
|
if (Parse(std::wstring((wchar_t*)file.data(), file.size() / sizeof(wchar_t))) == 0)
|
||||||
{
|
{
|
||||||
@ -110,7 +110,6 @@ BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved
|
|||||||
break;
|
break;
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
{
|
{
|
||||||
CloseHandle(replacementFile);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
extern const char* THREAD_LINKER;
|
extern const char* THREAD_LINKER;
|
||||||
extern const char* LINK;
|
extern const char* LINK;
|
||||||
@ -13,86 +12,58 @@ extern const char* THREAD_LINK_FROM;
|
|||||||
extern const char* THREAD_LINK_TO;
|
extern const char* THREAD_LINK_TO;
|
||||||
extern const char* HEXADECIMAL;
|
extern const char* HEXADECIMAL;
|
||||||
|
|
||||||
std::mutex m;
|
|
||||||
std::unordered_map<int64_t, std::unordered_multiset<int64_t>> linkedTextHandles;
|
std::unordered_map<int64_t, std::unordered_multiset<int64_t>> linkedTextHandles;
|
||||||
|
std::shared_mutex m;
|
||||||
|
|
||||||
struct : QMainWindow
|
class Window : public QMainWindow
|
||||||
{
|
{
|
||||||
void launch()
|
public:
|
||||||
|
Window()
|
||||||
{
|
{
|
||||||
auto centralWidget = new QWidget(this);
|
connect(&linkButton, &QPushButton::clicked, this, &Window::Link);
|
||||||
auto layout = new QHBoxLayout(centralWidget);
|
|
||||||
auto linkList = new QListWidget(centralWidget);
|
|
||||||
auto addLink = new QPushButton(LINK, centralWidget);
|
|
||||||
layout->addWidget(linkList);
|
|
||||||
layout->addWidget(addLink);
|
|
||||||
|
|
||||||
connect(addLink, &QPushButton::clicked, [=]
|
layout.addWidget(&linkList);
|
||||||
{
|
layout.addWidget(&linkButton);
|
||||||
bool ok1, ok2, ok3, ok4;
|
|
||||||
int from = QInputDialog::getText(this, THREAD_LINK_FROM, HEXADECIMAL, QLineEdit::Normal, "", &ok1, Qt::WindowCloseButtonHint).toInt(&ok2, 16);
|
|
||||||
int to = QInputDialog::getText(this, THREAD_LINK_TO, HEXADECIMAL, QLineEdit::Normal, "", &ok3, Qt::WindowCloseButtonHint).toInt(&ok4, 16);
|
|
||||||
if (ok1 && ok2 && ok3 && ok4)
|
|
||||||
{
|
|
||||||
std::lock_guard l(m);
|
|
||||||
linkedTextHandles[from].insert(to);
|
|
||||||
linkList->addItem(QString::number(from, 16) + "->" + QString::number(to, 16));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Unlink = [=]
|
|
||||||
{
|
|
||||||
if (linkList->currentItem())
|
|
||||||
{
|
|
||||||
QStringList link = linkList->currentItem()->text().split("->");
|
|
||||||
linkList->takeItem(linkList->currentRow());
|
|
||||||
std::lock_guard l(m);
|
|
||||||
linkedTextHandles[link[0].toInt(nullptr, 16)].erase(link[1].toInt(nullptr, 16));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
setCentralWidget(centralWidget);
|
setCentralWidget(¢ralWidget);
|
||||||
setWindowTitle(THREAD_LINKER);
|
setWindowTitle(THREAD_LINKER);
|
||||||
show();
|
QMetaObject::invokeMethod(this, &QWidget::show, Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Link()
|
||||||
|
{
|
||||||
|
bool ok1, ok2, ok3, ok4;
|
||||||
|
int from = QInputDialog::getText(this, THREAD_LINK_FROM, HEXADECIMAL, QLineEdit::Normal, "", &ok1, Qt::WindowCloseButtonHint).toInt(&ok2, 16);
|
||||||
|
int to = QInputDialog::getText(this, THREAD_LINK_TO, HEXADECIMAL, QLineEdit::Normal, "", &ok3, Qt::WindowCloseButtonHint).toInt(&ok4, 16);
|
||||||
|
if (ok1 && ok2 && ok3 && ok4)
|
||||||
|
{
|
||||||
|
std::lock_guard l(m);
|
||||||
|
linkedTextHandles[from].insert(to);
|
||||||
|
linkList.addItem(QString::number(from, 16) + "->" + QString::number(to, 16));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void keyPressEvent(QKeyEvent* event) override
|
void keyPressEvent(QKeyEvent* event) override
|
||||||
{
|
{
|
||||||
if (event->key() == Qt::Key_Delete) Unlink();
|
if (event->key() == Qt::Key_Delete && linkList.currentItem())
|
||||||
}
|
|
||||||
|
|
||||||
std::function<void()> Unlink;
|
|
||||||
}*window = nullptr;
|
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
|
||||||
{
|
|
||||||
switch (ul_reason_for_call)
|
|
||||||
{
|
|
||||||
case DLL_PROCESS_ATTACH:
|
|
||||||
{
|
|
||||||
QTimer::singleShot(0, []
|
|
||||||
{
|
{
|
||||||
|
QStringList link = linkList.currentItem()->text().split("->");
|
||||||
|
linkList.takeItem(linkList.currentRow());
|
||||||
std::lock_guard l(m);
|
std::lock_guard l(m);
|
||||||
(window = new std::remove_pointer_t<decltype(window)>)->launch();
|
linkedTextHandles[link[0].toInt(nullptr, 16)].erase(link[1].toInt(nullptr, 16));
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DLL_PROCESS_DETACH:
|
|
||||||
{
|
|
||||||
if (lpReserved == NULL) // https://blogs.msdn.microsoft.com/oldnewthing/20120105-00/?p=8683
|
|
||||||
{
|
|
||||||
std::lock_guard l(m);
|
|
||||||
delete window;
|
|
||||||
window = nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
QWidget centralWidget{ this };
|
||||||
return TRUE;
|
QHBoxLayout layout{ ¢ralWidget };
|
||||||
}
|
QListWidget linkList{ ¢ralWidget };
|
||||||
|
QPushButton linkButton{ LINK, ¢ralWidget };
|
||||||
|
} window;
|
||||||
|
|
||||||
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
bool ProcessSentence(std::wstring& sentence, SentenceInfo sentenceInfo)
|
||||||
{
|
{
|
||||||
std::lock_guard l(m);
|
std::shared_lock l(m);
|
||||||
int64_t textHandle = sentenceInfo["text number"];
|
int64_t textHandle = sentenceInfo["text number"];
|
||||||
|
|
||||||
for (auto linkedHandle : linkedTextHandles[textHandle])
|
for (auto linkedHandle : linkedTextHandles[textHandle])
|
||||||
|
Loading…
Reference in New Issue
Block a user