1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-22 22:13:35 +02:00

Moved Install from file button from Mods to Start Game tab

This commit is contained in:
Ivan Savenko 2024-12-04 15:19:02 +00:00
parent 4e83120882
commit d34ad05c36
9 changed files with 185 additions and 167 deletions

View File

@ -203,12 +203,6 @@ void MainWindow::on_startGameButton_clicked()
switchToStartTab();
}
void MainWindow::on_startEditorButton_clicked()
{
hide();
startEditor({});
}
CModListView * MainWindow::getModView()
{
return ui->modlistView;
@ -231,6 +225,67 @@ void MainWindow::on_aboutButton_clicked()
ui->tabListWidget->setCurrentIndex(TabRows::ABOUT);
}
void MainWindow::dragEnterEvent(QDragEnterEvent* event)
{
if(event->mimeData()->hasUrls())
for(const auto & url : event->mimeData()->urls())
for(const auto & ending : QStringList({".zip", ".h3m", ".h3c", ".vmap", ".vcmp", ".json", ".exe"}))
if(url.fileName().endsWith(ending, Qt::CaseInsensitive))
{
event->acceptProposedAction();
return;
}
}
void MainWindow::dropEvent(QDropEvent* event)
{
const QMimeData* mimeData = event->mimeData();
if(mimeData->hasUrls())
{
const QList<QUrl> urlList = mimeData->urls();
for (const auto & url : urlList)
manualInstallFile(url.toLocalFile());
}
}
void MainWindow::manualInstallFile(QString filePath)
{
QString fileName = QFileInfo{filePath}.fileName();
if(filePath.endsWith(".zip", Qt::CaseInsensitive))
getModView()->downloadFile(fileName.toLower()
// mod name currently comes from zip file -> remove suffixes from github zip download
.replace(QRegularExpression("-[0-9a-f]{40}"), "")
.replace(QRegularExpression("-vcmi-.+\\.zip"), ".zip")
.replace("-main.zip", ".zip")
, QUrl::fromLocalFile(filePath), "mods");
else if(filePath.endsWith(".json", Qt::CaseInsensitive))
{
QDir configDir(QString::fromStdString(VCMIDirs::get().userConfigPath().string()));
QStringList configFile = configDir.entryList({fileName}, QDir::Filter::Files); // case insensitive check
if(!configFile.empty())
{
auto dialogResult = QMessageBox::warning(this, tr("Replace config file?"), tr("Do you want to replace %1?").arg(configFile[0]), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
if(dialogResult == QMessageBox::Yes)
{
const auto configFilePath = configDir.filePath(configFile[0]);
QFile::remove(configFilePath);
QFile::copy(filePath, configFilePath);
// reload settings
Helper::loadSettings();
for(const auto widget : qApp->allWidgets())
if(auto settingsView = qobject_cast<CSettingsView *>(widget))
settingsView->loadSettings();
getModView()->reload();
}
}
}
else
getModView()->downloadFile(fileName, QUrl::fromLocalFile(filePath), fileName);
}
void MainWindow::updateTranslation()
{
#ifdef ENABLE_QT_TRANSLATIONS

View File

@ -58,6 +58,10 @@ public:
void switchToModsTab();
void switchToStartTab();
void dragEnterEvent(QDragEnterEvent* event) override;
void dropEvent(QDropEvent *event) override;
void manualInstallFile(QString filePath);
protected:
void changeEvent(QEvent * event) override;
@ -67,6 +71,5 @@ public slots:
private slots:
void on_modslistButton_clicked();
void on_settingsButton_clicked();
void on_startEditorButton_clicked();
void on_aboutButton_clicked();
};

View File

@ -62,7 +62,7 @@
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="autoExclusive">
<bool>true</bool>
@ -218,7 +218,7 @@
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="autoExclusive">
<bool>true</bool>

View File

@ -59,30 +59,6 @@ void CModListView::changeEvent(QEvent *event)
QWidget::changeEvent(event);
}
void CModListView::dragEnterEvent(QDragEnterEvent* event)
{
if(event->mimeData()->hasUrls())
for(const auto & url : event->mimeData()->urls())
for(const auto & ending : QStringList({".zip", ".h3m", ".h3c", ".vmap", ".vcmp", ".json", ".exe"}))
if(url.fileName().endsWith(ending, Qt::CaseInsensitive))
{
event->acceptProposedAction();
return;
}
}
void CModListView::dropEvent(QDropEvent* event)
{
const QMimeData* mimeData = event->mimeData();
if(mimeData->hasUrls())
{
const QList<QUrl> urlList = mimeData->urls();
for (const auto & url : urlList)
manualInstallFile(url.toLocalFile());
}
}
void CModListView::setupFilterModel()
{
filterModel = new CModFilterModel(modModel, this);
@ -169,6 +145,12 @@ CModListView::CModListView(QWidget * parent)
#endif
}
void CModListView::reload()
{
modStateModel->reloadLocalState();
modModel->reloadRepositories();
}
void CModListView::loadRepositories()
{
QStringList repositories;
@ -642,73 +624,6 @@ void CModListView::on_installButton_clicked()
}
}
void CModListView::on_installFromFileButton_clicked()
{
// iOS can't display modal dialogs when called directly on button press
// https://bugreports.qt.io/browse/QTBUG-98651
QTimer::singleShot(0, this, [this]
{
QString filter = tr("All supported files") + " (*.h3m *.vmap *.h3c *.vcmp *.zip *.json *.exe);;" +
tr("Maps") + " (*.h3m *.vmap);;" +
tr("Campaigns") + " (*.h3c *.vcmp);;" +
tr("Configs") + " (*.json);;" +
tr("Mods") + " (*.zip);;" +
tr("Gog files") + " (*.exe)";
#if defined(VCMI_MOBILE)
filter = tr("All files (*.*)"); //Workaround for sometimes incorrect mime for some extensions (e.g. for exe)
#endif
QStringList files = QFileDialog::getOpenFileNames(this, tr("Select files (configs, mods, maps, campaigns, gog files) to install..."), QDir::homePath(), filter);
for(const auto & file : files)
{
manualInstallFile(file);
}
});
}
void CModListView::manualInstallFile(QString filePath)
{
QString fileName = QFileInfo{filePath}.fileName();
if(filePath.endsWith(".zip", Qt::CaseInsensitive))
downloadFile(fileName.toLower()
// mod name currently comes from zip file -> remove suffixes from github zip download
.replace(QRegularExpression("-[0-9a-f]{40}"), "")
.replace(QRegularExpression("-vcmi-.+\\.zip"), ".zip")
.replace("-main.zip", ".zip")
, QUrl::fromLocalFile(filePath), "mods");
else if(filePath.endsWith(".json", Qt::CaseInsensitive))
{
QDir configDir(QString::fromStdString(VCMIDirs::get().userConfigPath().string()));
QStringList configFile = configDir.entryList({fileName}, QDir::Filter::Files); // case insensitive check
if(!configFile.empty())
{
auto dialogResult = QMessageBox::warning(this, tr("Replace config file?"), tr("Do you want to replace %1?").arg(configFile[0]), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
if(dialogResult == QMessageBox::Yes)
{
const auto configFilePath = configDir.filePath(configFile[0]);
QFile::remove(configFilePath);
QFile::copy(filePath, configFilePath);
// reload settings
Helper::loadSettings();
for(const auto widget : qApp->allWidgets())
if(auto settingsView = qobject_cast<CSettingsView *>(widget))
settingsView->loadSettings();
modStateModel->reloadLocalState();
modModel->reloadRepositories();
}
}
}
else
downloadFile(fileName, QUrl::fromLocalFile(filePath), fileName);
}
void CModListView::downloadFile(QString file, QString url, QString description, qint64 sizeBytes)
{
downloadFile(file, QUrl{url}, description, sizeBytes);
}
void CModListView::downloadFile(QString file, QUrl url, QString description, qint64 sizeBytes)
{
if(!dlManager)

View File

@ -52,9 +52,6 @@ class CModListView : public QWidget
// find mods unknown to mod list (not present in repo and not installed)
QStringList findUnavailableMods(QStringList candidates);
void manualInstallFile(QString filePath);
void downloadFile(QString file, QString url, QString description, qint64 sizeBytes = 0);
void downloadFile(QString file, QUrl url, QString description, qint64 sizeBytes = 0);
void installMods(QStringList archives);
void installMaps(QStringList maps);
@ -64,8 +61,6 @@ class CModListView : public QWidget
QString genModInfoText(const ModState & mod);
void changeEvent(QEvent *event) override;
void dragEnterEvent(QDragEnterEvent* event) override;
void dropEvent(QDropEvent *event) override;
public:
explicit CModListView(QWidget * parent = nullptr);
@ -74,6 +69,8 @@ public:
void loadScreenshots();
void loadRepositories();
void reload();
void disableModInfo();
void selectMod(const QModelIndex & index);
@ -95,6 +92,8 @@ public:
/// returns true if mod is currently installed
bool isModInstalled(const QString & modName);
void downloadFile(QString file, QUrl url, QString description, qint64 sizeBytes = 0);
public slots:
void enableModByName(QString modName);
void disableModByName(QString modName);
@ -109,31 +108,17 @@ private slots:
void hideProgressBar();
void on_lineEdit_textChanged(const QString & arg1);
void on_comboBox_currentIndexChanged(int index);
void on_enableButton_clicked();
void on_disableButton_clicked();
void on_updateButton_clicked();
void on_uninstallButton_clicked();
void on_installButton_clicked();
void on_installFromFileButton_clicked();
void on_pushButton_clicked();
void on_refreshButton_clicked();
void on_allModsView_activated(const QModelIndex & index);
void on_tabWidget_currentChanged(int index);
void on_screenshotsList_clicked(const QModelIndex & index);
void on_allModsView_doubleClicked(const QModelIndex &index);
private:

View File

@ -191,7 +191,9 @@
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; }
hr { height: 1px; border-width: 0; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'.AppleSystemUIFont'; font-size:13pt; font-weight:400; font-style:normal;&quot;&gt;
li.unchecked::marker { content: &quot;\2610&quot;; }
li.checked::marker { content: &quot;\2612&quot;; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Ubuntu'; font-size:11pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
@ -349,41 +351,6 @@ hr { height: 1px; border-width: 0; }
<property name="spacing">
<number>6</number>
</property>
<item>
<widget class="QPushButton" name="installFromFileButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>51</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>170</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Install from file</string>
</property>
<property name="icon">
<iconset>
<normaloff>icons:mod-download.png</normaloff>icons:mod-download.png</iconset>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="modButtonSpacer">
<property name="orientation">

View File

@ -4,7 +4,10 @@
#include "../mainwindow_moc.h"
#include "../main.h"
#include "../modManager/cmodlistview_moc.h"
#include "../../lib/filesystem/Filesystem.h"
#include "../../lib/VCMIDirs.h"
StartGameTab::StartGameTab(QWidget * parent)
: QWidget(parent)
@ -13,6 +16,8 @@ StartGameTab::StartGameTab(QWidget * parent)
ui->setupUi(this);
refreshState();
ui->buttonGameResume->setVisible(false); // TODO: implement
}
StartGameTab::~StartGameTab()
@ -29,6 +34,14 @@ MainWindow * StartGameTab::getMainWindow()
}
void StartGameTab::refreshState()
{
refreshGameData();
refreshUpdateStatus(EGameUpdateStatus::NOT_CHECKED);//TODO
refreshTranslation(ETranslationStatus::ACTIVE);
refreshMods();
}
void StartGameTab::refreshGameData()
{
// Some players are using pirated version of the game with some of the files missing
// leading to broken town hall menu (and possibly other dialogs)
@ -55,9 +68,6 @@ void StartGameTab::refreshState()
"DATA/FOOL",
};
bool updateAvailable = false;
bool checkedForUpdate = false;
bool missingSoundtrack = !CResourceHandler::get()->existsResource(AudioPath::builtin("Music/MainMenu"));
bool missingVideoFiles = !CResourceHandler::get()->existsResource(VideoPath::builtin("Video/H3Intro"));
bool missingGameFiles = false;
@ -69,13 +79,6 @@ void StartGameTab::refreshState()
for (const auto & filename : armaggedonBladeCampaigns)
missingCampaings &= !CResourceHandler::get()->existsResource(ResourcePath(filename, EResType::CAMPAIGN));
ui->buttonEngine->setText("VCMI " VCMI_VERSION_STRING);
ui->buttonUpdateCheck->setVisible(!checkedForUpdate);
ui->labelUpdateAvailable->setVisible(checkedForUpdate && updateAvailable);
ui->labelUpdateNotFound->setVisible(checkedForUpdate && !updateAvailable);
ui->buttonOpenChangelog->setVisible(checkedForUpdate && updateAvailable);
ui->buttonOpenDownloads->setVisible(checkedForUpdate && updateAvailable);
ui->labelMissingCampaigns->setVisible(missingCampaings);
ui->labelMissingFiles->setVisible(missingGameFiles);
ui->labelMissingVideo->setVisible(missingVideoFiles);
@ -85,6 +88,35 @@ void StartGameTab::refreshState()
ui->buttonMissingFilesHelp->setVisible(missingGameFiles);
ui->buttonMissingVideoHelp->setVisible(missingVideoFiles);
ui->buttonMissingSoundtrackHelp->setVisible(missingSoundtrack);
// TODO: Chronicles
}
void StartGameTab::refreshTranslation(ETranslationStatus status)
{
ui->buttonInstallTranslation->setVisible(status == ETranslationStatus::NOT_INSTALLLED);
ui->buttonInstallTranslationHelp->setVisible(status == ETranslationStatus::NOT_INSTALLLED);
ui->buttonActivateTranslation->setVisible(status == ETranslationStatus::NOT_INSTALLLED);
ui->buttonActivateTranslationHelp->setVisible(status == ETranslationStatus::NOT_INSTALLLED);
}
void StartGameTab::refreshMods()
{
QStringList updateableMods;
ui->buttonUpdateMods->setVisible(!updateableMods.empty());
ui->buttonUpdateModsHelp->setVisible(!updateableMods.empty());
}
void StartGameTab::refreshUpdateStatus(EGameUpdateStatus status)
{
ui->buttonEngine->setText("VCMI " VCMI_VERSION_STRING);
ui->buttonUpdateCheck->setVisible(status == EGameUpdateStatus::NOT_CHECKED);
ui->labelUpdateNotFound->setVisible(status == EGameUpdateStatus::NO_UPDATE);
ui->labelUpdateAvailable->setVisible(status == EGameUpdateStatus::UPDATE_AVAILABLE);
ui->buttonOpenChangelog->setVisible(status == EGameUpdateStatus::UPDATE_AVAILABLE);
ui->buttonOpenDownloads->setVisible(status == EGameUpdateStatus::UPDATE_AVAILABLE);
}
void StartGameTab::on_buttonGameStart_clicked()
@ -93,7 +125,6 @@ void StartGameTab::on_buttonGameStart_clicked()
startGame({});
}
void StartGameTab::on_buttonOpenChangelog_clicked()
{
QDesktopServices::openUrl(QUrl("https://vcmi.eu/ChangeLog/"));
@ -111,3 +142,40 @@ void StartGameTab::on_buttonUpdateCheck_clicked()
// TODO: implement
}
void StartGameTab::on_buttonGameEditor_clicked()
{
getMainWindow()->hide();
startEditor({});
}
void StartGameTab::on_buttonImportFiles_clicked()
{
const auto & importFunctor = [this]
{
#ifndef VCMI_MOBILE
QString filter =
tr("All supported files") + " (*.h3m *.vmap *.h3c *.vcmp *.zip *.json *.exe);;" +
tr("Maps") + " (*.h3m *.vmap);;" +
tr("Campaigns") + " (*.h3c *.vcmp);;" +
tr("Configs") + " (*.json);;" +
tr("Mods") + " (*.zip);;" +
tr("Gog files") + " (*.exe)";
#else
//Workaround for sometimes incorrect mime for some extensions (e.g. for exe)
QString filter = tr("All files (*.*)");
#endif
QStringList files = QFileDialog::getOpenFileNames(this, tr("Select files (configs, mods, maps, campaigns, gog files) to install..."), QDir::homePath(), filter);
for(const auto & file : files)
getMainWindow()->manualInstallFile(file);
};
// iOS can't display modal dialogs when called directly on button press
// https://bugreports.qt.io/browse/QTBUG-98651
QTimer::singleShot(0, this, importFunctor);
}

