Преглед на файлове

Implemented some functions in Lotro class

Ivan Arkhipov преди 5 години
родител
ревизия
07dbff2085
променени са 2 файла, в които са добавени 298 реда и са изтрити 94 реда
  1. 288 86
      src/Legacy-advanced/models/lotro.cpp
  2. 10 8
      src/Legacy-advanced/models/lotro.h

+ 288 - 86
src/Legacy-advanced/models/lotro.cpp

@@ -5,6 +5,10 @@
 #include <QFontDatabase>
 #include <QMessageBox>
 
+#include <string>
+#include <iostream>
+#include <fstream>
+
 Lotro::Lotro(QSettings& app_settings_, QObject *parent) : app_settings(app_settings_),
     QObject(parent) {
 }
@@ -12,12 +16,13 @@ Lotro::Lotro(QSettings& app_settings_, QObject *parent) : app_settings(app_setti
 void Lotro::initialiseDatFile(QString file_name) {
     if (!tryToBlockFile())
         return;
+    emit processStarted("initialiseDatFile", {file_name});
 
     qDebug() << "Initialising file " << file_name;
-    emit processStarted("initialiseDatFile", {file_name});
 
     if (!FileSystem::fileExists(file_path)) {
         emit caughtError("initialiseDatFile", {QString("Ошибка инициализации"), QString("Файл " + file_path + " несуществует! Невозможно инициализировать файл ресурсов.")});
+        busy = false;
         return;
     }
 
@@ -29,7 +34,9 @@ void Lotro::initialiseDatFile(QString file_name) {
 void Lotro::changeLocale() {
     if (!tryToBlockFile())
         return;
+
     qDebug() << "Changing locale of dat file...";
+    emit processStarted("changeLocale", {current_locale, new_locale});
 
     // Setting locale, opposite to current
     auto current_locale = file.GetLocaleManager().GetCurrentLocale();
@@ -40,109 +47,378 @@ void Lotro::changeLocale() {
     QString old_locale_name = (current_locale == LOTRO_DAT::DatLocaleManager::PATCHED ? "Русифицированная" : "Оригинальная");
     QString new_locale_name = (new_locale == LOTRO_DAT::DatLocaleManager::PATCHED ? "Русифицированная" : "Оригинальная");
 
-    emit processStarted("changeLocale", {current_locale, new_locale});
 
     auto operation = file.GetLocaleManager().SetLocale(new_locale);
 
     auto new_current_locale = file.GetLocaleManager().GetCurrentLocale();
     QString new_current_locale_name = (new_current_locale == LOTRO_DAT::DatLocaleManager::PATCHED ? "Русифицированная" : "Оригинальная");
 
+    busy = false;
     if (operation.result == LOTRO_DAT::SUCCESS) {
         emit processFinished("changeLocale", {"Success", new_current_locale_name});
     } else {
         emit caughtError("changeLocale", {"Ошибка смены локали!", QString("Не удалось сменить локаль игры! Текущая локаль: ") + new_current_locale_name});
         emit processFinished("changeLocale", {"Error", new_current_locale_name});
     }
-    busy = false;
 }
 
 void Lotro::getLocaleFileContents(long long file_id, int locale) {
     if (!tryToBlockFile())
         return;
+
     emit processStarted("getFileContents", {file_id, locale});
 
     auto getfile_op = file.GetLocaleManager().GetLocaleFile(file_id, locale);
     if (!getfile_op.result) {
         emit caughtError("getOriginalFileContents", {"Файл не найден!", QString("Не удаётся найти файл с id ") + QString::number(file_id)});
         emit processFinished("getOriginalFileContents", {"Error"});
-        return false;
+        busy = false;
+        return;
     }
 
     LOTRO_DAT::SubFile subfile = getfile_op.value;
 
     auto getfiledata_op = file.GetFileSystem().GetFileData(subfile, 8);
 
-    if (!getfile_op.result) {
+    if (getfile_op.result == LOTRO_DAT::ERROR) {
         emit caughtError("getOriginalFileContents", {"Ошибка извлечения!", QString("Обнаружены некорректные данные файла в словаре! Файл ресурсов мог быть повреждён!\nid = ") + QString::number(file_id) + ", locale_id = " + QString::number(locale)});
         emit processFinished("getOriginalFileContents", {"Error"});
-        return false;
+        busy = false;
+        return;
     }
 
     LOTRO_DAT::SubfileData result = subfile.PrepareForExport(getfiledata_op.value);
-    emit LocaleFileContentsReceived(locale, result);
 
-    emit processFinished("getFileContents", {"Success", file_id, locale});
     busy = false;
+    emit localeFileContentsReceived(locale, result);
+    emit processFinished("getFileContents", {"Success", file_id, locale});
 }
 
 void Lotro::importFilesFromDatabase(QString database_path) {
     if (!tryToBlockFile())
         return;
 
+    emit processStarted("importFilesFromDatabase", {database_path});
+
     if (!FileSystem::fileExists(database_path)) {
-        emit caughtError("importFilesFromDatabase", {QString("Ошибка импорта!"), QString("Файл " + file_path + " несуществует! Невозможно инициализировать базу данных!")});
+        emit caughtError("importFilesFromDatabase", {QString("Ошибка импорта!"), QString("Файл " + file_path + " не существует! Невозможно инициализировать базу данных!")});
+        emit processFinished("importFilesFromDatabase", {QString("Error")});
+        busy = false;
         return;
     }
-    emit processStarted("importFilesFromDatabase", {database_path});
 
     LOTRO_DAT::Database db;
     if (!db.InitDatabase(database_path.toStdString())) {
         emit caughtError("importFilesFromDatabase", {QString("Ошибка импорта!"), QString("Внутренняя ошибка инициализации базы данных!")});
         emit processFinished("importFilesFromDatabase", {QString("Error")});
+        busy = false;
         return;
     }
 
     auto patch_operation = file.GetPatcher().PatchAllDatabase(&db);
 
-    if (patch_operation.result) {
+    busy = false;
+    if (patch_operation.result == LOTRO_DAT::SUCCESS) {
         emit processFinished("importFilesFromDatabase", {QString("Success"), patch_operation.value});
     } else {
         emit processFinished("importFilesFromDatabase", {QString("Error"), 0});
     }
-    busy = false;
 }
 
 void Lotro::importFile(long long file_id, QString file_path) {
+    if (!tryToBlockFile())
+        return;
+
+    emit processStarted("importFile", {file_id, file_path});
+
+    if (!FileSystem::fileExists(file_path)) {
+        emit caughtError("importFile", {QString("Ошибка импорта!"), QString("Файл ") + file_path + QString(" не существует!")});
+        emit processFinished("importFile", {QString("Error")});
+        busy = false;
+        return;
+    }
+
+    LOTRO_DAT::SubfileData data;
+
+    data.options["fid"] = file_id;
 
+    auto getfile_op = file.GetFileSystem().GetFile(file_id);
+    if (getfile_op.value == LOTRO_DAT::ERROR) {
+        emit caughtError("importFile", {QString("Ошибка импорта!"), QString("Файл с id ") + QString::number(file_id) + QString(" не существует в ресурсах игры! Невозможно импортировать :/")});
+        emit processFinished("importFile", {QString("Error")});
+        busy = false;
+        return;
+    }
+
+    LOTRO_DAT::SubFile subfile = *(getfile_op.value);
+    data.options["ext"] = subfile.Extension();
+    data.options["cat"] = subfile.category;
+
+    if (subfile.FileType() == LOTRO_DAT::TEXT) {
+        std::basic_ifstream<char16_t> input_stream(file_path.toStdString(), std::ios::in);
+        if (!input_stream.is_open()) {
+            emit caughtError("importFile", {QString("Ошибка импорта!"), QString("Текстовый файл ") + file_path + QString(" не удаётся открыть!")});
+            emit processFinished("importFile", {QString("Error")});
+            busy = false;
+            return;
+        }
+
+        std::basic_stringstream<char16_t>  strStream;
+        strStream << input_stream.rdbuf();//read the file
+        data.text_data = strStream.str();//str holds the content of the file
+
+        input_stream.close();
+    } else {
+        QFile data_file(file_path);
+        data_file.open(QIODevice::ReadOnly);
+
+        if (!data_file.isOpen()) {
+            emit caughtError("importFile", {QString("Ошибка импорта!"), QString("Файл ") + file_path + QString(" не удаётся открыть!")});
+            emit processFinished("importFile", {QString("Error")});
+            busy = false;
+            return;
+        }
+
+        QByteArray contents = data_file.readAll();
+        data.binary_data = LOTRO_DAT::BinaryData(contents.constData(), contents.size());
+    }
+
+
+    auto patchfile_op = file.GetPatcher().PatchFile(data);
+
+    busy = false;
+    if (patchfile_op.result == LOTRO_DAT::SUCCESS) {
+        emit processFinished("importFile", {QString("Success")});
+    } else {
+        emit caughtError("importFile", {QString("Ошибка импорта!"), QString("Возникла внутренняя ошибка применения патча. Импорт завершился с ошибкой")});
+        emit processFinished("importFile", {QString("Error")});
+    }
+    return;
 }
 
 void Lotro::importTextFragment(long long file_id, long long fragment_id,
                                QString fragment_contents, QString arguments) {
+    if (!tryToBlockFile())
+        return;
+
+    emit processStarted("importTextFragment", {file_id, fragment_id});
+
+    if (fragment_contents.contains("DO_NOT_TOUCH")) {
+        emit caughtError("importTextFragment", {"Ошибка формата!", QString("Текстовые данные содержат указатели на аргументы DO_NOT_TOUCH! Такого быть не должно! Пользуйтесь порядком перечисления аргументов внизу")});
+        emit processFinished("importTextFragment", {"Error"});
+        busy = false;
+        return false;
+    }
+
+    auto getfile_op = file.GetFileSystem().GetFile(file_id);
+    if (!getfile_op.result) {
+        emit caughtError("importTextFragment", {"Файл не найден!", QString("Не удаётся найти в ресурсах файл с id ") + QString::number(file_id)});
+        emit processFinished("importTextFragment", {"Error"});
+        busy = false;
+        return false;
+    }
+
+    LOTRO_DAT::SubFile subfile = getfile_op.value;
+
+    auto getfiledata_op = file.GetFileSystem().GetFileData(subfile, 8);
 
+    if (getfile_op.result == LOTRO_DAT::ERROR) {
+        emit caughtError("importTextFragment", {"Ошибка импорта!", QString("Обнаружены некорректные данные файла в словаре! Файл ресурсов мог быть повреждён!\nid = ") + QString::number(file_id)});
+        emit processFinished("importTextFragment", {"Error"});
+        busy = false;
+        return false;
+    }
+
+    LOTRO_DAT::SubfileData data = subfile.PrepareForExport(getfiledata_op.value);
+    if (!result) {
+        emit caughtError("importTextFragment", {"Ошибка импорта!", QString("Не удалось подготовить файл к изменению фрагмента!\nid = ") + QString::number(file_id)});
+        emit processFinished("importTextFragment", {"Error"});
+        busy = false;
+        return false;
+    }
+
+    int beginning = data.text_data.find(QString::number(fragment_id).toStdU16String(), 0);
+    if (beginning == std::u16string::npos) {
+        emit caughtError("importTextFragment", {"Ошибка импорта!", QString("Не удалось найти фрагмент в файле!\nid = ") + QString::number(file_id) + "\nfragment_id = " + QString::number(fragment_id)});
+        emit processFinished("importTextFragment", {"Error"});
+        busy = false;
+        return false;
+    }
+
+    int ending = data.text_data.find(QString("|||").toStdU16String(), beginning);
+
+    QString new_fragment = QString::number(fragment_id) + ":::" + arguments + ":::" + fragment_contents;
+    std::u16string new_text =  data.text_data.substr(0, beginning) + new_fragment.toStdU16String() + result.text_data.substr(ending);
+    data.text_data = new_text;
+
+    auto patchfile_op = file.GetPatcher().PatchFile(data);
+
+    busy = false;
+    if (patchfile_op.result == LOTRO_DAT::SUCCESS) {
+        emit processFinished("importTextFragment", {QString("Success")});
+    } else {
+        emit caughtError("importTextFragment", {QString("Ошибка импорта!"), QString("Возникла внутренняя ошибка применения патча. Импорт завершился с ошибкой")});
+        emit processFinished("importTextFragment", {QString("Error")});
+    }
 }
 
 void Lotro::getTextFragment(long long file_id, long long fragment_id) {
+    if (!tryToBlockFile())
+        return;
+
+    emit processStarted("getTextFragment", {file_id, fragment_id});
 
+    auto getfile_op = file.GetFileSystem().GetFile(file_id);
+    if (!getfile_op.result) {
+        emit caughtError("getTextFragment", {"Файл не найден!", QString("Не удаётся найти в ресурсах файл с id ") + QString::number(file_id)});
+        emit processFinished("getTextFragment", {"Error"});
+        busy = false;
+        return false;
+    }
+
+    LOTRO_DAT::SubFile subfile = getfile_op.value;
+
+    auto getfiledata_op = file.GetFileSystem().GetFileData(subfile, 8);
+
+    if (getfile_op.result == LOTRO_DAT::ERROR) {
+        emit caughtError("getTextFragment", {"Ошибка импорта!", QString("Обнаружены некорректные данные файла в словаре! Файл ресурсов мог быть повреждён!\nid = ") + QString::number(file_id)});
+        emit processFinished("getTextFragment", {"Error"});
+        busy = false;
+        return false;
+    }
+
+    LOTRO_DAT::SubfileData data = subfile.PrepareForExport(getfiledata_op.value);
+    if (!result) {
+        emit caughtError("getTextFragment", {"Ошибка импорта!", QString("Не удалось подготовить файл к изменению фрагмента!\nid = ") + QString::number(file_id)});
+        emit processFinished("getTextFragment", {"Error"});
+        busy = false;
+        return false;
+    }
+
+    int beginning = data.text_data.find(QString::number(fragment_id).toStdU16String(), 0);
+    if (beginning == std::u16string::npos) {
+        emit caughtError("importTextFragment", {"Ошибка импорта!", QString("Не удалось найти фрагмент в файле!\nid = ") + QString::number(file_id) + "\nfragment_id = " + QString::number(fragment_id)});
+        emit processFinished("importTextFragment", {"Error"});
+        busy = false;
+        return false;
+    }
+
+    int ending = data.text_data.find(QString("|||").toStdU16String(), beginning);
+
+    int size = std::u16string::npos;
+
+    if (ending != std::u16string::npos)
+        size = ending - beginning;
+
+    std::u16string str = data.text_data.substr(beginning, size);
+
+    QStringList splitted_fragment = QString::fromStdU16String(str).split(":::");
+    if (splitted_fragment.size() != 3) {
+        emit caughtError("importTextFragment", {"Ошибка импорта!", QString("Получены некорректные данные фрагмента!\nДанные:") + QString::fromStdU16String(str)});
+        emit processFinished("importTextFragment", {"Error"});
+        busy = false;
+        return false;
+    }
+
+    busy = false;
+    emit textFragmentReceived(splitted_fragment.at(1), splitted_fragment.at(2));
+    emit processFinished("importTextFragment", {"Success"});
 }
 
 void Lotro::createCoreStatusFile(QString output_filename) {
+    if (!tryToBlockFile())
+        return;
 
+    emit processStarted("createCoreStatusFile", {output_filename});
+    auto gatherinfo_op = file.GatherInformation(output_filename.toStdString());
+    busy = false;
+
+    if (gatherinfo_op.result == LOTRO_DAT::SUCCESS) {
+        emit processFinished("createCoreStatusFile", {"Success", {output_filename}});
+    } else {
+        emit caughtError("createCoreStatusFile", {"Ошибка сбора информации!", QString("Не удаётся создать файл информации ядра")});
+        emit processFinished("createCoreStatusFile", {"Error", {output_filename}});
+    }
 }
 
 void Lotro::extractSingleFile(QString output_filename, long long file_id) {
+    if (!tryToBlockFile())
+        return;
+
+    emit processStarted("extractSingleFile", {output_filename, file_id});
+    auto extractfile_op = file.GetExporter().ExtractFileById(file_id, output_filename.toStdString());
+    busy = false;
 
+    if (extractfile_op.result == LOTRO_DAT::SUCCESS) {
+        emit processFinished("extractSingleFile", {"Success", output_filename, file_id});
+    } else {
+        emit caughtError("extractSingleFile", {"Ошибка экспорта!", QString("Не удаётся экспортировать файл " + QString::number(file_id) + " в файл " + output_filename)});
+        emit processFinished("extractSingleFile", {"Error", output_filename});
+    }
 }
 
 void Lotro::extractSingleFileToDatabase(QString database_path, long long file_id) {
+    if (!tryToBlockFile())
+        return;
+
+    emit processStarted("extractSingleFileToDatabase", {database_path, file_id});
+    LOTRO_DAT::Database db;
+    if (!db.InitDatabase(database_path.toStdString())) {
+        emit caughtError("extractSingleFileToDatabase", {"Ошибка экспорта!", QString("Не удаётся создать/открыть базу данных " + database_path)});
+        emit processFinished("extractSingleFileToDatabase", {"Error", database_path});
+        busy = false;
+        return;
+    }
 
+    auto extractfile_op = file.GetExporter().ExtractFileById(file_id, &db);
+    busy = false;
+
+    if (extractfile_op.result == LOTRO_DAT::SUCCESS) {
+        emit processFinished("extractSingleFileToDatabase", {"Success", {database_path, file_id}});
+    } else {
+        emit caughtError("extractSingleFileToDatabase", {"Ошибка экспорта!", QString("Не удаётся экспортировать файл " + QString::number(file_id) + " в базу данных " + database_path)});
+        emit processFinished("extractSingleFileToDatabase", {"Error", {database_path}});
+    }
 }
 
 void Lotro::extractGrouppedFiles(QString output_foldername, LOTRO_DAT::FILE_TYPE type) {
+    if (!tryToBlockFile())
+        return;
+
+    emit processStarted("extractSingleFile", {output_foldername, file_id});
+    auto extractfile_op = file.GetExporter().ExtractAllFilesByType(type, output_foldername.toStdString());
+    busy = false;
 
+    if (extractfile_op.result == LOTRO_DAT::SUCCESS) {
+        emit processFinished("extractSingleFile", {"Success", output_foldername, type});
+    } else {
+        emit caughtError("extractSingleFile", {"Ошибка экспорта!", QString("Не удаётся экспортировать файл " + QString::number(file_id) + " в файл " + output_filename)});
+        emit processFinished("extractSingleFile", {"Error", output_foldername});
+    }
 }
 
 void Lotro::extractGrouppedFilesToDatabase(QString database_path, LOTRO_DAT::FILE_TYPE type) {
+    if (!tryToBlockFile())
+        return;
+
+    emit processStarted("extractGrouppedFilesToDatabase", {database_path, file_id});
+    LOTRO_DAT::Database db;
+    if (!db.InitDatabase(database_path.toStdString())) {
+        emit caughtError("extractGrouppedFilesToDatabase", {"Ошибка экспорта!", QString("Не удаётся создать/открыть базу данных " + database_path)});
+        emit processFinished("extractGrouppedFilesToDatabase", {"Error", database_path});
+        busy = false;
+        return;
+    }
+
+    auto extractfile_op = file.GetExporter().ExtractFileById(file_id, &db);
+    busy = false;
 
+    if (extractfile_op.result == LOTRO_DAT::SUCCESS) {
+        emit processFinished("extractGrouppedFilesToDatabase", {"Success", {database_path, type}});
+    } else {
+        emit caughtError("extractGrouppedFilesToDatabase", {"Ошибка экспорта!", QString("Не удаётся экспортировать файлы с типом " + QString::number(type) + " в базу данных " + database_path)});
+        emit processFinished("extractGrouppedFilesToDatabase", {"Error", {output_foldername}});
+    }
 }
 
 void Lotro::getUnactiveCategories() {
@@ -174,77 +450,3 @@ bool Lotro::tryToBlockFile()
     busy = true;
 }
 
-
-
-
-void LegacyApp::ExtractFiles(QString folder_name, bool to_database, bool is_single_file, int file_id, LOTRO_DAT::FILE_TYPE type)
-{
-    qDebug() << "Extracting files with parameters " << folder_name << to_database << is_single_file << file_id << type;
-    QtConcurrent::run([this, folder_name, to_database, is_single_file, file_id, type](){
-        if (client_local_dat_busy == false) {
-            client_local_dat_busy = true;
-            if (is_single_file) {
-                auto operation = client_local_dat.GetExporter().ExtractFileById(file_id, std::string((folder_name + "/output").toLocal8Bit().constData()));
-
-                if (operation.result == LOTRO_DAT::SUCCESS)
-                    QMessageBox::information(nullptr, "Извлечение успешно!", "Файл " + QString::number(file_id) + " был успешно извлечён!\nПуть к файлу: " + folder_name + "/output.{расширение файла}");
-                else
-                    QMessageBox::critical(nullptr, "Ошибка извлечения!", "Файл " + QString::number(file_id) + " не был извлечён ввиду внутренней ошибки\nТекст ошибки: " + QString::fromStdString(operation.msg));
-            }
-
-            if (!is_single_file) {
-                if (to_database) {
-                    LOTRO_DAT::Database db;
-                    qint64 msecs = QDateTime::currentDateTime().toMSecsSinceEpoch();
-
-                    QString output_database_filename = folder_name + "/database_" + QString::number(msecs) + ".db";
-
-                    db.InitDatabase(std::string(output_database_filename.toStdString()));
-                    auto operation = client_local_dat.GetExporter().ExtractAllFilesByType(type, &db);
-                    db.CloseDatabase();
-
-                    if (operation.result == LOTRO_DAT::SUCCESS)
-                        QMessageBox::information(nullptr, "Извлечение успешно!", "Выбранные типы файлов были успешно извлечены в базу данных\nКол-во извлечённых файлов: " + QString::number(operation.value) + "\nПуть к извлечённой базе данных: " + output_database_filename);
-                    else
-                        QMessageBox::critical(nullptr, "Ошибка извлечения!", "Файлы не были извлечены ввиду внутренней ошибки\nТекст ошибки: " + QString::fromStdString(operation.msg));
-                } else {
-                    QString output_directory_path = folder_name + "/";
-                    auto operation = client_local_dat.GetExporter().ExtractAllFilesByType(type, std::string(output_directory_path.toLocal8Bit().constData()));
-
-                    if (operation.result == LOTRO_DAT::SUCCESS)
-                        QMessageBox::information(nullptr, "Извлечение успешно!", "Выбранные типы файлов были успешно извлечены в папку\nКол-во извлечённых файлов: " + QString::number(operation.value) + "\nПуть к папке: " + output_directory_path);
-                    else
-                        QMessageBox::critical(nullptr, "Ошибка извлечения!", "Файлы не были извлечены ввиду внутренней ошибки\nТекст ошибки: " + QString::fromStdString(operation.msg));
-                }
-            }
-
-            client_local_dat_busy = false;
-        }
-    });
-}
-
-void LegacyApp::ChangeLocale()
-{
-
-}
-
-void LegacyApp::CreateCoreStatusFile(QString output_folder)
-{
-    qDebug() << "Creating core status file to output folder " << output_folder;
-
-    QtConcurrent::run([this, output_folder](){
-        if (client_local_dat_busy == false) {
-            client_local_dat_busy = true;
-            qint64 msecs = QDateTime::currentDateTime().toMSecsSinceEpoch();
-            QString output_filename = output_folder + "/core_" + QString::number(msecs) + ".txt";
-            auto operation = client_local_dat.GatherInformation(std::string(output_filename.toLocal8Bit().constData()));
-            client_local_dat_busy = false;
-
-
-            if (operation.result == LOTRO_DAT::SUCCESS)
-                QMessageBox::information(nullptr, "Успех!", "Файл ядра успешно создан!\nПуть к файлу: " + output_filename);
-            else
-                QMessageBox::critical(nullptr, "Неудача!", "Ошибка создания файла ядра!\nТекст ошибки: " + QString::fromStdString(operation.msg));
-        }
-    });
-}

+ 10 - 8
src/Legacy-advanced/models/lotro.h

@@ -49,19 +49,21 @@ public slots:
 
     void startGame();
 
+    void showFileInfo();
+
 private:
     bool tryToBlockFile();
 
 signals:
     // general signals. First argument is process_name, second - processed values
-    void processStarted(QString, QList<QVariant>);
-    void processFinished(QString, QList<QVariant>);
-    void processUpdated(QString, QList<QVariant>);
-    void caughtError(QString, QList<QVariant>);
-
-    void TextFragmentReceived(QString, QString);
-    void UnactiveCategoriesReceived(QStringList);
-    void LocaleFileContentsReceived(int, LOTRO_DAT::SubfileData); // extention, contents
+    void processStarted(QString, QVector<QVariant>);
+    void processFinished(QString, QVector<QVariant>);
+    void processUpdated(QString, QVector<QVariant>);
+    void caughtError(QString, QVector<QVariant>);
+
+    void textFragmentReceived(QString, QString);
+    void unactiveCategoriesReceived(QStringList);
+    void localeFileContentsReceived(int, LOTRO_DAT::SubfileData); // extention, contents
 
 private:
     LOTRO_DAT::DatFile file;