Textractor/GUI/extenwindow.cpp

148 lines
4.5 KiB
C++
Raw Normal View History

#include "extenwindow.h"
#include "ui_extenwindow.h"
#include "defs.h"
2019-02-16 00:25:19 -05:00
#include <concrt.h>
#include <QDragEnterEvent>
#include <QDropEvent>
2018-11-01 18:47:19 -04:00
#include <QMimeData>
#include <QUrl>
#include <QLabel>
2019-06-04 23:14:46 -04:00
#include <QMessageBox>
2019-02-27 11:33:17 -05:00
extern const char* EXTENSIONS;
2019-06-04 23:14:46 -04:00
extern const char* INVALID_EXTENSION;
extern const char* CONFIRM_EXTENSION_OVERWRITE;
extern const char* EXTENSION_WRITE_ERROR;
2019-02-27 11:33:17 -05:00
extern const char* EXTEN_WINDOW_INSTRUCTIONS;
namespace
{
2019-02-09 00:30:38 -05:00
struct Extension
{
2019-02-09 00:30:38 -05:00
std::wstring name;
wchar_t*(*callback)(wchar_t*, const InfoForExtension*);
};
2019-02-16 00:25:19 -05:00
concurrency::reader_writer_lock extenMutex;
2019-02-09 00:30:38 -05:00
std::vector<Extension> extensions;
2019-06-04 23:14:46 -04:00
bool Load(QString extenName)
{
// Extension is dll and exports "OnNewSentence"
2019-06-04 23:14:46 -04:00
if (QTextFile(extenName + ".dll", QIODevice::ReadOnly).readAll().contains("OnNewSentence"))
{
2019-06-04 23:14:46 -04:00
if (auto callback = (decltype(Extension::callback))GetProcAddress(LoadLibraryOnce(S(extenName)), "OnNewSentence"))
{
std::scoped_lock writeLock(extenMutex);
extensions.push_back({ S(extenName), callback });
return true;
}
}
2019-06-04 23:14:46 -04:00
return false;
}
2019-02-09 00:30:38 -05:00
void Unload(int index)
{
2019-01-09 22:35:01 -05:00
std::scoped_lock writeLock(extenMutex);
2019-02-09 00:30:38 -05:00
FreeLibrary(GetModuleHandleW(extensions.at(index).name.c_str()));
extensions.erase(extensions.begin() + index);
}
2018-11-01 14:46:37 -04:00
void Reorder(QStringList extenNames)
{
2019-01-09 22:35:01 -05:00
std::scoped_lock writeLock(extenMutex);
2019-02-09 00:30:38 -05:00
std::vector<Extension> extensions;
for (auto extenName : extenNames)
2019-02-09 00:30:38 -05:00
extensions.push_back(*std::find_if(::extensions.begin(), ::extensions.end(), [&](auto extension) { return extension.name == S(extenName); }));
::extensions = extensions;
2018-11-01 14:46:37 -04:00
}
}
2019-02-09 00:30:38 -05:00
bool DispatchSentenceToExtensions(std::wstring& sentence, const InfoForExtension* miscInfo)
{
2019-02-18 20:57:10 -05:00
wchar_t* sentenceBuffer = (wchar_t*)HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, (sentence.size() + 1) * sizeof(wchar_t));
wcscpy_s(sentenceBuffer, sentence.size() + 1, sentence.c_str());
2019-02-16 00:25:19 -05:00
concurrency::reader_writer_lock::scoped_lock_read readLock(extenMutex);
2019-02-09 00:30:38 -05:00
for (const auto& extension : extensions)
2019-02-18 20:57:10 -05:00
if (*(sentenceBuffer = extension.callback(sentenceBuffer, miscInfo)) == L'\0') break;
sentence = sentenceBuffer;
HeapFree(GetProcessHeap(), 0, sentenceBuffer);
2019-02-18 20:57:10 -05:00
return !sentence.empty();
}
ExtenWindow::ExtenWindow(QWidget* parent) :
QMainWindow(parent, Qt::WindowCloseButtonHint),
ui(new Ui::ExtenWindow)
{
ui->setupUi(this);
ui->vboxLayout->addWidget(new QLabel(EXTEN_WINDOW_INSTRUCTIONS, this));
setWindowTitle(EXTENSIONS);
ui->extenList->installEventFilter(this);
if (!QFile::exists(EXTEN_SAVE_FILE)) QTextFile(EXTEN_SAVE_FILE, QIODevice::WriteOnly).write(DEFAULT_EXTENSIONS);
for (auto extenName : QString(QTextFile(EXTEN_SAVE_FILE, QIODevice::ReadOnly).readAll()).split(">")) Load(extenName);
Sync();
}
ExtenWindow::~ExtenWindow()
{
delete ui;
}
2018-11-01 18:47:19 -04:00
void ExtenWindow::Sync()
{
ui->extenList->clear();
QTextFile extenSaveFile(EXTEN_SAVE_FILE, QIODevice::WriteOnly | QIODevice::Truncate);
2019-02-16 00:25:19 -05:00
concurrency::reader_writer_lock::scoped_lock_read readLock(extenMutex);
2019-02-09 00:30:38 -05:00
for (auto extension : extensions)
2018-11-01 18:47:19 -04:00
{
2019-02-09 00:30:38 -05:00
ui->extenList->addItem(S(extension.name));
extenSaveFile.write((S(extension.name) + ">").toUtf8());
2018-11-01 18:47:19 -04:00
}
}
2018-12-28 12:14:56 -05:00
bool ExtenWindow::eventFilter(QObject* target, QEvent* event)
{
// See https://stackoverflow.com/questions/1224432/how-do-i-respond-to-an-internal-drag-and-drop-operation-using-a-qlistwidget/1528215
if (event->type() == QEvent::ChildRemoved)
{
2018-11-01 14:46:37 -04:00
QStringList extenNames;
for (int i = 0; i < ui->extenList->count(); ++i) extenNames.push_back(ui->extenList->item(i)->text());
2018-11-01 14:46:37 -04:00
Reorder(extenNames);
Sync();
}
2018-12-28 12:14:56 -05:00
return false;
}
void ExtenWindow::keyPressEvent(QKeyEvent* event)
{
2019-02-09 00:30:38 -05:00
if (event->key() == Qt::Key_Delete && ui->extenList->currentItem() != nullptr)
{
2019-02-09 00:30:38 -05:00
Unload(ui->extenList->currentIndex().row());
Sync();
}
}
2018-11-01 18:47:19 -04:00
void ExtenWindow::dragEnterEvent(QDragEnterEvent* event)
{
2018-11-01 18:47:19 -04:00
event->acceptProposedAction();
}
2018-12-28 12:14:56 -05:00
void ExtenWindow::dropEvent(QDropEvent* event)
{
2019-06-04 23:14:46 -04:00
for (auto file : event->mimeData()->urls())
{
QFileInfo extenFile = file.toLocalFile();
if (extenFile.suffix() != "dll") continue;
if (QFile::exists(extenFile.fileName()) && extenFile.absolutePath() != QDir::currentPath())
{
if (QMessageBox::question(this, EXTENSIONS, CONFIRM_EXTENSION_OVERWRITE) == QMessageBox::Yes) QFile::remove(extenFile.fileName());
if (!QFile::copy(extenFile.absoluteFilePath(), extenFile.fileName())) QMessageBox::warning(this, EXTENSIONS, EXTENSION_WRITE_ERROR);
}
if (Load(extenFile.completeBaseName())) Sync();
else QMessageBox::information(this, EXTENSIONS, QString(INVALID_EXTENSION).arg(extenFile.fileName()));
}
2018-11-01 18:47:19 -04:00
}