View File

@ -8,6 +8,21 @@ namespace Ui
class StartGameTab;
}
enum class EGameUpdateStatus : int8_t
{
NOT_CHECKED,
NO_UPDATE,
UPDATE_AVAILABLE
};
enum ETranslationStatus
{
NOT_AVAILABLE, // translation for this language was not found in mod list. Could also happen if player is offline or disabled repository checkout
NOT_INSTALLLED, // translation mod found, but it is not installed
DISABLED, // translation mod found, and installed, but toggled off
ACTIVE // translation mod active OR game is already in specified language (e.g. English H3 for players with English language)
};
class MainWindow;
class StartGameTab : public QWidget
@ -17,6 +32,12 @@ class StartGameTab : public QWidget
MainWindow * getMainWindow();
void refreshState();
void refreshUpdateStatus(EGameUpdateStatus status);
void refreshTranslation(ETranslationStatus status);
void refreshMods();
void refreshGameData();
public:
explicit StartGameTab(QWidget * parent = nullptr);
~StartGameTab();
@ -30,6 +51,10 @@ private slots:
void on_buttonUpdateCheck_clicked();
void on_buttonGameEditor_clicked();
void on_buttonImportFiles_clicked();
private:
Ui::StartGameTab * ui;
};

View File

@ -31,7 +31,7 @@
</size>
</property>
<property name="text">
<string>Preset %1</string>
<string>Preset: %1</string>
</property>
</widget>
</item>