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-FileCopyrightText: 2018 Raul Rodrigo Segura (raurodse)
6  *   SPDX-FileCopyrightText: 2019 Camilo Higuita <milo.h@aol.com>
7  *   SPDX-FileCopyrightText: 2021 Anubhav Choudhary <ac.10edu@gmail.com>
8  *   SPDX-License-Identifier: GPL-3.0-or-later
9  *
10  *   Calamares is Free Software: see the License-Identifier above.
11  *
12  */
13 
14 #ifndef BRANDING_H
15 #define BRANDING_H
16 
17 #include "CalamaresConfig.h"
18 #include "DllMacro.h"
19 #include "utils/NamedSuffix.h"
20 
21 #include <QMap>
22 #include <QObject>
23 #include <QPixmap>
24 #include <QSize>
25 #include <QStringList>
26 #include <QUrl>
27 
28 namespace YAML
29 {
30 class Node;
31 }
32 
33 namespace Calamares
34 {
35 
36 class GlobalStorage;
37 
38 class UIDLLEXPORT Branding : public QObject
39 {
40     Q_OBJECT
41 public:
42     /**
43      * Descriptive strings in the configuration file. use
44      * e.g. *Branding::ProductName to get the string value for
45      * the product name.
46      */
47 
48     enum StringEntry
49     {
50         ProductName,
51         Version,
52         ShortVersion,
53         VersionedName,
54         ShortVersionedName,
55         ShortProductName,
56         BootloaderEntryName,
57         ProductUrl,
58         SupportUrl,
59         KnownIssuesUrl,
60         ReleaseNotesUrl,
61         DonateUrl
62     };
63     Q_ENUM( StringEntry )
64 
65     enum ImageEntry : short
66     {
67         ProductBanner,
68         ProductIcon,
69         ProductLogo,
70         ProductWallpaper,
71         ProductWelcome
72     };
73     Q_ENUM( ImageEntry )
74 
75     enum StyleEntry : short
76     {
77         SidebarBackground,
78         SidebarText,
79         SidebarTextSelect,
80         SidebarTextSelected = SidebarTextSelect,  // TODO:3.3:Remove SidebarTextSelect
81         SidebarTextHighlight,
82         SidebarBackgroundSelected = SidebarTextHighlight  // TODO:3.3:Remove SidebarTextHighlight
83     };
84     Q_ENUM( StyleEntry )
85 
86     /** @brief Supported log-upload servers.
87      *
88      * 'None' is here as a fallback.
89      */
90     enum UploadServerType : short
91     {
92         None,
93         Fiche
94     };
95     Q_ENUM( UploadServerType )
96 
97     /** @brief Setting for how much the main window may expand. */
98     enum class WindowExpansion
99     {
100         Normal,
101         Fullscreen,
102         Fixed
103     };
104     Q_ENUM( WindowExpansion )
105     /** @brief Setting for the main window size.
106      *
107      * The units are pixels (Pixies) or something-based-on-fontsize (Fonties), which
108      * we suffix as "em", e.g. "600px" or "32em".
109      */
110     enum class WindowDimensionUnit
111     {
112         None,
113         Pixies,
114         Fonties
115     };
Q_ENUM(WindowDimensionUnit)116     Q_ENUM( WindowDimensionUnit )
117     class WindowDimension : public NamedSuffix< WindowDimensionUnit, WindowDimensionUnit::None >
118     {
119     public:
120         static const NamedEnumTable< WindowDimensionUnit >& suffixes();
121         bool isValid() const;
122 
123         using NamedSuffix::NamedSuffix;
124         WindowDimension( const QString& s )
125             : NamedSuffix( suffixes(), s )
126         {
127         }
128     };
129     /** @brief Placement of main window.
130      */
131     enum class WindowPlacement
132     {
133         Center,
134         Free
135     };
136     Q_ENUM( WindowPlacement )
137     ///@brief What kind of panel (sidebar, navigation) to use in the main window
138     enum class PanelFlavor
139     {
140         None,
141         Widget
142 #ifdef WITH_QML
143         ,
144         Qml
145 #endif
146     };
147     Q_ENUM( PanelFlavor )
148     ///@brief Where to place a panel (sidebar, navigation)
149     enum class PanelSide
150     {
151         None,
152         Left,
153         Right,
154         Top,
155         Bottom
156     };
157     Q_ENUM( PanelSide )
158 
159     static Branding* instance();
160 
161     explicit Branding( const QString& brandingFilePath, QObject* parent = nullptr );
162 
163     /** @brief Complete path of the branding descriptor file. */
descriptorPath()164     QString descriptorPath() const { return m_descriptorPath; }
165     /** @brief The component name found in the descriptor file.
166      *
167      * The component name always matches the last directory name in the path.
168      */
componentName()169     QString componentName() const { return m_componentName; }
170     /** @brief The directory holding all of the branding assets. */
171     QString componentDirectory() const;
172     /** @brief The directory where branding translations live.
173      *
174      * This is componentDir + "/lang".
175      */
translationsDirectory()176     QString translationsDirectory() const { return m_translationsPathPrefix; }
177 
178     /** @brief Path to the slideshow QML file, if any. (API == 1 or 2)*/
slideshowPath()179     QString slideshowPath() const { return m_slideshowPath; }
180     /// @brief List of pathnames of slideshow images, if any. (API == -1)
slideshowImages()181     QStringList slideshowImages() const { return m_slideshowFilenames; }
182     /** @brief Which slideshow API to use for the slideshow?
183      *
184      *  -  2    For QML-based slideshows loaded asynchronously (current)
185      *  -  1    For QML-based slideshows, loaded when shown (legacy)
186      *  - -1    For oldschool image-slideshows.
187      */
slideshowAPI()188     int slideshowAPI() const { return m_slideshowAPI; }
189 
190     QPixmap image( Branding::ImageEntry imageEntry, const QSize& size ) const;
191 
192     /** @brief Look up an image in the branding directory or as an icon
193      *
194      * The @p name is checked in the branding directory: if it is an image
195      * file, return the pixmap from that file, at the requested size.
196      * If it isn't a file, look it up as an icon name in the current theme.
197      * May return a null pixmap if nothing is found.
198      */
199     QPixmap image( const QString& name, const QSize& size ) const;
200 
201     /** @brief Stylesheet to apply for this branding. May be empty.
202      *
203      * The file is loaded every time this function is called, so
204      * it may be quite expensive -- although normally it will be
205      * called only once, on startup. (Or from the debug window)
206      */
207     QString stylesheet() const;
208 
welcomeStyleCalamares()209     bool welcomeStyleCalamares() const { return m_welcomeStyleCalamares; }
welcomeExpandingLogo()210     bool welcomeExpandingLogo() const { return m_welcomeExpandingLogo; }
windowMaximize()211     bool windowMaximize() const { return m_windowExpansion == WindowExpansion::Fullscreen; }
windowExpands()212     bool windowExpands() const { return m_windowExpansion != WindowExpansion::Fixed; }
windowSize()213     QPair< WindowDimension, WindowDimension > windowSize() const
214     {
215         return QPair< WindowDimension, WindowDimension >( m_windowWidth, m_windowHeight );
216     }
windowPlacementCentered()217     bool windowPlacementCentered() const { return m_windowPlacement == WindowPlacement::Center; }
218 
219     ///@brief Which sidebar flavor is configured
sidebarFlavor()220     PanelFlavor sidebarFlavor() const { return m_sidebarFlavor; }
221     ///@brief Which navigation flavor is configured
navigationFlavor()222     PanelFlavor navigationFlavor() const { return m_navigationFlavor; }
223 
224     /** @brief Upload server configuration
225      *
226      * This object has 3 items : the type (which may be none, in which case the URL
227      * is irrelevant and usually empty), the URL for the upload and the size limit of upload
228      * in bytes (for configuration value < 0, it serves -1, which stands for having no limit).
229      */
230     using UploadServerInfo = std::tuple< UploadServerType, QUrl, qint64 >;
uploadServer()231     UploadServerInfo uploadServer() const { return m_uploadServer; }
232 
233     /**
234      * Creates a map called "branding" in the global storage, and inserts an
235      * entry for each of the branding strings. This makes the branding
236      * information accessible to the Python modules.
237      */
238     void setGlobals( GlobalStorage* globalStorage ) const;
239 
240 public slots:
241     QString string( StringEntry stringEntry ) const;
versionedName()242     QString versionedName() const { return string( VersionedName ); }
productName()243     QString productName() const { return string( ProductName ); }
shortProductName()244     QString shortProductName() const { return string( ShortProductName ); }
shortVersionedName()245     QString shortVersionedName() const { return string( ShortVersionedName ); }
246 
247     QString styleString( StyleEntry styleEntry ) const;
248     QString imagePath( ImageEntry imageEntry ) const;
249 
sidebarSide()250     PanelSide sidebarSide() const { return m_sidebarSide; }
navigationSide()251     PanelSide navigationSide() const { return m_navigationSide; }
252 
253 private:
254     static Branding* s_instance;
255 
256     static const QStringList s_stringEntryStrings;
257     static const QStringList s_imageEntryStrings;
258     static const QStringList s_styleEntryStrings;
259     static const QStringList s_uploadServerStrings;
260 
261     QString m_descriptorPath;  // Path to descriptor (e.g. "/etc/calamares/default/branding.desc")
262     QString m_componentName;  // Matches last part of full path to containing directory
263     QMap< QString, QString > m_strings;
264     QMap< QString, QString > m_images;
265     QMap< QString, QString > m_style;
266     UploadServerInfo m_uploadServer;
267 
268     /* The slideshow can be done in one of two ways:
269      *  - as a sequence of images
270      *  - as a QML file
271      * The slideshow: setting selects which one is used. If it is
272      * a list (of filenames) then it is a sequence of images, and otherwise
273      * it is a QML file which is run. (For QML, the slideshow API is
274      * important).
275      */
276     QStringList m_slideshowFilenames;
277     QString m_slideshowPath;
278     int m_slideshowAPI;
279     QString m_translationsPathPrefix;
280 
281     /** @brief Initialize the simple settings below */
282     void initSimpleSettings( const YAML::Node& doc );
283     ///@brief Initialize the slideshow settings, above
284     void initSlideshowSettings( const YAML::Node& doc );
285 
286     bool m_welcomeStyleCalamares;
287     bool m_welcomeExpandingLogo;
288 
289     WindowExpansion m_windowExpansion;
290     WindowDimension m_windowHeight, m_windowWidth;
291     WindowPlacement m_windowPlacement;
292 
293     PanelFlavor m_sidebarFlavor = PanelFlavor::Widget;
294     PanelFlavor m_navigationFlavor = PanelFlavor::Widget;
295     PanelSide m_sidebarSide = PanelSide::Left;
296     PanelSide m_navigationSide = PanelSide::Bottom;
297 };
298 
299 }  // namespace Calamares
300 
301 #endif  // BRANDING_H
302