瀏覽代碼

- Implemented proposition to install translation mod when necessary

Ivan Savenko 2 年之前
父節點
當前提交
a062e5e425

+ 7 - 1
config/schemas/settings.json

@@ -22,6 +22,7 @@
 				"music",
 				"sound",
 				"language",
+				"gameDataLanguage",
 				"swipe",
 				"swipeDesktop",
 				"saveRandomMaps",
@@ -63,9 +64,14 @@
 				},
 				"language" : {
 					"type":"string",
-					"enum" : [ "chinese", "english", "german", "korean", "polish", "russian", "ukrainian", "other_cp1250", "other_cp1251", "other_cp1252" ],
+					"enum" : [ "chinese", "english", "german", "polish", "russian", "ukrainian" ],
 					"default" : "english"
 				},
+				"gameDataLanguage" : {
+					"type":"string",
+					"enum" : [ "auto", "chinese", "english", "german", "korean", "polish", "russian", "ukrainian", "other_cp1250", "other_cp1251", "other_cp1252" ],
+					"default" : "auto"
+				},
 				"lastSave" : {
 					"type":"string",
 					"default" : "NEWGAME"

+ 1 - 24
launcher/firstLaunch/firstlaunch_moc.cpp

@@ -237,36 +237,13 @@ bool FirstLaunchView::heroesDataDetect()
 	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()
 {
 	Languages::fillLanguages(ui->comboBoxLanguage, true);
 
-	QString language = heroesLanguageDetect();
-
+	QString language = Languages::getHeroesDataLanguage();
 	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);

+ 0 - 1
launcher/firstLaunch/firstlaunch_moc.h

@@ -48,7 +48,6 @@ class FirstLaunchView : public QWidget
 	void heroesDataMissing();
 	void heroesDataDetected();
 
-	QString heroesLanguageDetect();
 	void heroesLanguageUpdate();
 	void forceHeroesLanguage(const QString & language);
 

+ 4 - 4
launcher/firstLaunch/firstlaunch_moc.ui

@@ -115,7 +115,7 @@
    <item>
     <widget class="QStackedWidget" name="installerTabs">
      <property name="currentIndex">
-      <number>2</number>
+      <number>1</number>
      </property>
      <widget class="QWidget" name="pageLanguageSelect">
       <layout class="QGridLayout" name="gridLayout_3">
@@ -381,7 +381,7 @@
             </sizepolicy>
            </property>
            <property name="text">
-            <string>Your Heroes III data files have been succesfully found.</string>
+            <string>Your Heroes III data files have been successfully found.</string>
            </property>
            <property name="wordWrap">
             <bool>true</bool>
@@ -411,7 +411,7 @@
          <item row="1" column="0" colspan="2">
           <widget class="QLabel" name="labelDataSuccess">
            <property name="text">
-            <string>Your Heroes III language has been succesfully detected.</string>
+            <string>Your Heroes III language has been successfully detected.</string>
            </property>
            <property name="wordWrap">
             <bool>true</bool>
@@ -581,7 +581,7 @@
             </sizepolicy>
            </property>
            <property name="text">
-            <string>Install English translation of Heroes III</string>
+            <string>Install translation of Heroes III to your language</string>
            </property>
            <property name="wordWrap">
             <bool>true</bool>

+ 51 - 2
launcher/languages.cpp

@@ -12,6 +12,7 @@
 
 #include "../lib/CConfigHandler.h"
 #include "../lib/Languages.h"
+#include "../lib/CGeneralTextHandler.h"
 
 #include <QComboBox>
 #include <QListWidget>
@@ -36,6 +37,27 @@ static const std::array<std::string, 12> languageTranslatedNamesGenerator = {
 
 static_assert(languageTranslatedNamesGenerator.size() == static_cast<size_t>(Languages::ELanguages::COUNT), "Languages array is missing a value!");
 
+QString Languages::getHeroesDataLanguage()
+{
+	CGeneralTextHandler::detectInstallParameters();
+
+	QString language = QString::fromStdString(settings["session"]["language"].String());
+	double deviation = settings["session"]["languageDeviation"].Float();
+
+	if(deviation > 0.05)
+		return QString();
+	return language;
+}
+
+QString generateAutodetectedLanguageName(QString const & language)
+{
+	std::string languageNameEnglish = Languages::getLanguageOptions(language.toStdString()).nameEnglish;
+	QString languageName = QApplication::translate( "Language", languageNameEnglish.c_str());
+	QString itemName = QApplication::translate("Language", "Auto (%1)").arg(languageName);
+
+	return itemName;
+}
+
 QString Languages::generateLanguageName(const Languages::Options & language)
 {
 	std::string activeLanguage = settings["general"]["language"].String();
@@ -59,7 +81,19 @@ void Languages::fillLanguages(QComboBox * widget, bool includeAll)
 	widget->blockSignals(true); // we do not want calls caused by initialization
 	widget->clear();
 
-	std::string activeLanguage = settings["general"]["language"].String();
+	std::string activeLanguage = includeAll ?
+		settings["general"]["gameDataLanguage"].String():
+		settings["general"]["language"].String();
+
+	if (includeAll)
+	{
+		QString language = getHeroesDataLanguage();
+		if (!language.isEmpty())
+			widget->addItem(generateAutodetectedLanguageName(language), QString("auto"));
+
+		if (activeLanguage == "auto")
+			widget->setCurrentIndex(0);
+	}
 
 	for(const auto & language : Languages::getLanguageList())
 	{
@@ -82,7 +116,22 @@ void Languages::fillLanguages(QListWidget * widget, bool includeAll)
 	widget->blockSignals(true); // we do not want calls caused by initialization
 	widget->clear();
 
-	std::string activeLanguage = settings["general"]["language"].String();
+	std::string activeLanguage = includeAll ?
+		settings["general"]["gameDataLanguage"].String():
+		settings["general"]["language"].String();
+
+	if (includeAll)
+	{
+		QString language = getHeroesDataLanguage();
+		if (!language.isEmpty())
+		{
+			widget->addItem(generateAutodetectedLanguageName(language));
+			widget->item(widget->count() - 1)->setData(Qt::UserRole, QString("auto"));
+
+			if (activeLanguage == "auto")
+				widget->setCurrentRow(0);
+		}
+	}
 
 	for(const auto & language : Languages::getLanguageList())
 	{

+ 2 - 1
launcher/languages.h

@@ -18,9 +18,10 @@ namespace Languages
 	struct Options;
 
 	QString generateLanguageName(const Languages::Options & identifier);
+	QString getHeroesDataLanguage();
 
 	/// if includeAll is set, all languages including encoding placeholders will be included into widget
 	void fillLanguages(QComboBox * widget, bool includeAll);
 	void fillLanguages(QListWidget * widget, bool includeAll);
-}
 
+}

+ 7 - 2
launcher/mainwindow_moc.cpp

@@ -142,6 +142,12 @@ void MainWindow::exitSetup()
 	ui->tabListWidget->setCurrentIndex(TabRows::MODS);
 }
 
+void MainWindow::switchToModsTab()
+{
+	ui->startGameButton->setEnabled(true);
+	ui->tabListWidget->setCurrentIndex(TabRows::MODS);
+}
+
 void MainWindow::changeEvent(QEvent *event)
 {
 	if(event->type() == QEvent::LanguageChange)
@@ -183,8 +189,7 @@ CModListView * MainWindow::getModView()
 
 void MainWindow::on_modslistButton_clicked()
 {
-	ui->startGameButton->setEnabled(true);
-	ui->tabListWidget->setCurrentIndex(TabRows::MODS);
+	switchToModsTab();
 }
 
 void MainWindow::on_settingsButton_clicked()

+ 1 - 0
launcher/mainwindow_moc.h

@@ -55,6 +55,7 @@ public:
 	
 	void enterSetup();
 	void exitSetup();
+	void switchToModsTab();
 
 public slots:
 	void on_startGameButton_clicked();

+ 12 - 1
launcher/modManager/cmodlist.cpp

@@ -158,6 +158,17 @@ QString CModEntry::getName() const
 }
 
 QVariant CModEntry::getValue(QString value) const
+{
+	return getValueImpl(value, true);
+}
+
+QVariant CModEntry::getBaseValue(QString value) const
+{
+	return getValueImpl(value, false);
+}
+
+QVariant CModEntry::getValueImpl(QString value, bool localized) const
+
 {
 	QString langValue = QString::fromStdString(settings["general"]["language"].String());
 
@@ -178,7 +189,7 @@ QVariant CModEntry::getValue(QString value) const
 
 	auto & storage = useRepositoryData ? repository : localData;
 
-	if(storage.contains(langValue))
+	if(localized && storage.contains(langValue))
 	{
 		auto langStorage = storage[langValue].toMap();
 		if (langStorage.contains(value))

+ 2 - 0
launcher/modManager/cmodlist.h

@@ -42,6 +42,7 @@ class CModEntry
 
 	QString modname;
 
+	QVariant getValueImpl(QString value, bool localized) const;
 public:
 	CModEntry(QVariantMap repository, QVariantMap localData, QVariantMap modSettings, QString modname);
 
@@ -69,6 +70,7 @@ public:
 
 	// get value of some field in mod structure. Returns empty optional if value is not present
 	QVariant getValue(QString value) const;
+	QVariant getBaseValue(QString value) const;
 
 	// returns true if less < greater comparing versions section by section
 	static bool compareVersions(QString lesser, QString greater);

+ 8 - 2
launcher/modManager/cmodlistview_moc.cpp

@@ -835,16 +835,22 @@ bool CModListView::isModInstalled(const QString & modName)
 	return mod.isInstalled();
 }
 
+bool CModListView::isModEnabled(const QString & modName)
+{
+	auto mod = modModel->getMod(modName);
+	return mod.isEnabled();
+}
+
 QString CModListView::getTranslationModName(const QString & language)
 {
 	for(const auto & modName : modModel->getModList())
 	{
 		auto mod = modModel->getMod(modName);
 
-		if (mod.getValue("type") != "localization")
+		if (mod.getBaseValue("modType").toString().toLower() != "translation")
 			continue;
 
-		if (mod.getValue("language") != language)
+		if (mod.getBaseValue("language").toString() != language)
 			continue;
 
 		return modName;

+ 3 - 0
launcher/modManager/cmodlistview_moc.h

@@ -92,6 +92,9 @@ public:
 	/// finds translation mod for specified languages. Returns empty string on error
 	QString getTranslationModName(const QString & language);
 
+	/// returns true if mod is currently enabled
+	bool isModEnabled(const QString & modName);
+
 public slots:
 	void enableModByName(QString modName);
 	void disableModByName(QString modName);

+ 87 - 0
launcher/settingsView/csettingsview_moc.cpp

@@ -13,6 +13,7 @@
 
 #include "mainwindow_moc.h"
 
+#include "../modManager/cmodlistview_moc.h"
 #include "../jsonutils.h"
 #include "../languages.h"
 #include "../launcherdirs.h"
@@ -313,10 +314,17 @@ void CSettingsView::changeEvent(QEvent *event)
 	{
 		ui->retranslateUi(this);
 		Languages::fillLanguages(ui->comboBoxLanguage, false);
+		loadTranslation();
 	}
 	QWidget::changeEvent(event);
 }
 
+void CSettingsView::showEvent(QShowEvent * event)
+{
+	loadTranslation();
+	QWidget::showEvent(event);
+}
+
 void CSettingsView::on_comboBoxCursorType_currentIndexChanged(int index)
 {
 	Settings node = settings.write["video"]["cursor"];
@@ -341,5 +349,84 @@ void CSettingsView::on_listWidgetSettings_currentRowChanged(int currentRow)
 	int maxPosition = ui->settingsScrollArea->verticalScrollBar()->maximum();
 	ui->settingsScrollArea->verticalScrollBar()->setValue(maxPosition);
 	ui->settingsScrollArea->ensureWidgetVisible(currentTarget, 5, 5);
+}
+
+void CSettingsView::loadTranslation()
+{
+	Languages::fillLanguages(ui->comboBoxLanguageBase, true);
+
+	QString baseLanguage = Languages::getHeroesDataLanguage();
+
+	auto * mainWindow = dynamic_cast<MainWindow *>(qApp->activeWindow());
+
+	if (!mainWindow)
+		return;
+
+	QString languageName = QString::fromStdString(settings["general"]["language"].String());
+	QString modName = mainWindow->getModView()->getTranslationModName(languageName);
+	bool translationExists = !modName.isEmpty();
+	bool translationNeeded = languageName != baseLanguage;
+	bool showTranslation = translationNeeded && translationExists;
+
+	ui->labelTranslation->setVisible(showTranslation);
+	ui->labelTranslationStatus->setVisible(showTranslation);
+	ui->pushButtonTranslation->setVisible(showTranslation);
+
+	if (!translationExists)
+		return;
+
+	bool translationInstalled = mainWindow->getModView()->isModInstalled(modName);
+	bool translationEnabled = mainWindow->getModView()->isModEnabled(modName);
+
+	ui->pushButtonTranslation->setVisible(!translationEnabled);
+
+	if (translationEnabled)
+	{
+		ui->labelTranslationStatus->setText(tr("Active"));
+	}
+
+	if (translationInstalled && !translationEnabled)
+	{
+		ui->labelTranslationStatus->setText(tr("Disabled"));
+		ui->pushButtonTranslation->setText(tr("Enable"));
+	}
+
+	if (!translationInstalled)
+	{
+		ui->labelTranslationStatus->setText(tr("Not Installed"));
+		ui->pushButtonTranslation->setText(tr("Install"));
+	}
+}
 
+void CSettingsView::on_pushButtonTranslation_clicked()
+{
+	auto * mainWindow = dynamic_cast<MainWindow *>(qApp->activeWindow());
+
+	assert(mainWindow);
+	if (!mainWindow)
+		return;
+
+	QString languageName = QString::fromStdString(settings["general"]["language"].String());
+	QString modName = mainWindow->getModView()->getTranslationModName(languageName);
+
+	assert(!modName.isEmpty());
+	if (modName.isEmpty())
+		return;
+
+	if (mainWindow->getModView()->isModInstalled(modName))
+	{
+		mainWindow->getModView()->enableModByName(modName);
+	}
+	else
+	{
+		mainWindow->switchToModsTab();
+		mainWindow->getModView()->doInstallMod(modName);
+	}
+}
+
+void CSettingsView::on_comboBoxLanguageBase_currentIndexChanged(int index)
+{
+	Settings node = settings.write["general"]["gameDataLanguage"];
+	QString selectedLanguage = ui->comboBoxLanguageBase->itemData(index).toString();
+	node->String() = selectedLanguage.toStdString();
 }

+ 5 - 19
launcher/settingsView/csettingsview_moc.h

@@ -24,8 +24,10 @@ public:
 	~CSettingsView();
 
 	void loadSettings();
+	void loadTranslation();
 	void setDisplayList();
 	void changeEvent(QEvent *event) override;
+	void showEvent(QShowEvent * event) override;
 
 	bool isExtraResolutionsModEnabled{};
 
@@ -34,44 +36,28 @@ public slots:
 
 private slots:
 	void on_comboBoxResolution_currentTextChanged(const QString & arg1);
-
 	void on_comboBoxFullScreen_currentIndexChanged(int index);
-
 	void on_comboBoxPlayerAI_currentIndexChanged(const QString & arg1);
-
 	void on_comboBoxFriendlyAI_currentIndexChanged(const QString & arg1);
-
 	void on_comboBoxNeutralAI_currentIndexChanged(const QString & arg1);
-
 	void on_comboBoxEnemyAI_currentIndexChanged(const QString & arg1);
-
 	void on_spinBoxNetworkPort_valueChanged(int arg1);
-
 	void on_plainTextEditRepos_textChanged();
-
 	void on_openTempDir_clicked();
-
 	void on_openUserDataDir_clicked();
-
 	void on_openGameDataDir_clicked();
-
 	void on_comboBoxShowIntro_currentIndexChanged(int index);
-
 	void on_changeGameDataDir_clicked();
-
 	void on_comboBoxAutoCheck_currentIndexChanged(int index);
-
 	void on_comboBoxDisplayIndex_currentIndexChanged(int index);
-
 	void on_comboBoxAutoSave_currentIndexChanged(int index);
-
 	void on_updatesButton_clicked();
-
 	void on_comboBoxLanguage_currentIndexChanged(int index);
-
 	void on_comboBoxCursorType_currentIndexChanged(int index);
-
 	void on_listWidgetSettings_currentRowChanged(int currentRow);
+	void on_pushButtonTranslation_clicked();
+
+	void on_comboBoxLanguageBase_currentIndexChanged(int index);
 
 private:
 	Ui::CSettingsView * ui;

+ 254 - 223
launcher/settingsView/csettingsview_moc.ui

@@ -114,137 +114,139 @@
         <x>0</x>
         <y>0</y>
         <width>620</width>
-        <height>731</height>
+        <height>793</height>
        </rect>
       </property>
       <layout class="QGridLayout" name="gridLayout" columnstretch="3,0,0,0">
-       <item row="22" column="0" colspan="4">
-        <widget class="QPlainTextEdit" name="plainTextEditRepos">
-         <property name="lineWrapMode">
-          <enum>QPlainTextEdit::NoWrap</enum>
-         </property>
-         <property name="plainText">
-          <string notr="true">http://downloads.vcmi.eu/Mods/repository.json</string>
+       <item row="19" column="1" colspan="3">
+        <widget class="QComboBox" name="comboBoxEnemyAI">
+         <property name="editable">
+          <bool>false</bool>
          </property>
-        </widget>
-       </item>
-       <item row="12" column="1" colspan="3">
-        <widget class="QComboBox" name="comboBoxPlayerAI">
          <property name="currentText">
-          <string notr="true">VCAI</string>
+          <string notr="true">BattleAI</string>
          </property>
          <item>
           <property name="text">
-           <string notr="true">VCAI</string>
+           <string notr="true">BattleAI</string>
           </property>
          </item>
          <item>
           <property name="text">
-           <string notr="true">Nullkiller</string>
+           <string notr="true">StupidAI</string>
           </property>
          </item>
         </widget>
        </item>
-       <item row="15" column="0">
-        <widget class="QLabel" name="labelEnemyAI">
+       <item row="1" column="0">
+        <widget class="QLabel" name="labelLanguage">
          <property name="text">
-          <string>Enemy AI</string>
+          <string>VCMI Language</string>
          </property>
         </widget>
        </item>
-       <item row="21" column="2" colspan="2">
-        <widget class="QPushButton" name="updatesButton">
+       <item row="6" column="0">
+        <widget class="QLabel" name="labelNetworkPort">
          <property name="text">
-          <string>Update now</string>
+          <string>Network port</string>
          </property>
         </widget>
        </item>
-       <item row="2" column="0">
-        <widget class="QLabel" name="labelNetworkPort">
+       <item row="11" column="0">
+        <widget class="QLabel" name="labelFullScreen">
          <property name="text">
-          <string>Network port</string>
+          <string>Fullscreen</string>
          </property>
         </widget>
        </item>
-       <item row="14" column="1" colspan="3">
-        <widget class="QComboBox" name="comboBoxFriendlyAI">
-         <property name="editable">
-          <bool>false</bool>
-         </property>
-         <property name="currentText">
-          <string notr="true">BattleAI</string>
+       <item row="10" column="0">
+        <widget class="QLabel" name="labelResolution">
+         <property name="text">
+          <string>Resolution</string>
          </property>
-         <item>
-          <property name="text">
-           <string notr="true">BattleAI</string>
-          </property>
-         </item>
-         <item>
-          <property name="text">
-           <string notr="true">StupidAI</string>
-          </property>
-         </item>
         </widget>
        </item>
-       <item row="13" column="1" colspan="3">
-        <widget class="QComboBox" name="comboBoxNeutralAI">
-         <property name="currentText">
-          <string notr="true">BattleAI</string>
+       <item row="17" column="0">
+        <widget class="QLabel" name="labelNeutralAI">
+         <property name="text">
+          <string>Neutral AI</string>
          </property>
-         <item>
-          <property name="text">
-           <string notr="true">BattleAI</string>
-          </property>
-         </item>
-         <item>
-          <property name="text">
-           <string notr="true">StupidAI</string>
-          </property>
-         </item>
         </widget>
        </item>
-       <item row="3" column="0">
+       <item row="7" column="0">
         <widget class="QLabel" name="labelAutoSave">
          <property name="text">
           <string>Autosave</string>
          </property>
         </widget>
        </item>
-       <item row="17" column="1">
-        <widget class="QLineEdit" name="lineEditGameDir">
+       <item row="9" column="0">
+        <widget class="QLabel" name="labelVideo">
+         <property name="font">
+          <font>
+           <weight>75</weight>
+           <bold>true</bold>
+          </font>
+         </property>
          <property name="text">
-          <string notr="true">/usr/share/vcmi</string>
+          <string>Video</string>
          </property>
         </widget>
        </item>
-       <item row="19" column="3">
-        <widget class="QPushButton" name="openTempDir">
+       <item row="23" column="1" colspan="2">
+        <widget class="QLineEdit" name="lineEditTempDir">
+         <property name="enabled">
+          <bool>false</bool>
+         </property>
          <property name="text">
-          <string>Open</string>
+          <string notr="true">/home/user/.vcmi</string>
+         </property>
+         <property name="readOnly">
+          <bool>true</bool>
          </property>
         </widget>
        </item>
-       <item row="8" column="0">
-        <widget class="QLabel" name="labelShowIntro">
+       <item row="13" column="1" colspan="3">
+        <widget class="QComboBox" name="comboBoxDisplayIndex"/>
+       </item>
+       <item row="14" column="0">
+        <widget class="QLabel" name="labelCursorType">
          <property name="text">
-          <string>Show intro</string>
+          <string>Cursor</string>
          </property>
         </widget>
        </item>
-       <item row="18" column="1" colspan="2">
-        <widget class="QLineEdit" name="lineEditUserDataDir">
-         <property name="enabled">
-          <bool>false</bool>
-         </property>
+       <item row="22" column="3">
+        <widget class="QPushButton" name="openUserDataDir">
          <property name="text">
-          <string notr="true">/home/user/.vcmi</string>
+          <string>Open</string>
          </property>
-         <property name="readOnly">
-          <bool>true</bool>
+        </widget>
+       </item>
+       <item row="1" column="1" colspan="3">
+        <widget class="QComboBox" name="comboBoxLanguage"/>
+       </item>
+       <item row="18" column="1" colspan="3">
+        <widget class="QComboBox" name="comboBoxFriendlyAI">
+         <property name="editable">
+          <bool>false</bool>
          </property>
+         <property name="currentText">
+          <string notr="true">BattleAI</string>
+         </property>
+         <item>
+          <property name="text">
+           <string notr="true">BattleAI</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string notr="true">StupidAI</string>
+          </property>
+         </item>
         </widget>
        </item>
-       <item row="7" column="1" colspan="3">
+       <item row="11" column="1" colspan="3">
         <widget class="QComboBox" name="comboBoxFullScreen">
          <property name="currentIndex">
           <number>0</number>
@@ -266,27 +268,27 @@
          </item>
         </widget>
        </item>
-       <item row="20" column="0">
-        <widget class="QLabel" name="labelRepositories">
-         <property name="font">
-          <font>
-           <weight>75</weight>
-           <bold>true</bold>
-          </font>
+       <item row="6" column="1" colspan="3">
+        <widget class="QSpinBox" name="spinBoxNetworkPort">
+         <property name="minimum">
+          <number>1024</number>
          </property>
-         <property name="text">
-          <string>Mod Repositories</string>
+         <property name="maximum">
+          <number>65535</number>
+         </property>
+         <property name="value">
+          <number>3030</number>
          </property>
         </widget>
        </item>
-       <item row="9" column="0">
-        <widget class="QLabel" name="labelDisplayIndex">
+       <item row="23" column="3">
+        <widget class="QPushButton" name="openTempDir">
          <property name="text">
-          <string>Display index</string>
+          <string>Open</string>
          </property>
         </widget>
        </item>
-       <item row="3" column="1" colspan="3">
+       <item row="7" column="1" colspan="3">
         <widget class="QComboBox" name="comboBoxAutoSave">
          <property name="currentIndex">
           <number>1</number>
@@ -303,8 +305,8 @@
          </item>
         </widget>
        </item>
-       <item row="5" column="0">
-        <widget class="QLabel" name="labelVideo">
+       <item row="20" column="0">
+        <widget class="QLabel" name="labelDataDirs">
          <property name="font">
           <font>
            <weight>75</weight>
@@ -312,80 +314,97 @@
           </font>
          </property>
          <property name="text">
-          <string>Video</string>
+          <string>Data Directories</string>
          </property>
         </widget>
        </item>
-       <item row="19" column="0">
-        <widget class="QLabel" name="labelTempDir">
+       <item row="21" column="2">
+        <widget class="QPushButton" name="changeGameDataDir">
+         <property name="enabled">
+          <bool>false</bool>
+         </property>
          <property name="text">
-          <string>Log files directory</string>
+          <string>Change</string>
          </property>
         </widget>
        </item>
-       <item row="15" column="1" colspan="3">
-        <widget class="QComboBox" name="comboBoxEnemyAI">
-         <property name="editable">
-          <bool>false</bool>
-         </property>
-         <property name="currentText">
-          <string notr="true">BattleAI</string>
+       <item row="22" column="0">
+        <widget class="QLabel" name="labelUserDataDir">
+         <property name="text">
+          <string>User data directory</string>
          </property>
-         <item>
-          <property name="text">
-           <string notr="true">BattleAI</string>
-          </property>
-         </item>
-         <item>
-          <property name="text">
-           <string notr="true">StupidAI</string>
-          </property>
-         </item>
         </widget>
        </item>
-       <item row="4" column="0">
+       <item row="8" column="0">
         <widget class="QLabel" name="labelBuildVersionDesc">
          <property name="text">
           <string>Build version</string>
          </property>
         </widget>
        </item>
-       <item row="17" column="3">
-        <widget class="QPushButton" name="openGameDataDir">
+       <item row="0" column="0">
+        <widget class="QLabel" name="labelGeneral">
+         <property name="font">
+          <font>
+           <weight>75</weight>
+           <bold>true</bold>
+          </font>
+         </property>
          <property name="text">
-          <string>Open</string>
+          <string>General</string>
          </property>
         </widget>
        </item>
-       <item row="4" column="1" colspan="3">
-        <widget class="QLineEdit" name="lineEditBuildVersion">
+       <item row="12" column="0">
+        <widget class="QLabel" name="labelShowIntro">
          <property name="text">
-          <string notr="true"/>
+          <string>Show intro</string>
          </property>
-         <property name="readOnly">
-          <bool>true</bool>
+        </widget>
+       </item>
+       <item row="25" column="2" colspan="2">
+        <widget class="QPushButton" name="updatesButton">
+         <property name="text">
+          <string>Update now</string>
          </property>
         </widget>
        </item>
-       <item row="8" column="1" colspan="3">
-        <widget class="QComboBox" name="comboBoxShowIntro">
-         <property name="currentIndex">
-          <number>1</number>
+       <item row="13" column="0">
+        <widget class="QLabel" name="labelDisplayIndex">
+         <property name="text">
+          <string>Display index</string>
+         </property>
+        </widget>
+       </item>
+       <item row="21" column="1">
+        <widget class="QLineEdit" name="lineEditGameDir">
+         <property name="text">
+          <string notr="true">/usr/share/vcmi</string>
+         </property>
+        </widget>
+       </item>
+       <item row="17" column="1" colspan="3">
+        <widget class="QComboBox" name="comboBoxNeutralAI">
+         <property name="currentText">
+          <string notr="true">BattleAI</string>
          </property>
          <item>
           <property name="text">
-           <string>Off</string>
+           <string notr="true">BattleAI</string>
           </property>
          </item>
          <item>
           <property name="text">
-           <string>On</string>
+           <string notr="true">StupidAI</string>
           </property>
          </item>
         </widget>
        </item>
-       <item row="11" column="0">
-        <widget class="QLabel" name="labelArtificialIntelligence">
+       <item row="10" column="1" colspan="3">
+        <widget class="QComboBox" name="comboBoxResolution"/>
+       </item>
+       <item row="24" column="0">
+        <widget class="QLabel" name="labelRepositories">
          <property name="font">
           <font>
            <weight>75</weight>
@@ -393,79 +412,43 @@
           </font>
          </property>
          <property name="text">
-          <string>Artificial Intelligence</string>
+          <string>Mod Repositories</string>
          </property>
         </widget>
        </item>
-       <item row="6" column="0">
-        <widget class="QLabel" name="labelResolution">
+       <item row="18" column="0">
+        <widget class="QLabel" name="labelFriendlyAI">
          <property name="text">
-          <string>Resolution</string>
+          <string>Friendly AI</string>
          </property>
         </widget>
        </item>
-       <item row="10" column="0">
-        <widget class="QLabel" name="labelCursorType">
+       <item row="25" column="0">
+        <widget class="QLabel" name="labelAutoCheck">
          <property name="text">
-          <string>Cursor</string>
+          <string>Check on startup</string>
          </property>
         </widget>
        </item>
-       <item row="13" column="0">
-        <widget class="QLabel" name="labelNeutralAI">
-         <property name="text">
-          <string>Neutral AI</string>
+       <item row="12" column="1" colspan="3">
+        <widget class="QComboBox" name="comboBoxShowIntro">
+         <property name="currentIndex">
+          <number>1</number>
          </property>
-        </widget>
-       </item>
-       <item row="10" column="1" colspan="3">
-        <widget class="QComboBox" name="comboBoxCursorType">
-         <item>
-          <property name="text">
-           <string>Default</string>
-          </property>
-         </item>
          <item>
           <property name="text">
-           <string>Hardware</string>
+           <string>Off</string>
           </property>
          </item>
          <item>
           <property name="text">
-           <string>Software</string>
+           <string>On</string>
           </property>
          </item>
         </widget>
        </item>
-       <item row="21" column="0">
-        <widget class="QLabel" name="labelAutoCheck">
-         <property name="text">
-          <string>Check on startup</string>
-         </property>
-        </widget>
-       </item>
-       <item row="18" column="3">
-        <widget class="QPushButton" name="openUserDataDir">
-         <property name="text">
-          <string>Open</string>
-         </property>
-        </widget>
-       </item>
-       <item row="7" column="0">
-        <widget class="QLabel" name="labelFullScreen">
-         <property name="text">
-          <string>Fullscreen</string>
-         </property>
-        </widget>
-       </item>
-       <item row="9" column="1" colspan="3">
-        <widget class="QComboBox" name="comboBoxDisplayIndex"/>
-       </item>
-       <item row="6" column="1" colspan="3">
-        <widget class="QComboBox" name="comboBoxResolution"/>
-       </item>
-       <item row="19" column="1" colspan="2">
-        <widget class="QLineEdit" name="lineEditTempDir">
+       <item row="22" column="1" colspan="2">
+        <widget class="QLineEdit" name="lineEditUserDataDir">
          <property name="enabled">
           <bool>false</bool>
          </property>
@@ -477,14 +460,24 @@
          </property>
         </widget>
        </item>
-       <item row="1" column="0">
-        <widget class="QLabel" name="labelLanguage">
+       <item row="21" column="0">
+        <widget class="QLabel" name="labelGameDir">
          <property name="text">
-          <string>VCMI Language</string>
+          <string>Extra data directory</string>
          </property>
         </widget>
        </item>
-       <item row="21" column="1">
+       <item row="21" column="3">
+        <widget class="QPushButton" name="openGameDataDir">
+         <property name="text">
+          <string>Open</string>
+         </property>
+        </widget>
+       </item>
+       <item row="4" column="1" colspan="3">
+        <widget class="QComboBox" name="comboBoxLanguageBase"/>
+       </item>
+       <item row="25" column="1">
         <widget class="QComboBox" name="comboBoxAutoCheck">
          <property name="currentIndex">
           <number>1</number>
@@ -501,31 +494,78 @@
          </item>
         </widget>
        </item>
-       <item row="12" column="0">
-        <widget class="QLabel" name="labelPlayerAI">
+       <item row="4" column="0">
+        <widget class="QLabel" name="labelLanguageBase">
          <property name="text">
-          <string>Adventure Map AI</string>
+          <string>Heroes III Data Language</string>
          </property>
         </widget>
        </item>
-       <item row="1" column="1" colspan="3">
-        <widget class="QComboBox" name="comboBoxLanguage"/>
+       <item row="16" column="1" colspan="3">
+        <widget class="QComboBox" name="comboBoxPlayerAI">
+         <property name="currentText">
+          <string notr="true">VCAI</string>
+         </property>
+         <item>
+          <property name="text">
+           <string notr="true">VCAI</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string notr="true">Nullkiller</string>
+          </property>
+         </item>
+        </widget>
        </item>
-       <item row="16" column="0">
-        <widget class="QLabel" name="labelDataDirs">
-         <property name="font">
-          <font>
-           <weight>75</weight>
-           <bold>true</bold>
-          </font>
+       <item row="8" column="1" colspan="3">
+        <widget class="QLineEdit" name="lineEditBuildVersion">
+         <property name="text">
+          <string notr="true"/>
          </property>
+         <property name="readOnly">
+          <bool>true</bool>
+         </property>
+        </widget>
+       </item>
+       <item row="19" column="0">
+        <widget class="QLabel" name="labelEnemyAI">
          <property name="text">
-          <string>Data Directories</string>
+          <string>Enemy AI</string>
          </property>
         </widget>
        </item>
-       <item row="0" column="0">
-        <widget class="QLabel" name="labelGeneral">
+       <item row="26" column="0" colspan="4">
+        <widget class="QPlainTextEdit" name="plainTextEditRepos">
+         <property name="lineWrapMode">
+          <enum>QPlainTextEdit::NoWrap</enum>
+         </property>
+         <property name="plainText">
+          <string notr="true">http://downloads.vcmi.eu/Mods/repository.json</string>
+         </property>
+        </widget>
+       </item>
+       <item row="14" column="1" colspan="3">
+        <widget class="QComboBox" name="comboBoxCursorType">
+         <item>
+          <property name="text">
+           <string>Default</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>Hardware</string>
+          </property>
+         </item>
+         <item>
+          <property name="text">
+           <string>Software</string>
+          </property>
+         </item>
+        </widget>
+       </item>
+       <item row="15" column="0">
+        <widget class="QLabel" name="labelArtificialIntelligence">
          <property name="font">
           <font>
            <weight>75</weight>
@@ -533,51 +573,42 @@
           </font>
          </property>
          <property name="text">
-          <string>General</string>
+          <string>Artificial Intelligence</string>
          </property>
         </widget>
        </item>
-       <item row="18" column="0">
-        <widget class="QLabel" name="labelUserDataDir">
+       <item row="23" column="0">
+        <widget class="QLabel" name="labelTempDir">
          <property name="text">
-          <string>User data directory</string>
+          <string>Log files directory</string>
          </property>
         </widget>
        </item>
-       <item row="17" column="0">
-        <widget class="QLabel" name="labelGameDir">
+       <item row="16" column="0">
+        <widget class="QLabel" name="labelPlayerAI">
          <property name="text">
-          <string>Extra data directory</string>
+          <string>Adventure Map AI</string>
          </property>
         </widget>
        </item>
-       <item row="14" column="0">
-        <widget class="QLabel" name="labelFriendlyAI">
+       <item row="5" column="0">
+        <widget class="QLabel" name="labelTranslation">
          <property name="text">
-          <string>Friendly AI</string>
+          <string>Heroes III Translation</string>
          </property>
         </widget>
        </item>
-       <item row="2" column="1" colspan="3">
-        <widget class="QSpinBox" name="spinBoxNetworkPort">
-         <property name="minimum">
-          <number>1024</number>
-         </property>
-         <property name="maximum">
-          <number>65535</number>
-         </property>
-         <property name="value">
-          <number>3030</number>
+       <item row="5" column="3">
+        <widget class="QPushButton" name="pushButtonTranslation">
+         <property name="text">
+          <string/>
          </property>
         </widget>
        </item>
-       <item row="17" column="2">
-        <widget class="QPushButton" name="changeGameDataDir">
-         <property name="enabled">
-          <bool>false</bool>
-         </property>
+       <item row="5" column="1" colspan="2">
+        <widget class="QLabel" name="labelTranslationStatus">
          <property name="text">
-          <string>Change</string>
+          <string/>
          </property>
         </widget>
        </item>