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

Partially implemented Setup Window

Ivan Savenko преди 2 години
родител
ревизия
c3d78ba761

+ 5 - 1
config/schemas/settings.json

@@ -440,7 +440,7 @@
 			"type" : "object",
 			"default": {},
 			"additionalProperties" : false,
-			"required" : [ "repositoryURL", "enableInstalledMods", "extraResolutionsModPath", "autoCheckRepositories", "updateOnStartup", "updateConfigUrl", "lobbyUrl", "lobbyPort", "lobbyUsername", "connectionTimeout" ],
+			"required" : [ "setupCompleted", "repositoryURL", "enableInstalledMods", "extraResolutionsModPath", "autoCheckRepositories", "updateOnStartup", "updateConfigUrl", "lobbyUrl", "lobbyPort", "lobbyUsername", "connectionTimeout" ],
 			"properties" : {
 				"repositoryURL" : {
 					"type" : "array",
@@ -451,6 +451,10 @@
 						"type" : "string"
 					}
 				},
+				"setupCompleted" : {
+					"type" : "boolean",
+					"default" : false
+				},
 				"enableInstalledMods" : {
 					"type" : "boolean",
 					"default" : true

+ 392 - 14
launcher/firstLaunch/firstlaunch_moc.cpp

@@ -12,59 +12,437 @@
 #include "ui_firstlaunch_moc.h"
 
 #include "mainwindow_moc.h"
+#include "modManager/cmodlistview_moc.h"
 
-#include "../languages.h"
 #include "../../lib/CConfigHandler.h"
+#include "../../lib/CGeneralTextHandler.h"
+#include "../../lib/Languages.h"
+#include "../../lib/VCMIDirs.h"
+#include "../../lib/filesystem/Filesystem.h"
+#include "../languages.h"
 
 FirstLaunchView::FirstLaunchView(QWidget * parent)
-	: QWidget(parent), ui(new Ui::FirstLaunchView)
+	: QWidget(parent)
+	, ui(new Ui::FirstLaunchView)
 {
 	ui->setupUi(this);
 
+	enterSetup();
+	activateTabLanguage();
+
+	ui->lineEditDataSystem->setText(boost::filesystem::absolute(VCMIDirs::get().dataPaths().front()).c_str());
+	ui->lineEditDataUser->setText(boost::filesystem::absolute(VCMIDirs::get().userDataPath()).c_str());
+}
+
+void FirstLaunchView::on_buttonTabLanguage_clicked()
+{
+	activateTabLanguage();
+}
+
+void FirstLaunchView::on_buttonTabHeroesData_clicked()
+{
+	activateTabHeroesData();
+}
+
+void FirstLaunchView::on_buttonTabModPreset_clicked()
+{
+	activateTabModPreset();
+}
+
+void FirstLaunchView::on_buttonTabFinish_clicked()
+{
+	activateTabFinish();
+}
+
+void FirstLaunchView::on_listWidgetLanguage_currentRowChanged(int currentRow)
+{
+	languageSelected(ui->listWidgetLanguage->item(currentRow)->data(Qt::UserRole).toString());
+}
+
+void FirstLaunchView::changeEvent(QEvent * event)
+{
+	if(event->type() == QEvent::LanguageChange)
+	{
+		ui->retranslateUi(this);
+		Languages::fillLanguages(ui->listWidgetLanguage);
+	}
+	QWidget::changeEvent(event);
+}
+
+void FirstLaunchView::on_pushButtonLanguageNext_clicked()
+{
+	activateTabHeroesData();
+}
+
+void FirstLaunchView::on_pushButtonDataNext_clicked()
+{
+	activateTabModPreset();
+}
+
+void FirstLaunchView::on_pushButtonDataBack_clicked()
+{
+	activateTabLanguage();
+}
+
+void FirstLaunchView::on_pushButtonDataSearch_clicked()
+{
+	heroesDataUpdate();
+}
+
+void FirstLaunchView::on_pushButtonDataCopy_clicked()
+{
+	copyHeroesData();
+}
+
+void FirstLaunchView::on_pushButtonDataHelp_clicked()
+{
+	static const QUrl vcmibuilderWiki("https://wiki.vcmi.eu/Installation_on_Linux#Installing_Heroes_III_data_files");
+	QDesktopServices::openUrl(vcmibuilderWiki);
+}
+
+void FirstLaunchView::on_comboBoxLanguage_currentIndexChanged(int index)
+{
+	forceHeroesLanguage(ui->comboBoxLanguage->itemData(index).toString());
+}
+
+void FirstLaunchView::enterSetup()
+{
+	// TODO: block all UI except FirstLaunchView
 	Languages::fillLanguages(ui->listWidgetLanguage);
+	Languages::fillLanguages(ui->comboBoxLanguage);
 }
 
-FirstLaunchView::~FirstLaunchView()
+void FirstLaunchView::setSetupProgress(int progress)
 {
+	int value = std::max(progress, ui->setupProgressBar->value());
 
+	ui->setupProgressBar->setValue(value);
+
+	ui->buttonTabLanguage->setDisabled(value < 1);
+	ui->buttonTabHeroesData->setDisabled(value < 2);
+	ui->buttonTabModPreset->setDisabled(value < 3);
+	ui->buttonTabFinish->setDisabled(value < 4);
 }
 
-void FirstLaunchView::on_buttonTabLanguage_clicked()
+void FirstLaunchView::activateTabLanguage()
 {
+	setSetupProgress(1);
 	ui->installerTabs->setCurrentIndex(0);
+	ui->buttonTabLanguage->setChecked(true);
+	ui->buttonTabHeroesData->setChecked(false);
+	ui->buttonTabModPreset->setChecked(false);
+	ui->buttonTabFinish->setChecked(false);
 }
 
-void FirstLaunchView::on_buttonTabHeroesData_clicked()
+void FirstLaunchView::activateTabHeroesData()
 {
+	setSetupProgress(2);
 	ui->installerTabs->setCurrentIndex(1);
+	ui->buttonTabLanguage->setChecked(false);
+	ui->buttonTabHeroesData->setChecked(true);
+	ui->buttonTabModPreset->setChecked(false);
+	ui->buttonTabFinish->setChecked(false);
+
+	if(!hasVCMIBuilderScript)
+	{
+		ui->pushButtonDataHelp->hide();
+		ui->labelDataHelp->hide();
+	}
+	heroesDataUpdate();
 }
 
-void FirstLaunchView::on_buttonTabModPreset_clicked()
+void FirstLaunchView::activateTabModPreset()
 {
+	setSetupProgress(3);
 	ui->installerTabs->setCurrentIndex(2);
+	ui->buttonTabLanguage->setChecked(false);
+	ui->buttonTabHeroesData->setChecked(false);
+	ui->buttonTabModPreset->setChecked(true);
+	ui->buttonTabFinish->setChecked(false);
+
+	modPresetUpdate();
 }
 
-void FirstLaunchView::on_buttonTabFinish_clicked()
+void FirstLaunchView::activateTabFinish()
 {
+	setSetupProgress(4);
 	ui->installerTabs->setCurrentIndex(3);
+	ui->buttonTabLanguage->setChecked(false);
+	ui->buttonTabModPreset->setChecked(false);
+	ui->buttonTabHeroesData->setChecked(false);
+	ui->buttonTabFinish->setChecked(true);
 }
 
-void FirstLaunchView::on_listWidgetLanguage_currentRowChanged(int currentRow)
+void FirstLaunchView::exitSetup()
+{
+	//TODO: unlock UI, switch to another tab (mods?)
+}
+
+// Tab Language
+void FirstLaunchView::languageSelected(const QString & selectedLanguage)
 {
 	Settings node = settings.write["general"]["language"];
-	QString selectedLanguage = ui->listWidgetLanguage->item(currentRow)->data(Qt::UserRole).toString();
 	node->String() = selectedLanguage.toStdString();
 
 	if(auto * mainWindow = dynamic_cast<MainWindow *>(qApp->activeWindow()))
 		mainWindow->updateTranslation();
 }
 
-void FirstLaunchView::changeEvent(QEvent *event)
+void FirstLaunchView::heroesDataUpdate()
 {
-	if(event->type() == QEvent::LanguageChange)
+	if(heroesDataDetect())
+		heroesDataDetected();
+	else
+		heroesDataMissing();
+}
+
+void FirstLaunchView::heroesDataMissing()
+{
+	QPalette newPalette = palette();
+	newPalette.setColor(QPalette::Base, QColor(200, 50, 50));
+	ui->lineEditDataSystem->setPalette(newPalette);
+	ui->lineEditDataUser->setPalette(newPalette);
+
+	ui->pushButtonDataSearch->setVisible(true);
+	ui->pushButtonDataCopy->setVisible(true);
+
+	ui->labelDataSearch->setVisible(true);
+	ui->labelDataCopy->setVisible(true);
+
+	ui->labelDataFound->setVisible(false);
+
+	if(hasVCMIBuilderScript)
 	{
-		ui->retranslateUi(this);
-		Languages::fillLanguages(ui->listWidgetLanguage);
+		ui->pushButtonDataHelp->setVisible(true);
+		ui->labelDataHelp->setVisible(true);
 	}
-	QWidget::changeEvent(event);
 }
+
+void FirstLaunchView::heroesDataDetected()
+{
+	QPalette newPalette = palette();
+	newPalette.setColor(QPalette::Base, QColor(50, 200, 50));
+	ui->lineEditDataSystem->setPalette(newPalette);
+	ui->lineEditDataUser->setPalette(newPalette);
+
+	ui->pushButtonDataSearch->setVisible(false);
+	ui->pushButtonDataCopy->setVisible(false);
+
+	ui->labelDataSearch->setVisible(false);
+	ui->labelDataCopy->setVisible(false);
+
+	if(hasVCMIBuilderScript)
+	{
+		ui->pushButtonDataHelp->setVisible(false);
+		ui->labelDataHelp->setVisible(false);
+	}
+
+	ui->labelDataFound->setVisible(true);
+
+	heroesLanguageUpdate();
+}
+
+// Tab Heroes III Data
+bool FirstLaunchView::heroesDataDetect()
+{
+	// user might have copied files to one of our data path.
+	// perform full reinitialization of virtual filesystem
+	CResourceHandler::destroy();
+	CResourceHandler::initialize();
+	CResourceHandler::load("config/filesystem.json");
+
+	// use file from lod archive to check presence of H3 data. Very rough estimate, but will work in majority of cases
+	bool heroesDataFound = CResourceHandler::get()->existsResource(ResourceID("DATA/GENRLTXT.TXT"));
+
+	return heroesDataFound;
+}
+
+QString FirstLaunchView::heroesLanguageDetect()
+{
+	CGeneralTextHandler::detectInstallParameters();
+
+	QString language = QString::fromStdString(settings["session"]["language"].String());
+	double deviation = settings["session"]["languageDeviation"].Float();
+
+	if(deviation > 0.05)
+		return QString();
+	return language;
+}
+
+void FirstLaunchView::heroesLanguageUpdate()
+{
+	QString language = heroesLanguageDetect();
+
+	bool success = !language.isEmpty();
+
+	if(!language.isEmpty())
+	{
+		std::string languageNameEnglish = Languages::getLanguageOptions(language.toStdString()).nameEnglish;
+		QString languageName = QApplication::translate( "Languages", languageNameEnglish.c_str());
+		QString itemName = tr("Auto (%1)").arg(languageName);
+
+		ui->comboBoxLanguage->insertItem(0, itemName, QString("auto"));
+		ui->comboBoxLanguage->setCurrentIndex(0);
+	}
+	ui->labelDataFailure->setVisible(!success);
+	ui->labelDataSuccess->setVisible(success);
+	ui->pushButtonDataNext->setEnabled(success);
+}
+
+void FirstLaunchView::forceHeroesLanguage(const QString & language)
+{
+	Settings node = settings.write["general"]["gameDataLanguage"];
+
+	node->String() = language.toStdString();
+}
+
+void FirstLaunchView::copyHeroesData()
+{
+	assert(0); // TODO: test
+
+	QDir dir = QFileDialog::getExistingDirectory(this, "", "", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
+
+	if(!dir.exists())
+		return;
+
+	QStringList dirData = dir.entryList({"data"}, QDir::Filter::Dirs);
+	QStringList dirMaps = dir.entryList({"maps"}, QDir::Filter::Dirs);
+	QStringList dirMp3 = dir.entryList({"mp3"}, QDir::Filter::Dirs);
+
+	if(dirData.empty() || dirMaps.empty() || dirMp3.empty())
+		return;
+
+	QStringList lodArchives = QDir(dirData.front()).entryList({"*.lod"}, QDir::Filter::Files);
+
+	if(lodArchives.empty())
+		return;
+
+	QStringList copyDirectories = {dirData.front(), dirMaps.front(), dirMp3.front()};
+
+	QDir targetRoot = QString(VCMIDirs::get().userDataPath().c_str());
+
+	for(QDir sourceDir : copyDirectories)
+	{
+		QString dirName = sourceDir.dirName();
+		QDir targetDir = targetRoot.filePath(dirName);
+
+		if(!targetRoot.exists(dirName))
+			targetRoot.mkdir(dirName);
+
+		for(QString filename : sourceDir.entryList(QDir::Filter::Files))
+		{
+			QFile sourceFile(sourceDir.filePath(filename));
+			sourceFile.copy(targetDir.filePath(filename));
+		}
+	}
+
+	heroesDataUpdate();
+}
+
+// Tab Mod Preset
+void FirstLaunchView::modPresetUpdate()
+{
+	bool translationExists = !findTranslationModName().isEmpty();
+
+	ui->labelPresetLanguage->setVisible(translationExists);
+	ui->toolButtonPresetLanguage->setVisible(translationExists);
+
+	ui->toolButtonPresetLanguage->setEnabled(checkCanInstallTranslation());
+	ui->toolButtonPresetExtras->setEnabled(checkCanInstallExtras());
+	ui->toolButtonPresetHota->setEnabled(checkCanInstallHota());
+	ui->toolButtonPresetWog->setEnabled(checkCanInstallWog());
+}
+
+QString FirstLaunchView::findTranslationModName()
+{
+	if (!getModView())
+		return QString();
+
+	QString preferredlanguage = QString::fromStdString(settings["general"]["language"].String());
+	QString installedlanguage = QString::fromStdString(settings["session"]["language"].String());
+
+	if (preferredlanguage == installedlanguage)
+		return QString();
+
+	return getModView()->getTranslationModName(preferredlanguage);
+}
+
+bool FirstLaunchView::checkCanInstallTranslation()
+{
+	QString modName = findTranslationModName();
+
+	if(modName.isEmpty())
+		return false;
+
+	return checkCanInstallMod(modName);
+}
+
+bool FirstLaunchView::checkCanInstallWog()
+{
+	return checkCanInstallMod("wake-of-gods");
+}
+
+bool FirstLaunchView::checkCanInstallHota()
+{
+	return checkCanInstallMod("hota");
+}
+
+bool FirstLaunchView::checkCanInstallExtras()
+{
+	return checkCanInstallMod("vcmi-extras");
+}
+
+CModListView * FirstLaunchView::getModView()
+{
+	auto * mainWindow = dynamic_cast<MainWindow *>(qApp->activeWindow());
+
+	assert(mainWindow);
+	if (!mainWindow)
+		return nullptr;
+
+	return mainWindow->getModView();
+}
+
+bool FirstLaunchView::checkCanInstallMod(const QString & modID)
+{
+	return getModView() && !getModView()->isModInstalled(modID);
+}
+
+void FirstLaunchView::installTranslation()
+{
+	installMod(findTranslationModName());
+}
+
+void FirstLaunchView::installWog()
+{
+	installMod("wake-of-gods");
+}
+
+void FirstLaunchView::installHota()
+{
+	installMod("hota");
+}
+
+void FirstLaunchView::instalExtras()
+{
+	installMod("vcmi-extras");
+}
+
+void FirstLaunchView::installMod(const QString & modID)
+{
+	assert(0); // TODO: test
+
+	return getModView()->doInstallMod(modID);
+}
+
+void FirstLaunchView::on_pushButtonPresetBack_clicked()
+{
+	activateTabHeroesData();
+}
+
+
+void FirstLaunchView::on_pushButtonPresetNext_clicked()
+{
+	activateTabFinish();
+}
+

+ 67 - 5
launcher/firstLaunch/firstlaunch_moc.h

@@ -15,28 +15,90 @@ namespace Ui
 class FirstLaunchView;
 }
 
+class CModListView;
+
 class FirstLaunchView : public QWidget
 {
 	Q_OBJECT
 
+	// vcmibuilder script is not available on these platforms
+#if defined(VCMI_WINDOWS) || defined(VCMI_MOBILE) || defined(VCMI_APPLE)
+	static constexpr bool hasVCMIBuilderScript = false;
+#else
+	static constexpr bool hasVCMIBuilderScript = true;
+#endif
+
 	void changeEvent(QEvent *event);
+	CModListView * getModView();
+
+	void setSetupProgress(int progress);
+	void enterSetup();
+	void activateTabLanguage();
+	void activateTabHeroesData();
+	void activateTabModPreset();
+	void activateTabFinish();
+	void exitSetup();
+
+	// Tab Language
+	void languageSelected(const QString & languageCode);
+
+	// Tab Heroes III Data
+	void heroesDataUpdate();
+	bool heroesDataDetect();
+
+	void heroesDataMissing();
+	void heroesDataDetected();
+
+	QString heroesLanguageDetect();
+	void heroesLanguageUpdate();
+	void forceHeroesLanguage(const QString & language);
+
+	void copyHeroesData();
+
+	// Tab Mod Preset
+	void modPresetUpdate();
+
+	QString findTranslationModName();
+
+	bool checkCanInstallTranslation();
+	bool checkCanInstallWog();
+	bool checkCanInstallHota();
+	bool checkCanInstallExtras();
+	bool checkCanInstallMod(const QString & modID);
+
+	void installTranslation();
+	void installWog();
+	void installHota();
+	void instalExtras();
+	void installMod(const QString & modID);
+
 public:
 	explicit FirstLaunchView(QWidget * parent = 0);
-	~FirstLaunchView();
 
 public slots:
 
 private slots:
 
 	void on_buttonTabLanguage_clicked();
-
 	void on_buttonTabHeroesData_clicked();
-
 	void on_buttonTabModPreset_clicked();
-
 	void on_buttonTabFinish_clicked();
-
 	void on_listWidgetLanguage_currentRowChanged(int currentRow);
+	void on_pushButtonLanguageNext_clicked();
+	void on_pushButtonDataNext_clicked();
+	void on_pushButtonDataBack_clicked();
+
+	void on_pushButtonDataSearch_clicked();
+
+	void on_pushButtonDataCopy_clicked();
+
+	void on_pushButtonDataHelp_clicked();
+
+	void on_comboBoxLanguage_currentIndexChanged(int index);
+
+	void on_pushButtonPresetBack_clicked();
+
+	void on_pushButtonPresetNext_clicked();
 
 private:
 	Ui::FirstLaunchView * ui;

+ 23 - 11
launcher/firstLaunch/firstlaunch_moc.ui

@@ -119,7 +119,7 @@
     </layout>
    </item>
    <item>
-    <widget class="QProgressBar" name="progressBar">
+    <widget class="QProgressBar" name="setupProgressBar">
      <property name="minimum">
       <number>0</number>
      </property>
@@ -140,7 +140,7 @@
    <item>
     <widget class="QStackedWidget" name="installerTabs">
      <property name="currentIndex">
-      <number>0</number>
+      <number>2</number>
      </property>
      <widget class="QWidget" name="pageLanguageSelect">
       <layout class="QGridLayout" name="gridLayout_3">
@@ -286,23 +286,35 @@
           </widget>
          </item>
          <item row="1" column="1" colspan="3">
-          <widget class="QLineEdit" name="lineEditData1">
+          <widget class="QLineEdit" name="lineEditDataSystem">
+           <property name="enabled">
+            <bool>true</bool>
+           </property>
            <property name="sizePolicy">
             <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
              <horstretch>50</horstretch>
              <verstretch>0</verstretch>
             </sizepolicy>
            </property>
+           <property name="readOnly">
+            <bool>true</bool>
+           </property>
           </widget>
          </item>
          <item row="0" column="1" colspan="3">
-          <widget class="QLineEdit" name="lineEditData2">
+          <widget class="QLineEdit" name="lineEditDataUser">
+           <property name="enabled">
+            <bool>true</bool>
+           </property>
            <property name="sizePolicy">
             <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
              <horstretch>50</horstretch>
              <verstretch>0</verstretch>
             </sizepolicy>
            </property>
+           <property name="readOnly">
+            <bool>true</bool>
+           </property>
           </widget>
          </item>
          <item row="4" column="0" colspan="3">
@@ -424,7 +436,7 @@
          <item row="1" column="0" colspan="2">
           <widget class="QLabel" name="labelDataSuccess">
            <property name="text">
-            <string>You Heroes III language was succesfully detected automatically.</string>
+            <string>Your Heroes III language has been succesfully detected.</string>
            </property>
            <property name="wordWrap">
             <bool>true</bool>
@@ -562,7 +574,7 @@
             </sizepolicy>
            </property>
            <property name="text">
-            <string>VCMI provides its own version of Horn of the Abyss fan-made addon. If you wish you can install it right now. For more information about mod visit hota website</string>
+            <string>VCMI provides support for Horn of the Abyss: fan-made Heroes III expansion, ported by VCMI team</string>
            </property>
            <property name="wordWrap">
             <bool>true</bool>
@@ -578,7 +590,7 @@
             </sizepolicy>
            </property>
            <property name="text">
-            <string>Localization to English</string>
+            <string>Install localization</string>
            </property>
            <property name="toolButtonStyle">
             <enum>Qt::ToolButtonTextOnly</enum>
@@ -594,7 +606,7 @@
             </sizepolicy>
            </property>
            <property name="text">
-            <string>Install VCMI-compatible version of the &quot;In The Wake of Gods&quot; fan-made addon</string>
+            <string>VCMI provides compatible version of the &quot;In The Wake of Gods&quot; fan-made addon</string>
            </property>
            <property name="wordWrap">
             <bool>true</bool>
@@ -610,7 +622,7 @@
             </sizepolicy>
            </property>
            <property name="text">
-            <string>Heroes III + HotA</string>
+            <string>Install Horn of the Abyss</string>
            </property>
            <property name="toolButtonStyle">
             <enum>Qt::ToolButtonTextOnly</enum>
@@ -626,7 +638,7 @@
             </sizepolicy>
            </property>
            <property name="text">
-            <string>Heroes III + WoG</string>
+            <string>Install In the Wake of Gods</string>
            </property>
            <property name="toolButtonStyle">
             <enum>Qt::ToolButtonTextOnly</enum>
@@ -674,7 +686,7 @@
             </sizepolicy>
            </property>
            <property name="text">
-            <string>HD support</string>
+            <string>Install HD support</string>
            </property>
            <property name="toolButtonStyle">
             <enum>Qt::ToolButtonTextOnly</enum>

+ 0 - 3
launcher/languages.h

@@ -13,8 +13,6 @@ class QString;
 class QComboBox;
 class QListWidget;
 
-VCMI_LIB_NAMESPACE_BEGIN
-
 namespace Languages
 {
 	struct Options;
@@ -25,4 +23,3 @@ namespace Languages
 	void fillLanguages(QListWidget * widget);
 }
 
-VCMI_LIB_NAMESPACE_END

+ 21 - 8
launcher/mainwindow_moc.cpp

@@ -102,7 +102,22 @@ MainWindow::MainWindow(QWidget * parent)
 
 	computeSidePanelSizes();
 
-	ui->tabListWidget->setCurrentIndex(0);
+	bool h3DataFound = CResourceHandler::get()->existsResource(ResourceID("DATA/GENRLTXT.TXT"));
+	bool setupCompleted = settings["launcher"]["setupCompleted"].Bool();
+
+	if (h3DataFound && setupCompleted)
+	{
+		ui->tabListWidget->setCurrentIndex(TabRows::MODS);
+	}
+	else
+	{
+		ui->startGameButton->setEnabled(false);
+		ui->startEditorButton->setEnabled(false);
+		ui->lobbyButton->setEnabled(false);
+		ui->settingsButton->setEnabled(false);
+		ui->modslistButton->setEnabled(false);
+		ui->tabListWidget->setCurrentIndex(TabRows::SETUP);
+	}
 
 	ui->settingsView->isExtraResolutionsModEnabled = ui->modlistView->isExtraResolutionsModEnabled();
 	ui->settingsView->setDisplayList();
@@ -147,6 +162,11 @@ const CModList & MainWindow::getModList() const
 	return ui->modlistView->getModList();
 }
 
+CModListView * MainWindow::getModView()
+{
+	return ui->modlistView;
+}
+
 void MainWindow::on_modslistButton_clicked()
 {
 	ui->startGameButton->setEnabled(true);
@@ -197,10 +217,3 @@ void MainWindow::updateTranslation()
 
 #endif
 }
-
-void MainWindow::on_setupButton_clicked()
-{
-	ui->startGameButton->setEnabled(false);
-	ui->tabListWidget->setCurrentIndex(TabRows::SETUP);
-}
-

+ 2 - 2
launcher/mainwindow_moc.h

@@ -21,7 +21,7 @@ const QString appName = "VCMI Launcher";
 
 class QTableWidgetItem;
 class CModList;
-
+class CModListView;
 
 class MainWindow : public QMainWindow
 {
@@ -48,6 +48,7 @@ public:
 	~MainWindow() override;
 
 	const CModList & getModList() const;
+	CModListView * getModView();
 
 	void updateTranslation();
 	void computeSidePanelSizes();
@@ -60,5 +61,4 @@ private slots:
 	void on_settingsButton_clicked();
 	void on_lobbyButton_clicked();
 	void on_startEditorButton_clicked();
-	void on_setupButton_clicked();
 };

+ 0 - 46
launcher/mainwindow_moc.ui

@@ -183,52 +183,6 @@
         </property>
        </widget>
       </item>
-      <item>
-       <widget class="QToolButton" name="setupButton">
-        <property name="sizePolicy">
-         <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
-          <horstretch>1</horstretch>
-          <verstretch>1</verstretch>
-         </sizepolicy>
-        </property>
-        <property name="minimumSize">
-         <size>
-          <width>0</width>
-          <height>0</height>
-         </size>
-        </property>
-        <property name="maximumSize">
-         <size>
-          <width>16777215</width>
-          <height>16777215</height>
-         </size>
-        </property>
-        <property name="text">
-         <string>Setup</string>
-        </property>
-        <property name="iconSize">
-         <size>
-          <width>60</width>
-          <height>60</height>
-         </size>
-        </property>
-        <property name="checkable">
-         <bool>true</bool>
-        </property>
-        <property name="checked">
-         <bool>false</bool>
-        </property>
-        <property name="autoExclusive">
-         <bool>true</bool>
-        </property>
-        <property name="toolButtonStyle">
-         <enum>Qt::ToolButtonTextOnly</enum>
-        </property>
-        <property name="autoRaise">
-         <bool>true</bool>
-        </property>
-       </widget>
-      </item>
       <item>
        <spacer name="verticalSpacer">
         <property name="orientation">

+ 37 - 1
launcher/modManager/cmodlistview_moc.cpp

@@ -102,7 +102,7 @@ CModListView::CModListView(QWidget * parent)
 
 	ui->progressWidget->setVisible(false);
 	dlManager = nullptr;
-	disableModInfo();
+
 	if(settings["launcher"]["autoCheckRepositories"].Bool())
 	{
 		loadRepositories();
@@ -814,3 +814,39 @@ const CModList & CModListView::getModList() const
 	assert(modModel);
 	return *modModel;
 }
+
+void CModListView::doInstallMod(const QString & modName)
+{
+	assert(findInvalidDependencies(modName).empty());
+
+	for(auto & name : modModel->getRequirements(modName))
+	{
+		auto mod = modModel->getMod(name);
+		if(!mod.isInstalled())
+			downloadFile(name + ".zip", mod.getValue("download").toString(), "mods");
+	}
+}
+
+bool CModListView::isModInstalled(const QString & modName)
+{
+	auto mod = modModel->getMod(modName);
+	return mod.isInstalled();
+}
+
+QString CModListView::getTranslationModName(const QString & language)
+{
+	for (auto const & modName : modModel->getModList())
+	{
+		auto mod = modModel->getMod(modName);
+
+		if (mod.getValue("type") != "localization")
+			continue;
+
+		if (mod.getValue("language") != language)
+			continue;
+
+		return modName;
+	}
+
+	return QString();
+}

+ 11 - 1
launcher/modManager/cmodlistview_moc.h

@@ -74,7 +74,6 @@ public:
 
 	void loadScreenshots();
 
-	void enableModInfo();
 	void disableModInfo();
 
 	void selectMod(const QModelIndex & index);
@@ -82,6 +81,17 @@ public:
 
 	const CModList & getModList() const;
 	
+	// First Launch View interface
+
+	/// install mod by name
+	void doInstallMod(const QString & modName);
+
+	/// returns true if mod is currently installed
+	bool isModInstalled(const QString & modName);
+
+	/// finds translation mod for specified languages. Returns empty string on error
+	QString getTranslationModName(const QString & language);
+
 public slots:
 	void enableModByName(QString modName);
 	void disableModByName(QString modName);

+ 4 - 1
lib/CGeneralTextHandler.cpp

@@ -49,7 +49,7 @@ void CGeneralTextHandler::detectInstallParameters()
 
 	// load file that will be used for footprint generation
 	// this is one of the most text-heavy files in game and consists solely from translated texts
-	auto resource = CResourceHandler::get()->load(ResourceID("DATA/GENRLTXT.TXT", EResType::TEXT));
+	auto resource = CResourceHandler::get("core")->load(ResourceID("DATA/GENRLTXT.TXT", EResType::TEXT));
 
 	std::array<size_t, 256> charCount{};
 	std::array<double, 16> footprint{};
@@ -87,6 +87,9 @@ void CGeneralTextHandler::detectInstallParameters()
 	Settings language = settings.write["session"]["language"];
 	language->String() = knownLanguages[bestIndex];
 
+	Settings confidence = settings.write["session"]["languageDeviation"];
+	confidence->Float() = deviations[bestIndex];
+
 	Settings encoding = settings.write["session"]["encoding"];
 	encoding->String() =  Languages::getLanguageOptions(knownLanguages[bestIndex]).encoding;
 }

