Explorar el Código

Refactor part 2. Compilation success

Ivan Arkhipov hace 6 años
padre
commit
d08f4df5cd
Se han modificado 24 ficheros con 1092 adiciones y 1749 borrados
  1. 11 14
      Legacy.pro
  2. 11 16
      aconfig.cpp
  3. 0 2
      aconfig.h
  4. 221 0
      anetwork.cpp
  5. 50 0
      anetwork.h
  6. 0 112
      app.h
  7. 25 47
      downloadmanager.cpp
  8. 13 8
      downloadmanager.h
  9. 5 4
      filesystem.cpp
  10. 3 0
      filesystem.h
  11. 58 57
      gameres.cpp
  12. 12 10
      gameres.h
  13. 0 6
      gui.cpp
  14. 0 17
      gui.h
  15. 0 759
      helper.cpp
  16. 0 66
      helper.h
  17. 21 18
      main.cpp
  18. 402 217
      mainwindow.cpp
  19. 43 42
      mainwindow.h
  20. 0 313
      network.cpp
  21. 0 40
      network.h
  22. 187 0
      skin.cpp
  23. 29 0
      skin.h
  24. 1 1
      ui_mainwindow.h

+ 11 - 14
Legacy.pro

@@ -28,28 +28,25 @@ DEFINES += QT_DEPRECATED_WARNINGS
 
 SOURCES += \
     main.cpp \
-    mainwindow.cpp \
-    network.cpp \
-    helper.cpp \
-    downloadmanager.cpp \
-    gui.cpp \
     gameres.cpp \
     filesystem.cpp \
-    aconfig.cpp
+    aconfig.cpp \
+    anetwork.cpp \
+    downloadmanager.cpp \
+    skin.cpp \
+    mainwindow.cpp
 
 HEADERS += \
-        mainwindow.h \
-    app.h \
-    network.h \
-    helper.h \
-    downloadmanager.h \
-    gui.h \
     gameres.h \
     filesystem.h \
-    aconfig.h
+    aconfig.h \
+    anetwork.h \
+    downloadmanager.h \
+    skin.h \
+    mainwindow.h
 
 FORMS += \
-        mainwindow.ui
+    mainwindow.ui
 
 RESOURCES += \
     res.qrc \

+ 11 - 16
aconfig.cpp

@@ -1,19 +1,11 @@
-#include "app.h"
+#include "aconfig.h"
+
+#include <QApplication>
 
 AConfig::AConfig() {
     filename_ = QApplication::applicationDirPath() + "/settings.ini";
 }
 
