1 /* === This file is part of Calamares - <https://calamares.io> ===
2  *
3  *   SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac <teo@kde.org>
4  *   SPDX-FileCopyrightText: 2017-2018 Adriaan de Groot <groot@kde.org>
5  *   SPDX-License-Identifier: GPL-3.0-or-later
6  *
7  *   Calamares is Free Software: see the License-Identifier above.
8  *
9  */
10 
11 #include "ModuleFactory.h"
12 
13 #include "CalamaresConfig.h"
14 #include "CppJobModule.h"
15 #include "ProcessJobModule.h"
16 #include "ViewModule.h"
17 
18 #include "utils/Dirs.h"
19 #include "utils/Logger.h"
20 #include "utils/NamedEnum.h"
21 #include "utils/Yaml.h"
22 
23 #ifdef WITH_PYTHON
24 #include "PythonJobModule.h"
25 #endif
26 
27 #ifdef WITH_PYTHONQT
28 #include "PythonQtViewModule.h"
29 #endif
30 
31 #include <QDir>
32 #include <QFile>
33 #include <QFileInfo>
34 #include <QString>
35 
36 
37 namespace Calamares
38 {
39 
40 Module*
moduleFromDescriptor(const Calamares::ModuleSystem::Descriptor & moduleDescriptor,const QString & instanceId,const QString & configFileName,const QString & moduleDirectory)41 moduleFromDescriptor( const Calamares::ModuleSystem::Descriptor& moduleDescriptor,
42                       const QString& instanceId,
43                       const QString& configFileName,
44                       const QString& moduleDirectory )
45 {
46     using Type = Calamares::ModuleSystem::Type;
47     using Interface = Calamares::ModuleSystem::Interface;
48 
49     std::unique_ptr< Module > m;
50 
51     if ( !moduleDescriptor.isValid() )
52     {
53         cError() << "Bad module descriptor format" << instanceId;
54         return nullptr;
55     }
56     if ( moduleDescriptor.type() == Type::View )
57     {
58         if ( moduleDescriptor.interface() == Interface::QtPlugin )
59         {
60             m.reset( new ViewModule() );
61         }
62         else if ( moduleDescriptor.interface() == Interface::PythonQt )
63         {
64 #ifdef WITH_PYTHONQT
65             m.reset( new PythonQtViewModule() );
66 #else
67             cError() << "PythonQt view modules are not supported in this version of Calamares.";
68 #endif
69         }
70         else
71         {
72             cError() << "Bad interface"
73                      << Calamares::ModuleSystem::interfaceNames().find( moduleDescriptor.interface() )
74                      << "for module type" << Calamares::ModuleSystem::typeNames().find( moduleDescriptor.type() );
75         }
76     }
77     else if ( moduleDescriptor.type() == Type::Job )
78     {
79         if ( moduleDescriptor.interface() == Interface::QtPlugin )
80         {
81             m.reset( new CppJobModule() );
82         }
83         else if ( moduleDescriptor.interface() == Interface::Process )
84         {
85             m.reset( new ProcessJobModule() );
86         }
87         else if ( moduleDescriptor.interface() == Interface::Python )
88         {
89 #ifdef WITH_PYTHON
90             m.reset( new PythonJobModule() );
91 #else
92             cError() << "Python modules are not supported in this version of Calamares.";
93 #endif
94         }
95         else
96         {
97             cError() << "Bad interface"
98                      << Calamares::ModuleSystem::interfaceNames().find( moduleDescriptor.interface() )
99                      << "for module type" << Calamares::ModuleSystem::typeNames().find( moduleDescriptor.type() );
100         }
101     }
102     else
103     {
104         cError() << "Bad module type" << Calamares::ModuleSystem::typeNames().find( moduleDescriptor.type() );
105     }
106 
107     if ( !m )
108     {
109         cError() << "Bad module type (" << Calamares::ModuleSystem::typeNames().find( moduleDescriptor.type() )
110                  << ") or interface string ("
111                  << Calamares::ModuleSystem::interfaceNames().find( moduleDescriptor.interface() ) << ") for module "
112                  << instanceId;
113         return nullptr;
114     }
115 
116     QDir moduleDir( moduleDirectory );
117     if ( moduleDir.exists() && moduleDir.isReadable() )
118     {
119         m->m_directory = moduleDir.absolutePath();
120     }
121     else
122     {
123         cError() << "Bad module directory" << moduleDirectory << "for" << instanceId;
124         return nullptr;
125     }
126 
127     m->initFrom( moduleDescriptor, instanceId );
128     if ( !m->m_key.isValid() )
129     {
130         cError() << "Module" << instanceId << "invalid ID";
131         return nullptr;
132     }
133 
134     m->initFrom( moduleDescriptor );
135     if ( !configFileName.isEmpty() )
136     {
137         try
138         {
139             m->loadConfigurationFile( configFileName );
140         }
141         catch ( YAML::Exception& e )
142         {
143             cError() << "YAML parser error " << e.what();
144             return nullptr;
145         }
146     }
147     return m.release();
148 }
149 
150 
151 }  // namespace Calamares
152