2017-07-13 10:26:03 +02:00
/*
* mainwindow_moc . cpp , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
2013-08-22 17:22:49 +03:00
# include "StdInc.h"
2013-08-24 23:11:51 +03:00
# include "mainwindow_moc.h"
# include "ui_mainwindow_moc.h"
2013-08-22 17:22:49 +03:00
# include <QDir>
# include "../lib/CConfigHandler.h"
# include "../lib/VCMIDirs.h"
# include "../lib/filesystem/Filesystem.h"
# include "../lib/logging/CBasicLogConfigurator.h"
2024-07-20 14:55:17 +02:00
# include "../lib/texts/Languages.h"
2013-08-22 17:22:49 +03:00
2022-09-04 18:32:48 +02:00
# include "updatedialog_moc.h"
2022-11-07 11:44:58 +02:00
# include "main.h"
2024-04-21 16:56:39 +02:00
# include "helper.h"
2022-09-04 18:32:48 +02:00
2013-08-22 17:22:49 +03:00
void MainWindow : : load ( )
{
2017-08-09 00:09:29 +02:00
// Set current working dir to executable folder.
// This is important on Mac for relative paths to work inside DMG.
QDir : : setCurrent ( QApplication : : applicationDirPath ( ) ) ;
2024-03-02 23:24:00 +02:00
# ifndef VCMI_MOBILE
2017-07-16 11:58:05 +02:00
console = new CConsoleHandler ( ) ;
2022-09-27 06:05:10 +02:00
# endif
2022-09-17 15:56:01 +02:00
CBasicLogConfigurator logConfig ( VCMIDirs : : get ( ) . userLogsPath ( ) / " VCMI_Launcher_log.txt " , console ) ;
2013-08-22 17:22:49 +03:00
logConfig . configureDefault ( ) ;
CResourceHandler : : initialize ( ) ;
2013-11-08 23:36:26 +03:00
CResourceHandler : : load ( " config/filesystem.json " ) ;
2013-08-22 17:22:49 +03:00
2024-04-21 16:56:39 +02:00
Helper : : loadSettings ( ) ;
2013-08-22 17:22:49 +03:00
}
2022-12-29 16:38:43 +02:00
void MainWindow : : computeSidePanelSizes ( )
{
QVector < QToolButton * > widgets = {
ui - > modslistButton ,
ui - > settingsButton ,
2023-06-30 14:24:43 +02:00
ui - > aboutButton ,
2022-12-29 16:38:43 +02:00
ui - > startGameButton
} ;
for ( auto & widget : widgets )
{
QFontMetrics metrics ( widget - > font ( ) ) ;
QSize iconSize = widget - > iconSize ( ) ;
// this is minimal space that is needed for our button to avoid text clipping
int buttonHeight = iconSize . height ( ) + metrics . height ( ) + 4 ;
widget - > setMinimumHeight ( buttonHeight ) ;
widget - > setMaximumHeight ( buttonHeight * 1.2 ) ;
}
}
2018-04-13 07:34:58 +02:00
MainWindow : : MainWindow ( QWidget * parent )
: QMainWindow ( parent ) , ui ( new Ui : : MainWindow )
2013-08-22 17:22:49 +03:00
{
load ( ) ; // load FS before UI
2023-06-27 21:33:42 +02:00
bool setupCompleted = settings [ " launcher " ] [ " setupCompleted " ] . Bool ( ) ;
if ( ! setupCompleted )
detectPreferredLanguage ( ) ;
2022-12-25 23:06:22 +02:00
updateTranslation ( ) ; // load translation
2013-08-22 17:22:49 +03:00
ui - > setupUi ( this ) ;
2024-03-02 23:24:00 +02:00
2024-12-10 23:38:58 +02:00
setAcceptDrops ( true ) ;
2024-03-02 23:24:00 +02:00
setWindowIcon ( QIcon { " :/icons/menu-game.png " } ) ;
ui - > modslistButton - > setIcon ( QIcon { " :/icons/menu-mods.png " } ) ;
ui - > settingsButton - > setIcon ( QIcon { " :/icons/menu-settings.png " } ) ;
ui - > aboutButton - > setIcon ( QIcon { " :/icons/about-project.png " } ) ;
ui - > startGameButton - > setIcon ( QIcon { " :/icons/menu-game.png " } ) ;
# ifndef VCMI_MOBILE
2019-07-30 08:32:35 +02:00
//load window settings
QSettings s ( Ui : : teamName , Ui : : appName ) ;
auto size = s . value ( " MainWindow/Size " ) . toSize ( ) ;
2019-07-30 11:00:44 +02:00
if ( size . isValid ( ) )
2019-07-30 08:32:35 +02:00
{
resize ( size ) ;
}
auto position = s . value ( " MainWindow/Position " ) . toPoint ( ) ;
2019-07-30 11:00:44 +02:00
if ( ! position . isNull ( ) )
2019-07-30 08:32:35 +02:00
{
move ( position ) ;
}
2024-03-02 23:24:00 +02:00
# endif
2019-07-30 08:32:35 +02:00
2022-12-29 16:38:43 +02:00
computeSidePanelSizes ( ) ;
2019-07-30 08:32:35 +02:00
2023-08-23 14:07:50 +02:00
bool h3DataFound = CResourceHandler : : get ( ) - > existsResource ( ResourcePath ( " DATA/GENRLTXT.TXT " ) ) ;
2023-03-11 00:57:55 +02:00
if ( h3DataFound & & setupCompleted )
2024-11-24 19:33:25 +02:00
ui - > tabListWidget - > setCurrentIndex ( TabRows : : START ) ;
2023-03-11 00:57:55 +02:00
else
2023-03-12 18:33:29 +02:00
enterSetup ( ) ;
2022-09-27 10:51:49 +02:00
2017-08-24 03:52:02 +02:00
ui - > settingsView - > setDisplayList ( ) ;
2022-11-22 01:36:27 +02:00
2022-09-04 18:32:48 +02:00
if ( settings [ " launcher " ] [ " updateOnStartup " ] . Bool ( ) )
UpdateDialog : : showUpdateDialog ( false ) ;
2013-08-22 17:22:49 +03:00
}
2023-06-27 21:33:42 +02:00
void MainWindow : : detectPreferredLanguage ( )
{
auto preferredLanguages = QLocale : : system ( ) . uiLanguages ( ) ;
std : : string selectedLanguage ;
for ( auto const & userLang : preferredLanguages )
{
logGlobal - > info ( " Preferred language: %s " , userLang . toStdString ( ) ) ;
for ( auto const & vcmiLang : Languages : : getLanguageList ( ) )
if ( vcmiLang . tagIETF = = userLang . toStdString ( ) )
selectedLanguage = vcmiLang . identifier ;
2023-12-18 00:48:21 +02:00
if ( ! selectedLanguage . empty ( ) )
{
logGlobal - > info ( " Selected language: %s " , selectedLanguage ) ;
Settings node = settings . write [ " general " ] [ " language " ] ;
node - > String ( ) = selectedLanguage ;
return ;
}
2023-06-27 21:33:42 +02:00
}
}
2023-03-12 18:33:29 +02:00
void MainWindow : : enterSetup ( )
{
ui - > startGameButton - > setEnabled ( false ) ;
ui - > settingsButton - > setEnabled ( false ) ;
2023-07-13 15:56:11 +02:00
ui - > aboutButton - > setEnabled ( false ) ;
2023-03-12 18:33:29 +02:00
ui - > modslistButton - > setEnabled ( false ) ;
ui - > tabListWidget - > setCurrentIndex ( TabRows : : SETUP ) ;
}
void MainWindow : : exitSetup ( )
{
Settings writer = settings . write [ " launcher " ] [ " setupCompleted " ] ;
writer - > Bool ( ) = true ;
ui - > startGameButton - > setEnabled ( true ) ;
ui - > settingsButton - > setEnabled ( true ) ;
2023-07-13 15:56:11 +02:00
ui - > aboutButton - > setEnabled ( true ) ;
2023-03-12 18:33:29 +02:00
ui - > modslistButton - > setEnabled ( true ) ;
ui - > tabListWidget - > setCurrentIndex ( TabRows : : MODS ) ;
}
2024-11-24 19:33:25 +02:00
void MainWindow : : switchToStartTab ( )
{
ui - > startGameButton - > setEnabled ( true ) ;
2024-12-01 21:04:58 +02:00
ui - > startGameButton - > setChecked ( true ) ;
2024-11-24 19:33:25 +02:00
ui - > tabListWidget - > setCurrentIndex ( TabRows : : START ) ;
2024-12-10 23:28:11 +02:00
auto * startGameTabWidget = qobject_cast < StartGameTab * > ( ui - > tabListWidget - > widget ( TabRows : : START ) ) ;
if ( startGameTabWidget )
startGameTabWidget - > refreshState ( ) ;
2024-11-24 19:33:25 +02:00
}
2023-03-14 13:37:22 +02:00
void MainWindow : : switchToModsTab ( )
{
ui - > startGameButton - > setEnabled ( true ) ;
2024-12-01 21:04:58 +02:00
ui - > modslistButton - > setChecked ( true ) ;
2023-03-14 13:37:22 +02:00
ui - > tabListWidget - > setCurrentIndex ( TabRows : : MODS ) ;
}
2024-04-20 18:51:03 +02:00
void MainWindow : : changeEvent ( QEvent * event )
2022-12-25 13:19:16 +02:00
{
2022-12-29 16:37:38 +02:00
if ( event - > type ( ) = = QEvent : : LanguageChange )
2022-12-25 13:19:16 +02:00
{
ui - > retranslateUi ( this ) ;
}
2022-12-28 17:58:39 +02:00
QMainWindow : : changeEvent ( event ) ;
2022-12-25 13:19:16 +02:00
}
2013-08-22 17:22:49 +03:00
MainWindow : : ~ MainWindow ( )
{
2024-03-02 23:24:00 +02:00
# ifndef VCMI_MOBILE
2019-07-30 08:32:35 +02:00
//save window settings
QSettings s ( Ui : : teamName , Ui : : appName ) ;
s . setValue ( " MainWindow/Size " , size ( ) ) ;
s . setValue ( " MainWindow/Position " , pos ( ) ) ;
2024-03-02 23:24:00 +02:00
# endif
2019-07-30 08:32:35 +02:00
2013-08-22 17:22:49 +03:00
delete ui ;
}
2022-11-07 11:44:58 +02:00
void MainWindow : : on_startGameButton_clicked ( )
{
2024-11-24 19:33:25 +02:00
switchToStartTab ( ) ;
2022-11-07 11:44:58 +02:00
}
2022-11-17 01:15:26 +02:00
2023-03-11 00:57:55 +02:00
CModListView * MainWindow : : getModView ( )
{
return ui - > modlistView ;
}
2022-12-19 19:12:44 +02:00
void MainWindow : : on_modslistButton_clicked ( )
2022-11-17 01:15:26 +02:00
{
2023-03-14 13:37:22 +02:00
switchToModsTab ( ) ;
2022-12-19 19:12:44 +02:00
}
void MainWindow : : on_settingsButton_clicked ( )
{
ui - > startGameButton - > setEnabled ( true ) ;
ui - > tabListWidget - > setCurrentIndex ( TabRows : : SETTINGS ) ;
}
2023-06-30 14:24:43 +02:00
void MainWindow : : on_aboutButton_clicked ( )
{
ui - > startGameButton - > setEnabled ( true ) ;
ui - > tabListWidget - > setCurrentIndex ( TabRows : : ABOUT ) ;
}
2024-12-04 17:19:02 +02:00
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 )
{
2024-12-10 23:28:11 +02:00
if ( filePath . endsWith ( " .zip " , Qt : : CaseInsensitive ) | | filePath . endsWith ( " .exe " , Qt : : CaseInsensitive ) )
switchToModsTab ( ) ;
2024-12-04 17:19:02 +02:00
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
2024-12-10 23:28:11 +02:00
getModView ( ) - > installFiles ( QStringList { filePath } ) ;
2024-12-04 17:19:02 +02:00
}
2024-12-04 22:56:34 +02:00
ETranslationStatus MainWindow : : getTranslationStatus ( )
{
QString preferredlanguage = QString : : fromStdString ( settings [ " general " ] [ " language " ] . String ( ) ) ;
QString installedlanguage = QString : : fromStdString ( settings [ " session " ] [ " language " ] . String ( ) ) ;
if ( preferredlanguage = = installedlanguage )
return ETranslationStatus : : ACTIVE ;
QString modName = getModView ( ) - > getTranslationModName ( preferredlanguage ) ;
if ( modName . isEmpty ( ) )
return ETranslationStatus : : NOT_AVAILABLE ;
if ( ! getModView ( ) - > isModInstalled ( modName ) )
return ETranslationStatus : : NOT_INSTALLLED ;
if ( ! getModView ( ) - > isModEnabled ( modName ) )
return ETranslationStatus : : DISABLED ;
return ETranslationStatus : : ACTIVE ;
}
2022-12-25 13:19:16 +02:00
void MainWindow : : updateTranslation ( )
{
2022-12-25 23:42:06 +02:00
# ifdef ENABLE_QT_TRANSLATIONS
2024-07-18 17:29:46 +02:00
const std : : string translationFile = settings [ " general " ] [ " language " ] . String ( ) + " .qm " ;
QString translationFileResourcePath = QString { " :/translation/%1 " } . arg ( translationFile . c_str ( ) ) ;
2022-12-25 13:19:16 +02:00
2024-07-18 17:29:46 +02:00
logGlobal - > info ( " Loading translation %s " , translationFile ) ;
if ( ! QFile : : exists ( translationFileResourcePath ) )
{
2024-07-18 20:32:17 +02:00
logGlobal - > debug ( " Translation file %s does not exist " , translationFileResourcePath . toStdString ( ) ) ;
2024-07-18 17:29:46 +02:00
return ;
}
if ( ! translator . load ( translationFileResourcePath ) )
2022-12-29 16:37:03 +02:00
{
2024-07-18 17:29:46 +02:00
logGlobal - > error ( " Failed to load translation file %s " , translationFileResourcePath . toStdString ( ) ) ;
return ;
}
if ( translationFile = = " english.qm " )
{
// translator doesn't need to be installed for English
2024-03-02 23:24:00 +02:00
return ;
2022-12-29 16:37:03 +02:00
}
2024-03-02 23:24:00 +02:00
if ( ! qApp - > installTranslator ( & translator ) )
2024-07-18 17:29:46 +02:00
{
logGlobal - > error ( " Failed to install translator for translation file %s " , translationFileResourcePath . toStdString ( ) ) ;
}
2022-12-25 23:42:06 +02:00
# endif
2022-12-25 13:19:16 +02:00
}