diff --git a/src/core/ActivityInfo.cpp b/src/core/ActivityInfo.cpp index f52ffe58e..7feb4bb85 100644 --- a/src/core/ActivityInfo.cpp +++ b/src/core/ActivityInfo.cpp @@ -1,201 +1,191 @@ /* GCompris - ActivityInfo.cpp * * Copyright (C) 2014 Bruno Coudoin * * Authors: * Bruno Coudoin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include "ActivityInfo.h" #include #include #include #include #include "ApplicationSettings.h" ActivityInfo::ActivityInfo(QObject *parent): QObject(parent), m_demo(true), m_favorite(false), m_enabled(true), m_createdInVersion(0) { } QString ActivityInfo::name() const { return m_name; } void ActivityInfo::setName(const QString &name) { m_name = name; // Once we are given a name, we can get the favorite property // from the persistant configuration m_favorite = ApplicationSettings::getInstance()->isFavorite(m_name); emit nameChanged(); } QString ActivityInfo::section() const { return m_section; } void ActivityInfo::setSection(const QString §ion) { m_section = section; emit sectionChanged(); } quint32 ActivityInfo::difficulty() const { return m_difficulty; } void ActivityInfo::setDifficulty(const quint32 &difficulty) { m_difficulty = difficulty; emit difficultyChanged(); } QString ActivityInfo::icon() const { return m_icon; } void ActivityInfo::setIcon(const QString &icon) { m_icon = icon; emit iconChanged(); } QString ActivityInfo::author() const { return m_author; } void ActivityInfo::setAuthor(const QString &author) { m_author = author; emit authorChanged(); } bool ActivityInfo::demo() const { return m_demo; } void ActivityInfo::setDemo(const bool &demo) { m_demo = demo; emit demoChanged(); } QString ActivityInfo::title() const { return m_title; } void ActivityInfo::setTitle(const QString &title) { m_title = title; emit titleChanged(); } QString ActivityInfo::description() const { return m_description; } void ActivityInfo::setDescription(const QString &description) { m_description = description; emit descriptionChanged(); } QString ActivityInfo::goal() const { return m_goal; } void ActivityInfo::setGoal(const QString &goal) { m_goal = goal; emit goalChanged(); } QString ActivityInfo::prerequisite() const { return m_prerequisite; } void ActivityInfo::setPrerequisite(const QString &prerequisite) { m_prerequisite = prerequisite; emit prerequisiteChanged(); } QString ActivityInfo::manual() const { return m_manual; } void ActivityInfo::setManual(const QString &manual) { m_manual = manual; emit manualChanged(); } QString ActivityInfo::credit() const { return m_credit; } void ActivityInfo::setCredit(const QString &credit) { m_credit = credit; emit creditChanged(); } bool ActivityInfo::favorite() const { return m_favorite; } void ActivityInfo::setFavorite(const bool favorite) { m_favorite = favorite; ApplicationSettings::getInstance()->setFavorite(m_name, m_favorite); emit favoriteChanged(); } bool ActivityInfo::enabled() const { return m_enabled; } void ActivityInfo::setEnabled(const bool enabled) { m_enabled = enabled; emit enabledChanged(); } int ActivityInfo::createdInVersion() const { return m_createdInVersion; } void ActivityInfo::setCreatedInVersion(const int created) { m_createdInVersion = created; emit createdInVersionChanged(); } - -QStringList ActivityInfo::getSectionPath() -{ - QStringList path; - ActivityInfo *activity(this); - do { - path.prepend(activity->section()); - } while( ( activity = qobject_cast(activity->parent()) ) ); - return path; -} diff --git a/src/core/ActivityInfo.h b/src/core/ActivityInfo.h index 1a19d583c..365243d74 100644 --- a/src/core/ActivityInfo.h +++ b/src/core/ActivityInfo.h @@ -1,200 +1,198 @@ /* GCompris - ActivityInfo.h * * Copyright (C) 2014 Bruno Coudoin * * Authors: * Bruno Coudoin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #ifndef ACTIVITYINFO_H #define ACTIVITYINFO_H #include #include #include #include /** * @class ActivityInfo * @short A QML component holding meta information about an activity. * @ingroup components * * Each GCompris activity has to provide some meta data about itself in form * of an ActivityInfo definition. This data will be used to register it in the * ActivityInfoTree, and populate the full screen help dialog. * * @sa DialogHelp */ class ActivityInfo : public QObject { Q_OBJECT /** * Name of the main activity QML file. * * Example: "activity/Activity.qml" */ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) /** * Section(s) this activity belongs to. * * An activity can belong to one or multiple activity sections * (separated by whitespace) out of: * computer, discovery, experiment, fun, math, puzzle, * reading, strategy. */ Q_PROPERTY(QString section READ section WRITE setSection NOTIFY sectionChanged) /** * Difficulty of the activity. * * A difficulty level from 1 (easiest) to 6 (most difficult). */ Q_PROPERTY(quint32 difficulty READ difficulty WRITE setDifficulty NOTIFY difficultyChanged) /** * Relative path to the icon of the activity. * * Example: "activity/activity.svg" */ Q_PROPERTY(QString icon READ icon WRITE setIcon NOTIFY iconChanged) /** * Author of the activity. */ Q_PROPERTY(QString author READ author WRITE setAuthor NOTIFY authorChanged) /** * Whether the activity is part of the demo version of GCompris. */ Q_PROPERTY(bool demo READ demo WRITE setDemo NOTIFY demoChanged) /** * Title of the activity. */ Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) /** * Description of the activity. */ Q_PROPERTY(QString description READ description WRITE setDescription NOTIFY descriptionChanged) /** * Goal that this activity wants to achieve. */ Q_PROPERTY(QString goal READ goal WRITE setGoal NOTIFY goalChanged) /** * Prerequisite for using this activity. */ Q_PROPERTY(QString prerequisite READ prerequisite WRITE setPrerequisite NOTIFY prerequisiteChanged) /** * Manual describing the activity's usage. */ Q_PROPERTY(QString manual READ manual WRITE setManual NOTIFY manualChanged) /** * Credits to third parties. */ Q_PROPERTY(QString credit READ credit WRITE setCredit NOTIFY creditChanged) Q_PROPERTY(bool favorite READ favorite WRITE setFavorite NOTIFY favoriteChanged) /** * This activity is enabled. */ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) /** * Version in which this activity has been created */ Q_PROPERTY(int createdInVersion READ createdInVersion WRITE setCreatedInVersion NOTIFY createdInVersionChanged) public: /// @cond INTERNAL_DOCS explicit ActivityInfo(QObject *parent = 0); QString name() const; void setName(const QString &); QString section() const; void setSection(const QString &); quint32 difficulty() const; void setDifficulty(const quint32 &); QString icon() const; void setIcon(const QString &); QString author() const; void setAuthor(const QString &); bool demo() const; void setDemo(const bool &); QString title() const; void setTitle(const QString &); QString description() const; void setDescription(const QString &); QString goal() const; void setGoal(const QString &); QString prerequisite() const; void setPrerequisite(const QString &); QString manual() const; void setManual(const QString &); QString credit() const; void setCredit(const QString &); bool favorite() const; void setFavorite(const bool); bool enabled() const; void setEnabled(const bool); int createdInVersion() const; void setCreatedInVersion(const int); - QStringList getSectionPath(); - signals: void nameChanged(); void sectionChanged(); void difficultyChanged(); void iconChanged(); void authorChanged(); void demoChanged(); void titleChanged(); void descriptionChanged(); void goalChanged(); void prerequisiteChanged(); void manualChanged(); void creditChanged(); void favoriteChanged(); void enabledChanged(); void createdInVersionChanged(); /// @endcond private: QString m_name; QString m_section; quint32 m_difficulty; QString m_icon; QString m_author; bool m_demo; QString m_title; QString m_description; QString m_goal; QString m_prerequisite; QString m_manual; QString m_credit; bool m_favorite; bool m_enabled; int m_createdInVersion; }; #endif // ACTIVITYINFO_H diff --git a/src/core/ActivityInfoTree.cpp b/src/core/ActivityInfoTree.cpp index ac7dc3274..4a2959ce6 100644 --- a/src/core/ActivityInfoTree.cpp +++ b/src/core/ActivityInfoTree.cpp @@ -1,354 +1,340 @@ /* GCompris - ActivityInfoTree.cpp * * Copyright (C) 2014 Bruno Coudoin * * Authors: * Bruno Coudoin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include "ActivityInfoTree.h" #include "ApplicationInfo.h" #include #include #include #include #include #include #include ActivityInfoTree::ActivityInfoTree(QObject *parent) : QObject(parent), m_currentActivity(NULL) { } void ActivityInfoTree::setRootMenu(ActivityInfo *rootMenu) { m_rootMenu = rootMenu; } ActivityInfo *ActivityInfoTree::getRootMenu() const { return m_rootMenu; } QQmlListProperty ActivityInfoTree::menuTree() { return QQmlListProperty(this, NULL, &menuTreeCount, &menuTreeAt); } int ActivityInfoTree::menuTreeCount(QQmlListProperty *property) { ActivityInfoTree *obj = qobject_cast(property->object); if(obj) return obj->m_menuTree.count(); else return 0; } ActivityInfo *ActivityInfoTree::menuTreeAt(QQmlListProperty *property, int index) { ActivityInfoTree *obj = qobject_cast(property->object); if(obj) return obj->m_menuTree.at(index); else return 0; } ActivityInfo *ActivityInfoTree::menuTree(int index) const { return m_menuTree.at(index); } void ActivityInfoTree::setCurrentActivity(ActivityInfo *currentActivity) { m_currentActivity = currentActivity; emit currentActivityChanged(); } ActivityInfo *ActivityInfoTree::getCurrentActivity() const { return m_currentActivity; } -ActivityInfo *ActivityInfoTree::getParentActivity(ActivityInfo *root, ActivityInfo *menu) -{ - qDebug() << "Parent Path= " << menu->getSectionPath(); - - Q_FOREACH( QObject *object, root->children() ) - { - ActivityInfo *activityInfo = qobject_cast(object); - if(activityInfo->section() == menu->section()) { - return activityInfo; - } - } - return m_menuTree.at(0); -} - void ActivityInfoTree::menuTreeAppend(ActivityInfo *menu) { m_menuTreeFull.append(menu); } void ActivityInfoTree::menuTreeAppend(QQmlEngine *engine, const QDir &menuDir, const QString &menuFile) { QQmlComponent component(engine, QUrl::fromLocalFile(menuDir.absolutePath() + '/' + menuFile)); QObject *object = component.create(); if(component.isReady()) { if(QQmlProperty::read(object, "section").toString() == "/") { menuTreeAppend(qobject_cast(object)); } } else { qDebug() << menuFile << ": Failed to load"; } } void ActivityInfoTree::sortByDifficulty(bool emitChanged) { std::sort(m_menuTree.begin(), m_menuTree.end(), SortByDifficulty()); if (emitChanged) Q_EMIT menuTreeChanged(); } void ActivityInfoTree::sortByName(bool emitChanged) { std::sort(m_menuTree.begin(), m_menuTree.end(), SortByName()); if (emitChanged) Q_EMIT menuTreeChanged(); } // Filter the current activity list by the given tag // the tag 'all' means no filter // the tag 'favorite' means only marked as favorite // The level is also filtered based on the global property void ActivityInfoTree::filterByTag(const QString &tag, bool emitChanged) { m_menuTree.clear(); // https://www.kdab.com/goodbye-q_foreach/, for loops on QList may cause detach const auto constMenuTreeFull = m_menuTreeFull; for(const auto &activity: constMenuTreeFull) { if((activity->section().indexOf(tag) != -1 || tag == "all" || (tag == "favorite" && activity->favorite())) && (activity->difficulty() >= ApplicationSettings::getInstance()->filterLevelMin() && activity->difficulty() <= ApplicationSettings::getInstance()->filterLevelMax())) { m_menuTree.push_back(activity); } } sortByDifficulty(); if (emitChanged) Q_EMIT menuTreeChanged(); } void ActivityInfoTree::filterByDifficulty(quint32 levelMin, quint32 levelMax) { auto it = std::remove_if(m_menuTree.begin(), m_menuTree.end(), [&](const ActivityInfo* activity) { return activity->difficulty() < levelMin || activity->difficulty() > levelMax; }); m_menuTree.erase(it, m_menuTree.end()); } void ActivityInfoTree::filterLockedActivities(bool emitChanged) { // If we have the full version or if we show all the activities, we don't need to do anything if(!ApplicationSettings::getInstance()->isDemoMode() || ApplicationSettings::getInstance()->showLockedActivities()) return; // Remove non free activities if needed. We need to already have a menuTree filled! auto it = std::remove_if(m_menuTree.begin(), m_menuTree.end(), [](const ActivityInfo* activity) { return !activity->demo(); }); m_menuTree.erase(it, m_menuTree.end()); if (emitChanged) Q_EMIT menuTreeChanged(); } void ActivityInfoTree::filterEnabledActivities(bool emitChanged) { auto it = std::remove_if(m_menuTree.begin(), m_menuTree.end(), [](const ActivityInfo* activity) { return !activity->enabled(); }); m_menuTree.erase(it, m_menuTree.end()); if (emitChanged) Q_EMIT menuTreeChanged(); } void ActivityInfoTree::filterCreatedWithinVersions(int firstVersion, int lastVersion, bool emitChanged) { m_menuTree.clear(); const auto constMenuTreeFull = m_menuTreeFull; for(const auto &activity: constMenuTreeFull) { if(firstVersion < activity->createdInVersion() && activity->createdInVersion() <= lastVersion) { m_menuTree.push_back(activity); } } if (emitChanged) Q_EMIT menuTreeChanged(); } void ActivityInfoTree::exportAsSQL() { QTextStream cout(stdout); ApplicationSettings::getInstance()->setFilterLevelMin(1); ApplicationSettings::getInstance()->setFilterLevelMax(6); filterByTag("all"); cout << "CREATE TABLE activities (" << "id INT UNIQUE, " << "name TEXT," << "section TEXT," << "author TEXT," << "difficulty INT," << "icon TEXT," << "title TEXT," << "description TEXT," << "prerequisite TEXT," << "goal TEXT," << "manual TEXT," << "credit TEXT," << "demo INT);" << endl; cout << "DELETE FROM activities" << endl; int i(0); const auto constMenuTree = m_menuTree; for(const auto &activity: constMenuTree) { cout << "INSERT INTO activities VALUES(" << i++ << ", " << "'" << activity->name() << "', " << "'" << activity->section() << "', " << "'" << activity->author() << "', " << activity->difficulty() << ", " << "'" << activity->icon() << "', " << "\"" << activity->title() << "\", " << "\"" << activity->description() << "\", " << "\"" << activity->prerequisite() << "\", " << "\"" << activity->goal().toHtmlEscaped() << "\", " << "\"" << activity->manual().toHtmlEscaped() << "\", " << "\"" << activity->credit() << "\", " << activity->demo() << ");" << endl; } } QObject *ActivityInfoTree::menuTreeProvider(QQmlEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(scriptEngine) ActivityInfoTree *menuTree = new ActivityInfoTree(NULL); QQmlComponent componentRoot(engine, QUrl("qrc:/gcompris/src/activities/menu/ActivityInfo.qml")); QObject *objectRoot = componentRoot.create(); menuTree->setRootMenu(qobject_cast(objectRoot)); QFile file(":/gcompris/src/activities/activities_out.txt"); if(!file.open(QFile::ReadOnly)) { qDebug() << "Failed to load the activity list"; } QTextStream in(&file); while (!in.atEnd()) { QString line = in.readLine(); if(!line.startsWith(QLatin1String("#"))) { QString url = QString("qrc:/gcompris/src/activities/%1/ActivityInfo.qml").arg(line); if(!QResource::registerResource( ApplicationInfo::getFilePath(line + ".rcc"))) qDebug() << "Failed to load the resource file " << line + ".rcc"; QQmlComponent componentRoot(engine, QUrl(url)); QObject *objectRoot = componentRoot.create(); if(objectRoot) { menuTree->menuTreeAppend(qobject_cast(objectRoot)); } else { qDebug() << "ERROR: failed to load " << line << " " << componentRoot.errors(); } } } file.close(); menuTree->filterByTag("favorite"); menuTree->filterLockedActivities(); menuTree->filterEnabledActivities(); return menuTree; } void ActivityInfoTree::registerResources() { if(!QResource::registerResource(ApplicationInfo::getFilePath("core.rcc"))) qDebug() << "Failed to load the resource file " << ApplicationInfo::getFilePath("core.rcc"); if(!QResource::registerResource(ApplicationInfo::getFilePath("menu.rcc"))) qDebug() << "Failed to load the resource file menu.rcc"; if(!QResource::registerResource(ApplicationInfo::getFilePath("activities.rcc"))) qDebug() << "Failed to load the resource file activities.rcc"; if(QResource::registerResource(ApplicationSettings::getInstance()->cachePath() + "/data2/" + QString("full-%1.rcc").arg(COMPRESSED_AUDIO))) qDebug() << "Registered the pre-download " << QString("full-%1.rcc").arg(COMPRESSED_AUDIO); } void ActivityInfoTree::filterBySearch(const QString& text) { m_menuTree.clear(); if(!text.trimmed().isEmpty()) { // perform search on each word entered in the searchField const QStringList wordsList = text.split(' ', QString::SkipEmptyParts); for(const QString &searchTerm: wordsList) { const QString trimmedText = searchTerm.trimmed(); const auto constMenuTreeFull = m_menuTreeFull; for(const auto &activity: constMenuTreeFull) { if(activity->title().contains(trimmedText, Qt::CaseInsensitive) || activity->name().contains(trimmedText, Qt::CaseInsensitive) || activity->description().contains(trimmedText, Qt::CaseInsensitive)) { // add the activity only if it's not added if(m_menuTree.indexOf(activity) == -1) m_menuTree.push_back(activity); } } } } else m_menuTree = m_menuTreeFull; filterEnabledActivities(false); filterLockedActivities(false); filterByDifficulty(ApplicationSettings::getInstance()->filterLevelMin(), ApplicationSettings::getInstance()->filterLevelMax()); sortByDifficulty(false); Q_EMIT menuTreeChanged(); } QVariantList ActivityInfoTree::allCharacters() { QSet keyboardChars; const auto constMenuTreeFull = m_menuTreeFull; for(auto &tree: constMenuTreeFull) { const QString &title = tree->title(); Q_FOREACH(const QChar &letter, title) { if(!letter.isSpace() && !letter.isPunct()) { keyboardChars.insert(letter.toLower()); } } } Q_FOREACH(const QString &letters, keyboardChars) { m_keyboardCharacters.push_back(letters); } std::sort(m_keyboardCharacters.begin(), m_keyboardCharacters.end()); return m_keyboardCharacters; } diff --git a/src/core/ActivityInfoTree.h b/src/core/ActivityInfoTree.h index 4c1245898..817be12b3 100644 --- a/src/core/ActivityInfoTree.h +++ b/src/core/ActivityInfoTree.h @@ -1,100 +1,99 @@ /* GCompris - ActivityInfoTree.h * * Copyright (C) 2014 Bruno Coudoin * * Authors: * Bruno Coudoin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #ifndef ACTIVITYINFOTREE_H #define ACTIVITYINFOTREE_H #include "ActivityInfo.h" #include #include class ActivityInfoTree : public QObject { Q_OBJECT Q_PROPERTY(ActivityInfo* rootMenu READ getRootMenu CONSTANT) Q_PROPERTY(QQmlListProperty menuTree READ menuTree NOTIFY menuTreeChanged) Q_PROPERTY(ActivityInfo* currentActivity READ getCurrentActivity WRITE setCurrentActivity NOTIFY currentActivityChanged) Q_PROPERTY(QVariantList characters READ allCharacters CONSTANT) public: explicit ActivityInfoTree(QObject *parent = 0); QQmlListProperty menuTree(); ActivityInfo *getRootMenu() const; void setRootMenu(ActivityInfo *rootMenu); ActivityInfo *menuTree(int) const; void setCurrentActivity(ActivityInfo *currentActivity); ActivityInfo *getCurrentActivity() const; - ActivityInfo *getParentActivity(ActivityInfo *root, ActivityInfo *menu); void menuTreeAppend(ActivityInfo *menu); void menuTreeAppend(QQmlEngine *engine, const QDir &menuDir, const QString &menuFile); void sortByDifficulty(bool emitChanged = true); void sortByName(bool emitChanged = true); QVariantList allCharacters(); protected Q_SLOTS: Q_INVOKABLE void filterByTag(const QString &tag, bool emitChanged = true); Q_INVOKABLE void filterLockedActivities(bool emitChanged = true); Q_INVOKABLE void filterEnabledActivities(bool emitChanged = true); // create a tree from the whole list of activities with the activities created between the two versions Q_INVOKABLE void filterCreatedWithinVersions(int firstVersion, int lastVersion, bool emitChanged = true); Q_INVOKABLE void filterBySearch(const QString& text); Q_INVOKABLE void filterByDifficulty(quint32 levelMin, quint32 levelMax); signals: void menuTreeChanged(); void currentActivityChanged(); void allCharactersChanged(); private: // this is the full activity list, it never changes QList m_menuTreeFull; // represents the Menu view and can be filtered QList m_menuTree; ActivityInfo *m_rootMenu; ActivityInfo *m_currentActivity; QVariantList m_keyboardCharacters; static int menuTreeCount(QQmlListProperty *property); static ActivityInfo *menuTreeAt(QQmlListProperty *property, int index); struct SortByDifficulty { bool operator()(const ActivityInfo *a, const ActivityInfo *b) const { return a->difficulty() < b->difficulty(); } }; struct SortByName { bool operator()(const ActivityInfo *a, const ActivityInfo *b) const { return a->name() < b->name(); } }; public: static void registerResources(); static QObject *menuTreeProvider(QQmlEngine *engine, QJSEngine *scriptEngine); void exportAsSQL(); }; #endif // ACTIVITYINFOTREE_H diff --git a/src/core/ApplicationSettings.cpp b/src/core/ApplicationSettings.cpp index 94aaae469..b6004f1f7 100644 --- a/src/core/ApplicationSettings.cpp +++ b/src/core/ApplicationSettings.cpp @@ -1,493 +1,493 @@ /* GCompris - ApplicationSettings.cpp * * Copyright (C) 2014-2016 Johnny Jazeix * * Authors: * Johnny Jazeix * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include "ApplicationSettings.h" #include "ApplicationInfo.h" #include "DownloadManager.h" #include #include #include #include #include #include #include #include #include #include -#define GC_DEFAULT_FONT "Andika-R.otf" +#define GC_DEFAULT_FONT QLatin1String("Andika-R.otf") #define GC_DEFAULT_FONT_CAPITALIZATION 0 // Font.MixedCase #define GC_DEFAULT_FONT_LETTER_SPACING 0 -static const QString GENERAL_GROUP_KEY = "General"; -static const QString ADMIN_GROUP_KEY = "Admin"; -static const QString INTERNAL_GROUP_KEY = "Internal"; -static const QString FAVORITE_GROUP_KEY = "Favorite"; - -static const QString FULLSCREEN_KEY = "fullscreen"; -static const QString PREVIOUS_HEIGHT_KEY = "previousHeight"; -static const QString PREVIOUS_WIDTH_KEY = "previousWidth"; -static const QString SHOW_LOCKED_ACTIVITIES_KEY = "showLockedActivities"; -static const QString ENABLE_AUDIO_VOICES_KEY = "enableAudioVoices"; -static const QString ENABLE_AUDIO_EFFECTS_KEY = "enableAudioEffects"; -static const QString VIRTUALKEYBOARD_KEY = "virtualKeyboard"; -static const QString LOCALE_KEY = "locale"; -static const QString FONT_KEY = "font"; -static const QString IS_CURRENT_FONT_EMBEDDED = "isCurrentFontEmbedded"; -static const QString ENABLE_AUTOMATIC_DOWNLOADS = "enableAutomaticDownloads"; - -static const QString DOWNLOAD_SERVER_URL_KEY = "downloadServerUrl"; -static const QString CACHE_PATH_KEY = "cachePath"; - -static const QString EXE_COUNT_KEY = "exeCount"; -static const QString LAST_GC_VERSION_RAN = "lastGCVersionRan"; -static const QString RENDERER_KEY = "renderer"; - -static const QString FILTER_LEVEL_MIN = "filterLevelMin"; -static const QString FILTER_LEVEL_MAX = "filterLevelMax"; - -static const QString BASE_FONT_SIZE_KEY = "baseFontSize"; -static const QString FONT_CAPITALIZATION = "fontCapitalization"; -static const QString FONT_LETTER_SPACING = "fontLetterSpacing"; - -static const QString DEFAULT_CURSOR = "defaultCursor"; -static const QString NO_CURSOR = "noCursor"; -static const QString DEMO_KEY = "demo"; -static const QString CODE_KEY = "key"; -static const QString KIOSK_KEY = "kiosk"; -static const QString SECTION_VISIBLE = "sectionVisible"; -static const QString WORDSET = "wordset"; - -static const QString PROGRESS_KEY = "progress"; +static const QString GENERAL_GROUP_KEY = QLatin1String("General"); +static const QString ADMIN_GROUP_KEY = QLatin1String("Admin"); +static const QString INTERNAL_GROUP_KEY = QLatin1String("Internal"); +static const QString FAVORITE_GROUP_KEY = QLatin1String("Favorite"); + +static const QString FULLSCREEN_KEY = QLatin1String("fullscreen"); +static const QString PREVIOUS_HEIGHT_KEY = QLatin1String("previousHeight"); +static const QString PREVIOUS_WIDTH_KEY = QLatin1String("previousWidth"); +static const QString SHOW_LOCKED_ACTIVITIES_KEY = QLatin1String("showLockedActivities"); +static const QString ENABLE_AUDIO_VOICES_KEY = QLatin1String("enableAudioVoices"); +static const QString ENABLE_AUDIO_EFFECTS_KEY = QLatin1String("enableAudioEffects"); +static const QString VIRTUALKEYBOARD_KEY = QLatin1String("virtualKeyboard"); +static const QString LOCALE_KEY = QLatin1String("locale"); +static const QString FONT_KEY = QLatin1String("font"); +static const QString IS_CURRENT_FONT_EMBEDDED = QLatin1String("isCurrentFontEmbedded"); +static const QString ENABLE_AUTOMATIC_DOWNLOADS = QLatin1String("enableAutomaticDownloads"); + +static const QString DOWNLOAD_SERVER_URL_KEY = QLatin1String("downloadServerUrl"); +static const QString CACHE_PATH_KEY = QLatin1String("cachePath"); + +static const QString EXE_COUNT_KEY = QLatin1String("exeCount"); +static const QString LAST_GC_VERSION_RAN = QLatin1String("lastGCVersionRan"); +static const QString RENDERER_KEY = QLatin1String("renderer"); + +static const QString FILTER_LEVEL_MIN = QLatin1String("filterLevelMin"); +static const QString FILTER_LEVEL_MAX = QLatin1String("filterLevelMax"); + +static const QString BASE_FONT_SIZE_KEY = QLatin1String("baseFontSize"); +static const QString FONT_CAPITALIZATION = QLatin1String("fontCapitalization"); +static const QString FONT_LETTER_SPACING = QLatin1String("fontLetterSpacing"); + +static const QString DEFAULT_CURSOR = QLatin1String("defaultCursor"); +static const QString NO_CURSOR = QLatin1String("noCursor"); +static const QString DEMO_KEY = QLatin1String("demo"); +static const QString CODE_KEY = QLatin1String("key"); +static const QString KIOSK_KEY = QLatin1String("kiosk"); +static const QString SECTION_VISIBLE = QLatin1String("sectionVisible"); +static const QString WORDSET = QLatin1String("wordset"); + +static const QString PROGRESS_KEY = QLatin1String("progress"); ApplicationSettings *ApplicationSettings::m_instance = NULL; ApplicationSettings::ApplicationSettings(const QString &configPath, QObject *parent): QObject(parent), m_baseFontSizeMin(-7), m_baseFontSizeMax(7), m_fontLetterSpacingMin(0.0), m_fontLetterSpacingMax(8.0), m_config(configPath, QSettings::IniFormat) { const QRect &screenSize = QApplication::desktop()->screenGeometry(); // initialize from settings file or default // general group m_config.beginGroup(GENERAL_GROUP_KEY); m_isAudioEffectsEnabled = m_config.value(ENABLE_AUDIO_EFFECTS_KEY, true).toBool(); m_isFullscreen = m_config.value(FULLSCREEN_KEY, true).toBool(); m_previousHeight = m_config.value(PREVIOUS_HEIGHT_KEY, screenSize.height()).toUInt(); m_previousWidth = m_config.value(PREVIOUS_WIDTH_KEY, screenSize.width()).toUInt(); m_isAudioVoicesEnabled = m_config.value(ENABLE_AUDIO_VOICES_KEY, true).toBool(); m_isVirtualKeyboard = m_config.value(VIRTUALKEYBOARD_KEY, ApplicationInfo::getInstance()->isMobile()).toBool(); m_locale = m_config.value(LOCALE_KEY, GC_DEFAULT_LOCALE).toString(); m_font = m_config.value(FONT_KEY, GC_DEFAULT_FONT).toString(); - if(m_font == "Andika-R.ttf") + if(m_font == QLatin1String("Andika-R.ttf")) m_font = "Andika-R.otf"; m_fontCapitalization = m_config.value(FONT_CAPITALIZATION, GC_DEFAULT_FONT_CAPITALIZATION).toUInt(); setFontLetterSpacing(m_config.value(FONT_LETTER_SPACING, GC_DEFAULT_FONT_LETTER_SPACING).toReal()); m_isEmbeddedFont = m_config.value(IS_CURRENT_FONT_EMBEDDED, true).toBool(); // Init the activation mode if(QLatin1String(ACTIVATION_MODE) == "no") m_activationMode = 0; else if(QLatin1String(ACTIVATION_MODE) == "inapp") m_activationMode = 1; else if(QLatin1String(ACTIVATION_MODE) == "internal") m_activationMode = 2; else qFatal("Unknown activation mode"); // Set the demo mode if(QLatin1String(ACTIVATION_MODE) != "no") m_isDemoMode = m_config.value(DEMO_KEY, true).toBool(); else m_isDemoMode = false; m_codeKey = m_config.value(CODE_KEY, "").toString(); #if defined(WITH_KIOSK_MODE) m_isKioskMode = m_config.value(KIOSK_KEY, true).toBool(); #else m_isKioskMode = m_config.value(KIOSK_KEY, false).toBool(); #endif // Option only useful if we are in demo mode (else all the activities are available and unlocked) // By default, all the activities are displayed (even locked ones) m_showLockedActivities = m_config.value(SHOW_LOCKED_ACTIVITIES_KEY, m_isDemoMode).toBool(); m_sectionVisible = m_config.value(SECTION_VISIBLE, true).toBool(); m_wordset = m_config.value(WORDSET, "").toString(); m_isAutomaticDownloadsEnabled = m_config.value(ENABLE_AUTOMATIC_DOWNLOADS, !ApplicationInfo::getInstance()->isMobile() && ApplicationInfo::isDownloadAllowed()).toBool(); m_filterLevelMin = m_config.value(FILTER_LEVEL_MIN, 1).toUInt(); m_filterLevelMax = m_config.value(FILTER_LEVEL_MAX, 6).toUInt(); m_defaultCursor = m_config.value(DEFAULT_CURSOR, false).toBool(); m_noCursor = m_config.value(NO_CURSOR, false).toBool(); setBaseFontSize(m_config.value(BASE_FONT_SIZE_KEY, 0).toInt()); m_config.sync(); // make sure all defaults are written back m_config.endGroup(); // admin group m_config.beginGroup(ADMIN_GROUP_KEY); - m_downloadServerUrl = m_config.value(DOWNLOAD_SERVER_URL_KEY, "http://gcompris.net").toString(); + m_downloadServerUrl = m_config.value(DOWNLOAD_SERVER_URL_KEY, QLatin1String("http://gcompris.net")).toString(); m_cachePath = m_config.value(CACHE_PATH_KEY, QStandardPaths::writableLocation(QStandardPaths::CacheLocation)).toString(); m_config.endGroup(); // internal group m_config.beginGroup(INTERNAL_GROUP_KEY); m_exeCount = m_config.value(EXE_COUNT_KEY, 0).toUInt(); m_lastGCVersionRan = m_config.value(LAST_GC_VERSION_RAN, 0).toUInt(); m_renderer = m_config.value(RENDERER_KEY, GRAPHICAL_RENDERER).toString(); m_config.endGroup(); // no group m_isBarHidden = false; connect(this, &ApplicationSettings::showLockedActivitiesChanged, this, &ApplicationSettings::notifyShowLockedActivitiesChanged); connect(this, &ApplicationSettings::audioVoicesEnabledChanged, this, &ApplicationSettings::notifyAudioVoicesEnabledChanged); connect(this, &ApplicationSettings::audioEffectsEnabledChanged, this, &ApplicationSettings::notifyAudioEffectsEnabledChanged); connect(this, &ApplicationSettings::fullscreenChanged, this, &ApplicationSettings::notifyFullscreenChanged); connect(this, &ApplicationSettings::previousHeightChanged, this, &ApplicationSettings::notifyPreviousHeightChanged); connect(this, &ApplicationSettings::previousWidthChanged, this, &ApplicationSettings::notifyPreviousWidthChanged); connect(this, &ApplicationSettings::localeChanged, this, &ApplicationSettings::notifyLocaleChanged); connect(this, &ApplicationSettings::fontChanged, this, &ApplicationSettings::notifyFontChanged); connect(this, &ApplicationSettings::virtualKeyboardChanged, this, &ApplicationSettings::notifyVirtualKeyboardChanged); connect(this, &ApplicationSettings::automaticDownloadsEnabledChanged, this, &ApplicationSettings::notifyAutomaticDownloadsEnabledChanged); connect(this, &ApplicationSettings::filterLevelMinChanged, this, &ApplicationSettings::notifyFilterLevelMinChanged); connect(this, &ApplicationSettings::filterLevelMaxChanged, this, &ApplicationSettings::notifyFilterLevelMaxChanged); connect(this, &ApplicationSettings::sectionVisibleChanged, this, &ApplicationSettings::notifySectionVisibleChanged); connect(this, &ApplicationSettings::wordsetChanged, this, &ApplicationSettings::notifyWordsetChanged); connect(this, &ApplicationSettings::demoModeChanged, this, &ApplicationSettings::notifyDemoModeChanged); connect(this, &ApplicationSettings::codeKeyChanged, this, &ApplicationSettings::notifyCodeKeyChanged); connect(this, &ApplicationSettings::kioskModeChanged, this, &ApplicationSettings::notifyKioskModeChanged); connect(this, &ApplicationSettings::downloadServerUrlChanged, this, &ApplicationSettings::notifyDownloadServerUrlChanged); connect(this, &ApplicationSettings::cachePathChanged, this, &ApplicationSettings::notifyCachePathChanged); connect(this, &ApplicationSettings::exeCountChanged, this, &ApplicationSettings::notifyExeCountChanged); connect(this, &ApplicationSettings::barHiddenChanged, this, &ApplicationSettings::notifyBarHiddenChanged); connect(this, &ApplicationSettings::lastGCVersionRanChanged, this, &ApplicationSettings::notifyLastGCVersionRanChanged); connect(this, &ApplicationSettings::rendererChanged, this, &ApplicationSettings::notifyRendererChanged); } ApplicationSettings::~ApplicationSettings() { // make sure settings file is up2date: // general group m_config.beginGroup(GENERAL_GROUP_KEY); m_config.setValue(SHOW_LOCKED_ACTIVITIES_KEY, m_showLockedActivities); m_config.setValue(ENABLE_AUDIO_VOICES_KEY, m_isAudioVoicesEnabled); m_config.setValue(LOCALE_KEY, m_locale); m_config.setValue(FONT_KEY, m_font); m_config.setValue(IS_CURRENT_FONT_EMBEDDED, m_isEmbeddedFont); m_config.setValue(FULLSCREEN_KEY, m_isFullscreen); m_config.setValue(PREVIOUS_HEIGHT_KEY, m_previousHeight); m_config.setValue(PREVIOUS_WIDTH_KEY, m_previousWidth); m_config.setValue(VIRTUALKEYBOARD_KEY, m_isVirtualKeyboard); m_config.setValue(ENABLE_AUTOMATIC_DOWNLOADS, m_isAutomaticDownloadsEnabled); m_config.setValue(FILTER_LEVEL_MIN, m_filterLevelMin); m_config.setValue(FILTER_LEVEL_MAX, m_filterLevelMax); m_config.setValue(DEMO_KEY, m_isDemoMode); m_config.setValue(CODE_KEY, m_codeKey); m_config.setValue(KIOSK_KEY, m_isKioskMode); m_config.setValue(SECTION_VISIBLE, m_sectionVisible); m_config.setValue(WORDSET, m_wordset); m_config.setValue(DEFAULT_CURSOR, m_defaultCursor); m_config.setValue(NO_CURSOR, m_noCursor); m_config.setValue(BASE_FONT_SIZE_KEY, m_baseFontSize); m_config.setValue(FONT_CAPITALIZATION, m_fontCapitalization); m_config.setValue(FONT_LETTER_SPACING, m_fontLetterSpacing); m_config.endGroup(); // admin group m_config.beginGroup(ADMIN_GROUP_KEY); m_config.setValue(DOWNLOAD_SERVER_URL_KEY, m_downloadServerUrl); m_config.setValue(CACHE_PATH_KEY, m_cachePath); m_config.endGroup(); // internal group m_config.beginGroup(INTERNAL_GROUP_KEY); m_config.setValue(EXE_COUNT_KEY, m_exeCount); m_config.setValue(LAST_GC_VERSION_RAN, m_lastGCVersionRan); m_config.setValue(RENDERER_KEY, m_renderer); m_config.endGroup(); m_config.sync(); m_instance = NULL; } void ApplicationSettings::notifyShowLockedActivitiesChanged() { updateValueInConfig(GENERAL_GROUP_KEY, SHOW_LOCKED_ACTIVITIES_KEY, m_showLockedActivities); qDebug() << "notifyShowLockedActivitiesChanged: " << m_showLockedActivities; } void ApplicationSettings::notifyAudioVoicesEnabledChanged() { updateValueInConfig(GENERAL_GROUP_KEY, ENABLE_AUDIO_VOICES_KEY, m_isAudioVoicesEnabled); qDebug() << "notifyAudioVoices: " << m_isAudioVoicesEnabled; } void ApplicationSettings::notifyAudioEffectsEnabledChanged() { updateValueInConfig(GENERAL_GROUP_KEY, ENABLE_AUDIO_EFFECTS_KEY, m_isAudioEffectsEnabled); qDebug() << "notifyAudioEffects: " << m_isAudioEffectsEnabled; } void ApplicationSettings::notifyLocaleChanged() { updateValueInConfig(GENERAL_GROUP_KEY, LOCALE_KEY, m_locale); qDebug() << "new locale: " << m_locale; } void ApplicationSettings::notifyFontChanged() { updateValueInConfig(GENERAL_GROUP_KEY, FONT_KEY, m_font); qDebug() << "new font: " << m_font; } void ApplicationSettings::notifyEmbeddedFontChanged() { updateValueInConfig(GENERAL_GROUP_KEY, IS_CURRENT_FONT_EMBEDDED, m_isEmbeddedFont); qDebug() << "new font is embedded: " << m_isEmbeddedFont; } void ApplicationSettings::notifyFontCapitalizationChanged() { updateValueInConfig(GENERAL_GROUP_KEY, FONT_CAPITALIZATION, m_fontCapitalization); qDebug() << "new fontCapitalization: " << m_fontCapitalization; } void ApplicationSettings::notifyFontLetterSpacingChanged() { updateValueInConfig(GENERAL_GROUP_KEY, FONT_LETTER_SPACING, m_fontLetterSpacing); qDebug() << "new fontLetterSpacing: " << m_fontLetterSpacing; } void ApplicationSettings::notifyFullscreenChanged() { updateValueInConfig(GENERAL_GROUP_KEY, FULLSCREEN_KEY, m_isFullscreen); qDebug() << "fullscreen set to: " << m_isFullscreen; } void ApplicationSettings::notifyPreviousHeightChanged() { updateValueInConfig(GENERAL_GROUP_KEY, PREVIOUS_HEIGHT_KEY, m_previousHeight); qDebug() << "previous height set to: " << m_previousHeight; } void ApplicationSettings::notifyPreviousWidthChanged() { updateValueInConfig(GENERAL_GROUP_KEY, PREVIOUS_WIDTH_KEY, m_previousWidth); qDebug() << "previous width set to: " << m_previousWidth; } void ApplicationSettings::notifyVirtualKeyboardChanged() { updateValueInConfig(GENERAL_GROUP_KEY, VIRTUALKEYBOARD_KEY, m_isVirtualKeyboard); qDebug() << "virtualkeyboard set to: " << m_isVirtualKeyboard; } bool ApplicationSettings::isAutomaticDownloadsEnabled() const { return m_isAutomaticDownloadsEnabled && ApplicationInfo::isDownloadAllowed(); } void ApplicationSettings::setIsAutomaticDownloadsEnabled(const bool newIsAutomaticDownloadsEnabled) { if(ApplicationInfo::isDownloadAllowed()) { m_isAutomaticDownloadsEnabled = newIsAutomaticDownloadsEnabled; emit automaticDownloadsEnabledChanged(); } } void ApplicationSettings::notifyAutomaticDownloadsEnabledChanged() { updateValueInConfig(GENERAL_GROUP_KEY, ENABLE_AUTOMATIC_DOWNLOADS, m_isAutomaticDownloadsEnabled); qDebug() << "enableAutomaticDownloads set to: " << m_isAutomaticDownloadsEnabled; } void ApplicationSettings::notifyFilterLevelMinChanged() { updateValueInConfig(GENERAL_GROUP_KEY, FILTER_LEVEL_MIN, m_filterLevelMin); qDebug() << "filterLevelMin set to: " << m_filterLevelMin; } void ApplicationSettings::notifyFilterLevelMaxChanged() { updateValueInConfig(GENERAL_GROUP_KEY, FILTER_LEVEL_MAX, m_filterLevelMax); qDebug() << "filterLevelMax set to: " << m_filterLevelMax; } void ApplicationSettings::notifyDemoModeChanged() { updateValueInConfig(GENERAL_GROUP_KEY, DEMO_KEY, m_isDemoMode); qDebug() << "notifyDemoMode: " << m_isDemoMode; } void ApplicationSettings::notifyCodeKeyChanged() { checkPayment(); if(!m_isDemoMode) updateValueInConfig(GENERAL_GROUP_KEY, CODE_KEY, m_codeKey); qDebug() << "notifyCodeKey: " << m_codeKey; } void ApplicationSettings::notifyKioskModeChanged() { updateValueInConfig(GENERAL_GROUP_KEY, KIOSK_KEY, m_isKioskMode); qDebug() << "notifyKioskMode: " << m_isKioskMode; } void ApplicationSettings::notifySectionVisibleChanged() { updateValueInConfig(GENERAL_GROUP_KEY, SECTION_VISIBLE, m_sectionVisible); qDebug() << "notifySectionVisible: " << m_sectionVisible; } void ApplicationSettings::notifyWordsetChanged() { if(!m_wordset.isEmpty() && DownloadManager::getInstance()->haveLocalResource(m_wordset) && !DownloadManager::getInstance()->isDataRegistered("words")) { // words.rcc is there -> register old file first // then try to update in the background DownloadManager::getInstance()->updateResource(m_wordset); } updateValueInConfig(GENERAL_GROUP_KEY, WORDSET, m_wordset); qDebug() << "notifyWordset: " << m_wordset; } void ApplicationSettings::notifyDownloadServerUrlChanged() { updateValueInConfig(ADMIN_GROUP_KEY, DOWNLOAD_SERVER_URL_KEY, m_downloadServerUrl); qDebug() << "downloadServerUrl set to: " << m_downloadServerUrl; } void ApplicationSettings::notifyCachePathChanged() { updateValueInConfig(ADMIN_GROUP_KEY, CACHE_PATH_KEY, m_cachePath); qDebug() << "cachePath set to: " << m_cachePath; } void ApplicationSettings::notifyExeCountChanged() { updateValueInConfig(INTERNAL_GROUP_KEY, EXE_COUNT_KEY, m_exeCount); qDebug() << "exeCount set to: " << m_exeCount; } void ApplicationSettings::notifyLastGCVersionRanChanged() { updateValueInConfig(INTERNAL_GROUP_KEY, LAST_GC_VERSION_RAN, m_lastGCVersionRan); qDebug() << "lastVersionRan set to: " << m_lastGCVersionRan; } void ApplicationSettings::notifyRendererChanged() { updateValueInConfig(INTERNAL_GROUP_KEY, RENDERER_KEY, m_renderer); qDebug() << "renderer set to: " << m_renderer; } void ApplicationSettings::notifyBarHiddenChanged() { qDebug() << "is bar hidden: " << m_isBarHidden; } void ApplicationSettings::saveBaseFontSize() { updateValueInConfig(GENERAL_GROUP_KEY, BASE_FONT_SIZE_KEY, m_baseFontSize); } void ApplicationSettings::saveActivityConfiguration(const QString &activity, const QVariantMap &data) { qDebug() << "save configuration for:" << activity; QMapIterator i(data); while (i.hasNext()) { i.next(); updateValueInConfig(activity, i.key(), i.value()); } } QVariantMap ApplicationSettings::loadActivityConfiguration(const QString &activity) { qDebug() << "load configuration for:" << activity; m_config.beginGroup(activity); QStringList keys = m_config.childKeys(); QVariantMap data; foreach(const QString &key, keys) { data[key] = m_config.value(key); } m_config.endGroup(); return data; } void ApplicationSettings::setFavorite(const QString &activity, bool favorite) { updateValueInConfig(FAVORITE_GROUP_KEY, activity, favorite); } bool ApplicationSettings::isFavorite(const QString &activity) { m_config.beginGroup(FAVORITE_GROUP_KEY); bool favorite = m_config.value(activity, false).toBool(); m_config.endGroup(); return favorite; } template void ApplicationSettings::updateValueInConfig(const QString& group, const QString& key, const T& value) { m_config.beginGroup(group); m_config.setValue(key, value); m_config.endGroup(); m_config.sync(); } int ApplicationSettings::loadActivityProgress(const QString &activity) { int progress = 0; m_config.beginGroup(activity); progress = m_config.value(PROGRESS_KEY, 0).toInt(); m_config.endGroup(); qDebug() << "loaded progress for activity" << activity << ":" << progress; return progress; } void ApplicationSettings::saveActivityProgress(const QString &activity, int progress) { updateValueInConfig(activity, PROGRESS_KEY, progress); } bool ApplicationSettings::useExternalWordset() { return !m_wordset.isEmpty() && DownloadManager::getInstance()->isDataRegistered("words"); } QObject *ApplicationSettings::applicationSettingsProvider(QQmlEngine *engine, QJSEngine *scriptEngine) { Q_UNUSED(engine) Q_UNUSED(scriptEngine) ApplicationSettings* appSettings = getInstance(); return appSettings; } diff --git a/src/core/main.cpp b/src/core/main.cpp index f14780447..d78e84131 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -1,293 +1,293 @@ /* GCompris - main.cpp * * Copyright (C) 2014 Bruno Coudoin * * Authors: * Bruno Coudoin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include "GComprisPlugin.h" #include "ApplicationInfo.h" #include "ActivityInfoTree.h" #include "DownloadManager.h" bool loadAndroidTranslation(QTranslator &translator, const QString &locale) { QFile file("assets:/share/GCompris/gcompris_" + locale + ".qm"); file.open(QIODevice::ReadOnly); QDataStream in(&file); uchar *data = (uchar*)malloc(file.size()); if(!file.exists()) qDebug() << "file assets:/share/GCompris/gcompris_" << locale << ".qm does not exist"; in.readRawData((char*)data, file.size()); if(!translator.load(data, file.size())) { qDebug() << "Unable to load translation for locale " << locale << ", use en_US by default"; free(data); return false; } // Do not free data, it is still needed by translator return true; } // Return the locale QString loadTranslation(QSettings &config, QTranslator &translator) { QString locale; // Get locale if(config.contains("General/locale")) { locale = config.value("General/locale").toString(); } else { locale = GC_DEFAULT_LOCALE; } if(locale == GC_DEFAULT_LOCALE) locale = QString(QLocale::system().name() + ".UTF-8"); if(locale == "C.UTF-8" || locale == "en_US.UTF-8") return "en_US"; // Load translation // Remove .UTF8 locale.remove(".UTF-8"); #if defined(Q_OS_ANDROID) if(!loadAndroidTranslation(translator, locale)) loadAndroidTranslation(translator, ApplicationInfo::localeShort(locale)); #else #if (defined(Q_OS_LINUX) || defined(Q_OS_UNIX)) // only useful for translators: load from $application_dir/../share/... if exists as it is where kde scripts install translations if(translator.load("gcompris_qt.qm", QString("%1/../share/locale/%2/LC_MESSAGES").arg(QCoreApplication::applicationDirPath(), locale))) { qDebug() << "load translation for locale " << locale << " in " << QString("%1/../share/locale/%2/LC_MESSAGES").arg(QCoreApplication::applicationDirPath(), locale); } else if(translator.load("gcompris_qt.qm", QString("%1/../share/locale/%2/LC_MESSAGES").arg(QCoreApplication::applicationDirPath(), locale.split('_')[0]))) { qDebug() << "load translation for locale " << locale << " in " << QString("%1/../share/locale/%2/LC_MESSAGES").arg(QCoreApplication::applicationDirPath(), locale.split('_')[0]); } else #endif if(!translator.load("gcompris_" + locale, QString("%1/%2/translations").arg(QCoreApplication::applicationDirPath(), GCOMPRIS_DATA_FOLDER))) { qDebug() << "Unable to load translation for locale " << locale << ", use en_US by default"; } #endif return locale; } int main(int argc, char *argv[]) { // Disable it because we already support HDPI display natively qunsetenv("QT_DEVICE_PIXEL_RATIO"); QApplication app(argc, argv); app.setOrganizationName("KDE"); app.setApplicationName(GCOMPRIS_APPLICATION_NAME); app.setOrganizationDomain("kde.org"); app.setApplicationVersion(ApplicationInfo::GCVersion()); #if defined(Q_OS_MAC) // Sandboxing on MacOSX as documented in: // http://doc.qt.io/qt-5/osx-deployment.html QDir dir(QGuiApplication::applicationDirPath()); dir.cdUp(); dir.cd("Plugins"); QGuiApplication::setLibraryPaths(QStringList(dir.absolutePath())); #endif // Local scope for config QSettings config(QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + "/gcompris/" + GCOMPRIS_APPLICATION_NAME + ".conf", QSettings::IniFormat); // Load translations QTranslator translator; loadTranslation(config, translator); // Apply translation app.installTranslator(&translator); QCommandLineParser parser; parser.setApplicationDescription("GCompris is an educational software for children 2 to 10"); parser.addHelpOption(); parser.addVersionOption(); QCommandLineOption exportActivitiesAsSQL("export-activities-as-sql", "Export activities as SQL"); parser.addOption(exportActivitiesAsSQL); QCommandLineOption clDefaultCursor(QStringList() << "c" << "cursor", QObject::tr("Run GCompris with the default system cursor.")); parser.addOption(clDefaultCursor); QCommandLineOption clNoCursor(QStringList() << "C" << "nocursor", QObject::tr("Run GCompris without cursor (touch screen mode).")); parser.addOption(clNoCursor); QCommandLineOption clFullscreen(QStringList() << "f" << "fullscreen", QObject::tr("Run GCompris in fullscreen mode.")); parser.addOption(clFullscreen); QCommandLineOption clWindow(QStringList() << "w" << "window", QObject::tr("Run GCompris in window mode.")); parser.addOption(clWindow); QCommandLineOption clSound(QStringList() << "s" << "sound", QObject::tr("Run GCompris with sound enabled.")); parser.addOption(clSound); QCommandLineOption clMute(QStringList() << "m" << "mute", QObject::tr("Run GCompris without sound.")); parser.addOption(clMute); QCommandLineOption clWithoutKioskMode(QStringList() << "disable-kioskmode", QObject::tr("Disable the kiosk mode (default).")); parser.addOption(clWithoutKioskMode); QCommandLineOption clWithKioskMode(QStringList() << "enable-kioskmode", QObject::tr("Enable the kiosk mode.")); parser.addOption(clWithKioskMode); QCommandLineOption clSoftwareRenderer(QStringList() << "software-renderer", QObject::tr("Use software renderer instead of openGL (slower but should run with any graphical card, needs Qt 5.8 minimum).")); parser.addOption(clSoftwareRenderer); QCommandLineOption clOpenGLRenderer(QStringList() << "opengl-renderer", QObject::tr("Use openGL renderer instead of software (faster but crash potentially depending on your graphical card).")); parser.addOption(clOpenGLRenderer); parser.process(app); GComprisPlugin plugin; plugin.registerTypes("GCompris"); ActivityInfoTree::registerResources(); // Tell media players to stop playing, it's GCompris time ApplicationInfo::getInstance()->requestAudioFocus(); // Must be done after ApplicationSettings is constructed because we get an // async callback from the payment system ApplicationSettings::getInstance()->checkPayment(); // Getting fullscreen mode from config if exist, else true is default value bool isFullscreen = true; { if(config.contains("General/fullscreen")) { isFullscreen = config.value("General/fullscreen").toBool(); } // Set the cursor image bool defaultCursor = false; if(config.contains("General/defaultCursor")) { defaultCursor = config.value("General/defaultCursor").toBool(); } if(!defaultCursor && !parser.isSet(clDefaultCursor)) QGuiApplication::setOverrideCursor( QCursor(QPixmap(":/gcompris/src/core/resource/cursor.svg"), 0, 0)); // Hide the cursor bool noCursor = false; if(config.contains("General/noCursor")) { noCursor = config.value("General/noCursor").toBool(); } if(noCursor || parser.isSet(clNoCursor)) QGuiApplication::setOverrideCursor(QCursor(Qt::BlankCursor)); } // Update execution counter ApplicationSettings::getInstance()->setExeCount(ApplicationSettings::getInstance()->exeCount() + 1); if(parser.isSet(clFullscreen)) { isFullscreen = true; } if(parser.isSet(clWindow)) { isFullscreen = false; } if(parser.isSet(clMute)) { ApplicationSettings::getInstance()->setIsAudioEffectsEnabled(false); ApplicationSettings::getInstance()->setIsAudioVoicesEnabled(false); } if(parser.isSet(clSound)) { ApplicationSettings::getInstance()->setIsAudioEffectsEnabled(true); ApplicationSettings::getInstance()->setIsAudioVoicesEnabled(true); } if(parser.isSet(clWithoutKioskMode)) { ApplicationSettings::getInstance()->setKioskMode(false); } if(parser.isSet(clWithKioskMode)) { ApplicationSettings::getInstance()->setKioskMode(true); } if(parser.isSet(clSoftwareRenderer)) { ApplicationSettings::getInstance()->setRenderer(QStringLiteral("software")); } if(parser.isSet(clOpenGLRenderer)) { ApplicationSettings::getInstance()->setRenderer(QStringLiteral("opengl")); } // Set the renderer used const QString &renderer = ApplicationSettings::getInstance()->renderer(); - ApplicationInfo::getInstance()->setUseOpenGL(renderer != QStringLiteral("software")); + ApplicationInfo::getInstance()->setUseOpenGL(renderer != QLatin1String("software")); #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) - if(renderer == QStringLiteral("software")) + if(renderer == QLatin1String("software")) QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software); - else if(renderer == QStringLiteral("opengl")) + else if(renderer == QLatin1String("opengl")) QQuickWindow::setSceneGraphBackend(QSGRendererInterface::OpenGL); #endif QQmlApplicationEngine engine(QUrl("qrc:/gcompris/src/core/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::quit, DownloadManager::getInstance(), &DownloadManager::shutdown); // add import path for shipped qml modules: #ifdef SAILFISHOS engine.addImportPath(QStringLiteral("%1/../share/%2/lib/qml") .arg(QCoreApplication::applicationDirPath()).arg(GCOMPRIS_APPLICATION_NAME)); #else engine.addImportPath(QStringLiteral("%1/../lib/qml") .arg(QCoreApplication::applicationDirPath())); #endif if(parser.isSet(exportActivitiesAsSQL)) { ActivityInfoTree *menuTree(qobject_cast(ActivityInfoTree::menuTreeProvider(&engine, NULL))); menuTree->exportAsSQL(); exit(0); } QObject *topLevel = engine.rootObjects().value(0); QQuickWindow *window = qobject_cast(topLevel); if (!window) { qWarning("Error: Your root item has to be a Window."); return -1; } ApplicationInfo::setWindow(window); window->setIcon(QIcon(QPixmap(QString::fromUtf8(":/gcompris/src/core/resource/gcompris-icon.png")))); if(isFullscreen) { window->showFullScreen(); } else { window->show(); } return app.exec(); }