File indexing completed on 2024-04-21 14:43:47

0001 /* GCompris - ApplicationInfo.h
0002  *
0003  * SPDX-FileCopyrightText: 2014-2015 Bruno Coudoin <bruno.coudoin@gcompris.net>
0004  *
0005  * Authors:
0006  *   Bruno Coudoin <bruno.coudoin@gcompris.net>
0007  *
0008  * This file was originally created from Digia example code under BSD license
0009  * and heavily modified since then.
0010  *
0011  *   SPDX-License-Identifier: GPL-3.0-or-later
0012  */
0013 #ifndef APPLICATIONINFO_H
0014 #define APPLICATIONINFO_H
0015 
0016 #include <config.h>
0017 #include "ApplicationSettings.h"
0018 
0019 #include <QObject>
0020 #include <QSslSocket>
0021 
0022 class QQmlEngine;
0023 class QQuickWindow;
0024 
0025 /**
0026  * @class ApplicationInfo
0027  * @short A general purpose singleton that exposes miscellaneous native
0028  *        functions to the QML layer.
0029  * @ingroup infrastructure
0030  */
0031 class ApplicationInfo : public QObject
0032 {
0033     Q_OBJECT
0034 
0035     /**
0036      * Width of the application viewport.
0037      */
0038     Q_PROPERTY(int applicationWidth READ applicationWidth WRITE setApplicationWidth NOTIFY applicationWidthChanged)
0039 
0040     /**
0041      * Platform the application is currently running on.
0042      */
0043     Q_PROPERTY(Platform platform READ platform CONSTANT)
0044 
0045     /**
0046      * Whether the application is currently running on a mobile platform.
0047      *
0048      * Mobile platforms are Android, Ios (not supported yet),
0049      * Blackberry (not supported)
0050      */
0051     Q_PROPERTY(bool isMobile READ isMobile CONSTANT)
0052 
0053     /**
0054      * Whether the current platform supports fragment shaders.
0055      *
0056      * This flag is used in some core modules to selectively deactivate
0057      * particle effects which cause crashes on some Android devices.
0058      *
0059      * cf. https://bugreports.qt.io/browse/QTBUG-44194
0060      *
0061      * For now always set to false, to prevent crashes.
0062      */
0063     Q_PROPERTY(bool hasShader READ hasShader CONSTANT)
0064 
0065     /**
0066      * Whether currently in portrait mode, on mobile platforms.
0067      *
0068      * Based on viewport geometry.
0069      */
0070     Q_PROPERTY(bool isPortraitMode READ isPortraitMode WRITE setIsPortraitMode NOTIFY portraitModeChanged)
0071 
0072     /**
0073      * Ratio factor used for scaling of sizes on high-dpi devices.
0074      *
0075      * Must be used by activities as a scaling factor to all pixel values.
0076      */
0077     Q_PROPERTY(qreal ratio READ ratio NOTIFY ratioChanged)
0078 
0079     /**
0080      * Ratio factor used for font scaling.
0081      *
0082      * On some low-dpi Android devices with high res (e.g. Galaxy Tab 4) the
0083      * fonts in Text-like elements appear too small with respect to the other
0084      * graphics -- also if we are using font.pointSize.
0085      *
0086      * For these cases we calculate a fontRatio in ApplicationInfo that takes
0087      * dpi information into account, as proposed on
0088      * https://doc.qt.io/qt-5/scalability.html#calculating-scaling-ratio
0089      *
0090      * GCText applies this factor automatically on its new fontSize property.
0091      */
0092     Q_PROPERTY(qreal fontRatio READ fontRatio NOTIFY fontRatioChanged)
0093 
0094     /**
0095      * Short (2-letter) locale string of the currently active language.
0096      */
0097     Q_PROPERTY(QString localeShort READ localeShort CONSTANT)
0098 
0099     /**
0100      * GCompris version string (compile time).
0101      */
0102     Q_PROPERTY(QString GCVersion READ GCVersion CONSTANT)
0103 
0104     /**
0105      * GCompris version code (compile time).
0106      */
0107     Q_PROPERTY(int GCVersionCode READ GCVersionCode CONSTANT)
0108 
0109     /**
0110      * Qt version string (runtime).
0111      */
0112     Q_PROPERTY(QString QTVersion READ QTVersion CONSTANT)
0113 
0114     /**
0115      * OpenSSL version string (runtime).
0116      */
0117     Q_PROPERTY(QString OpenSSLVersion READ OpenSSLVersion CONSTANT)
0118 
0119     /**
0120      * Audio codec used for voices resources.
0121      *
0122      * This is determined at compile time (ogg for free platforms, aac on
0123      * MacOSX and IOS).
0124      */
0125     Q_PROPERTY(QString CompressedAudio READ CompressedAudio CONSTANT)
0126 
0127     /**
0128      * Download allowed
0129      *
0130      * This is determined at compile time. If set to NO GCompris will
0131      * never download anything.
0132      */
0133     Q_PROPERTY(bool isDownloadAllowed READ isDownloadAllowed CONSTANT)
0134 
0135     /**
0136      * Whether the application is currently using OpenGL or not.
0137      *
0138      * Use to deactivate some effects if OpenGL not used.
0139      */
0140     Q_PROPERTY(bool useOpenGL READ useOpenGL WRITE setUseOpenGL NOTIFY useOpenGLChanged)
0141 
0142     /**
0143      * Whether Box2D is installed or not.
0144      *
0145      * Use to disable activities that use Box2D when it's not installed.
0146      */
0147     Q_PROPERTY(bool isBox2DInstalled READ isBox2DInstalled NOTIFY isBox2DInstalledChanged)
0148 
0149 public:
0150     /**
0151      * Known host platforms.
0152      */
0153     enum Platform {
0154         Linux, /**< Linux (except Android) */
0155         Windows, /**< Windows */
0156         MacOSX, /**< MacOSX */
0157         Android, /**< Android */
0158         Ios, /**< IOS (not supported) */
0159         Blackberry, /**< Blackberry (not supported) */
0160         UbuntuTouchOS /**< UbuntuTouch OS */
0161     };
0162 
0163     Q_ENUM(Platform)
0164 
0165     /**
0166      * Returns an absolute and platform independent path to the passed @p file
0167      *
0168      * @param file A relative filename.
0169      * @returns Absolute path to the file.
0170      */
0171     static QString getFilePath(const QString &file);
0172 
0173     /**
0174      * Returns the short locale name for the passed @p locale.
0175      *
0176      * Handles also 'system' (GC_DEFAULT_LOCALE) correctly which resolves to
0177      * QLocale::system().name().
0178      *
0179      * @param locale A locale string of the form \<language\>_\<country\>
0180      * @returns A short locale string of the form \<language\>
0181      */
0182     static QString localeShort(const QString &locale)
0183     {
0184         QString _locale = locale;
0185         if (_locale == GC_DEFAULT_LOCALE) {
0186             _locale = QLocale::system().name();
0187         }
0188         if (_locale == "C") {
0189             _locale = "en_US";
0190         }
0191         // Can't use left(2) because of Asturian where there are 3 chars
0192         return _locale.left(_locale.indexOf('_'));
0193     }
0194 
0195     /**
0196      * Returns a locale string that can be used in voices filenames.
0197      *
0198      * @param locale A locale string of the form \<language\>_\<country\>
0199      * @returns A locale string as used in voices filenames.
0200      */
0201     Q_INVOKABLE QString getVoicesLocale(const QString &locale);
0202 
0203     /**
0204      * Request GCompris to take the Audio Focus at the system level.
0205      *
0206      * On systems that support it, it will mute a running audio player.
0207      */
0208     Q_INVOKABLE bool requestAudioFocus() const;
0209 
0210     /**
0211      * Abandon the Audio Focus.
0212      *
0213      * On systems that support it, it will let an audio player start again.
0214      */
0215     Q_INVOKABLE void abandonAudioFocus() const;
0216 
0217     /**
0218      * Compare two strings respecting locale specific sort order.
0219      *
0220      * @param a         First string to compare
0221      * @param b         Second string to compare
0222      * @param locale    Locale to respect for comparison in any of the forms
0223      *                  used in GCompris xx[_XX][.codeset]. Defaults to currently
0224      *                  set language from global configuration.
0225      * @returns         -1, 0 or 1 if a is less than, equal to or greater than b
0226      */
0227     Q_INVOKABLE int localeCompare(const QString &a, const QString &b, const QString &locale = "") const;
0228 
0229     /**
0230      * Sort a list of strings respecting locale specific sort order.
0231      *
0232      * This function is supposed to be called from QML/JS. As there are still
0233      * problems marshalling QStringList from C++ to QML/JS we use QVariantList
0234      * both for argument and return value.
0235      *
0236      * @param list      List of strings to be sorted.
0237      * @param locale    Locale to respect for sorting in any of the forms
0238      *                  used in GCompris xx[_XX][.codeset].
0239      * @returns         List sorted by the sort order of the passed locale.
0240      */
0241     Q_INVOKABLE QVariantList localeSort(QVariantList list, const QString &locale = "") const;
0242 
0243     /// @cond INTERNAL_DOCS
0244 
0245     static ApplicationInfo *getInstance()
0246     {
0247         if (!m_instance) {
0248             m_instance = new ApplicationInfo();
0249         }
0250         return m_instance;
0251     }
0252     static QObject *applicationInfoProvider(QQmlEngine *engine,
0253                                             QJSEngine *scriptEngine);
0254     static void setWindow(QQuickWindow *window);
0255     explicit ApplicationInfo(QObject *parent = nullptr);
0256     ~ApplicationInfo();
0257     int applicationWidth() const { return m_applicationWidth; }
0258     void setApplicationWidth(const int newWidth);
0259     Platform platform() const { return m_platform; }
0260     bool isPortraitMode() const { return m_isPortraitMode; }
0261     void setIsPortraitMode(const bool newMode);
0262     bool isMobile() const { return m_isMobile; }
0263     bool hasShader() const
0264     {
0265 #if defined(Q_OS_ANDROID)
0266         return false;
0267 #else
0268         return true;
0269 #endif
0270     }
0271     qreal ratio() const { return m_ratio; }
0272     qreal fontRatio() const { return m_fontRatio; }
0273     QString localeShort() const
0274     {
0275         return localeShort(ApplicationSettings::getInstance()->locale());
0276     }
0277     static QString GCVersion() { return VERSION; }
0278     static int GCVersionCode() { return VERSION_CODE; }
0279     static QString QTVersion() { return qVersion(); }
0280     static QString OpenSSLVersion() { return QSslSocket::sslLibraryVersionString(); }
0281     static QString CompressedAudio() { return COMPRESSED_AUDIO; }
0282     static bool isDownloadAllowed() { return QString(DOWNLOAD_ALLOWED) == "ON"; }
0283     bool useOpenGL() const { return m_useOpenGL; }
0284     void setUseOpenGL(bool useOpenGL) { m_useOpenGL = useOpenGL; }
0285 
0286     bool isBox2DInstalled() const { return m_isBox2DInstalled; }
0287     void setBox2DInstalled(const QQmlEngine &engine);
0288 
0289     /**
0290      * Returns the native screen orientation.
0291      *
0292      * Wraps QScreen::nativeOrientation: The native orientation of the screen
0293      * is the orientation where the logo sticker of the device appears the
0294      * right way up, or Qt::PrimaryOrientation if the platform does not support
0295      * this functionality.
0296      *
0297      * The native orientation is a property of the hardware, and does not change
0298      */
0299     Q_INVOKABLE Qt::ScreenOrientation getNativeOrientation();
0300 
0301     /**
0302      * Change the desired orientation of the application.
0303      *
0304      * Android specific function, cf. https://developer.android.com/reference/android/app/Activity.html#setRequestedOrientation(int)
0305      *
0306      * @param orientation Desired orientation of the application. For possible
0307      *                    values cf. https://developer.android.com/reference/android/content/pm/ActivityInfo.html#screenOrientation .
0308      *                    Some useful values:
0309      *                    - -1: SCREEN_ORIENTATION_UNSPECIFIED
0310      *                    -  0: SCREEN_ORIENTATION_LANDSCAPE: forces landscape
0311      *                    -  1: SCREEN_ORIENTATION_PORTRAIT: forces portrait
0312      *                    -  5: SCREEN_ORIENTATION_NOSENSOR: forces native
0313      *                          orientation mode on each device (portrait on
0314      *                          smartphones, landscape on tablet)
0315      *                    - 14: SCREEN_ORIENTATION_LOCKED: lock current orientation
0316      */
0317     Q_INVOKABLE void setRequestedOrientation(int orientation);
0318 
0319     /**
0320      * Query the desired orientation of the application.
0321      *
0322      * @sa setRequestedOrientation
0323      */
0324     Q_INVOKABLE int getRequestedOrientation();
0325 
0326     /**
0327      * Checks whether a sensor type from the QtSensor module is supported on
0328      * the current platform.
0329      *
0330      * @param sensorType  Classname of a sensor from the QtSensor module
0331      *                    to be checked (e.g. "QTiltSensor").
0332      */
0333     Q_INVOKABLE bool sensorIsSupported(const QString &sensorType);
0334 
0335     /**
0336      * Toggles activation of screensaver on android
0337      *
0338      * @param value Whether screensaver should be disabled (true) or
0339      *              enabled (false).
0340      */
0341     Q_INVOKABLE void setKeepScreenOn(bool value);
0342 
0343     /**
0344      * Ask for permissions for reading/writing in storage for android.
0345      * Do nothing for other platforms.
0346      *
0347      * https://developer.android.com/training/permissions/requesting
0348      * https://doc.qt.io/qt-5/qtandroid.html#requestPermissions
0349      * Needed for android above 6.0
0350      */
0351     bool checkPermissions() const;
0352 
0353     /// @endcond
0354 
0355 public Q_SLOTS:
0356     /**
0357      * Returns the resource root-paths used for GCompris resources.
0358      * First look in a local folder if exists, else will look into the rcc files.
0359      */
0360     QStringList getResourceDataPaths();
0361 
0362     /**
0363      * Returns an absolute path to a language specific sound/voices file. If
0364      * the file is already absolute only the token replacement is applied.
0365      *
0366      * @param file A templated relative path to a language specific file. Any
0367      *             occurrence of the '$LOCALE' placeholder will be replaced by
0368      *             the currently active locale string.
0369      *             Any occurrence of '$CA' placeholder will be replaced by
0370      *             the current compressed audio format ('ogg' or 'aac).
0371      *             Example: 'voices-$CA/$LOCALE/misc/click_on_letter.$CA'
0372      * @returns An absolute path to the corresponding resource file.
0373      */
0374     Q_INVOKABLE QString getAudioFilePath(const QString &file);
0375 
0376     /**
0377      * Returns an absolute path to a language specific sound/voices file. If
0378      * the file is already absolute only the token replacement is applied.
0379      *
0380      * @param file A templated relative path to a language specific file. Any
0381      *             occurrence of the '$LOCALE' placeholder will be replaced by
0382      *             the currently active locale string.
0383      *             Any occurrence of '$CA' placeholder will be replaced by
0384      *             the current compressed audio format ('ogg' or 'aac).
0385      *             Example: 'voices-$CA/$LOCALE/misc/click_on_letter.$CA'
0386      * @param localeName the locale for which to get this audio file
0387      * @returns An absolute path to the corresponding resource file.
0388      */
0389     Q_INVOKABLE QString getAudioFilePathForLocale(const QString &file,
0390                                                   const QString &localeName);
0391 
0392     /**
0393      * Returns an absolute path to a language specific resource file.
0394      *
0395      * Generalization of getAudioFilePath().
0396      * @sa getAudioFilePath
0397      */
0398     Q_INVOKABLE QString getLocaleFilePath(const QString &file);
0399 
0400     /**
0401      * @returns A list of systems-fonts that should be excluded from font
0402      *          selection.
0403      */
0404     Q_INVOKABLE QStringList getSystemExcludedFonts();
0405 
0406     /**
0407      * @returns A list of fonts contained in the fonts resources.
0408      */
0409     Q_INVOKABLE QStringList getFontsFromRcc();
0410     /**
0411      * @returns A list of background music contained in the background music resources.
0412      */
0413     Q_INVOKABLE QStringList getBackgroundMusicFromRcc();
0414     /**
0415      * Stores a screenshot in the passed @p file.
0416      *
0417      * @param file Absolute destination filename.
0418      */
0419     Q_INVOKABLE void screenshot(const QString &file);
0420 
0421     void notifyPortraitMode();
0422     Q_INVOKABLE void notifyFullscreenChanged();
0423 
0424 protected:
0425     qreal getSizeWithRatio(const qreal height) { return ratio() * height; }
0426 
0427 Q_SIGNALS:
0428     void applicationWidthChanged();
0429     void portraitModeChanged();
0430     void ratioChanged();
0431     void fontRatioChanged();
0432     void applicationSettingsChanged();
0433     void fullscreenChanged();
0434     void useOpenGLChanged();
0435     void isBox2DInstalledChanged();
0436 
0437 private:
0438     static ApplicationInfo *m_instance;
0439     int m_applicationWidth;
0440     Platform m_platform;
0441     bool m_isPortraitMode;
0442     bool m_isMobile;
0443     bool m_useOpenGL;
0444     bool m_isBox2DInstalled;
0445     qreal m_ratio;
0446     qreal m_fontRatio;
0447 
0448     // Symbols fonts that user can't see
0449     QStringList m_excludedFonts;
0450     QStringList m_fontsFromRcc;
0451     QStringList m_backgroundMusicFromRcc;
0452 
0453     static QQuickWindow *m_window;
0454 };
0455 
0456 #endif // APPLICATIONINFO_H