1 /* === This file is part of Calamares - <https://github.com/calamares> ===
3 * Copyright 2014-2015, Teo Mrnjavac <teo@kde.org>
4 * Copyright 2018, Adriaan de Groot <groot@kde.org>
6 * Calamares is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Calamares is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Calamares. If not, see <http://www.gnu.org/licenses/>.
19 #include <QDesktopWidget>
20 #include "CalamaresApplication.h"
22 #include "CalamaresConfig.h"
23 #include "CalamaresWindow.h"
24 #include "CalamaresVersion.h"
25 #include "progresstree/ProgressTreeView.h"
26 #include "progresstree/ProgressTreeModel.h"
28 #include "modulesystem/ModuleManager.h"
29 #include "utils/CalamaresUtilsGui.h"
30 #include "utils/CalamaresUtilsSystem.h"
31 #include "utils/Logger.h"
35 #include "viewpages/ViewStep.h"
36 #include "ViewManager.h"
42 CalamaresApplication::CalamaresApplication( int& argc, char* argv[] )
43 : QApplication( argc, argv )
44 , m_mainwindow( nullptr )
45 , m_moduleManager( nullptr )
46 , m_debugMode( false )
48 // Setting the organization name makes the default cache
49 // directory -- where Calamares stores logs, for instance --
50 // <org>/<app>/, so we end up with ~/.cache/Calamares/calamares/
51 // which is excessively squidly.
53 // setOrganizationName( QStringLiteral( CALAMARES_ORGANIZATION_NAME ) );
54 setOrganizationDomain( QStringLiteral( CALAMARES_ORGANIZATION_DOMAIN ) );
55 setApplicationName( QStringLiteral( CALAMARES_APPLICATION_NAME ) );
56 setApplicationVersion( QStringLiteral( CALAMARES_VERSION ) );
58 cDebug() << "Calamares version:" << CALAMARES_VERSION;
60 CalamaresUtils::installTranslator( QLocale::system(), QString(), this );
64 cDebug() << "Default font size" << f.pointSize() << ';' << f.pixelSize() << "px";
65 CalamaresUtils::setDefaultFontSize( f.pointSize() );
67 cDebug() << "Available languages:" << QString( CALAMARES_TRANSLATION_LANGUAGES ).split( ';' );
72 CalamaresApplication::init()
74 Logger::setupLogfile();
76 setQuitOnLastWindowClosed( false );
82 setWindowIcon( QIcon( Calamares::Branding::instance()->
83 imagePath( Calamares::Branding::ProductIcon ) ) );
85 cDebug() << "STARTUP: initQmlPath, initSettings, initBranding done";
87 initModuleManager(); //also shows main window
89 cDebug() << "STARTUP: initModuleManager: module init started";
93 CalamaresApplication::~CalamaresApplication()
95 cDebug( Logger::LOGVERBOSE ) << "Shutting down Calamares...";
97 // if ( JobQueue::instance() )
98 // JobQueue::instance()->stop();
100 // delete m_mainwindow;
102 // delete JobQueue::instance();
104 cDebug( Logger::LOGVERBOSE ) << "Finished shutdown.";
108 CalamaresApplication*
109 CalamaresApplication::instance()
111 return qobject_cast< CalamaresApplication* >( QApplication::instance() );
116 CalamaresApplication::setDebug( bool enabled )
118 m_debugMode = enabled;
123 CalamaresApplication::isDebug()
130 CalamaresApplication::mainWindow()
137 qmlDirCandidates( bool assumeBuilddir )
139 static const char QML[] = "qml";
142 if ( CalamaresUtils::isAppDataDirOverridden() )
143 qmlDirs << CalamaresUtils::appDataDir().absoluteFilePath( QML );
146 if ( assumeBuilddir )
147 qmlDirs << QDir::current().absoluteFilePath( "src/qml" ); // In build-dir
148 if ( CalamaresUtils::haveExtraDirs() )
149 for ( auto s : CalamaresUtils::extraDataDirs() )
150 qmlDirs << ( s + QML );
151 qmlDirs << CalamaresUtils::appDataDir().absoluteFilePath( QML );
159 settingsFileCandidates( bool assumeBuilddir )
161 static const char settings[] = "settings.conf";
163 QStringList settingsPaths;
164 if ( CalamaresUtils::isAppDataDirOverridden() )
165 settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings );
168 if ( assumeBuilddir )
169 settingsPaths << QDir::current().absoluteFilePath( settings );
170 if ( CalamaresUtils::haveExtraDirs() )
171 for ( auto s : CalamaresUtils::extraConfigDirs() )
172 settingsPaths << ( s + settings );
173 settingsPaths << CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/settings.conf"; // String concat
174 settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings );
177 return settingsPaths;
182 brandingFileCandidates( bool assumeBuilddir, const QString& brandingFilename )
184 QStringList brandingPaths;
185 if ( CalamaresUtils::isAppDataDirOverridden() )
186 brandingPaths << CalamaresUtils::appDataDir().absoluteFilePath( brandingFilename );
189 if ( assumeBuilddir )
190 brandingPaths << ( QDir::currentPath() + QStringLiteral( "/src/" ) + brandingFilename );
191 if ( CalamaresUtils::haveExtraDirs() )
192 for ( auto s : CalamaresUtils::extraDataDirs() )
193 brandingPaths << ( s + brandingFilename );
194 brandingPaths << QDir( CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/" ).absoluteFilePath( brandingFilename );
195 brandingPaths << CalamaresUtils::appDataDir().absoluteFilePath( brandingFilename);
198 return brandingPaths;
203 CalamaresApplication::initQmlPath()
205 QDir importPath; // Right now, current-dir
206 QStringList qmlDirCandidatesByPriority = qmlDirCandidates( isDebug() );
209 foreach ( const QString& path, qmlDirCandidatesByPriority )
212 if ( dir.exists() && dir.isReadable() )
220 if ( !found || !importPath.exists() || !importPath.isReadable() )
222 cError() << "Cowardly refusing to continue startup without a QML directory."
223 << Logger::DebugList( qmlDirCandidatesByPriority );
224 if ( CalamaresUtils::isAppDataDirOverridden() )
225 cError() << "FATAL: explicitly configured application data directory is missing qml/";
227 cError() << "FATAL: none of the expected QML paths exist.";
228 ::exit( EXIT_FAILURE );
231 cDebug() << "Using Calamares QML directory" << importPath.absolutePath();
232 CalamaresUtils::setQmlModulesDir( importPath );
237 CalamaresApplication::initSettings()
239 QStringList settingsFileCandidatesByPriority = settingsFileCandidates( isDebug() );
241 QFileInfo settingsFile;
244 foreach ( const QString& path, settingsFileCandidatesByPriority )
246 QFileInfo pathFi( path );
247 if ( pathFi.exists() && pathFi.isReadable() )
249 settingsFile = pathFi;
255 if ( !found || !settingsFile.exists() || !settingsFile.isReadable() )
257 cError() << "Cowardly refusing to continue startup without settings."
258 << Logger::DebugList( settingsFileCandidatesByPriority );
259 if ( CalamaresUtils::isAppDataDirOverridden() )
260 cError() << "FATAL: explicitly configured application data directory is missing settings.conf";
262 cError() << "FATAL: none of the expected configuration file paths exist.";
263 ::exit( EXIT_FAILURE );
266 new Calamares::Settings( settingsFile.absoluteFilePath(), isDebug(), this );
271 CalamaresApplication::initBranding()
273 QString brandingComponentName = Calamares::Settings::instance()->brandingComponentName();
274 if ( brandingComponentName.simplified().isEmpty() )
276 cError() << "FATAL: branding component not set in settings.conf";
277 ::exit( EXIT_FAILURE );
280 QString brandingDescriptorSubpath = QString( "branding/%1/branding.desc" ).arg( brandingComponentName );
281 QStringList brandingFileCandidatesByPriority = brandingFileCandidates( isDebug(), brandingDescriptorSubpath);
283 QFileInfo brandingFile;
286 foreach ( const QString& path, brandingFileCandidatesByPriority )
288 QFileInfo pathFi( path );
289 if ( pathFi.exists() && pathFi.isReadable() )
291 brandingFile = pathFi;
297 if ( !found || !brandingFile.exists() || !brandingFile.isReadable() )
299 cError() << "Cowardly refusing to continue startup without branding."
300 << Logger::DebugList( brandingFileCandidatesByPriority );
301 if ( CalamaresUtils::isAppDataDirOverridden() )
302 cError() << "FATAL: explicitly configured application data directory is missing" << brandingComponentName;
304 cError() << "FATAL: none of the expected branding descriptor file paths exist.";
305 ::exit( EXIT_FAILURE );
308 new Calamares::Branding( brandingFile.absoluteFilePath(), this );
313 CalamaresApplication::initModuleManager()
315 m_moduleManager = new Calamares::ModuleManager(
316 Calamares::Settings::instance()->modulesSearchPaths(), this );
317 connect( m_moduleManager, &Calamares::ModuleManager::initDone,
318 this, &CalamaresApplication::initView );
319 m_moduleManager->init();
324 CalamaresApplication::initView()
326 cDebug() << "STARTUP: initModuleManager: all modules init done";
328 cDebug() << "STARTUP: initJobQueue done";
330 m_mainwindow = new CalamaresWindow(); //also creates ViewManager
332 connect( m_moduleManager, &Calamares::ModuleManager::modulesLoaded,
333 this, &CalamaresApplication::initViewSteps );
334 connect( m_moduleManager, &Calamares::ModuleManager::modulesFailed,
335 this, &CalamaresApplication::initFailed );
337 m_moduleManager->loadModules();
340 this->desktop()->availableGeometry().center() -
341 m_mainwindow->rect().center() );
343 cDebug() << "STARTUP: CalamaresWindow created; loadModules started";
348 CalamaresApplication::initViewSteps()
350 cDebug() << "STARTUP: loadModules for all modules done";
351 m_moduleManager->checkRequirements();
352 if ( Calamares::Branding::instance()->windowMaximize() )
354 m_mainwindow->setWindowFlag( Qt::FramelessWindowHint );
355 m_mainwindow->showMaximized();
358 m_mainwindow->show();
360 ProgressTreeModel* m = new ProgressTreeModel( nullptr );
361 ProgressTreeView::instance()->setModel( m );
362 cDebug() << "STARTUP: Window now visible and ProgressTreeView populated";
366 CalamaresApplication::initFailed(const QStringList& l)
368 cError() << "STARTUP: failed modules are" << l;
369 m_mainwindow->show();
373 CalamaresApplication::initJobQueue()
375 Calamares::JobQueue* jobQueue = new Calamares::JobQueue( this );
376 new CalamaresUtils::System( Calamares::Settings::instance()->doChroot(), this );
377 Calamares::Branding::instance()->setGlobals( jobQueue->globalStorage() );