mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[apps/home] Apps placement defined by country
Instead of relying on the order in which the apps are passed at compile time, the look of the Home app is defined in a config file, and depends on the country chosen. Change-Id: If7f56a284e0001d6d75ece1e7efdf5fd1d0a9978
This commit is contained in:
committed by
Émilie Feral
parent
fad375c11c
commit
b2f81db4a9
@@ -1,11 +1,11 @@
|
||||
CountryCode,CountryPreferences::AvailableExamModes,CountryPreferences::MethodForQuartiles,Poincare::Preferences::UnitFormat
|
||||
CA,StandardOnly,MedianOfSublist,Metric
|
||||
DE,StandardOnly,MedianOfSublist,Metric
|
||||
ES,StandardOnly,MedianOfSublist,Metric
|
||||
FR,StandardOnly,CumulatedFrequency,Metric
|
||||
GB,StandardOnly,MedianOfSublist,Metric
|
||||
IT,StandardOnly,CumulatedFrequency,Metric
|
||||
NL,All,MedianOfSublist,Metric
|
||||
PT,StandardOnly,MedianOfSublist,Metric
|
||||
US,StandardOnly,MedianOfSublist,Imperial
|
||||
WW,StandardOnly,MedianOfSublist,Metric
|
||||
CountryCode,CountryPreferences::AvailableExamModes,CountryPreferences::MethodForQuartiles,Poincare::Preferences::UnitFormat,CountryPreferences::HomeAppsLayout
|
||||
CA,StandardOnly,MedianOfSublist,Metric,Default
|
||||
DE,StandardOnly,MedianOfSublist,Metric,Default
|
||||
ES,StandardOnly,MedianOfSublist,Metric,Default
|
||||
FR,StandardOnly,CumulatedFrequency,Metric,Default
|
||||
GB,StandardOnly,MedianOfSublist,Metric,Default
|
||||
IT,StandardOnly,CumulatedFrequency,Metric,Default
|
||||
NL,All,MedianOfSublist,Metric,Default
|
||||
PT,StandardOnly,MedianOfSublist,Metric,Default
|
||||
US,StandardOnly,MedianOfSublist,Imperial,HidePython
|
||||
WW,StandardOnly,MedianOfSublist,Metric,Default
|
||||
|
||||
|
@@ -15,20 +15,28 @@ public:
|
||||
CumulatedFrequency
|
||||
};
|
||||
|
||||
constexpr CountryPreferences(AvailableExamModes availableExamModes, MethodForQuartiles methodForQuartiles, Poincare::Preferences::UnitFormat unitFormat) :
|
||||
enum class HomeAppsLayout : uint8_t {
|
||||
Default,
|
||||
HidePython,
|
||||
};
|
||||
|
||||
constexpr CountryPreferences(AvailableExamModes availableExamModes, MethodForQuartiles methodForQuartiles, Poincare::Preferences::UnitFormat unitFormat, HomeAppsLayout homeAppsLayout) :
|
||||
m_availableExamModes(availableExamModes),
|
||||
m_methodForQuartiles(methodForQuartiles),
|
||||
m_unitFormat(unitFormat)
|
||||
m_unitFormat(unitFormat),
|
||||
m_homeAppsLayout(homeAppsLayout)
|
||||
{}
|
||||
|
||||
constexpr AvailableExamModes availableExamModes() const { return m_availableExamModes; }
|
||||
constexpr MethodForQuartiles methodForQuartiles() const { return m_methodForQuartiles; }
|
||||
constexpr Poincare::Preferences::UnitFormat unitFormat() const { return m_unitFormat; }
|
||||
constexpr HomeAppsLayout homeAppsLayout() const { return m_homeAppsLayout; }
|
||||
|
||||
private:
|
||||
const AvailableExamModes m_availableExamModes;
|
||||
const MethodForQuartiles m_methodForQuartiles;
|
||||
const Poincare::Preferences::UnitFormat m_unitFormat;
|
||||
const HomeAppsLayout m_homeAppsLayout;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,6 +19,7 @@ public:
|
||||
CountryPreferences::AvailableExamModes availableExamModes() const { return I18n::CountryPreferencesArray[static_cast<uint8_t>(m_country)].availableExamModes(); }
|
||||
CountryPreferences::MethodForQuartiles methodForQuartiles() const { return I18n::CountryPreferencesArray[static_cast<uint8_t>(m_country)].methodForQuartiles(); }
|
||||
Poincare::Preferences::UnitFormat unitFormat() const { return I18n::CountryPreferencesArray[static_cast<uint8_t>(m_country)].unitFormat(); }
|
||||
CountryPreferences::HomeAppsLayout homeAppsLayout() const { return I18n::CountryPreferencesArray[static_cast<uint8_t>(m_country)].homeAppsLayout(); }
|
||||
bool isInExamMode() const { return (int8_t)examMode() > 0; }
|
||||
ExamMode examMode() const;
|
||||
void setExamMode(ExamMode examMode);
|
||||
|
||||
@@ -1,9 +1,28 @@
|
||||
app_home_src = $(addprefix apps/home/,\
|
||||
app.cpp \
|
||||
app_cell.cpp \
|
||||
apps_layout.py \
|
||||
controller.cpp \
|
||||
)
|
||||
|
||||
apps_src += $(app_home_src)
|
||||
|
||||
i18n_files += $(call i18n_without_universal_for,home/base)
|
||||
|
||||
# Apps layout file generation
|
||||
|
||||
# The header is refered to as <apps/home/apps_layout.h> so make sure it's
|
||||
# findable this way
|
||||
SFLAGS += -I$(BUILD_DIR)
|
||||
|
||||
apps_layout = apps/home/apps_layout.csv
|
||||
|
||||
$(eval $(call rule_for, \
|
||||
APPS_LAYOUT, \
|
||||
apps/home/apps_layout.cpp, \
|
||||
, \
|
||||
$$(PYTHON) apps/home/apps_layout.py --layouts $(apps_layout) --header $$(subst .cpp,.h,$$@) --implementation $$@ --apps $$(EPSILON_APPS), \
|
||||
global \
|
||||
))
|
||||
|
||||
$(BUILD_DIR)/apps/home/apps_layout.h: $(BUILD_DIR)/apps/home/apps_layout.cpp
|
||||
|
||||
2
apps/home/apps_layout.csv
Normal file
2
apps/home/apps_layout.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
Default,calculation,graph,code,statistics,probability,solver,sequence,regression,settings
|
||||
HidePython,calculation,graph,solver,statistics,probability,regression,sequence,code,settings
|
||||
|
90
apps/home/apps_layout.py
Normal file
90
apps/home/apps_layout.py
Normal file
@@ -0,0 +1,90 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# This script builds the .h/.cpp files for managing the placement of
|
||||
# applications on the home menu, from the apps_layout.csv file.
|
||||
|
||||
import argparse
|
||||
import csv
|
||||
import io
|
||||
|
||||
parser = argparse.ArgumentParser(description="Build tools for the placement of applications on the home menu.")
|
||||
parser.add_argument('--header', help='the .h file to generate')
|
||||
parser.add_argument('--implementation', help='the .cpp file to generate')
|
||||
parser.add_argument('--apps', nargs='+', help='apps that are actually compiled')
|
||||
parser.add_argument('--layouts', help='the apps_layout.csv file')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
def build_permutation(apps, appsOrdered):
|
||||
res = [0] * len(apps)
|
||||
i = 0
|
||||
for app in appsOrdered:
|
||||
if app in apps:
|
||||
res[i] = apps.index(app) + 1
|
||||
i += 1
|
||||
return res
|
||||
|
||||
def parse_config_file(layouts, apps):
|
||||
res = {'styles':[], 'permutations':[]}
|
||||
with io.open(layouts, "r", encoding="utf-8") as f:
|
||||
csvreader = csv.reader(f, delimiter=',')
|
||||
for row in csvreader:
|
||||
res['styles'].append(row[0])
|
||||
res['permutations'].append(build_permutation(apps, row[1:]))
|
||||
return res
|
||||
|
||||
data = parse_config_file(args.layouts, args.apps)
|
||||
|
||||
def print_header(header, data):
|
||||
f = open(header, "w")
|
||||
f.write("#ifndef HOME_APPS_LAYOUT_H\n")
|
||||
f.write("#define HOME_APPS_LAYOUT_H\n")
|
||||
f.write("// This file is auto-generated by apps_layout.py\n\n")
|
||||
f.write("namespace Home {\n\n")
|
||||
|
||||
f.write("int PermutedAppSnapshotIndex(int index);\n\n")
|
||||
|
||||
f.write("}\n\n")
|
||||
f.write("#endif")
|
||||
f.close()
|
||||
|
||||
def print_implementation(implementation, data):
|
||||
f = open(implementation, "w")
|
||||
f.write("// This file is auto-generated by apps_layout.py\n\n")
|
||||
f.write('#include "apps_layout.h"\n')
|
||||
f.write("#include <apps/country_preferences.h>\n")
|
||||
f.write("#include <apps/global_preferences.h>\n")
|
||||
f.write("#include <assert.h>\n\n")
|
||||
f.write("namespace Home {\n\n")
|
||||
|
||||
styles = data['styles']
|
||||
permutations = data['permutations']
|
||||
|
||||
f.write("/* Permutations are built so that Permutation[n] is the index of the snapshot\n")
|
||||
f.write(" * for the nth app in the Home menu. */\n\n")
|
||||
|
||||
for i in range(len(styles)):
|
||||
f.write("static constexpr int " + styles[i] + "AppsPermutation[] = {\n")
|
||||
f.write(" 0,\n")
|
||||
for j in permutations[i]:
|
||||
f.write(" " + str(j) + ",\n")
|
||||
f.write("};\n")
|
||||
f.write('static_assert(' + styles[i] + 'AppsPermutation[0] == 0, "The Home apps must always be at index 0");\n\n')
|
||||
|
||||
f.write("int PermutedAppSnapshotIndex(int index) {\n")
|
||||
f.write(" CountryPreferences::HomeAppsLayout currentLayout = GlobalPreferences::sharedGlobalPreferences()->homeAppsLayout();\n")
|
||||
for i in range(len(styles)):
|
||||
f.write(" if (currentLayout == CountryPreferences::HomeAppsLayout::" + styles[i] + ") {\n")
|
||||
f.write(" return " + styles[i] + "AppsPermutation[index];")
|
||||
f.write(" }\n")
|
||||
f.write(" assert(false);\n")
|
||||
f.write(" return -1;\n")
|
||||
f.write("}\n\n")
|
||||
|
||||
f.write("}\n\n")
|
||||
f.close()
|
||||
|
||||
if args.header:
|
||||
print_header(args.header, data)
|
||||
if args.implementation:
|
||||
print_implementation(args.implementation, data)
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "controller.h"
|
||||
#include "app.h"
|
||||
#include <apps/home/apps_layout.h>
|
||||
#include "../apps_container.h"
|
||||
#include "../global_preferences.h"
|
||||
#include "../exam_mode_configuration.h"
|
||||
@@ -60,7 +61,7 @@ Controller::Controller(Responder * parentResponder, SelectableTableViewDataSourc
|
||||
bool Controller::handleEvent(Ion::Events::Event event) {
|
||||
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
|
||||
AppsContainer * container = AppsContainer::sharedAppsContainer();
|
||||
::App::Snapshot * selectedSnapshot = container->appSnapshotAtIndex(selectionDataSource()->selectedRow() * k_numberOfColumns + selectionDataSource()->selectedColumn() + 1);
|
||||
::App::Snapshot * selectedSnapshot = container->appSnapshotAtIndex(PermutedAppSnapshotIndex(selectionDataSource()->selectedRow() * k_numberOfColumns + selectionDataSource()->selectedColumn() + 1));
|
||||
if (ExamModeConfiguration::appIsForbiddenInExamMode(selectedSnapshot->descriptor()->name(), GlobalPreferences::sharedGlobalPreferences()->examMode())) {
|
||||
App::app()->displayWarning(I18n::Message::ForbidenAppInExamMode1, I18n::Message::ForbidenAppInExamMode2);
|
||||
} else {
|
||||
@@ -128,7 +129,7 @@ void Controller::willDisplayCellAtLocation(HighlightCell * cell, int i, int j) {
|
||||
appCell->setVisible(false);
|
||||
} else {
|
||||
appCell->setVisible(true);
|
||||
::App::Descriptor * descriptor = container->appSnapshotAtIndex(appIndex)->descriptor();
|
||||
::App::Descriptor * descriptor = container->appSnapshotAtIndex(PermutedAppSnapshotIndex(appIndex))->descriptor();
|
||||
appCell->setAppDescriptor(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user