-AConfig::AConfig(const AConfig&) {
-    throw QException(); // Выкидываем QException, в случае если
-                        // вообще попытались скопировать объект
-}
-
-AConfig& AConfig::operator=(AConfig&) {
-    throw QException(); // Выкидываем QException, в случае если
-                        // вообще попытались скопировать объект
-}
-
 void AConfig::saveConfig(){
     QSettings settings(filename_, QSettings::IniFormat);
     //Global
@@ -65,7 +57,7 @@ void AConfig::saveConfig(){
 }
 
 QString AConfig::getValue(QString section, QString key){
-    QSettings settings( conffile, QSettings::IniFormat );
+    QSettings settings(filename_, QSettings::IniFormat);
     settings.beginGroup(section);
     key = settings.value(key, -1).toString();
     settings.endGroup();
@@ -73,22 +65,25 @@ QString AConfig::getValue(QString section, QString key){
 }
 
 void AConfig::setValue(QString section, QString key, QString value){
-    QSettings settings( conffile, QSettings::IniFormat );
+    QSettings settings(filename_, QSettings::IniFormat);
     settings.beginGroup(section);
     settings.setValue(key, value);
     settings.sync();
 }
 
 void AConfig::deleteKey(QString section, QString key){
-    QSettings settings( conffile, QSettings::IniFormat );
+    QSettings settings(filename_, QSettings::IniFormat);
     QStringList keys = settings.childKeys();
     settings.beginGroup(section);
-    if (keys.contains(key)){ settings.remove(key); }
+
+    if (keys.contains(key))
+        settings.remove(key);
+
     settings.endGroup();
 }
 
 void AConfig::deleteSection(QString section){
-    QSettings settings( conffile, QSettings::IniFormat );
+    QSettings settings(filename_, QSettings::IniFormat );
     settings.beginGroup(section);
     settings.remove("");
     settings.endGroup();

+ 0 - 2
aconfig.h

@@ -12,8 +12,6 @@
 class AConfig {
 private:
     AConfig();
-    AConfig(const AConfig&);
-    AConfig& operator=(AConfig&);
 
 public:
     static AConfig* getInstance() {

+ 221 - 0
anetwork.cpp

@@ -0,0 +1,221 @@
+#include "aconfig.h"
+#include "filesystem.h"
+#include "anetwork.h"
+#include "downloadmanager.h"
+#include "mainwindow.h"
+
+#include <QApplication>
+#include <QtNetwork/QNetworkAccessManager>
+#include <QUrl>
+#include <QUrlQuery>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QObject>
+#include <QEventLoop>
+#include <QDir>
+#include <QMap>
+#include <QString>
+
+#include <string>
+
+ANetwork::ANetwork() {}
+
+void ANetwork::getPatches() {
+    QUrlQuery query;
+    QStringList names;
+    QString version;
+
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Начинаем проверку актуальности патчей.");
+    names  << "sound" << "text" << "image" << "video" << "screen" << "texture" << "font";
+    QUrl url(AConfig::getInstance()->getValue("Network", "releases"));
+
+    QString datafolder = QApplication::applicationDirPath() + "/data";
+
+    QDir dir(datafolder);
+    if(!dir.exists())
+        QDir().mkdir(datafolder);
+
+    foreach(QString s, names) {
+        if(AConfig::getInstance()->getValue("Editor", s + "s") == "true"){
+
+            if(s == "screen")
+                s = "loadscreen";   // поправка для заставок
+
+            QStringList paths = dir.entryList(QStringList(s + "*"));
+
+            if(!paths.empty()) {
+                 version = QString::number(getVersion(paths.first()));
+                 QString hash = FileSystem::fileHash(datafolder + "/" + paths.first(), QCryptographicHash::Md5);
+                 if(hash != AConfig::getInstance()->getValue("Hashes", s + "s")){
+                     qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Эталон хэша отсутствует (удаляю файл): ", paths.first().toStdString().c_str());
+                     QFile base(datafolder + "/" + paths.first());
+                     base.remove();
+                     version="100";
+                 }
+
+                 QString dateline = AConfig::getInstance()->getValue("Datetime", s + "s");
+                 if(dateline != "-1"){
+                    qDebug("%s:%i: %s", __FILE__, __LINE__, "Проставляем даты патчей.");
+                    emit updatePatchDates(s, dateline.split(" ")[0]);
+                 }
+            } else {
+                qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Патч отсутствует: ", s.toStdString().c_str());
+                version = "100";
+            }
+            query.addQueryItem(s, version);
+        }
+    }
+
+    url.setQuery(query.query());
+    qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Запрашиваем информацию о патчах: ", url.fileName().toStdString().c_str());
+    QString content = this->query(url);
+    if(content == "error"){
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Отсутствует связь с сервером. Прервано.");
+        return;
+    }
+
+    qDebug() << content;
+    if(content == "") {
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Все версии патчей соответствуют актуальным.");
+        return;
+    }
+
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Составляем список загрузок.");
+    QStringList downloads = content.split( "|" );
+
+    foreach (QString item, downloads) {
+        QStringList values = item.split( ":::" );
+
+        QStringList pathline = values[0].split( "_" );
+        pathline = pathline[0].split( "/" );
+        QUrl url = AConfig::getInstance()->getValue("Network", "server") + values[0];
+        AConfig::getInstance()->setValue("Hashes", pathline[3], values[1]);
+        AConfig::getInstance()->setValue("Datetime", pathline[3], values[2]);
+
+        // Удаляем устаревшие патчи
+        QStringList old = dir.entryList(QStringList(pathline[3] + "*"));
+        if(old.count() > 0){
+            foreach(QString filename, old){
+                QFile::remove(QApplication::applicationDirPath() + "/data/" + filename);
+            }
+        }
+
+        // Добавляем новый файл в список закачек
+        DownloadManager::getInstance()->append(url);
+    }
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Начинаем загрузку патчей.");
+    DownloadManager::getInstance()->startNextDownload();
+}
+
+QString ANetwork::query(QUrl url) {
+    QNetworkAccessManager* manager = new QNetworkAccessManager(MainWindow::getInstance());
+    QNetworkRequest request(url);
+    QNetworkReply* reply = manager->get(request);
+    QEventLoop loop;
+    QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
+    loop.exec();
+    QString content = reply->readAll();
+    if (reply->error() != QNetworkReply::NoError){
+        content = "error";
+        // пишем в лог
+        qDebug() << reply->errorString();
+    }
+    reply->deleteLater();
+    return content;
+}
+
+QByteArray ANetwork::query_binary(QUrl url) {
+    QNetworkAccessManager* manager = new QNetworkAccessManager(MainWindow::getInstance());
+    QNetworkRequest request(url);
+    QNetworkReply* reply = manager->get(request);
+    QEventLoop loop;
+    QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
+    loop.exec();
+    QByteArray bytes = reply->readAll();
+    return bytes;
+}
+
+void ANetwork::getCoupon() {
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Получаем купон.");
+    QString content = this->query(AConfig::getInstance()->getValue("Network", "coupon") + ".txt");
+    if (content == "error")
+        return;
+
+    AConfig::getInstance()->setValue("Values", "coupon", content);
+    qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Ответ сервера: ",content.toStdString().c_str());
+    emit getCouponFinished(content);
+}
+
+void ANetwork::getFootMessage() {
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Получаем данные для футера");
+    QString content = this->query(AConfig::getInstance()->getValue("Network", "foot") + ".txt");
+    qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Ответ сервера: ", content.toStdString().c_str());
+
+    if (content == "error" || content == "")
+        return;
+
+    emit getFootMessageFinished(content);
+}
+
+void ANetwork::getServers() {
+    QString content = this->query(AConfig::getInstance()->getValue("Network", "servers") + ".txt");
+
+    if (content == "error") {
+        emit getServersFinished("error");
+        return;
+    }
+
+    qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Ответ сервера: ", content.toStdString().c_str());
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Данные получены. Производим установку значений.");
+    AConfig::getInstance()->setValue("Values", "servers", content);
+
+    emit getServersFinished(content);
+}
+
+void ANetwork::getMicroPatch(int timestamp){
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Загрузка последних обновлений");
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Уточняем наличие обновлений");
+
+    QString microfolder = QApplication::applicationDirPath() + "/data/micro/";
+    QDir dir(microfolder);
+    if(!dir.exists())
+        QDir().mkdir(microfolder);
+
+    QString baseurl = AConfig::getInstance()->getValue("Network", "update");
+    QString url = baseurl + "/" + QString::number(timestamp);
+
+    qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Стартуем загрузку ", url.toStdString().c_str());
+    QNetworkAccessManager m_NetworkMngr;
+    QNetworkReply *reply= m_NetworkMngr.get(QNetworkRequest(url));
+    QEventLoop loop;
+    QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
+    loop.exec();
+
+    QUrl aUrl(url);
+    QFileInfo fileInfo=aUrl.path();
+    QString filename = microfolder + fileInfo.fileName() + ".db";
+    QFile file(filename);
+
+    file.open(QIODevice::WriteOnly);
+    file.write(reply->readAll());
+    delete reply;
+
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Загрузка микропатча завершена.");
+
+    emit getMicroPatchFinished(filename);
+}
+
+int ANetwork::getVersion(QString string) {
+    std::string str(string.toLatin1().data());
+    int version = 0;
+    for (unsigned int i = str.find("_v") + 2; i < str.find("_v") + 7; i += 2) {
+        version = version * 10 + (str[i] - '0');
+    }
+    return version;
+}
+
+
+
+
+
+

+ 50 - 0
anetwork.h

@@ -0,0 +1,50 @@
+#ifndef NETWORK_H
+#define NETWORK_H
+
+#include <QUrl>
+#include <QFile>
+#include <QNetworkReply>
+
+class MainWindow;
+
+class ANetwork : public QObject {
+Q_OBJECT
+// Realising Singleton here
+private:
+    ANetwork();
+
+public:
+    static ANetwork* getInstance() {
+        static ANetwork network;
+        return &network;
+    }
+    QString query(QUrl url);
+    QByteArray query_binary(QUrl url);
+
+public slots:
+    void getPatches();
+    void getCoupon();
+    void getServers();
+    void getFootMessage();
+    void getMicroPatch(int timestamp);
+
+signals:
+    void getPatchFinished(QString patchname, QString date);
+    void getCouponFinished(QString coupon);
+    void getServersFinished(QString server);
+    void getFootMessageFinished(QString msg);
+    void getMicroPatchFinished(QString filename);
+
+    void updatePatchDates(QString name, QString date);
+
+private:
+    int getVersion(QString string);
+    QNetworkReply* currentDownload;
+    QFile output;
+
+//private slots:
+    //void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
+    //void downloadFinished();
+};
+
+#endif // NETWORK_H

+ 0 - 112
app.h

@@ -1,112 +0,0 @@
-#ifndef APP_H
-#define APP_H
-
-#include "mainwindow.h"
-#include "ui_mainwindow.h"
-
-#include "config.h"
-#include "network.h"
-#include "helper.h"
-#include "downloadmanager.h"
-
-#include <QRegExp>
-#include <QBitmap>
-#include <QClipboard>
-#include <QException>
-#include <QWidget>
-#include <QGraphicsDropShadowEffect>
-#include <QDesktopWidget>
-#include <QFile>
-#include <QFileInfo>
-#include <QDir>
-#include <QFileDialog>
-#include <QMessageBox>
-#include <QRect>
-#include <QGridLayout>
-#include <QMovie>
-#include <QListWidget>
-#include <QtConcurrent/QtConcurrent>
-#include <QMessageLogger>
-#include <QDebug>
-#include <QFutureWatcher>
-#include "LotroDat.h"
-#include <string>
-
-using namespace LOTRO_DAT;
-
-class App {
-
-public:
-    App() {
-        instance = nullptr;
-        config = new AConfig();
-        network = new ANetwork();
-        helper = new Helper();
-        downloader = new DownloadManager();
-        writtenLabel = new QLabel();
-        //datfile  = new DatFile();
-        db  = new Database();
-        buildSeparators(9472, 65507, 45, 60, 48, 85);//9472 создаем разделители
-    }
-
-    static App& getInstance() {
-        if (instance == nullptr) {
-            instance = new App();
-        }
-        return *instance;
-    }
-
-    AConfig * config;
-    ANetwork * network;
-    Helper * helper;
-    MainWindow * window;
-    DownloadManager * downloader;
-    QLabel * writtenLabel;
-    QString state;
-    //DatFile * datfile;
-    Database * db;
-    QString app_folder = "";
-    QString qsep, qsepn, tsep, tsepn, bsep, bsepn;
-    QString stylehtml;
-    DatFile datfiles[5];
-    bool ready = true;
-
-    void log(QString msg){
-        QString format = "[" + QDate::currentDate().toString(Qt::ISODate).toUtf8() + " " + QTime::currentTime().toString(Qt::ISODate).toUtf8() + "]    " + msg;
-        fprintf(stderr, (format + "\n").toUtf8());
-    }
-
-    void logSectionStart(const char * msg){
-        topSeparate();
-        fprintf(stderr, "%s\n", msg);
-        bottomSeparate();
-    }
-
-    void logSectionEnd(){
-        fprintf(stderr, " \n");
-    }
-
-    void topSeparate(){
-        fprintf(stderr, tsepn.toUtf8());
-    }
-
-    void bottomSeparate(){
-        fprintf(stderr, bsepn.toUtf8());
-    }
-
-    void buildSeparators(int code_top, int code_bottom, int qcode, int tsize, int bsize, int qsize){
-        for(int i = 0; i < tsize; i++){ tsep.append(QChar(QChar(code_top))); }
-        tsepn = tsep + "\n";
-        for(int i = 0; i < bsize; i++){ bsep.append(QChar(QChar(code_bottom))); }
-        bsepn = bsep + "\n";
-        for(int i = 0; i < qsize; i++){ qsep.append(QChar(QChar(qcode))); }
-        qsepn = qsep + "\n";
-    }
-
-
-
-private:
-    static App * instance;
-
-};
-#endif // APP_H

+ 25 - 47
downloadmanager.cpp

@@ -1,4 +1,6 @@
-#include "app.h"
+#include "downloadmanager.h"
+#include "filesystem.h"
+#include "aconfig.h"
 
 #include <QFileInfo>
 #include <QApplication>
@@ -10,9 +12,7 @@
 #include <stdio.h>
 
 DownloadManager::DownloadManager(QObject *parent)
-    : QObject(parent), downloadedCount(0), totalCount(0)
-{
-}
+    : QObject(parent), downloadedCount(0), totalCount(0) {}
 
 void DownloadManager::append(const QStringList &urlList){
     foreach (QString url, urlList)
@@ -23,8 +23,7 @@ void DownloadManager::append(const QStringList &urlList){
 }
 
 void DownloadManager::append(const QUrl &url){
-    App *app = &App::getInstance();
-    qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Добавлен: ", app->helper->stringToChar(url.fileName()));
+    qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Добавлен: ", url.fileName().toStdString().c_str());
     if (downloadQueue.isEmpty())
         QTimer::singleShot(0, this, SLOT(startNextDownload()));
 
@@ -33,63 +32,53 @@ void DownloadManager::append(const QUrl &url){
     qDebug("%s:%i: %s%i", __FILE__, __LINE__, "Загрузок в списке: ", totalCount);
 }
 
-void DownloadManager::startNextDownload()
-{
-    App *app = &App::getInstance();
-
+void DownloadManager::startNextDownload() {
     if (downloadQueue.isEmpty()) {
-        app->helper->setState("free");// говорим что приложение освободилось
         qDebug("%s:%i: %s%d/%d", __FILE__, __LINE__, "Загрузка завершена. Загружено файлов: ", downloadedCount, totalCount);
-        emit finished();
+        emit finishedAllDownloads();
         return;
     }
 
     QUrl url = downloadQueue.dequeue();
     QString filename = QFileInfo(url.path()).fileName();
     output.setFileName(QApplication::applicationDirPath() + "/data/" + filename);
-    qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Начата загрузка файла: ", app->helper->stringToChar(filename));
+    qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Начата загрузка файла: ", filename.toStdString().c_str());
     // Проверяем целостность файла и игнорируем в случае если он цел
-    QString hash = app->helper->fileHash(QApplication::applicationDirPath() + "/data/" + filename, QCryptographicHash::Md5);
+    QString hash = FileSystem::fileHash(QApplication::applicationDirPath() + "/data/" + filename, QCryptographicHash::Md5);
     QStringList pname = output.fileName().split("/");
     QStringList ptype = pname.last().split("_");
     qDebug() << ptype.first();
     QString keyname = ptype.first();
     if(keyname == "loadscreens") keyname = "screens";
-    if(hash == app->config->getValue("Hashes", ptype.first()) && app->config->getValue("Editor", keyname) == "true"){
-        qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Проверка хэша успешно завершена: ", app->helper->stringToChar(filename));
+    if(hash == AConfig::getInstance()->getValue("Hashes", ptype.first()) && AConfig::getInstance()->getValue("Editor", keyname) == "true"){
+        qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Проверка хэша успешно завершена: ", filename.toStdString().c_str());
         startNextDownload();
         return;
     }
 
-    qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Хэш файла не совпал: ", app->helper->stringToChar(filename));
+    qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Хэш файла не совпал: ", filename.toStdString().c_str());
     QStringList parsename = filename.split("_");
     QString name = parsename[0] + "Status";
     download_name = parsename[0];
-    app->writtenLabel = app->window->ui->mainbox->findChild<QLabel *>(name);
 
     if (!output.open(QIODevice::WriteOnly)) {
-        qCritical("%s:%i: %s%s", __FILE__, __LINE__, "Произошла остановка скачивания ", app->helper->stringToChar(filename));
+        qWarning("%s:%i: %s%s", __FILE__, __LINE__, "Произошла остановка скачивания ", filename.toStdString().c_str());
         /*fprintf(stderr, "Problem opening save file '%s' for download '%s': %s\n",
                 qPrintable(filename), url.toEncoded().constData(),
                 qPrintable(output.errorString()));*/
-        if(app->writtenLabel != nullptr) app->writtenLabel->setText("Не удалась");
+        emit fileDownloadFinished(filename, "Не удалась");
         startNextDownload();
         return;
     }
 
-    qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Начинаем скачивание ", app->helper->stringToChar(url.fileName()));
-
-    app->helper->setState("busy");// говорим что приложение занято
+    qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Начинаем скачивание ", url.fileName().toStdString().c_str());
 
     QNetworkRequest request(url);
     currentDownload = manager.get(request);
     connect(this, SIGNAL(cancelDownload()), currentDownload, SLOT(abort()));
-    connect(currentDownload, SIGNAL(downloadProgress(qint64,qint64)),
-            SLOT(downloadProgress(qint64,qint64)));
-    connect(currentDownload, SIGNAL(finished()),
-            SLOT(downloadFinished()));
-    connect(currentDownload, SIGNAL(readyRead()),
-            SLOT(downloadReadyRead()));
+    connect(currentDownload, SIGNAL(downloadProgress(qint64,qint64)), SLOT(downloadProgress(qint64,qint64)));
+    connect(currentDownload, SIGNAL(finished()), SLOT(downloadFinished()));
+    connect(currentDownload, SIGNAL(readyRead()), SLOT(downloadReadyRead()));
 
     // prepare the output
 
@@ -113,26 +102,22 @@ void DownloadManager::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
     QString speedtext = QString::fromLatin1("%1 %2").arg(speed, 3, 'f', 1).arg(unit);
     QString percenttext = QString::fromLatin1("%1").arg(percent, 3);
 
-    App *app = &App::getInstance();
-    if(app->writtenLabel != nullptr) app->writtenLabel->setText("Загрузка ... <br/>" + percenttext+ "% (" + speedtext + ")");
+    emit updateDownloadProgress("Загрузка ... <br/>" + percenttext+ "% (" + speedtext + ")");
 }
 
 void DownloadManager::downloadFinished()
 {
+    QString filename = output.fileName();
     output.close();
-    App *app = &App::getInstance();
-    app->helper->setState("free");// говорим что приложение освободилось
 
     if (currentDownload->error()) {
-         qWarning("%s:%i: %s%s", __FILE__, __LINE__, "Загрузка не удалась: ", app->helper->stringToChar(currentDownload->errorString()));
+         qWarning("%s:%i: %s%s", __FILE__, __LINE__, "Загрузка не удалась: ", currentDownload->errorString().toStdString().c_str());
         //fprintf(stderr, "Failed: %s\n", qPrintable(currentDownload->errorString()));
-        if(app->writtenLabel != nullptr) app->writtenLabel->setText("Не удалась.");
-    } else {       
-        if(app->writtenLabel != nullptr) app->writtenLabel->setText("Готово");
+        emit fileDownloadFinished(filename, "Не удалась.");
+    } else {
+        emit fileDownloadFinished(filename, "Готово.");
         qInfo("%s:%i: %s", __FILE__, __LINE__, "Все загрузки завершены. Загрузчик завершил свою работу.");
         ++downloadedCount;
-        app->network->getPaths();
-
     }
 
     currentDownload->deleteLater();
@@ -144,14 +129,7 @@ void DownloadManager::downloadReadyRead(){
 }
 
 void DownloadManager::abortDownload(QString name){
-    App *app = &App::getInstance();
-    if(download_name == name){
-       if(app->state != "free" &&  currentDownload != NULL && currentDownload->isOpen()) {
-            qDebug() << "Прерываем закачку " + download_name;
-            qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Пользователь прервал закачку файла ", app->helper->stringToChar(download_name));
-            if(app->writtenLabel != nullptr) app->writtenLabel->setText("Не выбран");
+    if(download_name == name &&  currentDownload != nullptr && currentDownload->isOpen()) {
             currentDownload->abort();
-
-       }
     }
 }

+ 13 - 8
downloadmanager.h

@@ -9,25 +9,30 @@
 #include <QLabel>
 #include <QNetworkAccessManager>
 
-
-//#include "textprogressbar.h"
-
 class DownloadManager: public QObject
 {
-    Q_OBJECT
-public:
+Q_OBJECT
+private:
     DownloadManager(QObject *parent = 0);
 
+public:
+    static DownloadManager* getInstance() {
+        static DownloadManager instance;
+        return &instance;
+    }
+
+public:
     void append(const QUrl &url);
     void append(const QStringList &urlList);
     void startNextDownload();
     void abortDownload(QString name);
 
 signals:
-    void finished();
-    void cancelDownload();
-private slots:
+    void finishedAllDownloads();
+    void fileDownloadFinished(QString filename, QString msg);
+    void updateDownloadProgress(QString msg);
 
+private slots:
     void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
     void downloadFinished();
     void downloadReadyRead();

+ 5 - 4
filesystem.cpp

@@ -2,18 +2,19 @@
 #include <QFile>
 #include <QFileInfo>
 #include <QCryptographicHash>
+#include <QDebug>
 
-static bool FileSystem::fileExists(QString path) {
+bool FileSystem::fileExists(QString path) {
     QFileInfo check_file(path);
     bool exists = check_file.exists() && check_file.isFile();
 
     if(exists == false)
-        qWarning("%s:%i: %s%s", __FILE__, __LINE__, "Файл не найден: ", app->helper->stringToChar(path));
+        qWarning("%s:%i: %s%s", __FILE__, __LINE__, "Файл не найден: ", path.toStdString().c_str());
 
     return exists;
 }
 
-static QString FileSystem::fileHash(const QString &fileName, QCryptographicHash::Algorithm hashAlgorithm) {
+QString FileSystem::fileHash(const QString &fileName, QCryptographicHash::Algorithm hashAlgorithm) {
     QFile file(fileName);
     if (file.open(QIODevice::ReadOnly)) {
         QByteArray fileData = file.readAll();
@@ -23,7 +24,7 @@ static QString FileSystem::fileHash(const QString &fileName, QCryptographicHash:
     return QByteArray();
 }
 
-static void FileSystem::clearFolder(QDir &dir) {
+void FileSystem::clearFolder(QDir &dir) {
     //Получаем список файлов
     QStringList lstFiles = dir.entryList(QDir::Files);
 

+ 3 - 0
filesystem.h

@@ -1,6 +1,9 @@
 #ifndef FILESYSTEM_H
 #define FILESYSTEM_H
 
+#include <QCryptographicHash>
+#include <QDir>
+
 class FileSystem
 {
     // Static class, which gives some extra functions for files/folders manipulation

+ 58 - 57
gameres.cpp

@@ -1,16 +1,18 @@
 #include "gameres.h"
 #include "aconfig.h"
 #include "filesystem.h"
+#include "anetwork.h"
 
+#include <QApplication>
 #include <QString>
 #include <QDir>
 #include <QFile>
 #include <QTime>
+#include <QProcess>
+
 #include <string>
 
 GameRes::GameRes() {}
-GameRes::GameRes(const GameRes&) {}
-GameRes& GameRes::operator=(GameRes&) {}
 
 // Public functions
 
@@ -27,17 +29,17 @@ void GameRes::openDatFile(int id) {
         return;
     }
 
-    std::string filename = (app->config->getValue("Local", "folder") + "/" + dat_files[id]).toStdString();
+    std::string filename = (AConfig::getInstance()->getValue("Local", "folder") + "/" + dat_files[id]).toStdString();
 
-    qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Инициализация dat-файла. Открываем файл ", filename);
-    int dat_state = app->datfiles[id].InitDatFile(file, 0);
+    qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Инициализация dat-файла. Открываем файл ", filename.c_str());
+    int dat_state = GameRes::getInstance()->datfiles_[id].InitDatFile(filename, 0);
     qDebug("%s:%i: %s%d", __FILE__, __LINE__, "Состояние dat-файла: ", dat_state);
 
     emit openDatFileFinished(dat_state);
 }
 
 void GameRes::closeDatFile(int id) {
-    int result = datfiles[id].CloseDatFile();
+    int result = datfiles_[id].CloseDatFile();
     emit closeDatFileFinished(result);
     return;
 }
@@ -45,8 +47,8 @@ void GameRes::closeDatFile(int id) {
 void GameRes::applyPatch(QString name) {
     emit startedPatching(name);
 
-    qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Начинаем применение патча ", app->helper->stringToChar(name));
-    QLabel* label = app->window->findChild<QLabel*>(name + "Status");
+    qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Начинаем применение патча ", name.toStdString().c_str());
+
     QDir dir(QApplication::applicationDirPath() + "/data");
 
     if (!dir.exists()) {
@@ -55,7 +57,7 @@ void GameRes::applyPatch(QString name) {
     }
 
     QStringList paths = dir.entryList(QStringList(name + "*"));
-    qDebug() << ("data/" + paths.first()).toStdString();
+    qDebug() << ("data/" + paths.first());
 
     if(!paths.empty()) {
         db_.InitDatabase(("data/" + paths.first()).toStdString());
@@ -81,37 +83,43 @@ void GameRes::applyPatch(QString name) {
 
 void GameRes::setGameLocale(QString locale) {
     openDatFile(0);
-    locale_ = app->datfiles[0].current_locale();
+    locale_ = datfiles_[0].current_locale();
 
     if(locale_ == PATCHED) qDebug() << "Starting " + locale + " version. Current locale is PATCHED";
     if(locale_ == ORIGINAL) qDebug() << "Starting " + locale + " version. Current locale is ORIGINAL";
-    if(locale_ != ORIGINAL && loc != PATCHED) qDebug() << "Starting " + locale + " version. Current locale is UNKNOWN";
+    if(locale_ != ORIGINAL && locale_ != PATCHED) qDebug() << "Starting " + locale + " version. Current locale is UNKNOWN";
 
-    if(locale == "RU" && loc != PATCHED) {qDebug()<< "Current locale Original"; app->datfiles[0].SetLocale(PATCHED); dat_locale = PATCHED;}
-    if(locale == "Original" && loc != ORIGINAL) {qDebug()<< "Current locale RU"; app->datfiles[0].SetLocale(ORIGINAL); dat_locale = ORIGINAL;}
+    if(locale == "RU" && locale_ != PATCHED) {qDebug()<< "Current locale Original"; datfiles_[0].SetLocale(PATCHED); locale_ = PATCHED;}
+    if(locale == "Original" && locale_ != ORIGINAL) {qDebug()<< "Current locale RU"; datfiles_[0].SetLocale(ORIGINAL); locale_ = ORIGINAL;}
     closeDatFile(0);
     emit setGameLocaleFinished(0);
 }
 
+void GameRes::saveAllDatFiles(){
+    for(int i = 0; i < 5; i++){
+        datfiles_[i].CloseDatFile();
+    }
+}
+
 void GameRes::startGame() {
-    AConfig::getInstance()->saveAllDatFiles();
+    saveAllDatFiles();
 
     QStringList args;
     args << "-skiprawdownload" << "-nosplash";
     if (locale_ == PATCHED)
         args << "-disablePatch";
 
-    QFile f(app->config->getValue("Local", "folder") + "/TurbineLauncher.exe");
+    QFile f(AConfig::getInstance()->getValue("Local", "folder") + "/TurbineLauncher.exe");
     QProcess process;
-    if(fileExists(f.fileName())){
+    if(FileSystem::fileExists(f.fileName())){
         if (f.fileName().contains(" "))
             f.setFileName("\"" + f.fileName() + "\"");
 
         process.startDetached(f.fileName(), args);
         process.waitForFinished(-1);
         process.deleteLater();
-        QApplication::quit();
         emit startGameFinished(0);
+        QApplication::quit();
     } else {
         //QString text = "Запуск не удался";
         //QString info = "Не удалось запустить игру. Во время запуска произшла непредвиденная ошибка (возможно, не найден файл TurbineLauncher.exe в папке с игрой. Проверьте в 'Настройках', что у вас указан верный путь к игре, и повторите попытку запуска).";
@@ -120,12 +128,23 @@ void GameRes::startGame() {
     }
 }
 
+int GameRes::dateToTimestamp(QString customDateString, QString format) {
+    int timestamp = QDateTime::fromString(customDateString, format).toTime_t();
+    return timestamp;
+}
+
 void GameRes::installMicroPatch() {
-    prepareMicroPatch();
-    applyMicroPatch();
-    QDir dir("/data/micro");
-    FileSystem::clearFolder(dir);
-    emit installMicroPatchFinished(0);
+    QString date = AConfig::getInstance()->getValue("Updates", "update");
+
+    if(date == "false")
+        date = QDate::currentDate().toString("yyyy-MM-dd");
+
+    QTime time = QTime::currentTime();
+    int timestamp = dateToTimestamp(date + " " + time.toString("hh:mm:ss"), "yyyy-MM-dd hh:mm:ss") - 2592000;
+
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Опция активна. Начинаем загрузку обновлений");
+    ANetwork::getInstance()->getMicroPatch(timestamp);
+    connect(ANetwork::getInstance(), SIGNAL(ANetwork::getMicroPatchFinished(QString)), this, SLOT(applyMicroPatch(QString)));
 }
 
 void GameRes::applyAll() {
@@ -144,8 +163,8 @@ void GameRes::applyAll() {
     foreach(QString name, names){
         QStringList list = dir.entryList(QStringList(name + "*"));
         if(list.size() > 0 && list.first() != ""){
-            QString isset = app->config->getValue("Applied", name);
-            if(list.first() != isset && app->config->getValue("Editor", name) == "true") {
+            QString isset = AConfig::getInstance()->getValue("Applied", name);
+            if(list.first() != isset && AConfig::getInstance()->getValue("Editor", name) == "true") {
                 need.append(name);
             }
         }
@@ -158,7 +177,7 @@ void GameRes::applyAll() {
         }
     }
 
-    if(app->config->getValue("Updates", "micro") == "true")
+    if(AConfig::getInstance()->getValue("Updates", "micro") == "true")
         installMicroPatch();
 
     emit applyAllFinished(0);
@@ -183,7 +202,6 @@ void GameRes::checkDatFile() {
 }
 
 QStringList GameRes::getLotroPath(){
-    App *app = &App::getInstance();
     QStringList paths;
 
     //#if defined(Q_WS_WIN)
@@ -191,7 +209,7 @@ QStringList GameRes::getLotroPath(){
     // Windows 7
     QSettings m("HKEY_CLASSES_ROOT\\Local Settings\\Software\\Microsoft\\Windows\\Shell\\MuiCache", QSettings::NativeFormat);
     foreach (QString key, m.allKeys()) {
-      if(key.contains("TurbineLauncher.exe") && app->helper->fileExists(key)){
+      if(key.contains("TurbineLauncher.exe") && FileSystem::fileExists(key)){
           paths.append(key.replace("/TurbineLauncher.exe", ""));
       }
     }
@@ -202,7 +220,7 @@ QStringList GameRes::getLotroPath(){
         qDebug() << key;
         if(key.contains("InstallLocation") || key.contains("installlocation")){
             QString folder = n.value(key).toString().replace("\\", "/").replace("/TurbineLauncher.exe", "").replace("\"", "");
-            if(app->helper->fileExists(folder + "/TurbineLauncher.exe")) paths.append(folder);
+            if(FileSystem::fileExists(folder + "/TurbineLauncher.exe")) paths.append(folder);
         }
     }
 
@@ -218,7 +236,7 @@ QStringList GameRes::getLotroPath(){
 
 void GameRes::processFile() {
     SubfileData subfile;
-    subfile = app->db->GetNextFile();
+    subfile = db_.GetNextFile();
     if (subfile.Empty()){
         qInfo("%s:%i: %s", __FILE__, __LINE__, "Достигнут конец файла.");
     } else {
@@ -229,35 +247,16 @@ void GameRes::processFile() {
     }
 }
 
-void GameRes::prepareMicroPatch() {
-    QString date = AConfig::getInstance()->getValue("Updates", "update");
-
-    if(date == "false")
-        date = QDate::currentDate().toString("yyyy-MM-dd");
-
-    QTime time = QTime::currentTime();
-    int seconds = QTime(0, 0, 0).secsTo(time);
-    int timestamp = app->helper->dateToTimestamp(date + " " + time.toString("hh:mm:ss"), "yyyy-MM-dd hh:mm:ss") - 2592000;
-
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Опция активна. Начинаем загрузку обновлений");
-    app->network->micropatch = QApplication::applicationDirPath() + "/data/micro/" + QString::number(timestamp + seconds) + ".db";
-
-    if(!app->helper->fileExists(app->network->micropatch)){
-        qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Файл патча: ", app->helper->stringToChar(app->network->micropatch));
-        app->network->micropatch = app->network->getMicroPath(timestamp);
-    }
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-}
-
-void GameRes::applyMicroPatch() {
+void GameRes::applyMicroPatch(QString filename) {
     emit startedPatching(" новые переводы");
 
-    db_.InitDatabase(app->helper->stringToChar(app->network->micropatch));
+    db_.InitDatabase(filename.toStdString());
+
+    int indb = db_.CountRows();
     qInfo("%s:%i: %s%d", __FILE__, __LINE__, "Файлов в обновлении: ", indb);
-    int indb = app->db->CountRows();
     int percent = -1;
 
-    for(int i = 0; i <= indb; i++) {
+    for(int i = 0; i < indb; i++) {
         if (i * 100 / indb > percent) {
             percent = i * 100 / indb;
             qInfo("%s:%i: %s%d%s", __FILE__, __LINE__, "Применение обновления: ", percent, "%");
@@ -267,7 +266,10 @@ void GameRes::applyMicroPatch() {
     }
 
     db_.CloseDatabase();
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
+
+    QDir dir("/data/micro");
+    FileSystem::clearFolder(dir);
+    emit installMicroPatchFinished(0);
 }
 
 void GameRes::applyLoadscreens() {
@@ -334,9 +336,8 @@ bool GameRes::isDatReady() { // Checks if file is ready to write data
 }
 
 std::string GameRes::getDatPath(int id){
-    App *app = &App::getInstance();
     QStringList dats;
-    dats << app->config->getValue("Local", "file") << "client_general.dat" << "client_sound.dat" << "client_surface.dat" << "client_highres.dat";
+    dats << AConfig::getInstance()->getValue("Local", "file") << "client_general.dat" << "client_sound.dat" << "client_surface.dat" << "client_highres.dat";
     //std::string file = (app->config->getValue("Local", "folder") + "/" + dats.at(id)).toStdString();
-    return app->helper->stringToChar(app->config->getValue("Local", "folder") + "/" + dats.at(id));
+    return (AConfig::getInstance()->getValue("Local", "folder") + "/" + dats.at(id)).toStdString();
 }

+ 12 - 10
gameres.h

@@ -12,17 +12,14 @@ Q_OBJECT
     // Singleton realisation of class
 private:
     GameRes();
-    GameRes(const GameRes&);
-    GameRes& operator=(GameRes&);
-
 public:
-    GameRes* getInstance() {
+    static GameRes* getInstance() {
         static GameRes instance;
-        return instance;
+        return &instance;
     }
 
     // Basic public functions
-public:
+public slots:
     void openDatFile(int id);               // Opens .dat file by its id (0-local_English.dat)
 
     void closeDatFile(int id);              // Closes .dat file by its id
@@ -37,12 +34,14 @@ public:
 
     void applyAll();                        // Installs all patches (applyGlobal)
 
-    bool isBusy() {}                        // !!!!TO BE DONE Returns true if operations with game res are working now
+    bool isBusy() {return false;}                        // !!!!TO BE DONE Returns true if operations with game res are working now
 
     void checkDatFile();                    // Checks and returns information if dat file is clear/updated
 
     QStringList getLotroPath();             // Returns path to LotRO files
 
+    void saveAllDatFiles();                 // Saves and closes all .dat files
+
 signals:
     // Signals for every public function finish. Gives result int value.
     void openDatFileFinished(int result);
@@ -60,19 +59,22 @@ signals:
     void finishedPatching(QString patchname, QString result);
 
 private:
+    int dateToTimestamp(QString customDateString, QString format);
     void processFile();
-    void prepareMicroPatch();
-    void applyMicroPatch();
     void applyLoadscreens();
     bool isDatReady(); // Checks if file is ready to write data
 
     std::string getDatPath(int id);
 
+private slots:
+    void applyMicroPatch(QString filename);
+
+
 private:
     QThread *thread_;
     bool busy_;
-    DatFile datfiles_[5];
     Database db_;
+    DatFile datfiles_[5];
     LOCALE locale_;
 };
 

+ 0 - 6
gui.cpp

@@ -1,6 +0,0 @@
-#include "gui.h"
-
-GUI::GUI(QWidget *parent) : QMainWindow(parent)
-{
-
-}

+ 0 - 17
gui.h

@@ -1,17 +0,0 @@
-#ifndef GUI_H
-#define GUI_H
-
-#include <QMainWindow>
-
-class GUI : public QMainWindow
-{
-    Q_OBJECT
-public:
-    explicit GUI(QWidget *parent = nullptr);
-
-signals:
-
-public slots:
-};
-
-#endif // GUI_H

+ 0 - 759
helper.cpp

@@ -1,759 +0,0 @@
-#include "app.h"
-
-Helper::Helper()
-{
-
-}
-
-QString Helper::fileHash(const QString &fileName, QCryptographicHash::Algorithm hashAlgorithm){
-    QFile file(fileName);
-    if (file.open(QIODevice::ReadOnly)) {
-        QByteArray fileData = file.readAll();
-        QByteArray hashData = QCryptographicHash::hash(fileData, hashAlgorithm);
-        return hashData.toHex();
-    }
-    return QByteArray();
-}
-
-int Helper::getVersion(QString string) {
-    std::string str(string.toLatin1().data());
-    int version = 0;
-    for (int i = str.find("_v") + 2; i < str.find("_v") + 7; i += 2) {
-        version = version * 10 + (str[i] - '0');
-    }
-    return version;
-}
-
-void Helper::checkTab(QString tabname){
-    App *app = &App::getInstance();
-    QList<QGroupBox *> boxes = app->window->findChildren<QGroupBox *> ();
-    foreach (QGroupBox * box, boxes){
-        if(box->parent()->objectName() == "centralWidget"){
-            QLabel* boximage = app->window->findChild<QLabel*>(box->objectName() + "Image");
-            if(box->objectName() == tabname){
-                box->show();
-                if(boximage != nullptr) boximage->show();
-            } else {
-                box->hide();
-                if(boximage != nullptr) boximage->hide();
-            }
-        }
-    }
-    app->window->ui->serversbox->show();
-}
-
-void Helper::loadNews(){
-    App *app = &App::getInstance();
-    app->logSectionStart("Загружаем скин лаунчера");
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Загрузка новостей с сайта");
-    QString response = app->network->query(app->config->getValue("Network", "news"));
-    if(response == "error"){
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Отсутствует связь с сервером. Прервано.");
-        app->logSectionEnd();
-        return;
-    }
-    QStringList data = response.split(":::");
-    qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Получено новостей - ", app->helper->stringToChar(QString::number(data.count())));
-    int counter = 1;
-    foreach(QString news, data){
-        qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Начинаем размещение новости №", app->helper->stringToChar(QString::number(counter)));
-        QStringList item = news.split("|");
-        QLabel* image = app->window->ui->newsbox->findChild<QLabel*>("news" + QString::number(counter) + "Image");
-        QLabel* title = app->window->ui->newsbox->findChild<QLabel*>("news" + QString::number(counter) + "Title");
-        QLabel* teaser = app->window->ui->newsbox->findChild<QLabel*>("news" + QString::number(counter) + "Teaser");
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Устанавливаем миниатюру новости");
-        QByteArray bytes = app->network->query_binary(item[0]);
-        QImage img(36, 36, QImage::Format_Indexed8);
-        img.loadFromData(bytes);
-        QString skin = app->helper->getSkinName();
-        if(img.bits() == nullptr){
-            qInfo("%s:%i: %s", __FILE__, __LINE__, "Миниатюра не найдена, устанавливаем заглушку");
-            img.load(":/res/styles/" + skin + "/nophoto.jpg");
-        }
-        image->setPixmap(QPixmap::fromImage(img));
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Применяем HTML-цвета");
-        QString hrefcolor = app->helper->htmlColors.contains("a") ? app->helper->htmlColors.lowerBound("a").value() : "blue";
-        QString html = "<a href=\"" + item[3] +"\" style=\"color:" + hrefcolor + "; text-decoration:none;\">" + item[1] + "</a>";
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Размещаем тексты");
-        title->setText(html);
-        teaser->setText(item[2]);
-        counter = counter+1;
-    }
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-    app->logSectionEnd();
-}
-
-void Helper::loadHelp(){
-    App *app = &App::getInstance();
-    app->logSectionStart("Создание справки");
-    QFile file(QApplication::applicationDirPath() + "/readme.html");
-
-    if(file.open(QFile::ReadOnly | QFile::Text)){
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Справка загружена. Устанавливаем HTML-цвета и выводим.");
-        app->window->ui->textBrowser->setHtml("");
-        QString content = file.readAll();
-
-        app->stylehtml = "<style>";
-        for(auto e : app->helper->htmlColors.keys()){
-            app->stylehtml = app->stylehtml + e + "{color:" + app->helper->htmlColors.value(e) + ";}";
-        }
-
-
-        QFile styleF;
-        QString skin = app->helper->getSkinName();
-        styleF.setFileName(app->app_folder + "styles/" + skin + "/readme.css");
-        if(styleF.open(QFile::ReadOnly)){
-           app->stylehtml = "<html><head><style type=\"text/css\">" + app->stylehtml + styleF.readAll();
-        }
-
-        app->stylehtml = app->stylehtml + "</style></head>";
-
-        app->window->ui->textBrowser->setHtml(app->stylehtml + content);
-        app->window->ui->textBrowser->document()->setDefaultStyleSheet(styleF.readAll());
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-        app->logSectionEnd();
-    } else {
-        qWarning("%s:%i: %s", __FILE__, __LINE__, "Не удалось получить информацию с сервера");
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-        app->logSectionEnd();
-    }
-}
-
-void Helper::hideAll(){
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Прячем ненужные элементы.");
-    App *app = &App::getInstance();
-    app->window->ui->optbox->hide();
-    app->window->ui->optboxImage->hide();
-    app->window->ui->newsbox->hide();
-    app->window->ui->newsboxImage->hide();
-    app->window->ui->helpbox->hide();
-    app->window->ui->helpboxImage->hide();
-    app->window->ui->aboutbox->hide();
-    app->window->ui->aboutboxImage->hide();
-    app->window->ui->dialogbox->hide();
-    app->window->ui->loader->hide();
-    app->window->ui->dialogList->hide();
-    app->window->ui->startbox->hide();    
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Устанавливаем всплывающие подсказки.");
-    app->window->ui->goOriginal->setToolTip("Запуск оригинальной версии игры");
-    app->window->ui->goLocal->setToolTip("Запуск русской версии игры");
-    app->window->ui->goCancel->setToolTip("Вернуться обратно");
-    app->window->ui->goProgress->hide();
-    app->window->ui->goHint->hide();
-    app->window->ui->footRed->hide();
-    app->window->ui->footYellow->hide();
-}
-
-void Helper::setAbout(){
-    App *app = &App::getInstance();
-    app->logSectionStart("О нас");
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Размещаем информацию о хороших людях.");
-    app->window->ui->programmerslist->setText("Gi1dor, coder");
-    app->window->ui->designerslist->setText("Чирик, valyot, Quilanar, Eodoro");
-    app->window->ui->translatorslist->setText("Arissa, unnamedartist, valyot, Чирик, Eodoro, Ferdik, Tukbard, Alcassar, Satenskyhou, Quilanar, Коралан, Invizet, taiki_exe, Rhymer, Takhizis, Lauraldo, seventhgate027, Kerita, Хилко, Leodgar, Juolukka, Auruman, Drazgar, Tondred, Foldoren, Exildil, Anormir, Василий Волков, Andoriel, Felicer, noldohini, Gi1dor, Progylkin, Arkwendir, Bara Norkins, Siltier, Maxsikr, Nahkrin, Nick_os, Razverg, ENDrain, ToX4SHOW, Jeyolin, Frenni, Коралан, Palmuch, Marty");
-    app->window->ui->programmerslist->setText("Gi1dor, coder");
-    app->window->ui->helperslist->setText("Menelhad, Мурзилка, Pastor, Alvees, Mirta, иван петров, vensys, Arkelas, Чеширская Улыбка, Shanishka70 ");
-}
-
-void Helper::findSkins(){
-    App *app = &App::getInstance();
-    app->logSectionStart("Темы оформления");
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Производим поиск доступных тем.");
-    QDir dir(QApplication::applicationDirPath() + "/styles");
-    QStringList skins = dir.entryList(QDir::Dirs | QDir::AllDirs | QDir::NoDotAndDotDot);
-    app->window->ui->skinSelect->addItems(skins);
-    QString skinname = app->config->getValue("Global", "current_theme");
-    app->window->ui->skinSelect->setCurrentText(skinname);
-
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Устанавливаем отметку о файле локализации.");
-    QString file = app->config->getValue("Local", "file");
-    if(file == "client_local_English.dat") app->window->ui->enButton->setEnabled(false);
-    if(file == "client_local_DE.dat") app->window->ui->deButton->setEnabled(false);
-    if(file == "client_local_FR.dat") app->window->ui->frButton->setEnabled(false);
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-    app->logSectionEnd();
-}
-
-QString Helper::getSkinName() {
-    App *app = &App::getInstance();
-    QString skin = app->config->getValue("Global", "current_theme");
-    if(skin == "-1") skin = app->config->getValue("Global", "default_theme");
-    qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Текущая тема оформления: ", app->helper->stringToChar(skin));
-    return skin;
-}
-
-bool Helper::fileExists(QString path) {
-    App *app = &App::getInstance();
-    QFileInfo check_file(path);
-    bool exists = check_file.exists() && check_file.isFile();
-    if(exists == false) qWarning("%s:%i: %s%s", __FILE__, __LINE__, "Файл не найден: ", app->helper->stringToChar(path));
-    return exists;
-}
-
-void Helper::applyShadow(QWidget * obj, QString color, int blur, int offset_x, int offset_y){
-    QGraphicsDropShadowEffect *pLabelTextShadowEffect = new QGraphicsDropShadowEffect(obj);
-    pLabelTextShadowEffect->setColor(QColor(color));
-    pLabelTextShadowEffect->setBlurRadius(blur);
-    pLabelTextShadowEffect->setOffset(offset_x, offset_y);
-    obj->setGraphicsEffect(pLabelTextShadowEffect );
-
-}
-
-void Helper::myDialogBox(QString text, QString info, QString okText, QString cancelText, QString image, QString okAnswer, QString cancelAnswer,
-                        int w, int h, bool textshadow = false, bool is_cancel = false){
-
-    App *app = &App::getInstance();
-
-    if(okAnswer == "") okAnswer = "close";
-    app->helper->dialog_ok_answer = okAnswer;
-    if(cancelAnswer == "") cancelAnswer = "close";
-    app->helper->dialog_cancel_answer = cancelAnswer;
-
-    app->window->ui->okButton->setText(okText);
-    app->window->ui->cancelButton->setText(cancelText);
-    app->window->ui->dialogbox->setGeometry(0, 0, app->window->width(), app->window->height());
-
-    QSettings settings( app->config->getSkinFile(), QSettings::IniFormat );
-    settings.beginGroup("mainWindow");
-    int left = (settings.value("width").toInt() - w)/2;
-    int top = (settings.value("height").toInt() - h)/2;
-    app->window->ui->dialog->setGeometry(QRect(left, top, w, h));
-    settings.endGroup();
-
-    int image_height = app->window->ui->dialog->rect().height() - app->window->ui->dialogHeader->rect().height();
-    app->window->ui->dialogImage->setGeometry(0,
-        app->window->ui->dialogHeader->rect().bottom(),
-        image_height/2 ,image_height
-     );
-
-    QString skin = app->helper->getSkinName();
-    QString iconpath = "";
-    iconpath = app->helper->fileExists("styles/" + skin + "/" + image) ? "styles/" + skin + "/" + image : ":/res/styles/" + skin + "/" + image;
-    QPixmap icon(iconpath);
-
-    app->window->ui->dialogImage->setPixmap(icon.scaled(app->window->ui->dialogImage->width(), app->window->ui->dialogImage->height()));
-    if(icon.isNull()){
-        app->window->ui->dialogImage->setGeometry(QRect(10, 10, 10, 10));
-    }
-
-    app->window->ui->dialogHeader->setGeometry(
-                app->window->ui->dialogHeader->rect().left(),
-                app->window->ui->dialogHeader->rect().top(),
-                app->window->ui->dialog->rect().width(),
-                app->window->ui->dialogHeader->rect().height()
-    );
-
-    app->window->ui->dialogInfo->setGeometry(app->window->ui->dialogImage->rect().right(),
-        app->window->ui->dialogHeader->rect().bottom(),
-         app->window->ui->dialog->rect().width() - app->window->ui->dialogImage->rect().width()-7,
-         image_height - app->window->ui->cancelButton->height()
-     );
-
-
-
-    if(is_cancel){
-       app->window->ui->cancelButton->setGeometry(
-           app->window->ui->dialog->rect().left() + app->window->ui->dialog->width() - app->window->ui->cancelButton->width() - 20,
-           app->window->ui->dialog->rect().bottom() - app->window->ui->cancelButton->height() - 10,
-           app->window->ui->cancelButton->width(),
-           app->window->ui->cancelButton->height()
-        );
-       app->window->ui->okButton->setGeometry(
-           app->window->ui->dialog->rect().left() + app->window->ui->dialog->width() - app->window->ui->cancelButton->width() - app->window->ui->cancelButton->width() - 40,
-           app->window->ui->dialog->rect().bottom() - app->window->ui->cancelButton->height() - 10,
-           app->window->ui->cancelButton->width(),
-           app->window->ui->cancelButton->height()
-        );
-    } else {
-        app->window->ui->cancelButton->setGeometry(-1000,-1000, app->window->ui->cancelButton->width(), app->window->ui->cancelButton->height());
-        app->window->ui->okButton->setGeometry(
-            app->window->ui->dialog->rect().left() + app->window->ui->dialog->width() - app->window->ui->cancelButton->width() - 20,
-            app->window->ui->dialog->rect().bottom() - app->window->ui->cancelButton->height() - 10,
-            app->window->ui->cancelButton->width(),
-            app->window->ui->cancelButton->height()
-         );
-    }
-
-    app->window->ui->dialogHeader->setText(text);
-    app->window->ui->dialogInfo->setText(info);
-    app->window->ui->dialogImage->setText("");
-    app->window->ui->dialogbox->show();
-}
-
-void Helper::setState(QString state){
-    App *app = &App::getInstance();
-    if(state == "busy"){
-        app->window->ui->closeButton->setEnabled(false);
-        app->window->ui->enterButton->setEnabled(false);
-        app->window->ui->lotropathButton->setEnabled(false);
-        app->window->ui->repairButton->setEnabled(false);
-        app->state = "busy";
-        app->window->ui->loader->show();
-    }
-
-    if(state == "free"){
-        app->window->ui->closeButton->setEnabled(true);
-        app->window->ui->enterButton->setEnabled(true);
-        app->window->ui->lotropathButton->setEnabled(true);
-        app->window->ui->repairButton->setEnabled(true);
-        app->state = "free";
-        app->window->ui->loader->hide();
-    }
-
-    if(state == "nofolder"){
-        app->window->ui->enterButton->setEnabled(false);
-        app->state = "nofolder";
-        app->window->ui->loader->hide();
-    }
-
-    if(state == "runfirst"){
-        app->window->ui->enterButton->setEnabled(false);
-        app->window->ui->repairButton->setEnabled(false);
-        app->state = "runfirst";
-        app->window->ui->loader->hide();
-        QString info = "Вы запускаете программу русификации LotRO впервые. Мастер установки поможет вам настроить программу для ее дальнейшего использования. Сейчас будет осуществлена попытка автоматически определить каталог с игрой. Для продолжения нажмите «Далее».";
-        app->helper->myDialogBox("Добро пожаловать!", info, "Далее", "Отмена", "gandalf.png", "close gamefind", "", 400, 200, true, false);
-    }
-}
-
-int Helper::dateToTimestamp(QString customDateString, QString format){
-    int timestamp = QDateTime::fromString(customDateString, format).toTime_t();
-    return timestamp;
-}
-
-void Helper::installMicroPatch(){
-    App *app = &App::getInstance();
-    if(app->config->getValue("Updates", "micro") != "true") return;
-    app->helper->setState("busy");
-    app->window->ui->hintLabel->setText("Установка последних обновлений");
-    app->window->ui->exthintLabel->setText("Идет проверка и установка новых обновлений");
-    QFuture<void> future = QtConcurrent::run([=]() {
-        app->helper->prepareMicroPatch();
-        app->helper->applyMicroPatch();
-        QDir dir("/data/micro");
-        app->helper->clearFolder(dir);
-    });
-    app->window->ui->hintLabel->setText("Установка завершена");
-    app->window->ui->exthintLabel->setText("Обновления успешно установлены");
-    app->helper->setState("free");
-
-}
-
-void Helper::prepareMicroPatch(){
-    App *app = &App::getInstance();
-    app->logSectionStart("Автоматическая проверка обновлений");
-    app->helper->setState("busy");
-    app->window->ui->hintLabel->setText("Загрузка последних обновлений");
-    app->window->ui->exthintLabel->setText("Подождите пока загрузятся последние изменения в системе переводов");
-    QString date = app->config->getValue("Updates", "update");
-
-    if (date == "false" || date == "-1")
-        date = QDate::currentDate().toString("yyyy-MM-dd");
-
-    QTime time = QTime::currentTime();
-    int seconds = QTime(0, 0, 0).secsTo(time);
-    int timestamp = app->helper->dateToTimestamp(date + " " + time.toString("hh:mm:ss"), "yyyy-MM-dd hh:mm:ss") - 2592000;
-
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Опция активна. Начинаем загрузку обновлений");
-    app->network->micropatch = QApplication::applicationDirPath() + "/data/micro/" + QString::number(timestamp + seconds) + ".db";
-    if(!app->helper->fileExists(app->network->micropatch)){
-        qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Файл патча: ", app->helper->stringToChar(app->network->micropatch));
-        app->network->micropatch = app->network->getMicroPath(timestamp);
-    }
-    app->window->ui->hintLabel->setText("Загрузка завершена");
-    app->window->ui->exthintLabel->setText("Все обновления были успешно загружены и доступны к установке");
-
-    app->helper->setState("free");
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-    app->logSectionEnd();
-}
-
-void Helper::applyMicroPatch(){
-    App *app = &App::getInstance();
-    app->logSectionStart("Установка мгновенных обновлений");
-    app->helper->setState("busy");
-    app->window->ui->hintLabel->setText("Установка последних обновлений");
-    app->window->ui->exthintLabel->setText("Подождите пока закончится применение обновлений");
-
-    app->db->InitDatabase(app->helper->stringToChar(app->network->micropatch));
-    int indb = app->db->CountRows();
-    qInfo("%s:%i: %s%d", __FILE__, __LINE__, "Файлов в обновлении: ", indb);
-    for(int i = 0; i<=indb; i++){ processFile(); }
-    //for (int i = 0; i < 5; i++) app->datfiles[i].CommitChanges();
-    app->db->CloseDatabase();
-
-    app->helper->setState("free");
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-    app->logSectionEnd();
-}
-
-void Helper::applyLoadscreens(){
-    App *app = &App::getInstance();
-    app->logSectionStart("Установка заставочных экранов");
-    app->helper->setState("busy");
-
-    QString datafolder = QApplication::applicationDirPath() + "/data";
-    QDir dir(datafolder);
-    if (!dir.exists())
-        return;
-    QStringList paths = dir.entryList(QStringList("loadscreens*"));
-
-    if(!paths.empty()){
-
-        if(paths.first() == app->config->getValue("Applied", "screens")){
-            app->helper->setState("free");
-            return;
-        }
-
-        QString lang = app->config->getValue("Local", "lang");
-        QString folder = app->config->getValue("Local", "folder") + "/raw/" + lang + "/logo/";
-        SubfileData subfile;
-        QStringList filenames;
-        QString mainscreen = lang == "en" ? "lotro_ad_pregame.jpg" : "lotro_ad_pregame_" + lang + ".jpg";
-        filenames << mainscreen << "lotro_generic_teleport_screen_01.jpg" << "lotro_generic_teleport_screen_02.jpg"
-                  << "lotro_generic_teleport_screen_03.jpg" << "lotro_generic_teleport_screen_04.jpg" << "lotro_generic_teleport_screen_05.jpg"
-                  << "lotro_generic_teleport_screen_06.jpg" << "lotro_generic_teleport_screen_07.jpg" << "lotro_generic_teleport_screen_08.jpg"
-                  << "lotro_generic_teleport_screen_09.jpg" << "lotro_generic_teleport_screen_10.jpg";
-
-        QString basename = datafolder + "/" + paths.first();
-        app->db->InitDatabase(basename.toStdString());
-        int indb = app->db->CountRows();
-        qInfo("%s:%i: %s%d", __FILE__, __LINE__, "Файлы загрузочных экранов: ", indb);
-        for(int i = 0; i<indb; i++){
-            subfile = app->db->GetNextFile();
-            qDebug() << i;
-            if (!subfile.Empty()){
-                qInfo("%s:%i: %s", __FILE__, __LINE__, app->helper->stringToChar(folder + filenames[i]));
-                QFile::remove(folder + filenames[i]);
-                subfile.binary_data.WriteToFile((folder + filenames[i]).toStdString());
-            }
-        }
-        app->db->CloseDatabase();
-
-    }
-    app->helper->setState("free");
-    app->window->ui->loadscreensStatus->setText("Готово");
-    app->config->setValue("Applied", "screens", paths.first());
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-    app->logSectionEnd();
-}
-
-void Helper::addComboItem(QComboBox* combo, QString itemName, QIcon* icon){
-    combo->insertItem(0, itemName);
-    combo->setItemIcon(0, *icon);
-}
-
-void Helper::saveLocale(int locale, QPushButton * button){
-    App *app = &App::getInstance();
-    QString file;
-
-    if(locale == 0) file = "client_local_English.dat";
-    if(locale == 1) file = "client_local_DE.dat";
-    if(locale == 2) file = "client_local_FR.dat";
-    if(app->helper->fileExists(app->config->getValue("Local", "folder") + "/" + file)){
-        app->window->ui->enButton->setEnabled(true);
-        app->window->ui->deButton->setEnabled(true);
-        app->window->ui->frButton->setEnabled(true);
-        button->setEnabled(false);
-        app->config->setValue("Local", "file", file);
-    } else {
-        QString text = "Данная локализация отсутствует";
-        QString info = "В настоящий момент вы не можете выбрать данную опцию, поскольку файл " + file + " отсутствует в вашем игровом клиенте. Чтобы скачать его, запустите официальный лаунчер, выберите желаемый язык в верхней правой части окна и дождитесь, когда загрузка необходимых файлов завершится.";
-        app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "", "", 400, 220, true, false);
-    }
-}
-
-bool Helper::setGameLocale(QString locale){
-    App *app = &App::getInstance();
-    app->window->ui->goHint->show();
-    app->helper->setState("busy");
-    app->window->ui->goLocal->setEnabled(false);
-    app->window->ui->goOriginal->setEnabled(false);
-    app->window->ui->goCancel->setEnabled(false);
-
-    if(app->helper->openDatFile(0)){
-        LOCALE loc = app->datfiles[0].current_locale();
-        dat_locale = loc;
-
-        if(loc == PATCHED) qDebug() << "Starting " + locale + " version. Current locale is PATCHED";
-        if(loc == ORIGINAL) qDebug() << "Starting " + locale + " version. Current locale is ORIGINAL";
-        if(loc != ORIGINAL && loc != PATCHED) qDebug() << "Starting " + locale + " version. Current locale is UNKNOWN";
-
-        if(locale == "RU" && loc != PATCHED){ qDebug()<< "Current locale Original"; app->datfiles[0].SetLocale(PATCHED); dat_locale = PATCHED;}
-        if(locale == "Original" && loc != ORIGINAL){ qDebug()<< "Current locale RU"; app->datfiles[0].SetLocale(ORIGINAL); dat_locale = ORIGINAL;}
-        app->helper->closeDatFile(0);
-    }
-
-    app->window->ui->goHint->hide();
-    app->window->ui->goProgress->hide();
-    app->window->ui->startbox->hide();
-    app->window->ui->goLocal->setEnabled(true);
-    app->window->ui->goOriginal->setEnabled(true);
-    app->window->ui->goCancel->setEnabled(true);
-    app->helper->setState("free");
-    qDebug() << "Locale changed";
-
-    return true;
-}
-
-void Helper::startGame(){
-    App *app = &App::getInstance();
-    app->config->saveAllDatFiles();
-    QStringList args;
-    args << "-skiprawdownload" << "-nosplash";
-    if (dat_locale == PATCHED)
-        args << "-disablePatch";
-
-    QFile f(app->config->getValue("Local", "folder") + "/TurbineLauncher.exe");
-    QProcess process;
-    if(fileExists(f.fileName())){
-        if(f.fileName().contains(" ")) f.setFileName("\"" + f.fileName() + "\"");
-        process.startDetached(f.fileName(), args);
-        process.waitForFinished(-1);
-        process.deleteLater();
-        QApplication::quit();
-    } else {
-        QString text = "Запуск не удался";
-        QString info = "Не удалось запустить игру. Во время запуска произшла непредвиденная ошибка (возможно, не найден файл TurbineLauncher.exe в папке с игрой. Проверьте в 'Настройках', что у вас указан верный путь к игре, и повторите попытку запуска).";
-        app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "", "", 400, 160, true, false);
-    }
-}
-
-bool Helper::openDatFile(int id){
-    App *app = &App::getInstance();
-    QStringList dat_files;
-    dat_files << app->config->getValue("Local", "file") << "client_general.dat" << "client_sound.dat" << "client_surface.dat" << "client_highres.dat";
-    if(dat_files[id] != nullptr) {
-        qDebug() << dat_files[id];
-        const char * filename = app->helper->stringToChar(app->config->getValue("Local", "folder") + "/" + dat_files[id]);
-        std::string file = app->config->getDatPath(0);
-        qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Инициализация dat-файла. Открываем файл ", filename);
-        int dat_state = app->datfiles[id].InitDatFile(file, 0);
-        qDebug("%s:%i: %s%d", __FILE__, __LINE__, "Состояние dat-файла: ", dat_state);
-        if(dat_state > 0){
-            app->helper->setState("busy");
-            return true;
-        } else {
-            QString text = "Нет доступа к  файлам игры";
-            QString info = "Возможно в данный момент запущены клиент или лаунчер игры либо попытка доступа блокируется настройкой прав, антивирусом или другими приложениями. Завершите все процессы, использующие файлы игры и повторите попытку.";
-            app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "", "", 550, 200, true, false);
-            app->helper->setState("free");
-            return false;
-        }
-    }
-    return true;
-}
-
-void Helper::closeDatFile(int id){
-    App *app = &App::getInstance();
-    //app->datfiles[id].CommitChanges();
-    app->datfiles[id].CloseDatFile();
-    app->helper->setState("free");
-}
-
-const char * Helper::stringToChar(QString val){
-    ba = val.toLocal8Bit();
-    const char * result = ba.data();
-    return result;
-}
-
-void Helper::applyPatch(QString name){
-    App *app = &App::getInstance();
-    app->window->ui->hintLabel->setText("Установка патчей");
-    app->window->ui->exthintLabel->setText("Ожидайте. Идет установка выбранных патчей");
-    qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Начинаем применение патча ", app->helper->stringToChar(name));
-    QLabel* label = app->window->findChild<QLabel*>(name + "Status");
-    QDir dir(QApplication::applicationDirPath() + "/data");
-    if (!dir.exists()) {
-        app->window->ui->hintLabel->setText("Установка патчей завершена с ошибкой");
-        app->window->ui->exthintLabel->setText("Ошибка - не найдена папка data");
-        return;
-    }
-
-    QStringList paths = dir.entryList(QStringList(name + "*"));
-    qDebug() << app->helper->stringToChar("data/" + paths.first());
-    if(!paths.empty()){         
-       app->db->InitDatabase(app->helper->stringToChar("data/" + paths.first()));
-        int indb = app->db->CountRows();
-        qInfo("%s:%i: %s%d", __FILE__, __LINE__, "Файлов в обновлении: ", indb);
-        for(int i = 0; i<=indb; i++){
-            processFile();
-            if(label != nullptr) label->setText("Применение ... " + QString::fromLatin1("%1").arg(i*100/indb, 3, 'f', 1) + "%");
-        }
-        if(label != nullptr)label->setText("Готово");
-        //for (int i = 0; i < 5; i++) app->datfiles[i].CommitChanges();
-        app->config->setValue("Applied", name, paths.first());
-        app->db->CloseDatabase();
-    }
-    app->window->ui->hintLabel->setText("Установка патчей завершена");
-    app->window->ui->exthintLabel->setText("Применение выбранных вами патчей закончено");
-}
-
-void Helper::processFile(){
-    App *app = &App::getInstance();
-    SubfileData subfile;
-    subfile = app->db->GetNextFile();
-    if (subfile.Empty()){
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Достигнут конец файла.");
-    } else {
-        int dat_id = subfile.options["did"].as<int>();
-        int dat_state = app->datfiles[dat_id].InitDatFile(app->config->getDatPath(dat_id), dat_id);
-        //qDebug("%s:%i: %s%d", __FILE__, __LINE__, "Состояние dat-файла: ", dat_state);
-        if(dat_state > 0) app->datfiles[dat_id].PatchFile(subfile);
-    }
-}
-
-void Helper::applyGlobal(){
-    App *app = &App::getInstance();
-
-    // Применяем патч с заставочными экранами
-    if(app->config->getValue("Editor", "screens") == "true"){
-        app->helper->applyLoadscreens();
-    } else {
-        QString dateline = app->config->getValue("Datetime", "loadscreens");
-        if(dateline != "-1"){
-            QStringList date = dateline.split(" ");
-            app->window->ui->loadscreensStatus->setText(date[0]);
-        }
-    }
-
-    // Применяем остальные патчи
-    QStringList names;
-    QStringList need;
-    QFuture<void> f;
-    f = QtConcurrent::run([=]() {});
-    names  << "fonts" << "sounds" << "texts" << "images" << "videos" << "textures";
-    QDir dir(QApplication::applicationDirPath() + "/data");
-
-    foreach(QString name, names){
-        QStringList list = dir.entryList(QStringList(name + "*"));
-        if(list.size() > 0 && list.first() != ""){
-            QString isset = app->config->getValue("Applied", name);
-            if(list.first() != isset && app->config->getValue("Editor", name) == "true"){ need.append(name); }
-        }
-    }
-    Helper *helper = new Helper();
-    QFutureWatcher<void> * watcher = new QFutureWatcher<void>();
-    connect(watcher, SIGNAL(finished()), helper, SLOT(handleFinisheddd()));
-    if(need.size() > 0){
-        watcher->setFuture(QtConcurrent::run([=]() {
-            if(app->helper->openDatFile(0)){
-                foreach(QString name, need){ app->helper->applyPatch(name);}
-                app->helper->closeDatFile(0);
-            }
-        }));
-    } else {
-        app->helper->installMicroPatch();
-    }
-
-}
-
-void Helper::handleFinisheddd(){
-   App *app = &App::getInstance();
-   app->helper->installMicroPatch();
-}
-
-bool Helper::isDatReady(){
-    App *app = &App::getInstance();
-    bool free;
-    QString dir = app->config->getValue("Local", "folder");
-    QString file = app->config->getValue("Local", "file");
-    QFile fl(dir+"/" + file);
-    qDebug() << fl.fileName();
-    if(app->helper->fileExists(fl.fileName())){
-        QDir game_dir(dir);
-        free = game_dir.rename(fl.fileName(), fl.fileName() + "99");
-        game_dir.rename(fl.fileName() + "99", fl.fileName());
-    } else {
-        free = false;
-    }
-    if(free == true) qDebug() << "Dat is FREE"; else qDebug() << "Dat is BUSY";
-    return free;
-}
-
-void Helper::replaceSkin(QString name){
-    App *app = &App::getInstance();
-    QString text = "Смена темы оформления";
-    QString info = "Выбрана тема " + name + ". Изменения вступят в силу при следующем запуске лаунчера.";
-    //app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "", "", 400, 120, true, false);
-
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Оформляем главное окно.");
-
-    QFile styleF;
-    QString skin = app->helper->getSkinName();
-    styleF.setFileName(app->app_folder + "styles/" + name + "/style.css");
-    styleF.open(QFile::ReadOnly);
-    QString qssStr = styleF.readAll();
-
-    qApp->setStyleSheet(qssStr);
-
-    QPixmap maskPix(":/res/styles/" + name + "/bg.png");
-    QPixmap maskPixLocal(app->app_folder + "styles/" + name + "/bg.png");
-    maskPix = maskPix.isNull() ? maskPixLocal : maskPix;
-    app->window->setMask(maskPix.mask());
-
-    QString color = app->helper->htmlColors.contains("a") ? app->helper->htmlColors.lowerBound("a").value() : "blue";
-    app->config->loadSkin();
-    QString hrefcolor = app->helper->htmlColors.contains("a") ? app->helper->htmlColors.lowerBound("a").value() : "blue";
-
-    QString newtext = app->window->ui->news1Title->text().replace(color, hrefcolor);
-    app->window->ui->news1Title->setText(newtext);
-
-    newtext = app->window->ui->news2Title->text().replace(color, hrefcolor);
-    app->window->ui->news2Title->setText(newtext);
-
-    newtext = app->window->ui->news3Title->text().replace(color, hrefcolor);
-    app->window->ui->news3Title->setText(newtext);
-
-    newtext = app->window->ui->news4Title->text().replace(color, hrefcolor);
-    app->window->ui->news4Title->setText(newtext);
-
-    app->helper->loadHelp();
-
-    QMovie * movie = new QMovie(":/res/styles/" + skin + "/loader.gif");
-    if(!movie->isValid()) movie = new QMovie(app->app_folder + "styles/" + skin + "/loader.gif");
-    app->window->ui->loader->setMovie(movie);
-    movie->setScaledSize(QSize(app->window->ui->loader->width(), app->window->ui->loader->height()));
-    movie->start();
-}
-
-void Helper::checkDatFile(){
-    //bool CheckIfUpdatedByGame(); // Обновлялся ли игрой
-    //bool CheckIfNotPatched(); // Был ли хоть раз пропатчен новым лаунчером
-    //bool CheckIfPatchedByOldLauncher(); // Был ли хоть раз пропатчен старым лаунчером
-
-    App *app = &App::getInstance();
-    app->helper->openDatFile(0);
-    if(app->datfiles[0].CheckIfUpdatedByGame()){
-        app->ready = false;
-        QString text = "Файлы локализации изменены";
-        QString info = "В процессе последнего запуска игры были установлены обновления игрового клиента. Это могло затронуть файлы локализации. Желаете провести проверку и исправить поврежденные участки перевода? Вы можете в любой момент сделать это самостоятельно, нажав кнопку «Применить патчи заново».";
-        app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "applypaths", "", 400, 220, true, true);
-    }
-
-    if(app->datfiles[0].CheckIfNotPatched() && app->config->getValue("Local", "runfirst") == "1"){
-        app->ready = false;
-        QString text = "Файлы локализации отсутствуют";
-        QString info = "Текущий файл локализации не содержит патчей. Возможно это первый запуск «Наследия» с данным игровым клиентом, или клиент был обновлён игровым лаунчером. Применить выбранные патчи в данному файлу?";
-        app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "applypaths", "", 420, 200, true, true);
-    }
-
-    if(app->datfiles[0].CheckIfPatchedByOldLauncher()){
-        QString text = "Файлы локализации не являются оригинальными";
-        QString info = "Внимание! Присутствующие в вашем игровом клиенте файлы локализации не являются оригинальными, поскольку были модифицированы другой программой.<br/><strong>Мы настоятельно рекомендуем перекачать оригинальные версии файлов, поскольку правильная работа Наследия с данными файлами не гарантируется!</strong>";
-        app->helper->myDialogBox(text, info, "Перекачать", "Не надо", "gandalf.png", "loaddatfile", "", 550, 200, true, true);
-    }
-}
-
-void Helper::clearFolder(QDir &dir){
-    //Получаем список файлов
-    QStringList lstFiles = dir.entryList(QDir::Files);
-
-    //Удаляем файлы
-    foreach (QString entry, lstFiles){
-        QString entryAbsPath = dir.absolutePath() + "/" + entry;
-        //QFile::setPermissions(entryAbsPath, QFile::ReadOwner | QFile::WriteOwner);
-        qDebug() << dir.absolutePath();
-        QFile::remove(entryAbsPath);
-    }
-}

+ 0 - 66
helper.h

@@ -1,66 +0,0 @@
-#ifndef HELPER_H
-#define HELPER_H
-
-#include <QString>
-#include <QObject>
-#include <QMap>
-#include <QDir>
-#include <QPushButton>
-#include <QComboBox>
-#include <QCryptographicHash>
-#include "LotroDat.h"
-
-class Helper:public QObject {
-    Q_OBJECT
-   public:
-    Helper();
-    Helper( const Helper&);
-    Helper& operator=( Helper& );
-    int getVersion(QString string);
-    QMap <QString, QString> getPathsMap();
-    QMap <QString, QString> htmlColors;
-
-    void checkTab(QString tabname);
-    bool fileExists(QString path);
-    void loadNews();
-    void loadHelp();
-    void hideAll();
-    void setAbout();
-    void findSkins();
-    void prepareMicroPatch();
-    void saveLocale(int locale, QPushButton *button);
-    QString getSkinName();
-    void setState(QString state);
-    void applyShadow(QWidget *obj, QString color, int blur, int offset_x, int offset_y);
-    void myDialogBox(QString text, QString info, QString okText, QString cancelText, QString image,
-                   QString okAnswer, QString cancelAnswer, int w, int h, bool textshadow, bool is_cancel);
-    QString fileHash(const QString &fileName, QCryptographicHash::Algorithm hashAlgorithm);
-    int dateToTimestamp(QString customDateString, QString format);
-    void addComboItem(QComboBox* combo, QString itemName, QIcon* icon);
-    bool setGameLocale(QString locale);
-    void startGame();
-
-    bool openDatFile(int id);
-    void closeDatFile(int id);
-    void applyPatch(QString name);
-    void processFile();
-    const char *stringToChar(QString val);
-    void applyGlobal();
-    bool isDatReady();
-    void replaceSkin(QString name);
-    void applyMicroPatch();
-    void installMicroPatch();
-    void applyLoadscreens();
-    void checkDatFile();
-    void clearFolder(QDir &dir);
-    QByteArray ba;
-    QString dialog_ok_answer;
-    QString dialog_cancel_answer;
-    LOTRO_DAT::LOCALE dat_locale;
-
-private slots:
-    void handleFinisheddd();
-};
-
-
-#endif // HELPER_H

+ 21 - 18
main.cpp

@@ -1,15 +1,22 @@
-#include "app.h"
+#include "mainwindow.h"
+#include "skin.h"
+
 #include <QApplication>
 #include <QFile>
 #include <QTextCodec>
 #include <QLockFile>
 #include <QtGlobal>
 #include <QtGlobal>
-#include <stdio.h>
-#include <stdlib.h>
-
+#include <QMessageBox>
 #include <QThread>
 #include <QtConcurrent/QtConcurrentRun>
+#include <QDir>
+#include <QString>
+#include <QDate>
+#include <QtMessageHandler>
+
+#include <stdio.h>
+#include <stdlib.h>
 
 void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
 {
@@ -33,17 +40,18 @@ void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QS
         abort();
     }
 }
+
 int main(int argc, char *argv[]){
     //if (argc <= 1 || (argc > 1 && std::string(argv[1]) != std::string("-S") && std::string(argv[1]) != "-prelaunched"))
     //    return 0;
 
     freopen("log.txt", "w", stdout);
-    freopen("log.txt", "w", stderr);
+    freopen("log.txt", "a", stderr);
 
     // if it's later than 25.02.2018 - return. That's for temporary version
-    long long cur_time = time(0);
-    if (cur_time >= 1520629200)
-        return 0;
+    //long long cur_time = time(0);
+    //if (cur_time >= 1520629200)
+    //    return 0;
 
     setbuf(stdout, NULL);
     setbuf(stderr, NULL);
@@ -62,24 +70,19 @@ int main(int argc, char *argv[]){
         return 1;
     }
 
-    MainWindow w;
-    App *app = &App::getInstance();
-
-    app->logSectionStart("Начинаем работать");
+    MainWindow::getInstance()->show();
 
     QFile styleF;
-    QString skin = app->helper->getSkinName();
-    styleF.setFileName(app->app_folder + "styles/" + skin + "/style.css");
+    QString skin = Skin::getInstance()->getSkinName();
+    styleF.setFileName(QApplication::applicationDirPath() + "styles/" + skin + "/style.css");
     styleF.open(QFile::ReadOnly);
     QString qssStr = styleF.readAll();
 
     qApp->setStyleSheet(qssStr);
 
-    w.show();
-    w.doStartPreparations();
-    //QFuture<void> future = QtConcurrent::run(w, &MainWindow::doStartPreparations);
-    auto result = a.exec();
+    MainWindow::getInstance()->show();
 
+    auto result = a.exec();
     lockFile.unlock();
     return result;
 }

+ 402 - 217
mainwindow.cpp

@@ -1,95 +1,207 @@
-#include "app.h"
+#include "mainwindow.h"
 
-App *App::instance;
+#include "filesystem.h"
+#include "aconfig.h"
+#include "anetwork.h"
+#include "gameres.h"
+#include "downloadmanager.h"
+#include "skin.h"
 
 #include <QBitmap>
+#include <QMovie>
+#include <QGraphicsDropShadowEffect>
+#include <QCloseEvent>
+#include <QClipboard>
+#include <QFileDialog>
+
+MainWindow::MainWindow( QMainWindow* parent )
+    : QMainWindow(parent, Qt::Window | Qt::FramelessWindowHint)
+    , ui(new Ui::MainWindow)
+    , dx(0)
+    , dy(0) {
 
-MainWindow::MainWindow( QMainWindow* parent ) :
-    QMainWindow( parent, Qt::Window | Qt::FramelessWindowHint ),
-    ui( new Ui::MainWindow ), dx( 0 ), dy( 0 ) {
     ui->setupUi(this);
 
-    App *app = &App::getInstance();
-    if(!app->helper->fileExists(QApplication::applicationDirPath() + "/settings.ini")) app->config->saveConfig();
-    QString skin = app->helper->getSkinName();
+    if(!FileSystem::fileExists(QApplication::applicationDirPath() + "/settings.ini"))
+        AConfig::getInstance()->saveConfig();
+
+    QString skin = Skin::getInstance()->getSkinName();
     setWindowIcon(QIcon(":/res/styles/" + skin + "/icon6.png"));
     QCoreApplication::setOrganizationName(ORGANIZATION_NAME);
     QCoreApplication::setOrganizationDomain(ORGANIZATION_DOMAIN);
     QCoreApplication::setApplicationName(APPLICATION_NAME);
-    setWindowTitle("Русификация LOTRO");
-
-    app->logSectionEnd();
+    setWindowTitle("ВКО: Наследие");
+    show();
 
     // Проводим подготовку к запуску
-    app->window = this;
-    app->config->loadConfig();
-    app->config->loadSkin();
-    app->helper->hideAll();
-    app->helper->loadNews();
-    app->network->getFootMessage();
-    app->network->getServers();
-    app->network->getCoupon();
-    app->helper->loadHelp();
-    app->helper->setAbout();
-    app->helper->findSkins();
+    loadConfig();
+    Skin::getInstance()->loadSkin();
+    loadNews();
+
+    ANetwork::getInstance()->getFootMessage();
+    ANetwork::getInstance()->getServers();
+    ANetwork::getInstance()->getCoupon();
+
+    loadHelp();
+    setAbout();
+    Skin::getInstance()->findSkins();
     //app->helper->setPatchsDates();
 
-    app->logSectionStart("Запуск Наследия");
     qInfo("%s:%i: %s", __FILE__, __LINE__, "Оформляем главное окно.");
     QPixmap maskPix(":/res/styles/" + skin + "/bg.png");
-    QPixmap maskPixLocal(app->app_folder + "styles/" + skin + "/bg.png");
+    QPixmap maskPixLocal(QApplication::applicationDirPath() + "styles/" + skin + "/bg.png");
     maskPix = maskPix.isNull() ? maskPixLocal : maskPix;
     this->setMask(maskPix.mask());
 
     qInfo("%s:%i: %s", __FILE__, __LINE__, "Устанавливаем анимации.");
     QMovie * movie = new QMovie(":/res/styles/" + skin + "/loader.gif");
-    if(!movie->isValid()) movie = new QMovie(app->app_folder + "styles/" + skin + "/loader.gif");
+
     ui->loader->setMovie(movie);
     movie->setScaledSize(QSize(ui->loader->width(), ui->loader->height()));
     movie->start();
 
-    connect(app->window->ui->skinSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(saveSkin()));
+    connect(ui->skinSelect, SIGNAL(currentIndexChanged(int)), this, SLOT(saveSkin()));
+}
 
-    app->state = "busy";
+void MainWindow::addComboItem(QComboBox* combo, QString itemName, QIcon* icon){
+    combo->insertItem(0, itemName);
+    combo->setItemIcon(0, *icon);
 }
 
-void MainWindow::doStartPreparations() {
-    App *app = &App::getInstance();
-    // Проверяем файл локализации
-    app->helper->checkDatFile();
+void MainWindow::saveLocale(int locale, QPushButton * button){
+    QString file;
 
-    app->state = "free";
+    if(locale == 0) file = "client_local_English.dat";
+    if(locale == 1) file = "client_local_DE.dat";
+    if(locale == 2) file = "client_local_FR.dat";
 
-    // Если это первый запуск то показываем мастер
-    if(app->config->getValue("Local", "runfirst") == "-1"){
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Показываем мастер начальных настроек.");
-        app->helper->setState("runfirst");
+    if(FileSystem::fileExists(AConfig::getInstance()->getValue("Local", "folder") + "/" + file)){
+        ui->enButton->setEnabled(true);
+        ui->deButton->setEnabled(true);
+        ui->frButton->setEnabled(true);
+        button->setEnabled(false);
+        AConfig::getInstance()->setValue("Local", "file", file);
     } else {
-        app->helper->setState("free");
+        QString text = "Данная локализация отсутствует";
+        QString info = "В настоящий момент вы не можете выбрать данную опцию, поскольку файл " + file + " отсутствует в вашем игровом клиенте. Чтобы скачать его, запустите официальный лаунчер, выберите желаемый язык в верхней правой части окна и дождитесь, когда загрузка необходимых файлов завершится.";
+        myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "", "", 400, 220, true, false);
+    }
+}
+
+void MainWindow::loadConfig() {
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Находим каталог с игрой");
+        ui->lotropathLabel->setText(AConfig::getInstance()->getValue("Local", "folder") != "-1" ? AConfig::getInstance()->getValue("Local", "folder") : "Выберите папку с игрой");
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Проверяем активность патча \"Шрифты\"");
+        ui->checkFonts->setChecked(AConfig::getInstance()->getValue("Editor", "fonts") == "true" ? true : false);
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Проверяем активность патча \"Тексты\"");
+        ui->checkTexts->setChecked(AConfig::getInstance()->getValue("Editor", "texts")== "true" ? true : false);
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Проверяем активность патча \"Карты\"");
+        ui->checkMaps->setChecked(AConfig::getInstance()->getValue("Editor", "images") == "true" ? true : false);
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Проверяем активность патча \"Звуки\"");
+        ui->checkSounds->setChecked(AConfig::getInstance()->getValue("Editor", "sounds")== "true" ? true : false);
+
+        ui->checkVideos->setChecked(AConfig::getInstance()->getValue("Editor", "videos") == "true" ? true : false);
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Проверяем активность патча \"Заставки\"");
+        ui->checkScreens->setChecked(AConfig::getInstance()->getValue("Editor", "screens")== "true" ? true : false);
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Проверяем активность микрообновлений");
+        ui->checkMicro->setChecked(AConfig::getInstance()->getValue("Updates", "micro")== "true" ? true : false);
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
+}
+
+void MainWindow::loadNews(){
+    qInfo("Загружаем скин лаунчера");
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Загрузка новостей с сайта");
+    QString response = ANetwork::getInstance()->query(AConfig::getInstance()->getValue("Network", "news"));
+
+    if (response == "error"){
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Отсутствует связь с сервером. Прервано.");
+        return;
+    }
+
+    QStringList data = response.split(":::");
+    qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Получено новостей - ", QString::number(data.count()).toStdString().c_str());
+    int counter = 1;
+
+    foreach(QString news, data){
+        qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Начинаем размещение новости №", QString::number(counter).toStdString().c_str());
+
+        QStringList item = news.split("|");
+        QLabel* image = ui->newsbox->findChild<QLabel*>("news" + QString::number(counter) + "Image");
+        QLabel* title = ui->newsbox->findChild<QLabel*>("news" + QString::number(counter) + "Title");
+        QLabel* teaser = ui->newsbox->findChild<QLabel*>("news" + QString::number(counter) + "Teaser");
+
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Устанавливаем миниатюру новости");
+        QByteArray bytes = ANetwork::getInstance()->query_binary(item[0]);
+        QImage img(36, 36, QImage::Format_Indexed8);
+        img.loadFromData(bytes);
+
+        QString skin = Skin::getInstance()->getSkinName();
+
+        if(img.bits() == nullptr){
+            qInfo("%s:%i: %s", __FILE__, __LINE__, "Миниатюра не найдена, устанавливаем заглушку");
+            img.load(":/res/styles/" + skin + "/nophoto.jpg");
+        }
+
+        image->setPixmap(QPixmap::fromImage(img));
+
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Применяем HTML-цвета");
+        QString hrefcolor = htmlColors.contains("a") ? htmlColors.lowerBound("a").value() : "blue";
+        QString html = "<a href=\"" + item[3] +"\" style=\"color:" + hrefcolor + "; text-decoration:none;\">" + item[1] + "</a>";
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Размещаем тексты");
+        title->setText(html);
+        teaser->setText(item[2]);
+        counter = counter + 1;
     }
     qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-    app->logSectionEnd();
+}
+
+void MainWindow::loadHelp(){
+    qInfo("Создание справки");
+    QFile file(QApplication::applicationDirPath() + "/readme.html");
 
+    if(file.open(QFile::ReadOnly | QFile::Text)){
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Справка загружена. Устанавливаем HTML-цвета и выводим.");
+        ui->textBrowser->setHtml("");
+        QString content = file.readAll();
 
-    // Если приготовления выполнены загружаем патчи
-    if(app->state == "free" && app->ready == true){
-        app->logSectionStart("Загрузка патчей");
-        //for (int i = 0; i < 5; i++) app->datfiles[i].CommitChanges();
-        app->network->getPaths();
+        stylehtml = "<style>";
+        for(auto e : htmlColors.keys()){
+            stylehtml = stylehtml + e + "{color:" + htmlColors.value(e) + ";}";
+        }
+
+
+        QFile styleF;
+        QString skin = Skin::getInstance()->getSkinName();
+        styleF.setFileName(QApplication::applicationDirPath() + "styles/" + skin + "/readme.css");
+        if(styleF.open(QFile::ReadOnly)){
+           stylehtml = "<html><head><style type=\"text/css\">" + stylehtml + styleF.readAll();
+        }
+
+        stylehtml = stylehtml + "</style></head>";
+
+        ui->textBrowser->setHtml(stylehtml + content);
+        ui->textBrowser->document()->setDefaultStyleSheet(styleF.readAll());
+        qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
+    } else {
+        qWarning("%s:%i: %s", __FILE__, __LINE__, "Не удалось получить информацию с сервера");
         qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-        app->logSectionEnd();
     }
 }
 
-MainWindow::~MainWindow()
-{
+MainWindow::~MainWindow() {
     delete ui;
 }
 
-void MainWindow::closeEvent(QCloseEvent *e){
-    App *app = &App::getInstance();
-    if(app->state == "busy") e->ignore();
+void MainWindow::applyShadow(QWidget * obj, QString color, int blur, int offset_x, int offset_y){
+    QGraphicsDropShadowEffect *pLabelTextShadowEffect = new QGraphicsDropShadowEffect(obj);
+    pLabelTextShadowEffect->setColor(QColor(color));
+    pLabelTextShadowEffect->setBlurRadius(blur);
+    pLabelTextShadowEffect->setOffset(offset_x, offset_y);
+    obj->setGraphicsEffect(pLabelTextShadowEffect);
+}
 
+void MainWindow::closeEvent(QCloseEvent *e) {
+    if (state == "busy") e->ignore();
 }
 
 void MainWindow::mouseMoveEvent( QMouseEvent* e ) {
@@ -131,8 +243,7 @@ void MainWindow::minimize() {
 }
 
 bool MainWindow::eventFilter(QObject *obj, QEvent *event){
-    App *app = &App::getInstance();
-    if(app->state == "busy") return false;
+    if(state == "busy") return false;
 
     if(obj->objectName() == "mainButton"){
         this->ui->hintLabel->setText("Применение патчей");
@@ -166,74 +277,69 @@ bool MainWindow::eventFilter(QObject *obj, QEvent *event){
 }
 
 void MainWindow::on_mainButton_clicked(){
-    App *app = &App::getInstance();
-    app->helper->checkTab("mainbox");
-    app->window->ui->titleLabel->setText("Патчи");
-    if(app->state != "busy") app->network->getPaths();
+    checkTab("mainbox");
+    ui->titleLabel->setText("Патчи");
+    if(state != "busy") ANetwork::getInstance()->getPatches();
 }
 
 void MainWindow::on_optButton_clicked(){
-    App *app = &App::getInstance();
-    app->helper->checkTab("optbox");
-    app->window->ui->titleLabel->setText("Настройки");
+    checkTab("optbox");
+    ui->titleLabel->setText("Настройки");
 }
 
 void MainWindow::on_newsButton_clicked(){
-    App *app = &App::getInstance();
-    app->helper->checkTab("newsbox");
-    app->window->ui->titleLabel->setText("Новости");
+    checkTab("newsbox");
+    ui->titleLabel->setText("Новости");
 }
 
 void MainWindow::on_helpButton_clicked(){
-    App *app = &App::getInstance();
-    app->helper->checkTab("helpbox");
-    app->window->ui->titleLabel->setText("Справка");
+    checkTab("helpbox");
+    ui->titleLabel->setText("Справка");
 }
 
 void MainWindow::on_aboutButton_clicked(){
-    App *app = &App::getInstance();
-    app->helper->checkTab("aboutbox");
-    app->window->ui->titleLabel->setText("О нас");
+    checkTab("aboutbox");
+    ui->titleLabel->setText("О нас");
 }
 
 void MainWindow::on_enterButton_clicked(){
-    App *app = &App::getInstance();
-    app->window->ui->startbox->setGeometry(0, 0, app->window->width(), app->window->height());
-    QSettings settings( app->config->getSkinFile(), QSettings::IniFormat );
+    ui->startbox->setGeometry(0, 0, width(), height());
+    QSettings settings(Skin::getInstance()->getSkinFile(), QSettings::IniFormat);
 
     settings.beginGroup("mainWindow");
-    int left = (settings.value("width").toInt() - app->window->ui->startframe->width())/2;
-    int top = (settings.value("height").toInt() - app->window->ui->startframe->height())/2;
-    app->window->ui->startframe->setGeometry(QRect(left, top, app->window->ui->startframe->width(), app->window->ui->startframe->height()));
+    int left = (settings.value("width").toInt() - ui->startframe->width())/2;
+    int top = (settings.value("height").toInt() - ui->startframe->height())/2;
+    ui->startframe->setGeometry(QRect(left, top, ui->startframe->width(), ui->startframe->height()));
     settings.endGroup();
-    QString file = app->config->getValue("Local", "file");
-    if(file == "client_local_English.dat") file = "goenr.png";
-    if(file == "client_local_DE.dat") file = "goderr.png";
-    if(file == "client_local_FR.dat") file = "gofrr.png";
 
-    QString skin = app->config->getSkinName();
+    QString file = AConfig::getInstance()->getValue("Local", "file");
+
+    if (file == "client_local_English.dat") file = "goenr.png";
+    if (file == "client_local_DE.dat") file = "goderr.png";
+    if (file == "client_local_FR.dat") file = "gofrr.png";
+
+    QString skin = Skin::getInstance()->getSkinName();
     QString bname = ":/res/styles/" + skin + "/" + file;
     QPixmap isset(bname);
-    bname = isset.isNull() ? app->app_folder + "styles/" + skin + "/" + file : bname;
-    app->window->ui->goOriginal->setStyleSheet("QPushButton#goOriginal { border-image: url(" + bname + ") 0 0 0 0 stretch stretch;}");
-
-    app->window->ui->startbox->show();
+    bname = isset.isNull() ? app_folder + "styles/" + skin + "/" + file : bname;
+    ui->goOriginal->setStyleSheet("QPushButton#goOriginal { border-image: url(" + bname + ") 0 0 0 0 stretch stretch;}");
+    ui->startbox->show();
 }
 
 void MainWindow::on_goCancel_clicked(){
-    this->ui->startbox->hide();
+    ui->startbox->hide();
 }
 
 void MainWindow::on_goOriginal_clicked(){
-    App *app = &App::getInstance();
-    app->window->ui->goProgress->show();
-    QtConcurrent::run([=]() { app->helper->setGameLocale("Original"); app->helper->startGame(); });
+    ui->goProgress->show();
+    GameRes::getInstance()->setGameLocale("Original");
+    //connect(GameRes::getInstance(), SIGNAL(GameRes::getInstance()->setGameLocaleFinished()), GameRes::getInstance(), SLOT(GameRes::getInstance()->startGame()));
 }
 
 void MainWindow::on_goLocal_clicked(){
-    App *app = &App::getInstance();
-    app->window->ui->goProgress->show();
-    QtConcurrent::run([=]() { if(app->helper->setGameLocale("RU")) app->helper->startGame(); });
+    ui->goProgress->show();
+    GameRes::getInstance()->setGameLocale("RU");
+    //connect(GameRes::getInstance(), SIGNAL(GameRes::getInstance()->setGameLocaleFinished()), GameRes::getInstance(), SLOT(GameRes::getInstance()->startGame()));
 }
 
 void MainWindow::on_minimizeButton_clicked(){
@@ -245,203 +351,282 @@ void MainWindow::on_closeButton_clicked(){
 }
 
 void MainWindow::on_couponButton_clicked(){
-    App *app = &App::getInstance();
-    QApplication::clipboard()->setText(app->window->ui->couponButton->text());
-    this->ui->exthintLabel->setText("Код скопирован.");
+    QApplication::clipboard()->setText(ui->couponButton->text());
+    ui->exthintLabel->setText("Код скопирован.");
 }
 
 void MainWindow::on_enButton_clicked(){
-    App *app = &App::getInstance();
-    app->helper->saveLocale(0, this->ui->enButton);
-    app->config->setValue("Local", "lang", "en");
+    saveLocale(0, ui->enButton);
+    AConfig::getInstance()->setValue("Local", "lang", "en");
 }
 
 void MainWindow::on_deButton_clicked(){
-    App *app = &App::getInstance();
-    app->helper->saveLocale(1, this->ui->deButton);
-    app->config->setValue("Local", "lang", "de");
+    saveLocale(1, this->ui->deButton);
+    AConfig::getInstance()->setValue("Local", "lang", "de");
 }
 
 void MainWindow::on_frButton_clicked(){
-    App *app = &App::getInstance();
-    app->helper->saveLocale(2, this->ui->frButton);
-    app->config->setValue("Local", "lang", "fr");
+    saveLocale(2, this->ui->frButton);
+    AConfig::getInstance()->setValue("Local", "lang", "fr");
 }
 
 void MainWindow::saveSkin(){
-    App *app = &App::getInstance();
-    QString new_theme = app->window->ui->skinSelect->currentText();
-    if(app->config->getSkinName() != new_theme){
-        app->config->setValue("Global", "current_theme", new_theme);
-        app->helper->replaceSkin(new_theme);
+    QString new_theme = ui->skinSelect->currentText();
+    if(Skin::getInstance()->getSkinName() != new_theme){
+        AConfig::getInstance()->setValue("Global", "current_theme", new_theme);
+        Skin::getInstance()->replaceSkin(new_theme);
     }
 }
 
 void MainWindow::on_checkFonts_stateChanged(int arg1){
-    App *app = &App::getInstance();
-    app->config->setValue("Editor", "fonts", arg1 ? "true" : "false");
+    AConfig::getInstance()->setValue("Editor", "fonts", arg1 ? "true" : "false");
 }
 
 void MainWindow::on_checkTexts_stateChanged(int arg1){
-    App *app = &App::getInstance();
-    app->config->setValue("Editor", "texts", arg1 ? "true" : "false");;
-    app->downloader->abortDownload("texts");
+    AConfig::getInstance()->setValue("Editor", "texts", arg1 ? "true" : "false");;
+    DownloadManager::getInstance()->abortDownload("texts");
 }
 
 void MainWindow::on_checkSounds_stateChanged(int arg1){
-    App *app = &App::getInstance();
-    app->config->setValue("Editor", "sounds", arg1 ? "true" : "false");
-    app->downloader->abortDownload("sounds");
+    AConfig::getInstance()->setValue("Editor", "sounds", arg1 ? "true" : "false");
+    DownloadManager::getInstance()->abortDownload("sounds");
 }
 
 void MainWindow::on_checkMaps_stateChanged(int arg1){
-    App *app = &App::getInstance();
-    app->config->setValue("Editor", "images", arg1 ? "true" : "false");
-    app->downloader->abortDownload("images");
+    AConfig::getInstance()->setValue("Editor", "images", arg1 ? "true" : "false");
+    DownloadManager::getInstance()->abortDownload("images");
 }
 
 void MainWindow::on_checkScreens_stateChanged(int arg1){
-    App *app = &App::getInstance();
-    app->config->setValue("Editor", "screens", arg1 ? "true" : "false");
-    app->downloader->abortDownload("screens");
+    AConfig::getInstance()->setValue("Editor", "screens", arg1 ? "true" : "false");
+    DownloadManager::getInstance()->abortDownload("screens");
 }
 
 void MainWindow::on_checkVideos_stateChanged(int arg1){
-    App *app = &App::getInstance();
-    app->config->setValue("Editor", "videos", arg1 ? "true" : "false");
-    app->downloader->abortDownload("videos");
+    AConfig::getInstance()->setValue("Editor", "videos", arg1 ? "true" : "false");
+    DownloadManager::getInstance()->abortDownload("videos");
 }
 
 void MainWindow::on_checkMicro_stateChanged(int arg1){
-    App *app = &App::getInstance();
-    app->config->setValue("Updates", "micro", arg1 ? "true" : "false");
+    AConfig::getInstance()->setValue("Updates", "micro", arg1 ? "true" : "false");
 }
 
 void MainWindow::on_lotropathButton_clicked(){
-    App *app = &App::getInstance();
     QString path = QFileDialog::getExistingDirectory(0, "Выберите папку с игрой");
-    if(path != "" && app->helper->fileExists(path + "/TurbineLauncher.exe")){
-        app->window->ui->lotropathLabel->setText(path);
-        app->config->setValue("Local", "folder", path);
+    if(path != "" && FileSystem::fileExists(path + "/TurbineLauncher.exe")) {
+        ui->lotropathLabel->setText(path);
+        AConfig::getInstance()->setValue("Local", "folder", path);
     } else {
         QString text = "Выбрана неверная папка";
         QString info = "<p>Убедитесь, что выбранный вами каталог является папкой игры и содержит такие файлы как TurbineLauncher.exe и client_local_English.dat.</p>";
-        app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "", "", 400, 160, true, false);
+        myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "", "", 400, 160, true, false);
     }
 }
 
 void MainWindow::on_designButton_clicked(){
-   App *app = &App::getInstance();
-    app->helper->replaceSkin(app->config->getSkinName());
+    Skin::getInstance()->replaceSkin(Skin::getInstance()->getSkinName());
 }
 
 void MainWindow::on_repairButton_clicked(){
-   App *app = &App::getInstance();
-   app->config->deleteSection("Applied");
-   app->helper->applyGlobal();
-   app->helper->checkTab("mainbox");
+   AConfig::getInstance()->deleteSection("Applied");
+   GameRes::getInstance()->applyAll();
+   checkTab("mainbox");
 }
 
 void MainWindow::on_okButton_clicked(){
+    //QStringList commands = app->helper->dialog_ok_answer.split(" ");
+//    foreach(QString command, commands){
+//        if(command == "close"){
+//            ui->dialogbox->hide();
+//        }
+
+//        if(command == "gamefind"){
+//            QStringList folders = app->config->getLotroPath();
+//            if(folders.count() > 1){
+//                QString text = "Результаты поиска";
+//                QString info = "Найдены следующие папки в которых установлена игра:<br/><br/><br/><br/><br/>Выберите нужную папку и нажмите «Далее»<br/>";
+//                app->helper->myDialogBox(text, info, "Далее", "Отмена", "gandalf.png", "writefolder", "", 530, 200, true, false);
+//                ui->dialogList->setGeometry(QRect(
+//                    ui->dialogImage->rect().right() + 10,
+//                    ui->dialogHeader->rect().bottom()+40, 417, 50));
+
+//                foreach(QString f, folders) new QListWidgetItem(f, ui->dialogList);
+//                ui->dialogList->show();
+
+//            } else {
+//                if(folders.count() == 1){
+//                    ui->lotropathLabel->setText(folders.first());
+//                    app->config->setValue("Local", "folder", folders.first());
+//                    this->ui->dialogbox->hide();
+//                    QString text = "Завершающий этап";
+//                    QString info = "Необходимые приготовления завершены. Сейчас вы будете перенаправлены в раздел «Настройки», где сможете выбрать патчи, которые хотите установить. После этого перейдите в раздел «Патчи» для начала их загрузки и применения.";
+//                    app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "close gotooptions", "",400, 200, true, false);
+//                } else {
+//                    QString text = "Завершающий этап";
+//                    QString info = "Обнаружить каталог игры автоматически не удалось. Сейчас вы будете перенаправлены в раздел «Настройки», где сможете вручную выбрать каталог игры и патчи, которые хотите установить. После этого перейдите в раздел «Патчи» для начала их загрузки и применения.";
+//                    app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "close gotooptions", "",450, 200, true, false);
+//                }
+
+//            }
+
+//            qDebug() << folders;
+//        }
+
+//        if(command == "writefolder"){
+//            if(ui->dialogList->currentItem()){
+//                QString path = ui->dialogList->currentItem()->text();qDebug() << path;
+//                ui->lotropathLabel->setText(path);
+//                app->config->setValue("Local", "folder", path);
+//                ui->dialogList->clear();
+//                ui->dialogList->hide();
+//                this->ui->dialogbox->hide();
+//                QString text = "Завершающий этап";
+//                QString info = "Необходимые приготовления завершены. Сейчас вы будете перенаправлены в раздел «Настройки», где сможете выбрать патчи, которые хотите установить. После этого перейдите в раздел «Патчи» для начала их загрузки и применения.";
+//                app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "close gotooptions", "",400, 200, true, false);
+
+//            } else {
+//                break;
+//            }
+
+//        }
+
+//        if(command == "gotooptions"){
+//            app->helper->checkTab("optbox");
+//            app->config->setValue("Local", "runfirst", "1");
+//            app->helper->setState("free");
+//        }
+
+//        if(command == "applypaths"){
+//            app->ready = true;
+//            app->config->deleteSection("Applied");
+//            app->network->getPaths();
+//            app->helper->checkTab("mainbox");
+//        }
+
+//        if(command == "loaddatfile"){
+//            app->config->deleteSection("Applied");
+//            QString filename = app->config->getDatPath(0);
+//            qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Удаляем файл: ", app->helper->stringToChar(filename));
+//            app->helper->closeDatFile(0);
+//            if(QFile::remove(filename)){
+//                app->helper->startGame();
+//                qApp->exit();
+//            }
+
+//        }
+//    }
 
-    App *app = &App::getInstance();
-    QStringList commands = app->helper->dialog_ok_answer.split(" ");
-    foreach(QString command, commands){
-        if(command == "close"){
-            this->ui->dialogbox->hide();
-        }
-
-        if(command == "gamefind"){
-            QStringList folders = app->config->getLotroPath();
-            if(folders.count() > 1){
-                QString text = "Результаты поиска";
-                QString info = "Найдены следующие папки в которых установлена игра:<br/><br/><br/><br/><br/>Выберите нужную папку и нажмите «Далее»<br/>";
-                app->helper->myDialogBox(text, info, "Далее", "Отмена", "gandalf.png", "writefolder", "", 530, 200, true, false);
-                app->window->ui->dialogList->setGeometry(QRect(
-                    app->window->ui->dialogImage->rect().right() + 10,
-                    app->window->ui->dialogHeader->rect().bottom()+40, 417, 50));
-
-                foreach(QString f, folders) new QListWidgetItem(f, app->window->ui->dialogList);
-                app->window->ui->dialogList->show();
-
-            } else {
-                if(folders.count() == 1){
-                    app->window->ui->lotropathLabel->setText(folders.first());
-                    app->config->setValue("Local", "folder", folders.first());
-                    this->ui->dialogbox->hide();
-                    QString text = "Завершающий этап";
-                    QString info = "Необходимые приготовления завершены. Сейчас вы будете перенаправлены в раздел «Настройки», где сможете выбрать патчи, которые хотите установить. После этого перейдите в раздел «Патчи» для начала их загрузки и применения.";
-                    app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "close gotooptions", "",400, 200, true, false);
-                } else {
-                    QString text = "Завершающий этап";
-                    QString info = "Обнаружить каталог игры автоматически не удалось. Сейчас вы будете перенаправлены в раздел «Настройки», где сможете вручную выбрать каталог игры и патчи, которые хотите установить. После этого перейдите в раздел «Патчи» для начала их загрузки и применения.";
-                    app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "close gotooptions", "",450, 200, true, false);
-                }
 
-            }
+}
 
-            qDebug() << folders;
-        }
+void MainWindow::on_cancelButton_clicked(){
+//    QStringList commands = app->helper->dialog_cancel_answer.split(" ");
+//    foreach(QString command, commands){
+//        if(command == "close") this->ui->dialogbox->hide();
+//    }
+}
 
-        if(command == "writefolder"){
-            if(app->window->ui->dialogList->currentItem()){
-                QString path = app->window->ui->dialogList->currentItem()->text();qDebug() << path;
-                app->window->ui->lotropathLabel->setText(path);
-                app->config->setValue("Local", "folder", path);
-                app->window->ui->dialogList->clear();
-                app->window->ui->dialogList->hide();
-                this->ui->dialogbox->hide();
-                QString text = "Завершающий этап";
-                QString info = "Необходимые приготовления завершены. Сейчас вы будете перенаправлены в раздел «Настройки», где сможете выбрать патчи, которые хотите установить. После этого перейдите в раздел «Патчи» для начала их загрузки и применения.";
-                app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "close gotooptions", "",400, 200, true, false);
 
+void MainWindow::checkTab(QString tabname){
+    QList<QGroupBox *> boxes = findChildren<QGroupBox *> ();
+    foreach (QGroupBox * box, boxes){
+        if(box->parent()->objectName() == "centralWidget"){
+            QLabel* boximage = findChild<QLabel*>(box->objectName() + "Image");
+            if(box->objectName() == tabname){
+                box->show();
+                if(boximage != nullptr) boximage->show();
             } else {
-                break;
-            }
-
-        }
-
-        if(command == "gotooptions"){
-            app->helper->checkTab("optbox");
-            app->config->setValue("Local", "runfirst", "1");
-            app->helper->setState("free");
-        }
-
-        if(command == "applypaths"){
-            app->ready = true;
-            app->config->deleteSection("Applied");
-            app->network->getPaths();
-            app->helper->checkTab("mainbox");
-        }
-
-        if(command == "loaddatfile"){
-            app->config->deleteSection("Applied");
-            QString filename = app->config->getDatPath(0);
-            qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Удаляем файл: ", app->helper->stringToChar(filename));
-            app->helper->closeDatFile(0);
-            if(QFile::remove(filename)){
-                app->helper->startGame();
-                qApp->exit();
+                box->hide();
+                if(boximage != nullptr) boximage->hide();
             }
-
         }
     }
+    ui->serversbox->show();
+}
 
+void MainWindow::myDialogBox(QString text, QString info, QString okText, QString cancelText, QString image, QString okAnswer, QString cancelAnswer,
+                        int w, int h, bool textshadow = false, bool is_cancel = false){
 
-}
+    if(okAnswer == "") okAnswer = "close";
+    //app->helper->dialog_ok_answer = okAnswer;
+    if(cancelAnswer == "") cancelAnswer = "close";
+    //app->helper->dialog_cancel_answer = cancelAnswer;
 
-void MainWindow::on_cancelButton_clicked(){
+    ui->okButton->setText(okText);
+    ui->cancelButton->setText(cancelText);
+    ui->dialogbox->setGeometry(0, 0, width(), height());
 
-    App *app = &App::getInstance();
-    QStringList commands = app->helper->dialog_cancel_answer.split(" ");
-    foreach(QString command, commands){
-        if(command == "close") this->ui->dialogbox->hide();
+    QSettings settings(Skin::getInstance()->getSkinFile(), QSettings::IniFormat );
+    settings.beginGroup("mainWindow");
+    int left = (settings.value("width").toInt() - w)/2;
+    int top = (settings.value("height").toInt() - h)/2;
+    ui->dialog->setGeometry(QRect(left, top, w, h));
+    settings.endGroup();
 
+    int image_height = ui->dialog->rect().height() - ui->dialogHeader->rect().height();
+    ui->dialogImage->setGeometry(0,
+        ui->dialogHeader->rect().bottom(),
+        image_height/2 ,image_height
+     );
 
+    QString skin = Skin::getInstance()->getSkinName();
+    QString iconpath = "";
+    iconpath = FileSystem::fileExists("styles/" + skin + "/" + image) ? "styles/" + skin + "/" + image : ":/res/styles/" + skin + "/" + image;
+    QPixmap icon(iconpath);
 
+    ui->dialogImage->setPixmap(icon.scaled(ui->dialogImage->width(), ui->dialogImage->height()));
+    if(icon.isNull()){
+        ui->dialogImage->setGeometry(QRect(10, 10, 10, 10));
     }
 
+    ui->dialogHeader->setGeometry(
+                ui->dialogHeader->rect().left(),
+                ui->dialogHeader->rect().top(),
+                ui->dialog->rect().width(),
+                ui->dialogHeader->rect().height()
+    );
+
+    ui->dialogInfo->setGeometry(ui->dialogImage->rect().right(),
+         ui->dialogHeader->rect().bottom(),
+         ui->dialog->rect().width() - ui->dialogImage->rect().width()-7,
+         image_height - ui->cancelButton->height()
+     );
+
+
+
+    if(is_cancel){
+       ui->cancelButton->setGeometry(
+           ui->dialog->rect().left() + ui->dialog->width() - ui->cancelButton->width() - 20,
+           ui->dialog->rect().bottom() - ui->cancelButton->height() - 10,
+           ui->cancelButton->width(),
+           ui->cancelButton->height()
+        );
+       ui->okButton->setGeometry(
+           ui->dialog->rect().left() + ui->dialog->width() - ui->cancelButton->width() - ui->cancelButton->width() - 40,
+           ui->dialog->rect().bottom() - ui->cancelButton->height() - 10,
+           ui->cancelButton->width(),
+           ui->cancelButton->height()
+        );
+    } else {
+        ui->cancelButton->setGeometry(-1000,-1000, ui->cancelButton->width(), ui->cancelButton->height());
+        ui->okButton->setGeometry(
+            ui->dialog->rect().left() + ui->dialog->width() - ui->cancelButton->width() - 20,
+            ui->dialog->rect().bottom() - ui->cancelButton->height() - 10,
+            ui->cancelButton->width(),
+            ui->cancelButton->height()
+         );
+    }
 
+    ui->dialogHeader->setText(text);
+    ui->dialogInfo->setText(info);
+    ui->dialogImage->setText("");
+    ui->dialogbox->show();
 }
 
-
+void MainWindow::setAbout(){
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Размещаем информацию о хороших людях.");
+    ui->programmerslist->setText("Gi1dor, coder");
+    ui->designerslist->setText("Чирик, valyot, Quilanar, Eodoro");
+    ui->translatorslist->setText("Arissa, unnamedartist, valyot, Чирик, Eodoro, Ferdik, Tukbard, Alcassar, Satenskyhou, Quilanar, Коралан, Invizet, taiki_exe, Rhymer, Takhizis, Lauraldo, seventhgate027, Kerita, Хилко, Leodgar, Juolukka, Auruman, Drazgar, Tondred, Foldoren, Exildil, Anormir, Василий Волков, Andoriel, Felicer, noldohini, Gi1dor, Progylkin, Arkwendir, Bara Norkins, Siltier, Maxsikr, Nahkrin, Nick_os, Razverg, ENDrain, ToX4SHOW, Jeyolin, Frenni, Коралан, Palmuch, Marty");
+    ui->helperslist->setText("Menelhad, Мурзилка, Pastor, Alvees, Mirta, иван петров, vensys, Arkelas, Чеширская Улыбка, Shanishka70 ");
+}

+ 43 - 42
mainwindow.h

@@ -1,100 +1,101 @@
-#ifndef MAINWINDOW_H
-#define MAINWINDOW_H
+#ifndef MainWindow_H
+#define MainWindow_H
+
+#include "ui_mainwindow.h"
+
 
 #include <QMainWindow>
-#include <QMouseEvent>
-#include <QCloseEvent>
-#include <QWidget>
+#include <QComboBox>
+#include <QPushButton>
+#include <QApplication>
 
 namespace Ui {
 class MainWindow;
 }
 
-class MainWindow : public QMainWindow
-{
+class MainWindow : public QMainWindow {
     Q_OBJECT
 
-public:
-    Ui::MainWindow *ui;
+private:
     explicit MainWindow(QMainWindow *parent = 0);
     ~MainWindow();
-    bool eventFilter(QObject *obj, QEvent *event);
-    void doStartPreparations();
 
-    QString hint = "";
-    QString exthint = "";
-
-private:
+public:
+    static MainWindow* getInstance() {
+        static MainWindow instance;
+        return &instance;
+    }
 
+    bool eventFilter(QObject *obj, QEvent *event);
+    void setState(QString state);
+    void applyShadow(QWidget *obj, QString color, int blur, int offset_x, int offset_y);
+    void myDialogBox(QString text, QString info, QString okText, QString cancelText, QString image,
+                   QString okAnswer, QString cancelAnswer, int w, int h, bool textshadow, bool is_cancel);
+    void addComboItem(QComboBox* combo, QString itemName, QIcon* icon);
+    void saveLocale(int locale, QPushButton *button);
 
 private slots:
     void minimize();
     void saveSkin();
 
     void on_mainButton_clicked();
-
     void on_optButton_clicked();
-
     void on_newsButton_clicked();
-
     void on_helpButton_clicked();
-
     void on_aboutButton_clicked();
-
     void on_minimizeButton_clicked();
-
     void on_closeButton_clicked();
 
     void on_checkFonts_stateChanged(int arg1);
-
     void on_checkTexts_stateChanged(int arg1);
-
     void on_checkSounds_stateChanged(int arg1);
-
     void on_checkMaps_stateChanged(int arg1);
-
     void on_checkScreens_stateChanged(int arg1);
-
     void on_checkVideos_stateChanged(int arg1);
-
     void on_checkMicro_stateChanged(int arg1);
 
     void on_lotropathButton_clicked();
-
     void on_okButton_clicked();
-
     void on_couponButton_clicked();
-
     void on_cancelButton_clicked();
-
     void on_enButton_clicked();
-
     void on_deButton_clicked();
-
     void on_frButton_clicked();
-
     void on_enterButton_clicked();
-
     void on_goCancel_clicked();
-
     void on_goOriginal_clicked();
-
     void on_goLocal_clicked();
-
     void on_repairButton_clicked();
-
     void on_designButton_clicked();
 
-
 protected:
     void mouseMoveEvent( QMouseEvent* e );
     void mousePressEvent( QMouseEvent* e );
     void mouseReleaseEvent( QMouseEvent* e );
     void closeEvent( QCloseEvent * e );
+
+public:
+    void checkTab(QString tabname);
+
+    void loadConfig();
+    void loadNews();
+    void loadHelp();
+    void setAbout();
+
+    void hideAll();
+
+public:
+    QMap <QString, QString> htmlColors;
+    QString stylehtml;
+    Ui::MainWindow *ui;
+
 private:
+    QString hint = "";
+    QString exthint = "";
     int dx;
     int dy;
-
+    QString state;
+    QString app_folder;
 };
 
-#endif // MAINWINDOW_H
+#endif // MainWindow_H

+ 0 - 313
network.cpp

@@ -1,313 +0,0 @@
-#include "app.h"
-
-#include <QtNetwork/QNetworkAccessManager>
-#include <QUrl>
-#include <QUrlQuery>
-#include <QNetworkRequest>
-#include <QNetworkReply>
-#include <QObject>
-#include <QEventLoop>
-#include <QDir>
-#include <QMap>
-
-ANetwork::ANetwork() {
-
-}
-
-ANetwork::ANetwork(const ANetwork&) {
-    throw QException(); // Выкидываем QException, в случае если
-                        // вообще попытались скопировать объект
-}
-
-ANetwork& ANetwork::operator=(ANetwork&) {
-    throw QException(); // Выкидываем QException, в случае если
-                        // вообще попытались скопировать объект
-}
-
-QString ANetwork::query(QUrl url){
-    App *app = &App::getInstance();
-    QNetworkAccessManager* manager = new QNetworkAccessManager(app->window);
-    QNetworkRequest request(url);
-    QNetworkReply* reply = manager->get(request);
-    QEventLoop loop;
-    QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
-    loop.exec();
-    QString content = reply->readAll();
-    if (reply->error() != QNetworkReply::NoError){
-        content = "error";
-        // пишем в лог
-        qDebug() << reply->errorString();
-    }
-    reply->deleteLater();
-    return content;
-}
-
-QByteArray ANetwork::query_binary(QUrl url){
-    App *app = &App::getInstance();
-    QNetworkAccessManager* manager = new QNetworkAccessManager(app->window);
-    QNetworkRequest request(url);
-    QNetworkReply* reply = manager->get(request);
-    QEventLoop loop;
-    QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
-    loop.exec();
-    QByteArray bytes = reply->readAll();
-    return bytes;
-}
-
-QString ANetwork::getCoupon(){
-    App *app = &App::getInstance();
-    app->logSectionStart("Код купона");
-    QString content = this->query(app->config->getValue("Network", "coupon") + ".txt");
-    if (content != "error"){
-        app->config->setValue("Values", "coupon", content);
-        qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Ответ сервера: ", app->helper->stringToChar(content));
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Данные получены. Производим установку значений.");
-    } else {
-        qWarning("%s:%i: %s", __FILE__, __LINE__, "Не удалось получить информацию с сервера");
-        content = app->config->getValue("Values", "coupon");
-    }
-    app->window->ui->couponButton->setText(content);
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-    app->logSectionEnd();
-    return content;
-}
-
-QString ANetwork::getFootMessage(){
-    App *app = &App::getInstance();
-    app->logSectionStart("Информация о профилактике");
-   // app->window->ui->footRed->setText("Профилактика. Все сервера отключены. Примерное время окончания работ - 40:00 (МСК).");
-    QString content = this->query(app->config->getValue("Network", "foot") + ".txt");
-    if (content != "error"){
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Данные получены");
-        app->config->setValue("Values", "foot", content);
-        qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Ответ сервера: ", app->helper->stringToChar(content));
-    } else {
-        qWarning("%s:%i: %s", __FILE__, __LINE__, "Не удалось получить информацию с сервера");
-        content = app->config->getValue("Values", "foot");
-        app->logSectionEnd();
-        return content;
-    }
-
-    if(content != ""){
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Есть сообщения о профилактике. Производим разбор и установку значений");
-        QStringList list = content.split(":::");
-        //QStringList date = list[2].split(" ");
-
-        QString day = list[2];
-        QString month = " " + list[3];
-        app->window->ui->footYellow->show();
-        app->window->ui->footYellow->setText("Внимание! Плановая профилактика игровых серверов состоится " + day + month + " с " + list[0] +" до " + list[1] + " (МСК).");
-    } else {
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Сообщения о профилактике отсутствуют.");
-    }
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-    app->logSectionEnd();
-    return content;
-}
-
-
-QString ANetwork::getServers(){
-    App *app = &App::getInstance();
-    QString time = "";
-    app->logSectionStart("Статусы серверов");
-    QString content = this->query(app->config->getValue("Network", "servers") + ".txt");
-    if (content != "error"){
-        qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Ответ сервера: ", app->helper->stringToChar(content));
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Данные получены. Производим установку значений.");
-        app->config->setValue("Values", "servers", content);
-        qDebug() << content;
-    } else {
-        qWarning("%s:%i: %s", __FILE__, __LINE__, "Не удалось получить информацию с сервера.");
-        content = app->config->getValue("Values", "servers");
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-        app->logSectionEnd();
-        return content;
-    }
-
-    if(content == "profilaktika"){
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "По данным сервера в данный момент идут техработы.");
-        foreach(QObject * obj,  app->window->ui->serversbox->children()){
-            if (obj != nullptr && obj->objectName() != ""){
-                QLabel * label = dynamic_cast<QLabel*>(obj);
-                label->setStyleSheet("QLabel{ background-color:#8A0808; }");
-             }
-        }
-
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Парсим данные о профилактике.");
-        content = app->config->getValue("Values", "foot");
-        if(content != ""){
-            QStringList list = content.split(":::");
-            time = "Примерное время окончания работ - " + list[1] + " (МСК)";
-        }
-
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Выводим сообщение о профилактике.");
-        app->window->ui->footRed->show();
-        app->window->ui->footRed->setText("Профилактика. Все сервера отключены. " + time);
-        if(app->window->ui->footYellow->text() != "") app->window->ui->footYellow->setText("");
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-        app->logSectionEnd();
-
-
-        return content;
-    }
-
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Раскрашиваем индикаторы серверов.");
-    QStringList data = content.split("|||");
-    foreach(QString item, data){
-        QStringList server = item.split(":::");
-        QString color = server[1] == "on" ? "#173B0B" : "#8A0808";
-        QLabel* obj = app->window->ui->serversbox->findChild<QLabel*>(server[0]);
-        if (obj != nullptr){
-            obj->setStyleSheet("QLabel{ background-color:" + color + "; }");
-        }
-    }
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-    app->logSectionEnd();
-    return content;
-}
-
-
-void ANetwork::getPaths(){
-
-    App *app = &App::getInstance();
-    QUrlQuery query;
-    QStringList names;
-    QString version;
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Начинаем проверку актуальности патчей.");
-    names  << "sound" << "text" << "image" << "video" << "screen" << "texture" << "font";
-    QUrl url(app->config->getValue("Network", "releases"));
-
-    QString datafolder = QApplication::applicationDirPath() + "/data";
-    QDir dir(datafolder);
-    if(!dir.exists()) QDir().mkdir(datafolder);
-
-    foreach(QString s, names){
-        if(app->config->getValue("Editor", s + "s") == "true"){
-            if(s == "screen") s = "loadscreen";// поправка для заставок
-
-            QStringList paths = dir.entryList(QStringList(s + "*"));
-
-            if(!paths.empty()) {
-                 version = QString::number(app->helper->getVersion(paths.first()));
-                 QString hash = app->helper->fileHash(datafolder + "/" + paths.first(), QCryptographicHash::Md5);
-                 if(hash != app->config->getValue("Hashes", s + "s")){
-                     qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Эталон хэша отсутствует (удаляю файл): ", app->helper->stringToChar(paths.first()));
-                     QFile base(datafolder + "/" + paths.first());
-                     base.remove();
-                     version="100";
-                 }
-
-                 QString dateline = app->config->getValue("Datetime", s + "s");
-                 if(dateline != "-1"){
-                    qDebug("%s:%i: %s", __FILE__, __LINE__, "Проставляем даты патчей.");
-                    QLabel* obj = app->window->ui->mainbox->findChild<QLabel*>(s + "sStatus");
-                    if (obj != nullptr){
-                        QStringList date = dateline.split(" ");
-                        obj->setText(date[0]);
-                    }
-
-                 }
-
-            } else {
-                qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Патч отсутствует: ", app->helper->stringToChar(s));
-                version = "100";
-            }
-            query.addQueryItem(s, version);
-        }
-    }
-
-    url.setQuery(query.query());
-    qDebug("%s:%i: %s%s", __FILE__, __LINE__, "Запрашиваем информацию о патчах: ", app->helper->stringToChar(url.fileName()));
-    QString content = this->query(url);
-    if(content == "error"){
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Отсутствует связь с сервером. Прервано.");
-        app->logSectionEnd();
-        return;
-    }
-
-    qDebug() << content;
-    if(content == "") {
-        qInfo("%s:%i: %s", __FILE__, __LINE__, "Все версии патчей соответствуют актуальным.");
-        app->helper->setState("busy");
-        app->helper->applyGlobal();
-        app->helper->setState("free");
-        return;
-    }
-
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Составляем список загрузок.");
-    QStringList downloads = content.split( "|" );
-
-    foreach (QString item, downloads){
-        QStringList values = item.split( ":::" );
-
-        QStringList pathline = values[0].split( "_" );
-        pathline = pathline[0].split( "/" );
-        QUrl url = app->config->getValue("Network", "server") + values[0];
-        app->config->setValue("Hashes", pathline[3], values[1]);
-        app->config->setValue("Datetime", pathline[3], values[2]);
-
-        // Удаляем устаревшие патчи
-        QStringList old = dir.entryList(QStringList(pathline[3] + "*"));
-        if(old.count() > 0){
-            foreach(QString filename, old){
-                QFile::remove(QApplication::applicationDirPath() + "/data/" + filename);
-            }
-        }
-
-        // Добавляем новый файл в список закачек
-        app->downloader->append(url);
-    }
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Начинаем загрузку патчей.");
-    app->downloader->startNextDownload();
-}
-
-QString ANetwork::getMicroPath(int timestamp){
-
-    App *app = &App::getInstance();
-
-    app->logSectionStart("Загрузка последних обновлений");
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Уточняем наличие обновлений");
-
-    QString microfolder = QApplication::applicationDirPath() + "/data/micro/";
-    QDir dir(microfolder);
-    if(!dir.exists()) QDir().mkdir(microfolder);
-    QString baseurl = app->config->getValue("Network", "update");
-    QString url = baseurl + "/" + QString::number(timestamp);
-    qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Стартуем загрузку ", app->helper->stringToChar(url));
-    QNetworkAccessManager m_NetworkMngr;
-    QNetworkReply *reply= m_NetworkMngr.get(QNetworkRequest(url));
-    QEventLoop loop;
-    QObject::connect(reply, SIGNAL(finished()),&loop, SLOT(quit()));
-    loop.exec();
-    QUrl aUrl(url);
-    QFileInfo fileInfo=aUrl.path();
-    QString filename = microfolder + fileInfo.fileName() + ".db";
-    QFile file(filename);
-    file.open(QIODevice::WriteOnly);
-    file.write(reply->readAll());
-    delete reply;
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Загрузка микропатча завершена.");
-
-
-    app->db->InitDatabase(app->helper->stringToChar(filename));
-    int indb = app->db->CountRows();
-    qInfo("%s:%i: %s%i", __FILE__, __LINE__, "Патч содержит строк: ", indb);
-    for(int i = 0; i<=indb; i++) app->helper->processFile();
-    qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
-    app->config->saveAllDatFiles();
-    app->db->CloseDatabase();
-    app->logSectionEnd();
-
-    return filename;
-
-}
-
-
-
-
-
-
-
-
-
-

+ 0 - 40
network.h

@@ -1,40 +0,0 @@
-#ifndef NETWORK_H
-#define NETWORK_H
-
-#include <QUrl>
-#include <QNetworkAccessManager>
-#include <QtNetwork/QNetworkReply>
-#include <QProgressBar>
-#include <QFile>
-
-class MainWindow;
-
-class ANetwork {
-
-public:
-    ANetwork();
-    ANetwork( const ANetwork&);
-    ANetwork& operator=( ANetwork& );
-
-    QNetworkReply* currentDownload;
-    QFile output;
-
-    void getUrl();
-    QString getCoupon();
-    void getPaths();
-    QString getServers();
-    QString getFootMessage();
-    QString getMicroPath(int timestamp);
-
-    QString query(QUrl url);
-    QByteArray query_binary(QUrl url);
-
-    QString micropatch;
-
-private slots:
-    void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
-    void downloadFinished();
-
-};
-
-#endif // NETWORK_H

+ 187 - 0
skin.cpp

@@ -0,0 +1,187 @@
+#include "skin.h"
+#include "aconfig.h"
+#include "filesystem.h"
+#include "mainwindow.h"
+
+#include <QPushButton>
+#include <QString>
+#include <QDesktopWidget>
+#include <QApplication>
+#include <QLabel>
+#include <QBitmap>
+#include <QMovie>
+
+Skin::Skin(QObject *parent) : QObject(parent) {
+
+}
+
+QString Skin::getSkinFile(){
+    QString current_theme = QApplication::applicationDirPath() + "/styles/" + AConfig::getInstance()->getValue("Global", "current_theme") + "/skin.ini";
+    QString default_theme = QApplication::applicationDirPath() + "/styles/" + AConfig::getInstance()->getValue("Global", "default_theme") + "/skin.ini";
+    QString skinfile = FileSystem::fileExists(current_theme) ? current_theme : default_theme;
+    return skinfile;
+}
+
+QString Skin::getSkinName(){
+    QString current_theme = AConfig::getInstance()->getValue("Global", "current_theme");
+    QString default_theme = AConfig::getInstance()->getValue("Global", "default_theme");
+    QString path = QApplication::applicationDirPath() + "/styles/" + current_theme + "/skin.ini";
+    QString skinname = FileSystem::fileExists(path) ? current_theme : default_theme;
+    return skinname;
+}
+
+void Skin::loadSkin(){
+    qInfo("Загружаем скин лаунчера");
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Определяем активную тему оформления");
+    QSettings settings( getSkinFile(), QSettings::IniFormat );
+    QStringList items = settings.childGroups();
+    QVariant k;
+    QPushButton butt;
+    QLabel lab;
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Начинаем настройку элементов");
+
+    foreach (QString item, items){
+        qInfo("%s:%i: %s%s", __FILE__, __LINE__, "Устанавливаем настройки для ", item.toStdString().c_str());
+        MainWindow *a = MainWindow::getInstance();
+        QWidget* obj = a->findChild<QWidget*>(item);
+        if (obj != nullptr){
+            obj->installEventFilter(MainWindow::getInstance());
+            settings.beginGroup(item);
+            if(settings.value("left").toString() != "-1"){
+                obj->setGeometry(QRect(
+                    settings.value("left").toInt(),
+                    settings.value("top").toInt(),
+                    settings.value("width").toInt(),
+                    settings.value("height").toInt()
+                ));
+            }
+
+            qInfo("%s:%i: %s%s", __FILE__, __LINE__, item.toStdString().c_str(), ": настройка геометрии завершена");
+
+            if(settings.value("shadow") != k){
+                QString color = settings.value("shcolor") != k ? settings.value("shcolor").toString() : "#222";
+                int blur = settings.value("shblur") != k ? settings.value("shblur").toInt() : 2;
+                int offset_x = settings.value("shx") != k ? settings.value("shx").toInt() : 1;
+                int offset_y = settings.value("shy") != k ? settings.value("shy").toInt() : 1;
+                MainWindow::getInstance()->applyShadow(obj, color, blur, offset_x, offset_y);
+            }
+            qInfo("%s:%i: %s%s", __FILE__, __LINE__, item.toStdString().c_str(), ":  настройка теней завершена");
+
+            if(settings.value("text") != k){
+                QString text = settings.value("text").toString();
+                if(text == "del") text = "";
+                if(obj->metaObject()->className() == butt.metaObject()->className()){
+                   QPushButton * b = dynamic_cast<QPushButton* >(obj);
+                   b->setText(text);
+                }
+
+
+                if(obj->metaObject()->className() == lab.metaObject()->className()){
+                   QLabel * l = dynamic_cast<QLabel* >(obj);
+                   l->setText(settings.value("text").toString());
+                }
+                qInfo("%s:%i: %s%s", __FILE__, __LINE__, item.toStdString().c_str(), ": текст установлен");
+            }
+
+            if(settings.value("align") != k){
+                QLabel * lab = dynamic_cast<QLabel* >(obj);
+                if(settings.value("align") == "left") lab->setAlignment(Qt::AlignLeft);
+                if(settings.value("align") == "center") lab->setAlignment(Qt::AlignCenter);
+                if(settings.value("align") == "right") lab->setAlignment(Qt::AlignRight);
+            }
+            qInfo("%s:%i: %s%s", __FILE__, __LINE__, item.toStdString().c_str(), ": настройки позиционирования применены");
+
+            settings.endGroup();
+        } else  {
+            if(item == "mainWindow") {
+                settings.beginGroup(item);
+                qInfo("%s:%i: %s%s", __FILE__, __LINE__, item.toStdString().c_str(), ": обработка параметров главного окна");
+                int w = settings.value("width").toInt();
+                int h = settings.value("height").toInt();
+
+                QDesktopWidget desktop;
+                QRect rect = desktop.availableGeometry(desktop.primaryScreen()); // прямоугольник с размерами экрана
+                QPoint center = rect.center(); //координаты центра экрана
+                int x = center.x() - (w / 2);  // учитываем половину ширины окна
+                int y = center.y() - (h / 2); // .. половину высоты
+                center.setX(x);
+                center.setY(y);
+                MainWindow::getInstance()->move(center);
+                settings.endGroup();
+            }
+            qInfo("%s:%i: %s%s", __FILE__, __LINE__, item.toStdString().c_str(), ": закончен просчет геометрии");
+
+            if(item == "htmlColors") {
+                settings.beginGroup(item);
+                foreach(QString key, settings.allKeys()){
+                   MainWindow::getInstance()->htmlColors.insert(key, settings.value(key).toString());
+                }
+                settings.endGroup();
+            }
+            qInfo("%s:%i: %s%s", __FILE__, __LINE__, item.toStdString().c_str(), ": загружены HTML-цвета");
+        }
+    }
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
+}
+
+void Skin::findSkins(){
+    qInfo("Темы оформления");
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Производим поиск доступных тем.");
+    QDir dir(QApplication::applicationDirPath() + "/styles");
+    QStringList skins = dir.entryList(QDir::Dirs | QDir::AllDirs | QDir::NoDotAndDotDot);
+    MainWindow::getInstance()->ui->skinSelect->addItems(skins);
+    QString skinname = AConfig::getInstance()->getValue("Global", "current_theme");
+    MainWindow::getInstance()->ui->skinSelect->setCurrentText(skinname);
+
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Устанавливаем отметку о файле локализации.");
+    QString file = AConfig::getInstance()->getValue("Local", "file");
+    if(file == "client_local_English.dat") MainWindow::getInstance()->ui->enButton->setEnabled(false);
+    if(file == "client_local_DE.dat") MainWindow::getInstance()->ui->deButton->setEnabled(false);
+    if(file == "client_local_FR.dat") MainWindow::getInstance()->ui->frButton->setEnabled(false);
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Выполнено.");
+}
+
+void Skin::replaceSkin(QString name){
+    QString text = "Смена темы оформления";
+    QString info = "Выбрана тема " + name + ". Изменения вступят в силу при следующем запуске лаунчера.";
+    //app->helper->myDialogBox(text, info, "OK", "Отмена", "gandalf.png", "", "", 400, 120, true, false);
+
+    qInfo("%s:%i: %s", __FILE__, __LINE__, "Оформляем главное окно.");
+
+    QFile styleF;
+    QString skin = getSkinName();
+    styleF.setFileName(QApplication::applicationDirPath() + "styles/" + name + "/style.css");
+    styleF.open(QFile::ReadOnly);
+    QString qssStr = styleF.readAll();
+
+    qApp->setStyleSheet(qssStr);
+
+    QPixmap maskPix(":/res/styles/" + name + "/bg.png");
+    QPixmap maskPixLocal(QApplication::applicationDirPath() + "styles/" + name + "/bg.png");
+    maskPix = maskPix.isNull() ? maskPixLocal : maskPix;
+    MainWindow::getInstance()->setMask(maskPix.mask());
+
+    QString color = MainWindow::getInstance()->htmlColors.contains("a") ? MainWindow::getInstance()->htmlColors.lowerBound("a").value() : "blue";
+    loadSkin();
+    QString hrefcolor = MainWindow::getInstance()->htmlColors.contains("a") ? MainWindow::getInstance()->htmlColors.lowerBound("a").value() : "blue";
+
+    QString newtext = MainWindow::getInstance()->ui->news1Title->text().replace(color, hrefcolor);
+    MainWindow::getInstance()->ui->news1Title->setText(newtext);
+
+    newtext = MainWindow::getInstance()->ui->news2Title->text().replace(color, hrefcolor);
+    MainWindow::getInstance()->ui->news2Title->setText(newtext);
+
+    newtext = MainWindow::getInstance()->ui->news3Title->text().replace(color, hrefcolor);
+    MainWindow::getInstance()->ui->news3Title->setText(newtext);
+
+    newtext = MainWindow::getInstance()->ui->news4Title->text().replace(color, hrefcolor);
+    MainWindow::getInstance()->ui->news4Title->setText(newtext);
+
+    MainWindow::getInstance()->loadHelp();
+
+    QMovie * movie = new QMovie(":/res/styles/" + skin + "/loader.gif");
+    if(!movie->isValid()) movie = new QMovie(QApplication::applicationDirPath() + "styles/" + skin + "/loader.gif");
+    MainWindow::getInstance()->ui->loader->setMovie(movie);
+    movie->setScaledSize(QSize(MainWindow::getInstance()->ui->loader->width(), MainWindow::getInstance()->ui->loader->height()));
+    movie->start();
+}

+ 29 - 0
skin.h

@@ -0,0 +1,29 @@
+#ifndef SKIN_H
+#define SKIN_H
+
+#include <QObject>
+
+class Skin : public QObject
+{
+    Q_OBJECT
+private:
+    explicit Skin(QObject *parent = nullptr);
+
+public:
+    static Skin* getInstance() {
+        static Skin instance;
+        return &instance;
+    }
+
+    QString getSkinFile();
+    QString getSkinName();
+    void loadSkin();
+    void findSkins();
+    void replaceSkin(QString name);
+
+signals:
+
+public slots:
+};
+
+#endif // SKIN_H

+ 1 - 1
ui_mainwindow.h

@@ -1,7 +1,7 @@
 /********************************************************************************
 ** Form generated from reading UI file 'mainwindow.ui'
 **
-** Created by: Qt User Interface Compiler version 5.9.2
+** Created by: Qt User Interface Compiler version 5.9.3
 **
 ** WARNING! All changes made in this file will be lost when recompiling UI file!
 ********************************************************************************/