mirror of https://github.com/cutefishos/calamares
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
301 lines
9.1 KiB
C++
301 lines
9.1 KiB
C++
/* === This file is part of Calamares - <https://calamares.io> ===
|
|
*
|
|
* SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac <teo@kde.org>
|
|
* SPDX-FileCopyrightText: 2018 Adriaan de Groot <groot@kde.org>
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*
|
|
* Calamares is Free Software: see the License-Identifier above.
|
|
*
|
|
*/
|
|
#include "CalamaresApplication.h"
|
|
|
|
#include "CalamaresConfig.h"
|
|
#include "CalamaresVersion.h"
|
|
#include "CalamaresWindow.h"
|
|
#include "progresstree/ProgressTreeView.h"
|
|
|
|
#include "Branding.h"
|
|
#include "JobQueue.h"
|
|
#include "Settings.h"
|
|
#include "ViewManager.h"
|
|
#include "modulesystem/ModuleManager.h"
|
|
#include "utils/CalamaresUtilsGui.h"
|
|
#include "utils/CalamaresUtilsSystem.h"
|
|
#include "utils/Dirs.h"
|
|
#include "utils/Logger.h"
|
|
#ifdef WITH_QML
|
|
#include "utils/Qml.h"
|
|
#endif
|
|
#include "utils/Retranslator.h"
|
|
#include "viewpages/ViewStep.h"
|
|
|
|
#include <QDesktopWidget>
|
|
#include <QDir>
|
|
#include <QFileInfo>
|
|
#include <QScreen>
|
|
#include <QTimer>
|
|
|
|
/// @brief Convenience for "are the settings in debug mode"
|
|
static bool
|
|
isDebug()
|
|
{
|
|
return Calamares::Settings::instance() && Calamares::Settings::instance()->debugMode();
|
|
}
|
|
|
|
CalamaresApplication::CalamaresApplication( int& argc, char* argv[] )
|
|
: QApplication( argc, argv )
|
|
, m_mainwindow( nullptr )
|
|
, m_moduleManager( nullptr )
|
|
{
|
|
// Setting the organization name makes the default cache
|
|
// directory -- where Calamares stores logs, for instance --
|
|
// <org>/<app>/, so we end up with ~/.cache/Calamares/calamares/
|
|
// which is excessively squidly.
|
|
//
|
|
// setOrganizationName( QStringLiteral( CALAMARES_ORGANIZATION_NAME ) );
|
|
setOrganizationDomain( QStringLiteral( CALAMARES_ORGANIZATION_DOMAIN ) );
|
|
setApplicationName( QStringLiteral( CALAMARES_APPLICATION_NAME ) );
|
|
setApplicationVersion( QStringLiteral( CALAMARES_VERSION ) );
|
|
|
|
QFont f = font();
|
|
CalamaresUtils::setDefaultFontSize( f.pointSize() );
|
|
}
|
|
|
|
|
|
void
|
|
CalamaresApplication::init()
|
|
{
|
|
Logger::setupLogfile();
|
|
cDebug() << "Calamares version:" << CALAMARES_VERSION;
|
|
cDebug() << Logger::SubEntry
|
|
<< "languages:" << QString( CALAMARES_TRANSLATION_LANGUAGES ).replace( ";", ", " );
|
|
|
|
if ( !Calamares::Settings::instance() )
|
|
{
|
|
cError() << "Must create Calamares::Settings before the application.";
|
|
::exit( 1 );
|
|
}
|
|
initQmlPath();
|
|
initBranding();
|
|
|
|
CalamaresUtils::installTranslator( QLocale::system(), QString() );
|
|
|
|
setQuitOnLastWindowClosed( false );
|
|
setWindowIcon( QIcon( Calamares::Branding::instance()->imagePath( Calamares::Branding::ProductIcon ) ) );
|
|
|
|
cDebug() << Logger::SubEntry << "STARTUP: initSettings, initQmlPath, initBranding done";
|
|
|
|
initModuleManager(); //also shows main window
|
|
|
|
cDebug() << Logger::SubEntry << "STARTUP: initModuleManager: module init started";
|
|
}
|
|
|
|
|
|
CalamaresApplication::~CalamaresApplication()
|
|
{
|
|
Logger::CDebug( Logger::LOGVERBOSE ) << "Shutting down Calamares...";
|
|
Logger::CDebug( Logger::LOGVERBOSE ) << Logger::SubEntry << "Finished shutdown.";
|
|
}
|
|
|
|
|
|
CalamaresApplication*
|
|
CalamaresApplication::instance()
|
|
{
|
|
return qobject_cast< CalamaresApplication* >( QApplication::instance() );
|
|
}
|
|
|
|
|
|
CalamaresWindow*
|
|
CalamaresApplication::mainWindow()
|
|
{
|
|
return m_mainwindow;
|
|
}
|
|
|
|
|
|
static QStringList
|
|
brandingFileCandidates( bool assumeBuilddir, const QString& brandingFilename )
|
|
{
|
|
QStringList brandingPaths;
|
|
if ( CalamaresUtils::isAppDataDirOverridden() )
|
|
{
|
|
brandingPaths << CalamaresUtils::appDataDir().absoluteFilePath( brandingFilename );
|
|
}
|
|
else
|
|
{
|
|
if ( assumeBuilddir )
|
|
{
|
|
brandingPaths << ( QDir::currentPath() + QStringLiteral( "/src/" ) + brandingFilename );
|
|
}
|
|
if ( CalamaresUtils::haveExtraDirs() )
|
|
for ( auto s : CalamaresUtils::extraDataDirs() )
|
|
{
|
|
brandingPaths << ( s + brandingFilename );
|
|
}
|
|
brandingPaths << QDir( CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/" ).absoluteFilePath( brandingFilename );
|
|
brandingPaths << CalamaresUtils::appDataDir().absoluteFilePath( brandingFilename );
|
|
}
|
|
|
|
return brandingPaths;
|
|
}
|
|
|
|
|
|
void
|
|
CalamaresApplication::initQmlPath()
|
|
{
|
|
#ifdef WITH_QML
|
|
if ( !CalamaresUtils::initQmlModulesDir() )
|
|
{
|
|
::exit( EXIT_FAILURE );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
void
|
|
CalamaresApplication::initBranding()
|
|
{
|
|
QString brandingComponentName = Calamares::Settings::instance()->brandingComponentName();
|
|
if ( brandingComponentName.simplified().isEmpty() )
|
|
{
|
|
cError() << "FATAL: branding component not set in settings.conf";
|
|
::exit( EXIT_FAILURE );
|
|
}
|
|
|
|
QString brandingDescriptorSubpath = QString( "branding/%1/branding.desc" ).arg( brandingComponentName );
|
|
QStringList brandingFileCandidatesByPriority = brandingFileCandidates( isDebug(), brandingDescriptorSubpath );
|
|
|
|
QFileInfo brandingFile;
|
|
bool found = false;
|
|
|
|
foreach ( const QString& path, brandingFileCandidatesByPriority )
|
|
{
|
|
QFileInfo pathFi( path );
|
|
if ( pathFi.exists() && pathFi.isReadable() )
|
|
{
|
|
brandingFile = pathFi;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !found || !brandingFile.exists() || !brandingFile.isReadable() )
|
|
{
|
|
cError() << "Cowardly refusing to continue startup without branding."
|
|
<< Logger::DebugList( brandingFileCandidatesByPriority );
|
|
if ( CalamaresUtils::isAppDataDirOverridden() )
|
|
{
|
|
cError() << "FATAL: explicitly configured application data directory is missing" << brandingComponentName;
|
|
}
|
|
else
|
|
{
|
|
cError() << "FATAL: none of the expected branding descriptor file paths exist.";
|
|
}
|
|
::exit( EXIT_FAILURE );
|
|
}
|
|
|
|
new Calamares::Branding( brandingFile.absoluteFilePath(), this );
|
|
}
|
|
|
|
|
|
void
|
|
CalamaresApplication::initModuleManager()
|
|
{
|
|
m_moduleManager = new Calamares::ModuleManager( Calamares::Settings::instance()->modulesSearchPaths(), this );
|
|
connect( m_moduleManager, &Calamares::ModuleManager::initDone, this, &CalamaresApplication::initView );
|
|
m_moduleManager->init();
|
|
}
|
|
|
|
/** @brief centers the widget @p w on (a) screen
|
|
*
|
|
* This tries to duplicate the (deprecated) qApp->desktop()->availableGeometry()
|
|
* placement by iterating over screens and putting Calamares in the first
|
|
* one where it fits; this is *generally* the primary screen.
|
|
*
|
|
* With debugging, it would look something like this (2 screens attached,
|
|
* primary at +1080+240 because I have a very strange X setup). Before
|
|
* being mapped, the Calamares window is at +0+0 but does have a size.
|
|
* The first screen's geometry includes the offset from the origin in
|
|
* screen coordinates.
|
|
*
|
|
* Proposed window size: 1024 520
|
|
* Window QRect(0,0 1024x520)
|
|
* Screen QRect(1080,240 2560x1440)
|
|
* Moving QPoint(1848,700)
|
|
* Screen QRect(0,0 1080x1920)
|
|
*
|
|
*/
|
|
static void
|
|
centerWindowOnScreen( QWidget* w )
|
|
{
|
|
QList< QScreen* > screens = qApp->screens();
|
|
QPoint windowCenter = w->rect().center();
|
|
QSize windowSize = w->rect().size();
|
|
|
|
for ( const auto* screen : screens )
|
|
{
|
|
QSize screenSize = screen->availableGeometry().size();
|
|
if ( ( screenSize.width() >= windowSize.width() ) && ( screenSize.height() >= windowSize.height() ) )
|
|
{
|
|
w->move( screen->availableGeometry().center() - windowCenter );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
CalamaresApplication::initView()
|
|
{
|
|
cDebug() << "STARTUP: initModuleManager: all modules init done";
|
|
initJobQueue();
|
|
cDebug() << "STARTUP: initJobQueue done";
|
|
|
|
m_mainwindow = new CalamaresWindow(); //also creates ViewManager
|
|
|
|
connect( m_moduleManager, &Calamares::ModuleManager::modulesLoaded, this, &CalamaresApplication::initViewSteps );
|
|
connect( m_moduleManager, &Calamares::ModuleManager::modulesFailed, this, &CalamaresApplication::initFailed );
|
|
|
|
QTimer::singleShot( 0, m_moduleManager, &Calamares::ModuleManager::loadModules );
|
|
|
|
if ( Calamares::Branding::instance() && Calamares::Branding::instance()->windowPlacementCentered() )
|
|
{
|
|
centerWindowOnScreen( m_mainwindow );
|
|
}
|
|
cDebug() << "STARTUP: CalamaresWindow created; loadModules started";
|
|
}
|
|
|
|
|
|
void
|
|
CalamaresApplication::initViewSteps()
|
|
{
|
|
cDebug() << "STARTUP: loadModules for all modules done";
|
|
m_moduleManager->checkRequirements();
|
|
if ( Calamares::Branding::instance()->windowMaximize() )
|
|
{
|
|
m_mainwindow->setWindowFlag( Qt::FramelessWindowHint );
|
|
m_mainwindow->showMaximized();
|
|
}
|
|
else
|
|
{
|
|
m_mainwindow->show();
|
|
}
|
|
|
|
cDebug() << "STARTUP: Window now visible and ProgressTreeView populated";
|
|
cDebug() << Logger::SubEntry << Calamares::ViewManager::instance()->viewSteps().count() << "view steps loaded.";
|
|
Calamares::ViewManager::instance()->onInitComplete();
|
|
}
|
|
|
|
void
|
|
CalamaresApplication::initFailed( const QStringList& l )
|
|
{
|
|
cError() << "STARTUP: failed modules are" << l;
|
|
m_mainwindow->show();
|
|
}
|
|
|
|
void
|
|
CalamaresApplication::initJobQueue()
|
|
{
|
|
Calamares::JobQueue* jobQueue = new Calamares::JobQueue( this );
|
|
new CalamaresUtils::System( Calamares::Settings::instance()->doChroot(), this );
|
|
Calamares::Branding::instance()->setGlobals( jobQueue->globalStorage() );
|
|
}
|