+ 0 - 2
lib/filesystem/AdapterLoaders.cpp

@@ -58,12 +58,10 @@ std::unordered_set<ResourceID> CMappedFileLoader::getFilteredFiles(std::function
 
 CFilesystemList::CFilesystemList()
 {
-	//loaders = new std::vector<std::unique_ptr<ISimpleResourceLoader> >;
 }
 
 CFilesystemList::~CFilesystemList()
 {
-	//delete loaders;
 }
 
 std::unique_ptr<CInputStream> CFilesystemList::load(const ResourceID & resourceName) const

+ 6 - 0
lib/filesystem/Filesystem.cpp

@@ -192,6 +192,12 @@ void CResourceHandler::initialize()
 	addFilesystem("root", "local", localFS);
 }
 
+void CResourceHandler::destroy()
+{
+	knownLoaders.clear();
+	globalResourceHandler.rootLoader.reset();
+}
+
 ISimpleResourceLoader * CResourceHandler::get()
 {
 	return get("root");

+ 6 - 0
lib/filesystem/Filesystem.h

@@ -81,6 +81,12 @@ public:
 	 */
 	static void initialize();
 
+	/**
+	 * Destroys all existing data in filesystem, bringing it into uninitialized state
+	 *
+	 */
+	static void destroy();
+
 	/**
 	 * Will load all filesystem data from Json data at this path (normally - config/filesystem.json)
 	 * @param fsConfigURI - URI from which data will be loaded